#ifndef IODEVA_H
#define IODEVA_H

#define _NEGBASE(b)	((0xffffffff << (b)) & 0xffffffff)
#define XDEV_ADDR_BASE  _NEGBASE(XDEV_ADDR_SHIFT+XDEV_ADDR_BITS)
#define IODEV_ADDR_BASE _NEGBASE(IODEV_ADDR_SHIFT+IODEV_ADDR_BITS)

/* Address for I/O device d, subregister r, offset o */
#define IODEVA(b,r,o)   ((b ## _BASE)+((r) << 2)+(o))

#ifdef __ASSEMBLY__

/*
 * The I/O device range is designed so that it can be addressed via
 * negative offsets from the zero register. Use (zero) after the
 * macro in a load or store instruction.
 */
#define IODEVV(d,r)	IODEVA(d,r,0)
#define IODEVB0(d,r)	IODEVA(d,r,0)
#define IODEVB1(d,r)	IODEVA(d,r,1)
#define IODEVB2(d,r)	IODEVA(d,r,2)
#define IODEVB3(d,r)	IODEVA(d,r,3)
#define IODEVH0(d,r)	IODEVA(d,r,0)
#define IODEVH1(d,r)	IODEVA(d,r,1)
#define IODEVL(d,r)	IODEVA(d,r,0)

#define IODEVRV(d,r)	IODEVA(d,r,0)
#define IODEVRB0(d,r)	IODEVA(d,r,0)
#define IODEVRB1(d,r)	IODEVA(d,r,1)
#define IODEVRB2(d,r)	IODEVA(d,r,2)
#define IODEVRB3(d,r)	IODEVA(d,r,3)
#define IODEVRH0(d,r)	IODEVA(d,r,0)
#define IODEVRH1(d,r)	IODEVA(d,r,1)
#define IODEVRL(d,r)	IODEVA(d,r,0)

#define PTR(x)	    x

#else

/* Writable registers */
#define IODEVV(d,r)   (*(volatile void     *)IODEVA(d,r,0))
#define IODEVB0(d,r)  (*(volatile uint8_t  *)IODEVA(d,r,0))
#define IODEVB1(d,r)  (*(volatile uint8_t  *)IODEVA(d,r,1))
#define IODEVB2(d,r)  (*(volatile uint8_t  *)IODEVA(d,r,2))
#define IODEVB3(d,r)  (*(volatile uint8_t  *)IODEVA(d,r,3))
#define IODEVH0(d,r)  (*(volatile uint16_t *)IODEVA(d,r,0))
#define IODEVH1(d,r)  (*(volatile uint16_t *)IODEVA(d,r,2))
#define IODEVL(d,r)   (*(volatile uint32_t *)IODEVA(d,r,0))

/* Readonly registers */
#define IODEVRV(d,r)  (*(const volatile void     *)IODEVA(d,r,0))
#define IODEVRB0(d,r) (*(const volatile uint8_t  *)IODEVA(d,r,0))
#define IODEVRB1(d,r) (*(const volatile uint8_t  *)IODEVA(d,r,1))
#define IODEVRB2(d,r) (*(const volatile uint8_t  *)IODEVA(d,r,2))
#define IODEVRB3(d,r) (*(const volatile uint8_t  *)IODEVA(d,r,3))
#define IODEVRH0(d,r) (*(const volatile uint16_t *)IODEVA(d,r,0))
#define IODEVRH1(d,r) (*(const volatile uint16_t *)IODEVA(d,r,2))
#define IODEVRL(d,r)  (*(const volatile uint32_t *)IODEVA(d,r,0))

#define PTR(x) (&(x))

#endif /* __ASSEMBLY__ */

#define IODEVB(d,r)	IODEVB0(d,r)
#define IODEVH(d,r)	IODEVH0(d,r)
#define IODEVRB(d,r)	IODEVRB0(d,r)
#define IODEVRH(d,r)	IODEVRH0(d,r)

#endif /* IODEVA_H */
