Access macros (was Re: Status)

Juergen Buchmueller pullmoll at t-online.de
Tue Jun 12 09:07:18 PDT 2007


On Mon, 11 Jun 2007 23:19:31 -0700 (PDT)
"Eric Smith" <eric at brouhaha.com> wrote:

Some more comments regarding this:

> Possibly.  The uinst_t struct is composed of bit fields that should all
> wind up in a 32-bit word, so I'd expect the compiler to pass those around
> as efficiently as a uint32_t.  I haven't looked at the generated code.

You'd just have to be aware of endianess-issues with bit fields, as you most
probably know.

The "better" choice is to use macros to access shifted and masked values,
which is what GNU generates for x86, too, just that for bit fields it
isn't endianess independent, while for shifted values in macros it is.

In my code I now actually have such a bunch  of macros to access every bit
field in a value.

/*
 * Some macros to have easier access to the bit-reversed notation
 * that the Xerox Alto docs use all over the place.
 */
#define BITSHIFT(width,to) \
	((width)-1-(to))

#define BITMASK(width,from,to) \
	(((1<<((to)+1-(from)))-1) << BITSHIFT(width,to))

#define	ALTO_EQU(reg,width,from,to,val) \
	(((reg) & BITMASK(width,from,to)) == \
		(((val) << BITSHIFT(width,to)) & BITMASK(width,from,to)))

#define	ALTO_GET(reg,width,from,to) \
	(((reg) & BITMASK(width,from,to)) >> BITSHIFT(width,to))

#define	ALTO_PUT(reg,width,from,to,val) do { \
	(reg) = ((reg) & ~BITMASK(width,from,to)) | \
		(((val) << BITSHIFT(width,to)) & BITMASK(width,from,to)); \
} while (0)


And based on these I then defined the basic microinstruction register and
emulator instruction register read access macros:

/* width,from,to of the 32 bit micro instruction register */
#define	MIR_RSEL(mir)	ALTO_GET(mir,32, 0, 4)
#define	MIR_ALUF(mir)	ALTO_GET(mir,32, 5, 8)
#define	MIR_BS(mir)	ALTO_GET(mir,32, 9,11)
#define	MIR_F1(mir)	ALTO_GET(mir,32,12,15)
#define	MIR_F2(mir)	ALTO_GET(mir,32,16,19)
#define	MIR_T(mir)	ALTO_GET(mir,32,20,20)
#define	MIR_L(mir)	ALTO_GET(mir,32,21,21)
#define	MIR_NEXT(mir)	ALTO_GET(mir,32,22,31)

/* width,from,to of the 16 bit instruction register (emulator) */
#define	IR_ARITH(ir)	ALTO_GET(ir,16, 0, 0)
#define	IR_SrcAC(ir)	ALTO_GET(ir,16, 1, 2)
#define	IR_DstAC(ir)	ALTO_GET(ir,16, 3, 4)
#define	IR_AFunc(ir)	ALTO_GET(ir,16, 5, 7)
#define	IR_SH(ir)	ALTO_GET(ir,16, 8, 9)
#define	IR_CY(ir)	ALTO_GET(ir,16,10,11)
#define	IR_NL(ir)	ALTO_GET(ir,16,12,12)
#define	IR_SK(ir)	ALTO_GET(ir,16,13,15)

#define	IR_MFunc(ir)	ALTO_GET(ir,16, 1, 2)
#define	IR_JFunc(ir)	ALTO_GET(ir,16, 3, 4)
#define	IR_I(ir)	ALTO_GET(ir,16, 5, 5)
#define	IR_X(ir)	ALTO_GET(ir,16, 6, 7)
#define	IR_DISP(ir)	ALTO_GET(ir,16, 8,15)
#define	IR_AUGFUNC(ir)	ALTO_GET(ir,16, 3, 7)

In the code I then just write
  switch (MIR_F1(mir))
    {
      case f1_blah:
      ...
    }
which looks readable to me and avoids typos.

In other places, when I e.g. want to set some VAL[7-11] bits of a 16 bit
value, I just write ALTO_PUT(val,16,7,11, new);

It helped me a lot, since I'm not used to octal numbers and found it
difficult to even see what a (017 << 7) would look like as a constant ;-)


More information about the Altogether-devel mailing list