Skip to content

Commit

Permalink
register: Define REG and FIELD macros
Browse files Browse the repository at this point in the history
Define some macros that can be used for defining registers and fields.

The REG32 macro will define A_FOO, for the byte address of a register
as well as R_FOO for the uint32_t[] register number (A_FOO / 4).

The FIELD macro will define FOO_BAR_MASK, FOO_BAR_SHIFT and
FOO_BAR_LENGTH constants for field BAR in register FOO.

Finally, there are some shorthand helpers for extracting/depositing
fields from registers based on these naming schemes.

Usage can greatly reduce the verbosity of device code.

The deposit and extract macros (eg FIELD_EX32, FIELD_DP32  etc.) can be
used to generate extract and deposits without any repetition of the name
stems.

Signed-off-by: Peter Crosthwaite <[email protected]>
Reviewed-by: Peter Maydell <[email protected]>
Signed-off-by: Alistair Francis <[email protected]>
Signed-off-by: Edgar E. Iglesias <[email protected]>
Message-id: bbd87a3c03b1f173b1ed73a6d502c0196c18a72f.1467053537.git.alistair.francis@xilinx.com
[ EI Changes:
  * Add Deposit macros
]
Signed-off-by: Edgar E. Iglesias <[email protected]>
Signed-off-by: Alistair Francis <[email protected]>
Reviewed-by: Peter Maydell <[email protected]>
Signed-off-by: Peter Maydell <[email protected]>
  • Loading branch information
pete128 authored and pm215 committed Jul 4, 2016
1 parent 0b73c9b commit 6842045
Showing 1 changed file with 46 additions and 0 deletions.
46 changes: 46 additions & 0 deletions include/hw/register.h
Original file line number Diff line number Diff line change
Expand Up @@ -152,4 +152,50 @@ void register_write_memory(void *opaque, hwaddr addr, uint64_t value,

uint64_t register_read_memory(void *opaque, hwaddr addr, unsigned size);

/* Define constants for a 32 bit register */

/* This macro will define A_FOO, for the byte address of a register
* as well as R_FOO for the uint32_t[] register number (A_FOO / 4).
*/
#define REG32(reg, addr) \
enum { A_ ## reg = (addr) }; \
enum { R_ ## reg = (addr) / 4 };

/* Define SHIFT, LENGTH and MASK constants for a field within a register */

/* This macro will define FOO_BAR_MASK, FOO_BAR_SHIFT and FOO_BAR_LENGTH
* constants for field BAR in register FOO.
*/
#define FIELD(reg, field, shift, length) \
enum { R_ ## reg ## _ ## field ## _SHIFT = (shift)}; \
enum { R_ ## reg ## _ ## field ## _LENGTH = (length)}; \
enum { R_ ## reg ## _ ## field ## _MASK = \
MAKE_64BIT_MASK(shift, length)};

/* Extract a field from a register */
#define FIELD_EX32(storage, reg, field) \
extract32((storage), R_ ## reg ## _ ## field ## _SHIFT, \
R_ ## reg ## _ ## field ## _LENGTH)

/* Extract a field from an array of registers */
#define ARRAY_FIELD_EX32(regs, reg, field) \
FIELD_EX32((regs)[R_ ## reg], reg, field)

/* Deposit a register field.
* Assigning values larger then the target field will result in
* compilation warnings.
*/
#define FIELD_DP32(storage, reg, field, val) ({ \
struct { \
unsigned int v:R_ ## reg ## _ ## field ## _LENGTH; \
} v = { .v = val }; \
uint32_t d; \
d = deposit32((storage), R_ ## reg ## _ ## field ## _SHIFT, \
R_ ## reg ## _ ## field ## _LENGTH, v.v); \
d; })

/* Deposit a field to array of registers. */
#define ARRAY_FIELD_DP32(regs, reg, field, val) \
(regs)[R_ ## reg] = FIELD_DP32((regs)[R_ ## reg], reg, field, val);

#endif

0 comments on commit 6842045

Please sign in to comment.