The X Macro using D
Walter Bright via Digitalmars-d
digitalmars-d at puremagic.com
Thu Jul 20 14:17:45 PDT 2017
Some time ago, I wrote about the X Macro in C:
https://digitalmars.com/articles/b51.html
I used it from time to time in C code. It's one of the things I actually like
about the C preprocessor. But in translating the aged C code to D it was time to
make X work in D. Here's the C code, followed by the D translation.
(I suppose it could be done with C++ templates, but I'll leave that to Andrei or
Eric Niebler <g>.)
================ C Version ================
// Macro trick to generate several parallel tables
#define Y \
X("AH",4,mAX,TYuchar) \
X("AL",0,mAX,TYuchar) \
X("AX",8,mAX,TYushort) \
X("BH",7,mBX,TYuchar) \
X("BL",3,mBX,TYuchar) \
X("BP",13,0,TYushort) \
X("BX",11,mBX,TYushort) \
X("CH",5,mCX,TYuchar) \
X("CL",1,mCX,TYuchar) \
X("CX",9,mCX,TYushort) \
X("DH",6,mDX,TYuchar) \
X("DI",15,mDI,TYushort) \
X("DL",2,mDX,TYuchar) \
X("DX",10,mDX,TYushort) \
X("EAX",16,mAX,TYulong) \
X("EBP",21,0,TYulong) \
X("EBX",19,mBX,TYulong) \
X("ECX",17,mCX,TYulong) \
X("EDI",23,mDI,TYulong) \
X("EDX",18,mDX,TYulong) \
X("ESI",22,mSI,TYulong) \
X("ESP",20,0,TYulong) \
X("SI",14,mSI,TYushort) \
X("SP",12,0,TYushort)
// Table for identifiers
static const char *pseudotab[] =
{
#define X(id,reg,m,ty) id,
Y
#undef X
};
// Register number to use in addressing mode
unsigned char pseudoreg[] =
{
#define X(id,reg,m,ty) reg,
Y
#undef X
};
// Mask to use for registers affected
regm_t pseudomask[] =
{
#define X(id,reg,m,ty) m,
Y
#undef X
};
// Table for type of pseudo register variable
static unsigned char pseudoty[] =
{
#define X(id,reg,m,ty) mTYvolatile | ty,
Y
#undef X
};
================ D Version ================
/* 4 parallel tables using "X Macro" technique
*/
template Y(alias X)
{
enum Y =
[
// id reg mask ty
X!("AH", 4, mAX, TYuchar),
X!("AL", 0, mAX, TYuchar),
X!("AX", 8, mAX, TYushort),
X!("BH", 7, mBX, TYuchar),
X!("BL", 3, mBX, TYuchar),
X!("BP", 13, 0, TYushort),
X!("BX", 11, mBX, TYushort),
X!("CH", 5, mCX, TYuchar),
X!("CL", 1, mCX, TYuchar),
X!("CX", 9, mCX, TYushort),
X!("DH", 6, mDX, TYuchar),
X!("DI", 15, mDI, TYushort),
X!("DL", 2, mDX, TYuchar),
X!("DX", 10, mDX, TYushort),
X!("EAX", 16, mAX, TYulong),
X!("EBP", 21, 0, TYulong),
X!("EBX", 19, mBX, TYulong),
X!("ECX", 17, mCX, TYulong),
X!("EDI", 23, mDI, TYulong),
X!("EDX", 18, mDX, TYulong),
X!("ESI", 22, mSI, TYulong),
X!("ESP", 20, 0, TYulong),
X!("SI", 14, mSI, TYushort),
X!("SP", 12, 0, TYushort),
];
}
// Table for identifiers
template Xtab(alias A, alias B, alias C, alias D) { enum Xtab = A; }
private __gshared const(char)*[24] pseudotab = Y!Xtab;
// Register number to use in addressing mode
template Xreg(alias A, alias B, alias C, alias D) { enum Xreg = B; }
__gshared ubyte[24] pseudoreg = Y!Xreg;
// Mask to use for registers affected
template Xmask(alias A, alias B, alias C, alias D) { enum Xmask = C; }
__gshared regm_t[24] pseudomask = Y!Xmask;
// Table for type of pseudo register variable
template Xty(alias A, alias B, alias C, alias D) { enum Xty = mTYvolatile | D; }
private __gshared const(tym_t)[24] pseudoty = Y!Xty;
More information about the Digitalmars-d
mailing list