changeset 944:eb310635d80e

Fixed accessing function symbols from inline asm. Ran x86(-64) asm processors through a code formatter.
author Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
date Sun, 08 Feb 2009 05:14:24 +0100
parents 95d09451cb59
children 03d7c4aac654
files gen/asm-x86-32.h gen/asm-x86-64.h
diffstat 2 files changed, 5708 insertions(+), 5225 deletions(-) [+]
line wrap: on
line diff
--- a/gen/asm-x86-32.h	Thu Feb 05 18:17:42 2009 +0100
+++ b/gen/asm-x86-32.h	Sun Feb 08 05:14:24 2009 +0100
@@ -3,358 +3,373 @@
 
 #include "id.h"
 
-namespace AsmParserx8632 {
+namespace AsmParserx8632
+{
 
-typedef enum {
-    Reg_Invalid = -1,
-    Reg_EAX = 0,
-    Reg_EBX,
-    Reg_ECX,
-    Reg_EDX,
-    Reg_ESI,
-    Reg_EDI,
-    Reg_EBP,
-    Reg_ESP,
-    Reg_ST,
-    Reg_ST1, Reg_ST2, Reg_ST3, Reg_ST4, Reg_ST5, Reg_ST6, Reg_ST7,
-    Reg_MM0, Reg_MM1, Reg_MM2, Reg_MM3, Reg_MM4, Reg_MM5, Reg_MM6, Reg_MM7,
-    Reg_XMM0, Reg_XMM1, Reg_XMM2, Reg_XMM3, Reg_XMM4, Reg_XMM5, Reg_XMM6, Reg_XMM7,
-    // xmm8-15?
-    Reg_EFLAGS,
-    Reg_CS,
-    Reg_DS,
-    Reg_SS,
-    Reg_ES,
-    Reg_FS,
-    Reg_GS,
-    Reg_AX, Reg_BX, Reg_CX, Reg_DX, Reg_SI, Reg_DI, Reg_BP, Reg_SP,
-    Reg_AL, Reg_AH, Reg_BL, Reg_BH, Reg_CL, Reg_CH, Reg_DL, Reg_DH,
-    Reg_CR0, Reg_CR2, Reg_CR3, Reg_CR4,
-    Reg_DR0, Reg_DR1, Reg_DR2, Reg_DR3, Reg_DR6, Reg_DR7,
-    Reg_TR3, Reg_TR4, Reg_TR5, Reg_TR6, Reg_TR7
-} Reg;
+    typedef enum
+    {
+        Reg_Invalid = -1,
+        Reg_EAX = 0,
+        Reg_EBX,
+        Reg_ECX,
+        Reg_EDX,
+        Reg_ESI,
+        Reg_EDI,
+        Reg_EBP,
+        Reg_ESP,
+        Reg_ST,
+        Reg_ST1, Reg_ST2, Reg_ST3, Reg_ST4, Reg_ST5, Reg_ST6, Reg_ST7,
+        Reg_MM0, Reg_MM1, Reg_MM2, Reg_MM3, Reg_MM4, Reg_MM5, Reg_MM6, Reg_MM7,
+        Reg_XMM0, Reg_XMM1, Reg_XMM2, Reg_XMM3, Reg_XMM4, Reg_XMM5, Reg_XMM6, Reg_XMM7,
+        // xmm8-15?
+        Reg_EFLAGS,
+        Reg_CS,
+        Reg_DS,
+        Reg_SS,
+        Reg_ES,
+        Reg_FS,
+        Reg_GS,
+        Reg_AX, Reg_BX, Reg_CX, Reg_DX, Reg_SI, Reg_DI, Reg_BP, Reg_SP,
+        Reg_AL, Reg_AH, Reg_BL, Reg_BH, Reg_CL, Reg_CH, Reg_DL, Reg_DH,
+        Reg_CR0, Reg_CR2, Reg_CR3, Reg_CR4,
+        Reg_DR0, Reg_DR1, Reg_DR2, Reg_DR3, Reg_DR6, Reg_DR7,
+        Reg_TR3, Reg_TR4, Reg_TR5, Reg_TR6, Reg_TR7
+    } Reg;
 
-static const int N_Regs = /*gp*/ 8 + /*fp*/ 8 + /*mmx*/ 8 + /*sse*/ 8 +
-/*seg*/ 6 + /*16bit*/ 8 + /*8bit*/ 8 + /*sys*/ 4+6+5 + /*flags*/ + 1;
+    static const int N_Regs = /*gp*/ 8 + /*fp*/ 8 + /*mmx*/ 8 + /*sse*/ 8 +
+                                     /*seg*/ 6 + /*16bit*/ 8 + /*8bit*/ 8 + /*sys*/ 4+6+5 + /*flags*/ + 1;
 
 #define NULL_TREE ""
 
-static struct {
-    const char * name;
-    std::string gccName; // GAS will take upper case, but GCC won't (needed for the clobber list)
-    Identifier * ident;
-    char size;
-    char baseReg; // %% todo: Reg, Reg_XX
-} regInfo[N_Regs] = {
-    { "EAX", NULL_TREE, NULL, 4,  Reg_EAX },
-    { "EBX", NULL_TREE, NULL, 4,  Reg_EBX },
-    { "ECX", NULL_TREE, NULL, 4,  Reg_ECX },
-    { "EDX", NULL_TREE, NULL, 4,  Reg_EDX },
-    { "ESI", NULL_TREE, NULL, 4,  Reg_ESI },
-    { "EDI", NULL_TREE, NULL, 4,  Reg_EDI },
-    { "EBP", NULL_TREE, NULL, 4,  Reg_EBP },
-    { "ESP", NULL_TREE, NULL, 4,  Reg_ESP },
-    { "ST", NULL_TREE, NULL,   10, Reg_ST },
-    { "ST(1)", NULL_TREE, NULL,10, Reg_ST1 },
-    { "ST(2)", NULL_TREE, NULL,10, Reg_ST2 },
-    { "ST(3)", NULL_TREE, NULL,10, Reg_ST3 },
-    { "ST(4)", NULL_TREE, NULL,10, Reg_ST4 },
-    { "ST(5)", NULL_TREE, NULL,10, Reg_ST5 },
-    { "ST(6)", NULL_TREE, NULL,10, Reg_ST6 },
-    { "ST(7)", NULL_TREE, NULL,10, Reg_ST7 },
-    { "MM0", NULL_TREE, NULL, 8, Reg_MM0 },
-    { "MM1", NULL_TREE, NULL, 8, Reg_MM1 },
-    { "MM2", NULL_TREE, NULL, 8, Reg_MM2 },
-    { "MM3", NULL_TREE, NULL, 8, Reg_MM3 },
-    { "MM4", NULL_TREE, NULL, 8, Reg_MM4 },
-    { "MM5", NULL_TREE, NULL, 8, Reg_MM5 },
-    { "MM6", NULL_TREE, NULL, 8, Reg_MM6 },
-    { "MM7", NULL_TREE, NULL, 8, Reg_MM7 },
-    { "XMM0", NULL_TREE, NULL, 16, Reg_XMM0 },
-    { "XMM1", NULL_TREE, NULL, 16, Reg_XMM1 },
-    { "XMM2", NULL_TREE, NULL, 16, Reg_XMM2 },
-    { "XMM3", NULL_TREE, NULL, 16, Reg_XMM3 },
-    { "XMM4", NULL_TREE, NULL, 16, Reg_XMM4 },
-    { "XMM5", NULL_TREE, NULL, 16, Reg_XMM5 },
-    { "XMM6", NULL_TREE, NULL, 16, Reg_XMM6 },
-    { "XMM7", NULL_TREE, NULL, 16, Reg_XMM7 },
-    { "FLAGS", NULL_TREE, NULL, 0, Reg_EFLAGS }, // the gcc name is "flags"; not used in assembler input
-    { "CS",  NULL_TREE, NULL, 2, -1 },
-    { "DS",  NULL_TREE, NULL, 2, -1 },
-    { "SS",  NULL_TREE, NULL, 2, -1 },
-    { "ES",  NULL_TREE, NULL, 2, -1 },
-    { "FS",  NULL_TREE, NULL, 2, -1 },
-    { "GS",  NULL_TREE, NULL, 2, -1 },
-    { "AX",  NULL_TREE, NULL, 2,  Reg_EAX },
-    { "BX",  NULL_TREE, NULL, 2,  Reg_EBX },
-    { "CX",  NULL_TREE, NULL, 2,  Reg_ECX },
-    { "DX",  NULL_TREE, NULL, 2,  Reg_EDX },
-    { "SI",  NULL_TREE, NULL, 2,  Reg_ESI },
-    { "DI",  NULL_TREE, NULL, 2,  Reg_EDI },
-    { "BP",  NULL_TREE, NULL, 2,  Reg_EBP },
-    { "SP",  NULL_TREE, NULL, 2,  Reg_ESP },
-    { "AL",  NULL_TREE, NULL, 1,  Reg_EAX },
-    { "AH",  NULL_TREE, NULL, 1,  Reg_EAX },
-    { "BL",  NULL_TREE, NULL, 1,  Reg_EBX },
-    { "BH",  NULL_TREE, NULL, 1,  Reg_EBX },
-    { "CL",  NULL_TREE, NULL, 1,  Reg_ECX },
-    { "CH",  NULL_TREE, NULL, 1,  Reg_ECX },
-    { "DL",  NULL_TREE, NULL, 1,  Reg_EDX },
-    { "DH",  NULL_TREE, NULL, 1,  Reg_EDX },
-    { "CR0", NULL_TREE, NULL, 0, -1 },
-    { "CR2", NULL_TREE, NULL, 0, -1 },
-    { "CR3", NULL_TREE, NULL, 0, -1 },
-    { "CR4", NULL_TREE, NULL, 0, -1 },
-    { "DR0", NULL_TREE, NULL, 0, -1 },
-    { "DR1", NULL_TREE, NULL, 0, -1 },
-    { "DR2", NULL_TREE, NULL, 0, -1 },
-    { "DR3", NULL_TREE, NULL, 0, -1 },
-    { "DR6", NULL_TREE, NULL, 0, -1 },
-    { "DR7", NULL_TREE, NULL, 0, -1 },
-    { "TR3", NULL_TREE, NULL, 0, -1 },
-    { "TR4", NULL_TREE, NULL, 0, -1 },
-    { "TR5", NULL_TREE, NULL, 0, -1 },
-    { "TR6", NULL_TREE, NULL, 0, -1 },
-    { "TR7", NULL_TREE, NULL, 0, -1 }
-};
+    static struct
+    {
+        const char * name;
+        std::string gccName; // GAS will take upper case, but GCC won't (needed for the clobber list)
+        Identifier * ident;
+        char size;
+        char baseReg; // %% todo: Reg, Reg_XX
+    } regInfo[N_Regs] =
+    {
+        { "EAX", NULL_TREE, NULL, 4,  Reg_EAX },
+        { "EBX", NULL_TREE, NULL, 4,  Reg_EBX },
+        { "ECX", NULL_TREE, NULL, 4,  Reg_ECX },
+        { "EDX", NULL_TREE, NULL, 4,  Reg_EDX },
+        { "ESI", NULL_TREE, NULL, 4,  Reg_ESI },
+        { "EDI", NULL_TREE, NULL, 4,  Reg_EDI },
+        { "EBP", NULL_TREE, NULL, 4,  Reg_EBP },
+        { "ESP", NULL_TREE, NULL, 4,  Reg_ESP },
+        { "ST", NULL_TREE, NULL,   10, Reg_ST },
+        { "ST(1)", NULL_TREE, NULL,10, Reg_ST1 },
+        { "ST(2)", NULL_TREE, NULL,10, Reg_ST2 },
+        { "ST(3)", NULL_TREE, NULL,10, Reg_ST3 },
+        { "ST(4)", NULL_TREE, NULL,10, Reg_ST4 },
+        { "ST(5)", NULL_TREE, NULL,10, Reg_ST5 },
+        { "ST(6)", NULL_TREE, NULL,10, Reg_ST6 },
+        { "ST(7)", NULL_TREE, NULL,10, Reg_ST7 },
+        { "MM0", NULL_TREE, NULL, 8, Reg_MM0 },
+        { "MM1", NULL_TREE, NULL, 8, Reg_MM1 },
+        { "MM2", NULL_TREE, NULL, 8, Reg_MM2 },
+        { "MM3", NULL_TREE, NULL, 8, Reg_MM3 },
+        { "MM4", NULL_TREE, NULL, 8, Reg_MM4 },
+        { "MM5", NULL_TREE, NULL, 8, Reg_MM5 },
+        { "MM6", NULL_TREE, NULL, 8, Reg_MM6 },
+        { "MM7", NULL_TREE, NULL, 8, Reg_MM7 },
+        { "XMM0", NULL_TREE, NULL, 16, Reg_XMM0 },
+        { "XMM1", NULL_TREE, NULL, 16, Reg_XMM1 },
+        { "XMM2", NULL_TREE, NULL, 16, Reg_XMM2 },
+        { "XMM3", NULL_TREE, NULL, 16, Reg_XMM3 },
+        { "XMM4", NULL_TREE, NULL, 16, Reg_XMM4 },
+        { "XMM5", NULL_TREE, NULL, 16, Reg_XMM5 },
+        { "XMM6", NULL_TREE, NULL, 16, Reg_XMM6 },
+        { "XMM7", NULL_TREE, NULL, 16, Reg_XMM7 },
+        { "FLAGS", NULL_TREE, NULL, 0, Reg_EFLAGS }, // the gcc name is "flags"; not used in assembler input
+        { "CS",  NULL_TREE, NULL, 2, -1 },
+        { "DS",  NULL_TREE, NULL, 2, -1 },
+        { "SS",  NULL_TREE, NULL, 2, -1 },
+        { "ES",  NULL_TREE, NULL, 2, -1 },
+        { "FS",  NULL_TREE, NULL, 2, -1 },
+        { "GS",  NULL_TREE, NULL, 2, -1 },
+        { "AX",  NULL_TREE, NULL, 2,  Reg_EAX },
+        { "BX",  NULL_TREE, NULL, 2,  Reg_EBX },
+        { "CX",  NULL_TREE, NULL, 2,  Reg_ECX },
+        { "DX",  NULL_TREE, NULL, 2,  Reg_EDX },
+        { "SI",  NULL_TREE, NULL, 2,  Reg_ESI },
+        { "DI",  NULL_TREE, NULL, 2,  Reg_EDI },
+        { "BP",  NULL_TREE, NULL, 2,  Reg_EBP },
+        { "SP",  NULL_TREE, NULL, 2,  Reg_ESP },
+        { "AL",  NULL_TREE, NULL, 1,  Reg_EAX },
+        { "AH",  NULL_TREE, NULL, 1,  Reg_EAX },
+        { "BL",  NULL_TREE, NULL, 1,  Reg_EBX },
+        { "BH",  NULL_TREE, NULL, 1,  Reg_EBX },
+        { "CL",  NULL_TREE, NULL, 1,  Reg_ECX },
+        { "CH",  NULL_TREE, NULL, 1,  Reg_ECX },
+        { "DL",  NULL_TREE, NULL, 1,  Reg_EDX },
+        { "DH",  NULL_TREE, NULL, 1,  Reg_EDX },
+        { "CR0", NULL_TREE, NULL, 0, -1 },
+        { "CR2", NULL_TREE, NULL, 0, -1 },
+        { "CR3", NULL_TREE, NULL, 0, -1 },
+        { "CR4", NULL_TREE, NULL, 0, -1 },
+        { "DR0", NULL_TREE, NULL, 0, -1 },
+        { "DR1", NULL_TREE, NULL, 0, -1 },
+        { "DR2", NULL_TREE, NULL, 0, -1 },
+        { "DR3", NULL_TREE, NULL, 0, -1 },
+        { "DR6", NULL_TREE, NULL, 0, -1 },
+        { "DR7", NULL_TREE, NULL, 0, -1 },
+        { "TR3", NULL_TREE, NULL, 0, -1 },
+        { "TR4", NULL_TREE, NULL, 0, -1 },
+        { "TR5", NULL_TREE, NULL, 0, -1 },
+        { "TR6", NULL_TREE, NULL, 0, -1 },
+        { "TR7", NULL_TREE, NULL, 0, -1 }
+    };
 
-typedef enum {
-    No_Type_Needed,
-    Int_Types,
-    Word_Types, // same as Int_Types, but byte is not allowed
-    FP_Types,
-    FPInt_Types,
-    Byte_NoType, // byte only, but no type suffix
-} TypeNeeded;
+    typedef enum
+    {
+        No_Type_Needed,
+        Int_Types,
+        Word_Types, // same as Int_Types, but byte is not allowed
+        FP_Types,
+        FPInt_Types,
+        Byte_NoType, // byte only, but no type suffix
+    } TypeNeeded;
 
-typedef enum {
-    No_Link,
-    Out_Mnemonic,
-    Next_Form
-} OpLink;
+    typedef enum
+    {
+        No_Link,
+        Out_Mnemonic,
+        Next_Form
+    } OpLink;
 
-typedef enum {
-    Clb_SizeAX   = 0x01,
-    Clb_SizeDXAX = 0x02,
-    Clb_EAX      = 0x03,
-    Clb_DXAX_Mask = 0x03,
-    
-    Clb_Flags    = 0x04,
-    Clb_DI       = 0x08,
-    Clb_SI       = 0x10,
-    Clb_CX       = 0x20,
-    Clb_ST       = 0x40,
-    Clb_SP       = 0x80 // Doesn't actually let GCC know the frame pointer is modified
-} ImplicitClober;
+    typedef enum
+    {
+        Clb_SizeAX   = 0x01,
+        Clb_SizeDXAX = 0x02,
+        Clb_EAX      = 0x03,
+        Clb_DXAX_Mask = 0x03,
+
+        Clb_Flags    = 0x04,
+        Clb_DI       = 0x08,
+        Clb_SI       = 0x10,
+        Clb_CX       = 0x20,
+        Clb_ST       = 0x40,
+        Clb_SP       = 0x80 // Doesn't actually let GCC know the frame pointer is modified
+    } ImplicitClober;
 
 // "^ +/..\([A-Za-z_0-9]+\).*" -> "    \1,"
-typedef enum {
-    Op_Invalid,
-    Op_Adjust,
-    Op_Dst,
-    Op_Upd,
-    Op_DstW,
-    Op_DstF,
-    Op_UpdF,
-    Op_DstSrc,
-    Op_DstSrcF,
-    Op_UpdSrcF,
-    Op_DstSrcFW,
-    Op_UpdSrcFW,
-    Op_DstSrcSSE,
-    Op_DstSrcMMX,
-    Op_DstSrcImmS,
-    Op_DstSrcImmM,
-    Op_UpdSrcShft,
-    Op_DstSrcNT,
-    Op_UpdSrcNT,
-    Op_DstMemNT,
-    Op_DstRMBNT,
-    Op_DstRMWNT,
-    Op_UpdUpd,
-    Op_UpdUpdF,
-    Op_Src,
-    Op_SrcRMWNT,
-    Op_SrcW,
-    Op_SrcImm,
-    Op_Src_DXAXF,
-    Op_SrcMemNT,
-    Op_SrcMemNTF,
-    Op_SrcSrc,
-    Op_SrcSrcF,
-    Op_SrcSrcFW,
-    Op_SrcSrcSSEF,
-    Op_SrcSrcMMX,
-    Op_Shift,
-    Op_Branch,
-    Op_CBranch,
-    Op_0,
-    Op_0_AX,
-    Op_0_DXAX,
-    Op_Loop,
-    Op_Flags,
-    Op_F0_ST,
-    Op_F0_P,
-    Op_Fs_P,
-    Op_Fis,
-    Op_Fis_ST,
-    Op_Fis_P,
-    Op_Fid,
-    Op_Fid_P,
-    Op_Ffd,
-    Op_FfdR,
-    Op_Ffd_P,
-    Op_FfdR_P,
-    Op_Fd_P,
-    Op_FdST,
-    Op_FMath,
-    Op_FdSTiSTi,
-    Op_FPMath,
-    Op_FCmp,
-    Op_FCmp1,
-    Op_FCmpP,
-    Op_FCmpP1,
-    Op_FCmpFlg,
-    Op_FCmpFlgP,
-    Op_fld,
-    Op_fldR,
-    Op_fxch,
-    Op_fxch1,
-    Op_fxch0,
-    Op_SizedStack,
-    Op_bound,
-    Op_bswap,
-    Op_cmps,
-    Op_cmpsd,
-    Op_cmpsX,
-    Op_cmpxchg8b,
-    Op_cmpxchg,
-    Op_cpuid,
-    Op_enter,
-    Op_fdisi,
-    Op_feni,
-    Op_fsetpm,
-    Op_fXstsw,
-    Op_imul,
-    Op_imul2,
-    Op_imul1,
-    Op_in,
-    Op_ins,
-    Op_insX,
-    Op_iret,
-    Op_iretd,
-    Op_lods,
-    Op_lodsX,
-    Op_movs,
-    Op_movsd,
-    Op_movsX,
-    Op_movsx,
-    Op_movzx,
-    Op_mul,
-    Op_out,
-    Op_outs,
-    Op_outsX,
-    Op_push,
-    Op_ret,
-    Op_retf,
-    Op_scas,
-    Op_scasX,
-    Op_stos,
-    Op_stosX,
-    Op_xlat,
-    N_AsmOpInfo,
-    Op_Align,
-    Op_Even,
-    Op_Naked,
-    Op_db,
-    Op_ds,
-    Op_di,
-    Op_dl,
-    Op_df,
-    Op_dd,
-    Op_de
-} AsmOp;
+    typedef enum
+    {
+        Op_Invalid,
+        Op_Adjust,
+        Op_Dst,
+        Op_Upd,
+        Op_DstW,
+        Op_DstF,
+        Op_UpdF,
+        Op_DstSrc,
+        Op_DstSrcF,
+        Op_UpdSrcF,
+        Op_DstSrcFW,
+        Op_UpdSrcFW,
+        Op_DstSrcSSE,
+        Op_DstSrcMMX,
+        Op_DstSrcImmS,
+        Op_DstSrcImmM,
+        Op_UpdSrcShft,
+        Op_DstSrcNT,
+        Op_UpdSrcNT,
+        Op_DstMemNT,
+        Op_DstRMBNT,
+        Op_DstRMWNT,
+        Op_UpdUpd,
+        Op_UpdUpdF,
+        Op_Src,
+        Op_SrcRMWNT,
+        Op_SrcW,
+        Op_SrcImm,
+        Op_Src_DXAXF,
+        Op_SrcMemNT,
+        Op_SrcMemNTF,
+        Op_SrcSrc,
+        Op_SrcSrcF,
+        Op_SrcSrcFW,
+        Op_SrcSrcSSEF,
+        Op_SrcSrcMMX,
+        Op_Shift,
+        Op_Branch,
+        Op_CBranch,
+        Op_0,
+        Op_0_AX,
+        Op_0_DXAX,
+        Op_Loop,
+        Op_Flags,
+        Op_F0_ST,
+        Op_F0_P,
+        Op_Fs_P,
+        Op_Fis,
+        Op_Fis_ST,
+        Op_Fis_P,
+        Op_Fid,
+        Op_Fid_P,
+        Op_Ffd,
+        Op_FfdR,
+        Op_Ffd_P,
+        Op_FfdR_P,
+        Op_Fd_P,
+        Op_FdST,
+        Op_FMath,
+        Op_FdSTiSTi,
+        Op_FPMath,
+        Op_FCmp,
+        Op_FCmp1,
+        Op_FCmpP,
+        Op_FCmpP1,
+        Op_FCmpFlg,
+        Op_FCmpFlgP,
+        Op_fld,
+        Op_fldR,
+        Op_fxch,
+        Op_fxch1,
+        Op_fxch0,
+        Op_SizedStack,
+        Op_bound,
+        Op_bswap,
+        Op_cmps,
+        Op_cmpsd,
+        Op_cmpsX,
+        Op_cmpxchg8b,
+        Op_cmpxchg,
+        Op_cpuid,
+        Op_enter,
+        Op_fdisi,
+        Op_feni,
+        Op_fsetpm,
+        Op_fXstsw,
+        Op_imul,
+        Op_imul2,
+        Op_imul1,
+        Op_in,
+        Op_ins,
+        Op_insX,
+        Op_iret,
+        Op_iretd,
+        Op_lods,
+        Op_lodsX,
+        Op_movs,
+        Op_movsd,
+        Op_movsX,
+        Op_movsx,
+        Op_movzx,
+        Op_mul,
+        Op_out,
+        Op_outs,
+        Op_outsX,
+        Op_push,
+        Op_ret,
+        Op_retf,
+        Op_scas,
+        Op_scasX,
+        Op_stos,
+        Op_stosX,
+        Op_xlat,
+        N_AsmOpInfo,
+        Op_Align,
+        Op_Even,
+        Op_Naked,
+        Op_db,
+        Op_ds,
+        Op_di,
+        Op_dl,
+        Op_df,
+        Op_dd,
+        Op_de
+    } AsmOp;
 
-typedef enum {
-    Opr_None = 0,
-    OprC_MRI  = 1,
-    OprC_MR   = 2,
-    OprC_Mem  = 3,
-    OprC_Reg  = 4,
-    OprC_Imm  = 5,
-    OprC_SSE  = 6,
-    OprC_SSE_Mem = 7,
-    OprC_R32  = 8,
-    OprC_RWord = 9,
-    OprC_RFP   = 10,
-    OprC_AbsRel = 11,
-    OprC_Relative = 12,
-    OprC_Port = 13, // DX or imm
-    OprC_AX = 14, // AL,AX,EAX
-    OprC_DX = 15, // only DX
-    OprC_MMX = 16,
-    OprC_MMX_Mem = 17,
-    OprC_Shift = 18, // imm or CL
-    
-    Opr_ClassMask = 0x1f,
-    
-    Opr_Dest     = 0x20,
-    Opr_Update   = 0x60,
-    
-    Opr_NoType = 0x80,
-} OprVals;
+    typedef enum
+    {
+        Opr_None = 0,
+        OprC_MRI  = 1,
+        OprC_MR   = 2,
+        OprC_Mem  = 3,
+        OprC_Reg  = 4,
+        OprC_Imm  = 5,
+        OprC_SSE  = 6,
+        OprC_SSE_Mem = 7,
+        OprC_R32  = 8,
+        OprC_RWord = 9,
+        OprC_RFP   = 10,
+        OprC_AbsRel = 11,
+        OprC_Relative = 12,
+        OprC_Port = 13, // DX or imm
+        OprC_AX = 14, // AL,AX,EAX
+        OprC_DX = 15, // only DX
+        OprC_MMX = 16,
+        OprC_MMX_Mem = 17,
+        OprC_Shift = 18, // imm or CL
+
+        Opr_ClassMask = 0x1f,
+
+        Opr_Dest     = 0x20,
+        Opr_Update   = 0x60,
+
+        Opr_NoType = 0x80,
+    } OprVals;
 
 
-typedef struct {
-} AsmOprInfo;
+    typedef struct
+    {
+    } AsmOprInfo;
 
-typedef unsigned char Opr;
+    typedef unsigned char Opr;
 
-typedef struct {
-    Opr operands[3];
-    unsigned char
-	needsType : 3,
-	implicitClobbers : 8,
-        linkType : 2;
-    unsigned link;
+    typedef struct
+    {
+        Opr operands[3];
+        unsigned char
+    needsType : 3,
+    implicitClobbers : 8,
+    linkType : 2;
+        unsigned link;
+
+        /*
+        bool takesLabel() {
+        return operands[0] & Opr_Label;
+        }
+        */
 
-    /*
-    bool takesLabel() {
-	return operands[0] & Opr_Label;
-    }
-    */
-    
-    unsigned nOperands() {
-	if (!operands[0])
-	    return 0;
-	else if (!operands[1])
-	    return 1;
-	else if (!operands[2])
-	    return 2;
-	else
-	    return 3;
-    }
-} AsmOpInfo;
+        unsigned nOperands()
+        {
+            if ( !operands[0] )
+                return 0;
+            else if ( !operands[1] )
+                return 1;
+            else if ( !operands[2] )
+                return 2;
+            else
+                return 3;
+        }
+    } AsmOpInfo;
 
-typedef enum {
-    Mn_fdisi,
-    Mn_feni,
-    Mn_fsetpm,
-    Mn_iretw,
-    Mn_iret,
-    Mn_lret,
-    Mn_cmpxchg8b,
-    N_AltMn
-} Alternate_Mnemonics;
+    typedef enum
+    {
+        Mn_fdisi,
+        Mn_feni,
+        Mn_fsetpm,
+        Mn_iretw,
+        Mn_iret,
+        Mn_lret,
+        Mn_cmpxchg8b,
+        N_AltMn
+    } Alternate_Mnemonics;
 
-static const char * alternateMnemonics[N_AltMn] = {
-    ".byte 0xdb, 0xe1",
-    ".byte 0xdb, 0xe0",
-    ".byte 0xdb, 0xe4",
-    "iretw",
-    "iret",
-    "lret",
-    "cmpxchg8b" };
+    static const char * alternateMnemonics[N_AltMn] =
+    {
+        ".byte 0xdb, 0xe1",
+        ".byte 0xdb, 0xe0",
+        ".byte 0xdb, 0xe4",
+        "iretw",
+        "iret",
+        "lret",
+        "cmpxchg8b"
+    };
 
 #define mri  OprC_MRI
 #define mr   OprC_MR
@@ -380,127 +395,128 @@
 //#define L    Opr_Label
 
 // D=dest, N=notype
-static AsmOpInfo asmOpInfo[N_AsmOpInfo] = {
-    /* Op_Invalid   */  {},
-    /* Op_Adjust    */  { 0,0,0,             0, Clb_EAX /*just AX*/ },
-    /* Op_Dst       */  { D|mr,  0,    0,    1  },
-    /* Op_Upd       */  { U|mr,  0,    0,    1  },
-    /* Op_DstW      */  { D|mr,  0,    0,    Word_Types  },
-    /* Op_DstF      */  { D|mr,  0,    0,    1, Clb_Flags },
-    /* Op_UpdF      */  { U|mr,  0,    0,    1, Clb_Flags },
-    /* Op_DstSrc    */  { D|mr,  mri,  0,/**/1  }, 
-    /* Op_DstSrcF   */  { D|mr,  mri,  0,/**/1, Clb_Flags }, 
-    /* Op_UpdSrcF   */  { U|mr,  mri,  0,/**/1, Clb_Flags }, 
-    /* Op_DstSrcFW  */  { D|mr,  mri,  0,/**/Word_Types, Clb_Flags }, 
-    /* Op_UpdSrcFW  */  { U|mr,  mri,  0,/**/Word_Types, Clb_Flags }, 
-    /* Op_DstSrcSSE */  { U|sse, ssem, 0     },  // some may not be update %%
-    /* Op_DstSrcMMX */  { U|mmx, mmxm, 0     },  // some may not be update %%
-    /* Op_DstSrcImmS*/  { U|sse, ssem, N|imm  }, // some may not be update %%
-    /* Op_DstSrcImmM*/  { U|mmx, mmxm, N|imm  }, // some may not be update %%
-    /* Op_UpdSrcShft*/  { U|mr,  reg,  N|shft, 1, Clb_Flags }, // 16/32 only
-    /* Op_DstSrcNT  */  { D|mr,  mr,   0,    0 }, // used for movd .. operands can be rm32,sse,mmx
-    /* Op_UpdSrcNT  */  { U|mr,  mr,   0,    0 }, // used for movd .. operands can be rm32,sse,mmx
-    /* Op_DstMemNT  */  { D|mem, 0,    0     },
-    /* Op_DstRMBNT  */  { D|mr,  0,    0,    Byte_NoType },
-    /* Op_DstRMWNT  */  { D|mr,  0,    0     },
-    /* Op_UpdUpd    */  { U|mr,U|mr,   0,/**/1  }, 
-    /* Op_UpdUpdF   */  { U|mr,U|mr,   0,/**/1, Clb_Flags }, 
-    /* Op_Src       */  {   mri, 0,    0,    1  },
-    /* Op_SrcRMWNT  */  {   mr,  0,    0,    0  },
-    /* Op_SrcW      */  {   mri, 0,    0,    Word_Types  },
-    /* Op_SrcImm    */  {   imm },
-    /* Op_Src_DXAXF */  {   mr,  0,    0,    1, Clb_SizeDXAX|Clb_Flags },
-    /* Op_SrcMemNT  */  {   mem, 0,    0     },
-    /* Op_SrcMemNTF */  {   mem, 0,    0,    0, Clb_Flags },
-    /* Op_SrcSrc    */  {   mr,  mri,  0,    1  },
-    /* Op_SrcSrcF   */  {   mr,  mri,  0,    1, Clb_Flags },
-    /* Op_SrcSrcFW  */  {   mr,  mri,  0,    Word_Types, Clb_Flags },
-    /* Op_SrcSrcSSEF*/  {   sse, ssem, 0,    0, Clb_Flags },
-    /* Op_SrcSrcMMX */  {   mmx, mmx,  0, },
-    /* Op_Shift     */  { D|mr,N|shft, 0,/**/1, Clb_Flags }, 
-    /* Op_Branch    */  {   mri },
-    /* Op_CBranch   */  {   imm },
-    /* Op_0         */  {   0,0,0 },
-    /* Op_0_AX      */  {   0,0,0,           0, Clb_SizeAX },
-    /* Op_0_DXAX    */  {   0,0,0,           0, Clb_SizeDXAX }, // but for cwd/cdq -- how do know the size..
-    /* Op_Loop      */  {   imm, 0,    0,    0, Clb_CX },
-    /* Op_Flags     */  {   0,0,0,           0, Clb_Flags },
-    /* Op_F0_ST     */  {   0,0,0,           0, Clb_ST },
-    /* Op_F0_P      */  {   0,0,0,           0, Clb_ST }, // push, pops, etc. not sure how to inform gcc..
-    /* Op_Fs_P      */  {   mem, 0,    0,    0, Clb_ST }, // "
-    /* Op_Fis       */  {   mem, 0,    0,    FPInt_Types }, // only 16bit and 32bit, DMD defaults to 16bit
-    /* Op_Fis_ST    */  {   mem, 0,    0,    FPInt_Types, Clb_ST }, // "
-    /* Op_Fis_P     */  {   mem, 0,    0,    FPInt_Types, Clb_ST }, // push and pop, fild so also 64 bit 
-    /* Op_Fid       */  { D|mem, 0,    0,    FPInt_Types }, // only 16bit and 32bit, DMD defaults to 16bit
-    /* Op_Fid_P     */  { D|mem, 0,    0,    FPInt_Types, Clb_ST }, // push and pop, fild so also 64 bit 
-    /* Op_Ffd       */  { D|mfp, 0,    0,    FP_Types, 0, Next_Form, Op_FfdR }, // only 16bit and 32bit, DMD defaults to 16bit, reg form doesn't need type
-    /* Op_FfdR      */  { D|rfp, 0,    0  }, 
-    /* Op_Ffd_P     */  { D|mfp, 0,    0,    FP_Types, Clb_ST, Next_Form, Op_FfdR_P, }, // pop, fld so also 80 bit, "
-    /* Op_FfdR_P    */  { D|rfp, 0,    0,    0,        Clb_ST },
-    /* Op_Fd_P      */  { D|mem, 0,    0,    0, Clb_ST }, // "
-    /* Op_FdST      */  { D|rfp, 0,    0  },
-    /* Op_FMath     */  {   mfp, 0,    0,    FP_Types, Clb_ST, Next_Form, Op_FdSTiSTi  }, // and only single or double prec
-    /* Op_FdSTiSTi  */  { D|rfp, rfp,  0, },
-    /* Op_FPMath    */  { D|rfp, rfp,  0,    0,        Clb_ST, Next_Form, Op_F0_P }, // pops
-    /* Op_FCmp      */  {   mfp, 0,    0,    FP_Types, 0,      Next_Form, Op_FCmp1 }, // DMD defaults to float ptr
-    /* Op_FCmp1     */  {   rfp, 0,    0,    0,        0,      Next_Form, Op_0 },
-    /* Op_FCmpP     */  {   mfp, 0,    0,    FP_Types, 0,      Next_Form, Op_FCmpP1 }, // pops
-    /* Op_FCmpP1    */  {   rfp, 0,    0,    0,        0,      Next_Form, Op_F0_P }, // pops
-    /* Op_FCmpFlg   */  {   rfp, rfp,  0,    0,        Clb_Flags },
-    /* Op_FCmpFlgP  */  {   rfp, rfp,  0,    0,        Clb_Flags }, // pops
-    /* Op_fld       */  {   mfp, 0,    0,    FP_Types, Clb_ST, Next_Form, Op_fldR },
-    /* Op_fldR      */  {   rfp, 0,    0,    0,        Clb_ST },
-    /* Op_fxch      */  { D|rfp,D|rfp, 0,    0,        Clb_ST, Next_Form, Op_fxch1 }, // not in intel manual?, but DMD allows it (gas won't), second arg must be ST
-    /* Op_fxch1     */  { D|rfp, 0,    0,    0,        Clb_ST, Next_Form, Op_fxch0 },
-    /* Op_fxch0     */  {   0,   0,    0,    0,        Clb_ST }, // Also clobbers ST(1)
-    /* Op_SizedStack*/  {   0,   0,    0,    0,        Clb_SP }, // type suffix special case
-    /* Op_bound     */  {   mr,  mri,  0,    Word_Types  }, // operands *not* reversed for gas
-    /* Op_bswap     */  { D|r32      },
-    /* Op_cmps      */  {   mem, mem, 0,     1, Clb_DI|Clb_SI|Clb_Flags },
-    /* Op_cmpsd     */  {   0,   0,   0,     0, Clb_DI|Clb_SI|Clb_Flags, Next_Form, Op_DstSrcImmS },
-    /* Op_cmpsX     */  {   0,   0,   0,     0, Clb_DI|Clb_SI|Clb_Flags },
-    /* Op_cmpxchg8b */  { D|mem/*64*/,0,0,   0, Clb_SizeDXAX/*32*/|Clb_Flags, Out_Mnemonic, Mn_cmpxchg8b },
-    /* Op_cmpxchg   */  { D|mr,  reg, 0,     1, Clb_SizeAX|Clb_Flags },
-    /* Op_cpuid     */  {   0,0,0 },    // Clobbers eax, ebx, ecx, and edx. Handled specially below.
-    /* Op_enter     */  {   imm, imm }, // operands *not* reversed for gas, %% inform gcc of EBP clobber?, 
-    /* Op_fdisi     */  {   0,0,0,           0, 0, Out_Mnemonic, Mn_fdisi },
-    /* Op_feni      */  {   0,0,0,           0, 0, Out_Mnemonic, Mn_feni },
-    /* Op_fsetpm    */  {   0,0,0,           0, 0, Out_Mnemonic, Mn_fsetpm },
-    /* Op_fXstsw    */  { D|mr,  0,   0,     }, // ax is the only allowed register
-    /* Op_imul      */  { D|reg, mr,  imm,   1, Clb_Flags, Next_Form, Op_imul2 }, // 16/32 only
-    /* Op_imul2     */  { D|reg, mri, 0,     1, Clb_Flags, Next_Form, Op_imul1 }, // 16/32 only
-    /* Op_imul1     */  {   mr,  0,   0,     1, Clb_Flags|Clb_SizeDXAX },
-    /* Op_in        */  { D|ax,N|port,0,     1  },        
-    /* Op_ins       */  {   mem,N|dx, 0,     1, Clb_DI }, // can't override ES segment for this one
-    /* Op_insX      */  {   0,   0,   0,     0, Clb_DI }, // output segment overrides %% needs work
-    /* Op_iret      */  {   0,0,0,           0, 0, Out_Mnemonic, Mn_iretw },
-    /* Op_iretd     */  {   0,0,0,           0, 0, Out_Mnemonic, Mn_iret },
-    /* Op_lods      */  {   mem, 0,   0,     1, Clb_SI },
-    /* Op_lodsX     */  {   0,   0,   0,     0, Clb_SI },
-    /* Op_movs      */  {   mem, mem, 0,     1, Clb_DI|Clb_SI }, // only src/DS can be overridden
-    /* Op_movsd     */  {   0,   0,   0,     0, Clb_DI|Clb_SI, Next_Form, Op_DstSrcSSE }, // %% gas doesn't accept movsd .. has to movsl
-    /* Op_movsX     */  {   0,   0,   0,     0, Clb_DI|Clb_SI },
-    /* Op_movsx     */  { D|reg, mr,  0,     1 }, // type suffix is special case
-    /* Op_movzx     */  { D|reg, mr,  0,     1 }, // type suffix is special case
-    /* Op_mul       */  { U|ax,  mr,  0,     1, Clb_SizeDXAX|Clb_Flags, Next_Form, Op_Src_DXAXF },
-    /* Op_out       */  { N|port,ax,  0,     1  },        
-    /* Op_outs      */  { N|dx,  mem, 0,     1, Clb_SI },
-    /* Op_outsX     */  {   0,   0,   0,     0, Clb_SI },
-    /* Op_push      */  {   mri, 0,    0,    Word_Types, Clb_SP }, // would be Op_SrcW, but DMD defaults to 32-bit for immediate form
-    /* Op_ret       */  {   imm, 0,   0,     0, 0, Next_Form, Op_0  }, 
-    /* Op_retf      */  {   0,   0,   0,     0, 0, Out_Mnemonic, Mn_lret  },
-    /* Op_scas      */  {   mem, 0,   0,     1, Clb_DI|Clb_Flags },
-    /* Op_scasX     */  {   0,   0,   0,     0, Clb_DI|Clb_Flags },
-    /* Op_stos      */  {   mem, 0,   0,     1, Clb_DI },
-    /* Op_stosX     */  {   0,   0,   0,     0, Clb_DI },
-    /* Op_xlat      */  {   mem, 0,   0,     0, Clb_SizeAX }
-    
-    /// * Op_arpl      */  { D|mr,  reg }, // 16 only -> DstSrc
-    /// * Op_bsX       */  {   rw,  mrw,  0,    1, Clb_Flags },//->srcsrcf 
-    /// * Op_bt        */  {   mrw, riw,  0,    1, Clb_Flags },//->srcsrcf
-    /// * Op_btX       */  { D|mrw, riw,  0,    1, Clb_Flags },//->dstsrcf .. immediate does not contribute to size
-    /// * Op_cmovCC    */  { D|rw,  mrw,  0,    1 } // ->dstsrc
-};
+    static AsmOpInfo asmOpInfo[N_AsmOpInfo] =
+    {
+        /* Op_Invalid   */  {},
+        /* Op_Adjust    */  { 0,0,0,             0, Clb_EAX /*just AX*/ },
+        /* Op_Dst       */  { D|mr,  0,    0,    1  },
+        /* Op_Upd       */  { U|mr,  0,    0,    1  },
+        /* Op_DstW      */  { D|mr,  0,    0,    Word_Types  },
+        /* Op_DstF      */  { D|mr,  0,    0,    1, Clb_Flags },
+        /* Op_UpdF      */  { U|mr,  0,    0,    1, Clb_Flags },
+        /* Op_DstSrc    */  { D|mr,  mri,  0,/**/1  },
+        /* Op_DstSrcF   */  { D|mr,  mri,  0,/**/1, Clb_Flags },
+        /* Op_UpdSrcF   */  { U|mr,  mri,  0,/**/1, Clb_Flags },
+        /* Op_DstSrcFW  */  { D|mr,  mri,  0,/**/Word_Types, Clb_Flags },
+        /* Op_UpdSrcFW  */  { U|mr,  mri,  0,/**/Word_Types, Clb_Flags },
+        /* Op_DstSrcSSE */  { U|sse, ssem, 0     },  // some may not be update %%
+        /* Op_DstSrcMMX */  { U|mmx, mmxm, 0     },  // some may not be update %%
+        /* Op_DstSrcImmS*/  { U|sse, ssem, N|imm  }, // some may not be update %%
+        /* Op_DstSrcImmM*/  { U|mmx, mmxm, N|imm  }, // some may not be update %%
+        /* Op_UpdSrcShft*/  { U|mr,  reg,  N|shft, 1, Clb_Flags }, // 16/32 only
+        /* Op_DstSrcNT  */  { D|mr,  mr,   0,    0 }, // used for movd .. operands can be rm32,sse,mmx
+        /* Op_UpdSrcNT  */  { U|mr,  mr,   0,    0 }, // used for movd .. operands can be rm32,sse,mmx
+        /* Op_DstMemNT  */  { D|mem, 0,    0     },
+        /* Op_DstRMBNT  */  { D|mr,  0,    0,    Byte_NoType },
+        /* Op_DstRMWNT  */  { D|mr,  0,    0     },
+        /* Op_UpdUpd    */  { U|mr,U|mr,   0,/**/1  },
+        /* Op_UpdUpdF   */  { U|mr,U|mr,   0,/**/1, Clb_Flags },
+        /* Op_Src       */  {   mri, 0,    0,    1  },
+        /* Op_SrcRMWNT  */  {   mr,  0,    0,    0  },
+        /* Op_SrcW      */  {   mri, 0,    0,    Word_Types  },
+        /* Op_SrcImm    */  {   imm },
+        /* Op_Src_DXAXF */  {   mr,  0,    0,    1, Clb_SizeDXAX|Clb_Flags },
+        /* Op_SrcMemNT  */  {   mem, 0,    0     },
+        /* Op_SrcMemNTF */  {   mem, 0,    0,    0, Clb_Flags },
+        /* Op_SrcSrc    */  {   mr,  mri,  0,    1  },
+        /* Op_SrcSrcF   */  {   mr,  mri,  0,    1, Clb_Flags },
+        /* Op_SrcSrcFW  */  {   mr,  mri,  0,    Word_Types, Clb_Flags },
+        /* Op_SrcSrcSSEF*/  {   sse, ssem, 0,    0, Clb_Flags },
+        /* Op_SrcSrcMMX */  {   mmx, mmx,  0, },
+        /* Op_Shift     */  { D|mr,N|shft, 0,/**/1, Clb_Flags },
+        /* Op_Branch    */  {   mri },
+        /* Op_CBranch   */  {   imm },
+        /* Op_0         */  {   0,0,0 },
+        /* Op_0_AX      */  {   0,0,0,           0, Clb_SizeAX },
+        /* Op_0_DXAX    */  {   0,0,0,           0, Clb_SizeDXAX }, // but for cwd/cdq -- how do know the size..
+        /* Op_Loop      */  {   imm, 0,    0,    0, Clb_CX },
+        /* Op_Flags     */  {   0,0,0,           0, Clb_Flags },
+        /* Op_F0_ST     */  {   0,0,0,           0, Clb_ST },
+        /* Op_F0_P      */  {   0,0,0,           0, Clb_ST }, // push, pops, etc. not sure how to inform gcc..
+        /* Op_Fs_P      */  {   mem, 0,    0,    0, Clb_ST }, // "
+        /* Op_Fis       */  {   mem, 0,    0,    FPInt_Types }, // only 16bit and 32bit, DMD defaults to 16bit
+        /* Op_Fis_ST    */  {   mem, 0,    0,    FPInt_Types, Clb_ST }, // "
+        /* Op_Fis_P     */  {   mem, 0,    0,    FPInt_Types, Clb_ST }, // push and pop, fild so also 64 bit
+        /* Op_Fid       */  { D|mem, 0,    0,    FPInt_Types }, // only 16bit and 32bit, DMD defaults to 16bit
+        /* Op_Fid_P     */  { D|mem, 0,    0,    FPInt_Types, Clb_ST }, // push and pop, fild so also 64 bit
+        /* Op_Ffd       */  { D|mfp, 0,    0,    FP_Types, 0, Next_Form, Op_FfdR }, // only 16bit and 32bit, DMD defaults to 16bit, reg form doesn't need type
+        /* Op_FfdR      */  { D|rfp, 0,    0  },
+        /* Op_Ffd_P     */  { D|mfp, 0,    0,    FP_Types, Clb_ST, Next_Form, Op_FfdR_P, }, // pop, fld so also 80 bit, "
+        /* Op_FfdR_P    */  { D|rfp, 0,    0,    0,        Clb_ST },
+        /* Op_Fd_P      */  { D|mem, 0,    0,    0, Clb_ST }, // "
+        /* Op_FdST      */  { D|rfp, 0,    0  },
+        /* Op_FMath     */  {   mfp, 0,    0,    FP_Types, Clb_ST, Next_Form, Op_FdSTiSTi  }, // and only single or double prec
+        /* Op_FdSTiSTi  */  { D|rfp, rfp,  0, },
+        /* Op_FPMath    */  { D|rfp, rfp,  0,    0,        Clb_ST, Next_Form, Op_F0_P }, // pops
+        /* Op_FCmp      */  {   mfp, 0,    0,    FP_Types, 0,      Next_Form, Op_FCmp1 }, // DMD defaults to float ptr
+        /* Op_FCmp1     */  {   rfp, 0,    0,    0,        0,      Next_Form, Op_0 },
+        /* Op_FCmpP     */  {   mfp, 0,    0,    FP_Types, 0,      Next_Form, Op_FCmpP1 }, // pops
+        /* Op_FCmpP1    */  {   rfp, 0,    0,    0,        0,      Next_Form, Op_F0_P }, // pops
+        /* Op_FCmpFlg   */  {   rfp, rfp,  0,    0,        Clb_Flags },
+        /* Op_FCmpFlgP  */  {   rfp, rfp,  0,    0,        Clb_Flags }, // pops
+        /* Op_fld       */  {   mfp, 0,    0,    FP_Types, Clb_ST, Next_Form, Op_fldR },
+        /* Op_fldR      */  {   rfp, 0,    0,    0,        Clb_ST },
+        /* Op_fxch      */  { D|rfp,D|rfp, 0,    0,        Clb_ST, Next_Form, Op_fxch1 }, // not in intel manual?, but DMD allows it (gas won't), second arg must be ST
+        /* Op_fxch1     */  { D|rfp, 0,    0,    0,        Clb_ST, Next_Form, Op_fxch0 },
+        /* Op_fxch0     */  {   0,   0,    0,    0,        Clb_ST }, // Also clobbers ST(1)
+        /* Op_SizedStack*/  {   0,   0,    0,    0,        Clb_SP }, // type suffix special case
+        /* Op_bound     */  {   mr,  mri,  0,    Word_Types  }, // operands *not* reversed for gas
+        /* Op_bswap     */  { D|r32      },
+        /* Op_cmps      */  {   mem, mem, 0,     1, Clb_DI|Clb_SI|Clb_Flags },
+        /* Op_cmpsd     */  {   0,   0,   0,     0, Clb_DI|Clb_SI|Clb_Flags, Next_Form, Op_DstSrcImmS },
+        /* Op_cmpsX     */  {   0,   0,   0,     0, Clb_DI|Clb_SI|Clb_Flags },
+        /* Op_cmpxchg8b */  { D|mem/*64*/,0,0,   0, Clb_SizeDXAX/*32*/|Clb_Flags, Out_Mnemonic, Mn_cmpxchg8b },
+        /* Op_cmpxchg   */  { D|mr,  reg, 0,     1, Clb_SizeAX|Clb_Flags },
+        /* Op_cpuid     */  {   0,0,0 },    // Clobbers eax, ebx, ecx, and edx. Handled specially below.
+        /* Op_enter     */  {   imm, imm }, // operands *not* reversed for gas, %% inform gcc of EBP clobber?,
+        /* Op_fdisi     */  {   0,0,0,           0, 0, Out_Mnemonic, Mn_fdisi },
+        /* Op_feni      */  {   0,0,0,           0, 0, Out_Mnemonic, Mn_feni },
+        /* Op_fsetpm    */  {   0,0,0,           0, 0, Out_Mnemonic, Mn_fsetpm },
+        /* Op_fXstsw    */  { D|mr,  0,   0,     }, // ax is the only allowed register
+        /* Op_imul      */  { D|reg, mr,  imm,   1, Clb_Flags, Next_Form, Op_imul2 }, // 16/32 only
+        /* Op_imul2     */  { D|reg, mri, 0,     1, Clb_Flags, Next_Form, Op_imul1 }, // 16/32 only
+        /* Op_imul1     */  {   mr,  0,   0,     1, Clb_Flags|Clb_SizeDXAX },
+        /* Op_in        */  { D|ax,N|port,0,     1  },
+        /* Op_ins       */  {   mem,N|dx, 0,     1, Clb_DI }, // can't override ES segment for this one
+        /* Op_insX      */  {   0,   0,   0,     0, Clb_DI }, // output segment overrides %% needs work
+        /* Op_iret      */  {   0,0,0,           0, 0, Out_Mnemonic, Mn_iretw },
+        /* Op_iretd     */  {   0,0,0,           0, 0, Out_Mnemonic, Mn_iret },
+        /* Op_lods      */  {   mem, 0,   0,     1, Clb_SI },
+        /* Op_lodsX     */  {   0,   0,   0,     0, Clb_SI },
+        /* Op_movs      */  {   mem, mem, 0,     1, Clb_DI|Clb_SI }, // only src/DS can be overridden
+        /* Op_movsd     */  {   0,   0,   0,     0, Clb_DI|Clb_SI, Next_Form, Op_DstSrcSSE }, // %% gas doesn't accept movsd .. has to movsl
+        /* Op_movsX     */  {   0,   0,   0,     0, Clb_DI|Clb_SI },
+        /* Op_movsx     */  { D|reg, mr,  0,     1 }, // type suffix is special case
+        /* Op_movzx     */  { D|reg, mr,  0,     1 }, // type suffix is special case
+        /* Op_mul       */  { U|ax,  mr,  0,     1, Clb_SizeDXAX|Clb_Flags, Next_Form, Op_Src_DXAXF },
+        /* Op_out       */  { N|port,ax,  0,     1  },
+        /* Op_outs      */  { N|dx,  mem, 0,     1, Clb_SI },
+        /* Op_outsX     */  {   0,   0,   0,     0, Clb_SI },
+        /* Op_push      */  {   mri, 0,    0,    Word_Types, Clb_SP }, // would be Op_SrcW, but DMD defaults to 32-bit for immediate form
+        /* Op_ret       */  {   imm, 0,   0,     0, 0, Next_Form, Op_0  },
+        /* Op_retf      */  {   0,   0,   0,     0, 0, Out_Mnemonic, Mn_lret  },
+        /* Op_scas      */  {   mem, 0,   0,     1, Clb_DI|Clb_Flags },
+        /* Op_scasX     */  {   0,   0,   0,     0, Clb_DI|Clb_Flags },
+        /* Op_stos      */  {   mem, 0,   0,     1, Clb_DI },
+        /* Op_stosX     */  {   0,   0,   0,     0, Clb_DI },
+        /* Op_xlat      */  {   mem, 0,   0,     0, Clb_SizeAX }
+
+        /// * Op_arpl      */  { D|mr,  reg }, // 16 only -> DstSrc
+        /// * Op_bsX       */  {   rw,  mrw,  0,    1, Clb_Flags },//->srcsrcf
+        /// * Op_bt        */  {   mrw, riw,  0,    1, Clb_Flags },//->srcsrcf
+        /// * Op_btX       */  { D|mrw, riw,  0,    1, Clb_Flags },//->dstsrcf .. immediate does not contribute to size
+        /// * Op_cmovCC    */  { D|rw,  mrw,  0,    1 } // ->dstsrc
+    };
 
 #undef mri
 #undef mr
@@ -524,2216 +540,2442 @@
 #undef N
 //#undef L
 
-typedef struct {
-    const char  * inMnemonic;
-    AsmOp   asmOp;
-} AsmOpEnt;
+    typedef struct
+    {
+        const char  * inMnemonic;
+        AsmOp   asmOp;
+    } AsmOpEnt;
 
-/* Some opcodes which have data size restrictions, but we don't check
+    /* Some opcodes which have data size restrictions, but we don't check
 
-   cmov, l<segreg> ?, lea, lsl, shld
+       cmov, l<segreg> ?, lea, lsl, shld
 
-   todo: push <immediate> is always the 32-bit form, even tho push <mem> is 16-bit
-*/
+       todo: push <immediate> is always the 32-bit form, even tho push <mem> is 16-bit
+    */
 
-static AsmOpEnt opData[] = {
-    { "aaa",    Op_Adjust },
-    { "aad",    Op_Adjust },
-    { "aam",    Op_Adjust },
-    { "aas",    Op_Adjust },
-    { "adc",    Op_UpdSrcF },
-    { "add",    Op_UpdSrcF },
-    { "addpd",  Op_DstSrcSSE },
-    { "addps",  Op_DstSrcSSE },
-    { "addsd",  Op_DstSrcSSE },
-    { "addss",  Op_DstSrcSSE },
-    { "addsubpd", Op_DstSrcSSE },
-    { "addsubps", Op_DstSrcSSE },    
-    { "align",  Op_Align },
-    { "and",    Op_UpdSrcF },
-    { "andnpd", Op_DstSrcSSE },
-    { "andnps", Op_DstSrcSSE },
-    { "andpd",  Op_DstSrcSSE },
-    { "andps",  Op_DstSrcSSE },
-    { "arpl",   Op_UpdSrcNT },
-    { "bound",  Op_bound },
-    { "bsf",    Op_SrcSrcFW },
-    { "bsr",    Op_SrcSrcFW },
-    { "bswap",  Op_bswap },
-    { "bt",     Op_SrcSrcFW },
-    { "btc",    Op_UpdSrcFW },
-    { "btr",    Op_UpdSrcFW },
-    { "bts",    Op_UpdSrcFW },
-    { "call",   Op_Branch },
-    { "cbw",    Op_0_AX },
-    { "cdq",    Op_0_DXAX },
-    { "clc",    Op_Flags },
-    { "cld",    Op_Flags },
-    { "clflush",Op_SrcMemNT },
-    { "cli",    Op_Flags },
-    { "clts",   Op_0 },
-    { "cmc",    Op_Flags },
-    { "cmova",  Op_DstSrc },
-    { "cmovae", Op_DstSrc },
-    { "cmovb",  Op_DstSrc },
-    { "cmovbe", Op_DstSrc },
-    { "cmovc",  Op_DstSrc },
-    { "cmove",  Op_DstSrc },
-    { "cmovg",  Op_DstSrc },
-    { "cmovge", Op_DstSrc },
-    { "cmovl",  Op_DstSrc },
-    { "cmovle", Op_DstSrc },
-    { "cmovna", Op_DstSrc },
-    { "cmovnae",Op_DstSrc },
-    { "cmovnb", Op_DstSrc },
-    { "cmovnbe",Op_DstSrc },
-    { "cmovnc", Op_DstSrc },
-    { "cmovne", Op_DstSrc },
-    { "cmovng", Op_DstSrc },
-    { "cmovnge",Op_DstSrc },
-    { "cmovnl", Op_DstSrc },
-    { "cmovnle",Op_DstSrc },
-    { "cmovno", Op_DstSrc },
-    { "cmovnp", Op_DstSrc },
-    { "cmovns", Op_DstSrc },
-    { "cmovnz", Op_DstSrc },
-    { "cmovo",  Op_DstSrc },
-    { "cmovp",  Op_DstSrc },
-    { "cmovpe", Op_DstSrc },
-    { "cmovpo", Op_DstSrc },
-    { "cmovs",  Op_DstSrc },
-    { "cmovz",  Op_DstSrc },
-    { "cmp",    Op_SrcSrcF },
-    { "cmppd",  Op_DstSrcImmS },
-    { "cmpps",  Op_DstSrcImmS },
-    { "cmps",   Op_cmps  },
-    { "cmpsb",  Op_cmpsX },
-    { "cmpsd",  Op_cmpsd }, // string cmp, and SSE cmp
-    { "cmpss",  Op_DstSrcImmS },
-    { "cmpsw",  Op_cmpsX },
-    { "cmpxch8b", Op_cmpxchg8b }, // %% DMD opcode typo?
-    { "cmpxchg",  Op_cmpxchg },
-    { "comisd", Op_SrcSrcSSEF },
-    { "comiss", Op_SrcSrcSSEF },
-    { "cpuid",  Op_cpuid },
-    { "cvtdq2pd", Op_DstSrcSSE },
-    { "cvtdq2ps", Op_DstSrcSSE },
-    { "cvtpd2dq", Op_DstSrcSSE },
-    { "cvtpd2pi", Op_DstSrcSSE },
-    { "cvtpd2ps", Op_DstSrcSSE },
-    { "cvtpi2pd", Op_DstSrcSSE },
-    { "cvtpi2ps", Op_DstSrcSSE },
-    { "cvtps2dq", Op_DstSrcSSE },
-    { "cvtps2pd", Op_DstSrcSSE },
-    { "cvtps2pi", Op_DstSrcSSE },
-    { "cvtsd2si", Op_DstSrcSSE },
-    { "cvtsd2ss", Op_DstSrcSSE },
-    { "cvtsi2sd", Op_DstSrcSSE },
-    { "cvtsi2ss", Op_DstSrcSSE },
-    { "cvtss2sd", Op_DstSrcSSE },
-    { "cvtss2si", Op_DstSrcSSE },
-    { "cvttpd2dq", Op_DstSrcSSE },
-    { "cvttpd2pi", Op_DstSrcSSE },
-    { "cvttps2dq", Op_DstSrcSSE },
-    { "cvttps2pi", Op_DstSrcSSE },
-    { "cvttsd2si", Op_DstSrcSSE },
-    { "cvttss2si", Op_DstSrcSSE },
-    { "cwd",  Op_0_DXAX },
-    { "cwde", Op_0_AX },
-    //{ "da", Op_ },// dunno what this is -- takes labels?
-    { "daa",   Op_Adjust },
-    { "das",   Op_Adjust },    
-    { "db",    Op_db },
-    { "dd",    Op_dd },
-    { "de",    Op_de },
-    { "dec",   Op_UpdF },
-    { "df",    Op_df },
-    { "di",    Op_di },
-    { "div",   Op_Src_DXAXF },
-    { "divpd", Op_DstSrcSSE },
-    { "divps", Op_DstSrcSSE },
-    { "divsd", Op_DstSrcSSE },
-    { "divss", Op_DstSrcSSE },
-    { "dl",    Op_dl },
-    { "dq",    Op_dl },
-    { "ds",    Op_ds },
-    { "dt",    Op_de },
-    { "dw",    Op_ds },
-    { "emms",  Op_0 }, // clobber all mmx/fp?
-    { "enter", Op_enter },
-    { "even",  Op_Even },
-    { "f2xm1",  Op_F0_ST }, // %% most of these are update...
-    { "fabs",   Op_F0_ST },
-    { "fadd",   Op_FMath },
-    { "faddp",  Op_FPMath },
-    { "fbld",   Op_Fs_P },
-    { "fbstp",  Op_Fd_P },
-    { "fchs",   Op_F0_ST },
-    { "fclex",  Op_0 },
-    { "fcmovb",   Op_FdSTiSTi }, // but only ST(0) can be the destination -- should be FdST0STi
-    { "fcmovbe",  Op_FdSTiSTi },
-    { "fcmove",   Op_FdSTiSTi },
-    { "fcmovnb",  Op_FdSTiSTi },
-    { "fcmovnbe", Op_FdSTiSTi },
-    { "fcmovne",  Op_FdSTiSTi },
-    { "fcmovnu",  Op_FdSTiSTi },
-    { "fcmovu",   Op_FdSTiSTi },
-    { "fcom",   Op_FCmp },
-    { "fcomi",  Op_FCmpFlg  }, 
-    { "fcomip", Op_FCmpFlgP },
-    { "fcomp",  Op_FCmpP },
-    { "fcompp", Op_F0_P },   // pops twice
-    { "fcos",   Op_F0_ST }, 
-    { "fdecstp",Op_F0_P },   // changes stack
-    { "fdisi",  Op_fdisi },
-    { "fdiv",   Op_FMath },
-    { "fdivp",  Op_FPMath }, 
-    { "fdivr",  Op_FMath },
-    { "fdivrp", Op_FPMath },
-    { "feni",   Op_feni },
-    { "ffree",  Op_FdST },
-    { "fiadd",  Op_Fis_ST },
-    { "ficom",  Op_Fis   },
-    { "ficomp", Op_Fis_P },
-    { "fidiv",  Op_Fis_ST },
-    { "fidivr", Op_Fis_ST },
-    { "fild",   Op_Fis_P },
-    { "fimul",  Op_Fis_ST },
-    { "fincstp",Op_F0_P },
-    { "finit",  Op_F0_P },
-    { "fist",   Op_Fid }, // only 16,32bit
-    { "fistp",  Op_Fid_P }, 
-    { "fisttp", Op_Fid_P }, 
-    { "fisub",  Op_Fis_ST },
-    { "fisubr", Op_Fis_ST },
-    { "fld",    Op_fld },
-    { "fld1",   Op_F0_P },
-    { "fldcw",  Op_SrcMemNT },
-    { "fldenv", Op_SrcMemNT },
-    { "fldl2e", Op_F0_P },
-    { "fldl2t", Op_F0_P },
-    { "fldlg2", Op_F0_P },
-    { "fldln2", Op_F0_P },
-    { "fldpi",  Op_F0_P },
-    { "fldz",   Op_F0_P },
-    { "fmul",   Op_FMath },
-    { "fmulp",  Op_FPMath },
-    { "fnclex", Op_0 },
-    { "fndisi", Op_fdisi }, // ??
-    { "fneni",  Op_feni }, // ??
-    { "fninit", Op_0 },
-    { "fnop",   Op_0 },
-    { "fnsave", Op_DstMemNT },
-    { "fnstcw", Op_DstMemNT },
-    { "fnstenv",Op_DstMemNT },
-    { "fnstsw", Op_fXstsw },
-    { "fpatan", Op_F0_P }, // pop and modify new ST
-    { "fprem",  Op_F0_ST }, 
-    { "fprem1", Op_F0_ST }, 
-    { "fptan",  Op_F0_P }, // modify ST and push 1.0
-    { "frndint",Op_F0_ST }, 
-    { "frstor", Op_SrcMemNT }, // but clobbers everything
-    { "fsave",  Op_DstMemNT },
-    { "fscale", Op_F0_ST },
-    { "fsetpm", Op_fsetpm },
-    { "fsin",   Op_F0_ST },
-    { "fsincos",Op_F0_P },
-    { "fsqrt",  Op_F0_ST },
-    { "fst",    Op_Ffd },
-    { "fstcw",  Op_DstMemNT },
-    { "fstenv", Op_DstMemNT },
-    { "fstp",   Op_Ffd_P },
-    { "fstsw",  Op_fXstsw },
-    { "fsub",   Op_FMath },
-    { "fsubp",  Op_FPMath },
-    { "fsubr",  Op_FMath },
-    { "fsubrp", Op_FPMath },
-    { "ftst",   Op_0 },
-    { "fucom",  Op_FCmp },
-    { "fucomi", Op_FCmpFlg },
-    { "fucomip",Op_FCmpFlgP },
-    { "fucomp", Op_FCmpP },
-    { "fucompp",Op_F0_P }, // pops twice
-    { "fwait",  Op_0 },
-    { "fxam",   Op_0 },
-    { "fxch",   Op_fxch },
-    { "fxrstor",Op_SrcMemNT },  // clobbers FP,MMX,SSE
-    { "fxsave", Op_DstMemNT },
-    { "fxtract",Op_F0_P }, // pushes
-    { "fyl2x",  Op_F0_P }, // pops
-    { "fyl2xp1",Op_F0_P }, // pops
-    { "haddpd", Op_DstSrcSSE },
-    { "haddps", Op_DstSrcSSE },
-    { "hlt",  Op_0 },
-    { "hsubpd", Op_DstSrcSSE },
-    { "hsubps", Op_DstSrcSSE },
-    { "idiv", Op_Src_DXAXF },
-    { "imul", Op_imul },
-    { "in",   Op_in },
-    { "inc",  Op_UpdF },
-    { "ins",  Op_ins },
-    { "insb", Op_insX },
-    { "insd", Op_insX },
-    { "insw", Op_insX },
-    { "int",  Op_SrcImm },
-    { "into", Op_0 },
-    { "invd", Op_0 },
-    { "invlpg", Op_SrcMemNT },
-    { "iret",  Op_iret },
-    { "iretd", Op_iretd },    
-    { "ja",    Op_CBranch },
-    { "jae",   Op_CBranch },
-    { "jb",    Op_CBranch },
-    { "jbe",   Op_CBranch },
-    { "jc",    Op_CBranch },
-    { "jcxz",  Op_CBranch },
-    { "je",    Op_CBranch },
-    { "jecxz", Op_CBranch },
-    { "jg",    Op_CBranch },
-    { "jge",   Op_CBranch },
-    { "jl",    Op_CBranch },
-    { "jle",   Op_CBranch },
-    { "jmp",   Op_Branch },
-    { "jna",   Op_CBranch },
-    { "jnae",  Op_CBranch },
-    { "jnb",   Op_CBranch },
-    { "jnbe",  Op_CBranch },
-    { "jnc",   Op_CBranch },
-    { "jne",   Op_CBranch },
-    { "jng",   Op_CBranch },
-    { "jnge",  Op_CBranch },
-    { "jnl",   Op_CBranch },
-    { "jnle",  Op_CBranch },
-    { "jno",   Op_CBranch },
-    { "jnp",   Op_CBranch },
-    { "jns",   Op_CBranch },
-    { "jnz",   Op_CBranch },
-    { "jo",    Op_CBranch },
-    { "jp",    Op_CBranch },
-    { "jpe",   Op_CBranch },
-    { "jpo",   Op_CBranch },
-    { "js",    Op_CBranch },
-    { "jz",    Op_CBranch },
-    { "lahf",  Op_0_AX },
-    { "lar",   Op_DstSrcFW }, // reg dest only
-    { "lddqu", Op_DstSrcSSE },
-    { "ldmxcsr", Op_SrcMemNT },
-    { "lds",   Op_DstSrc },  // reg dest only
-    { "lea",   Op_DstSrc },  // "
-    { "leave", Op_0 },       // EBP,ESP clobbers
-    { "les",   Op_DstSrc },
-    { "lfence",Op_0 },
-    { "lfs",   Op_DstSrc },
-    { "lgdt",  Op_SrcMemNT },
-    { "lgs",   Op_DstSrc },
-    { "lidt",  Op_SrcMemNT },
-    { "lldt",  Op_SrcRMWNT },
-    { "lmsw",  Op_SrcRMWNT },
-    { "lock",  Op_0 },
-    { "lods",  Op_lods },
-    { "lodsb", Op_lodsX },
-    { "lodsd", Op_lodsX },
-    { "lodsw", Op_lodsX },
-    { "loop",  Op_Loop },
-    { "loope", Op_Loop },
-    { "loopne",Op_Loop },
-    { "loopnz",Op_Loop },
-    { "loopz", Op_Loop },
-    { "lsl",   Op_DstSrcFW }, // reg dest only
-    { "lss",   Op_DstSrc },
-    { "ltr",   Op_DstMemNT },
-    { "maskmovdqu", Op_SrcSrcMMX }, // writes to [edi]
-    { "maskmovq",   Op_SrcSrcMMX }, 
-    { "maxpd", Op_DstSrcSSE },
-    { "maxps", Op_DstSrcSSE },
-    { "maxsd", Op_DstSrcSSE },
-    { "maxss", Op_DstSrcSSE },
-    { "mfence",Op_0},
-    { "minpd", Op_DstSrcSSE },
-    { "minps", Op_DstSrcSSE },
-    { "minsd", Op_DstSrcSSE },
-    { "minss", Op_DstSrcSSE },
-    { "monitor", Op_0 },
-    { "mov",   Op_DstSrc },
-    { "movapd",  Op_DstSrcSSE },
-    { "movaps",  Op_DstSrcSSE },
-    { "movd",    Op_DstSrcNT  }, // also mmx and sse
-    { "movddup", Op_DstSrcSSE },
-    { "movdq2q", Op_DstSrcNT }, // mmx/sse
-    { "movdqa",  Op_DstSrcSSE },
-    { "movdqu",  Op_DstSrcSSE },
-    { "movhlps", Op_DstSrcSSE },
-    { "movhpd",  Op_DstSrcSSE },
-    { "movhps",  Op_DstSrcSSE },
-    { "movlhps", Op_DstSrcSSE },
-    { "movlpd",  Op_DstSrcSSE },
-    { "movlps",  Op_DstSrcSSE },
-    { "movmskpd",Op_DstSrcSSE },
-    { "movmskps",Op_DstSrcSSE },
-    { "movntdq", Op_DstSrcNT  }, // limited to sse, but mem dest
-    { "movnti",  Op_DstSrcNT  }, // limited to gpr, but mem dest
-    { "movntpd", Op_DstSrcNT  }, // limited to sse, but mem dest
-    { "movntps", Op_DstSrcNT  }, // limited to sse, but mem dest
-    { "movntq",  Op_DstSrcNT  }, // limited to mmx, but mem dest
-    { "movq",    Op_DstSrcNT  }, // limited to sse and mmx
-    { "movq2dq", Op_DstSrcNT  }, // limited to sse <- mmx regs
-    { "movs",  Op_movs },
-    { "movsb", Op_movsX },
-    { "movsd", Op_movsd },
-    { "movshdup", Op_DstSrcSSE },
-    { "movsldup", Op_DstSrcSSE },
-    { "movss", Op_DstSrcSSE },
-    { "movsw", Op_movsX },
-    { "movsx", Op_movsx }, // word-only, reg dest
-    { "movupd",Op_DstSrcSSE },
-    { "movups",Op_DstSrcSSE },
-    { "movzx", Op_movzx },
-    { "mul",   Op_mul },
-    { "mulpd", Op_DstSrcSSE },
-    { "mulps", Op_DstSrcSSE },
-    { "mulsd", Op_DstSrcSSE },
-    { "mulss", Op_DstSrcSSE },
-    { "mwait", Op_0 },
-    { "naked", Op_Naked },
-    { "neg",   Op_UpdF },
-    { "nop",   Op_0 },
-    { "not",   Op_Upd },
-    { "or",    Op_UpdSrcF },
-    { "orpd",  Op_DstSrcSSE },
-    { "orps",  Op_DstSrcSSE },
-    { "out",   Op_out },
-    { "outs",  Op_outs },
-    { "outsb", Op_outsX },
-    { "outsd", Op_outsX },
-    { "outsw", Op_outsX },
-    { "packssdw", Op_DstSrcMMX }, // %% also SSE
-    { "packsswb", Op_DstSrcMMX },
-    { "packuswb", Op_DstSrcMMX },
-    { "paddb",    Op_DstSrcMMX },
-    { "paddd",    Op_DstSrcMMX },
-    { "paddq",    Op_DstSrcMMX },
-    { "paddsb",   Op_DstSrcMMX },
-    { "paddsw",   Op_DstSrcMMX },
-    { "paddusb",  Op_DstSrcMMX },
-    { "paddusw",  Op_DstSrcMMX },
-    { "paddw",    Op_DstSrcMMX },
-    { "pand",     Op_DstSrcMMX },
-    { "pandn",    Op_DstSrcMMX },
-    { "pavgb",    Op_DstSrcMMX },
-    { "pavgw",    Op_DstSrcMMX },
-    { "pcmpeqb",  Op_DstSrcMMX },
-    { "pcmpeqd",  Op_DstSrcMMX },
-    { "pcmpeqw",  Op_DstSrcMMX },
-    { "pcmpgtb",  Op_DstSrcMMX },
-    { "pcmpgtd",  Op_DstSrcMMX },
-    { "pcmpgtw",  Op_DstSrcMMX },
-    { "pextrw",   Op_DstSrcImmM }, // gpr32 dest
-    { "pinsrw",   Op_DstSrcImmM }, // gpr32(16), mem16 src, sse too
-    { "pmaddwd",  Op_DstSrcMMX },
-    { "pmaxsw",   Op_DstSrcMMX },
-    { "pmaxub",   Op_DstSrcMMX },
-    { "pminsw",   Op_DstSrcMMX },
-    { "pminub",   Op_DstSrcMMX },
-    { "pmovmskb", Op_DstSrcMMX },
-    { "pmulhuw",  Op_DstSrcMMX },
-    { "pmulhw",   Op_DstSrcMMX },
-    { "pmullw",   Op_DstSrcMMX },
-    { "pmuludq",  Op_DstSrcMMX }, // also sse
-    { "pop",      Op_DstW },
-    { "popa",     Op_SizedStack },  // For intel this is always 16-bit
-    { "popad",    Op_SizedStack },  // GAS doesn't accept 'popad' -- these clobber everything, but supposedly it would be used to preserve clobbered regs
-    { "popf",     Op_SizedStack },  // rewrite the insn with a special case
-    { "popfd",    Op_SizedStack }, 
-    { "por",      Op_DstSrcMMX },
-    { "prefetchnta", Op_SrcMemNT },
-    { "prefetcht0",  Op_SrcMemNT },
-    { "prefetcht1",  Op_SrcMemNT },
-    { "prefetcht2",  Op_SrcMemNT },
-    { "psadbw",   Op_DstSrcMMX },
-    { "pshufd",   Op_DstSrcImmM },
-    { "pshufhw",  Op_DstSrcImmM },
-    { "pshuflw",  Op_DstSrcImmM },
-    { "pshufw",   Op_DstSrcImmM },
-    { "pslld",    Op_DstSrcMMX }, // immediate operands...
-    { "pslldq",   Op_DstSrcMMX },
-    { "psllq",    Op_DstSrcMMX },
-    { "psllw",    Op_DstSrcMMX },
-    { "psrad",    Op_DstSrcMMX },
-    { "psraw",    Op_DstSrcMMX },
-    { "psrld",    Op_DstSrcMMX },
-    { "psrldq",   Op_DstSrcMMX },
-    { "psrlq",    Op_DstSrcMMX },
-    { "psrlw",    Op_DstSrcMMX },
-    { "psubb",    Op_DstSrcMMX },
-    { "psubd",    Op_DstSrcMMX },
-    { "psubq",    Op_DstSrcMMX },
-    { "psubsb",   Op_DstSrcMMX },
-    { "psubsw",   Op_DstSrcMMX },
-    { "psubusb",  Op_DstSrcMMX },
-    { "psubusw",  Op_DstSrcMMX },
-    { "psubw",    Op_DstSrcMMX },
-    { "punpckhbw", Op_DstSrcMMX },
-    { "punpckhdq", Op_DstSrcMMX },
-    { "punpckhqdq",Op_DstSrcMMX },
-    { "punpckhwd", Op_DstSrcMMX },
-    { "punpcklbw", Op_DstSrcMMX },
-    { "punpckldq", Op_DstSrcMMX },
-    { "punpcklqdq",Op_DstSrcMMX },
-    { "punpcklwd", Op_DstSrcMMX },
-    { "push",   Op_push },
-    { "pusha",  Op_SizedStack },
-    { "pushad", Op_SizedStack },
-    { "pushf",  Op_SizedStack },
-    { "pushfd", Op_SizedStack },
-    { "pxor",   Op_DstSrcMMX },
-    { "rcl",    Op_Shift }, // limited src operands -- change to shift
-    { "rcpps",  Op_DstSrcSSE },
-    { "rcpss",  Op_DstSrcSSE },
-    { "rcr",    Op_Shift },
-    { "rdmsr",  Op_0_DXAX },
-    { "rdpmc",  Op_0_DXAX },
-    { "rdtsc",  Op_0_DXAX },
-    { "rep",    Op_0 },
-    { "repe",   Op_0 },
-    { "repne",  Op_0 },
-    { "repnz",  Op_0 },
-    { "repz",   Op_0 },
-    { "ret",    Op_ret },
-    { "retf",   Op_retf },
-    { "rol",    Op_Shift },
-    { "ror",    Op_Shift },
-    { "rsm",    Op_0 },
-    { "rsqrtps", Op_DstSrcSSE },
-    { "rsqrtss", Op_DstSrcSSE },
-    { "sahf",   Op_Flags },
-    { "sal",    Op_Shift },
-    { "sar",    Op_Shift },
-    { "sbb",    Op_UpdSrcF },
-    { "scas",   Op_scas },
-    { "scasb",  Op_scasX },
-    { "scasd",  Op_scasX },
-    { "scasw",  Op_scasX },
-    { "seta",   Op_DstRMBNT }, // also gpr8
-    { "setae",  Op_DstRMBNT },
-    { "setb",   Op_DstRMBNT },
-    { "setbe",  Op_DstRMBNT },
-    { "setc",   Op_DstRMBNT },
-    { "sete",   Op_DstRMBNT },
-    { "setg",   Op_DstRMBNT },
-    { "setge",  Op_DstRMBNT },
-    { "setl",   Op_DstRMBNT },
-    { "setle",  Op_DstRMBNT },
-    { "setna",  Op_DstRMBNT },
-    { "setnae", Op_DstRMBNT },
-    { "setnb",  Op_DstRMBNT },
-    { "setnbe", Op_DstRMBNT },
-    { "setnc",  Op_DstRMBNT },
-    { "setne",  Op_DstRMBNT },
-    { "setng",  Op_DstRMBNT },
-    { "setnge", Op_DstRMBNT },
-    { "setnl",  Op_DstRMBNT },
-    { "setnle", Op_DstRMBNT },
-    { "setno",  Op_DstRMBNT },
-    { "setnp",  Op_DstRMBNT },
-    { "setns",  Op_DstRMBNT },
-    { "setnz",  Op_DstRMBNT },
-    { "seto",   Op_DstRMBNT },
-    { "setp",   Op_DstRMBNT },
-    { "setpe",  Op_DstRMBNT },
-    { "setpo",  Op_DstRMBNT },
-    { "sets",   Op_DstRMBNT },
-    { "setz",   Op_DstRMBNT },
-    { "sfence", Op_0 },
-    { "sgdt",   Op_DstMemNT },
-    { "shl",    Op_Shift },
-    { "shld",   Op_UpdSrcShft },
-    { "shr",    Op_Shift },
-    { "shrd",   Op_UpdSrcShft },
-    { "shufpd", Op_DstSrcImmS },
-    { "shufps", Op_DstSrcImmS },
-    { "sidt",   Op_DstMemNT },
-    { "sldt",   Op_DstRMWNT },
-    { "smsw",   Op_DstRMWNT },
-    { "sqrtpd", Op_DstSrcSSE },
-    { "sqrtps", Op_DstSrcSSE },
-    { "sqrtsd", Op_DstSrcSSE },
-    { "sqrtss", Op_DstSrcSSE },
-    { "stc",    Op_Flags },
-    { "std",    Op_Flags },
-    { "sti",    Op_Flags },
-    { "stmxcsr",Op_DstMemNT },
-    { "stos",   Op_stos },
-    { "stosb",  Op_stosX },
-    { "stosd",  Op_stosX },
-    { "stosw",  Op_stosX },
-    { "str",    Op_DstMemNT }, // also r16
-    { "sub",    Op_UpdSrcF },
-    { "subpd",  Op_DstSrcSSE },
-    { "subps",  Op_DstSrcSSE },
-    { "subsd",  Op_DstSrcSSE },
-    { "subss",  Op_DstSrcSSE },
-    { "sysenter",Op_0 },
-    { "sysexit", Op_0 },
-    { "test",    Op_SrcSrcF },
-    { "ucomisd", Op_SrcSrcSSEF },
-    { "ucomiss", Op_SrcSrcSSEF },
-    { "ud2",     Op_0 },
-    { "unpckhpd", Op_DstSrcSSE },
-    { "unpckhps", Op_DstSrcSSE },
-    { "unpcklpd", Op_DstSrcSSE },
-    { "unpcklps", Op_DstSrcSSE },
-    { "verr",   Op_SrcMemNTF },
-    { "verw",   Op_SrcMemNTF },
-    { "wait",   Op_0 },
-    { "wbinvd", Op_0 },
-    { "wrmsr",  Op_0 },
-    { "xadd",   Op_UpdUpdF },
-    { "xchg",   Op_UpdUpd },
-    { "xlat",   Op_xlat },
-    { "xlatb",  Op_0_AX },
-    { "xor",    Op_DstSrcF },
-    { "xorpd",  Op_DstSrcSSE },
-    { "xorps",  Op_DstSrcSSE },
-};
+    static AsmOpEnt opData[] =
+    {
+        { "aaa",    Op_Adjust },
+        { "aad",    Op_Adjust },
+        { "aam",    Op_Adjust },
+        { "aas",    Op_Adjust },
+        { "adc",    Op_UpdSrcF },
+        { "add",    Op_UpdSrcF },
+        { "addpd",  Op_DstSrcSSE },
+        { "addps",  Op_DstSrcSSE },
+        { "addsd",  Op_DstSrcSSE },
+        { "addss",  Op_DstSrcSSE },
+        { "addsubpd", Op_DstSrcSSE },
+        { "addsubps", Op_DstSrcSSE },
+        { "align",  Op_Align },
+        { "and",    Op_UpdSrcF },
+        { "andnpd", Op_DstSrcSSE },
+        { "andnps", Op_DstSrcSSE },
+        { "andpd",  Op_DstSrcSSE },
+        { "andps",  Op_DstSrcSSE },
+        { "arpl",   Op_UpdSrcNT },
+        { "bound",  Op_bound },
+        { "bsf",    Op_SrcSrcFW },
+        { "bsr",    Op_SrcSrcFW },
+        { "bswap",  Op_bswap },
+        { "bt",     Op_SrcSrcFW },
+        { "btc",    Op_UpdSrcFW },
+        { "btr",    Op_UpdSrcFW },
+        { "bts",    Op_UpdSrcFW },
+        { "call",   Op_Branch },
+        { "cbw",    Op_0_AX },
+        { "cdq",    Op_0_DXAX },
+        { "clc",    Op_Flags },
+        { "cld",    Op_Flags },
+        { "clflush",Op_SrcMemNT },
+        { "cli",    Op_Flags },
+        { "clts",   Op_0 },
+        { "cmc",    Op_Flags },
+        { "cmova",  Op_DstSrc },
+        { "cmovae", Op_DstSrc },
+        { "cmovb",  Op_DstSrc },
+        { "cmovbe", Op_DstSrc },
+        { "cmovc",  Op_DstSrc },
+        { "cmove",  Op_DstSrc },
+        { "cmovg",  Op_DstSrc },
+        { "cmovge", Op_DstSrc },
+        { "cmovl",  Op_DstSrc },
+        { "cmovle", Op_DstSrc },
+        { "cmovna", Op_DstSrc },
+        { "cmovnae",Op_DstSrc },
+        { "cmovnb", Op_DstSrc },
+        { "cmovnbe",Op_DstSrc },
+        { "cmovnc", Op_DstSrc },
+        { "cmovne", Op_DstSrc },
+        { "cmovng", Op_DstSrc },
+        { "cmovnge",Op_DstSrc },
+        { "cmovnl", Op_DstSrc },
+        { "cmovnle",Op_DstSrc },
+        { "cmovno", Op_DstSrc },
+        { "cmovnp", Op_DstSrc },
+        { "cmovns", Op_DstSrc },
+        { "cmovnz", Op_DstSrc },
+        { "cmovo",  Op_DstSrc },
+        { "cmovp",  Op_DstSrc },
+        { "cmovpe", Op_DstSrc },
+        { "cmovpo", Op_DstSrc },
+        { "cmovs",  Op_DstSrc },
+        { "cmovz",  Op_DstSrc },
+        { "cmp",    Op_SrcSrcF },
+        { "cmppd",  Op_DstSrcImmS },
+        { "cmpps",  Op_DstSrcImmS },
+        { "cmps",   Op_cmps  },
+        { "cmpsb",  Op_cmpsX },
+        { "cmpsd",  Op_cmpsd }, // string cmp, and SSE cmp
+        { "cmpss",  Op_DstSrcImmS },
+        { "cmpsw",  Op_cmpsX },
+        { "cmpxch8b", Op_cmpxchg8b }, // %% DMD opcode typo?
+        { "cmpxchg",  Op_cmpxchg },
+        { "comisd", Op_SrcSrcSSEF },
+        { "comiss", Op_SrcSrcSSEF },
+        { "cpuid",  Op_cpuid },
+        { "cvtdq2pd", Op_DstSrcSSE },
+        { "cvtdq2ps", Op_DstSrcSSE },
+        { "cvtpd2dq", Op_DstSrcSSE },
+        { "cvtpd2pi", Op_DstSrcSSE },
+        { "cvtpd2ps", Op_DstSrcSSE },
+        { "cvtpi2pd", Op_DstSrcSSE },
+        { "cvtpi2ps", Op_DstSrcSSE },
+        { "cvtps2dq", Op_DstSrcSSE },
+        { "cvtps2pd", Op_DstSrcSSE },
+        { "cvtps2pi", Op_DstSrcSSE },
+        { "cvtsd2si", Op_DstSrcSSE },
+        { "cvtsd2ss", Op_DstSrcSSE },
+        { "cvtsi2sd", Op_DstSrcSSE },
+        { "cvtsi2ss", Op_DstSrcSSE },
+        { "cvtss2sd", Op_DstSrcSSE },
+        { "cvtss2si", Op_DstSrcSSE },
+        { "cvttpd2dq", Op_DstSrcSSE },
+        { "cvttpd2pi", Op_DstSrcSSE },
+        { "cvttps2dq", Op_DstSrcSSE },
+        { "cvttps2pi", Op_DstSrcSSE },
+        { "cvttsd2si", Op_DstSrcSSE },
+        { "cvttss2si", Op_DstSrcSSE },
+        { "cwd",  Op_0_DXAX },
+        { "cwde", Op_0_AX },
+        //{ "da", Op_ },// dunno what this is -- takes labels?
+        { "daa",   Op_Adjust },
+        { "das",   Op_Adjust },
+        { "db",    Op_db },
+        { "dd",    Op_dd },
+        { "de",    Op_de },
+        { "dec",   Op_UpdF },
+        { "df",    Op_df },
+        { "di",    Op_di },
+        { "div",   Op_Src_DXAXF },
+        { "divpd", Op_DstSrcSSE },
+        { "divps", Op_DstSrcSSE },
+        { "divsd", Op_DstSrcSSE },
+        { "divss", Op_DstSrcSSE },
+        { "dl",    Op_dl },
+        { "dq",    Op_dl },
+        { "ds",    Op_ds },
+        { "dt",    Op_de },
+        { "dw",    Op_ds },
+        { "emms",  Op_0 }, // clobber all mmx/fp?
+        { "enter", Op_enter },
+        { "even",  Op_Even },
+        { "f2xm1",  Op_F0_ST }, // %% most of these are update...
+        { "fabs",   Op_F0_ST },
+        { "fadd",   Op_FMath },
+        { "faddp",  Op_FPMath },
+        { "fbld",   Op_Fs_P },
+        { "fbstp",  Op_Fd_P },
+        { "fchs",   Op_F0_ST },
+        { "fclex",  Op_0 },
+        { "fcmovb",   Op_FdSTiSTi }, // but only ST(0) can be the destination -- should be FdST0STi
+        { "fcmovbe",  Op_FdSTiSTi },
+        { "fcmove",   Op_FdSTiSTi },
+        { "fcmovnb",  Op_FdSTiSTi },
+        { "fcmovnbe", Op_FdSTiSTi },
+        { "fcmovne",  Op_FdSTiSTi },
+        { "fcmovnu",  Op_FdSTiSTi },
+        { "fcmovu",   Op_FdSTiSTi },
+        { "fcom",   Op_FCmp },
+        { "fcomi",  Op_FCmpFlg  },
+        { "fcomip", Op_FCmpFlgP },
+        { "fcomp",  Op_FCmpP },
+        { "fcompp", Op_F0_P },   // pops twice
+        { "fcos",   Op_F0_ST },
+        { "fdecstp",Op_F0_P },   // changes stack
+        { "fdisi",  Op_fdisi },
+        { "fdiv",   Op_FMath },
+        { "fdivp",  Op_FPMath },
+        { "fdivr",  Op_FMath },
+        { "fdivrp", Op_FPMath },
+        { "feni",   Op_feni },
+        { "ffree",  Op_FdST },
+        { "fiadd",  Op_Fis_ST },
+        { "ficom",  Op_Fis   },
+        { "ficomp", Op_Fis_P },
+        { "fidiv",  Op_Fis_ST },
+        { "fidivr", Op_Fis_ST },
+        { "fild",   Op_Fis_P },
+        { "fimul",  Op_Fis_ST },
+        { "fincstp",Op_F0_P },
+        { "finit",  Op_F0_P },
+        { "fist",   Op_Fid }, // only 16,32bit
+        { "fistp",  Op_Fid_P },
+        { "fisttp", Op_Fid_P },
+        { "fisub",  Op_Fis_ST },
+        { "fisubr", Op_Fis_ST },
+        { "fld",    Op_fld },
+        { "fld1",   Op_F0_P },
+        { "fldcw",  Op_SrcMemNT },
+        { "fldenv", Op_SrcMemNT },
+        { "fldl2e", Op_F0_P },
+        { "fldl2t", Op_F0_P },
+        { "fldlg2", Op_F0_P },
+        { "fldln2", Op_F0_P },
+        { "fldpi",  Op_F0_P },
+        { "fldz",   Op_F0_P },
+        { "fmul",   Op_FMath },
+        { "fmulp",  Op_FPMath },
+        { "fnclex", Op_0 },
+        { "fndisi", Op_fdisi }, // ??
+        { "fneni",  Op_feni }, // ??
+        { "fninit", Op_0 },
+        { "fnop",   Op_0 },
+        { "fnsave", Op_DstMemNT },
+        { "fnstcw", Op_DstMemNT },
+        { "fnstenv",Op_DstMemNT },
+        { "fnstsw", Op_fXstsw },
+        { "fpatan", Op_F0_P }, // pop and modify new ST
+        { "fprem",  Op_F0_ST },
+        { "fprem1", Op_F0_ST },
+        { "fptan",  Op_F0_P }, // modify ST and push 1.0
+        { "frndint",Op_F0_ST },
+        { "frstor", Op_SrcMemNT }, // but clobbers everything
+        { "fsave",  Op_DstMemNT },
+        { "fscale", Op_F0_ST },
+        { "fsetpm", Op_fsetpm },
+        { "fsin",   Op_F0_ST },
+        { "fsincos",Op_F0_P },
+        { "fsqrt",  Op_F0_ST },
+        { "fst",    Op_Ffd },
+        { "fstcw",  Op_DstMemNT },
+        { "fstenv", Op_DstMemNT },
+        { "fstp",   Op_Ffd_P },
+        { "fstsw",  Op_fXstsw },
+        { "fsub",   Op_FMath },
+        { "fsubp",  Op_FPMath },
+        { "fsubr",  Op_FMath },
+        { "fsubrp", Op_FPMath },
+        { "ftst",   Op_0 },
+        { "fucom",  Op_FCmp },
+        { "fucomi", Op_FCmpFlg },
+        { "fucomip",Op_FCmpFlgP },
+        { "fucomp", Op_FCmpP },
+        { "fucompp",Op_F0_P }, // pops twice
+        { "fwait",  Op_0 },
+        { "fxam",   Op_0 },
+        { "fxch",   Op_fxch },
+        { "fxrstor",Op_SrcMemNT },  // clobbers FP,MMX,SSE
+        { "fxsave", Op_DstMemNT },
+        { "fxtract",Op_F0_P }, // pushes
+        { "fyl2x",  Op_F0_P }, // pops
+        { "fyl2xp1",Op_F0_P }, // pops
+        { "haddpd", Op_DstSrcSSE },
+        { "haddps", Op_DstSrcSSE },
+        { "hlt",  Op_0 },
+        { "hsubpd", Op_DstSrcSSE },
+        { "hsubps", Op_DstSrcSSE },
+        { "idiv", Op_Src_DXAXF },
+        { "imul", Op_imul },
+        { "in",   Op_in },
+        { "inc",  Op_UpdF },
+        { "ins",  Op_ins },
+        { "insb", Op_insX },
+        { "insd", Op_insX },
+        { "insw", Op_insX },
+        { "int",  Op_SrcImm },
+        { "into", Op_0 },
+        { "invd", Op_0 },
+        { "invlpg", Op_SrcMemNT },
+        { "iret",  Op_iret },
+        { "iretd", Op_iretd },
+        { "ja",    Op_CBranch },
+        { "jae",   Op_CBranch },
+        { "jb",    Op_CBranch },
+        { "jbe",   Op_CBranch },
+        { "jc",    Op_CBranch },
+        { "jcxz",  Op_CBranch },
+        { "je",    Op_CBranch },
+        { "jecxz", Op_CBranch },
+        { "jg",    Op_CBranch },
+        { "jge",   Op_CBranch },
+        { "jl",    Op_CBranch },
+        { "jle",   Op_CBranch },
+        { "jmp",   Op_Branch },
+        { "jna",   Op_CBranch },
+        { "jnae",  Op_CBranch },
+        { "jnb",   Op_CBranch },
+        { "jnbe",  Op_CBranch },
+        { "jnc",   Op_CBranch },
+        { "jne",   Op_CBranch },
+        { "jng",   Op_CBranch },
+        { "jnge",  Op_CBranch },
+        { "jnl",   Op_CBranch },
+        { "jnle",  Op_CBranch },
+        { "jno",   Op_CBranch },
+        { "jnp",   Op_CBranch },
+        { "jns",   Op_CBranch },
+        { "jnz",   Op_CBranch },
+        { "jo",    Op_CBranch },
+        { "jp",    Op_CBranch },
+        { "jpe",   Op_CBranch },
+        { "jpo",   Op_CBranch },
+        { "js",    Op_CBranch },
+        { "jz",    Op_CBranch },
+        { "lahf",  Op_0_AX },
+        { "lar",   Op_DstSrcFW }, // reg dest only
+        { "lddqu", Op_DstSrcSSE },
+        { "ldmxcsr", Op_SrcMemNT },
+        { "lds",   Op_DstSrc },  // reg dest only
+        { "lea",   Op_DstSrc },  // "
+        { "leave", Op_0 },       // EBP,ESP clobbers
+        { "les",   Op_DstSrc },
+        { "lfence",Op_0 },
+        { "lfs",   Op_DstSrc },
+        { "lgdt",  Op_SrcMemNT },
+        { "lgs",   Op_DstSrc },
+        { "lidt",  Op_SrcMemNT },
+        { "lldt",  Op_SrcRMWNT },
+        { "lmsw",  Op_SrcRMWNT },
+        { "lock",  Op_0 },
+        { "lods",  Op_lods },
+        { "lodsb", Op_lodsX },
+        { "lodsd", Op_lodsX },
+        { "lodsw", Op_lodsX },
+        { "loop",  Op_Loop },
+        { "loope", Op_Loop },
+        { "loopne",Op_Loop },
+        { "loopnz",Op_Loop },
+        { "loopz", Op_Loop },
+        { "lsl",   Op_DstSrcFW }, // reg dest only
+        { "lss",   Op_DstSrc },
+        { "ltr",   Op_DstMemNT },
+        { "maskmovdqu", Op_SrcSrcMMX }, // writes to [edi]
+        { "maskmovq",   Op_SrcSrcMMX },
+        { "maxpd", Op_DstSrcSSE },
+        { "maxps", Op_DstSrcSSE },
+        { "maxsd", Op_DstSrcSSE },
+        { "maxss", Op_DstSrcSSE },
+        { "mfence",Op_0},
+        { "minpd", Op_DstSrcSSE },
+        { "minps", Op_DstSrcSSE },
+        { "minsd", Op_DstSrcSSE },
+        { "minss", Op_DstSrcSSE },
+        { "monitor", Op_0 },
+        { "mov",   Op_DstSrc },
+        { "movapd",  Op_DstSrcSSE },
+        { "movaps",  Op_DstSrcSSE },
+        { "movd",    Op_DstSrcNT  }, // also mmx and sse
+        { "movddup", Op_DstSrcSSE },
+        { "movdq2q", Op_DstSrcNT }, // mmx/sse
+        { "movdqa",  Op_DstSrcSSE },
+        { "movdqu",  Op_DstSrcSSE },
+        { "movhlps", Op_DstSrcSSE },
+        { "movhpd",  Op_DstSrcSSE },
+        { "movhps",  Op_DstSrcSSE },
+        { "movlhps", Op_DstSrcSSE },
+        { "movlpd",  Op_DstSrcSSE },
+        { "movlps",  Op_DstSrcSSE },
+        { "movmskpd",Op_DstSrcSSE },
+        { "movmskps",Op_DstSrcSSE },
+        { "movntdq", Op_DstSrcNT  }, // limited to sse, but mem dest
+        { "movnti",  Op_DstSrcNT  }, // limited to gpr, but mem dest
+        { "movntpd", Op_DstSrcNT  }, // limited to sse, but mem dest
+        { "movntps", Op_DstSrcNT  }, // limited to sse, but mem dest
+        { "movntq",  Op_DstSrcNT  }, // limited to mmx, but mem dest
+        { "movq",    Op_DstSrcNT  }, // limited to sse and mmx
+        { "movq2dq", Op_DstSrcNT  }, // limited to sse <- mmx regs
+        { "movs",  Op_movs },
+        { "movsb", Op_movsX },
+        { "movsd", Op_movsd },
+        { "movshdup", Op_DstSrcSSE },
+        { "movsldup", Op_DstSrcSSE },
+        { "movss", Op_DstSrcSSE },
+        { "movsw", Op_movsX },
+        { "movsx", Op_movsx }, // word-only, reg dest
+        { "movupd",Op_DstSrcSSE },
+        { "movups",Op_DstSrcSSE },
+        { "movzx", Op_movzx },
+        { "mul",   Op_mul },
+        { "mulpd", Op_DstSrcSSE },
+        { "mulps", Op_DstSrcSSE },
+        { "mulsd", Op_DstSrcSSE },
+        { "mulss", Op_DstSrcSSE },
+        { "mwait", Op_0 },
+        { "naked", Op_Naked },
+        { "neg",   Op_UpdF },
+        { "nop",   Op_0 },
+        { "not",   Op_Upd },
+        { "or",    Op_UpdSrcF },
+        { "orpd",  Op_DstSrcSSE },
+        { "orps",  Op_DstSrcSSE },
+        { "out",   Op_out },
+        { "outs",  Op_outs },
+        { "outsb", Op_outsX },
+        { "outsd", Op_outsX },
+        { "outsw", Op_outsX },
+        { "packssdw", Op_DstSrcMMX }, // %% also SSE
+        { "packsswb", Op_DstSrcMMX },
+        { "packuswb", Op_DstSrcMMX },
+        { "paddb",    Op_DstSrcMMX },
+        { "paddd",    Op_DstSrcMMX },
+        { "paddq",    Op_DstSrcMMX },
+        { "paddsb",   Op_DstSrcMMX },
+        { "paddsw",   Op_DstSrcMMX },
+        { "paddusb",  Op_DstSrcMMX },
+        { "paddusw",  Op_DstSrcMMX },
+        { "paddw",    Op_DstSrcMMX },
+        { "pand",     Op_DstSrcMMX },
+        { "pandn",    Op_DstSrcMMX },
+        { "pavgb",    Op_DstSrcMMX },
+        { "pavgw",    Op_DstSrcMMX },
+        { "pcmpeqb",  Op_DstSrcMMX },
+        { "pcmpeqd",  Op_DstSrcMMX },
+        { "pcmpeqw",  Op_DstSrcMMX },
+        { "pcmpgtb",  Op_DstSrcMMX },
+        { "pcmpgtd",  Op_DstSrcMMX },
+        { "pcmpgtw",  Op_DstSrcMMX },
+        { "pextrw",   Op_DstSrcImmM }, // gpr32 dest
+        { "pinsrw",   Op_DstSrcImmM }, // gpr32(16), mem16 src, sse too
+        { "pmaddwd",  Op_DstSrcMMX },
+        { "pmaxsw",   Op_DstSrcMMX },
+        { "pmaxub",   Op_DstSrcMMX },
+        { "pminsw",   Op_DstSrcMMX },
+        { "pminub",   Op_DstSrcMMX },
+        { "pmovmskb", Op_DstSrcMMX },
+        { "pmulhuw",  Op_DstSrcMMX },
+        { "pmulhw",   Op_DstSrcMMX },
+        { "pmullw",   Op_DstSrcMMX },
+        { "pmuludq",  Op_DstSrcMMX }, // also sse
+        { "pop",      Op_DstW },
+        { "popa",     Op_SizedStack },  // For intel this is always 16-bit
+        { "popad",    Op_SizedStack },  // GAS doesn't accept 'popad' -- these clobber everything, but supposedly it would be used to preserve clobbered regs
+        { "popf",     Op_SizedStack },  // rewrite the insn with a special case
+        { "popfd",    Op_SizedStack },
+        { "por",      Op_DstSrcMMX },
+        { "prefetchnta", Op_SrcMemNT },
+        { "prefetcht0",  Op_SrcMemNT },
+        { "prefetcht1",  Op_SrcMemNT },
+        { "prefetcht2",  Op_SrcMemNT },
+        { "psadbw",   Op_DstSrcMMX },
+        { "pshufd",   Op_DstSrcImmM },
+        { "pshufhw",  Op_DstSrcImmM },
+        { "pshuflw",  Op_DstSrcImmM },
+        { "pshufw",   Op_DstSrcImmM },
+        { "pslld",    Op_DstSrcMMX }, // immediate operands...
+        { "pslldq",   Op_DstSrcMMX },
+        { "psllq",    Op_DstSrcMMX },
+        { "psllw",    Op_DstSrcMMX },
+        { "psrad",    Op_DstSrcMMX },
+        { "psraw",    Op_DstSrcMMX },
+        { "psrld",    Op_DstSrcMMX },
+        { "psrldq",   Op_DstSrcMMX },
+        { "psrlq",    Op_DstSrcMMX },
+        { "psrlw",    Op_DstSrcMMX },
+        { "psubb",    Op_DstSrcMMX },
+        { "psubd",    Op_DstSrcMMX },
+        { "psubq",    Op_DstSrcMMX },
+        { "psubsb",   Op_DstSrcMMX },
+        { "psubsw",   Op_DstSrcMMX },
+        { "psubusb",  Op_DstSrcMMX },
+        { "psubusw",  Op_DstSrcMMX },
+        { "psubw",    Op_DstSrcMMX },
+        { "punpckhbw", Op_DstSrcMMX },
+        { "punpckhdq", Op_DstSrcMMX },
+        { "punpckhqdq",Op_DstSrcMMX },
+        { "punpckhwd", Op_DstSrcMMX },
+        { "punpcklbw", Op_DstSrcMMX },
+        { "punpckldq", Op_DstSrcMMX },
+        { "punpcklqdq",Op_DstSrcMMX },
+        { "punpcklwd", Op_DstSrcMMX },
+        { "push",   Op_push },
+        { "pusha",  Op_SizedStack },
+        { "pushad", Op_SizedStack },
+        { "pushf",  Op_SizedStack },
+        { "pushfd", Op_SizedStack },
+        { "pxor",   Op_DstSrcMMX },
+        { "rcl",    Op_Shift }, // limited src operands -- change to shift
+        { "rcpps",  Op_DstSrcSSE },
+        { "rcpss",  Op_DstSrcSSE },
+        { "rcr",    Op_Shift },
+        { "rdmsr",  Op_0_DXAX },
+        { "rdpmc",  Op_0_DXAX },
+        { "rdtsc",  Op_0_DXAX },
+        { "rep",    Op_0 },
+        { "repe",   Op_0 },
+        { "repne",  Op_0 },
+        { "repnz",  Op_0 },
+        { "repz",   Op_0 },
+        { "ret",    Op_ret },
+        { "retf",   Op_retf },
+        { "rol",    Op_Shift },
+        { "ror",    Op_Shift },
+        { "rsm",    Op_0 },
+        { "rsqrtps", Op_DstSrcSSE },
+        { "rsqrtss", Op_DstSrcSSE },
+        { "sahf",   Op_Flags },
+        { "sal",    Op_Shift },
+        { "sar",    Op_Shift },
+        { "sbb",    Op_UpdSrcF },
+        { "scas",   Op_scas },
+        { "scasb",  Op_scasX },
+        { "scasd",  Op_scasX },
+        { "scasw",  Op_scasX },
+        { "seta",   Op_DstRMBNT }, // also gpr8
+        { "setae",  Op_DstRMBNT },
+        { "setb",   Op_DstRMBNT },
+        { "setbe",  Op_DstRMBNT },
+        { "setc",   Op_DstRMBNT },
+        { "sete",   Op_DstRMBNT },
+        { "setg",   Op_DstRMBNT },
+        { "setge",  Op_DstRMBNT },
+        { "setl",   Op_DstRMBNT },
+        { "setle",  Op_DstRMBNT },
+        { "setna",  Op_DstRMBNT },
+        { "setnae", Op_DstRMBNT },
+        { "setnb",  Op_DstRMBNT },
+        { "setnbe", Op_DstRMBNT },
+        { "setnc",  Op_DstRMBNT },
+        { "setne",  Op_DstRMBNT },
+        { "setng",  Op_DstRMBNT },
+        { "setnge", Op_DstRMBNT },
+        { "setnl",  Op_DstRMBNT },
+        { "setnle", Op_DstRMBNT },
+        { "setno",  Op_DstRMBNT },
+        { "setnp",  Op_DstRMBNT },
+        { "setns",  Op_DstRMBNT },
+        { "setnz",  Op_DstRMBNT },
+        { "seto",   Op_DstRMBNT },
+        { "setp",   Op_DstRMBNT },
+        { "setpe",  Op_DstRMBNT },
+        { "setpo",  Op_DstRMBNT },
+        { "sets",   Op_DstRMBNT },
+        { "setz",   Op_DstRMBNT },
+        { "sfence", Op_0 },
+        { "sgdt",   Op_DstMemNT },
+        { "shl",    Op_Shift },
+        { "shld",   Op_UpdSrcShft },
+        { "shr",    Op_Shift },
+        { "shrd",   Op_UpdSrcShft },
+        { "shufpd", Op_DstSrcImmS },
+        { "shufps", Op_DstSrcImmS },
+        { "sidt",   Op_DstMemNT },
+        { "sldt",   Op_DstRMWNT },
+        { "smsw",   Op_DstRMWNT },
+        { "sqrtpd", Op_DstSrcSSE },
+        { "sqrtps", Op_DstSrcSSE },
+        { "sqrtsd", Op_DstSrcSSE },
+        { "sqrtss", Op_DstSrcSSE },
+        { "stc",    Op_Flags },
+        { "std",    Op_Flags },
+        { "sti",    Op_Flags },
+        { "stmxcsr",Op_DstMemNT },
+        { "stos",   Op_stos },
+        { "stosb",  Op_stosX },
+        { "stosd",  Op_stosX },
+        { "stosw",  Op_stosX },
+        { "str",    Op_DstMemNT }, // also r16
+        { "sub",    Op_UpdSrcF },
+        { "subpd",  Op_DstSrcSSE },
+        { "subps",  Op_DstSrcSSE },
+        { "subsd",  Op_DstSrcSSE },
+        { "subss",  Op_DstSrcSSE },
+        { "sysenter",Op_0 },
+        { "sysexit", Op_0 },
+        { "test",    Op_SrcSrcF },
+        { "ucomisd", Op_SrcSrcSSEF },
+        { "ucomiss", Op_SrcSrcSSEF },
+        { "ud2",     Op_0 },
+        { "unpckhpd", Op_DstSrcSSE },
+        { "unpckhps", Op_DstSrcSSE },
+        { "unpcklpd", Op_DstSrcSSE },
+        { "unpcklps", Op_DstSrcSSE },
+        { "verr",   Op_SrcMemNTF },
+        { "verw",   Op_SrcMemNTF },
+        { "wait",   Op_0 },
+        { "wbinvd", Op_0 },
+        { "wrmsr",  Op_0 },
+        { "xadd",   Op_UpdUpdF },
+        { "xchg",   Op_UpdUpd },
+        { "xlat",   Op_xlat },
+        { "xlatb",  Op_0_AX },
+        { "xor",    Op_DstSrcF },
+        { "xorpd",  Op_DstSrcSSE },
+        { "xorps",  Op_DstSrcSSE },
+    };
 
-typedef enum {
-    Default_Ptr = 0,
-    Byte_Ptr = 1,
-    Short_Ptr = 2,
-    Int_Ptr = 4,
-    QWord_Ptr =  8,
-    Float_Ptr = 4,
-    Double_Ptr = 8,
-    Extended_Ptr = 10,
-    Near_Ptr = 98,
-    Far_Ptr = 99,
-    N_PtrTypes
-} PtrType;
+    typedef enum
+    {
+        Default_Ptr = 0,
+        Byte_Ptr = 1,
+        Short_Ptr = 2,
+        Int_Ptr = 4,
+        QWord_Ptr =  8,
+        Float_Ptr = 4,
+        Double_Ptr = 8,
+        Extended_Ptr = 10,
+        Near_Ptr = 98,
+        Far_Ptr = 99,
+        N_PtrTypes
+    } PtrType;
 
-static const int N_PtrNames = 8;
-static const char * ptrTypeNameTable[N_PtrNames] = {
-    "word", "dword", "qword",
-    "float", "double", "extended",
-    "near",  "far"
-};
+    static const int N_PtrNames = 8;
+    static const char * ptrTypeNameTable[N_PtrNames] =
+    {
+        "word", "dword", "qword",
+        "float", "double", "extended",
+        "near",  "far"
+    };
 
-static Identifier * ptrTypeIdentTable[N_PtrNames];
-static PtrType ptrTypeValueTable[N_PtrNames] = {
-    Short_Ptr, Int_Ptr, QWord_Ptr,
-    Float_Ptr, Double_Ptr, Extended_Ptr,
-    Near_Ptr, Far_Ptr
-};
+    static Identifier * ptrTypeIdentTable[N_PtrNames];
+    static PtrType ptrTypeValueTable[N_PtrNames] =
+    {
+        Short_Ptr, Int_Ptr, QWord_Ptr,
+        Float_Ptr, Double_Ptr, Extended_Ptr,
+        Near_Ptr, Far_Ptr
+    };
 
-typedef enum {
-    Opr_Invalid,
-    Opr_Immediate,
-    Opr_Reg,
-    Opr_Mem
-} OperandClass;
+    typedef enum
+    {
+        Opr_Invalid,
+        Opr_Immediate,
+        Opr_Reg,
+        Opr_Mem
+    } OperandClass;
 
-/* kill inlining if we reference a local? */
+    /* kill inlining if we reference a local? */
 
-/* DMD seems to allow only one 'symbol' per operand .. include __LOCAL_SIZE */
+    /* DMD seems to allow only one 'symbol' per operand .. include __LOCAL_SIZE */
 
-/* DMD offset usage: <parm>[<reg>] seems to always be relative to EBP+8 .. even
-   if naked.. */
+    /* DMD offset usage: <parm>[<reg>] seems to always be relative to EBP+8 .. even
+       if naked.. */
 
 // mov eax, 4
 // mov eax, fs:4
 // -- have to assume we know whether or not to use '$'
 
-static Token eof_tok;
-static Expression * Handled;
-static Identifier * ident_seg;
-
-struct AsmProcessor
-{
-    typedef struct {
-	int inBracket;
-	int hasBracket;
-	int hasNumber;
-	int isOffset;
-
-	Reg segmentPrefix;
-	Reg reg;
-	sinteger_t constDisplacement; // use to build up.. should be int constant in the end..
-	Array      symbolDisplacement; // array of expressions or..
-	Reg baseReg;
-	Reg indexReg;
-	int scale;
-	
-	OperandClass cls;
-	PtrType dataSize;
-	PtrType dataSizeHint; // DMD can use the type of a referenced variable
-    } Operand;
-
-    static const unsigned Max_Operands = 3;
-
-    AsmStatement * stmt;
-    Scope * sc;
-
-    Token * token;
-    OutBuffer * insnTemplate;
+    static Token eof_tok;
+    static Expression * Handled;
+    static Identifier * ident_seg;
 
-    AsmOp       op;
-    AsmOpInfo * opInfo;
-    Operand operands[Max_Operands];
-    Identifier * opIdent;
-    Operand * operand;
-
-    AsmProcessor(Scope * sc, AsmStatement * stmt)
-    {
-	this->sc = sc;
-	this->stmt = stmt;
-	token = stmt->tokens;
-	insnTemplate = new OutBuffer;
-
-	opInfo = NULL;
-
-	if ( ! regInfo[0].ident ) {
-	    char buf[8], *p;
-	    
-	    for (int i = 0; i < N_Regs; i++) {
-		strncpy(buf, regInfo[i].name, sizeof(buf) - 1);
-		for (p = buf; *p; p++)
-		    *p = std::tolower(*p);
-		regInfo[i].gccName = std::string(buf, p - buf);
-		if ( (i <= Reg_ST || i > Reg_ST7) && i != Reg_EFLAGS )
-		    regInfo[i].ident = Lexer::idPool(regInfo[i].name);
-	    }
-
-	    for (int i = 0; i < N_PtrNames; i++)
-		ptrTypeIdentTable[i] = Lexer::idPool(ptrTypeNameTable[i]);
-
-	    Handled = new Expression(0, TOKvoid, sizeof(Expression));
-
-	    ident_seg = Lexer::idPool("seg");
-	
-	    eof_tok.value = TOKeof; 
-	    eof_tok.next = 0;
-	}
-    }
-
-    void run()
+    struct AsmProcessor
     {
-	parse();
-    }
+        typedef struct
+        {
+            int inBracket;
+            int hasBracket;
+            int hasNumber;
+            int isOffset;
+
+            Reg segmentPrefix;
+            Reg reg;
+            sinteger_t constDisplacement; // use to build up.. should be int constant in the end..
+            Array      symbolDisplacement; // array of expressions or..
+            Reg baseReg;
+            Reg indexReg;
+            int scale;
+
+            OperandClass cls;
+            PtrType dataSize;
+            PtrType dataSizeHint; // DMD can use the type of a referenced variable
+        } Operand;
+
+        static const unsigned Max_Operands = 3;
+
+        AsmStatement * stmt;
+        Scope * sc;
+
+        Token * token;
+        OutBuffer * insnTemplate;
 
-    void nextToken() {
-	if (token->next)
-	    token = token->next;
-	else
-	    token = & eof_tok;
-    }
+        AsmOp       op;
+        AsmOpInfo * opInfo;
+        Operand operands[Max_Operands];
+        Identifier * opIdent;
+        Operand * operand;
+
+        AsmProcessor ( Scope * sc, AsmStatement * stmt )
+        {
+            this->sc = sc;
+            this->stmt = stmt;
+            token = stmt->tokens;
+            insnTemplate = new OutBuffer;
+
+            opInfo = NULL;
+
+            if ( ! regInfo[0].ident )
+            {
+                char buf[8], *p;
+
+                for ( int i = 0; i < N_Regs; i++ )
+                {
+                    strncpy ( buf, regInfo[i].name, sizeof ( buf ) - 1 );
+                    for ( p = buf; *p; p++ )
+                        *p = std::tolower ( *p );
+                    regInfo[i].gccName = std::string ( buf, p - buf );
+                    if ( ( i <= Reg_ST || i > Reg_ST7 ) && i != Reg_EFLAGS )
+                        regInfo[i].ident = Lexer::idPool ( regInfo[i].name );
+                }
+
+                for ( int i = 0; i < N_PtrNames; i++ )
+                    ptrTypeIdentTable[i] = Lexer::idPool ( ptrTypeNameTable[i] );
+
+                Handled = new Expression ( 0, TOKvoid, sizeof ( Expression ) );
+
+                ident_seg = Lexer::idPool ( "seg" );
 
-    Token * peekToken() {
-	if (token->next)
-	    return token->next;
-	else
-	    return & eof_tok;
-    }
+                eof_tok.value = TOKeof;
+                eof_tok.next = 0;
+            }
+        }
+
+        void run()
+        {
+            parse();
+        }
+
+        void nextToken()
+        {
+            if ( token->next )
+                token = token->next;
+            else
+                token = & eof_tok;
+        }
+
+        Token * peekToken()
+        {
+            if ( token->next )
+                return token->next;
+            else
+                return & eof_tok;
+        }
+
+        void expectEnd()
+        {
+            if ( token->value != TOKeof )
+                stmt->error ( "expected end of statement" ); // %% extra at end...
+        }
 
-    void expectEnd() {
-	if (token->value != TOKeof)
-	    stmt->error("expected end of statement"); // %% extra at end...
-    }
+        void parse()
+        {
+            op = parseOpcode();
+
+            switch ( op )
+            {
+                case Op_Align:
+                    doAlign();
+                    expectEnd();
+                    break;
+                case Op_Even:
+                    doEven();
+                    expectEnd();
+                    break;
+                case Op_Naked:
+                    doNaked();
+                    expectEnd();
+                    break;
+                case Op_Invalid:
+                    break;
+                default:
+                    if ( op >= Op_db && op <= Op_de )
+                        doData();
+                    else
+                        doInstruction();
+            }
+        }
+
+        AsmOp parseOpcode()
+        {
+            static const int N_ents = sizeof ( opData ) /sizeof ( AsmOpEnt );
 
-    void parse() {
-	op = parseOpcode();
-	
-	switch (op) {
-	case Op_Align:
-	    doAlign();
-	    expectEnd();
-	    break;
-	case Op_Even:
-	    doEven();
-	    expectEnd();
-	    break;
-	case Op_Naked:
-	    doNaked();
-	    expectEnd();
-	    break;
-	case Op_Invalid:
-	    break;
-	default:
-	    if (op >= Op_db && op <= Op_de)
-		doData();
-	    else
-		doInstruction();
-	}
-    }
+            switch ( token->value )
+            {
+                case TOKalign:
+                    nextToken();
+                    return Op_Align;
+                case TOKin:
+                    nextToken();
+                    opIdent = Id::___in;
+                    return Op_in;
+                case TOKint32: // "int"
+                    nextToken();
+                    opIdent = Id::__int;
+                    return Op_SrcImm;
+                case TOKout:
+                    nextToken();
+                    opIdent = Id::___out;
+                    return Op_out;
+                case TOKidentifier:
+                    // search for mnemonic below
+                    break;
+                default:
+                    stmt->error ( "expected opcode" );
+                    return Op_Invalid;
+            }
+
+            opIdent = token->ident;
+            const char * opcode = token->ident->string;
+
+            nextToken();
+
+            // %% okay to use bsearch?
+            int i = 0, j = N_ents, k, l;
+            do
+            {
+                k = ( i + j ) / 2;
+                l = strcmp ( opcode, opData[k].inMnemonic );
+                if ( ! l )
+                    return opData[k].asmOp;
+                else if ( l < 0 )
+                    j = k;
+                else
+                    i = k + 1;
+            }
+            while ( i != j );
+
+            stmt->error ( "unknown opcode '%s'", opcode );
+
+            return Op_Invalid;
+        }
+
+        // need clobber information.. use information is good too...
+        void doInstruction()
+        {
+            bool ok = true;
+            unsigned operand_i = 0;
+
+            opInfo = & asmOpInfo[op];
+            memset ( operands, 0, sizeof ( operands ) );
 
-    AsmOp parseOpcode() {
-	static const int N_ents = sizeof(opData)/sizeof(AsmOpEnt);
+            while ( token->value != TOKeof )
+            {
+                if ( operand_i < Max_Operands )
+                {
+                    operand = & operands[operand_i];
+                    operand->reg = operand->baseReg = operand->indexReg =
+                                                          operand->segmentPrefix = Reg_Invalid;
+                    parseOperand();
+                    operand_i++;
+                }
+                else
+                {
+                    ok = false;
+                    stmt->error ( "too many operands for instruction" );
+                    break;
+                }
+
+                if ( token->value == TOKcomma )
+                    nextToken();
+                else if ( token->value != TOKeof )
+                {
+                    ok = false;
+                    stmt->error ( "expected comma after operand" );
+                    return;
+                }
+            }
+//  if (operand_i < opInfo->minOperands) {
+//      ok = false;
+//      stmt->error("too few operands for instruction");
+//  }
+
+            if ( matchOperands ( operand_i ) )
+            {
+                AsmCode * asmcode = new AsmCode ( N_Regs );
+
+                if ( formatInstruction ( operand_i, asmcode ) )
+                    stmt->asmcode = ( code * ) asmcode;
+            }
+        }
 
-	switch (token->value) {
-	case TOKalign:
-	    nextToken();
-	    return Op_Align;
-	case TOKin:
-	    nextToken();
-	    opIdent = Id::___in;
-	    return Op_in;
-        case TOKint32: // "int"
-            nextToken();
-            opIdent = Id::__int;
-            return Op_SrcImm;
-	case TOKout:
-	    nextToken();
-	    opIdent = Id::___out;
-	    return Op_out;
-	case TOKidentifier:
-	    // search for mnemonic below
-	    break;
-	default:
-	    stmt->error("expected opcode");
-	    return Op_Invalid;
-	}
+        void setAsmCode()
+        {
+            AsmCode * asmcode = new AsmCode ( N_Regs );
+            asmcode->insnTemplateLen = insnTemplate->offset;
+            asmcode->insnTemplate = ( char* ) insnTemplate->extractData();
+            stmt->asmcode = ( code* ) asmcode;
+        }
+
+        // note: doesn't update AsmOp op
+        bool matchOperands ( unsigned nOperands )
+        {
+            bool wrong_number = true;
+
+            for ( unsigned i = 0; i < nOperands; i++ )
+                classifyOperand ( & operands[i] );
+
+            while ( 1 )
+            {
+                if ( nOperands == opInfo->nOperands() )
+                {
+                    wrong_number = false;
+                    /*  Cases in which number of operands is not
+                        enough for a match: Op_FCmp/Op_FCmp1,
+                        Op_FCmpP/Op_FCmpP1 */
+                    for ( unsigned i = 0; i < nOperands; i++ )
+                    {
+                        Operand * operand = & operands[i];
+
+                        switch ( opInfo->operands[i] & Opr_ClassMask )
+                        {
+                            case OprC_Mem: // no FPMem currently
+                                if ( operand->cls != Opr_Mem )
+                                    goto no_match;
+                                break;
+                            case OprC_RFP:
+                                if ( ! ( operand->reg >= Reg_ST && operand->reg <= Reg_ST7 ) )
+                                    goto no_match;
+                                break;
+                            default:
+                                break;
+                        }
+                    }
 
-	opIdent = token->ident;
-	const char * opcode = token->ident->string;
+                    return true;
+                }
+            no_match:
+                if ( opInfo->linkType == Next_Form )
+                    opInfo = & asmOpInfo[ op = ( AsmOp ) opInfo->link ];
+                else
+                    break;
+            }
+            if ( wrong_number )
+                stmt->error ( "wrong number of operands" );
+            else
+                stmt->error ( "wrong operand types" );
+            return false;
+        }
 
-	nextToken();
+        void addOperand ( const char * fmt, AsmArgType type, Expression * e, AsmCode * asmcode, AsmArgMode mode = Mode_Input )
+        {
+            if ( sc->func->naked )
+            {
+                switch ( type )
+                {
+                    case Arg_Integer:
+                        if ( e->type->isunsigned() )
+                            insnTemplate->printf ( "$%llu", e->toUInteger() );
+                        else
+                            insnTemplate->printf ( "$%lld", e->toInteger() );
+                        break;
 
-	// %% okay to use bsearch?
-	int i = 0, j = N_ents, k, l;
-	do {
-	    k = (i + j) / 2;
-	    l = strcmp(opcode, opData[k].inMnemonic);
-	    if (! l)
-		return opData[k].asmOp;
-	    else if (l < 0)
-		j = k;
-	    else
-		i = k + 1;
-	} while (i != j);
+                    case Arg_Pointer:
+                        stmt->error ( "unsupported pointer reference to '%s' in naked asm", e->toChars() );
+                        break;
 
-	stmt->error("unknown opcode '%s'", opcode);
-	
-	return Op_Invalid;
-    }
+                    case Arg_Memory:
+                        if ( e->op == TOKvar )
+                        {
+                            VarExp* v = ( VarExp* ) e;
+                            if ( VarDeclaration* vd = v->var->isVarDeclaration() )
+                            {
+                                if ( !vd->isDataseg() )
+                                {
+                                    stmt->error ( "only global variables can be referenced by identifier in naked asm" );
+                                    break;
+                                }
 
-    // need clobber information.. use information is good too...
-    void doInstruction() {
-	bool ok = true;
-	unsigned operand_i = 0;
-	
-	opInfo = & asmOpInfo[op];
-	memset(operands, 0, sizeof(operands));
+                                // osx needs an extra underscore
+                                if ( global.params.os == OSMacOSX )
+                                    insnTemplate->writestring ( "_" );
+
+                                // print out the mangle
+                                insnTemplate->writestring ( vd->mangle() );
+                                vd->nakedUse = true;
+                                break;
+                            }
+                        }
+                        stmt->error ( "unsupported memory reference to '%s' in naked asm", e->toChars() );
+                        break;
 
-	while (token->value != TOKeof) {
-	    if (operand_i < Max_Operands) {
-		operand = & operands[operand_i];
-		operand->reg = operand->baseReg = operand->indexReg =
-		    operand->segmentPrefix = Reg_Invalid;
-		parseOperand();
-		operand_i++;
-	    } else {
-		ok = false;
-		stmt->error("too many operands for instruction");
-		break;
-	    }
+                    default:
+                        assert ( 0 && "asm unsupported arg" );
+                        break;
+                }
+            }
+            else
+            {
+                insnTemplate->writestring ( ( char* ) fmt );
+                insnTemplate->printf ( "<<%s%d>>", ( mode==Mode_Input ) ?"in":"out", asmcode->args.dim );
+                asmcode->args.push ( new AsmArg ( type, e, mode ) );
+            }
+        }
+        void addOperand2 ( const char * fmtpre, const char * fmtpost, AsmArgType type, Expression * e, AsmCode * asmcode, AsmArgMode mode = Mode_Input )
+        {
+            assert ( !sc->func->naked );
+            insnTemplate->writestring ( ( char* ) fmtpre );
+            insnTemplate->printf ( "<<%s%d>>", ( mode==Mode_Input ) ?"in":"out", asmcode->args.dim );
+            insnTemplate->writestring ( ( char* ) fmtpost );
+            asmcode->args.push ( new AsmArg ( type, e, mode ) );
+        }
+
+        void addLabel ( char* id )
+        {
+            insnTemplate->writestring ( sc->func->mangle() );
+            insnTemplate->writestring ( "_" );
+            insnTemplate->writestring ( id );
+        }
+
+        /* Determines whether the operand is a register, memory reference
+           or immediate.  Immediate addresses are currently classified as
+           memory.  This function is called before the exact instructions
+           is known and thus, should not use opInfo. */
+        void classifyOperand ( Operand * operand )
+        {
+            operand->cls = classifyOperand1 ( operand );
+        }
 
-	    if (token->value == TOKcomma)
-		nextToken();
-	    else if (token->value != TOKeof) {
-		ok = false;
-		stmt->error("expected comma after operand");
-		return;
-	    }
-	}
-// 	if (operand_i < opInfo->minOperands) {
-// 	    ok = false;
-// 	    stmt->error("too few operands for instruction");
-// 	}
+        OperandClass classifyOperand1 ( Operand * operand )
+        {
+            bool is_localsize = false;
+            bool really_have_symbol = false;
+
+            if ( operand->symbolDisplacement.dim )
+            {
+                is_localsize = isLocalSize ( ( Expression * ) operand->symbolDisplacement.data[0] );
+                really_have_symbol = ! is_localsize;
+            }
 
-	if ( matchOperands(operand_i) ) {
-	    AsmCode * asmcode = new AsmCode(N_Regs);
+            if ( operand->isOffset && ! operand->hasBracket )
+                return Opr_Immediate;
+
+            if ( operand->hasBracket || really_have_symbol ) // %% redo for 'offset' function
+            {
+                if ( operand->reg != Reg_Invalid )
+                {
+                    invalidExpression();
+                    return Opr_Invalid;
+                }
 
-	    if (formatInstruction(operand_i, asmcode))
-		stmt->asmcode = (code *) asmcode;
-	}
-    }
+                return Opr_Mem;
+            }
+
+            if ( operand->reg != Reg_Invalid && operand->constDisplacement != 0 )
+            {
+                invalidExpression();
+                return Opr_Invalid;
+            }
 
-    void setAsmCode() {
-	AsmCode * asmcode = new AsmCode(N_Regs);
-	asmcode->insnTemplateLen = insnTemplate->offset;
-	asmcode->insnTemplate = (char*) insnTemplate->extractData();
-	stmt->asmcode = (code*) asmcode;
-    }
+            if ( operand->segmentPrefix != Reg_Invalid )
+            {
+                if ( operand->reg != Reg_Invalid )
+                {
+                    invalidExpression();
+                    return Opr_Invalid;
+                }
 
-    // note: doesn't update AsmOp op
-    bool matchOperands(unsigned nOperands) {
-	bool wrong_number = true;
+                return Opr_Mem;
+            }
+
+            if ( operand->reg != Reg_Invalid && ! operand->hasNumber )
+                return Opr_Reg;
 
-	for (unsigned i = 0; i < nOperands; i++)
-	    classifyOperand(& operands[i]);
-	
-	while (1) {
-	    if (nOperands == opInfo->nOperands()) {
-		wrong_number = false;
-		/*  Cases in which number of operands is not
-		    enough for a match: Op_FCmp/Op_FCmp1,
-		    Op_FCmpP/Op_FCmpP1 */
-		for (unsigned i = 0; i < nOperands; i++) {
-		    Operand * operand = & operands[i];
-		    
-		    switch (opInfo->operands[i] & Opr_ClassMask) {
-		    case OprC_Mem: // no FPMem currently
-			if (operand->cls != Opr_Mem)
-			    goto no_match;
-			break;
-		    case OprC_RFP:
-			if (! (operand->reg >= Reg_ST && operand->reg <= Reg_ST7))
-			    goto no_match;
-			break;
-		    default:
-			break;
-		    }
-		}
+            // should check immediate given (operand->hasNumber);
+            //
+            if ( operand->hasNumber || is_localsize )
+            {
+                // size determination not correct if there are symbols Opr_Immediate
+                if ( operand->dataSize == Default_Ptr )
+                {
+                    if ( operand->constDisplacement < 0x100 )
+                        operand->dataSize = Byte_Ptr;
+                    else if ( operand->constDisplacement < 0x10000 )
+                        operand->dataSize = Short_Ptr;
+                    else
+                        operand->dataSize = Int_Ptr;
+                }
+                return Opr_Immediate;
+            }
+
+            // probably a bug,?
+            stmt->error ( "invalid operand" );
+            return Opr_Invalid;
+        }
+
+        void writeReg ( Reg reg )
+        {
+            insnTemplate->writestring ( ( char* ) "%" );
+            insnTemplate->write ( regInfo[reg].gccName.c_str(), regInfo[reg].gccName.length() );
+        }
+
+        bool opTakesLabel()
+        {
+            switch ( op )
+            {
+                case Op_Branch:
+                case Op_CBranch:
+                case Op_Loop:
+                    return true;
+                default:
+                    return false;
+            }
+        }
 
-		return true;
-	    }
-	    no_match:
-	    if (opInfo->linkType == Next_Form)
-		opInfo = & asmOpInfo[ op = (AsmOp) opInfo->link ];
-	    else
-		break;
-	}
-	if (wrong_number)
-	    stmt->error("wrong number of operands");
-	else
-	    stmt->error("wrong operand types");
-	return false;
-    }
-
-    void addOperand(const char * fmt, AsmArgType type, Expression * e, AsmCode * asmcode, AsmArgMode mode = Mode_Input) {
-        if (sc->func->naked)
+        bool getTypeChar ( TypeNeeded needed, PtrType ptrtype, char & type_char )
         {
-            switch(type)
+            switch ( needed )
             {
-            case Arg_Integer:
-                if (e->type->isunsigned())
-                    insnTemplate->printf("$%llu", e->toUInteger());
-                else
-                    insnTemplate->printf("$%lld", e->toInteger());
-                break;
+                case Byte_NoType:
+                    return ptrtype == Byte_Ptr;
+                case Word_Types:
+                    if ( ptrtype == Byte_Ptr )
+                        return false;
+                    // drop through
+                case Int_Types:
+                    switch ( ptrtype )
+                    {
+                        case Byte_Ptr:  type_char = 'b'; break;
+                        case Short_Ptr: type_char = 'w'; break;
+                        case Int_Ptr:   type_char = 'l'; break;
+                        default:
+                            // %% these may be too strict
+                            return false;
+                    }
+                    break;
+                case FPInt_Types:
+                    switch ( ptrtype )
+                    {
+                        case Short_Ptr: type_char = 0;   break;
+                        case Int_Ptr:   type_char = 'l'; break;
+                        case QWord_Ptr: type_char = 'q'; break;
+                        default:
+                            return false;
+                    }
+                    break;
+                case FP_Types:
+                    switch ( ptrtype )
+                    {
+                        case Float_Ptr:    type_char = 's'; break;
+                        case Double_Ptr:   type_char = 'l'; break;
+                        case Extended_Ptr: type_char = 't'; break;
+                        default:
+                            return false;
+                    }
+                    break;
+                default:
+                    return false;
+            }
+            return true;
+        }
 
-            case Arg_Pointer:
-                stmt->error("unsupported pointer reference to '%s' in naked asm", e->toChars());
-                break;
+        // also set impl clobbers
+        bool formatInstruction ( int nOperands, AsmCode * asmcode )
+        {
+            const char *fmt;
+            const char *mnemonic;
+            char type_char = 0;
+            bool use_star;
+            AsmArgMode mode;
 
-            case Arg_Memory:
-                if (e->op == TOKvar)
+            insnTemplate = new OutBuffer;
+            // %% todo: special case for something..
+            if ( opInfo->linkType == Out_Mnemonic )
+                mnemonic = alternateMnemonics[opInfo->link];
+            else
+                mnemonic = opIdent->string;
+
+            if ( opInfo->needsType )
+            {
+                PtrType exact_type = Default_Ptr;
+                PtrType min_type = Default_Ptr;
+                PtrType hint_type = Default_Ptr;
+
+                /* Default types: This attempts to match the observed behavior of DMD */
+                switch ( opInfo->needsType )
                 {
-                    VarExp* v = (VarExp*)e;
-                    if (VarDeclaration* vd = v->var->isVarDeclaration())
+                    case Int_Types:   min_type = Byte_Ptr; break;
+                    case Word_Types:  min_type = Short_Ptr; break;
+                    case FPInt_Types:
+                        if ( op == Op_Fis_ST ) // integer math instructions
+                            min_type = Int_Ptr;
+                        else // compare, load, store
+                            min_type = Short_Ptr;
+                        break;
+                    case FP_Types:    min_type = Float_Ptr; break;
+                }
+                if ( op == Op_push && operands[0].cls == Opr_Immediate )
+                    min_type = Int_Ptr;
+
+                for ( int i = 0; i < nOperands; i++ )
+                {
+                    if ( hint_type == Default_Ptr &&
+                            ! ( opInfo->operands[i] & Opr_NoType ) )
+                        hint_type = operands[i].dataSizeHint;
+
+                    if ( ( opInfo->operands[i] & Opr_NoType ) ||
+                            operands[i].dataSize == Default_Ptr )
+                        continue;
+                    if ( operands[i].cls == Opr_Immediate )
                     {
-                        if (!vd->isDataseg())
-                        {
-                            stmt->error("only global variables can be referenced by identifier in naked asm");
-                            break;
-                        }
-
-                        // osx needs an extra underscore
-                        if (global.params.os == OSMacOSX)
-                            insnTemplate->writestring("_");
-
-                        // print out the mangle
-                        insnTemplate->writestring(vd->mangle());
-                        vd->nakedUse = true;
+                        min_type = operands[i].dataSize > min_type ?
+                                   operands[i].dataSize : min_type;
+                    }
+                    else
+                    {
+                        exact_type = operands[i].dataSize; // could check for conflicting types
                         break;
                     }
                 }
-                stmt->error("unsupported memory reference to '%s' in naked asm", e->toChars());
+
+                bool type_ok;
+                if ( exact_type == Default_Ptr )
+                {
+                    type_ok = getTypeChar ( ( TypeNeeded ) opInfo->needsType, hint_type, type_char );
+                    if ( ! type_ok )
+                        type_ok = getTypeChar ( ( TypeNeeded ) opInfo->needsType, min_type, type_char );
+                }
+                else
+                    type_ok = getTypeChar ( ( TypeNeeded ) opInfo->needsType, exact_type, type_char );
+
+                if ( ! type_ok )
+                {
+                    stmt->error ( "invalid operand size" );
+                    return false;
+                }
+            }
+            else if ( op == Op_Branch )
+            {
+                if ( operands[0].dataSize == Far_Ptr ) // %% type=Far_Ptr not set by Seg:Ofss OTOH, we don't support that..
+                    insnTemplate->writebyte ( 'l' );
+            }
+            else if ( op == Op_fxch )
+            {
+                // gas won't accept the two-operand form
+                if ( operands[1].cls == Opr_Reg && operands[1].reg == Reg_ST )
+                {
+                    nOperands = 1;
+                }
+                else
+                {
+                    stmt->error ( "invalid operands" );
+                    return false;
+                }
+            }
+
+            switch ( op )
+            {
+                case Op_SizedStack:
+                {
+                    int mlen = strlen ( mnemonic );
+                    if ( mnemonic[mlen-1] == 'd' )
+                        insnTemplate->write ( mnemonic, mlen-1 );
+                    else
+                    {
+                        insnTemplate->writestring ( ( char* ) mnemonic );
+                        insnTemplate->writebyte ( 'w' );
+                    }
+                }
+                break;
+                case Op_cmpsd:
+                case Op_insX:
+                case Op_lodsX:
+                case Op_movsd:
+                case Op_outsX:
+                case Op_scasX:
+                case Op_stosX:
+                {
+                    int mlen = strlen ( mnemonic );
+                    if ( mnemonic[mlen-1] == 'd' )
+                    {
+                        insnTemplate->write ( mnemonic, mlen-1 );
+                        insnTemplate->writebyte ( 'l' );
+                    }
+                    else
+                    {
+                        insnTemplate->writestring ( ( char* ) mnemonic );
+                    }
+                }
+                break;
+                case Op_movsx:
+                case Op_movzx:
+                {
+                    char tc_1;
+                    int mlen = strlen ( mnemonic );
+                    PtrType op1_size = operands[1].dataSize;
+                    if ( op1_size == Default_Ptr )
+                        op1_size = operands[1].dataSizeHint;
+                    // Need type char for source arg
+                    switch ( op1_size )
+                    {
+                        case Byte_Ptr:
+                        case Default_Ptr:
+                            tc_1 = 'b';
+                            break;
+                        case Short_Ptr:
+                            tc_1 = 'w';
+                            break;
+                        default:
+                            stmt->error ( "invalid operand size/type" );
+                            return false;
+                    }
+                    assert ( type_char != 0 );
+                    insnTemplate->write ( mnemonic, mlen-1 );
+                    insnTemplate->writebyte ( tc_1 );
+                    insnTemplate->writebyte ( type_char );
+                }
                 break;
+                default:
+                    insnTemplate->writestring ( ( char* ) mnemonic );
+                    if ( type_char )
+                        insnTemplate->writebyte ( type_char );
+                    break;
+            }
+
+            switch ( opInfo->implicitClobbers & Clb_DXAX_Mask )
+            {
+                case Clb_SizeAX:
+                case Clb_EAX:
+                    asmcode->regs[Reg_EAX] = true;
+                    break;
+                case Clb_SizeDXAX:
+                    asmcode->regs[Reg_EAX] = true;
+                    if ( type_char != 'b' )
+                        asmcode->regs[Reg_EDX] = true;
+                    break;
+                default:
+                    // nothing
+                    break;
+            }
+
+            if ( opInfo->implicitClobbers & Clb_DI )
+                asmcode->regs[Reg_EDI] = true;
+            if ( opInfo->implicitClobbers & Clb_SI )
+                asmcode->regs[Reg_ESI] = true;
+            if ( opInfo->implicitClobbers & Clb_CX )
+                asmcode->regs[Reg_ECX] = true;
+            if ( opInfo->implicitClobbers & Clb_SP )
+                asmcode->regs[Reg_ESP] = true;
+            if ( opInfo->implicitClobbers & Clb_ST )
+            {
+                /* Can't figure out how to tell GCC that an
+                   asm statement leaves an arg pushed on the stack.
+                   Maybe if the statment had and input or output
+                   operand it would work...  In any case, clobbering
+                   all FP prevents incorrect code generation. */
+                asmcode->regs[Reg_ST] = true;
+                asmcode->regs[Reg_ST1] = true;
+                asmcode->regs[Reg_ST2] = true;
+                asmcode->regs[Reg_ST3] = true;
+                asmcode->regs[Reg_ST4] = true;
+                asmcode->regs[Reg_ST5] = true;
+                asmcode->regs[Reg_ST6] = true;
+                asmcode->regs[Reg_ST7] = true;
+            }
+            if ( opInfo->implicitClobbers & Clb_Flags )
+                asmcode->regs[Reg_EFLAGS] = true;
+            if ( op == Op_cpuid )
+            {
+                asmcode->regs[Reg_EAX] = true;
+                asmcode->regs[Reg_ECX] = true;
+                asmcode->regs[Reg_EDX] = true;
+            }
+
+            insnTemplate->writebyte ( ' ' );
+            for ( int i__ = 0; i__ < nOperands; i__++ )
+            {
+                int i;
+                if ( i__ != 0 )
+                    insnTemplate->writestring ( ( char* ) ", " );
+
+                fmt = "$";
+
+                switch ( op )
+                {
+                    case Op_mul:
+                        // gas won't accept the two-operand form; skip to the source operand
+                        i__ = 1;
+                        // drop through
+                    case Op_bound:
+                    case Op_enter:
+                        i = i__;
+                        break;
+                    default:
+                        i = nOperands - 1 - i__; // operand = & operands[ nOperands - 1 - i ];
+                        break;
+                }
+                operand = & operands[ i ];
+
+                switch ( operand->cls )
+                {
+                    case Opr_Immediate:
+                        // for implementing offset:
+                        // $var + $7 // fails
+                        // $var + 7  // ok
+                        // $7 + $var // ok
+
+                        // DMD doesn't seem to allow this
+                        /*
+                        if (opInfo->takesLabel())  tho... (near ptr <Number> would be abs?)
+                            fmt = "$a"; // GAS won't accept "jmp $42"; must be "jmp 42" (rel) or "jmp *42" (abs)
+                        */
+                        if ( opTakesLabel() /*opInfo->takesLabel()*/ )
+                        {
+                            // "relative addressing not allowed in branch instructions" ..
+                            stmt->error ( "integer constant not allowed in branch instructions" );
+                            return false;
+                        }
+
+                        if ( operand->symbolDisplacement.dim &&
+                                isLocalSize ( ( Expression * ) operand->symbolDisplacement.data[0] ) )
+                        {
+                            // handle __LOCAL_SIZE, which in this constant, is an immediate
+                            // should do this in slotexp..
+                            addOperand ( "$", Arg_LocalSize,
+                                         ( Expression * ) operand->symbolDisplacement.data[0], asmcode );
+                            if ( operand->constDisplacement )
+                                insnTemplate->writebyte ( '+' );
+                            else
+                                break;
+                        }
+
+                        if ( operand->symbolDisplacement.dim )
+                        {
+                            fmt = "$a";
+                            addOperand ( "$", Arg_Pointer,
+                                         ( Expression * ) operand->symbolDisplacement.data[0],
+                                         asmcode );
+
+                            if ( operand->constDisplacement )
+                                insnTemplate->writebyte ( '+' );
+                            else
+                                // skip the addOperand(fmt, Arg_Integer...) below
+                                break;
+                        }
+                        addOperand ( fmt, Arg_Integer, newIntExp ( operand->constDisplacement ), asmcode );
+                        break;
+                    case Opr_Reg:
+                        if ( opInfo->operands[i] & Opr_Dest )
+                        {
+                            Reg clbr_reg = ( Reg ) regInfo[operand->reg].baseReg;
+                            if ( clbr_reg != Reg_Invalid )
+                            {
+                                asmcode->regs[clbr_reg] = true;
+                            }
+                        }
+                        if ( opTakesLabel() /*opInfo->takesLabel()*/ )
+                            insnTemplate->writebyte ( '*' );
+                        writeReg ( operand->reg );
+                        /*
+                        insnTemplate->writestring("%");
+                        insnTemplate->writestring(regInfo[operand->reg].name);
+                        */
+                        break;
+                    case Opr_Mem:
+                        // better: use output operands for simple variable references
+                        if ( ( opInfo->operands[i] & Opr_Update ) == Opr_Update )
+                        {
+                            mode = Mode_Update;
+                        }
+                        else if ( opInfo->operands[i] & Opr_Dest )
+                        {
+                            mode = Mode_Output;
+                        }
+                        else
+                        {
+                            mode = Mode_Input;
+                        }
+
+                        use_star = opTakesLabel();//opInfo->takesLabel();
+                        if ( operand->segmentPrefix != Reg_Invalid )
+                        {
+                            writeReg ( operand->segmentPrefix );
+                            insnTemplate->writebyte ( ':' );
+                        }
+                        if ( operand->symbolDisplacement.dim )
+                        {
+                            Expression * e = ( Expression * ) operand->symbolDisplacement.data[0];
+                            Declaration * decl = 0;
+
+                            if ( e->op == TOKvar )
+                                decl = ( ( VarExp * ) e )->var;
+
+                            if ( operand->baseReg != Reg_Invalid &&
+                                    decl && ! decl->isDataseg() )
+                            {
+
+                                // Use the offset from frame pointer
 
-            default:
-                assert(0 && "asm unsupported arg");
-                break;
+                                /* GCC doesn't give the front end access to stack offsets
+                                   when optimization is turned on (3.x) or at all (4.x).
+                                   
+                                   Try to convert var[EBP] (or var[ESP] for naked funcs) to
+                                   a memory expression that does not require us to know
+                                   the stack offset.
+                                */
+
+                                if ( operand->indexReg == Reg_Invalid &&
+                                        decl->isVarDeclaration() &&
+                                        ( ( operand->baseReg == Reg_EBP && ! sc->func->naked ) ||
+                                          ( operand->baseReg == Reg_ESP && sc->func->naked ) ) )
+                                {
+
+                                    if ( mode == Mode_Output )
+                                    {
+                                        e = new AddrExp ( 0, e );
+                                        e->type = decl->type->pointerTo();
+                                    }
+
+#if !IN_LLVM
+                                    /* DMD uses the same frame offsets for naked functions. */
+                                    if ( sc->func->naked )
+                                        operand->constDisplacement += 4;
+
+                                    if ( operand->constDisplacement )
+                                    {
+                                        e = new AddExp ( 0, e,
+                                                         new IntegerExp ( 0, operand->constDisplacement,
+                                                                          Type::tint32 ) );
+                                        e->type = decl->type->pointerTo();
+                                    }
+                                    e = new PtrExp ( 0, e );
+                                    e->type = decl->type;
+#endif
+                                    operand->constDisplacement = 0;
+                                    operand->baseReg = Reg_Invalid;
+
+                                    addOperand ( fmt, Arg_Memory, e, asmcode, mode );
+
+                                }
+                                else
+                                {
+                                    // FIXME: what is this ?
+                                    addOperand2 ( "${",":a}", Arg_FrameRelative, e, asmcode );
+                                }
+                                if ( opInfo->operands[i] & Opr_Dest )
+                                    asmcode->clobbersMemory = 1;
+                            }
+                            else
+                            {
+                                // Plain memory reference to variable
+
+                                /* If in a reg, DMD moves to memory.. even with -O, so we'll do the same
+                                   by always using the "m" contraint.
+
+                                   In order to get the correct output for function and label symbols,
+                                   the %an format must be used with the "p" constraint.
+                                */
+                                if ( isDollar ( e ) )
+                                {
+                                    error ( "dollar labels are not supported", stmt->loc.toChars() );
+                                    asmcode->dollarLabel = 1;
+                                }
+                                else if ( e->op == TOKdsymbol )
+                                {
+                                    LabelDsymbol * lbl = ( LabelDsymbol * ) ( ( DsymbolExp * ) e )->s;
+                                    stmt->isBranchToLabel = lbl->ident;
+
+                                    use_star = false;
+                                    addLabel ( lbl->ident->toChars() );
+                                }
+                                else if ( ( decl && decl->isCodeseg() ) )   // if function or label
+                                {
+                                    use_star = false;
+                                    // simply write out the mangle
+                                    // on osx, prepend extra _
+                                    if ( global.params.os == OSMacOSX )
+                                        insnTemplate->writestring ( "_" );
+                                    insnTemplate->writestring ( decl->mangle() );
+//              addOperand2("${", ":c}", Arg_Pointer, e, asmcode);
+                                }
+                                else
+                                {
+                                    if ( use_star )
+                                    {
+                                        insnTemplate->writebyte ( '*' );
+                                        use_star = false;
+                                    }
+
+                                    if ( !sc->func->naked ) // no addrexp in naked asm please :)
+                                    {
+                                        Type* tt = e->type->pointerTo();
+                                        e = new AddrExp ( 0, e );
+                                        e->type = tt;
+                                    }
+
+                                    addOperand ( fmt, Arg_Memory, e, asmcode, mode );
+                                }
+                            }
+                        }
+                        if ( use_star )
+                            insnTemplate->writebyte ( '*' );
+                        if ( operand->segmentPrefix != Reg_Invalid || operand->constDisplacement )
+                        {
+                            if ( operand->symbolDisplacement.dim )
+                                insnTemplate->writebyte ( '+' );
+                            //addOperand(fmt, Arg_Integer, newIntExp(operand->constDisplacement), asmcode);
+                            insnTemplate->printf ( "%d", operand->constDisplacement );
+                            if ( opInfo->operands[i] & Opr_Dest )
+                                asmcode->clobbersMemory = 1;
+                        }
+                        if ( operand->baseReg != Reg_Invalid || operand->indexReg != Reg_Invalid )
+                        {
+                            insnTemplate->writebyte ( '(' );
+                            if ( operand->baseReg != Reg_Invalid )
+                                writeReg ( operand->baseReg );
+                            if ( operand->indexReg != Reg_Invalid )
+                            {
+                                insnTemplate->writebyte ( ',' );
+                                writeReg ( operand->indexReg );
+                                if ( operand->scale )
+                                {
+                                    insnTemplate->printf ( ",%d", operand->scale );
+                                }
+                            }
+                            insnTemplate->writebyte ( ')' );
+                            if ( opInfo->operands[i] & Opr_Dest )
+                                asmcode->clobbersMemory = 1;
+                        }
+                        break;
+                    case Opr_Invalid:
+                        return false;
+                }
+            }
+
+            asmcode->insnTemplateLen = insnTemplate->offset;
+            asmcode->insnTemplate = ( char* ) insnTemplate->extractData();
+            return true;
+        }
+
+        bool isIntExp ( Expression * exp )
+        {
+            if ( exp->op == TOKint64 )
+                return 1;
+            if ( exp->op == TOKvar )
+            {
+                Declaration * v = ( ( VarExp * ) exp )->var;
+                if ( v->isConst() && v->type->isintegral() )
+                    return 1;
+            }
+            return 0;
+        }
+        bool isRegExp ( Expression * exp ) { return exp->op == TOKmod; } // ewww.%%
+        bool isLocalSize ( Expression * exp )
+        {
+            // cleanup: make a static var
+            return exp->op == TOKidentifier && ( ( IdentifierExp * ) exp )->ident == Id::__LOCAL_SIZE;
+        }
+        bool isDollar ( Expression * exp )
+        {
+            return exp->op == TOKidentifier && ( ( IdentifierExp * ) exp )->ident == Id::__dollar;
+        }
+
+        Expression * newRegExp ( int regno )
+        {
+            IntegerExp * e = new IntegerExp ( regno );
+            e->op = TOKmod;
+            return e;
+        }
+
+        Expression * newIntExp ( int v /* %% type */ )
+        {
+            // Only handles 32-bit numbers as this is IA-32.
+            return new IntegerExp ( stmt->loc, v, Type::tint32 );
+        }
+
+        void slotExp ( Expression * exp )
+        {
+            /*
+              if offset, make a note
+
+              if integer, add to immediate
+              if reg:
+                  if not in bracket, set reg (else error)
+                  if in bracket:
+                 if not base, set base
+                 if not index, set index
+                 else, error
+              if symbol:
+                set symbol field
+             */
+
+            bool is_offset = false;
+            if ( exp->op == TOKaddress )
+            {
+                exp = ( ( AddrExp * ) exp )->e1;
+                is_offset = true;
+            }
+
+            if ( isIntExp ( exp ) )
+            {
+                if ( is_offset )
+                    invalidExpression();
+                operand->constDisplacement += exp->toInteger();
+                if ( ! operand->inBracket )
+                    operand->hasNumber = 1;
+            }
+            else if ( isRegExp ( exp ) )
+            {
+                if ( is_offset )
+                    invalidExpression();
+                if ( ! operand->inBracket )
+                {
+                    if ( operand->reg == Reg_Invalid )
+                        operand->reg = ( Reg ) exp->toInteger();
+                    else
+                        stmt->error ( "too many registers in operand (use brackets)" );
+                }
+                else
+                {
+                    if ( operand->baseReg == Reg_Invalid )
+                        operand->baseReg = ( Reg ) exp->toInteger();
+                    else if ( operand->indexReg == Reg_Invalid )
+                    {
+                        operand->indexReg = ( Reg ) exp->toInteger();
+                        operand->scale = 1;
+                    }
+                    else
+                    {
+                        stmt->error ( "too many registers memory operand" );
+                    }
+                }
+            }
+            else if ( exp->op == TOKvar )
+            {
+                VarDeclaration * v = ( ( VarExp * ) exp )->var->isVarDeclaration();
+
+                if ( v && v->storage_class & STCfield )
+                {
+                    operand->constDisplacement += v->offset;
+                    if ( ! operand->inBracket )
+                        operand->hasNumber = 1;
+                }
+                else
+                {
+                    if ( v && v->type->isscalar() )
+                    {
+                        // DMD doesn't check Tcomplex*, and counts Tcomplex32 as Tfloat64
+                        TY ty = v->type->toBasetype()->ty;
+                        operand->dataSizeHint = ty == Tfloat80 || ty == Timaginary80 ?
+                                                Extended_Ptr : ( PtrType ) v->type->size ( 0 );
+                    }
+
+                    if ( ! operand->symbolDisplacement.dim )
+                    {
+                        if ( is_offset && ! operand->inBracket )
+                            operand->isOffset = 1;
+                        operand->symbolDisplacement.push ( exp );
+                    }
+                    else
+                    {
+                        stmt->error ( "too many symbols in operand" );
+                    }
+                }
+            }
+            else if ( exp->op == TOKidentifier || exp->op == TOKdsymbol )
+            {
+                // %% localsize could be treated as a simple constant..
+                // change to addSymbolDisp(e)
+                if ( ! operand->symbolDisplacement.dim )
+                {
+                    operand->symbolDisplacement.push ( exp );
+                }
+                else
+                {
+                    stmt->error ( "too many symbols in operand" );
+                }
+            }
+            else if ( exp == Handled )
+            {
+                // nothing
+            }
+            else
+            {
+                stmt->error ( "invalid operand" );
             }
         }
-        else
+
+        void invalidExpression()
         {
-            insnTemplate->writestring((char*) fmt);
-            insnTemplate->printf("<<%s%d>>", (mode==Mode_Input)?"in":"out", asmcode->args.dim);
-            asmcode->args.push( new AsmArg(type, e, mode) );
+            // %% report operand number
+            stmt->error ( "invalid expression" );
         }
-    }
-    void addOperand2(const char * fmtpre, const char * fmtpost, AsmArgType type, Expression * e, AsmCode * asmcode, AsmArgMode mode = Mode_Input) {
-        assert(!sc->func->naked);
-        insnTemplate->writestring((char*) fmtpre);
-        insnTemplate->printf("<<%s%d>>", (mode==Mode_Input)?"in":"out", asmcode->args.dim);
-        insnTemplate->writestring((char*) fmtpost);
-        asmcode->args.push( new AsmArg(type, e, mode) );
-    }
-
-    void addLabel(char* id) {
-        insnTemplate->writestring(sc->func->mangle());
-        insnTemplate->writestring("_");
-        insnTemplate->writestring(id);
-    }
-
-    /* Determines whether the operand is a register, memory reference
-       or immediate.  Immediate addresses are currently classified as
-       memory.  This function is called before the exact instructions
-       is known and thus, should not use opInfo. */
-    void classifyOperand(Operand * operand) {
-	operand->cls = classifyOperand1(operand);
-    }
-    
-    OperandClass classifyOperand1(Operand * operand) {
-	bool is_localsize = false;
-	bool really_have_symbol = false;
-
-	if (operand->symbolDisplacement.dim) {
-	    is_localsize = isLocalSize( (Expression *) operand->symbolDisplacement.data[0] );
-	    really_have_symbol = ! is_localsize;
-	}
-
-	if (operand->isOffset && ! operand->hasBracket)
-	    return Opr_Immediate;
-	
-	if (operand->hasBracket || really_have_symbol) { // %% redo for 'offset' function
-	    if (operand->reg != Reg_Invalid) {
-		invalidExpression();
-		return Opr_Invalid;
-	    }
-
-	    return Opr_Mem;
-	}
-
-	if (operand->reg != Reg_Invalid && operand->constDisplacement != 0) {
-	    invalidExpression();
-	    return Opr_Invalid;
-	}
-	
-	if (operand->segmentPrefix != Reg_Invalid) {
-	    if (operand->reg != Reg_Invalid) {
-		invalidExpression();
-		return Opr_Invalid;
-	    }
-
-	    return Opr_Mem;
-	}
-
-	if (operand->reg != Reg_Invalid && ! operand->hasNumber)
-	    return Opr_Reg;
-
-	// should check immediate given (operand->hasNumber);
-	//
-	if (operand->hasNumber || is_localsize) {
-	    // size determination not correct if there are symbols Opr_Immediate
-	    if (operand->dataSize == Default_Ptr) {
-		if (operand->constDisplacement < 0x100)
-		    operand->dataSize = Byte_Ptr;
-		else if (operand->constDisplacement < 0x10000)
-		    operand->dataSize = Short_Ptr;
-		else
-		    operand->dataSize = Int_Ptr;
-	    }
-	    return Opr_Immediate;
-	}
-
-	// probably a bug,?
-	stmt->error("invalid operand");
-	return Opr_Invalid;
-    }
-
-    void writeReg(Reg reg) {
-	insnTemplate->writestring((char*) "%");
-	insnTemplate->write(regInfo[reg].gccName.c_str(), regInfo[reg].gccName.length());
-    }
-
-    bool opTakesLabel() {
-	switch(op) {
-	case Op_Branch:
-	case Op_CBranch:
-	case Op_Loop:
-	    return true;
-	default:
-	    return false;
-	}
-    }
 
-    bool getTypeChar(TypeNeeded needed, PtrType ptrtype, char & type_char)
-    {
-	switch (needed) {
-	case Byte_NoType:
-	    return ptrtype == Byte_Ptr;
-	case Word_Types:
-	    if (ptrtype == Byte_Ptr)
-		return false;
-	    // drop through
-	case Int_Types:
-	    switch (ptrtype) {
-	    case Byte_Ptr:  type_char = 'b'; break;
-	    case Short_Ptr: type_char = 'w'; break;
-	    case Int_Ptr:   type_char = 'l'; break;
-	    default:
-		// %% these may be too strict
-		return false;
-	    }
-	    break;
-	case FPInt_Types:
-	    switch (ptrtype) {
-	    case Short_Ptr: type_char = 0;   break;
-	    case Int_Ptr:   type_char = 'l'; break;
-	    case QWord_Ptr: type_char = 'q'; break;
-	    default:
-		return false;
-	    }
-	    break;
-	case FP_Types:
-	    switch (ptrtype) {
-	    case Float_Ptr:    type_char = 's'; break;
-	    case Double_Ptr:   type_char = 'l'; break;
-	    case Extended_Ptr: type_char = 't'; break;
-	    default:
-		return false;
-	    }
-	    break;
-	default:
-	    return false;
-	}
-	return true;
-    }
-
-    // also set impl clobbers
-    bool formatInstruction(int nOperands, AsmCode * asmcode) {
-	const char *fmt;
-	const char *mnemonic;
-	char type_char = 0;
-	bool use_star;
-	AsmArgMode mode;
+        Expression * intOp ( TOK op, Expression * e1, Expression * e2 )
+        {
+            Expression * e;
+            if ( isIntExp ( e1 ) && ( ! e2 || isIntExp ( e2 ) ) )
+            {
+                switch ( op )
+                {
+                    case TOKadd:
+                        if ( e2 )
+                            e = new AddExp ( stmt->loc, e1, e2 );
+                        else
+                            e = e1;
+                        break;
+                    case TOKmin:
+                        if ( e2 )
+                            e = new MinExp ( stmt->loc, e1, e2 );
+                        else
+                            e = new NegExp ( stmt->loc, e1 );
+                        break;
+                    case TOKmul:
+                        e = new MulExp ( stmt->loc, e1, e2 );
+                        break;
+                    case TOKdiv:
+                        e = new DivExp ( stmt->loc, e1, e2 );
+                        break;
+                    case TOKmod:
+                        e = new ModExp ( stmt->loc, e1, e2 );
+                        break;
+                    case TOKshl:
+                        e = new ShlExp ( stmt->loc, e1, e2 );
+                        break;
+                    case TOKshr:
+                        e = new ShrExp ( stmt->loc, e1, e2 );
+                        break;
+                    case TOKushr:
+                        e = new UshrExp ( stmt->loc, e1, e2 );
+                        break;
+                    case TOKnot:
+                        e = new NotExp ( stmt->loc, e1 );
+                        break;
+                    case TOKtilde:
+                        e = new ComExp ( stmt->loc, e1 );
+                        break;
+                    default:
+                        assert ( 0 );
+                }
+                e = e->semantic ( sc );
+                return e->optimize ( WANTvalue | WANTinterpret );
+            }
+            else
+            {
+                stmt->error ( "expected integer operand(s) for '%s'", Token::tochars[op] );
+                return newIntExp ( 0 );
+            }
+        }
 
-	insnTemplate = new OutBuffer;
-	// %% todo: special case for something..
-	if (opInfo->linkType == Out_Mnemonic)
-	    mnemonic = alternateMnemonics[opInfo->link];
-	else
-	    mnemonic = opIdent->string;
-
-	if (opInfo->needsType) {
-	    PtrType exact_type = Default_Ptr;
-	    PtrType min_type = Default_Ptr;
-	    PtrType hint_type = Default_Ptr;
+        void parseOperand()
+        {
+            Expression * exp = parseAsmExp();
+            slotExp ( exp );
+            if ( isRegExp ( exp ) )
+                operand->dataSize = ( PtrType ) regInfo[exp->toInteger() ].size;
+        }
 
-	    /* Default types: This attempts to match the observed behavior of DMD */
-	    switch (opInfo->needsType) {
-	    case Int_Types:   min_type = Byte_Ptr; break;
-	    case Word_Types:  min_type = Short_Ptr; break;
-	    case FPInt_Types:
-		if (op == Op_Fis_ST) // integer math instructions 
-		    min_type = Int_Ptr;
-		else // compare, load, store
-		    min_type = Short_Ptr;
-		break;
-	    case FP_Types:    min_type = Float_Ptr; break;
-	    }
-	    if (op == Op_push && operands[0].cls == Opr_Immediate)
-		min_type = Int_Ptr;
-	    
-	    for (int i = 0; i < nOperands; i++) {
-		if (hint_type == Default_Ptr &&
-		    ! (opInfo->operands[i] & Opr_NoType))
-		    hint_type = operands[i].dataSizeHint;
-		    
-		if ((opInfo->operands[i] & Opr_NoType) ||
-		    operands[i].dataSize == Default_Ptr)
-		    continue;
-		if (operands[i].cls == Opr_Immediate) {
-		    min_type = operands[i].dataSize > min_type ?
-			operands[i].dataSize : min_type;
-		} else {
-		    exact_type = operands[i].dataSize; // could check for conflicting types
-		    break;
-		}
-	    }
+        Expression * parseAsmExp()
+        {
+            return parseShiftExp();
+        }
 
-	    bool type_ok;
-	    if (exact_type == Default_Ptr) {
-		type_ok = getTypeChar((TypeNeeded) opInfo->needsType, hint_type, type_char);
-		if (! type_ok)
-		    type_ok = getTypeChar((TypeNeeded) opInfo->needsType, min_type, type_char);
-	    } else
-		type_ok = getTypeChar((TypeNeeded) opInfo->needsType, exact_type, type_char);
+        Expression * parseShiftExp()
+        {
+            Expression * e1 = parseAddExp();
+            Expression * e2;
 
-	    if (! type_ok) {
-		stmt->error("invalid operand size");
-		return false;
-	    }
-	} else if (op == Op_Branch) {
-	    if (operands[0].dataSize == Far_Ptr) // %% type=Far_Ptr not set by Seg:Ofss OTOH, we don't support that..
-		insnTemplate->writebyte('l');
-	} else if (op == Op_fxch) {
-	    // gas won't accept the two-operand form
-	    if (operands[1].cls == Opr_Reg && operands[1].reg == Reg_ST) {
-		nOperands = 1;
-	    } else {
-		stmt->error("invalid operands");
-		return false;
-	    }
-	}
-	
-	switch (op) {
-	case Op_SizedStack:
-	    {
-		int mlen = strlen(mnemonic);
-		if (mnemonic[mlen-1] == 'd')
-		    insnTemplate->write(mnemonic, mlen-1);
-		else {
-		    insnTemplate->writestring((char*) mnemonic);
-		    insnTemplate->writebyte('w');
-		}
-	    }
-	    break;
-	case Op_cmpsd:
-	case Op_insX:
-	case Op_lodsX:
-	case Op_movsd:
-	case Op_outsX:
-	case Op_scasX:
-	case Op_stosX:
-	    {
-		int mlen = strlen(mnemonic);
-		if (mnemonic[mlen-1] == 'd') {
-		    insnTemplate->write(mnemonic, mlen-1);
-		    insnTemplate->writebyte('l');
-		} else {
-		    insnTemplate->writestring((char*) mnemonic);
-		}
-	    }
-	    break;
-	case Op_movsx:
-	case Op_movzx:
-	    {
-		char tc_1;
-		int mlen = strlen(mnemonic);
-		PtrType op1_size = operands[1].dataSize;
-		if (op1_size == Default_Ptr)
-		    op1_size = operands[1].dataSizeHint;
-		// Need type char for source arg
-		switch (op1_size) {
-		case Byte_Ptr: 
-		case Default_Ptr:
-		    tc_1 = 'b';
-		    break;
-		case Short_Ptr:
-		    tc_1 = 'w';
-		    break;
-		default:
-		    stmt->error("invalid operand size/type");
-		    return false;
-		}
-		assert(type_char != 0);
-		insnTemplate->write(mnemonic, mlen-1);
-		insnTemplate->writebyte(tc_1);
-		insnTemplate->writebyte(type_char);
-	    }
-	    break;
-	default:
-	    insnTemplate->writestring((char*) mnemonic);
-	    if (type_char)
-		insnTemplate->writebyte(type_char);
-	    break;
-	}
+            while ( 1 )
+            {
+                TOK tv = token->value;
+                switch ( tv )
+                {
+                    case TOKshl:
+                    case TOKshr:
+                    case TOKushr:
+                        nextToken();
+                        e2 = parseAddExp();
+                        e1 = intOp ( tv, e1, e2 );
+                        continue;
+                    default:
+                        break;
+                }
+                break;
+            }
+            return e1;
+        }
 
-	switch (opInfo->implicitClobbers & Clb_DXAX_Mask) {
-	case Clb_SizeAX:
-	case Clb_EAX:
-	    asmcode->regs[Reg_EAX] = true;
-	    break;
-	case Clb_SizeDXAX:
-	    asmcode->regs[Reg_EAX] = true;
-	    if (type_char != 'b')
-		asmcode->regs[Reg_EDX] = true;
-	    break;
-	default:
-	    // nothing
-	    break;
-	}
-
-	if (opInfo->implicitClobbers & Clb_DI)
-	    asmcode->regs[Reg_EDI] = true;
-	if (opInfo->implicitClobbers & Clb_SI)
-	    asmcode->regs[Reg_ESI] = true;
-	if (opInfo->implicitClobbers & Clb_CX)
-	    asmcode->regs[Reg_ECX] = true;
-	if (opInfo->implicitClobbers & Clb_SP)
-	    asmcode->regs[Reg_ESP] = true;
-	if (opInfo->implicitClobbers & Clb_ST)
-	{
-	    /* Can't figure out how to tell GCC that an
-	       asm statement leaves an arg pushed on the stack.
-	       Maybe if the statment had and input or output
-	       operand it would work...  In any case, clobbering
-	       all FP prevents incorrect code generation. */
-	    asmcode->regs[Reg_ST] = true;
-	    asmcode->regs[Reg_ST1] = true;
-	    asmcode->regs[Reg_ST2] = true;
-	    asmcode->regs[Reg_ST3] = true;
-	    asmcode->regs[Reg_ST4] = true;
-	    asmcode->regs[Reg_ST5] = true;
-	    asmcode->regs[Reg_ST6] = true;
-	    asmcode->regs[Reg_ST7] = true;
-	}
-	if (opInfo->implicitClobbers & Clb_Flags)
-	    asmcode->regs[Reg_EFLAGS] = true;
-	if (op == Op_cpuid) {
-	    asmcode->regs[Reg_EAX] = true;
-	    asmcode->regs[Reg_ECX] = true;
-	    asmcode->regs[Reg_EDX] = true;
-	}
-
-	insnTemplate->writebyte(' ');
-	for (int i__ = 0; i__ < nOperands; i__++) {
-	    int i;
-	    if (i__ != 0)
-		insnTemplate->writestring((char*) ", ");
-
-	    fmt = "$";
-    
-	    switch (op) {
-	    case Op_mul:
-		// gas won't accept the two-operand form; skip to the source operand
-		i__ = 1;
-		// drop through
-	    case Op_bound:
-	    case Op_enter:
-		i = i__;
-		break;
-	    default:
-		i = nOperands - 1 - i__; // operand = & operands[ nOperands - 1 - i ];
-		break;
-	    }
-	    operand = & operands[ i ];
+        Expression * parseAddExp()
+        {
+            Expression * e1 = parseMultExp();
+            Expression * e2;
 
-	    switch (operand->cls) {
-	    case Opr_Immediate:
-		// for implementing offset:
-		// $var + $7 // fails
-		// $var + 7  // ok
-		// $7 + $var // ok
-
-		// DMD doesn't seem to allow this
-		/*
-		if (opInfo->takesLabel())  tho... (near ptr <Number> would be abs?)
-		    fmt = "$a"; // GAS won't accept "jmp $42"; must be "jmp 42" (rel) or "jmp *42" (abs)
-		*/
-		if (opTakesLabel()/*opInfo->takesLabel()*/) {
-		    // "relative addressing not allowed in branch instructions" ..
-		    stmt->error("integer constant not allowed in branch instructions");
-		    return false;
-		}
-
-		if (operand->symbolDisplacement.dim &&
-		    isLocalSize( (Expression *) operand->symbolDisplacement.data[0] )) {
-		    // handle __LOCAL_SIZE, which in this constant, is an immediate
-		    // should do this in slotexp..
-		    addOperand("$", Arg_LocalSize,
-			(Expression *) operand->symbolDisplacement.data[0], asmcode);
-		    if (operand->constDisplacement)
-			insnTemplate->writebyte('+');
-		    else
-			break;
-		}
-
-		if (operand->symbolDisplacement.dim) {
-		    fmt = "$a";
-		    addOperand("$", Arg_Pointer,
-			(Expression *) operand->symbolDisplacement.data[0],
-			asmcode);
-
-		    if (operand->constDisplacement)
-			insnTemplate->writebyte('+');
-		    else
-			// skip the addOperand(fmt, Arg_Integer...) below
-			break;
-		}
-		addOperand(fmt, Arg_Integer, newIntExp(operand->constDisplacement), asmcode);
-		break;
-	    case Opr_Reg:
-		if (opInfo->operands[i] & Opr_Dest) {
-		    Reg clbr_reg = (Reg) regInfo[operand->reg].baseReg;
-		    if (clbr_reg != Reg_Invalid) {
-			asmcode->regs[clbr_reg] = true;
-		    }
-		}
-		if (opTakesLabel()/*opInfo->takesLabel()*/)
-		    insnTemplate->writebyte('*');
-		writeReg(operand->reg);
-		/*
-		insnTemplate->writestring("%");
-		insnTemplate->writestring(regInfo[operand->reg].name);
-		*/
-		break;
-	    case Opr_Mem:
-		// better: use output operands for simple variable references
-		if ( (opInfo->operands[i] & Opr_Update) == Opr_Update) {
-		    mode = Mode_Update;
-		} else if (opInfo->operands[i] & Opr_Dest) {
-		    mode = Mode_Output;
-		} else {
-		    mode = Mode_Input;
-		}
-		
-		use_star = opTakesLabel();//opInfo->takesLabel();
-		if (operand->segmentPrefix != Reg_Invalid) {
-		    writeReg(operand->segmentPrefix);
-		    insnTemplate->writebyte(':');
-		}
-		if (operand->symbolDisplacement.dim) {
-		    Expression * e = (Expression *) operand->symbolDisplacement.data[0];
-		    Declaration * decl = 0;
+            while ( 1 )
+            {
+                TOK tv = token->value;
+                switch ( tv )
+                {
+                    case TOKadd:
+                        nextToken();
+                        e2 = parseMultExp();
+                        if ( isIntExp ( e1 ) && isIntExp ( e2 ) )
+                            e1 = intOp ( tv, e1, e2 );
+                        else
+                        {
+                            slotExp ( e1 );
+                            slotExp ( e2 );
+                            e1 = Handled;
+                        }
+                        continue;
+                    case TOKmin:
+                        // Note: no support for symbol address difference
+                        nextToken();
+                        e2 = parseMultExp();
+                        if ( isIntExp ( e1 ) && isIntExp ( e2 ) )
+                            e1 = intOp ( tv, e1, e2 );
+                        else
+                        {
+                            slotExp ( e1 );
+                            e2 = intOp ( TOKmin, e2, NULL ); // verifies e2 is an int
+                            slotExp ( e2 );
+                            e1 = Handled;
+                        }
+                        continue;
+                    default:
+                        break;
+                }
+                break;
+            }
+            return e1;
+        }
 
-		    if (e->op == TOKvar)
-			decl = ((VarExp *) e)->var;
-
-		    if (operand->baseReg != Reg_Invalid &&
-			decl && ! decl->isDataseg()) {
-
-			// Use the offset from frame pointer
-
-			/* GCC doesn't give the front end access to stack offsets
-			   when optimization is turned on (3.x) or at all (4.x).
-			   
-			   Try to convert var[EBP] (or var[ESP] for naked funcs) to
-			   a memory expression that does not require us to know
-			   the stack offset.
-			*/
-
-			if (operand->indexReg == Reg_Invalid &&
-			    decl->isVarDeclaration() &&
-			    ((operand->baseReg == Reg_EBP && ! sc->func->naked ) ||
-				(operand->baseReg == Reg_ESP && sc->func->naked)) ) {
-
-                if (mode == Mode_Output)
+        bool tryScale ( Expression * e1, Expression * e2 )
+        {
+            Expression * et;
+            if ( isIntExp ( e1 ) && isRegExp ( e2 ) )
+            {
+                et = e1;
+                e1 = e2;
+                e2 = et;
+                goto do_scale;
+            }
+            else if ( isRegExp ( e1 ) && isIntExp ( e2 ) )
+            {
+            do_scale:
+                if ( ! operand->inBracket )
                 {
-                    e = new AddrExp(0, e);
-                    e->type = decl->type->pointerTo();
-                }
-
-#if !IN_LLVM
-			    /* DMD uses the same frame offsets for naked functions. */
-			    if (sc->func->naked)
-				operand->constDisplacement += 4;
-
-			    if (operand->constDisplacement) {
-				e = new AddExp(0, e,
-				    new IntegerExp(0, operand->constDisplacement,
-					Type::tint32));
-				e->type = decl->type->pointerTo();
-			    }
-			    e = new PtrExp(0, e);
-			    e->type = decl->type;
-#endif
-			    operand->constDisplacement = 0;
-			    operand->baseReg = Reg_Invalid;
-
-			    addOperand(fmt, Arg_Memory, e, asmcode, mode);
-			    
-			} else {
-			    addOperand2("${",":a}", Arg_FrameRelative, e, asmcode);
-			}
-			if (opInfo->operands[i] & Opr_Dest)
-			    asmcode->clobbersMemory = 1;
-		    } else  {
-			// Plain memory reference to variable
-			
-			/* If in a reg, DMD moves to memory.. even with -O, so we'll do the same
-			   by always using the "m" contraint.
-
-			   In order to get the correct output for function and label symbols,
-			   the %an format must be used with the "p" constraint.
-			*/
-			if (isDollar(e)) {
-			    error("dollar labels are not supported", stmt->loc.toChars());
-			    asmcode->dollarLabel = 1;
-			} else if (e->op == TOKdsymbol) {
-			    LabelDsymbol * lbl = (LabelDsymbol *) ((DsymbolExp *) e)->s;
-			    stmt->isBranchToLabel = lbl->ident;
-
-			    use_star = false;
-			    addLabel(lbl->ident->toChars());
-			} else if ((decl && decl->isCodeseg())) { // if function or label
-			    use_star = false;
-			    addOperand2("${", ":c}", Arg_Pointer, e, asmcode);
-			} else {
-			    if (use_star) {
-				insnTemplate->writebyte('*');
-				use_star = false;
-			    }
-
-                if (!sc->func->naked) { // no addrexp in naked asm please :)
-                Type* tt = e->type->pointerTo();
-			    e = new AddrExp(0, e);
-			    e->type = tt;
+                    invalidExpression(); // maybe should allow, e.g. DS:EBX+EAX*4
                 }
 
-			    addOperand(fmt, Arg_Memory, e, asmcode, mode);
-			}
-		    }
-		}
-		if (use_star)
-		    insnTemplate->writebyte('*');
-		if (operand->segmentPrefix != Reg_Invalid || operand->constDisplacement) {
-		    if (operand->symbolDisplacement.dim)
-			insnTemplate->writebyte('+');
-		    //addOperand(fmt, Arg_Integer, newIntExp(operand->constDisplacement), asmcode);
-		    insnTemplate->printf("%d", operand->constDisplacement);
-		    if (opInfo->operands[i] & Opr_Dest)
-			asmcode->clobbersMemory = 1;
-		}
-		if (operand->baseReg != Reg_Invalid || operand->indexReg != Reg_Invalid) {
-		    insnTemplate->writebyte('(');
-		    if (operand->baseReg != Reg_Invalid)
-			writeReg(operand->baseReg);
-		    if (operand->indexReg != Reg_Invalid) {
-			insnTemplate->writebyte(',');
-			writeReg(operand->indexReg);
-			if (operand->scale) {
-			    insnTemplate->printf(",%d", operand->scale);
-			}
-		    }
-		    insnTemplate->writebyte(')');
-		    if (opInfo->operands[i] & Opr_Dest)
-			asmcode->clobbersMemory = 1;
-		}
-		break;
-	    case Opr_Invalid:
-		return false;
-	    }
-	}
+                if ( operand->scale || operand->indexReg != Reg_Invalid )
+                {
+                    invalidExpression();
+                    return true;
+                }
 
-	asmcode->insnTemplateLen = insnTemplate->offset;
-	asmcode->insnTemplate = (char*) insnTemplate->extractData();
-	return true;
-    }
+                operand->indexReg = ( Reg ) e1->toInteger();
+                operand->scale = e2->toInteger();
+                switch ( operand->scale )
+                {
+                    case 1:
+                    case 2:
+                    case 4:
+                    case 8:
+                        // ok; do nothing
+                        break;
+                    default:
+                        stmt->error ( "invalid index register scale '%d'", operand->scale );
+                        return true;
+                }
 
-    bool isIntExp(Expression * exp) {
-	if (exp->op == TOKint64)
-	    return 1;
-	if (exp->op == TOKvar) {
-	    Declaration * v = ((VarExp *) exp)->var;
-	    if (v->isConst() && v->type->isintegral())
-		return 1;
-	}
-	return 0;
-    }
-    bool isRegExp(Expression * exp) { return exp->op == TOKmod; } // ewww.%%
-    bool isLocalSize(Expression * exp) {
-	// cleanup: make a static var
-	return exp->op == TOKidentifier && ((IdentifierExp *) exp)->ident == Id::__LOCAL_SIZE;
-    }
-    bool isDollar(Expression * exp) {
-	return exp->op == TOKidentifier && ((IdentifierExp *) exp)->ident == Id::__dollar;
-    }
+                return true;
+            }
+            return false;
+        }
 
-    Expression * newRegExp(int regno) {
-	IntegerExp * e = new IntegerExp(regno);
-	e->op = TOKmod;
-	return e;
-    }
-
-    Expression * newIntExp(int v /* %% type */) {
-	// Only handles 32-bit numbers as this is IA-32.
-	return new IntegerExp(stmt->loc, v, Type::tint32);
-    }
+        Expression * parseMultExp()
+        {
+            Expression * e1 = parseBrExp();
+            Expression * e2;
 
-    void slotExp(Expression * exp) {
-	/*
-	  if offset, make a note
-	
-	  if integer, add to immediate
-	  if reg:
-	      if not in bracket, set reg (else error)
-	      if in bracket:
-		 if not base, set base
-		 if not index, set index
-		 else, error
-	  if symbol:
-	    set symbol field
-	 */
+            while ( 1 )
+            {
+                TOK tv = token->value;
+                switch ( tv )
+                {
+                    case TOKmul:
+                        nextToken();
+                        e2 = parseMultExp();
+                        if ( isIntExp ( e1 ) && isIntExp ( e2 ) )
+                            e1 = intOp ( tv, e1, e2 );
+                        else if ( tryScale ( e1,e2 ) )
+                            e1 = Handled;
+                        else
+                            invalidExpression();
+                        continue;
+                    case TOKdiv:
+                    case TOKmod:
+                        nextToken();
+                        e2 = parseMultExp();
+                        e1 = intOp ( tv, e1, e2 );
+                        continue;
+                    default:
+                        break;
+                }
+                break;
+            }
+            return e1;
+        }
 
-	bool is_offset = false;
-	if (exp->op == TOKaddress) {
-	    exp = ((AddrExp *) exp)->e1;
-	    is_offset = true;
-	}
-	
-	if (isIntExp(exp)) {
-	    if (is_offset)
-		invalidExpression();
-	    operand->constDisplacement += exp->toInteger();
-	    if (! operand->inBracket)
-		operand->hasNumber = 1;
-	} else if (isRegExp(exp)) {
-	    if (is_offset)
-		invalidExpression();
-	    if (! operand->inBracket) {
-		if (operand->reg == Reg_Invalid)
-		    operand->reg = (Reg) exp->toInteger();
-		else
-		    stmt->error("too many registers in operand (use brackets)");
-	    } else {
-		if (operand->baseReg == Reg_Invalid)
-		    operand->baseReg = (Reg) exp->toInteger();
-		else if (operand->indexReg == Reg_Invalid) {
-		    operand->indexReg = (Reg) exp->toInteger();
-		    operand->scale = 1;
-		} else {
-		    stmt->error("too many registers memory operand");
-		}
-	    }
-	} else if (exp->op == TOKvar) {
-	    VarDeclaration * v = ((VarExp *) exp)->var->isVarDeclaration();
+        Expression * parseBrExp()
+        {
+            // %% check (why is bracket lower precends..)
+            // 3+4[eax] -> 3 + (4 [EAX]) ..
+
+            // only one bracked allowed, so this doesn't quite handle
+            // the spec'd syntax
+            Expression * e;
+
+            if ( token->value == TOKlbracket )
+                e = Handled;
+            else
+                e = parseUnaExp();
 
-	    if (v && v->storage_class & STCfield) {
-		operand->constDisplacement += v->offset;
-		if (! operand->inBracket)
-		    operand->hasNumber = 1;
-	    } else {
-		if (v && v->type->isscalar())
-		{
-		    // DMD doesn't check Tcomplex*, and counts Tcomplex32 as Tfloat64
-		    TY ty = v->type->toBasetype()->ty;
-		    operand->dataSizeHint = ty == Tfloat80 || ty == Timaginary80 ?
-			Extended_Ptr : (PtrType) v->type->size(0);
-		}
-		
-		if (! operand->symbolDisplacement.dim) {
-		    if (is_offset && ! operand->inBracket)
-			operand->isOffset = 1;
-		    operand->symbolDisplacement.push( exp );
-		} else {
-		    stmt->error("too many symbols in operand");
-		}
-	    }
-	} else if (exp->op == TOKidentifier || exp->op == TOKdsymbol) {
-	    // %% localsize could be treated as a simple constant..
-	    // change to addSymbolDisp(e)
-	    if (! operand->symbolDisplacement.dim) {
-		operand->symbolDisplacement.push( exp );
-	    } else {
-		stmt->error("too many symbols in operand");
-	    }
-	} else if (exp == Handled) {
-	    // nothing
-	} else {
-	    stmt->error("invalid operand");
-	}
-    }
+            // DMD allows multiple bracket expressions.
+            while ( token->value == TOKlbracket )
+            {
+                nextToken();
+
+                operand->inBracket = operand->hasBracket = 1;
+                slotExp ( parseAsmExp() );
+                operand->inBracket = 0;
 
-    void invalidExpression() {
-	// %% report operand number
-	stmt->error("invalid expression");
-    }
+                if ( token->value == TOKrbracket )
+                    nextToken();
+                else
+                    stmt->error ( "missing ']'" );
+            }
+
+            return e;
+        }
 
-    Expression * intOp(TOK op, Expression * e1, Expression * e2) {
-	Expression * e;
-	if (isIntExp(e1) && (! e2 || isIntExp(e2))) {
-	    switch (op) {
-	    case TOKadd:
-		if (e2)
-		    e = new AddExp(stmt->loc, e1, e2);
-		else
-		    e = e1;
-		break;
-	    case TOKmin:
-		if (e2)
-		    e = new MinExp(stmt->loc, e1, e2);
-		else
-		    e = new NegExp(stmt->loc, e1);
-		break;
-	    case TOKmul:
-		e = new MulExp(stmt->loc, e1, e2);
-		break;
-	    case TOKdiv:
-		e = new DivExp(stmt->loc, e1, e2);
-		break;
-	    case TOKmod:
-		e = new ModExp(stmt->loc, e1, e2);
-		break;
-	    case TOKshl:
-		e = new ShlExp(stmt->loc, e1, e2);
-		break;
-	    case TOKshr:
-		e = new ShrExp(stmt->loc, e1, e2);
-		break;
-	    case TOKushr:
-		e = new UshrExp(stmt->loc, e1, e2);
-		break;
-	    case TOKnot:
-		e = new NotExp(stmt->loc, e1);
-		break;
-	    case TOKtilde:
-		e = new ComExp(stmt->loc, e1);
-		break;
-	    default:
-		assert(0);
-	    }
-	    e = e->semantic(sc);
-	    return e->optimize(WANTvalue | WANTinterpret);
-	} else {
-	    stmt->error("expected integer operand(s) for '%s'", Token::tochars[op]);
-	    return newIntExp(0);
-	}
-    }
+        PtrType isPtrType ( Token * tok )
+        {
+            switch ( tok->value )
+            {
+                case TOKint8: return Byte_Ptr;
+                case TOKint16: return Short_Ptr;
+                case TOKint32: return Int_Ptr;
+                    // 'long ptr' isn't accepted?
+                case TOKfloat32: return Float_Ptr;
+                case TOKfloat64: return Double_Ptr;
+                case TOKfloat80: return Extended_Ptr;
+                case TOKidentifier:
+                    for ( int i = 0; i < N_PtrNames; i++ )
+                        if ( tok->ident == ptrTypeIdentTable[i] )
+                            return ptrTypeValueTable[i];
+                    break;
+                default:
+                    break;
+            }
+            return Default_Ptr;
+        }
 
-    void parseOperand() {
-	Expression * exp = parseAsmExp();
-	slotExp(exp);
-	if (isRegExp(exp))
-	    operand->dataSize = (PtrType) regInfo[exp->toInteger()].size;
-    }
+        Expression * parseUnaExp()
+        {
+            Expression * e = NULL;
+            PtrType ptr_type;
 
-    Expression * parseAsmExp() {
-	return parseShiftExp();
-    }
-
-    Expression * parseShiftExp() {
-	Expression * e1 = parseAddExp();
-	Expression * e2;
+            // First, check for type prefix.
+            if ( token->value != TOKeof &&
+                    peekToken()->value == TOKidentifier &&
+                    peekToken()->ident == Id::ptr )
+            {
 
-	while (1) {
-	    TOK tv = token->value;
-	    switch (tv) {
-	    case TOKshl:
-	    case TOKshr:
-	    case TOKushr:
-		nextToken();
-		e2 = parseAddExp();
-		e1 = intOp(tv, e1, e2);
-		continue;
-	    default:
-		break;
-	    }
-	    break;
-	}
-	return e1;
-    }
-
-    Expression * parseAddExp() {
-	Expression * e1 = parseMultExp();
-	Expression * e2;
+                ptr_type = isPtrType ( token );
+                if ( ptr_type != Default_Ptr )
+                {
+                    if ( operand->dataSize == Default_Ptr )
+                        operand->dataSize = ptr_type;
+                    else
+                        stmt->error ( "multiple specifications of operand size" );
+                }
+                else
+                    stmt->error ( "unknown operand size '%s'", token->toChars() );
+                nextToken();
+                nextToken();
+                return parseAsmExp();
+            }
 
-	while (1) {
-	    TOK tv = token->value;
-	    switch (tv) {
-	    case TOKadd:
-		nextToken();
-		e2 = parseMultExp();
-		if (isIntExp(e1) && isIntExp(e2))
-		    e1 = intOp(tv, e1, e2);
-		else {
-		    slotExp(e1);
-		    slotExp(e2);
-		    e1 = Handled;
-		}
-		continue;
-	    case TOKmin:
-		// Note: no support for symbol address difference
-		nextToken();
-		e2 = parseMultExp();
-		if (isIntExp(e1) && isIntExp(e2))
-		    e1 = intOp(tv, e1, e2);
-		else {
-		    slotExp(e1);
-		    e2 = intOp(TOKmin, e2, NULL); // verifies e2 is an int
-		    slotExp(e2);
-		    e1 = Handled;
-		}
-		continue;
-	    default:
-		break;
-	    }
-	    break;
-	}
-	return e1;
-    }
+            TOK tv = token->value;
+            switch ( tv )
+            {
+                case TOKidentifier:
+                    if ( token->ident == ident_seg )
+                    {
+                        nextToken();
+                        stmt->error ( "'seg' not supported" );
+                        e = parseAsmExp();
+                    }
+                    else if ( token->ident == Id::offset ||
+                              token->ident == Id::offsetof )
+                    {
+                        if ( token->ident == Id::offset && ! global.params.useDeprecated )
+                            stmt->error ( "offset deprecated, use offsetof" );
+                        nextToken();
+                        e = parseAsmExp();
+                        e = new AddrExp ( stmt->loc, e );
+                    }
+                    else
+                    {
+                        // primary exp
+                        break;
+                    }
+                    return e;
+                case TOKadd:
+                case TOKmin:
+                case TOKnot:
+                case TOKtilde:
+                    nextToken();
+                    e = parseUnaExp();
+                    return intOp ( tv, e, NULL );
+                default:
+                    // primary exp
+                    break;
+            }
+            return parsePrimaryExp();
+        }
 
-    bool tryScale(Expression * e1, Expression * e2) {
-	Expression * et;
-	if (isIntExp(e1) && isRegExp(e2)) {
-	    et = e1;
-	    e1 = e2;
-	    e2 = et;
-	    goto do_scale;
-	} else if (isRegExp(e1) && isIntExp(e2)) {
-	do_scale:
-	    if (! operand->inBracket) {
-		invalidExpression(); // maybe should allow, e.g. DS:EBX+EAX*4
-	    }
-	    
-	    if (operand->scale || operand->indexReg != Reg_Invalid) {
-		invalidExpression();
-		return true;
-	    }
+        Expression * parsePrimaryExp()
+        {
+            Expression * e;
+            Identifier * ident = NULL;
 
-	    operand->indexReg = (Reg) e1->toInteger();
-	    operand->scale = e2->toInteger();
-	    switch (operand->scale) {
-	    case 1:
-	    case 2:
-	    case 4:
-	    case 8:
-		// ok; do nothing
-		break;
-	    default:
-		stmt->error("invalid index register scale '%d'", operand->scale);
-		return true;
-	    }
-	    
-	    return true;
-	}
-	return false;
-    }
-
-    Expression * parseMultExp() {
-	Expression * e1 = parseBrExp();
-	Expression * e2;
+            switch ( token->value )
+            {
+                case TOKint32v:
+                case TOKuns32v:
+                case TOKint64v:
+                case TOKuns64v:
+                    // semantic here?
+                    // %% for tok64 really should use 64bit type
+                    e = new IntegerExp ( stmt->loc, token->uns64value, Type::tint32 );
+                    nextToken();
+                    break;
+                case TOKfloat32v:
+                case TOKfloat64v:
+                case TOKfloat80v:
+                    // %% need different types?
+                    e = new RealExp ( stmt->loc, token->float80value, Type::tfloat80 );
+                    nextToken();
+                    break;
+                case TOKidentifier:
+                {
+                    ident = token->ident;
+                    nextToken();
 
-	while (1) {
-	    TOK tv = token->value;
-	    switch (tv) {
-	    case TOKmul:
-		nextToken();
-		e2 = parseMultExp();
-		if (isIntExp(e1) && isIntExp(e2))
-		    e1 = intOp(tv, e1, e2);
-		else if (tryScale(e1,e2))
-		    e1 = Handled;
-		else
-		    invalidExpression();
-		continue;
-	    case TOKdiv:
-	    case TOKmod:
-		nextToken();
-		e2 = parseMultExp();
-		e1 = intOp(tv, e1, e2);
-		continue;
-	    default:
-		break;
-	    }
-	    break;
-	}
-	return e1;
-    }
+                    if ( ident == Id::__LOCAL_SIZE )
+                    {
+                        return new IdentifierExp ( stmt->loc, ident );
+                    }
+                    else if ( ident == Id::__dollar )
+                    {
+                    do_dollar:
+                        return new IdentifierExp ( stmt->loc, ident );
+                    }
+                    else
+                    {
+                        e = new IdentifierExp ( stmt->loc, ident );
+                    }
 
-    Expression * parseBrExp() {
-	// %% check (why is bracket lower precends..)
-	// 3+4[eax] -> 3 + (4 [EAX]) ..
-	
-	// only one bracked allowed, so this doesn't quite handle
-	// the spec'd syntax
-	Expression * e;
-	
-	if (token->value == TOKlbracket)
-	    e = Handled;
-	else
-	    e = parseUnaExp();
-
-	// DMD allows multiple bracket expressions.
-	while (token->value == TOKlbracket) {
-	    nextToken();
-	    
-	    operand->inBracket = operand->hasBracket = 1;
-	    slotExp(parseAsmExp());
-	    operand->inBracket = 0;
-
-	    if (token->value == TOKrbracket)
-		nextToken();
-	    else
-		stmt->error("missing ']'");
-	}
-
-	return e;
-    }
-
-    PtrType isPtrType(Token * tok) {
-	switch (tok->value) {
-	case TOKint8: return Byte_Ptr;
-	case TOKint16: return Short_Ptr;
-	case TOKint32: return Int_Ptr;
-	    // 'long ptr' isn't accepted?
-	case TOKfloat32: return Float_Ptr;
-	case TOKfloat64: return Double_Ptr;
-	case TOKfloat80: return Extended_Ptr;
-	case TOKidentifier:
-	    for (int i = 0; i < N_PtrNames; i++)
-		if (tok->ident == ptrTypeIdentTable[i])
-		    return ptrTypeValueTable[i];
-	    break;
-	default:
-	    break;
-	}
-	return Default_Ptr;
-    }
-
-    Expression * parseUnaExp() {
-	Expression * e = NULL;
-	PtrType ptr_type;
-	
-	// First, check for type prefix.
-	if (token->value != TOKeof &&
-	    peekToken()->value == TOKidentifier &&
-	    peekToken()->ident == Id::ptr) {
-
-	    ptr_type = isPtrType(token);
-	    if (ptr_type != Default_Ptr) {
-		if (operand->dataSize == Default_Ptr)
-		    operand->dataSize = ptr_type;
-		else
-		    stmt->error("multiple specifications of operand size");
-	    } else
-		stmt->error("unknown operand size '%s'", token->toChars());
-	    nextToken();
-	    nextToken();
-	    return parseAsmExp();
-	}
+                    // If this is more than one component ref, it gets complicated: *(&Field + n)
+                    // maybe just do one step at a time..
+                    // simple case is Type.f -> VarDecl(field)
+                    // actually, DMD only supports on level...
+                    // X.y+Y.z[EBX] is supported, tho..
+                    // %% doesn't handle properties (check%%)
+                    while ( token->value == TOKdot )
+                    {
+                        nextToken();
+                        if ( token->value == TOKidentifier )
+                        {
+                            e = new DotIdExp ( stmt->loc, e, token->ident );
+                            nextToken();
+                        }
+                        else
+                        {
+                            stmt->error ( "expected identifier" );
+                            return Handled;
+                        }
+                    }
 
-	TOK tv = token->value;
-	switch (tv) {
-	case TOKidentifier:
-	    if (token->ident == ident_seg) {
-		nextToken();
-		stmt->error("'seg' not supported");
-		e = parseAsmExp();
-	    } else if (token->ident == Id::offset ||
-		       token->ident == Id::offsetof) {
-		if (token->ident == Id::offset && ! global.params.useDeprecated)
-		    stmt->error("offset deprecated, use offsetof");
-		nextToken();
-		e = parseAsmExp();
-		e = new AddrExp(stmt->loc, e);
-	    } else {
-		// primary exp
-		break;
-	    }
-	    return e;
-	case TOKadd:
-	case TOKmin:
-	case TOKnot:
-	case TOKtilde:
-	    nextToken();
-	    e = parseUnaExp();
-	    return intOp(tv, e, NULL);
-	default:
-	    // primary exp
-	    break;
-	}
-	return parsePrimaryExp();
-    }
+                    // check for reg first then dotexp is an error?
+                    if ( e->op == TOKidentifier )
+                    {
+                        for ( int i = 0; i < N_Regs; i++ )
+                        {
+                            if ( ident == regInfo[i].ident )
+                            {
+                                if ( ( Reg ) i == Reg_ST && token->value == TOKlparen )
+                                {
+                                    nextToken();
+                                    switch ( token->value )
+                                    {
+                                    case TOKint32v: case TOKuns32v:
+                                    case TOKint64v: case TOKuns64v:
+                                            if ( token->uns64value < 8 )
+                                                e = newRegExp ( ( Reg ) ( Reg_ST + token->uns64value ) );
+                                            else
+                                            {
+                                                stmt->error ( "invalid floating point register index" );
+                                                e = Handled;
+                                            }
+                                            nextToken();
+                                            if ( token->value == TOKrparen )
+                                                nextToken();
+                                            else
+                                                stmt->error ( "expected ')'" );
+                                            return e;
+                                        default:
+                                            break;
+                                    }
+                                    invalidExpression();
+                                    return Handled;
+                                }
+                                else if ( token->value == TOKcolon )
+                                {
+                                    nextToken();
+                                    if ( operand->segmentPrefix != Reg_Invalid )
+                                        stmt->error ( "too many segment prefixes" );
+                                    else if ( i >= Reg_CS && i <= Reg_GS )
+                                        operand->segmentPrefix = ( Reg ) i;
+                                    else
+                                        stmt->error ( "'%s' is not a segment register", ident->string );
+                                    return parseAsmExp();
+                                }
+                                else
+                                {
+                                    return newRegExp ( ( Reg ) i );
+                                }
+                            }
+                        }
+                    }
 
-    Expression * parsePrimaryExp() {
-	Expression * e;
-	Identifier * ident = NULL;
-	
-	switch (token->value) {
-	case TOKint32v:
-	case TOKuns32v:
-	case TOKint64v:
-	case TOKuns64v:
-	    // semantic here?
-	    // %% for tok64 really should use 64bit type
-	    e = new IntegerExp(stmt->loc, token->uns64value, Type::tint32);
-	    nextToken();
-	    break;
-	case TOKfloat32v:
-	case TOKfloat64v:
-	case TOKfloat80v:
-	    // %% need different types?
-        e = new RealExp(stmt->loc, token->float80value, Type::tfloat80);
-	    nextToken();
-	    break;
-	case TOKidentifier:
-	    {
-		ident = token->ident;
-		nextToken();
-		
-		if (ident == Id::__LOCAL_SIZE) {
-		    return new IdentifierExp(stmt->loc, ident);
-		} else if (ident == Id::__dollar) {
-		do_dollar:
-		    return new IdentifierExp(stmt->loc, ident);
-		} else {
-		    e = new IdentifierExp(stmt->loc, ident);
-		}
+                    if ( opTakesLabel() /*opInfo->takesLabel()*/ && e->op == TOKidentifier )
+                    {
+                        // DMD uses labels secondarily to other symbols, so check
+                        // if IdentifierExp::semantic won't find anything.
+                        Dsymbol *scopesym;
+
+                        if ( ! sc->search ( stmt->loc, ident, & scopesym ) )
+                            return new DsymbolExp ( stmt->loc,
+                                                    sc->func->searchLabel ( ident ) );
+                    }
+
+                    e = e->semantic ( sc );
 
-		// If this is more than one component ref, it gets complicated: *(&Field + n)
-		// maybe just do one step at a time..
-		// simple case is Type.f -> VarDecl(field)
-		// actually, DMD only supports on level...
-		// X.y+Y.z[EBX] is supported, tho..
-		// %% doesn't handle properties (check%%)
-		while (token->value == TOKdot) {
-		    nextToken();
-		    if (token->value == TOKidentifier) {
-			e = new DotIdExp(stmt->loc, e, token->ident);
-			nextToken();
-		    } else {
-			stmt->error("expected identifier");
-			return Handled;
-		    }
-		}
+                    // Special case for floating point constant declarations.
+                    if ( e->op == TOKfloat64 )
+                    {
+                        Dsymbol * sym = sc->search ( stmt->loc, ident, NULL );
+                        if ( sym )
+                        {
+                            VarDeclaration *v = sym->isVarDeclaration();
+                            if ( v )
+                            {
+                                Expression *ve = new VarExp ( stmt->loc, v );
+                                ve->type = e->type;
+                                e = ve;
+                            }
+                        }
+                    }
+                    return e;
+                }
+                break;
+                case TOKdollar:
+                    nextToken();
+                    ident = Id::__dollar;
+                    goto do_dollar;
+                    break;
+                default:
+                    invalidExpression();
+                    return Handled;
+            }
+            return e;
+        }
+
+        void doAlign()
+        {
+            // .align bits vs. bytes...
+            // apparently a.out platforms use bits instead of bytes...
 
-		// check for reg first then dotexp is an error?
-		if (e->op == TOKidentifier) {
-		    for (int i = 0; i < N_Regs; i++) {
-			if (ident == regInfo[i].ident) {
-			    if ( (Reg) i == Reg_ST && token->value == TOKlparen) {
-				nextToken();
-				switch (token->value) {
-				case TOKint32v: case TOKuns32v:
-				case TOKint64v: case TOKuns64v:
-				    if (token->uns64value < 8)
-					e = newRegExp( (Reg) (Reg_ST + token->uns64value) );
-				    else {
-					stmt->error("invalid floating point register index");
-					e = Handled;
-				    }
-				    nextToken();
-				    if (token->value == TOKrparen)
-					nextToken();
-				    else
-					stmt->error("expected ')'");
-				    return e;
-				default:
-				    break;
-				}
-				invalidExpression();
-				return Handled;
-			    } else if (token->value == TOKcolon) {
-				nextToken();
-				if (operand->segmentPrefix != Reg_Invalid)
-				    stmt->error("too many segment prefixes");
-				else if (i >= Reg_CS && i <= Reg_GS)
-				    operand->segmentPrefix = (Reg) i;
-				else
-				    stmt->error("'%s' is not a segment register", ident->string);
-				return parseAsmExp();
-			    } else {
-				return newRegExp( (Reg) i );
-			    }
-			}
-		    }
-		}
-		
-		if (opTakesLabel()/*opInfo->takesLabel()*/ && e->op == TOKidentifier) {
-		    // DMD uses labels secondarily to other symbols, so check
-		    // if IdentifierExp::semantic won't find anything.
-		    Dsymbol *scopesym;
-		    
-		    if ( ! sc->search(stmt->loc, ident, & scopesym) )		    
-			return new DsymbolExp(stmt->loc,
-			    sc->func->searchLabel( ident ));
-		}
+            // parse primary: DMD allows 'MyAlign' (const int) but not '2+2'
+            // GAS is padding with NOPs last time I checked.
+            Expression * e = parseAsmExp()->optimize ( WANTvalue | WANTinterpret );
+            uinteger_t align = e->toUInteger();
 
-		e = e->semantic(sc);
+            if ( ( align & ( align - 1 ) ) == 0 )
+            {
+                //FIXME: This printf is not portable. The use of `align` varies from system to system;
+                // on i386 using a.out, .align `n` will align on a 2^`n` boundary instead of an `n` boundary
+#ifdef HAVE_GAS_BALIGN_AND_P2ALIGN
+                insnTemplate->printf ( ".balign\t%u", ( unsigned ) align );
+#else
+                insnTemplate->printf ( ".align\t%u", ( unsigned ) align );
+#endif
+            }
+            else
+            {
+                stmt->error ( "alignment must be a power of 2, not %u", ( unsigned ) align );
+            }
 
-		// Special case for floating point constant declarations.
-		if (e->op == TOKfloat64) {
-		    Dsymbol * sym = sc->search(stmt->loc, ident, NULL);
-		    if ( sym ) {
-			VarDeclaration *v = sym->isVarDeclaration();
-			if ( v ) {
-			    Expression *ve = new VarExp(stmt->loc, v);
-			    ve->type = e->type;
-			    e = ve;
-			}
-		    }			    
-		}
-		return e;
-	    }
-	    break;
-	case TOKdollar:
-	    nextToken();
-	    ident = Id::__dollar;
-	    goto do_dollar;
-	    break;
-	default:
-	    invalidExpression();
-	    return Handled;
-	}
-	return e;
-    }
+            setAsmCode();
+        }
 
-    void doAlign() {
-	// .align bits vs. bytes...
-	// apparently a.out platforms use bits instead of bytes...
-
-	// parse primary: DMD allows 'MyAlign' (const int) but not '2+2'
-	// GAS is padding with NOPs last time I checked.
-	Expression * e = parseAsmExp()->optimize(WANTvalue | WANTinterpret);
-	uinteger_t align = e->toUInteger();
-
-	if ((align & (align - 1)) == 0) {
-	    //FIXME: This printf is not portable. The use of `align` varies from system to system; 
-	    // on i386 using a.out, .align `n` will align on a 2^`n` boundary instead of an `n` boundary
-#ifdef HAVE_GAS_BALIGN_AND_P2ALIGN 
-	    insnTemplate->printf(".balign\t%u", (unsigned) align);
+        void doEven()
+        {
+            // .align for GAS is in bits, others probably use bytes..
+#ifdef HAVE_GAS_BALIGN_AND_P2ALIGN
+            insnTemplate->writestring ( ( char * ) ".align\t2" );
 #else
-	    insnTemplate->printf(".align\t%u", (unsigned) align);
+            insnTemplate->writestring ( ( char * ) ".align\t2" );
 #endif
-	} else {
-	    stmt->error("alignment must be a power of 2, not %u", (unsigned) align);
-	}
+            setAsmCode();
+        }
 
-	setAsmCode();
-    }
+        void doNaked()
+        {
+            // %% can we assume sc->func != 0?
+            sc->func->naked = 1;
+        }
 
-    void doEven() {
-	// .align for GAS is in bits, others probably use bytes..
-#ifdef HAVE_GAS_BALIGN_AND_P2ALIGN 
-	insnTemplate->writestring((char *) ".align\t2");
-#else
-	insnTemplate->writestring((char *) ".align\t2");
-#endif
-	setAsmCode();
-    }
+        void doData()
+        {
+            static const char * directives[] = { ".byte", ".short", ".long", ".long",
+                                                 "", "", ""
+                                               };
+// FIXME
+            /*
+                machine_mode mode;
 
-    void doNaked() {
-	// %% can we assume sc->func != 0?
-	sc->func->naked = 1;
-    }
-
-    void doData() {
-	static const char * directives[] = { ".byte", ".short", ".long", ".long",
-					     "", "", "" };
-// FIXME
-/*
-	machine_mode mode;
-
-	insnTemplate->writestring((char*) directives[op - Op_db]);
-	insnTemplate->writebyte(' ');
+                insnTemplate->writestring((char*) directives[op - Op_db]);
+                insnTemplate->writebyte(' ');
 
-	do {
-	    // DMD is pretty strict here, not even constant expressions are allowed..
-	    switch (op) {
-	    case Op_db:
-	    case Op_ds:
-	    case Op_di:
-	    case Op_dl:
-		if (token->value == TOKint32v || token->value == TOKuns32v ||
-		    token->value == TOKint64v || token->value == TOKuns64v) {
-		    // As per usual with GNU, assume at least 32-bit host
-		    if (op != Op_dl)
-			insnTemplate->printf("%u", (d_uns32) token->uns64value);
-		    else {
-			// Output two .longS.  GAS has .quad, but would have to rely on 'L' format ..
-			// just need to use HOST_WIDE_INT_PRINT_DEC
-			insnTemplate->printf("%u,%u",
-			    (d_uns32) token->uns64value, (d_uns32) (token->uns64value >> 32));
-		    }
-		} else {
-		    stmt->error("expected integer constant");
-		}
-		break;
-	    case Op_df:
-		mode = SFmode;
-		goto do_float;
-	    case Op_dd:
-		mode = DFmode;
-		goto do_float;
-	    case Op_de:
-#ifndef TARGET_80387
-#define XFmode TFmode
-#endif
-		mode = XFmode; // not TFmode
-		// drop through
-	    do_float:
-		if (token->value == TOKfloat32v || token->value == TOKfloat64v ||
-		    token->value == TOKfloat80v) {
-		    long words[3];
-		    real_to_target(words, & token->float80value.rv(), mode);
-		    // don't use directives..., just use .long like GCC
-		    insnTemplate->printf(".long\t%u", words[0]);
-		    if (mode != SFmode)
-			insnTemplate->printf(",%u", words[1]);
-		    // DMD outputs 10 bytes, so we need to switch to .short here
-		    if (mode == XFmode)
-			insnTemplate->printf("\n\t.short\t%u", words[2]);
-		} else {
-		    stmt->error("expected float constant");
-		}
-		break;
-	    default:
-		abort();
-	    }
-	    
-	    nextToken();	    
-	    if (token->value == TOKcomma) {
-		insnTemplate->writebyte(',');
-		nextToken();
-	    } else if (token->value == TOKeof) {
-		break;
-	    } else {
-		stmt->error("expected comma");
-	    }
-	} while (1);
+                do {
+                    // DMD is pretty strict here, not even constant expressions are allowed..
+                    switch (op) {
+                    case Op_db:
+                    case Op_ds:
+                    case Op_di:
+                    case Op_dl:
+                    if (token->value == TOKint32v || token->value == TOKuns32v ||
+                        token->value == TOKint64v || token->value == TOKuns64v) {
+                        // As per usual with GNU, assume at least 32-bit host
+                        if (op != Op_dl)
+                        insnTemplate->printf("%u", (d_uns32) token->uns64value);
+                        else {
+                        // Output two .longS.  GAS has .quad, but would have to rely on 'L' format ..
+                        // just need to use HOST_WIDE_INT_PRINT_DEC
+                        insnTemplate->printf("%u,%u",
+                            (d_uns32) token->uns64value, (d_uns32) (token->uns64value >> 32));
+                        }
+                    } else {
+                        stmt->error("expected integer constant");
+                    }
+                    break;
+                    case Op_df:
+                    mode = SFmode;
+                    goto do_float;
+                    case Op_dd:
+                    mode = DFmode;
+                    goto do_float;
+                    case Op_de:
+            #ifndef TARGET_80387
+            #define XFmode TFmode
+            #endif
+                    mode = XFmode; // not TFmode
+                    // drop through
+                    do_float:
+                    if (token->value == TOKfloat32v || token->value == TOKfloat64v ||
+                        token->value == TOKfloat80v) {
+                        long words[3];
+                        real_to_target(words, & token->float80value.rv(), mode);
+                        // don't use directives..., just use .long like GCC
+                        insnTemplate->printf(".long\t%u", words[0]);
+                        if (mode != SFmode)
+                        insnTemplate->printf(",%u", words[1]);
+                        // DMD outputs 10 bytes, so we need to switch to .short here
+                        if (mode == XFmode)
+                        insnTemplate->printf("\n\t.short\t%u", words[2]);
+                    } else {
+                        stmt->error("expected float constant");
+                    }
+                    break;
+                    default:
+                    abort();
+                    }
 
-	setAsmCode();*/
-    }
-};
+                    nextToken();
+                    if (token->value == TOKcomma) {
+                    insnTemplate->writebyte(',');
+                    nextToken();
+                    } else if (token->value == TOKeof) {
+                    break;
+                    } else {
+                    stmt->error("expected comma");
+                    }
+                } while (1);
+
+                setAsmCode();*/
+        }
+    };
 
 #if D_GCC_VER < 40
 // struct rtx was modified for c++; this macro from rtl.h needs to
 // be modified accordingly.
 #undef XEXP
-#define XEXP(RTX, N)	(RTL_CHECK2 (RTX, N, 'e', 'u').rt_rtx)
+#define XEXP(RTX, N)    (RTL_CHECK2 (RTX, N, 'e', 'u').rt_rtx)
 #endif
 
 // FIXME
-    #define HOST_WIDE_INT long
-bool getFrameRelativeValue(LLValue* decl, HOST_WIDE_INT * result)
-{
-assert(0);
+#define HOST_WIDE_INT long
+    bool getFrameRelativeValue ( LLValue* decl, HOST_WIDE_INT * result )
+    {
+        assert ( 0 );
 // FIXME
 //     // Using this instead of DECL_RTL for struct args seems like a
 //     // good way to get hit by a truck because it may not agree with
 //     // non-asm access, but asm code wouldn't know what GCC does anyway. */
 //     rtx r = DECL_INCOMING_RTL(decl);
 //     rtx e1, e2;
-// 
+//
 //     // Local variables don't have DECL_INCOMING_RTL
 //     if (r == NULL_RTX)
-// 	r = DECL_RTL(decl);
-// 
+//  r = DECL_RTL(decl);
+//
 //     if (r != NULL_RTX && GET_CODE(r) == MEM /* && r->frame_related */ ) {
-// 	r = XEXP(r, 0);
-// 	if (GET_CODE(r) == PLUS) {
-// 	    e1 = XEXP(r, 0);
-// 	    e2 = XEXP(r, 1);
-// 	    if (e1 == virtual_incoming_args_rtx && GET_CODE(e2) == CONST_INT) {
-// 		*result = INTVAL(e2) + 8; // %% 8 is 32-bit specific...
-// 		return true;
-// 	    } else if (e1 == virtual_stack_vars_rtx && GET_CODE(e2) == CONST_INT) {
-// 		*result = INTVAL(e2); // %% 8 is 32-bit specific...
-// 		return true;
-// 	    }
-// 	} else if (r == virtual_incoming_args_rtx) {
-// 	    *result = 8;
-// 	    return true; // %% same as above
-// 	}
-// 	// shouldn't have virtual_stack_vars_rtx by itself
+//  r = XEXP(r, 0);
+//  if (GET_CODE(r) == PLUS) {
+//      e1 = XEXP(r, 0);
+//      e2 = XEXP(r, 1);
+//      if (e1 == virtual_incoming_args_rtx && GET_CODE(e2) == CONST_INT) {
+//      *result = INTVAL(e2) + 8; // %% 8 is 32-bit specific...
+//      return true;
+//      } else if (e1 == virtual_stack_vars_rtx && GET_CODE(e2) == CONST_INT) {
+//      *result = INTVAL(e2); // %% 8 is 32-bit specific...
+//      return true;
+//      }
+//  } else if (r == virtual_incoming_args_rtx) {
+//      *result = 8;
+//      return true; // %% same as above
+//  }
+//  // shouldn't have virtual_stack_vars_rtx by itself
 //     }
-//     
-    return false;
-}
+//
+        return false;
+    }
 
 
-struct AsmParser : public AsmParserCommon
-{
-    virtual void run(Scope* sc, AsmStatement* asmst) {
-        AsmProcessor ap(sc, asmst);
-        ap.run();
-    }
+    struct AsmParser : public AsmParserCommon
+    {
+        virtual void run ( Scope* sc, AsmStatement* asmst )
+        {
+            AsmProcessor ap ( sc, asmst );
+            ap.run();
+        }
 
-    virtual std::string getRegName(int i) {
-        return regInfo[i].gccName;
-    }
-};
+        virtual std::string getRegName ( int i )
+        {
+            return regInfo[i].gccName;
+        }
+    };
 
 }
--- a/gen/asm-x86-64.h	Thu Feb 05 18:17:42 2009 +0100
+++ b/gen/asm-x86-64.h	Sun Feb 08 05:14:24 2009 +0100
@@ -3,432 +3,447 @@
 
 #include "id.h"
 
-namespace AsmParserx8664 {
+namespace AsmParserx8664
+{
 
-typedef enum {
-    Reg_Invalid = -1,
-    Reg_EAX = 0,
-    Reg_EBX,
-    Reg_ECX,
-    Reg_EDX,
-    Reg_ESI,
-    Reg_EDI,
-    Reg_EBP,
-    Reg_ESP,
-    Reg_ST,
-    Reg_ST1, Reg_ST2, Reg_ST3, Reg_ST4, Reg_ST5, Reg_ST6, Reg_ST7,
-    Reg_MM0, Reg_MM1, Reg_MM2, Reg_MM3, Reg_MM4, Reg_MM5, Reg_MM6, Reg_MM7,
-    Reg_XMM0, Reg_XMM1, Reg_XMM2, Reg_XMM3, Reg_XMM4, Reg_XMM5, Reg_XMM6, Reg_XMM7,
-
-    Reg_RAX, Reg_RBX, Reg_RCX, Reg_RDX, Reg_RSI, Reg_RDI, Reg_RBP, Reg_RSP, 
-    Reg_R8, Reg_R9, Reg_R10, Reg_R11, Reg_R12, Reg_R13, Reg_R14, Reg_R15,
-    Reg_R8B, Reg_R9B, Reg_R10B, Reg_R11B, Reg_R12B, Reg_R13B, Reg_R14B, Reg_R15B,
-    Reg_R8W, Reg_R9W, Reg_R10W, Reg_R11W, Reg_R12W, Reg_R13W, Reg_R14W, Reg_R15W,
-    Reg_R8D, Reg_R9D, Reg_R10D, Reg_R11D, Reg_R12D, Reg_R13D, Reg_R14D, Reg_R15D,
-    Reg_XMM8, Reg_XMM9, Reg_XMM10, Reg_XMM11, Reg_XMM12, Reg_XMM13, Reg_XMM14, Reg_XMM15,
-    Reg_RIP,
-    Reg_SIL, Reg_DIL, Reg_BPL, Reg_SPL, 
+    typedef enum
+    {
+        Reg_Invalid = -1,
+        Reg_EAX = 0,
+        Reg_EBX,
+        Reg_ECX,
+        Reg_EDX,
+        Reg_ESI,
+        Reg_EDI,
+        Reg_EBP,
+        Reg_ESP,
+        Reg_ST,
+        Reg_ST1, Reg_ST2, Reg_ST3, Reg_ST4, Reg_ST5, Reg_ST6, Reg_ST7,
+        Reg_MM0, Reg_MM1, Reg_MM2, Reg_MM3, Reg_MM4, Reg_MM5, Reg_MM6, Reg_MM7,
+        Reg_XMM0, Reg_XMM1, Reg_XMM2, Reg_XMM3, Reg_XMM4, Reg_XMM5, Reg_XMM6, Reg_XMM7,
 
-    Reg_EFLAGS,
-    Reg_CS,
-    Reg_DS,
-    Reg_SS,
-    Reg_ES,
-    Reg_FS,
-    Reg_GS,
-    Reg_AX, Reg_BX, Reg_CX, Reg_DX, Reg_SI, Reg_DI, Reg_BP, Reg_SP,
-    Reg_AL, Reg_AH, Reg_BL, Reg_BH, Reg_CL, Reg_CH, Reg_DL, Reg_DH,
-    Reg_CR0, Reg_CR2, Reg_CR3, Reg_CR4,
-    Reg_DR0, Reg_DR1, Reg_DR2, Reg_DR3, Reg_DR6, Reg_DR7,
-    Reg_TR3, Reg_TR4, Reg_TR5, Reg_TR6, Reg_TR7
-} Reg;
+        Reg_RAX, Reg_RBX, Reg_RCX, Reg_RDX, Reg_RSI, Reg_RDI, Reg_RBP, Reg_RSP,
+        Reg_R8, Reg_R9, Reg_R10, Reg_R11, Reg_R12, Reg_R13, Reg_R14, Reg_R15,
+        Reg_R8B, Reg_R9B, Reg_R10B, Reg_R11B, Reg_R12B, Reg_R13B, Reg_R14B, Reg_R15B,
+        Reg_R8W, Reg_R9W, Reg_R10W, Reg_R11W, Reg_R12W, Reg_R13W, Reg_R14W, Reg_R15W,
+        Reg_R8D, Reg_R9D, Reg_R10D, Reg_R11D, Reg_R12D, Reg_R13D, Reg_R14D, Reg_R15D,
+        Reg_XMM8, Reg_XMM9, Reg_XMM10, Reg_XMM11, Reg_XMM12, Reg_XMM13, Reg_XMM14, Reg_XMM15,
+        Reg_RIP,
+        Reg_SIL, Reg_DIL, Reg_BPL, Reg_SPL,
 
-static const int N_Regs = /*gp*/ 8 + /*fp*/ 8 + /*mmx*/ 8 + /*sse*/ 8 +
-/*seg*/ 6 + /*16bit*/ 8 + /*8bit*/ 8 + /*sys*/ 4+6+5 + /*flags*/ + 1
-+ 8 /*RAX, etc*/ 
-+ 8 /*R8-15*/ 
-+ 4 /*SIL, etc. 8-bit*/ 
-+ 8 /*R8-15B*/ 
-+ 8 /*R8-15W*/ 
-+ 8 /*R8-15D*/ 
-+ 8 /*XMM8-15*/
-+ 1 /*RIP*/ 
+        Reg_EFLAGS,
+        Reg_CS,
+        Reg_DS,
+        Reg_SS,
+        Reg_ES,
+        Reg_FS,
+        Reg_GS,
+        Reg_AX, Reg_BX, Reg_CX, Reg_DX, Reg_SI, Reg_DI, Reg_BP, Reg_SP,
+        Reg_AL, Reg_AH, Reg_BL, Reg_BH, Reg_CL, Reg_CH, Reg_DL, Reg_DH,
+        Reg_CR0, Reg_CR2, Reg_CR3, Reg_CR4,
+        Reg_DR0, Reg_DR1, Reg_DR2, Reg_DR3, Reg_DR6, Reg_DR7,
+        Reg_TR3, Reg_TR4, Reg_TR5, Reg_TR6, Reg_TR7
+    } Reg;
 
-;
+    static const int N_Regs = /*gp*/ 8 + /*fp*/ 8 + /*mmx*/ 8 + /*sse*/ 8 +
+                                     /*seg*/ 6 + /*16bit*/ 8 + /*8bit*/ 8 + /*sys*/ 4+6+5 + /*flags*/ + 1
+                                     + 8 /*RAX, etc*/
+                                     + 8 /*R8-15*/
+                                     + 4 /*SIL, etc. 8-bit*/
+                                     + 8 /*R8-15B*/
+                                     + 8 /*R8-15W*/
+                                     + 8 /*R8-15D*/
+                                     + 8 /*XMM8-15*/
+                                     + 1 /*RIP*/
+
+                                     ;
 
 #define NULL_TREE ""
 
-static struct {
-    const char * name;
-    std::string gccName; // GAS will take upper case, but GCC won't (needed for the clobber list)
-    Identifier * ident;
-    char size;
-    char baseReg; // %% todo: Reg, Reg_XX
-} regInfo[N_Regs] = {
-    { "EAX", NULL_TREE, NULL, 4,  Reg_EAX },
-    { "EBX", NULL_TREE, NULL, 4,  Reg_EBX },
-    { "ECX", NULL_TREE, NULL, 4,  Reg_ECX },
-    { "EDX", NULL_TREE, NULL, 4,  Reg_EDX },
-    { "ESI", NULL_TREE, NULL, 4,  Reg_ESI },
-    { "EDI", NULL_TREE, NULL, 4,  Reg_EDI },
-    { "EBP", NULL_TREE, NULL, 4,  Reg_EBP },
-    { "ESP", NULL_TREE, NULL, 4,  Reg_ESP },
-    { "ST", NULL_TREE, NULL,   10, Reg_ST },
-    { "ST(1)", NULL_TREE, NULL,10, Reg_ST1 },
-    { "ST(2)", NULL_TREE, NULL,10, Reg_ST2 },
-    { "ST(3)", NULL_TREE, NULL,10, Reg_ST3 },
-    { "ST(4)", NULL_TREE, NULL,10, Reg_ST4 },
-    { "ST(5)", NULL_TREE, NULL,10, Reg_ST5 },
-    { "ST(6)", NULL_TREE, NULL,10, Reg_ST6 },
-    { "ST(7)", NULL_TREE, NULL,10, Reg_ST7 },
-    { "MM0", NULL_TREE, NULL, 8, Reg_MM0 },
-    { "MM1", NULL_TREE, NULL, 8, Reg_MM1 },
-    { "MM2", NULL_TREE, NULL, 8, Reg_MM2 },
-    { "MM3", NULL_TREE, NULL, 8, Reg_MM3 },
-    { "MM4", NULL_TREE, NULL, 8, Reg_MM4 },
-    { "MM5", NULL_TREE, NULL, 8, Reg_MM5 },
-    { "MM6", NULL_TREE, NULL, 8, Reg_MM6 },
-    { "MM7", NULL_TREE, NULL, 8, Reg_MM7 },
-    { "XMM0", NULL_TREE, NULL, 16, Reg_XMM0 },
-    { "XMM1", NULL_TREE, NULL, 16, Reg_XMM1 },
-    { "XMM2", NULL_TREE, NULL, 16, Reg_XMM2 },
-    { "XMM3", NULL_TREE, NULL, 16, Reg_XMM3 },
-    { "XMM4", NULL_TREE, NULL, 16, Reg_XMM4 },
-    { "XMM5", NULL_TREE, NULL, 16, Reg_XMM5 },
-    { "XMM6", NULL_TREE, NULL, 16, Reg_XMM6 },
-    { "XMM7", NULL_TREE, NULL, 16, Reg_XMM7 },
+    static struct
+    {
+        const char * name;
+        std::string gccName; // GAS will take upper case, but GCC won't (needed for the clobber list)
+        Identifier * ident;
+        char size;
+        char baseReg; // %% todo: Reg, Reg_XX
+    } regInfo[N_Regs] =
+    {
+        { "EAX", NULL_TREE, NULL, 4,  Reg_EAX },
+        { "EBX", NULL_TREE, NULL, 4,  Reg_EBX },
+        { "ECX", NULL_TREE, NULL, 4,  Reg_ECX },
+        { "EDX", NULL_TREE, NULL, 4,  Reg_EDX },
+        { "ESI", NULL_TREE, NULL, 4,  Reg_ESI },
+        { "EDI", NULL_TREE, NULL, 4,  Reg_EDI },
+        { "EBP", NULL_TREE, NULL, 4,  Reg_EBP },
+        { "ESP", NULL_TREE, NULL, 4,  Reg_ESP },
+        { "ST", NULL_TREE, NULL,   10, Reg_ST },
+        { "ST(1)", NULL_TREE, NULL,10, Reg_ST1 },
+        { "ST(2)", NULL_TREE, NULL,10, Reg_ST2 },
+        { "ST(3)", NULL_TREE, NULL,10, Reg_ST3 },
+        { "ST(4)", NULL_TREE, NULL,10, Reg_ST4 },
+        { "ST(5)", NULL_TREE, NULL,10, Reg_ST5 },
+        { "ST(6)", NULL_TREE, NULL,10, Reg_ST6 },
+        { "ST(7)", NULL_TREE, NULL,10, Reg_ST7 },
+        { "MM0", NULL_TREE, NULL, 8, Reg_MM0 },
+        { "MM1", NULL_TREE, NULL, 8, Reg_MM1 },
+        { "MM2", NULL_TREE, NULL, 8, Reg_MM2 },
+        { "MM3", NULL_TREE, NULL, 8, Reg_MM3 },
+        { "MM4", NULL_TREE, NULL, 8, Reg_MM4 },
+        { "MM5", NULL_TREE, NULL, 8, Reg_MM5 },
+        { "MM6", NULL_TREE, NULL, 8, Reg_MM6 },
+        { "MM7", NULL_TREE, NULL, 8, Reg_MM7 },
+        { "XMM0", NULL_TREE, NULL, 16, Reg_XMM0 },
+        { "XMM1", NULL_TREE, NULL, 16, Reg_XMM1 },
+        { "XMM2", NULL_TREE, NULL, 16, Reg_XMM2 },
+        { "XMM3", NULL_TREE, NULL, 16, Reg_XMM3 },
+        { "XMM4", NULL_TREE, NULL, 16, Reg_XMM4 },
+        { "XMM5", NULL_TREE, NULL, 16, Reg_XMM5 },
+        { "XMM6", NULL_TREE, NULL, 16, Reg_XMM6 },
+        { "XMM7", NULL_TREE, NULL, 16, Reg_XMM7 },
 
-    { "RAX", NULL_TREE, NULL, 8,  Reg_RAX },
-    { "RBX", NULL_TREE, NULL, 8,  Reg_RBX },
-    { "RCX", NULL_TREE, NULL, 8,  Reg_RCX },
-    { "RDX", NULL_TREE, NULL, 8,  Reg_RDX },
-    { "RSI", NULL_TREE, NULL, 8,  Reg_RSI },
-    { "RDI", NULL_TREE, NULL, 8,  Reg_RDI },
-    { "RBP", NULL_TREE, NULL, 8,  Reg_RBP },
-    { "RSP", NULL_TREE, NULL, 8,  Reg_RSP },
-    { "R8", NULL_TREE, NULL, 8,  Reg_R8 },
-    { "R9", NULL_TREE, NULL, 8,  Reg_R9 },
-    { "R10", NULL_TREE, NULL, 8,  Reg_R10 },
-    { "R11", NULL_TREE, NULL, 8,  Reg_R11 },
-    { "R12", NULL_TREE, NULL, 8,  Reg_R12 },
-    { "R13", NULL_TREE, NULL, 8,  Reg_R13 },
-    { "R14", NULL_TREE, NULL, 8,  Reg_R14 },
-    { "R15", NULL_TREE, NULL, 8,  Reg_R15 },
-    { "R8B", NULL_TREE, NULL, 1,  Reg_R8 },
-    { "R9B", NULL_TREE, NULL, 1,  Reg_R9 },
-    { "R10B", NULL_TREE, NULL, 1,  Reg_R10 },
-    { "R11B", NULL_TREE, NULL, 1,  Reg_R11 },
-    { "R12B", NULL_TREE, NULL, 1,  Reg_R12 },
-    { "R13B", NULL_TREE, NULL, 1,  Reg_R13 },
-    { "R14B", NULL_TREE, NULL, 1,  Reg_R14 },
-    { "R15B", NULL_TREE, NULL, 1,  Reg_R15 },
-    { "R8W", NULL_TREE, NULL, 2,  Reg_R8 },
-    { "R9W", NULL_TREE, NULL, 2,  Reg_R9 },
-    { "R10W", NULL_TREE, NULL, 2,  Reg_R10 },
-    { "R11W", NULL_TREE, NULL, 2,  Reg_R11 },
-    { "R12W", NULL_TREE, NULL, 2,  Reg_R12 },
-    { "R13W", NULL_TREE, NULL, 2,  Reg_R13 },
-    { "R14W", NULL_TREE, NULL, 2,  Reg_R14 },
-    { "R15W", NULL_TREE, NULL, 2,  Reg_R15 },
-    { "R8D", NULL_TREE, NULL, 4,  Reg_R8 },
-    { "R9D", NULL_TREE, NULL, 4,  Reg_R9 },
-    { "R10D", NULL_TREE, NULL, 4,  Reg_R10 },
-    { "R11D", NULL_TREE, NULL, 4,  Reg_R11 },
-    { "R12D", NULL_TREE, NULL, 4,  Reg_R12 },
-    { "R13D", NULL_TREE, NULL, 4,  Reg_R13 },
-    { "R14D", NULL_TREE, NULL, 4,  Reg_R14 },
-    { "R15D", NULL_TREE, NULL, 4,  Reg_R15 },
-    { "XMM8", NULL_TREE, NULL, 16, Reg_XMM8 },
-    { "XMM9", NULL_TREE, NULL, 16, Reg_XMM9 },
-    { "XMM10", NULL_TREE, NULL, 16, Reg_XMM10 },
-    { "XMM11", NULL_TREE, NULL, 16, Reg_XMM11 },
-    { "XMM12", NULL_TREE, NULL, 16, Reg_XMM12 },
-    { "XMM13", NULL_TREE, NULL, 16, Reg_XMM13 },
-    { "XMM14", NULL_TREE, NULL, 16, Reg_XMM14 },
-    { "XMM15", NULL_TREE, NULL, 16, Reg_XMM15 },
-    { "RIP", NULL_TREE, NULL, 8,  Reg_RIP },
-    { "SIL", NULL_TREE, NULL, 1,  Reg_SIL },
-    { "DIL", NULL_TREE, NULL, 1,  Reg_DIL },
-    { "BPL", NULL_TREE, NULL, 1,  Reg_BPL },
-    { "SPL", NULL_TREE, NULL, 1,  Reg_SPL },
+        { "RAX", NULL_TREE, NULL, 8,  Reg_RAX },
+        { "RBX", NULL_TREE, NULL, 8,  Reg_RBX },
+        { "RCX", NULL_TREE, NULL, 8,  Reg_RCX },
+        { "RDX", NULL_TREE, NULL, 8,  Reg_RDX },
+        { "RSI", NULL_TREE, NULL, 8,  Reg_RSI },
+        { "RDI", NULL_TREE, NULL, 8,  Reg_RDI },
+        { "RBP", NULL_TREE, NULL, 8,  Reg_RBP },
+        { "RSP", NULL_TREE, NULL, 8,  Reg_RSP },
+        { "R8", NULL_TREE, NULL, 8,  Reg_R8 },
+        { "R9", NULL_TREE, NULL, 8,  Reg_R9 },
+        { "R10", NULL_TREE, NULL, 8,  Reg_R10 },
+        { "R11", NULL_TREE, NULL, 8,  Reg_R11 },
+        { "R12", NULL_TREE, NULL, 8,  Reg_R12 },
+        { "R13", NULL_TREE, NULL, 8,  Reg_R13 },
+        { "R14", NULL_TREE, NULL, 8,  Reg_R14 },
+        { "R15", NULL_TREE, NULL, 8,  Reg_R15 },
+        { "R8B", NULL_TREE, NULL, 1,  Reg_R8 },
+        { "R9B", NULL_TREE, NULL, 1,  Reg_R9 },
+        { "R10B", NULL_TREE, NULL, 1,  Reg_R10 },
+        { "R11B", NULL_TREE, NULL, 1,  Reg_R11 },
+        { "R12B", NULL_TREE, NULL, 1,  Reg_R12 },
+        { "R13B", NULL_TREE, NULL, 1,  Reg_R13 },
+        { "R14B", NULL_TREE, NULL, 1,  Reg_R14 },
+        { "R15B", NULL_TREE, NULL, 1,  Reg_R15 },
+        { "R8W", NULL_TREE, NULL, 2,  Reg_R8 },
+        { "R9W", NULL_TREE, NULL, 2,  Reg_R9 },
+        { "R10W", NULL_TREE, NULL, 2,  Reg_R10 },
+        { "R11W", NULL_TREE, NULL, 2,  Reg_R11 },
+        { "R12W", NULL_TREE, NULL, 2,  Reg_R12 },
+        { "R13W", NULL_TREE, NULL, 2,  Reg_R13 },
+        { "R14W", NULL_TREE, NULL, 2,  Reg_R14 },
+        { "R15W", NULL_TREE, NULL, 2,  Reg_R15 },
+        { "R8D", NULL_TREE, NULL, 4,  Reg_R8 },
+        { "R9D", NULL_TREE, NULL, 4,  Reg_R9 },
+        { "R10D", NULL_TREE, NULL, 4,  Reg_R10 },
+        { "R11D", NULL_TREE, NULL, 4,  Reg_R11 },
+        { "R12D", NULL_TREE, NULL, 4,  Reg_R12 },
+        { "R13D", NULL_TREE, NULL, 4,  Reg_R13 },
+        { "R14D", NULL_TREE, NULL, 4,  Reg_R14 },
+        { "R15D", NULL_TREE, NULL, 4,  Reg_R15 },
+        { "XMM8", NULL_TREE, NULL, 16, Reg_XMM8 },
+        { "XMM9", NULL_TREE, NULL, 16, Reg_XMM9 },
+        { "XMM10", NULL_TREE, NULL, 16, Reg_XMM10 },
+        { "XMM11", NULL_TREE, NULL, 16, Reg_XMM11 },
+        { "XMM12", NULL_TREE, NULL, 16, Reg_XMM12 },
+        { "XMM13", NULL_TREE, NULL, 16, Reg_XMM13 },
+        { "XMM14", NULL_TREE, NULL, 16, Reg_XMM14 },
+        { "XMM15", NULL_TREE, NULL, 16, Reg_XMM15 },
+        { "RIP", NULL_TREE, NULL, 8,  Reg_RIP },
+        { "SIL", NULL_TREE, NULL, 1,  Reg_SIL },
+        { "DIL", NULL_TREE, NULL, 1,  Reg_DIL },
+        { "BPL", NULL_TREE, NULL, 1,  Reg_BPL },
+        { "SPL", NULL_TREE, NULL, 1,  Reg_SPL },
 
-    { "FLAGS", NULL_TREE, NULL, 0, Reg_EFLAGS }, // the gcc name is "flags"; not used in assembler input
-    { "CS",  NULL_TREE, NULL, 2, -1 },
-    { "DS",  NULL_TREE, NULL, 2, -1 },
-    { "SS",  NULL_TREE, NULL, 2, -1 },
-    { "ES",  NULL_TREE, NULL, 2, -1 },
-    { "FS",  NULL_TREE, NULL, 2, -1 },
-    { "GS",  NULL_TREE, NULL, 2, -1 },
-    { "AX",  NULL_TREE, NULL, 2,  Reg_EAX },
-    { "BX",  NULL_TREE, NULL, 2,  Reg_EBX },
-    { "CX",  NULL_TREE, NULL, 2,  Reg_ECX },
-    { "DX",  NULL_TREE, NULL, 2,  Reg_EDX },
-    { "SI",  NULL_TREE, NULL, 2,  Reg_ESI },
-    { "DI",  NULL_TREE, NULL, 2,  Reg_EDI },
-    { "BP",  NULL_TREE, NULL, 2,  Reg_EBP },
-    { "SP",  NULL_TREE, NULL, 2,  Reg_ESP },
-    { "AL",  NULL_TREE, NULL, 1,  Reg_EAX },
-    { "AH",  NULL_TREE, NULL, 1,  Reg_EAX },
-    { "BL",  NULL_TREE, NULL, 1,  Reg_EBX },
-    { "BH",  NULL_TREE, NULL, 1,  Reg_EBX },
-    { "CL",  NULL_TREE, NULL, 1,  Reg_ECX },
-    { "CH",  NULL_TREE, NULL, 1,  Reg_ECX },
-    { "DL",  NULL_TREE, NULL, 1,  Reg_EDX },
-    { "DH",  NULL_TREE, NULL, 1,  Reg_EDX },
-    { "CR0", NULL_TREE, NULL, 0, -1 },
-    { "CR2", NULL_TREE, NULL, 0, -1 },
-    { "CR3", NULL_TREE, NULL, 0, -1 },
-    { "CR4", NULL_TREE, NULL, 0, -1 },
-    { "DR0", NULL_TREE, NULL, 0, -1 },
-    { "DR1", NULL_TREE, NULL, 0, -1 },
-    { "DR2", NULL_TREE, NULL, 0, -1 },
-    { "DR3", NULL_TREE, NULL, 0, -1 },
-    { "DR6", NULL_TREE, NULL, 0, -1 },
-    { "DR7", NULL_TREE, NULL, 0, -1 },
-    { "TR3", NULL_TREE, NULL, 0, -1 },
-    { "TR4", NULL_TREE, NULL, 0, -1 },
-    { "TR5", NULL_TREE, NULL, 0, -1 },
-    { "TR6", NULL_TREE, NULL, 0, -1 },
-    { "TR7", NULL_TREE, NULL, 0, -1 }
-};
+        { "FLAGS", NULL_TREE, NULL, 0, Reg_EFLAGS }, // the gcc name is "flags"; not used in assembler input
+        { "CS",  NULL_TREE, NULL, 2, -1 },
+        { "DS",  NULL_TREE, NULL, 2, -1 },
+        { "SS",  NULL_TREE, NULL, 2, -1 },
+        { "ES",  NULL_TREE, NULL, 2, -1 },
+        { "FS",  NULL_TREE, NULL, 2, -1 },
+        { "GS",  NULL_TREE, NULL, 2, -1 },
+        { "AX",  NULL_TREE, NULL, 2,  Reg_EAX },
+        { "BX",  NULL_TREE, NULL, 2,  Reg_EBX },
+        { "CX",  NULL_TREE, NULL, 2,  Reg_ECX },
+        { "DX",  NULL_TREE, NULL, 2,  Reg_EDX },
+        { "SI",  NULL_TREE, NULL, 2,  Reg_ESI },
+        { "DI",  NULL_TREE, NULL, 2,  Reg_EDI },
+        { "BP",  NULL_TREE, NULL, 2,  Reg_EBP },
+        { "SP",  NULL_TREE, NULL, 2,  Reg_ESP },
+        { "AL",  NULL_TREE, NULL, 1,  Reg_EAX },
+        { "AH",  NULL_TREE, NULL, 1,  Reg_EAX },
+        { "BL",  NULL_TREE, NULL, 1,  Reg_EBX },
+        { "BH",  NULL_TREE, NULL, 1,  Reg_EBX },
+        { "CL",  NULL_TREE, NULL, 1,  Reg_ECX },
+        { "CH",  NULL_TREE, NULL, 1,  Reg_ECX },
+        { "DL",  NULL_TREE, NULL, 1,  Reg_EDX },
+        { "DH",  NULL_TREE, NULL, 1,  Reg_EDX },
+        { "CR0", NULL_TREE, NULL, 0, -1 },
+        { "CR2", NULL_TREE, NULL, 0, -1 },
+        { "CR3", NULL_TREE, NULL, 0, -1 },
+        { "CR4", NULL_TREE, NULL, 0, -1 },
+        { "DR0", NULL_TREE, NULL, 0, -1 },
+        { "DR1", NULL_TREE, NULL, 0, -1 },
+        { "DR2", NULL_TREE, NULL, 0, -1 },
+        { "DR3", NULL_TREE, NULL, 0, -1 },
+        { "DR6", NULL_TREE, NULL, 0, -1 },
+        { "DR7", NULL_TREE, NULL, 0, -1 },
+        { "TR3", NULL_TREE, NULL, 0, -1 },
+        { "TR4", NULL_TREE, NULL, 0, -1 },
+        { "TR5", NULL_TREE, NULL, 0, -1 },
+        { "TR6", NULL_TREE, NULL, 0, -1 },
+        { "TR7", NULL_TREE, NULL, 0, -1 }
+    };
 
-typedef enum {
-    No_Type_Needed,
-    Int_Types,
-    Word_Types, // same as Int_Types, but byte is not allowed
-    FP_Types,
-    FPInt_Types,
-    Byte_NoType, // byte only, but no type suffix
-} TypeNeeded;
+    typedef enum
+    {
+        No_Type_Needed,
+        Int_Types,
+        Word_Types, // same as Int_Types, but byte is not allowed
+        FP_Types,
+        FPInt_Types,
+        Byte_NoType, // byte only, but no type suffix
+    } TypeNeeded;
 
-typedef enum {
-    No_Link,
-    Out_Mnemonic,
-    Next_Form
-} OpLink;
+    typedef enum
+    {
+        No_Link,
+        Out_Mnemonic,
+        Next_Form
+    } OpLink;
 
-typedef enum {
-    Clb_SizeAX   = 0x01,
-    Clb_SizeDXAX = 0x02,
-    Clb_EAX      = 0x03,
-    Clb_DXAX_Mask = 0x03,
-    
-    Clb_Flags    = 0x04,
-    Clb_DI       = 0x08,
-    Clb_SI       = 0x10,
-    Clb_CX       = 0x20,
-    Clb_ST       = 0x40,
-    Clb_SP       = 0x80 // Doesn't actually let GCC know the frame pointer is modified
-} ImplicitClober;
+    typedef enum
+    {
+        Clb_SizeAX   = 0x01,
+        Clb_SizeDXAX = 0x02,
+        Clb_EAX      = 0x03,
+        Clb_DXAX_Mask = 0x03,
+
+        Clb_Flags    = 0x04,
+        Clb_DI       = 0x08,
+        Clb_SI       = 0x10,
+        Clb_CX       = 0x20,
+        Clb_ST       = 0x40,
+        Clb_SP       = 0x80 // Doesn't actually let GCC know the frame pointer is modified
+    } ImplicitClober;
 
 // "^ +/..\([A-Za-z_0-9]+\).*" -> "    \1,"
-typedef enum {
-    Op_Invalid,
-    Op_Adjust,
-    Op_Dst,
-    Op_Upd,
-    Op_DstW,
-    Op_DstF,
-    Op_UpdF,
-    Op_DstSrc,
-    Op_DstSrcF,
-    Op_UpdSrcF,
-    Op_DstSrcFW,
-    Op_UpdSrcFW,
-    Op_DstSrcSSE,
-    Op_DstSrcMMX,
-    Op_DstSrcImmS,
-    Op_DstSrcImmM,
-    Op_UpdSrcShft,
-    Op_DstSrcNT,
-    Op_UpdSrcNT,
-    Op_DstMemNT,
-    Op_DstRMBNT,
-    Op_DstRMWNT,
-    Op_UpdUpd,
-    Op_UpdUpdF,
-    Op_Src,
-    Op_SrcRMWNT,
-    Op_SrcW,
-    Op_SrcImm,
-    Op_Src_DXAXF,
-    Op_SrcMemNT,
-    Op_SrcMemNTF,
-    Op_SrcSrc,
-    Op_SrcSrcF,
-    Op_SrcSrcFW,
-    Op_SrcSrcSSEF,
-    Op_SrcSrcMMX,
-    Op_Shift,
-    Op_Branch,
-    Op_CBranch,
-    Op_0,
-    Op_0_AX,
-    Op_0_DXAX,
-    Op_Loop,
-    Op_Flags,
-    Op_F0_ST,
-    Op_F0_P,
-    Op_Fs_P,
-    Op_Fis,
-    Op_Fis_ST,
-    Op_Fis_P,
-    Op_Fid,
-    Op_Fid_P,
-    Op_Ffd,
-    Op_FfdR,
-    Op_Ffd_P,
-    Op_FfdR_P,
-    Op_Fd_P,
-    Op_FdST,
-    Op_FMath,
-    Op_FdSTiSTi,
-    Op_FPMath,
-    Op_FCmp,
-    Op_FCmp1,
-    Op_FCmpP,
-    Op_FCmpP1,
-    Op_FCmpFlg,
-    Op_FCmpFlgP,
-    Op_fld,
-    Op_fldR,
-    Op_fxch,
-    Op_fxch1,
-    Op_fxch0,
-    Op_SizedStack,
-    Op_bound,
-    Op_bswap,
-    Op_cmps,
-    Op_cmpsd,
-    Op_cmpsX,
-    Op_cmpxchg8b,
-    Op_cmpxchg,
-    Op_cpuid,
-    Op_enter,
-    Op_fdisi,
-    Op_feni,
-    Op_fsetpm,
-    Op_fXstsw,
-    Op_imul,
-    Op_imul2,
-    Op_imul1,
-    Op_in,
-    Op_ins,
-    Op_insX,
-    Op_iret,
-    Op_iretd,
-    Op_lods,
-    Op_lodsX,
-    Op_movs,
-    Op_movsd,
-    Op_movsX,
-    Op_movsx,
-    Op_movzx,
-    Op_mul,
-    Op_out,
-    Op_outs,
-    Op_outsX,
-    Op_push,
-    Op_ret,
-    Op_retf,
-    Op_scas,
-    Op_scasX,
-    Op_stos,
-    Op_stosX,
-    Op_xlat,
-    N_AsmOpInfo,
-    Op_Align,
-    Op_Even,
-    Op_Naked,
-    Op_db,
-    Op_ds,
-    Op_di,
-    Op_dl,
-    Op_df,
-    Op_dd,
-    Op_de
-} AsmOp;
+    typedef enum
+    {
+        Op_Invalid,
+        Op_Adjust,
+        Op_Dst,
+        Op_Upd,
+        Op_DstW,
+        Op_DstF,
+        Op_UpdF,
+        Op_DstSrc,
+        Op_DstSrcF,
+        Op_UpdSrcF,
+        Op_DstSrcFW,
+        Op_UpdSrcFW,
+        Op_DstSrcSSE,
+        Op_DstSrcMMX,
+        Op_DstSrcImmS,
+        Op_DstSrcImmM,
+        Op_UpdSrcShft,
+        Op_DstSrcNT,
+        Op_UpdSrcNT,
+        Op_DstMemNT,
+        Op_DstRMBNT,
+        Op_DstRMWNT,
+        Op_UpdUpd,
+        Op_UpdUpdF,
+        Op_Src,
+        Op_SrcRMWNT,
+        Op_SrcW,
+        Op_SrcImm,
+        Op_Src_DXAXF,
+        Op_SrcMemNT,
+        Op_SrcMemNTF,
+        Op_SrcSrc,
+        Op_SrcSrcF,
+        Op_SrcSrcFW,
+        Op_SrcSrcSSEF,
+        Op_SrcSrcMMX,
+        Op_Shift,
+        Op_Branch,
+        Op_CBranch,
+        Op_0,
+        Op_0_AX,
+        Op_0_DXAX,
+        Op_Loop,
+        Op_Flags,
+        Op_F0_ST,
+        Op_F0_P,
+        Op_Fs_P,
+        Op_Fis,
+        Op_Fis_ST,
+        Op_Fis_P,
+        Op_Fid,
+        Op_Fid_P,
+        Op_Ffd,
+        Op_FfdR,
+        Op_Ffd_P,
+        Op_FfdR_P,
+        Op_Fd_P,
+        Op_FdST,
+        Op_FMath,
+        Op_FdSTiSTi,
+        Op_FPMath,
+        Op_FCmp,
+        Op_FCmp1,
+        Op_FCmpP,
+        Op_FCmpP1,
+        Op_FCmpFlg,
+        Op_FCmpFlgP,
+        Op_fld,
+        Op_fldR,
+        Op_fxch,
+        Op_fxch1,
+        Op_fxch0,
+        Op_SizedStack,
+        Op_bound,
+        Op_bswap,
+        Op_cmps,
+        Op_cmpsd,
+        Op_cmpsX,
+        Op_cmpxchg8b,
+        Op_cmpxchg,
+        Op_cpuid,
+        Op_enter,
+        Op_fdisi,
+        Op_feni,
+        Op_fsetpm,
+        Op_fXstsw,
+        Op_imul,
+        Op_imul2,
+        Op_imul1,
+        Op_in,
+        Op_ins,
+        Op_insX,
+        Op_iret,
+        Op_iretd,
+        Op_lods,
+        Op_lodsX,
+        Op_movs,
+        Op_movsd,
+        Op_movsX,
+        Op_movsx,
+        Op_movzx,
+        Op_mul,
+        Op_out,
+        Op_outs,
+        Op_outsX,
+        Op_push,
+        Op_ret,
+        Op_retf,
+        Op_scas,
+        Op_scasX,
+        Op_stos,
+        Op_stosX,
+        Op_xlat,
+        N_AsmOpInfo,
+        Op_Align,
+        Op_Even,
+        Op_Naked,
+        Op_db,
+        Op_ds,
+        Op_di,
+        Op_dl,
+        Op_df,
+        Op_dd,
+        Op_de
+    } AsmOp;
 
-typedef enum {
-    Opr_None = 0,
-    OprC_MRI  = 1,
-    OprC_MR   = 2,
-    OprC_Mem  = 3,
-    OprC_Reg  = 4,
-    OprC_Imm  = 5,
-    OprC_SSE  = 6,
-    OprC_SSE_Mem = 7,
-    OprC_R32  = 8,
-    OprC_RWord = 9,
-    OprC_RFP   = 10,
-    OprC_AbsRel = 11,
-    OprC_Relative = 12,
-    OprC_Port = 13, // DX or imm
-    OprC_AX = 14, // AL,AX,EAX
-    OprC_DX = 15, // only DX
-    OprC_MMX = 16,
-    OprC_MMX_Mem = 17,
-    OprC_Shift = 18, // imm or CL
-    
-    Opr_ClassMask = 0x1f,
-    
-    Opr_Dest     = 0x20,
-    Opr_Update   = 0x60,
-    
-    Opr_NoType = 0x80,
-} OprVals;
+    typedef enum
+    {
+        Opr_None = 0,
+        OprC_MRI  = 1,
+        OprC_MR   = 2,
+        OprC_Mem  = 3,
+        OprC_Reg  = 4,
+        OprC_Imm  = 5,
+        OprC_SSE  = 6,
+        OprC_SSE_Mem = 7,
+        OprC_R32  = 8,
+        OprC_RWord = 9,
+        OprC_RFP   = 10,
+        OprC_AbsRel = 11,
+        OprC_Relative = 12,
+        OprC_Port = 13, // DX or imm
+        OprC_AX = 14, // AL,AX,EAX
+        OprC_DX = 15, // only DX
+        OprC_MMX = 16,
+        OprC_MMX_Mem = 17,
+        OprC_Shift = 18, // imm or CL
+
+        Opr_ClassMask = 0x1f,
+
+        Opr_Dest     = 0x20,
+        Opr_Update   = 0x60,
+
+        Opr_NoType = 0x80,
+    } OprVals;
 
 
-typedef struct {
-} AsmOprInfo;
+    typedef struct
+    {
+    } AsmOprInfo;
 
-typedef unsigned char Opr;
+    typedef unsigned char Opr;
 
-typedef struct {
-    Opr operands[3];
-    unsigned char
-	needsType : 3,
-	implicitClobbers : 8,
-        linkType : 2;
-    unsigned link;
+    typedef struct
+    {
+        Opr operands[3];
+        unsigned char
+    needsType : 3,
+    implicitClobbers : 8,
+    linkType : 2;
+        unsigned link;
+
+        /*
+        bool takesLabel() {
+        return operands[0] & Opr_Label;
+        }
+        */
 
-    /*
-    bool takesLabel() {
-	return operands[0] & Opr_Label;
-    }
-    */
-    
-    unsigned nOperands() {
-	if (!operands[0])
-	    return 0;
-	else if (!operands[1])
-	    return 1;
-	else if (!operands[2])
-	    return 2;
-	else
-	    return 3;
-    }
-} AsmOpInfo;
+        unsigned nOperands()
+        {
+            if ( !operands[0] )
+                return 0;
+            else if ( !operands[1] )
+                return 1;
+            else if ( !operands[2] )
+                return 2;
+            else
+                return 3;
+        }
+    } AsmOpInfo;
 
-typedef enum {
-    Mn_fdisi,
-    Mn_feni,
-    Mn_fsetpm,
-    Mn_iretw,
-    Mn_iret,
-    Mn_lret,
-    Mn_cmpxchg8b,
-    N_AltMn
-} Alternate_Mnemonics;
+    typedef enum
+    {
+        Mn_fdisi,
+        Mn_feni,
+        Mn_fsetpm,
+        Mn_iretw,
+        Mn_iret,
+        Mn_lret,
+        Mn_cmpxchg8b,
+        N_AltMn
+    } Alternate_Mnemonics;
 
-static const char * alternateMnemonics[N_AltMn] = {
-    ".byte 0xdb, 0xe1",
-    ".byte 0xdb, 0xe0",
-    ".byte 0xdb, 0xe4",
-    "iretw",
-    "iret",
-    "lret",
-    "cmpxchg8b" };
+    static const char * alternateMnemonics[N_AltMn] =
+    {
+        ".byte 0xdb, 0xe1",
+        ".byte 0xdb, 0xe0",
+        ".byte 0xdb, 0xe4",
+        "iretw",
+        "iret",
+        "lret",
+        "cmpxchg8b"
+    };
 
 #define mri  OprC_MRI
 #define mr   OprC_MR
@@ -454,127 +469,128 @@
 //#define L    Opr_Label
 
 // D=dest, N=notype
-static AsmOpInfo asmOpInfo[N_AsmOpInfo] = {
-    /* Op_Invalid   */  {},
-    /* Op_Adjust    */  { 0,0,0,             0, Clb_EAX /*just AX*/ },
-    /* Op_Dst       */  { D|mr,  0,    0,    1  },
-    /* Op_Upd       */  { U|mr,  0,    0,    1  },
-    /* Op_DstW      */  { D|mr,  0,    0,    Word_Types  },
-    /* Op_DstF      */  { D|mr,  0,    0,    1, Clb_Flags },
-    /* Op_UpdF      */  { U|mr,  0,    0,    1, Clb_Flags },
-    /* Op_DstSrc    */  { D|mr,  mri,  0,/**/1  }, 
-    /* Op_DstSrcF   */  { D|mr,  mri,  0,/**/1, Clb_Flags }, 
-    /* Op_UpdSrcF   */  { U|mr,  mri,  0,/**/1, Clb_Flags }, 
-    /* Op_DstSrcFW  */  { D|mr,  mri,  0,/**/Word_Types, Clb_Flags }, 
-    /* Op_UpdSrcFW  */  { U|mr,  mri,  0,/**/Word_Types, Clb_Flags }, 
-    /* Op_DstSrcSSE */  { U|sse, ssem, 0     },  // some may not be update %%
-    /* Op_DstSrcMMX */  { U|mmx, mmxm, 0     },  // some may not be update %%
-    /* Op_DstSrcImmS*/  { U|sse, ssem, N|imm  }, // some may not be update %%
-    /* Op_DstSrcImmM*/  { U|mmx, mmxm, N|imm  }, // some may not be update %%
-    /* Op_UpdSrcShft*/  { U|mr,  reg,  N|shft, 1, Clb_Flags }, // 16/32 only
-    /* Op_DstSrcNT  */  { D|mr,  mr,   0,    0 }, // used for movd .. operands can be rm32,sse,mmx
-    /* Op_UpdSrcNT  */  { U|mr,  mr,   0,    0 }, // used for movd .. operands can be rm32,sse,mmx
-    /* Op_DstMemNT  */  { D|mem, 0,    0     },
-    /* Op_DstRMBNT  */  { D|mr,  0,    0,    Byte_NoType },
-    /* Op_DstRMWNT  */  { D|mr,  0,    0     },
-    /* Op_UpdUpd    */  { U|mr,U|mr,   0,/**/1  }, 
-    /* Op_UpdUpdF   */  { U|mr,U|mr,   0,/**/1, Clb_Flags }, 
-    /* Op_Src       */  {   mri, 0,    0,    1  },
-    /* Op_SrcRMWNT  */  {   mr,  0,    0,    0  },
-    /* Op_SrcW      */  {   mri, 0,    0,    Word_Types  },
-    /* Op_SrcImm    */  {   imm },
-    /* Op_Src_DXAXF */  {   mr,  0,    0,    1, Clb_SizeDXAX|Clb_Flags },
-    /* Op_SrcMemNT  */  {   mem, 0,    0     },
-    /* Op_SrcMemNTF */  {   mem, 0,    0,    0, Clb_Flags },
-    /* Op_SrcSrc    */  {   mr,  mri,  0,    1  },
-    /* Op_SrcSrcF   */  {   mr,  mri,  0,    1, Clb_Flags },
-    /* Op_SrcSrcFW  */  {   mr,  mri,  0,    Word_Types, Clb_Flags },
-    /* Op_SrcSrcSSEF*/  {   sse, ssem, 0,    0, Clb_Flags },
-    /* Op_SrcSrcMMX */  {   mmx, mmx,  0, },
-    /* Op_Shift     */  { D|mr,N|shft, 0,/**/1, Clb_Flags }, 
-    /* Op_Branch    */  {   mri },
-    /* Op_CBranch   */  {   imm },
-    /* Op_0         */  {   0,0,0 },
-    /* Op_0_AX      */  {   0,0,0,           0, Clb_SizeAX },
-    /* Op_0_DXAX    */  {   0,0,0,           0, Clb_SizeDXAX }, // but for cwd/cdq -- how do know the size..
-    /* Op_Loop      */  {   imm, 0,    0,    0, Clb_CX },
-    /* Op_Flags     */  {   0,0,0,           0, Clb_Flags },
-    /* Op_F0_ST     */  {   0,0,0,           0, Clb_ST },
-    /* Op_F0_P      */  {   0,0,0,           0, Clb_ST }, // push, pops, etc. not sure how to inform gcc..
-    /* Op_Fs_P      */  {   mem, 0,    0,    0, Clb_ST }, // "
-    /* Op_Fis       */  {   mem, 0,    0,    FPInt_Types }, // only 16bit and 32bit, DMD defaults to 16bit
-    /* Op_Fis_ST    */  {   mem, 0,    0,    FPInt_Types, Clb_ST }, // "
-    /* Op_Fis_P     */  {   mem, 0,    0,    FPInt_Types, Clb_ST }, // push and pop, fild so also 64 bit 
-    /* Op_Fid       */  { D|mem, 0,    0,    FPInt_Types }, // only 16bit and 32bit, DMD defaults to 16bit
-    /* Op_Fid_P     */  { D|mem, 0,    0,    FPInt_Types, Clb_ST }, // push and pop, fild so also 64 bit 
-    /* Op_Ffd       */  { D|mfp, 0,    0,    FP_Types, 0, Next_Form, Op_FfdR }, // only 16bit and 32bit, DMD defaults to 16bit, reg form doesn't need type
-    /* Op_FfdR      */  { D|rfp, 0,    0  }, 
-    /* Op_Ffd_P     */  { D|mfp, 0,    0,    FP_Types, Clb_ST, Next_Form, Op_FfdR_P, }, // pop, fld so also 80 bit, "
-    /* Op_FfdR_P    */  { D|rfp, 0,    0,    0,        Clb_ST },
-    /* Op_Fd_P      */  { D|mem, 0,    0,    0, Clb_ST }, // "
-    /* Op_FdST      */  { D|rfp, 0,    0  },
-    /* Op_FMath     */  {   mfp, 0,    0,    FP_Types, Clb_ST, Next_Form, Op_FdSTiSTi  }, // and only single or double prec
-    /* Op_FdSTiSTi  */  { D|rfp, rfp,  0, },
-    /* Op_FPMath    */  { D|rfp, rfp,  0,    0,        Clb_ST, Next_Form, Op_F0_P }, // pops
-    /* Op_FCmp      */  {   mfp, 0,    0,    FP_Types, 0,      Next_Form, Op_FCmp1 }, // DMD defaults to float ptr
-    /* Op_FCmp1     */  {   rfp, 0,    0,    0,        0,      Next_Form, Op_0 },
-    /* Op_FCmpP     */  {   mfp, 0,    0,    FP_Types, 0,      Next_Form, Op_FCmpP1 }, // pops
-    /* Op_FCmpP1    */  {   rfp, 0,    0,    0,        0,      Next_Form, Op_F0_P }, // pops
-    /* Op_FCmpFlg   */  {   rfp, rfp,  0,    0,        Clb_Flags },
-    /* Op_FCmpFlgP  */  {   rfp, rfp,  0,    0,        Clb_Flags }, // pops
-    /* Op_fld       */  {   mfp, 0,    0,    FP_Types, Clb_ST, Next_Form, Op_fldR },
-    /* Op_fldR      */  {   rfp, 0,    0,    0,        Clb_ST },
-    /* Op_fxch      */  { D|rfp,D|rfp, 0,    0,        Clb_ST, Next_Form, Op_fxch1 }, // not in intel manual?, but DMD allows it (gas won't), second arg must be ST
-    /* Op_fxch1     */  { D|rfp, 0,    0,    0,        Clb_ST, Next_Form, Op_fxch0 },
-    /* Op_fxch0     */  {   0,   0,    0,    0,        Clb_ST }, // Also clobbers ST(1)
-    /* Op_SizedStack*/  {   0,   0,    0,    0,        Clb_SP }, // type suffix special case
-    /* Op_bound     */  {   mr,  mri,  0,    Word_Types  }, // operands *not* reversed for gas
-    /* Op_bswap     */  { D|r32      },
-    /* Op_cmps      */  {   mem, mem, 0,     1, Clb_DI|Clb_SI|Clb_Flags },
-    /* Op_cmpsd     */  {   0,   0,   0,     0, Clb_DI|Clb_SI|Clb_Flags, Next_Form, Op_DstSrcImmS },
-    /* Op_cmpsX     */  {   0,   0,   0,     0, Clb_DI|Clb_SI|Clb_Flags },
-    /* Op_cmpxchg8b */  { D|mem/*64*/,0,0,   0, Clb_SizeDXAX/*32*/|Clb_Flags, Out_Mnemonic, Mn_cmpxchg8b },
-    /* Op_cmpxchg   */  { D|mr,  reg, 0,     1, Clb_SizeAX|Clb_Flags },
-    /* Op_cpuid     */  {   0,0,0 },    // Clobbers eax, ebx, ecx, and edx. Handled specially below.
-    /* Op_enter     */  {   imm, imm }, // operands *not* reversed for gas, %% inform gcc of EBP clobber?, 
-    /* Op_fdisi     */  {   0,0,0,           0, 0, Out_Mnemonic, Mn_fdisi },
-    /* Op_feni      */  {   0,0,0,           0, 0, Out_Mnemonic, Mn_feni },
-    /* Op_fsetpm    */  {   0,0,0,           0, 0, Out_Mnemonic, Mn_fsetpm },
-    /* Op_fXstsw    */  { D|mr,  0,   0,     }, // ax is the only allowed register
-    /* Op_imul      */  { D|reg, mr,  imm,   1, Clb_Flags, Next_Form, Op_imul2 }, // 16/32 only
-    /* Op_imul2     */  { D|reg, mri, 0,     1, Clb_Flags, Next_Form, Op_imul1 }, // 16/32 only
-    /* Op_imul1     */  {   mr,  0,   0,     1, Clb_Flags|Clb_SizeDXAX },
-    /* Op_in        */  { D|ax,N|port,0,     1  },        
-    /* Op_ins       */  {   mem,N|dx, 0,     1, Clb_DI }, // can't override ES segment for this one
-    /* Op_insX      */  {   0,   0,   0,     0, Clb_DI }, // output segment overrides %% needs work
-    /* Op_iret      */  {   0,0,0,           0, 0, Out_Mnemonic, Mn_iretw },
-    /* Op_iretd     */  {   0,0,0,           0, 0, Out_Mnemonic, Mn_iret },
-    /* Op_lods      */  {   mem, 0,   0,     1, Clb_SI },
-    /* Op_lodsX     */  {   0,   0,   0,     0, Clb_SI },
-    /* Op_movs      */  {   mem, mem, 0,     1, Clb_DI|Clb_SI }, // only src/DS can be overridden
-    /* Op_movsd     */  {   0,   0,   0,     0, Clb_DI|Clb_SI, Next_Form, Op_DstSrcSSE }, // %% gas doesn't accept movsd .. has to movsl
-    /* Op_movsX     */  {   0,   0,   0,     0, Clb_DI|Clb_SI },
-    /* Op_movsx     */  { D|reg, mr,  0,     1 }, // type suffix is special case
-    /* Op_movzx     */  { D|reg, mr,  0,     1 }, // type suffix is special case
-    /* Op_mul       */  { U|ax,  mr,  0,     1, Clb_SizeDXAX|Clb_Flags, Next_Form, Op_Src_DXAXF },
-    /* Op_out       */  { N|port,ax,  0,     1  },        
-    /* Op_outs      */  { N|dx,  mem, 0,     1, Clb_SI },
-    /* Op_outsX     */  {   0,   0,   0,     0, Clb_SI },
-    /* Op_push      */  {   mri, 0,    0,    0, Clb_SP }, // would be Op_SrcW, but DMD defaults to 32-bit for immediate form
-    /* Op_ret       */  {   imm, 0,   0,     0, 0, Next_Form, Op_0  }, 
-    /* Op_retf      */  {   0,   0,   0,     0, 0, Out_Mnemonic, Mn_lret  },
-    /* Op_scas      */  {   mem, 0,   0,     1, Clb_DI|Clb_Flags },
-    /* Op_scasX     */  {   0,   0,   0,     0, Clb_DI|Clb_Flags },
-    /* Op_stos      */  {   mem, 0,   0,     1, Clb_DI },
-    /* Op_stosX     */  {   0,   0,   0,     0, Clb_DI },
-    /* Op_xlat      */  {   mem, 0,   0,     0, Clb_SizeAX }
-    
-    /// * Op_arpl      */  { D|mr,  reg }, // 16 only -> DstSrc
-    /// * Op_bsX       */  {   rw,  mrw,  0,    1, Clb_Flags },//->srcsrcf 
-    /// * Op_bt        */  {   mrw, riw,  0,    1, Clb_Flags },//->srcsrcf
-    /// * Op_btX       */  { D|mrw, riw,  0,    1, Clb_Flags },//->dstsrcf .. immediate does not contribute to size
-    /// * Op_cmovCC    */  { D|rw,  mrw,  0,    1 } // ->dstsrc
-};
+    static AsmOpInfo asmOpInfo[N_AsmOpInfo] =
+    {
+        /* Op_Invalid   */  {},
+        /* Op_Adjust    */  { 0,0,0,             0, Clb_EAX /*just AX*/ },
+        /* Op_Dst       */  { D|mr,  0,    0,    1  },
+        /* Op_Upd       */  { U|mr,  0,    0,    1  },
+        /* Op_DstW      */  { D|mr,  0,    0,    Word_Types  },
+        /* Op_DstF      */  { D|mr,  0,    0,    1, Clb_Flags },
+        /* Op_UpdF      */  { U|mr,  0,    0,    1, Clb_Flags },
+        /* Op_DstSrc    */  { D|mr,  mri,  0,/**/1  },
+        /* Op_DstSrcF   */  { D|mr,  mri,  0,/**/1, Clb_Flags },
+        /* Op_UpdSrcF   */  { U|mr,  mri,  0,/**/1, Clb_Flags },
+        /* Op_DstSrcFW  */  { D|mr,  mri,  0,/**/Word_Types, Clb_Flags },
+        /* Op_UpdSrcFW  */  { U|mr,  mri,  0,/**/Word_Types, Clb_Flags },
+        /* Op_DstSrcSSE */  { U|sse, ssem, 0     },  // some may not be update %%
+        /* Op_DstSrcMMX */  { U|mmx, mmxm, 0     },  // some may not be update %%
+        /* Op_DstSrcImmS*/  { U|sse, ssem, N|imm  }, // some may not be update %%
+        /* Op_DstSrcImmM*/  { U|mmx, mmxm, N|imm  }, // some may not be update %%
+        /* Op_UpdSrcShft*/  { U|mr,  reg,  N|shft, 1, Clb_Flags }, // 16/32 only
+        /* Op_DstSrcNT  */  { D|mr,  mr,   0,    0 }, // used for movd .. operands can be rm32,sse,mmx
+        /* Op_UpdSrcNT  */  { U|mr,  mr,   0,    0 }, // used for movd .. operands can be rm32,sse,mmx
+        /* Op_DstMemNT  */  { D|mem, 0,    0     },
+        /* Op_DstRMBNT  */  { D|mr,  0,    0,    Byte_NoType },
+        /* Op_DstRMWNT  */  { D|mr,  0,    0     },
+        /* Op_UpdUpd    */  { U|mr,U|mr,   0,/**/1  },
+        /* Op_UpdUpdF   */  { U|mr,U|mr,   0,/**/1, Clb_Flags },
+        /* Op_Src       */  {   mri, 0,    0,    1  },
+        /* Op_SrcRMWNT  */  {   mr,  0,    0,    0  },
+        /* Op_SrcW      */  {   mri, 0,    0,    Word_Types  },
+        /* Op_SrcImm    */  {   imm },
+        /* Op_Src_DXAXF */  {   mr,  0,    0,    1, Clb_SizeDXAX|Clb_Flags },
+        /* Op_SrcMemNT  */  {   mem, 0,    0     },
+        /* Op_SrcMemNTF */  {   mem, 0,    0,    0, Clb_Flags },
+        /* Op_SrcSrc    */  {   mr,  mri,  0,    1  },
+        /* Op_SrcSrcF   */  {   mr,  mri,  0,    1, Clb_Flags },
+        /* Op_SrcSrcFW  */  {   mr,  mri,  0,    Word_Types, Clb_Flags },
+        /* Op_SrcSrcSSEF*/  {   sse, ssem, 0,    0, Clb_Flags },
+        /* Op_SrcSrcMMX */  {   mmx, mmx,  0, },
+        /* Op_Shift     */  { D|mr,N|shft, 0,/**/1, Clb_Flags },
+        /* Op_Branch    */  {   mri },
+        /* Op_CBranch   */  {   imm },
+        /* Op_0         */  {   0,0,0 },
+        /* Op_0_AX      */  {   0,0,0,           0, Clb_SizeAX },
+        /* Op_0_DXAX    */  {   0,0,0,           0, Clb_SizeDXAX }, // but for cwd/cdq -- how do know the size..
+        /* Op_Loop      */  {   imm, 0,    0,    0, Clb_CX },
+        /* Op_Flags     */  {   0,0,0,           0, Clb_Flags },
+        /* Op_F0_ST     */  {   0,0,0,           0, Clb_ST },
+        /* Op_F0_P      */  {   0,0,0,           0, Clb_ST }, // push, pops, etc. not sure how to inform gcc..
+        /* Op_Fs_P      */  {   mem, 0,    0,    0, Clb_ST }, // "
+        /* Op_Fis       */  {   mem, 0,    0,    FPInt_Types }, // only 16bit and 32bit, DMD defaults to 16bit
+        /* Op_Fis_ST    */  {   mem, 0,    0,    FPInt_Types, Clb_ST }, // "
+        /* Op_Fis_P     */  {   mem, 0,    0,    FPInt_Types, Clb_ST }, // push and pop, fild so also 64 bit
+        /* Op_Fid       */  { D|mem, 0,    0,    FPInt_Types }, // only 16bit and 32bit, DMD defaults to 16bit
+        /* Op_Fid_P     */  { D|mem, 0,    0,    FPInt_Types, Clb_ST }, // push and pop, fild so also 64 bit
+        /* Op_Ffd       */  { D|mfp, 0,    0,    FP_Types, 0, Next_Form, Op_FfdR }, // only 16bit and 32bit, DMD defaults to 16bit, reg form doesn't need type
+        /* Op_FfdR      */  { D|rfp, 0,    0  },
+        /* Op_Ffd_P     */  { D|mfp, 0,    0,    FP_Types, Clb_ST, Next_Form, Op_FfdR_P, }, // pop, fld so also 80 bit, "
+        /* Op_FfdR_P    */  { D|rfp, 0,    0,    0,        Clb_ST },
+        /* Op_Fd_P      */  { D|mem, 0,    0,    0, Clb_ST }, // "
+        /* Op_FdST      */  { D|rfp, 0,    0  },
+        /* Op_FMath     */  {   mfp, 0,    0,    FP_Types, Clb_ST, Next_Form, Op_FdSTiSTi  }, // and only single or double prec
+        /* Op_FdSTiSTi  */  { D|rfp, rfp,  0, },
+        /* Op_FPMath    */  { D|rfp, rfp,  0,    0,        Clb_ST, Next_Form, Op_F0_P }, // pops
+        /* Op_FCmp      */  {   mfp, 0,    0,    FP_Types, 0,      Next_Form, Op_FCmp1 }, // DMD defaults to float ptr
+        /* Op_FCmp1     */  {   rfp, 0,    0,    0,        0,      Next_Form, Op_0 },
+        /* Op_FCmpP     */  {   mfp, 0,    0,    FP_Types, 0,      Next_Form, Op_FCmpP1 }, // pops
+        /* Op_FCmpP1    */  {   rfp, 0,    0,    0,        0,      Next_Form, Op_F0_P }, // pops
+        /* Op_FCmpFlg   */  {   rfp, rfp,  0,    0,        Clb_Flags },
+        /* Op_FCmpFlgP  */  {   rfp, rfp,  0,    0,        Clb_Flags }, // pops
+        /* Op_fld       */  {   mfp, 0,    0,    FP_Types, Clb_ST, Next_Form, Op_fldR },
+        /* Op_fldR      */  {   rfp, 0,    0,    0,        Clb_ST },
+        /* Op_fxch      */  { D|rfp,D|rfp, 0,    0,        Clb_ST, Next_Form, Op_fxch1 }, // not in intel manual?, but DMD allows it (gas won't), second arg must be ST
+        /* Op_fxch1     */  { D|rfp, 0,    0,    0,        Clb_ST, Next_Form, Op_fxch0 },
+        /* Op_fxch0     */  {   0,   0,    0,    0,        Clb_ST }, // Also clobbers ST(1)
+        /* Op_SizedStack*/  {   0,   0,    0,    0,        Clb_SP }, // type suffix special case
+        /* Op_bound     */  {   mr,  mri,  0,    Word_Types  }, // operands *not* reversed for gas
+        /* Op_bswap     */  { D|r32      },
+        /* Op_cmps      */  {   mem, mem, 0,     1, Clb_DI|Clb_SI|Clb_Flags },
+        /* Op_cmpsd     */  {   0,   0,   0,     0, Clb_DI|Clb_SI|Clb_Flags, Next_Form, Op_DstSrcImmS },
+        /* Op_cmpsX     */  {   0,   0,   0,     0, Clb_DI|Clb_SI|Clb_Flags },
+        /* Op_cmpxchg8b */  { D|mem/*64*/,0,0,   0, Clb_SizeDXAX/*32*/|Clb_Flags, Out_Mnemonic, Mn_cmpxchg8b },
+        /* Op_cmpxchg   */  { D|mr,  reg, 0,     1, Clb_SizeAX|Clb_Flags },
+        /* Op_cpuid     */  {   0,0,0 },    // Clobbers eax, ebx, ecx, and edx. Handled specially below.
+        /* Op_enter     */  {   imm, imm }, // operands *not* reversed for gas, %% inform gcc of EBP clobber?,
+        /* Op_fdisi     */  {   0,0,0,           0, 0, Out_Mnemonic, Mn_fdisi },
+        /* Op_feni      */  {   0,0,0,           0, 0, Out_Mnemonic, Mn_feni },
+        /* Op_fsetpm    */  {   0,0,0,           0, 0, Out_Mnemonic, Mn_fsetpm },
+        /* Op_fXstsw    */  { D|mr,  0,   0,     }, // ax is the only allowed register
+        /* Op_imul      */  { D|reg, mr,  imm,   1, Clb_Flags, Next_Form, Op_imul2 }, // 16/32 only
+        /* Op_imul2     */  { D|reg, mri, 0,     1, Clb_Flags, Next_Form, Op_imul1 }, // 16/32 only
+        /* Op_imul1     */  {   mr,  0,   0,     1, Clb_Flags|Clb_SizeDXAX },
+        /* Op_in        */  { D|ax,N|port,0,     1  },
+        /* Op_ins       */  {   mem,N|dx, 0,     1, Clb_DI }, // can't override ES segment for this one
+        /* Op_insX      */  {   0,   0,   0,     0, Clb_DI }, // output segment overrides %% needs work
+        /* Op_iret      */  {   0,0,0,           0, 0, Out_Mnemonic, Mn_iretw },
+        /* Op_iretd     */  {   0,0,0,           0, 0, Out_Mnemonic, Mn_iret },
+        /* Op_lods      */  {   mem, 0,   0,     1, Clb_SI },
+        /* Op_lodsX     */  {   0,   0,   0,     0, Clb_SI },
+        /* Op_movs      */  {   mem, mem, 0,     1, Clb_DI|Clb_SI }, // only src/DS can be overridden
+        /* Op_movsd     */  {   0,   0,   0,     0, Clb_DI|Clb_SI, Next_Form, Op_DstSrcSSE }, // %% gas doesn't accept movsd .. has to movsl
+        /* Op_movsX     */  {   0,   0,   0,     0, Clb_DI|Clb_SI },
+        /* Op_movsx     */  { D|reg, mr,  0,     1 }, // type suffix is special case
+        /* Op_movzx     */  { D|reg, mr,  0,     1 }, // type suffix is special case
+        /* Op_mul       */  { U|ax,  mr,  0,     1, Clb_SizeDXAX|Clb_Flags, Next_Form, Op_Src_DXAXF },
+        /* Op_out       */  { N|port,ax,  0,     1  },
+        /* Op_outs      */  { N|dx,  mem, 0,     1, Clb_SI },
+        /* Op_outsX     */  {   0,   0,   0,     0, Clb_SI },
+        /* Op_push      */  {   mri, 0,    0,    0, Clb_SP }, // would be Op_SrcW, but DMD defaults to 32-bit for immediate form
+        /* Op_ret       */  {   imm, 0,   0,     0, 0, Next_Form, Op_0  },
+        /* Op_retf      */  {   0,   0,   0,     0, 0, Out_Mnemonic, Mn_lret  },
+        /* Op_scas      */  {   mem, 0,   0,     1, Clb_DI|Clb_Flags },
+        /* Op_scasX     */  {   0,   0,   0,     0, Clb_DI|Clb_Flags },
+        /* Op_stos      */  {   mem, 0,   0,     1, Clb_DI },
+        /* Op_stosX     */  {   0,   0,   0,     0, Clb_DI },
+        /* Op_xlat      */  {   mem, 0,   0,     0, Clb_SizeAX }
+
+        /// * Op_arpl      */  { D|mr,  reg }, // 16 only -> DstSrc
+        /// * Op_bsX       */  {   rw,  mrw,  0,    1, Clb_Flags },//->srcsrcf
+        /// * Op_bt        */  {   mrw, riw,  0,    1, Clb_Flags },//->srcsrcf
+        /// * Op_btX       */  { D|mrw, riw,  0,    1, Clb_Flags },//->dstsrcf .. immediate does not contribute to size
+        /// * Op_cmovCC    */  { D|rw,  mrw,  0,    1 } // ->dstsrc
+    };
 
 #undef mri
 #undef mr
@@ -598,2265 +614,2490 @@
 #undef N
 //#undef L
 
-typedef struct {
-    const char  * inMnemonic;
-    AsmOp   asmOp;
-} AsmOpEnt;
-
-/* Some opcodes which have data size restrictions, but we don't check
-
-   cmov, l<segreg> ?, lea, lsl, shld
-
-   todo: push <immediate> is always the 32-bit form, even tho push <mem> is 16-bit
-*/
-
-static AsmOpEnt opData[] = {
-    { "adc",    Op_UpdSrcF },
+    typedef struct
+    {
+        const char  * inMnemonic;
+        AsmOp   asmOp;
+    } AsmOpEnt;
 
-    { "add",    Op_DstSrcNT }, //Op_UpdSrcF },
-    { "addpd",  Op_DstSrcSSE },
-    { "addps",  Op_DstSrcSSE },
-    { "addq",    Op_DstSrcSSE },
-    { "addsd",  Op_DstSrcSSE },
-    { "addss",  Op_DstSrcSSE },
-    { "addsubpd", Op_DstSrcSSE },
-    { "addsubps", Op_DstSrcSSE },    
-    { "and",    Op_UpdSrcF },
-    { "andnpd", Op_DstSrcSSE },
-    { "andnps", Op_DstSrcSSE },
-    { "andpd",  Op_DstSrcSSE },
-    { "andps",  Op_DstSrcSSE },
-    { "bsf",    Op_SrcSrcFW },
-    { "bsr",    Op_SrcSrcFW },
-    { "bswap",  Op_bswap },
-    { "bt",     Op_SrcSrcFW },
-    { "btc",    Op_UpdSrcFW },
-    { "btr",    Op_UpdSrcFW },
-    { "bts",    Op_UpdSrcFW },
-    { "call",   Op_Branch },
-    { "callf",   Op_Branch },
-    { "cbw",    Op_0_AX },
-    { "cdqe",    Op_0_DXAX },
-    { "clc",    Op_Flags },
-    { "cld",    Op_Flags },
-    { "clflush",Op_SrcMemNT },
-    { "cli",    Op_Flags },
-    { "clts",   Op_0 },
-    { "cmc",    Op_Flags },
-    { "cmova",  Op_DstSrc },
-    { "cmovae", Op_DstSrc },
-    { "cmovb",  Op_DstSrc },
-    { "cmovbe", Op_DstSrc },
-    { "cmovc",  Op_DstSrc },
-    { "cmove",  Op_DstSrc },
-    { "cmovg",  Op_DstSrc },
-    { "cmovge", Op_DstSrc },
-    { "cmovl",  Op_DstSrc },
-    { "cmovle", Op_DstSrc },
-    { "cmovna", Op_DstSrc },
-    { "cmovnae",Op_DstSrc },
-    { "cmovnb", Op_DstSrc },
-    { "cmovnbe",Op_DstSrc },
-    { "cmovnc", Op_DstSrc },
-    { "cmovne", Op_DstSrc },
-    { "cmovng", Op_DstSrc },
-    { "cmovnge",Op_DstSrc },
-    { "cmovnl", Op_DstSrc },
-    { "cmovnle",Op_DstSrc },
-    { "cmovno", Op_DstSrc },
-    { "cmovnp", Op_DstSrc },
-    { "cmovns", Op_DstSrc },
-    { "cmovnz", Op_DstSrc },
-    { "cmovo",  Op_DstSrc },
-    { "cmovp",  Op_DstSrc },
-    { "cmovpe", Op_DstSrc },
-    { "cmovpo", Op_DstSrc },
-    { "cmovs",  Op_DstSrc },
-    { "cmovz",  Op_DstSrc },
-    { "cmp",    Op_SrcSrcF },
-    { "cmppd",  Op_DstSrcImmS },
-    { "cmpps",  Op_DstSrcImmS },
-    { "cmps",   Op_cmps  },
-    { "cmpsb",  Op_cmpsX },
-    { "cmpsd",  Op_cmpsd }, // string cmp, and SSE cmp
-    { "cmpss",  Op_DstSrcImmS },
-    { "cmpsw",  Op_cmpsX },
-    { "cmpsq",  Op_cmpsX },
-    /*
-    { "cdqe",  Op_0_DXAX },
-    { "cmpsq",  Op_cmpsX },
-    { "cmpxch16b", Op_cmpxchg16b }, 
-    { "cqo",    Op_0_DXAX },
-    { "lodsq", Op_lodsX },
-    { "movsq", Op_movsX },
-    { "popfq", Op_SizedStack },
-    { "pushfq", Op_SizedStack },
-    { "scasq",  Op_scasX },
-    { "stosq",  Op_stosX },
-    { "iretq", Op_iretd },  
-    { "swapgs", Op_0 },  
-    { "extrq",  Op_Extrq },
-    { "movsxq", Op_movsxq },
-    
-    { "clgi",    Op_Flags },
-    { "invlpga", Op_SrcMemNT },
-    { "rdtscp",  Op_0_DXAX },
-    { "stgi",    Op_Flags },
-    { "sysret", Op_0 },
+    /* Some opcodes which have data size restrictions, but we don't check
+
+       cmov, l<segreg> ?, lea, lsl, shld
+
+       todo: push <immediate> is always the 32-bit form, even tho push <mem> is 16-bit
     */
 
-    { "cmpxch16b", Op_cmpxchg8b },
-    { "cmpxch8b", Op_cmpxchg8b }, // %% DMD opcode typo?
-    { "cmpxchg",  Op_cmpxchg },
-    { "comisd", Op_SrcSrcSSEF },
-    { "comiss", Op_SrcSrcSSEF },
-    { "cpuid",  Op_cpuid },
-    { "cvtdq2pd", Op_DstSrcSSE },
-    { "cvtdq2ps", Op_DstSrcSSE },
-    { "cvtpd2dq", Op_DstSrcSSE },
-    { "cvtpd2pi", Op_DstSrcSSE },
-    { "cvtpd2ps", Op_DstSrcSSE },
-    { "cvtpi2pd", Op_DstSrcSSE },
-    { "cvtpi2ps", Op_DstSrcSSE },
-    { "cvtps2dq", Op_DstSrcSSE },
-    { "cvtps2pd", Op_DstSrcSSE },
-    { "cvtps2pi", Op_DstSrcSSE },
-    { "cvtsd2si", Op_DstSrcSSE },
-    { "cvtsd2ss", Op_DstSrcSSE },
-    { "cvtsi2sd", Op_DstSrcSSE },
-    { "cvtsi2ss", Op_DstSrcSSE },
-    { "cvtss2sd", Op_DstSrcSSE },
-    { "cvtss2si", Op_DstSrcSSE },
-    { "cvttpd2dq", Op_DstSrcSSE },
-    { "cvttpd2pi", Op_DstSrcSSE },
-    { "cvttps2dq", Op_DstSrcSSE },
-    { "cvttps2pi", Op_DstSrcSSE },
-    { "cvttsd2si", Op_DstSrcSSE },
-    { "cvttss2si", Op_DstSrcSSE },
-    { "cwd",  Op_0_DXAX },
-    { "cwde", Op_0_DXAX },
-    //{ "da", Op_ },// dunno what this is -- takes labels?
-    { "db",    Op_db },
-    { "dd",    Op_dd },
-    { "de",    Op_de },
-    { "dec",   Op_UpdF },
-    { "df",    Op_df },
-    { "di",    Op_di },
-    { "div",   Op_Src_DXAXF },
-    { "divpd", Op_DstSrcSSE },
-    { "divps", Op_DstSrcSSE },
-    { "divsd", Op_DstSrcSSE },
-    { "divss", Op_DstSrcSSE },
-    { "dl",    Op_dl },
-    { "dq",    Op_dl },
-    { "ds",    Op_ds },
-    { "dt",    Op_de },
-    { "dw",    Op_ds },
-    { "emms",  Op_0 }, // clobber all mmx/fp?
-    { "enter", Op_enter },
-    { "f2xm1",  Op_F0_ST }, // %% most of these are update...
-    { "fabs",   Op_F0_ST },
-    { "fadd",   Op_FMath },
-    { "faddp",  Op_FPMath },
-    { "fbld",   Op_Fs_P },
-    { "fbstp",  Op_Fd_P },
-    { "fchs",   Op_F0_ST },
-    { "fclex",  Op_0 },
-    { "fcmovb",   Op_FdSTiSTi }, // but only ST(0) can be the destination -- should be FdST0STi
-    { "fcmovbe",  Op_FdSTiSTi },
-    { "fcmove",   Op_FdSTiSTi },
-    { "fcmovnb",  Op_FdSTiSTi },
-    { "fcmovnbe", Op_FdSTiSTi },
-    { "fcmovne",  Op_FdSTiSTi },
-    { "fcmovnu",  Op_FdSTiSTi },
-    { "fcmovu",   Op_FdSTiSTi },
-    { "fcom",   Op_FCmp },
-    { "fcomi",  Op_FCmpFlg  }, 
-    { "fcomip", Op_FCmpFlgP },
-    { "fcomp",  Op_FCmpP },
-    { "fcompp", Op_F0_P },   // pops twice
-    { "fcos",   Op_F0_ST }, 
-    { "fdecstp",Op_F0_P },   // changes stack
-    { "fdisi",  Op_fdisi },
-    { "fdiv",   Op_FMath },
-    { "fdivp",  Op_FPMath }, 
-    { "fdivr",  Op_FMath },
-    { "fdivrp", Op_FPMath },
-    { "feni",   Op_feni },
-    { "ffree",  Op_FdST },
-    { "fiadd",  Op_Fis_ST },
-    { "ficom",  Op_Fis   },
-    { "ficomp", Op_Fis_P },
-    { "fidiv",  Op_Fis_ST },
-    { "fidivr", Op_Fis_ST },
-    { "fild",   Op_Fis_P },
-    { "fimul",  Op_Fis_ST },
-    { "fincstp",Op_F0_P },
-    { "finit",  Op_F0_P },
-    { "fist",   Op_Fid }, // only 16,32bit
-    { "fistp",  Op_Fid_P }, 
-    { "fisttp", Op_Fid_P }, 
-    { "fisub",  Op_Fis_ST },
-    { "fisubr", Op_Fis_ST },
-    { "fld",    Op_fld },
-    { "fld1",   Op_F0_P },
-    { "fldcw",  Op_SrcMemNT },
-    { "fldenv", Op_SrcMemNT },
-    { "fldl2e", Op_F0_P },
-    { "fldl2t", Op_F0_P },
-    { "fldlg2", Op_F0_P },
-    { "fldln2", Op_F0_P },
-    { "fldpi",  Op_F0_P },
-    { "fldz",   Op_F0_P },
-    { "fmul",   Op_FMath },
-    { "fmulp",  Op_FPMath },
-    { "fnclex", Op_0 },
-    { "fndisi", Op_fdisi }, // ??
-    { "fneni",  Op_feni }, // ??
-    { "fninit", Op_0 },
-    { "fnop",   Op_0 },
-    { "fnsave", Op_DstMemNT },
-    { "fnstcw", Op_DstMemNT },
-    { "fnstenv",Op_DstMemNT },
-    { "fnstsw", Op_fXstsw },
-    { "fpatan", Op_F0_P }, // pop and modify new ST
-    { "fprem",  Op_F0_ST }, 
-    { "fprem1", Op_F0_ST }, 
-    { "fptan",  Op_F0_P }, // modify ST and push 1.0
-    { "frndint",Op_F0_ST }, 
-    { "frstor", Op_SrcMemNT }, // but clobbers everything
-    { "fsave",  Op_DstMemNT },
-    { "fscale", Op_F0_ST },
-    { "fsetpm", Op_fsetpm },
-    { "fsin",   Op_F0_ST },
-    { "fsincos",Op_F0_P },
-    { "fsqrt",  Op_F0_ST },
-    { "fst",    Op_Ffd },
-    { "fstcw",  Op_DstMemNT },
-    { "fstenv", Op_DstMemNT },
-    { "fstp",   Op_Ffd_P },
-    { "fstsw",  Op_fXstsw },
-    { "fsub",   Op_FMath },
-    { "fsubp",  Op_FPMath },
-    { "fsubr",  Op_FMath },
-    { "fsubrp", Op_FPMath },
-    { "ftst",   Op_0 },
-    { "fucom",  Op_FCmp },
-    { "fucomi", Op_FCmpFlg },
-    { "fucomip",Op_FCmpFlgP },
-    { "fucomp", Op_FCmpP },
-    { "fucompp",Op_F0_P }, // pops twice
-    { "fwait",  Op_0 },
-    { "fxam",   Op_0 },
-    { "fxch",   Op_fxch },
-    { "fxrstor",Op_SrcMemNT },  // clobbers FP,MMX,SSE
-    { "fxsave", Op_DstMemNT },
-    { "fxtract",Op_F0_P }, // pushes
-    { "fyl2x",  Op_F0_P }, // pops
-    { "fyl2xp1",Op_F0_P }, // pops
-    { "haddpd", Op_DstSrcSSE },
-    { "haddps", Op_DstSrcSSE },
-    { "hlt",  Op_0 },
-    { "hsubpd", Op_DstSrcSSE },
-    { "hsubps", Op_DstSrcSSE },
-    { "idiv", Op_Src_DXAXF },
-    { "imul",   Op_DstSrcNT  },
-    { "in",   Op_in },
-    { "inc",  Op_UpdF },
-    { "ins",  Op_ins },
-    { "insb", Op_insX },
-    { "insd", Op_insX },
-    { "insw", Op_insX },
-    { "int",  Op_SrcImm },
-    { "into", Op_0 },
-    { "invd", Op_0 },
-    { "invlpg", Op_SrcMemNT },
-    { "iret",  Op_iret },
-    { "iretd", Op_iretd },    
-    { "iretq", Op_iretd },    
-    { "ja",    Op_CBranch },
-    { "jae",   Op_CBranch },
-    { "jb",    Op_CBranch },
-    { "jbe",   Op_CBranch },
-    { "jc",    Op_CBranch },
-    { "jcxz",  Op_CBranch },
-    { "je",    Op_CBranch },
-    { "jecxz", Op_CBranch },
-    { "jg",    Op_CBranch },
-    { "jge",   Op_CBranch },
-    { "jl",    Op_CBranch },
-    { "jle",   Op_CBranch },
-    { "jmp",   Op_Branch },
-    { "jmpe",   Op_Branch },
-    { "jmpf",   Op_Branch },
-    { "jna",   Op_CBranch },
-    { "jnae",  Op_CBranch },
-    { "jnb",   Op_CBranch },
-    { "jnbe",  Op_CBranch },
-    { "jnc",   Op_CBranch },
-    { "jne",   Op_CBranch },
-    { "jng",   Op_CBranch },
-    { "jnge",  Op_CBranch },
-    { "jnl",   Op_CBranch },
-    { "jnle",  Op_CBranch },
-    { "jno",   Op_CBranch },
-    { "jnp",   Op_CBranch },
-    { "jns",   Op_CBranch },
-    { "jnz",   Op_CBranch },
-    { "jo",    Op_CBranch },
-    { "jp",    Op_CBranch },
-    { "jpe",   Op_CBranch },
-    { "jpo",   Op_CBranch },
-    { "jrcxz", Op_CBranch },
-    { "js",    Op_CBranch },
-    { "jz",    Op_CBranch },
-    { "lahf",  Op_0_AX },
-    { "lar",   Op_DstSrcFW }, // reg dest only
-    { "lddqu", Op_DstSrcSSE },
-    { "ldmxcsr", Op_SrcMemNT },
-    { "lds",   Op_DstSrc },  // reg dest only
-    { "lea",   Op_DstSrc },  // "
-    { "leaq",   Op_DstSrcSSE },  // "
-    { "leave", Op_0 },       // EBP,ESP clobbers
-    { "lfence",Op_0 },
-    { "lfs",   Op_DstSrc },
-    { "lgdt",  Op_SrcMemNT },
-    { "lgs",   Op_DstSrc },
-    { "lidt",  Op_SrcMemNT },
-    { "lldt",  Op_SrcRMWNT },
-    { "lmsw",  Op_SrcRMWNT },
-    { "lock",  Op_0 },
-    { "lods",  Op_lods },
-    { "lodsb", Op_lodsX },
-    { "lodsd", Op_lodsX },
-    { "lodsw", Op_lodsX },
-    { "lodsq", Op_lodsX },
-    { "loop",  Op_Loop },
-    { "loope", Op_Loop },
-    { "loopne",Op_Loop },
-    { "loopnz",Op_Loop },
-    { "loopz", Op_Loop },
-    { "lsl",   Op_DstSrcFW }, // reg dest only
-    { "lss",   Op_DstSrc },
-    { "ltr",   Op_DstMemNT },
-    { "maskmovdqu", Op_SrcSrcMMX }, // writes to [edi]
-    { "maskmovq",   Op_SrcSrcMMX }, 
-    { "maxpd", Op_DstSrcSSE },
-    { "maxps", Op_DstSrcSSE },
-    { "maxsd", Op_DstSrcSSE },
-    { "maxss", Op_DstSrcSSE },
-    { "mfence",Op_0},
-    { "minpd", Op_DstSrcSSE },
-    { "minps", Op_DstSrcSSE },
-    { "minsd", Op_DstSrcSSE },
-    { "minss", Op_DstSrcSSE },
-    { "monitor", Op_0 },
-    { "mov",   Op_DstSrc },
-    { "movapd",  Op_DstSrcSSE },
-    { "movaps",  Op_DstSrcSSE },
-    { "movb",   Op_DstSrcNT  },
-    { "movd",    Op_DstSrcNT  }, // also mmx and sse
-    { "movddup", Op_DstSrcSSE },
-    { "movdq2q", Op_DstSrcNT }, // mmx/sse
-    { "movdqa",  Op_DstSrcSSE },
-    { "movdqu",  Op_DstSrcSSE },
-    { "movhlps", Op_DstSrcSSE },
-    { "movhpd",  Op_DstSrcSSE },
-    { "movhps",  Op_DstSrcSSE },
-    { "movl",   Op_DstSrc },
-    { "movlhps", Op_DstSrcSSE },
-    { "movlpd",  Op_DstSrcSSE },
-    { "movlps",  Op_DstSrcSSE },
-    { "movmskpd",Op_DstSrcSSE },
-    { "movmskps",Op_DstSrcSSE },
-    { "movntdq", Op_DstSrcNT  }, // limited to sse, but mem dest
-    { "movnti",  Op_DstSrcNT  }, // limited to gpr, but mem dest
-    { "movntpd", Op_DstSrcNT  }, // limited to sse, but mem dest
-    { "movntps", Op_DstSrcNT  }, // limited to sse, but mem dest
-    { "movntq",  Op_DstSrcNT  }, // limited to mmx, but mem dest
-    { "movq",    Op_DstSrcNT  }, // limited to sse and mmx
-    { "movq2dq", Op_DstSrcNT  }, // limited to sse <- mmx regs
-    { "movs",  Op_movs },
-    { "movsb", Op_movsX },
-    { "movsd", Op_movsd },
-    { "movsq", Op_movsd },
-    { "movshdup", Op_DstSrcSSE },
-    { "movsldup", Op_DstSrcSSE },
-    { "movss", Op_DstSrcSSE },
-    { "movsw", Op_movsX },
-    { "movsx", Op_movsx }, // word-only, reg dest
-    { "movsxd", Op_movsx }, 
-    { "movupd",Op_DstSrcSSE },
-    { "movups",Op_DstSrcSSE },
-    { "movzbl",   Op_DstSrcNT  },
-    { "movzx", Op_movzx },
-    { "mul",   Op_DstSrcNT  },
-    { "mulpd", Op_DstSrcSSE },
-    { "mulps", Op_DstSrcSSE },
-    { "mulsd", Op_DstSrcSSE },
-    { "mulss", Op_DstSrcSSE },
-    { "mwait", Op_0 },
-    { "naked", Op_Naked },
-    { "neg",   Op_UpdF },
-    { "nop",   Op_0 },
-    { "not",   Op_Upd },
-    { "or",    Op_UpdSrcF },
-    { "orpd",  Op_DstSrcSSE },
-    { "orps",  Op_DstSrcSSE },
-    { "out",   Op_out },
-    { "outs",  Op_outs },
-    { "outsb", Op_outsX },
-    { "outsd", Op_outsX },
-    { "outsw", Op_outsX },
-    { "pabsb",    Op_DstSrcSSE },
-    { "pabsw",    Op_DstSrcSSE },
-    { "pabsq",    Op_DstSrcSSE },
-    { "packssdw", Op_DstSrcMMX }, // %% also SSE
-    { "packsswb", Op_DstSrcMMX },
-    { "packuswb", Op_DstSrcMMX },
-    { "paddb",    Op_DstSrcMMX },
-    { "paddd",    Op_DstSrcMMX },
-    { "paddq",    Op_DstSrcMMX },
-    { "paddsb",   Op_DstSrcMMX },
-    { "paddsw",   Op_DstSrcMMX },
-    { "paddusb",  Op_DstSrcMMX },
-    { "paddusw",  Op_DstSrcMMX },
-    { "paddw",    Op_DstSrcMMX },
-    { "palignr",     Op_DstSrcSSE },
-    { "pand",     Op_DstSrcMMX },
-    { "pandn",    Op_DstSrcMMX },
-    { "pause",    Op_DstSrcMMX },
-    { "pavgb",    Op_DstSrcMMX },
-    { "pavgw",    Op_DstSrcMMX },
-    { "pcmpeqb",  Op_DstSrcMMX },
-    { "pcmpeqd",  Op_DstSrcMMX },
-    { "pcmpeqw",  Op_DstSrcMMX },
-    { "pcmpgtb",  Op_DstSrcMMX },
-    { "pcmpgtd",  Op_DstSrcMMX },
-    { "pcmpgtw",  Op_DstSrcMMX },
-    { "pextrw",   Op_DstSrcImmM }, // gpr32 dest
-    { "phaddd",     Op_DstSrcSSE },
-    { "phaddsw",     Op_DstSrcSSE },
-    { "phaddw",     Op_DstSrcSSE },
-    { "phsubd",     Op_DstSrcSSE },
-    { "phsubsw",     Op_DstSrcSSE },
-    { "phsubw",     Op_DstSrcSSE },
-    { "pinsrw",   Op_DstSrcImmM }, // gpr32(16), mem16 src, sse too
-    { "pmaddubsw",  Op_DstSrcSSE },
-    { "pmaddwd",  Op_DstSrcMMX },
-    { "pmaxsw",   Op_DstSrcMMX },
-    { "pmaxub",   Op_DstSrcMMX },
-    { "pminsw",   Op_DstSrcMMX },
-    { "pminub",   Op_DstSrcMMX },
-    { "pmovmskb", Op_DstSrcMMX },
-    { "pmulhrsw",  Op_DstSrcMMX },
-    { "pmulhuw",  Op_DstSrcMMX },
-    { "pmulhw",   Op_DstSrcMMX },
-    { "pmullw",   Op_DstSrcMMX },
-    { "pmuludq",  Op_DstSrcMMX }, // also sse
-    { "popf",     Op_SizedStack },  // rewrite the insn with a special case
-    { "popfq",    Op_SizedStack }, 
-    { "popq",    Op_push }, 
-    { "por",      Op_DstSrcMMX },
-    { "prefetchnta", Op_SrcMemNT },
-    { "prefetcht0",  Op_SrcMemNT },
-    { "prefetcht1",  Op_SrcMemNT },
-    { "prefetcht2",  Op_SrcMemNT },
-    { "psadbw",   Op_DstSrcMMX },
-    { "pshufb",   Op_DstSrcImmM },
-    { "pshufd",   Op_DstSrcImmM },
-    { "pshufhw",  Op_DstSrcImmM },
-    { "pshuflw",  Op_DstSrcImmM },
-    { "pshufw",   Op_DstSrcImmM },
-    { "psignb",   Op_DstSrcSSE },
-    { "psignd",   Op_DstSrcSSE },
-    { "psignw",   Op_DstSrcSSE },
-    { "pslld",    Op_DstSrcMMX }, // immediate operands...
-    { "pslldq",   Op_DstSrcMMX },
-    { "psllq",    Op_DstSrcMMX },
-    { "psllw",    Op_DstSrcMMX },
-    { "psrad",    Op_DstSrcMMX },
-    { "psraw",    Op_DstSrcMMX },
-    { "psrld",    Op_DstSrcMMX },
-    { "psrldq",   Op_DstSrcMMX },
-    { "psrlq",    Op_DstSrcMMX },
-    { "psrlw",    Op_DstSrcMMX },
-    { "psubb",    Op_DstSrcMMX },
-    { "psubd",    Op_DstSrcMMX },
-    { "psubq",    Op_DstSrcMMX },
-    { "psubsb",   Op_DstSrcMMX },
-    { "psubsw",   Op_DstSrcMMX },
-    { "psubusb",  Op_DstSrcMMX },
-    { "psubusw",  Op_DstSrcMMX },
-    { "psubw",    Op_DstSrcMMX },
-    { "punpckhbw", Op_DstSrcMMX },
-    { "punpckhdq", Op_DstSrcMMX },
-    { "punpckhqdq",Op_DstSrcMMX },
-    { "punpckhwd", Op_DstSrcMMX },
-    { "punpcklbw", Op_DstSrcMMX },
-    { "punpckldq", Op_DstSrcMMX },
-    { "punpcklqdq",Op_DstSrcMMX },
-    { "punpcklwd", Op_DstSrcMMX },
-    { "pushf",  Op_SizedStack },
-    { "pushfq", Op_SizedStack },
-    { "pushq", Op_push },
-    { "pxor",   Op_DstSrcMMX },
-    { "rcl",    Op_Shift }, // limited src operands -- change to shift
-    { "rcpps",  Op_DstSrcSSE },
-    { "rcpss",  Op_DstSrcSSE },
-    { "rcr",    Op_Shift },
-    { "rdmsr",  Op_0_DXAX },
-    { "rdpmc",  Op_0_DXAX },
-    { "rdtsc",  Op_0_DXAX },
-    { "rep",    Op_0 },
-    { "repe",   Op_0 },
-    { "repne",  Op_0 },
-    { "repnz",  Op_0 },
-    { "repz",   Op_0 },
-    { "ret",    Op_ret },
-    { "retf",   Op_retf },
-    { "retn",   Op_retf },
-    { "rol",    Op_Shift },
-    { "ror",    Op_Shift },
-    { "rsm",    Op_0 },
-    { "rsqrtps", Op_DstSrcSSE },
-    { "rsqrtss", Op_DstSrcSSE },
-    { "sahf",   Op_Flags },
-    { "sal",    Op_Shift },
-    { "salq",   Op_DstSrcNT  },
-    { "sar",    Op_Shift },
-    { "sbb",    Op_UpdSrcF },
-    { "scas",   Op_scas },
-    { "scasb",  Op_scasX },
-    { "scasd",  Op_scasX },
-    { "scasw",  Op_scasX },
-    { "scasq",  Op_scasX },
-    { "seta",   Op_DstRMBNT }, // also gpr8
-    { "setae",  Op_DstRMBNT },
-    { "setb",   Op_DstRMBNT },
-    { "setbe",  Op_DstRMBNT },
-    { "setc",   Op_DstRMBNT },
-    { "sete",   Op_DstRMBNT },
-    { "setg",   Op_DstRMBNT },
-    { "setge",  Op_DstRMBNT },
-    { "setl",   Op_DstRMBNT },
-    { "setle",  Op_DstRMBNT },
-    { "setna",  Op_DstRMBNT },
-    { "setnae", Op_DstRMBNT },
-    { "setnb",  Op_DstRMBNT },
-    { "setnbe", Op_DstRMBNT },
-    { "setnc",  Op_DstRMBNT },
-    { "setne",  Op_DstRMBNT },
-    { "setng",  Op_DstRMBNT },
-    { "setnge", Op_DstRMBNT },
-    { "setnl",  Op_DstRMBNT },
-    { "setnle", Op_DstRMBNT },
-    { "setno",  Op_DstRMBNT },
-    { "setnp",  Op_DstRMBNT },
-    { "setns",  Op_DstRMBNT },
-    { "setnz",  Op_DstRMBNT },
-    { "seto",   Op_DstRMBNT },
-    { "setp",   Op_DstRMBNT },
-    { "setpe",  Op_DstRMBNT },
-    { "setpo",  Op_DstRMBNT },
-    { "sets",   Op_DstRMBNT },
-    { "setz",   Op_DstRMBNT },
-    { "sfence", Op_0 },
-    { "sgdt",   Op_DstMemNT },
-    { "shl",    Op_Shift },
-    { "shld",   Op_UpdSrcShft },
-    { "shr",    Op_Shift },
-    { "shrd",   Op_UpdSrcShft },
-    { "shufpd", Op_DstSrcImmS },
-    { "shufps", Op_DstSrcImmS },
-    { "sidt",   Op_DstMemNT },
-    { "sldt",   Op_DstRMWNT },
-    { "smsw",   Op_DstRMWNT },
-    { "sqrtpd", Op_DstSrcSSE },
-    { "sqrtps", Op_DstSrcSSE },
-    { "sqrtsd", Op_DstSrcSSE },
-    { "sqrtss", Op_DstSrcSSE },
-    { "stc",    Op_Flags },
-    { "std",    Op_Flags },
-    { "sti",    Op_Flags },
-    { "stmxcsr",Op_DstMemNT },
-    { "stos",   Op_stos },
-    { "stosb",  Op_stosX },
-    { "stosd",  Op_stosX },
-    { "stosw",  Op_stosX },
-    { "stosq",  Op_stosX },
-    { "str",    Op_DstMemNT }, // also r16
-    { "sub",    Op_UpdSrcF },
-    { "subpd",  Op_DstSrcSSE },
-    { "subps",  Op_DstSrcSSE },
-    { "subq",    Op_DstSrcSSE },
-    { "subsd",  Op_DstSrcSSE },
-    { "subss",  Op_DstSrcSSE },
-    { "swapgs",  Op_DstSrcSSE },
-    { "sysenter",Op_0 },
-    { "sysexit", Op_0 },
-    { "sysret", Op_0 },
-    { "testl",   Op_DstSrcNT  },
-    { "ucomisd", Op_SrcSrcSSEF },
-    { "ucomiss", Op_SrcSrcSSEF },
-    { "ud2",     Op_0 },
-    { "unpckhpd", Op_DstSrcSSE },
-    { "unpckhps", Op_DstSrcSSE },
-    { "unpcklpd", Op_DstSrcSSE },
-    { "unpcklps", Op_DstSrcSSE },
-    { "verr",   Op_SrcMemNTF },
-    { "verw",   Op_SrcMemNTF },
-    { "wbinvd", Op_0 },
-    { "wrmsr",  Op_0 },
-    { "xadd",   Op_UpdUpdF },
-    { "xchg",   Op_UpdUpd },
-    { "xlat",   Op_xlat },
-    { "xlatb",  Op_0_AX },
-    { "xor",    Op_DstSrcF },
-    { "xorpd",  Op_DstSrcSSE },
-    { "xorps",  Op_DstSrcSSE },
-    { "xorq",   Op_DstSrcNT  },
-};
+    static AsmOpEnt opData[] =
+    {
+        { "adc",    Op_UpdSrcF },
+
+        { "add",    Op_DstSrcNT }, //Op_UpdSrcF },
+        { "addpd",  Op_DstSrcSSE },
+        { "addps",  Op_DstSrcSSE },
+        { "addq",    Op_DstSrcSSE },
+        { "addsd",  Op_DstSrcSSE },
+        { "addss",  Op_DstSrcSSE },
+        { "addsubpd", Op_DstSrcSSE },
+        { "addsubps", Op_DstSrcSSE },
+        { "and",    Op_UpdSrcF },
+        { "andnpd", Op_DstSrcSSE },
+        { "andnps", Op_DstSrcSSE },
+        { "andpd",  Op_DstSrcSSE },
+        { "andps",  Op_DstSrcSSE },
+        { "bsf",    Op_SrcSrcFW },
+        { "bsr",    Op_SrcSrcFW },
+        { "bswap",  Op_bswap },
+        { "bt",     Op_SrcSrcFW },
+        { "btc",    Op_UpdSrcFW },
+        { "btr",    Op_UpdSrcFW },
+        { "bts",    Op_UpdSrcFW },
+        { "call",   Op_Branch },
+        { "callf",   Op_Branch },
+        { "cbw",    Op_0_AX },
+        { "cdqe",    Op_0_DXAX },
+        { "clc",    Op_Flags },
+        { "cld",    Op_Flags },
+        { "clflush",Op_SrcMemNT },
+        { "cli",    Op_Flags },
+        { "clts",   Op_0 },
+        { "cmc",    Op_Flags },
+        { "cmova",  Op_DstSrc },
+        { "cmovae", Op_DstSrc },
+        { "cmovb",  Op_DstSrc },
+        { "cmovbe", Op_DstSrc },
+        { "cmovc",  Op_DstSrc },
+        { "cmove",  Op_DstSrc },
+        { "cmovg",  Op_DstSrc },
+        { "cmovge", Op_DstSrc },
+        { "cmovl",  Op_DstSrc },
+        { "cmovle", Op_DstSrc },
+        { "cmovna", Op_DstSrc },
+        { "cmovnae",Op_DstSrc },
+        { "cmovnb", Op_DstSrc },
+        { "cmovnbe",Op_DstSrc },
+        { "cmovnc", Op_DstSrc },
+        { "cmovne", Op_DstSrc },
+        { "cmovng", Op_DstSrc },
+        { "cmovnge",Op_DstSrc },
+        { "cmovnl", Op_DstSrc },
+        { "cmovnle",Op_DstSrc },
+        { "cmovno", Op_DstSrc },
+        { "cmovnp", Op_DstSrc },
+        { "cmovns", Op_DstSrc },
+        { "cmovnz", Op_DstSrc },
+        { "cmovo",  Op_DstSrc },
+        { "cmovp",  Op_DstSrc },
+        { "cmovpe", Op_DstSrc },
+        { "cmovpo", Op_DstSrc },
+        { "cmovs",  Op_DstSrc },
+        { "cmovz",  Op_DstSrc },
+        { "cmp",    Op_SrcSrcF },
+        { "cmppd",  Op_DstSrcImmS },
+        { "cmpps",  Op_DstSrcImmS },
+        { "cmps",   Op_cmps  },
+        { "cmpsb",  Op_cmpsX },
+        { "cmpsd",  Op_cmpsd }, // string cmp, and SSE cmp
+        { "cmpss",  Op_DstSrcImmS },
+        { "cmpsw",  Op_cmpsX },
+        { "cmpsq",  Op_cmpsX },
+        /*
+        { "cdqe",  Op_0_DXAX },
+        { "cmpsq",  Op_cmpsX },
+        { "cmpxch16b", Op_cmpxchg16b },
+        { "cqo",    Op_0_DXAX },
+        { "lodsq", Op_lodsX },
+        { "movsq", Op_movsX },
+        { "popfq", Op_SizedStack },
+        { "pushfq", Op_SizedStack },
+        { "scasq",  Op_scasX },
+        { "stosq",  Op_stosX },
+        { "iretq", Op_iretd },
+        { "swapgs", Op_0 },
+        { "extrq",  Op_Extrq },
+        { "movsxq", Op_movsxq },
+
+        { "clgi",    Op_Flags },
+        { "invlpga", Op_SrcMemNT },
+        { "rdtscp",  Op_0_DXAX },
+        { "stgi",    Op_Flags },
+        { "sysret", Op_0 },
+        */
 
-typedef enum {
-    Default_Ptr = 0,
-    Byte_Ptr = 1,
-    Short_Ptr = 2,
-    Int_Ptr = 4,
-    QWord_Ptr =  8,
-    Float_Ptr = 4,
-    Double_Ptr = 8,
-    Extended_Ptr = 10,
-    Near_Ptr = 98,
-    Far_Ptr = 99,
-    N_PtrTypes
-} PtrType;
-
-static const int N_PtrNames = 8;
-static const char * ptrTypeNameTable[N_PtrNames] = {
-    "word", "dword", "qword",
-    "float", "double", "extended",
-    "near",  "far"
-};
+        { "cmpxch16b", Op_cmpxchg8b },
+        { "cmpxch8b", Op_cmpxchg8b }, // %% DMD opcode typo?
+        { "cmpxchg",  Op_cmpxchg },
+        { "comisd", Op_SrcSrcSSEF },
+        { "comiss", Op_SrcSrcSSEF },
+        { "cpuid",  Op_cpuid },
+        { "cvtdq2pd", Op_DstSrcSSE },
+        { "cvtdq2ps", Op_DstSrcSSE },
+        { "cvtpd2dq", Op_DstSrcSSE },
+        { "cvtpd2pi", Op_DstSrcSSE },
+        { "cvtpd2ps", Op_DstSrcSSE },
+        { "cvtpi2pd", Op_DstSrcSSE },
+        { "cvtpi2ps", Op_DstSrcSSE },
+        { "cvtps2dq", Op_DstSrcSSE },
+        { "cvtps2pd", Op_DstSrcSSE },
+        { "cvtps2pi", Op_DstSrcSSE },
+        { "cvtsd2si", Op_DstSrcSSE },
+        { "cvtsd2ss", Op_DstSrcSSE },
+        { "cvtsi2sd", Op_DstSrcSSE },
+        { "cvtsi2ss", Op_DstSrcSSE },
+        { "cvtss2sd", Op_DstSrcSSE },
+        { "cvtss2si", Op_DstSrcSSE },
+        { "cvttpd2dq", Op_DstSrcSSE },
+        { "cvttpd2pi", Op_DstSrcSSE },
+        { "cvttps2dq", Op_DstSrcSSE },
+        { "cvttps2pi", Op_DstSrcSSE },
+        { "cvttsd2si", Op_DstSrcSSE },
+        { "cvttss2si", Op_DstSrcSSE },
+        { "cwd",  Op_0_DXAX },
+        { "cwde", Op_0_DXAX },
+        //{ "da", Op_ },// dunno what this is -- takes labels?
+        { "db",    Op_db },
+        { "dd",    Op_dd },
+        { "de",    Op_de },
+        { "dec",   Op_UpdF },
+        { "df",    Op_df },
+        { "di",    Op_di },
+        { "div",   Op_Src_DXAXF },
+        { "divpd", Op_DstSrcSSE },
+        { "divps", Op_DstSrcSSE },
+        { "divsd", Op_DstSrcSSE },
+        { "divss", Op_DstSrcSSE },
+        { "dl",    Op_dl },
+        { "dq",    Op_dl },
+        { "ds",    Op_ds },
+        { "dt",    Op_de },
+        { "dw",    Op_ds },
+        { "emms",  Op_0 }, // clobber all mmx/fp?
+        { "enter", Op_enter },
+        { "f2xm1",  Op_F0_ST }, // %% most of these are update...
+        { "fabs",   Op_F0_ST },
+        { "fadd",   Op_FMath },
+        { "faddp",  Op_FPMath },
+        { "fbld",   Op_Fs_P },
+        { "fbstp",  Op_Fd_P },
+        { "fchs",   Op_F0_ST },
+        { "fclex",  Op_0 },
+        { "fcmovb",   Op_FdSTiSTi }, // but only ST(0) can be the destination -- should be FdST0STi
+        { "fcmovbe",  Op_FdSTiSTi },
+        { "fcmove",   Op_FdSTiSTi },
+        { "fcmovnb",  Op_FdSTiSTi },
+        { "fcmovnbe", Op_FdSTiSTi },
+        { "fcmovne",  Op_FdSTiSTi },
+        { "fcmovnu",  Op_FdSTiSTi },
+        { "fcmovu",   Op_FdSTiSTi },
+        { "fcom",   Op_FCmp },
+        { "fcomi",  Op_FCmpFlg  },
+        { "fcomip", Op_FCmpFlgP },
+        { "fcomp",  Op_FCmpP },
+        { "fcompp", Op_F0_P },   // pops twice
+        { "fcos",   Op_F0_ST },
+        { "fdecstp",Op_F0_P },   // changes stack
+        { "fdisi",  Op_fdisi },
+        { "fdiv",   Op_FMath },
+        { "fdivp",  Op_FPMath },
+        { "fdivr",  Op_FMath },
+        { "fdivrp", Op_FPMath },
+        { "feni",   Op_feni },
+        { "ffree",  Op_FdST },
+        { "fiadd",  Op_Fis_ST },
+        { "ficom",  Op_Fis   },
+        { "ficomp", Op_Fis_P },
+        { "fidiv",  Op_Fis_ST },
+        { "fidivr", Op_Fis_ST },
+        { "fild",   Op_Fis_P },
+        { "fimul",  Op_Fis_ST },
+        { "fincstp",Op_F0_P },
+        { "finit",  Op_F0_P },
+        { "fist",   Op_Fid }, // only 16,32bit
+        { "fistp",  Op_Fid_P },
+        { "fisttp", Op_Fid_P },
+        { "fisub",  Op_Fis_ST },
+        { "fisubr", Op_Fis_ST },
+        { "fld",    Op_fld },
+        { "fld1",   Op_F0_P },
+        { "fldcw",  Op_SrcMemNT },
+        { "fldenv", Op_SrcMemNT },
+        { "fldl2e", Op_F0_P },
+        { "fldl2t", Op_F0_P },
+        { "fldlg2", Op_F0_P },
+        { "fldln2", Op_F0_P },
+        { "fldpi",  Op_F0_P },
+        { "fldz",   Op_F0_P },
+        { "fmul",   Op_FMath },
+        { "fmulp",  Op_FPMath },
+        { "fnclex", Op_0 },
+        { "fndisi", Op_fdisi }, // ??
+        { "fneni",  Op_feni }, // ??
+        { "fninit", Op_0 },
+        { "fnop",   Op_0 },
+        { "fnsave", Op_DstMemNT },
+        { "fnstcw", Op_DstMemNT },
+        { "fnstenv",Op_DstMemNT },
+        { "fnstsw", Op_fXstsw },
+        { "fpatan", Op_F0_P }, // pop and modify new ST
+        { "fprem",  Op_F0_ST },
+        { "fprem1", Op_F0_ST },
+        { "fptan",  Op_F0_P }, // modify ST and push 1.0
+        { "frndint",Op_F0_ST },
+        { "frstor", Op_SrcMemNT }, // but clobbers everything
+        { "fsave",  Op_DstMemNT },
+        { "fscale", Op_F0_ST },
+        { "fsetpm", Op_fsetpm },
+        { "fsin",   Op_F0_ST },
+        { "fsincos",Op_F0_P },
+        { "fsqrt",  Op_F0_ST },
+        { "fst",    Op_Ffd },
+        { "fstcw",  Op_DstMemNT },
+        { "fstenv", Op_DstMemNT },
+        { "fstp",   Op_Ffd_P },
+        { "fstsw",  Op_fXstsw },
+        { "fsub",   Op_FMath },
+        { "fsubp",  Op_FPMath },
+        { "fsubr",  Op_FMath },
+        { "fsubrp", Op_FPMath },
+        { "ftst",   Op_0 },
+        { "fucom",  Op_FCmp },
+        { "fucomi", Op_FCmpFlg },
+        { "fucomip",Op_FCmpFlgP },
+        { "fucomp", Op_FCmpP },
+        { "fucompp",Op_F0_P }, // pops twice
+        { "fwait",  Op_0 },
+        { "fxam",   Op_0 },
+        { "fxch",   Op_fxch },
+        { "fxrstor",Op_SrcMemNT },  // clobbers FP,MMX,SSE
+        { "fxsave", Op_DstMemNT },
+        { "fxtract",Op_F0_P }, // pushes
+        { "fyl2x",  Op_F0_P }, // pops
+        { "fyl2xp1",Op_F0_P }, // pops
+        { "haddpd", Op_DstSrcSSE },
+        { "haddps", Op_DstSrcSSE },
+        { "hlt",  Op_0 },
+        { "hsubpd", Op_DstSrcSSE },
+        { "hsubps", Op_DstSrcSSE },
+        { "idiv", Op_Src_DXAXF },
+        { "imul",   Op_DstSrcNT  },
+        { "in",   Op_in },
+        { "inc",  Op_UpdF },
+        { "ins",  Op_ins },
+        { "insb", Op_insX },
+        { "insd", Op_insX },
+        { "insw", Op_insX },
+        { "int",  Op_SrcImm },
+        { "into", Op_0 },
+        { "invd", Op_0 },
+        { "invlpg", Op_SrcMemNT },
+        { "iret",  Op_iret },
+        { "iretd", Op_iretd },
+        { "iretq", Op_iretd },
+        { "ja",    Op_CBranch },
+        { "jae",   Op_CBranch },
+        { "jb",    Op_CBranch },
+        { "jbe",   Op_CBranch },
+        { "jc",    Op_CBranch },
+        { "jcxz",  Op_CBranch },
+        { "je",    Op_CBranch },
+        { "jecxz", Op_CBranch },
+        { "jg",    Op_CBranch },
+        { "jge",   Op_CBranch },
+        { "jl",    Op_CBranch },
+        { "jle",   Op_CBranch },
+        { "jmp",   Op_Branch },
+        { "jmpe",   Op_Branch },
+        { "jmpf",   Op_Branch },
+        { "jna",   Op_CBranch },
+        { "jnae",  Op_CBranch },
+        { "jnb",   Op_CBranch },
+        { "jnbe",  Op_CBranch },
+        { "jnc",   Op_CBranch },
+        { "jne",   Op_CBranch },
+        { "jng",   Op_CBranch },
+        { "jnge",  Op_CBranch },
+        { "jnl",   Op_CBranch },
+        { "jnle",  Op_CBranch },
+        { "jno",   Op_CBranch },
+        { "jnp",   Op_CBranch },
+        { "jns",   Op_CBranch },
+        { "jnz",   Op_CBranch },
+        { "jo",    Op_CBranch },
+        { "jp",    Op_CBranch },
+        { "jpe",   Op_CBranch },
+        { "jpo",   Op_CBranch },
+        { "jrcxz", Op_CBranch },
+        { "js",    Op_CBranch },
+        { "jz",    Op_CBranch },
+        { "lahf",  Op_0_AX },
+        { "lar",   Op_DstSrcFW }, // reg dest only
+        { "lddqu", Op_DstSrcSSE },
+        { "ldmxcsr", Op_SrcMemNT },
+        { "lds",   Op_DstSrc },  // reg dest only
+        { "lea",   Op_DstSrc },  // "
+        { "leaq",   Op_DstSrcSSE },  // "
+        { "leave", Op_0 },       // EBP,ESP clobbers
+        { "lfence",Op_0 },
+        { "lfs",   Op_DstSrc },
+        { "lgdt",  Op_SrcMemNT },
+        { "lgs",   Op_DstSrc },
+        { "lidt",  Op_SrcMemNT },
+        { "lldt",  Op_SrcRMWNT },
+        { "lmsw",  Op_SrcRMWNT },
+        { "lock",  Op_0 },
+        { "lods",  Op_lods },
+        { "lodsb", Op_lodsX },
+        { "lodsd", Op_lodsX },
+        { "lodsw", Op_lodsX },
+        { "lodsq", Op_lodsX },
+        { "loop",  Op_Loop },
+        { "loope", Op_Loop },
+        { "loopne",Op_Loop },
+        { "loopnz",Op_Loop },
+        { "loopz", Op_Loop },
+        { "lsl",   Op_DstSrcFW }, // reg dest only
+        { "lss",   Op_DstSrc },
+        { "ltr",   Op_DstMemNT },
+        { "maskmovdqu", Op_SrcSrcMMX }, // writes to [edi]
+        { "maskmovq",   Op_SrcSrcMMX },
+        { "maxpd", Op_DstSrcSSE },
+        { "maxps", Op_DstSrcSSE },
+        { "maxsd", Op_DstSrcSSE },
+        { "maxss", Op_DstSrcSSE },
+        { "mfence",Op_0},
+        { "minpd", Op_DstSrcSSE },
+        { "minps", Op_DstSrcSSE },
+        { "minsd", Op_DstSrcSSE },
+        { "minss", Op_DstSrcSSE },
+        { "monitor", Op_0 },
+        { "mov",   Op_DstSrc },
+        { "movapd",  Op_DstSrcSSE },
+        { "movaps",  Op_DstSrcSSE },
+        { "movb",   Op_DstSrcNT  },
+        { "movd",    Op_DstSrcNT  }, // also mmx and sse
+        { "movddup", Op_DstSrcSSE },
+        { "movdq2q", Op_DstSrcNT }, // mmx/sse
+        { "movdqa",  Op_DstSrcSSE },
+        { "movdqu",  Op_DstSrcSSE },
+        { "movhlps", Op_DstSrcSSE },
+        { "movhpd",  Op_DstSrcSSE },
+        { "movhps",  Op_DstSrcSSE },
+        { "movl",   Op_DstSrc },
+        { "movlhps", Op_DstSrcSSE },
+        { "movlpd",  Op_DstSrcSSE },
+        { "movlps",  Op_DstSrcSSE },
+        { "movmskpd",Op_DstSrcSSE },
+        { "movmskps",Op_DstSrcSSE },
+        { "movntdq", Op_DstSrcNT  }, // limited to sse, but mem dest
+        { "movnti",  Op_DstSrcNT  }, // limited to gpr, but mem dest
+        { "movntpd", Op_DstSrcNT  }, // limited to sse, but mem dest
+        { "movntps", Op_DstSrcNT  }, // limited to sse, but mem dest
+        { "movntq",  Op_DstSrcNT  }, // limited to mmx, but mem dest
+        { "movq",    Op_DstSrcNT  }, // limited to sse and mmx
+        { "movq2dq", Op_DstSrcNT  }, // limited to sse <- mmx regs
+        { "movs",  Op_movs },
+        { "movsb", Op_movsX },
+        { "movsd", Op_movsd },
+        { "movsq", Op_movsd },
+        { "movshdup", Op_DstSrcSSE },
+        { "movsldup", Op_DstSrcSSE },
+        { "movss", Op_DstSrcSSE },
+        { "movsw", Op_movsX },
+        { "movsx", Op_movsx }, // word-only, reg dest
+        { "movsxd", Op_movsx },
+        { "movupd",Op_DstSrcSSE },
+        { "movups",Op_DstSrcSSE },
+        { "movzbl",   Op_DstSrcNT  },
+        { "movzx", Op_movzx },
+        { "mul",   Op_DstSrcNT  },
+        { "mulpd", Op_DstSrcSSE },
+        { "mulps", Op_DstSrcSSE },
+        { "mulsd", Op_DstSrcSSE },
+        { "mulss", Op_DstSrcSSE },
+        { "mwait", Op_0 },
+        { "naked", Op_Naked },
+        { "neg",   Op_UpdF },
+        { "nop",   Op_0 },
+        { "not",   Op_Upd },
+        { "or",    Op_UpdSrcF },
+        { "orpd",  Op_DstSrcSSE },
+        { "orps",  Op_DstSrcSSE },
+        { "out",   Op_out },
+        { "outs",  Op_outs },
+        { "outsb", Op_outsX },
+        { "outsd", Op_outsX },
+        { "outsw", Op_outsX },
+        { "pabsb",    Op_DstSrcSSE },
+        { "pabsw",    Op_DstSrcSSE },
+        { "pabsq",    Op_DstSrcSSE },
+        { "packssdw", Op_DstSrcMMX }, // %% also SSE
+        { "packsswb", Op_DstSrcMMX },
+        { "packuswb", Op_DstSrcMMX },
+        { "paddb",    Op_DstSrcMMX },
+        { "paddd",    Op_DstSrcMMX },
+        { "paddq",    Op_DstSrcMMX },
+        { "paddsb",   Op_DstSrcMMX },
+        { "paddsw",   Op_DstSrcMMX },
+        { "paddusb",  Op_DstSrcMMX },
+        { "paddusw",  Op_DstSrcMMX },
+        { "paddw",    Op_DstSrcMMX },
+        { "palignr",     Op_DstSrcSSE },
+        { "pand",     Op_DstSrcMMX },
+        { "pandn",    Op_DstSrcMMX },
+        { "pause",    Op_DstSrcMMX },
+        { "pavgb",    Op_DstSrcMMX },
+        { "pavgw",    Op_DstSrcMMX },
+        { "pcmpeqb",  Op_DstSrcMMX },
+        { "pcmpeqd",  Op_DstSrcMMX },
+        { "pcmpeqw",  Op_DstSrcMMX },
+        { "pcmpgtb",  Op_DstSrcMMX },
+        { "pcmpgtd",  Op_DstSrcMMX },
+        { "pcmpgtw",  Op_DstSrcMMX },
+        { "pextrw",   Op_DstSrcImmM }, // gpr32 dest
+        { "phaddd",     Op_DstSrcSSE },
+        { "phaddsw",     Op_DstSrcSSE },
+        { "phaddw",     Op_DstSrcSSE },
+        { "phsubd",     Op_DstSrcSSE },
+        { "phsubsw",     Op_DstSrcSSE },
+        { "phsubw",     Op_DstSrcSSE },
+        { "pinsrw",   Op_DstSrcImmM }, // gpr32(16), mem16 src, sse too
+        { "pmaddubsw",  Op_DstSrcSSE },
+        { "pmaddwd",  Op_DstSrcMMX },
+        { "pmaxsw",   Op_DstSrcMMX },
+        { "pmaxub",   Op_DstSrcMMX },
+        { "pminsw",   Op_DstSrcMMX },
+        { "pminub",   Op_DstSrcMMX },
+        { "pmovmskb", Op_DstSrcMMX },
+        { "pmulhrsw",  Op_DstSrcMMX },
+        { "pmulhuw",  Op_DstSrcMMX },
+        { "pmulhw",   Op_DstSrcMMX },
+        { "pmullw",   Op_DstSrcMMX },
+        { "pmuludq",  Op_DstSrcMMX }, // also sse
+        { "popf",     Op_SizedStack },  // rewrite the insn with a special case
+        { "popfq",    Op_SizedStack },
+        { "popq",    Op_push },
+        { "por",      Op_DstSrcMMX },
+        { "prefetchnta", Op_SrcMemNT },
+        { "prefetcht0",  Op_SrcMemNT },
+        { "prefetcht1",  Op_SrcMemNT },
+        { "prefetcht2",  Op_SrcMemNT },
+        { "psadbw",   Op_DstSrcMMX },
+        { "pshufb",   Op_DstSrcImmM },
+        { "pshufd",   Op_DstSrcImmM },
+        { "pshufhw",  Op_DstSrcImmM },
+        { "pshuflw",  Op_DstSrcImmM },
+        { "pshufw",   Op_DstSrcImmM },
+        { "psignb",   Op_DstSrcSSE },
+        { "psignd",   Op_DstSrcSSE },
+        { "psignw",   Op_DstSrcSSE },
+        { "pslld",    Op_DstSrcMMX }, // immediate operands...
+        { "pslldq",   Op_DstSrcMMX },
+        { "psllq",    Op_DstSrcMMX },
+        { "psllw",    Op_DstSrcMMX },
+        { "psrad",    Op_DstSrcMMX },
+        { "psraw",    Op_DstSrcMMX },
+        { "psrld",    Op_DstSrcMMX },
+        { "psrldq",   Op_DstSrcMMX },
+        { "psrlq",    Op_DstSrcMMX },
+        { "psrlw",    Op_DstSrcMMX },
+        { "psubb",    Op_DstSrcMMX },
+        { "psubd",    Op_DstSrcMMX },
+        { "psubq",    Op_DstSrcMMX },
+        { "psubsb",   Op_DstSrcMMX },
+        { "psubsw",   Op_DstSrcMMX },
+        { "psubusb",  Op_DstSrcMMX },
+        { "psubusw",  Op_DstSrcMMX },
+        { "psubw",    Op_DstSrcMMX },
+        { "punpckhbw", Op_DstSrcMMX },
+        { "punpckhdq", Op_DstSrcMMX },
+        { "punpckhqdq",Op_DstSrcMMX },
+        { "punpckhwd", Op_DstSrcMMX },
+        { "punpcklbw", Op_DstSrcMMX },
+        { "punpckldq", Op_DstSrcMMX },
+        { "punpcklqdq",Op_DstSrcMMX },
+        { "punpcklwd", Op_DstSrcMMX },
+        { "pushf",  Op_SizedStack },
+        { "pushfq", Op_SizedStack },
+        { "pushq", Op_push },
+        { "pxor",   Op_DstSrcMMX },
+        { "rcl",    Op_Shift }, // limited src operands -- change to shift
+        { "rcpps",  Op_DstSrcSSE },
+        { "rcpss",  Op_DstSrcSSE },
+        { "rcr",    Op_Shift },
+        { "rdmsr",  Op_0_DXAX },
+        { "rdpmc",  Op_0_DXAX },
+        { "rdtsc",  Op_0_DXAX },
+        { "rep",    Op_0 },
+        { "repe",   Op_0 },
+        { "repne",  Op_0 },
+        { "repnz",  Op_0 },
+        { "repz",   Op_0 },
+        { "ret",    Op_ret },
+        { "retf",   Op_retf },
+        { "retn",   Op_retf },
+        { "rol",    Op_Shift },
+        { "ror",    Op_Shift },
+        { "rsm",    Op_0 },
+        { "rsqrtps", Op_DstSrcSSE },
+        { "rsqrtss", Op_DstSrcSSE },
+        { "sahf",   Op_Flags },
+        { "sal",    Op_Shift },
+        { "salq",   Op_DstSrcNT  },
+        { "sar",    Op_Shift },
+        { "sbb",    Op_UpdSrcF },
+        { "scas",   Op_scas },
+        { "scasb",  Op_scasX },
+        { "scasd",  Op_scasX },
+        { "scasw",  Op_scasX },
+        { "scasq",  Op_scasX },
+        { "seta",   Op_DstRMBNT }, // also gpr8
+        { "setae",  Op_DstRMBNT },
+        { "setb",   Op_DstRMBNT },
+        { "setbe",  Op_DstRMBNT },
+        { "setc",   Op_DstRMBNT },
+        { "sete",   Op_DstRMBNT },
+        { "setg",   Op_DstRMBNT },
+        { "setge",  Op_DstRMBNT },
+        { "setl",   Op_DstRMBNT },
+        { "setle",  Op_DstRMBNT },
+        { "setna",  Op_DstRMBNT },
+        { "setnae", Op_DstRMBNT },
+        { "setnb",  Op_DstRMBNT },
+        { "setnbe", Op_DstRMBNT },
+        { "setnc",  Op_DstRMBNT },
+        { "setne",  Op_DstRMBNT },
+        { "setng",  Op_DstRMBNT },
+        { "setnge", Op_DstRMBNT },
+        { "setnl",  Op_DstRMBNT },
+        { "setnle", Op_DstRMBNT },
+        { "setno",  Op_DstRMBNT },
+        { "setnp",  Op_DstRMBNT },
+        { "setns",  Op_DstRMBNT },
+        { "setnz",  Op_DstRMBNT },
+        { "seto",   Op_DstRMBNT },
+        { "setp",   Op_DstRMBNT },
+        { "setpe",  Op_DstRMBNT },
+        { "setpo",  Op_DstRMBNT },
+        { "sets",   Op_DstRMBNT },
+        { "setz",   Op_DstRMBNT },
+        { "sfence", Op_0 },
+        { "sgdt",   Op_DstMemNT },
+        { "shl",    Op_Shift },
+        { "shld",   Op_UpdSrcShft },
+        { "shr",    Op_Shift },
+        { "shrd",   Op_UpdSrcShft },
+        { "shufpd", Op_DstSrcImmS },
+        { "shufps", Op_DstSrcImmS },
+        { "sidt",   Op_DstMemNT },
+        { "sldt",   Op_DstRMWNT },
+        { "smsw",   Op_DstRMWNT },
+        { "sqrtpd", Op_DstSrcSSE },
+        { "sqrtps", Op_DstSrcSSE },
+        { "sqrtsd", Op_DstSrcSSE },
+        { "sqrtss", Op_DstSrcSSE },
+        { "stc",    Op_Flags },
+        { "std",    Op_Flags },
+        { "sti",    Op_Flags },
+        { "stmxcsr",Op_DstMemNT },
+        { "stos",   Op_stos },
+        { "stosb",  Op_stosX },
+        { "stosd",  Op_stosX },
+        { "stosw",  Op_stosX },
+        { "stosq",  Op_stosX },
+        { "str",    Op_DstMemNT }, // also r16
+        { "sub",    Op_UpdSrcF },
+        { "subpd",  Op_DstSrcSSE },
+        { "subps",  Op_DstSrcSSE },
+        { "subq",    Op_DstSrcSSE },
+        { "subsd",  Op_DstSrcSSE },
+        { "subss",  Op_DstSrcSSE },
+        { "swapgs",  Op_DstSrcSSE },
+        { "sysenter",Op_0 },
+        { "sysexit", Op_0 },
+        { "sysret", Op_0 },
+        { "testl",   Op_DstSrcNT  },
+        { "ucomisd", Op_SrcSrcSSEF },
+        { "ucomiss", Op_SrcSrcSSEF },
+        { "ud2",     Op_0 },
+        { "unpckhpd", Op_DstSrcSSE },
+        { "unpckhps", Op_DstSrcSSE },
+        { "unpcklpd", Op_DstSrcSSE },
+        { "unpcklps", Op_DstSrcSSE },
+        { "verr",   Op_SrcMemNTF },
+        { "verw",   Op_SrcMemNTF },
+        { "wbinvd", Op_0 },
+        { "wrmsr",  Op_0 },
+        { "xadd",   Op_UpdUpdF },
+        { "xchg",   Op_UpdUpd },
+        { "xlat",   Op_xlat },
+        { "xlatb",  Op_0_AX },
+        { "xor",    Op_DstSrcF },
+        { "xorpd",  Op_DstSrcSSE },
+        { "xorps",  Op_DstSrcSSE },
+        { "xorq",   Op_DstSrcNT  },
+    };
 
-static Identifier * ptrTypeIdentTable[N_PtrNames];
-static PtrType ptrTypeValueTable[N_PtrNames] = {
-    Short_Ptr, Int_Ptr, QWord_Ptr,
-    Float_Ptr, Double_Ptr, Extended_Ptr,
-    Near_Ptr, Far_Ptr
-};
+    typedef enum
+    {
+        Default_Ptr = 0,
+        Byte_Ptr = 1,
+        Short_Ptr = 2,
+        Int_Ptr = 4,
+        QWord_Ptr =  8,
+        Float_Ptr = 4,
+        Double_Ptr = 8,
+        Extended_Ptr = 10,
+        Near_Ptr = 98,
+        Far_Ptr = 99,
+        N_PtrTypes
+    } PtrType;
+
+    static const int N_PtrNames = 8;
+    static const char * ptrTypeNameTable[N_PtrNames] =
+    {
+        "word", "dword", "qword",
+        "float", "double", "extended",
+        "near",  "far"
+    };
 
-typedef enum {
-    Opr_Invalid,
-    Opr_Immediate,
-    Opr_Reg,
-    Opr_Mem
-} OperandClass;
+    static Identifier * ptrTypeIdentTable[N_PtrNames];
+    static PtrType ptrTypeValueTable[N_PtrNames] =
+    {
+        Short_Ptr, Int_Ptr, QWord_Ptr,
+        Float_Ptr, Double_Ptr, Extended_Ptr,
+        Near_Ptr, Far_Ptr
+    };
 
-/* kill inlining if we reference a local? */
+    typedef enum
+    {
+        Opr_Invalid,
+        Opr_Immediate,
+        Opr_Reg,
+        Opr_Mem
+    } OperandClass;
 
-/* DMD seems to allow only one 'symbol' per operand .. include __LOCAL_SIZE */
+    /* kill inlining if we reference a local? */
 
-/* DMD offset usage: <parm>[<reg>] seems to always be relative to EBP+8 .. even
-   if naked.. */
+    /* DMD seems to allow only one 'symbol' per operand .. include __LOCAL_SIZE */
+
+    /* DMD offset usage: <parm>[<reg>] seems to always be relative to EBP+8 .. even
+       if naked.. */
 
 // mov eax, 4
 // mov eax, fs:4
 // -- have to assume we know whether or not to use '$'
 
-static Token eof_tok;
-static Expression * Handled;
-static Identifier * ident_seg;
-
-struct AsmProcessor
-{
-    typedef struct {
-	int inBracket;
-	int hasBracket;
-	int hasNumber;
-	int isOffset;
-
-	Reg segmentPrefix;
-	Reg reg;
-	sinteger_t constDisplacement; // use to build up.. should be int constant in the end..
-	Array      symbolDisplacement; // array of expressions or..
-	Reg baseReg;
-	Reg indexReg;
-	int scale;
-	
-	OperandClass cls;
-	PtrType dataSize;
-	PtrType dataSizeHint; // DMD can use the type of a referenced variable
-    } Operand;
-
-    static const unsigned Max_Operands = 3;
-
-    AsmStatement * stmt;
-    Scope * sc;
-
-    Token * token;
-    OutBuffer * insnTemplate;
+    static Token eof_tok;
+    static Expression * Handled;
+    static Identifier * ident_seg;
 
-    AsmOp       op;
-    AsmOpInfo * opInfo;
-    Operand operands[Max_Operands];
-    Identifier * opIdent;
-    Operand * operand;
-
-    AsmProcessor(Scope * sc, AsmStatement * stmt)
-    {
-	this->sc = sc;
-	this->stmt = stmt;
-	token = stmt->tokens;
-	insnTemplate = new OutBuffer;
-
-	opInfo = NULL;
-
-	if ( ! regInfo[0].ident ) {
-	    char buf[8], *p;
-	    
-	    for (int i = 0; i < N_Regs; i++) {
-		strncpy(buf, regInfo[i].name, sizeof(buf) - 1);
-		for (p = buf; *p; p++)
-		    *p = std::tolower(*p);
-		regInfo[i].gccName = std::string(buf, p - buf);
-		if ( (i <= Reg_ST || i > Reg_ST7) && i != Reg_EFLAGS )
-		    regInfo[i].ident = Lexer::idPool(regInfo[i].name);
-	    }
-
-	    for (int i = 0; i < N_PtrNames; i++)
-		ptrTypeIdentTable[i] = Lexer::idPool(ptrTypeNameTable[i]);
-
-	    Handled = new Expression(0, TOKvoid, sizeof(Expression));
-
-	    ident_seg = Lexer::idPool("seg");
-	
-	    eof_tok.value = TOKeof; 
-	    eof_tok.next = 0;
-	}
-    }
-
-    void run()
+    struct AsmProcessor
     {
-	parse();
-    }
+        typedef struct
+        {
+            int inBracket;
+            int hasBracket;
+            int hasNumber;
+            int isOffset;
+
+            Reg segmentPrefix;
+            Reg reg;
+            sinteger_t constDisplacement; // use to build up.. should be int constant in the end..
+            Array      symbolDisplacement; // array of expressions or..
+            Reg baseReg;
+            Reg indexReg;
+            int scale;
+
+            OperandClass cls;
+            PtrType dataSize;
+            PtrType dataSizeHint; // DMD can use the type of a referenced variable
+        } Operand;
+
+        static const unsigned Max_Operands = 3;
+
+        AsmStatement * stmt;
+        Scope * sc;
+
+        Token * token;
+        OutBuffer * insnTemplate;
 
-    void nextToken() {
-	if (token->next)
-	    token = token->next;
-	else
-	    token = & eof_tok;
-    }
+        AsmOp       op;
+        AsmOpInfo * opInfo;
+        Operand operands[Max_Operands];
+        Identifier * opIdent;
+        Operand * operand;
+
+        AsmProcessor ( Scope * sc, AsmStatement * stmt )
+        {
+            this->sc = sc;
+            this->stmt = stmt;
+            token = stmt->tokens;
+            insnTemplate = new OutBuffer;
+
+            opInfo = NULL;
+
+            if ( ! regInfo[0].ident )
+            {
+                char buf[8], *p;
+
+                for ( int i = 0; i < N_Regs; i++ )
+                {
+                    strncpy ( buf, regInfo[i].name, sizeof ( buf ) - 1 );
+                    for ( p = buf; *p; p++ )
+                        *p = std::tolower ( *p );
+                    regInfo[i].gccName = std::string ( buf, p - buf );
+                    if ( ( i <= Reg_ST || i > Reg_ST7 ) && i != Reg_EFLAGS )
+                        regInfo[i].ident = Lexer::idPool ( regInfo[i].name );
+                }
+
+                for ( int i = 0; i < N_PtrNames; i++ )
+                    ptrTypeIdentTable[i] = Lexer::idPool ( ptrTypeNameTable[i] );
+
+                Handled = new Expression ( 0, TOKvoid, sizeof ( Expression ) );
+
+                ident_seg = Lexer::idPool ( "seg" );
 
-    Token * peekToken() {
-	if (token->next)
-	    return token->next;
-	else
-	    return & eof_tok;
-    }
+                eof_tok.value = TOKeof;
+                eof_tok.next = 0;
+            }
+        }
+
+        void run()
+        {
+            parse();
+        }
+
+        void nextToken()
+        {
+            if ( token->next )
+                token = token->next;
+            else
+                token = & eof_tok;
+        }
+
+        Token * peekToken()
+        {
+            if ( token->next )
+                return token->next;
+            else
+                return & eof_tok;
+        }
+
+        void expectEnd()
+        {
+            if ( token->value != TOKeof )
+                stmt->error ( "expected end of statement" ); // %% extra at end...
+        }
 
-    void expectEnd() {
-	if (token->value != TOKeof)
-	    stmt->error("expected end of statement"); // %% extra at end...
-    }
+        void parse()
+        {
+            op = parseOpcode();
+
+            switch ( op )
+            {
+                case Op_Align:
+                    doAlign();
+                    expectEnd();
+                    break;
+                case Op_Even:
+                    doEven();
+                    expectEnd();
+                    break;
+                case Op_Naked:
+                    doNaked();
+                    expectEnd();
+                    break;
+                case Op_Invalid:
+                    break;
+                default:
+                    if ( op >= Op_db && op <= Op_de )
+                        doData();
+                    else
+                        doInstruction();
+            }
+        }
+
+        AsmOp parseOpcode()
+        {
+            static const int N_ents = sizeof ( opData ) /sizeof ( AsmOpEnt );
 
-    void parse() {
-	op = parseOpcode();
-	
-	switch (op) {
-	case Op_Align:
-	    doAlign();
-	    expectEnd();
-	    break;
-	case Op_Even:
-	    doEven();
-	    expectEnd();
-	    break;
-	case Op_Naked:
-	    doNaked();
-	    expectEnd();
-	    break;
-	case Op_Invalid:
-	    break;
-	default:
-	    if (op >= Op_db && op <= Op_de)
-		doData();
-	    else
-		doInstruction();
-	}
-    }
+            switch ( token->value )
+            {
+                case TOKalign:
+                    nextToken();
+                    return Op_Align;
+                case TOKin:
+                    nextToken();
+                    opIdent = Id::___in;
+                    return Op_in;
+                case TOKint32: // "int"
+                    nextToken();
+                    opIdent = Id::__int;
+                    return Op_SrcImm;
+                case TOKout:
+                    nextToken();
+                    opIdent = Id::___out;
+                    return Op_out;
+                case TOKidentifier:
+                    // search for mnemonic below
+                    break;
+                default:
+                    stmt->error ( "expected opcode" );
+                    return Op_Invalid;
+            }
+
+            opIdent = token->ident;
+            const char * opcode = token->ident->string;
+
+            nextToken();
+
+            // %% okay to use bsearch?
+            int i = 0, j = N_ents, k, l;
+            do
+            {
+                k = ( i + j ) / 2;
+                l = strcmp ( opcode, opData[k].inMnemonic );
+                if ( ! l )
+                    return opData[k].asmOp;
+                else if ( l < 0 )
+                    j = k;
+                else
+                    i = k + 1;
+            }
+            while ( i != j );
+
+            stmt->error ( "unknown opcode '%s'", opcode );
+
+            return Op_Invalid;
+        }
+
+        // need clobber information.. use information is good too...
+        void doInstruction()
+        {
+            bool ok = true;
+            unsigned operand_i = 0;
+
+            opInfo = & asmOpInfo[op];
+            memset ( operands, 0, sizeof ( operands ) );
 
-    AsmOp parseOpcode() {
-	static const int N_ents = sizeof(opData)/sizeof(AsmOpEnt);
+            while ( token->value != TOKeof )
+            {
+                if ( operand_i < Max_Operands )
+                {
+                    operand = & operands[operand_i];
+                    operand->reg = operand->baseReg = operand->indexReg =
+                                                          operand->segmentPrefix = Reg_Invalid;
+                    parseOperand();
+                    operand_i++;
+                }
+                else
+                {
+                    ok = false;
+                    stmt->error ( "too many operands for instruction" );
+                    break;
+                }
+
+                if ( token->value == TOKcomma )
+                    nextToken();
+                else if ( token->value != TOKeof )
+                {
+                    ok = false;
+                    stmt->error ( "expected comma after operand" );
+                    return;
+                }
+            }
+//  if (operand_i < opInfo->minOperands) {
+//      ok = false;
+//      stmt->error("too few operands for instruction");
+//  }
+
+            if ( matchOperands ( operand_i ) )
+            {
+                AsmCode * asmcode = new AsmCode ( N_Regs );
+
+                if ( formatInstruction ( operand_i, asmcode ) )
+                    stmt->asmcode = ( code * ) asmcode;
+            }
+        }
 
-	switch (token->value) {
-	case TOKalign:
-	    nextToken();
-	    return Op_Align;
-	case TOKin:
-	    nextToken();
-	    opIdent = Id::___in;
-	    return Op_in;
-        case TOKint32: // "int"
-            nextToken();
-            opIdent = Id::__int;
-            return Op_SrcImm;
-	case TOKout:
-	    nextToken();
-	    opIdent = Id::___out;
-	    return Op_out;
-	case TOKidentifier:
-	    // search for mnemonic below
-	    break;
-	default:
-	    stmt->error("expected opcode");
-	    return Op_Invalid;
-	}
+        void setAsmCode()
+        {
+            AsmCode * asmcode = new AsmCode ( N_Regs );
+            asmcode->insnTemplateLen = insnTemplate->offset;
+            asmcode->insnTemplate = ( char* ) insnTemplate->extractData();
+            stmt->asmcode = ( code* ) asmcode;
+        }
+
+        // note: doesn't update AsmOp op
+        bool matchOperands ( unsigned nOperands )
+        {
+            bool wrong_number = true;
+
+            for ( unsigned i = 0; i < nOperands; i++ )
+                classifyOperand ( & operands[i] );
+
+            while ( 1 )
+            {
+                if ( nOperands == opInfo->nOperands() )
+                {
+                    wrong_number = false;
+                    /*  Cases in which number of operands is not
+                        enough for a match: Op_FCmp/Op_FCmp1,
+                        Op_FCmpP/Op_FCmpP1 */
+                    for ( unsigned i = 0; i < nOperands; i++ )
+                    {
+                        Operand * operand = & operands[i];
+
+                        switch ( opInfo->operands[i] & Opr_ClassMask )
+                        {
+                            case OprC_Mem: // no FPMem currently
+                                if ( operand->cls != Opr_Mem )
+                                    goto no_match;
+                                break;
+                            case OprC_RFP:
+                                if ( ! ( operand->reg >= Reg_ST && operand->reg <= Reg_ST7 ) )
+                                    goto no_match;
+                                break;
+                            default:
+                                break;
+                        }
+                    }
 
-	opIdent = token->ident;
-	const char * opcode = token->ident->string;
+                    return true;
+                }
+            no_match:
+                if ( opInfo->linkType == Next_Form )
+                    opInfo = & asmOpInfo[ op = ( AsmOp ) opInfo->link ];
+                else
+                    break;
+            }
+            if ( wrong_number )
+                stmt->error ( "wrong number of operands" );
+            else
+                stmt->error ( "wrong operand types" );
+            return false;
+        }
 
-	nextToken();
+        void addOperand ( const char * fmt, AsmArgType type, Expression * e, AsmCode * asmcode, AsmArgMode mode = Mode_Input )
+        {
+            if ( sc->func->naked )
+            {
+                switch ( type )
+                {
+                    case Arg_Integer:
+                        if ( e->type->isunsigned() )
+                            insnTemplate->printf ( "$%llu", e->toUInteger() );
+                        else
+                            insnTemplate->printf ( "$%lld", e->toInteger() );
+                        break;
 
-	// %% okay to use bsearch?
-	int i = 0, j = N_ents, k, l;
-	do {
-	    k = (i + j) / 2;
-	    l = strcmp(opcode, opData[k].inMnemonic);
-	    if (! l)
-		return opData[k].asmOp;
-	    else if (l < 0)
-		j = k;
-	    else
-		i = k + 1;
-	} while (i != j);
+                    case Arg_Pointer:
+                        stmt->error ( "unsupported pointer reference to '%s' in naked asm", e->toChars() );
+                        break;
 
-	stmt->error("unknown opcode '%s'", opcode);
-	
-	return Op_Invalid;
-    }
+                    case Arg_Memory:
+                        if ( e->op == TOKvar )
+                        {
+                            VarExp* v = ( VarExp* ) e;
+                            if ( VarDeclaration* vd = v->var->isVarDeclaration() )
+                            {
+                                if ( !vd->isDataseg() )
+                                {
+                                    stmt->error ( "only global variables can be referenced by identifier in naked asm" );
+                                    break;
+                                }
 
-    // need clobber information.. use information is good too...
-    void doInstruction() {
-	bool ok = true;
-	unsigned operand_i = 0;
-	
-	opInfo = & asmOpInfo[op];
-	memset(operands, 0, sizeof(operands));
+                                // osx needs an extra underscore
+                                if ( global.params.os == OSMacOSX )
+                                    insnTemplate->writestring ( "_" );
+
+                                // print out the mangle
+                                insnTemplate->writestring ( vd->mangle() );
+                                vd->nakedUse = true;
+                                break;
+                            }
+                        }
+                        stmt->error ( "unsupported memory reference to '%s' in naked asm", e->toChars() );
+                        break;
 
-	while (token->value != TOKeof) {
-	    if (operand_i < Max_Operands) {
-		operand = & operands[operand_i];
-		operand->reg = operand->baseReg = operand->indexReg =
-		    operand->segmentPrefix = Reg_Invalid;
-		parseOperand();
-		operand_i++;
-	    } else {
-		ok = false;
-		stmt->error("too many operands for instruction");
-		break;
-	    }
+                    default:
+                        assert ( 0 && "asm unsupported arg" );
+                        break;
+                }
+            }
+            else
+            {
+                insnTemplate->writestring ( ( char* ) fmt );
+                insnTemplate->printf ( "<<%s%d>>", ( mode==Mode_Input ) ?"in":"out", asmcode->args.dim );
+                asmcode->args.push ( new AsmArg ( type, e, mode ) );
+            }
+        }
+        void addOperand2 ( const char * fmtpre, const char * fmtpost, AsmArgType type, Expression * e, AsmCode * asmcode, AsmArgMode mode = Mode_Input )
+        {
+            assert ( !sc->func->naked );
+            insnTemplate->writestring ( ( char* ) fmtpre );
+            insnTemplate->printf ( "<<%s%d>>", ( mode==Mode_Input ) ?"in":"out", asmcode->args.dim );
+            insnTemplate->writestring ( ( char* ) fmtpost );
+            asmcode->args.push ( new AsmArg ( type, e, mode ) );
+        }
+
+        void addLabel ( char* id )
+        {
+            insnTemplate->writestring ( sc->func->mangle() );
+            insnTemplate->writestring ( "_" );
+            insnTemplate->writestring ( id );
+        }
+
+        /* Determines whether the operand is a register, memory reference
+           or immediate.  Immediate addresses are currently classified as
+           memory.  This function is called before the exact instructions
+           is known and thus, should not use opInfo. */
+        void classifyOperand ( Operand * operand )
+        {
+            operand->cls = classifyOperand1 ( operand );
+        }
 
-	    if (token->value == TOKcomma)
-		nextToken();
-	    else if (token->value != TOKeof) {
-		ok = false;
-		stmt->error("expected comma after operand");
-		return;
-	    }
-	}
-// 	if (operand_i < opInfo->minOperands) {
-// 	    ok = false;
-// 	    stmt->error("too few operands for instruction");
-// 	}
+        OperandClass classifyOperand1 ( Operand * operand )
+        {
+            bool is_localsize = false;
+            bool really_have_symbol = false;
+
+            if ( operand->symbolDisplacement.dim )
+            {
+                is_localsize = isLocalSize ( ( Expression * ) operand->symbolDisplacement.data[0] );
+                really_have_symbol = ! is_localsize;
+            }
 
-	if ( matchOperands(operand_i) ) {
-	    AsmCode * asmcode = new AsmCode(N_Regs);
+            if ( operand->isOffset && ! operand->hasBracket )
+                return Opr_Immediate;
+
+            if ( operand->hasBracket || really_have_symbol ) // %% redo for 'offset' function
+            {
+                if ( operand->reg != Reg_Invalid )
+                {
+                    invalidExpression();
+                    return Opr_Invalid;
+                }
 
-	    if (formatInstruction(operand_i, asmcode))
-		stmt->asmcode = (code *) asmcode;
-	}
-    }
+                return Opr_Mem;
+            }
+
+            if ( operand->reg != Reg_Invalid && operand->constDisplacement != 0 )
+            {
+                invalidExpression();
+                return Opr_Invalid;
+            }
 
-    void setAsmCode() {
-	AsmCode * asmcode = new AsmCode(N_Regs);
-	asmcode->insnTemplateLen = insnTemplate->offset;
-	asmcode->insnTemplate = (char*) insnTemplate->extractData();
-	stmt->asmcode = (code*) asmcode;
-    }
+            if ( operand->segmentPrefix != Reg_Invalid )
+            {
+                if ( operand->reg != Reg_Invalid )
+                {
+                    invalidExpression();
+                    return Opr_Invalid;
+                }
 
-    // note: doesn't update AsmOp op
-    bool matchOperands(unsigned nOperands) {
-	bool wrong_number = true;
+                return Opr_Mem;
+            }
+
+            if ( operand->reg != Reg_Invalid && ! operand->hasNumber )
+                return Opr_Reg;
 
-	for (unsigned i = 0; i < nOperands; i++)
-	    classifyOperand(& operands[i]);
-	
-	while (1) {
-	    if (nOperands == opInfo->nOperands()) {
-		wrong_number = false;
-		/*  Cases in which number of operands is not
-		    enough for a match: Op_FCmp/Op_FCmp1,
-		    Op_FCmpP/Op_FCmpP1 */
-		for (unsigned i = 0; i < nOperands; i++) {
-		    Operand * operand = & operands[i];
-		    
-		    switch (opInfo->operands[i] & Opr_ClassMask) {
-		    case OprC_Mem: // no FPMem currently
-			if (operand->cls != Opr_Mem)
-			    goto no_match;
-			break;
-		    case OprC_RFP:
-			if (! (operand->reg >= Reg_ST && operand->reg <= Reg_ST7))
-			    goto no_match;
-			break;
-		    default:
-			break;
-		    }
-		}
+            // should check immediate given (operand->hasNumber);
+            //
+            if ( operand->hasNumber || is_localsize )
+            {
+                // size determination not correct if there are symbols Opr_Immediate
+                if ( operand->dataSize == Default_Ptr )
+                {
+                    if ( operand->constDisplacement < 0x100 )
+                        operand->dataSize = Byte_Ptr;
+                    else if ( operand->constDisplacement < 0x10000 )
+                        operand->dataSize = Short_Ptr;
+                    else
+                        operand->dataSize = Int_Ptr;
+                }
+                return Opr_Immediate;
+            }
+
+            // probably a bug,?
+            stmt->error ( "invalid operand" );
+            return Opr_Invalid;
+        }
+
+        void writeReg ( Reg reg )
+        {
+            insnTemplate->writestring ( ( char* ) "%" );
+            insnTemplate->write ( regInfo[reg].gccName.c_str(), regInfo[reg].gccName.length() );
+        }
+
+        bool opTakesLabel()
+        {
+            switch ( op )
+            {
+                case Op_Branch:
+                case Op_CBranch:
+                case Op_Loop:
+                    return true;
+                default:
+                    return false;
+            }
+        }
 
-		return true;
-	    }
-	    no_match:
-	    if (opInfo->linkType == Next_Form)
-		opInfo = & asmOpInfo[ op = (AsmOp) opInfo->link ];
-	    else
-		break;
-	}
-	if (wrong_number)
-	    stmt->error("wrong number of operands");
-	else
-	    stmt->error("wrong operand types");
-	return false;
-    }
-
-    void addOperand(const char * fmt, AsmArgType type, Expression * e, AsmCode * asmcode, AsmArgMode mode = Mode_Input) {
-        if (sc->func->naked)
+        bool getTypeChar ( TypeNeeded needed, PtrType ptrtype, char & type_char )
         {
-            switch(type)
+            switch ( needed )
             {
-            case Arg_Integer:
-                if (e->type->isunsigned())
-                    insnTemplate->printf("$%llu", e->toUInteger());
-                else
-                    insnTemplate->printf("$%lld", e->toInteger());
-                break;
+                case Byte_NoType:
+                    return ptrtype == Byte_Ptr;
+                case Word_Types:
+                    if ( ptrtype == Byte_Ptr )
+                        return false;
+                    // drop through
+                case Int_Types:
+                    switch ( ptrtype )
+                    {
+                        case Byte_Ptr:  type_char = 'b'; break;
+                        case Short_Ptr: type_char = 'w'; break;
+                        case Int_Ptr:   type_char = 'l'; break;
+                        default:
+                            // %% these may be too strict
+                            return false;
+                    }
+                    break;
+                case FPInt_Types:
+                    switch ( ptrtype )
+                    {
+                        case Short_Ptr: type_char = 0;   break;
+                        case Int_Ptr:   type_char = 'l'; break;
+                        case QWord_Ptr: type_char = 'q'; break;
+                        default:
+                            return false;
+                    }
+                    break;
+                case FP_Types:
+                    switch ( ptrtype )
+                    {
+                        case Float_Ptr:    type_char = 's'; break;
+                        case Double_Ptr:   type_char = 'l'; break;
+                        case Extended_Ptr: type_char = 't'; break;
+                        default:
+                            return false;
+                    }
+                    break;
+                default:
+                    return false;
+            }
+            return true;
+        }
 
-            case Arg_Pointer:
-                stmt->error("unsupported pointer reference to '%s' in naked asm", e->toChars());
-                break;
+        // also set impl clobbers
+        bool formatInstruction ( int nOperands, AsmCode * asmcode )
+        {
+            const char *fmt;
+            const char *mnemonic;
+            char type_char = 0;
+            bool use_star;
+            AsmArgMode mode;
 
-            case Arg_Memory:
-                if (e->op == TOKvar)
+            insnTemplate = new OutBuffer;
+            // %% todo: special case for something..
+            if ( opInfo->linkType == Out_Mnemonic )
+                mnemonic = alternateMnemonics[opInfo->link];
+            else
+                mnemonic = opIdent->string;
+
+            if ( opInfo->needsType )
+            {
+                PtrType exact_type = Default_Ptr;
+                PtrType min_type = Default_Ptr;
+                PtrType hint_type = Default_Ptr;
+
+                /* Default types: This attempts to match the observed behavior of DMD */
+                switch ( opInfo->needsType )
                 {
-                    VarExp* v = (VarExp*)e;
-                    if (VarDeclaration* vd = v->var->isVarDeclaration())
+                    case Int_Types:   min_type = Byte_Ptr; break;
+                    case Word_Types:  min_type = Short_Ptr; break;
+                    case FPInt_Types:
+                        if ( op == Op_Fis_ST ) // integer math instructions
+                            min_type = Int_Ptr;
+                        else // compare, load, store
+                            min_type = Short_Ptr;
+                        break;
+                    case FP_Types:    min_type = Float_Ptr; break;
+                }
+                if ( op == Op_push && operands[0].cls == Opr_Immediate )
+                    min_type = Int_Ptr;
+
+                for ( int i = 0; i < nOperands; i++ )
+                {
+                    if ( hint_type == Default_Ptr &&
+                            ! ( opInfo->operands[i] & Opr_NoType ) )
+                        hint_type = operands[i].dataSizeHint;
+
+                    if ( ( opInfo->operands[i] & Opr_NoType ) ||
+                            operands[i].dataSize == Default_Ptr )
+                        continue;
+                    if ( operands[i].cls == Opr_Immediate )
                     {
-                        if (!vd->isDataseg())
-                        {
-                            stmt->error("only global variables can be referenced by identifier in naked asm");
-                            break;
-                        }
-
-			// osx needs an extra underscore
-			if (global.params.os == OSMacOSX)
-			  insnTemplate->writestring("_");
-
-                        // print out the mangle
-                        insnTemplate->writestring(vd->mangle());
-                        vd->nakedUse = true;
+                        min_type = operands[i].dataSize > min_type ?
+                                   operands[i].dataSize : min_type;
+                    }
+                    else
+                    {
+                        exact_type = operands[i].dataSize; // could check for conflicting types
                         break;
                     }
                 }
-                stmt->error("unsupported memory reference to '%s' in naked asm", e->toChars());
+
+                bool type_ok;
+                if ( exact_type == Default_Ptr )
+                {
+                    type_ok = getTypeChar ( ( TypeNeeded ) opInfo->needsType, hint_type, type_char );
+                    if ( ! type_ok )
+                        type_ok = getTypeChar ( ( TypeNeeded ) opInfo->needsType, min_type, type_char );
+                }
+                else
+                    type_ok = getTypeChar ( ( TypeNeeded ) opInfo->needsType, exact_type, type_char );
+
+                if ( ! type_ok )
+                {
+                    stmt->error ( "invalid operand size" );
+                    return false;
+                }
+            }
+            else if ( op == Op_Branch )
+            {
+                if ( operands[0].dataSize == Far_Ptr ) // %% type=Far_Ptr not set by Seg:Ofss OTOH, we don't support that..
+                    insnTemplate->writebyte ( 'l' );
+            }
+            else if ( op == Op_fxch )
+            {
+                // gas won't accept the two-operand form
+                if ( operands[1].cls == Opr_Reg && operands[1].reg == Reg_ST )
+                {
+                    nOperands = 1;
+                }
+                else
+                {
+                    stmt->error ( "invalid operands" );
+                    return false;
+                }
+            }
+
+            switch ( op )
+            {
+                case Op_SizedStack:
+                {
+                    int mlen = strlen ( mnemonic );
+                    if ( mnemonic[mlen-1] == 'd' )
+                        insnTemplate->write ( mnemonic, mlen-1 );
+                    else
+                    {
+                        insnTemplate->writestring ( ( char* ) mnemonic );
+                        insnTemplate->writebyte ( 'w' );
+                    }
+                }
+                break;
+                case Op_cmpsd:
+                case Op_insX:
+                case Op_lodsX:
+                case Op_movsd:
+                case Op_outsX:
+                case Op_scasX:
+                case Op_stosX:
+                {
+                    int mlen = strlen ( mnemonic );
+                    if ( mnemonic[mlen-1] == 'd' )
+                    {
+                        insnTemplate->write ( mnemonic, mlen-1 );
+                        insnTemplate->writebyte ( 'l' );
+                    }
+                    else
+                    {
+                        insnTemplate->writestring ( ( char* ) mnemonic );
+                    }
+                }
+                break;
+                case Op_movsx:
+                case Op_movzx:
+                {
+                    char tc_1;
+                    int mlen = strlen ( mnemonic );
+                    PtrType op1_size = operands[1].dataSize;
+                    if ( op1_size == Default_Ptr )
+                        op1_size = operands[1].dataSizeHint;
+                    // Need type char for source arg
+                    switch ( op1_size )
+                    {
+                        case Byte_Ptr:
+                        case Default_Ptr:
+                            tc_1 = 'b';
+                            break;
+                        case Short_Ptr:
+                            tc_1 = 'w';
+                            break;
+                        default:
+                            stmt->error ( "invalid operand size/type" );
+                            return false;
+                    }
+                    assert ( type_char != 0 );
+                    insnTemplate->write ( mnemonic, mlen-1 );
+                    insnTemplate->writebyte ( tc_1 );
+                    insnTemplate->writebyte ( type_char );
+                }
                 break;
+                default:
+                    insnTemplate->writestring ( ( char* ) mnemonic );
+                    if ( type_char )
+                        insnTemplate->writebyte ( type_char );
+                    break;
+            }
+
+            switch ( opInfo->implicitClobbers & Clb_DXAX_Mask )
+            {
+                case Clb_SizeAX:
+                case Clb_EAX:
+                    asmcode->regs[Reg_EAX] = true;
+                    break;
+                case Clb_SizeDXAX:
+                    asmcode->regs[Reg_EAX] = true;
+                    if ( type_char != 'b' )
+                        asmcode->regs[Reg_EDX] = true;
+                    break;
+                default:
+                    // nothing
+                    break;
+            }
+
+            if ( opInfo->implicitClobbers & Clb_DI )
+                asmcode->regs[Reg_EDI] = true;
+            if ( opInfo->implicitClobbers & Clb_SI )
+                asmcode->regs[Reg_ESI] = true;
+            if ( opInfo->implicitClobbers & Clb_CX )
+                asmcode->regs[Reg_ECX] = true;
+            if ( opInfo->implicitClobbers & Clb_SP )
+                asmcode->regs[Reg_ESP] = true;
+            if ( opInfo->implicitClobbers & Clb_ST )
+            {
+                /* Can't figure out how to tell GCC that an
+                   asm statement leaves an arg pushed on the stack.
+                   Maybe if the statment had and input or output
+                   operand it would work...  In any case, clobbering
+                   all FP prevents incorrect code generation. */
+                asmcode->regs[Reg_ST] = true;
+                asmcode->regs[Reg_ST1] = true;
+                asmcode->regs[Reg_ST2] = true;
+                asmcode->regs[Reg_ST3] = true;
+                asmcode->regs[Reg_ST4] = true;
+                asmcode->regs[Reg_ST5] = true;
+                asmcode->regs[Reg_ST6] = true;
+                asmcode->regs[Reg_ST7] = true;
+            }
+            if ( opInfo->implicitClobbers & Clb_Flags )
+                asmcode->regs[Reg_EFLAGS] = true;
+            if ( op == Op_cpuid )
+            {
+                asmcode->regs[Reg_EAX] = true;
+                asmcode->regs[Reg_ECX] = true;
+                asmcode->regs[Reg_EDX] = true;
+            }
+
+            insnTemplate->writebyte ( ' ' );
+            for ( int i__ = 0; i__ < nOperands; i__++ )
+            {
+                int i;
+                if ( i__ != 0 )
+                    insnTemplate->writestring ( ( char* ) ", " );
+
+                fmt = "$";
+
+                switch ( op )
+                {
+                    case Op_mul:
+                        // gas won't accept the two-operand form; skip to the source operand
+                        i__ = 1;
+                        // drop through
+                    case Op_bound:
+                    case Op_enter:
+                        i = i__;
+                        break;
+                    default:
+                        i = nOperands - 1 - i__; // operand = & operands[ nOperands - 1 - i ];
+                        break;
+                }
+                operand = & operands[ i ];
+
+                switch ( operand->cls )
+                {
+                    case Opr_Immediate:
+                        // for implementing offset:
+                        // $var + $7 // fails
+                        // $var + 7  // ok
+                        // $7 + $var // ok
+
+                        // DMD doesn't seem to allow this
+                        /*
+                        if (opInfo->takesLabel())  tho... (near ptr <Number> would be abs?)
+                            fmt = "$a"; // GAS won't accept "jmp $42"; must be "jmp 42" (rel) or "jmp *42" (abs)
+                        */
+                        if ( opTakesLabel() /*opInfo->takesLabel()*/ )
+                        {
+                            // "relative addressing not allowed in branch instructions" ..
+                            stmt->error ( "integer constant not allowed in branch instructions" );
+                            return false;
+                        }
+
+                        if ( operand->symbolDisplacement.dim &&
+                                isLocalSize ( ( Expression * ) operand->symbolDisplacement.data[0] ) )
+                        {
+                            // handle __LOCAL_SIZE, which in this constant, is an immediate
+                            // should do this in slotexp..
+                            addOperand ( "$", Arg_LocalSize,
+                                         ( Expression * ) operand->symbolDisplacement.data[0], asmcode );
+                            if ( operand->constDisplacement )
+                                insnTemplate->writebyte ( '+' );
+                            else
+                                break;
+                        }
+
+                        if ( operand->symbolDisplacement.dim )
+                        {
+                            fmt = "$a";
+                            addOperand ( "$", Arg_Pointer,
+                                         ( Expression * ) operand->symbolDisplacement.data[0],
+                                         asmcode );
+
+                            if ( operand->constDisplacement )
+                                insnTemplate->writebyte ( '+' );
+                            else
+                                // skip the addOperand(fmt, Arg_Integer...) below
+                                break;
+                        }
+                        addOperand ( fmt, Arg_Integer, newIntExp ( operand->constDisplacement ), asmcode );
+                        break;
+                    case Opr_Reg:
+                        if ( opInfo->operands[i] & Opr_Dest )
+                        {
+                            Reg clbr_reg = ( Reg ) regInfo[operand->reg].baseReg;
+                            if ( clbr_reg != Reg_Invalid )
+                            {
+                                asmcode->regs[clbr_reg] = true;
+                            }
+                        }
+                        if ( opTakesLabel() /*opInfo->takesLabel()*/ )
+                            insnTemplate->writebyte ( '*' );
+                        writeReg ( operand->reg );
+                        /*
+                        insnTemplate->writestring("%");
+                        insnTemplate->writestring(regInfo[operand->reg].name);
+                        */
+                        break;
+                    case Opr_Mem:
+                        // better: use output operands for simple variable references
+                        if ( ( opInfo->operands[i] & Opr_Update ) == Opr_Update )
+                        {
+                            mode = Mode_Update;
+                        }
+                        else if ( opInfo->operands[i] & Opr_Dest )
+                        {
+                            mode = Mode_Output;
+                        }
+                        else
+                        {
+                            mode = Mode_Input;
+                        }
+
+                        use_star = opTakesLabel();//opInfo->takesLabel();
+                        if ( operand->segmentPrefix != Reg_Invalid )
+                        {
+                            writeReg ( operand->segmentPrefix );
+                            insnTemplate->writebyte ( ':' );
+                        }
+                        if ( operand->symbolDisplacement.dim )
+                        {
+                            Expression * e = ( Expression * ) operand->symbolDisplacement.data[0];
+                            Declaration * decl = 0;
+
+                            if ( e->op == TOKvar )
+                                decl = ( ( VarExp * ) e )->var;
+
+                            if ( operand->baseReg != Reg_Invalid &&
+                                    decl && ! decl->isDataseg() )
+                            {
+
+                                // Use the offset from frame pointer
 
-            default:
-                assert(0 && "asm unsupported arg");
-                break;
+                                /* GCC doesn't give the front end access to stack offsets
+                                   when optimization is turned on (3.x) or at all (4.x).
+                                   
+                                   Try to convert var[EBP] (or var[ESP] for naked funcs) to
+                                   a memory expression that does not require us to know
+                                   the stack offset.
+                                */
+
+                                if ( operand->indexReg == Reg_Invalid &&
+                                        decl->isVarDeclaration() &&
+                                        ( ( ( operand->baseReg == Reg_EBP || ( operand->baseReg == Reg_RBP ) ) && ! sc->func->naked ) ||
+                                          ( ( operand->baseReg == Reg_ESP || ( operand->baseReg == Reg_RSP ) ) && sc->func->naked ) ) )
+                                {
+
+                                    if ( mode == Mode_Output )
+                                    {
+                                        e = new AddrExp ( 0, e );
+                                        e->type = decl->type->pointerTo();
+                                    }
+
+#if !IN_LLVM
+                                    /* DMD uses the same frame offsets for naked functions. */
+                                    if ( sc->func->naked )
+                                        operand->constDisplacement += 4;
+
+                                    if ( operand->constDisplacement )
+                                    {
+                                        e = new AddExp ( 0, e,
+                                                         new IntegerExp ( 0, operand->constDisplacement,
+                                                                          Type::tint32 ) );
+                                        e->type = decl->type->pointerTo();
+                                    }
+                                    e = new PtrExp ( 0, e );
+                                    e->type = decl->type;
+#endif
+                                    operand->constDisplacement = 0;
+                                    operand->baseReg = Reg_Invalid;
+
+                                    addOperand ( fmt, Arg_Memory, e, asmcode, mode );
+
+                                }
+                                else
+                                {
+                                    // FIXME: what is this ?
+                                    addOperand2 ( "${",":a}", Arg_FrameRelative, e, asmcode );
+                                }
+                                if ( opInfo->operands[i] & Opr_Dest )
+                                    asmcode->clobbersMemory = 1;
+                            }
+                            else
+                            {
+                                // Plain memory reference to variable
+
+                                /* If in a reg, DMD moves to memory.. even with -O, so we'll do the same
+                                   by always using the "m" contraint.
+
+                                   In order to get the correct output for function and label symbols,
+                                   the %an format must be used with the "p" constraint.
+                                */
+                                if ( isDollar ( e ) )
+                                {
+                                    error ( "dollar labels are not supported", stmt->loc.toChars() );
+                                    asmcode->dollarLabel = 1;
+                                }
+                                else if ( e->op == TOKdsymbol )
+                                {
+                                    LabelDsymbol * lbl = ( LabelDsymbol * ) ( ( DsymbolExp * ) e )->s;
+                                    stmt->isBranchToLabel = lbl->ident;
+
+                                    use_star = false;
+                                    addLabel ( lbl->ident->toChars() );
+                                }
+                                else if ( ( decl && decl->isCodeseg() ) )   // if function or label
+                                {
+                                    use_star = false;
+                                    // simply write out the mangle
+                                    // on osx, prepend extra _
+                                    if ( global.params.os == OSMacOSX )
+                                        insnTemplate->writestring ( "_" );
+                                    insnTemplate->writestring ( decl->mangle() );
+//              addOperand2("${", ":c}", Arg_Pointer, e, asmcode);
+                                }
+                                else
+                                {
+                                    if ( use_star )
+                                    {
+                                        insnTemplate->writebyte ( '*' );
+                                        use_star = false;
+                                    }
+
+                                    if ( !sc->func->naked ) // no addrexp in naked asm please :)
+                                    {
+                                        Type* tt = e->type->pointerTo();
+                                        e = new AddrExp ( 0, e );
+                                        e->type = tt;
+                                    }
+
+                                    addOperand ( fmt, Arg_Memory, e, asmcode, mode );
+                                }
+                            }
+                        }
+                        if ( use_star )
+                            insnTemplate->writebyte ( '*' );
+                        if ( operand->segmentPrefix != Reg_Invalid || operand->constDisplacement )
+                        {
+                            if ( operand->symbolDisplacement.dim )
+                                insnTemplate->writebyte ( '+' );
+                            //addOperand(fmt, Arg_Integer, newIntExp(operand->constDisplacement), asmcode);
+                            insnTemplate->printf ( "%d", operand->constDisplacement );
+                            if ( opInfo->operands[i] & Opr_Dest )
+                                asmcode->clobbersMemory = 1;
+                        }
+                        if ( operand->baseReg != Reg_Invalid || operand->indexReg != Reg_Invalid )
+                        {
+                            insnTemplate->writebyte ( '(' );
+                            if ( operand->baseReg != Reg_Invalid )
+                                writeReg ( operand->baseReg );
+                            if ( operand->indexReg != Reg_Invalid )
+                            {
+                                insnTemplate->writebyte ( ',' );
+                                writeReg ( operand->indexReg );
+                                if ( operand->scale )
+                                {
+                                    insnTemplate->printf ( ",%d", operand->scale );
+                                }
+                            }
+                            insnTemplate->writebyte ( ')' );
+                            if ( opInfo->operands[i] & Opr_Dest )
+                                asmcode->clobbersMemory = 1;
+                        }
+                        break;
+                    case Opr_Invalid:
+                        return false;
+                }
+            }
+
+            asmcode->insnTemplateLen = insnTemplate->offset;
+            asmcode->insnTemplate = ( char* ) insnTemplate->extractData();
+            return true;
+        }
+
+        bool isIntExp ( Expression * exp )
+        {
+            if ( exp->op == TOKint64 )
+                return 1;
+            if ( exp->op == TOKvar )
+            {
+                Declaration * v = ( ( VarExp * ) exp )->var;
+                if ( v->isConst() && v->type->isintegral() )
+                    return 1;
+            }
+            return 0;
+        }
+        bool isRegExp ( Expression * exp ) { return exp->op == TOKmod; } // ewww.%%
+        bool isLocalSize ( Expression * exp )
+        {
+            // cleanup: make a static var
+            return exp->op == TOKidentifier && ( ( IdentifierExp * ) exp )->ident == Id::__LOCAL_SIZE;
+        }
+        bool isDollar ( Expression * exp )
+        {
+            return exp->op == TOKidentifier && ( ( IdentifierExp * ) exp )->ident == Id::__dollar;
+        }
+
+        Expression * newRegExp ( int regno )
+        {
+            IntegerExp * e = new IntegerExp ( regno );
+            e->op = TOKmod;
+            return e;
+        }
+
+        Expression * newIntExp ( int v /* %% type */ )
+        {
+            // Only handles 32-bit numbers as this is IA-32.
+            return new IntegerExp ( stmt->loc, v, Type::tint32 );
+        }
+
+        void slotExp ( Expression * exp )
+        {
+            /*
+              if offset, make a note
+
+              if integer, add to immediate
+              if reg:
+                  if not in bracket, set reg (else error)
+                  if in bracket:
+                 if not base, set base
+                 if not index, set index
+                 else, error
+              if symbol:
+                set symbol field
+             */
+
+            bool is_offset = false;
+            if ( exp->op == TOKaddress )
+            {
+                exp = ( ( AddrExp * ) exp )->e1;
+                is_offset = true;
+            }
+
+            if ( isIntExp ( exp ) )
+            {
+                if ( is_offset )
+                    invalidExpression();
+                operand->constDisplacement += exp->toInteger();
+                if ( ! operand->inBracket )
+                    operand->hasNumber = 1;
+            }
+            else if ( isRegExp ( exp ) )
+            {
+                if ( is_offset )
+                    invalidExpression();
+                if ( ! operand->inBracket )
+                {
+                    if ( operand->reg == Reg_Invalid )
+                        operand->reg = ( Reg ) exp->toInteger();
+                    else
+                        stmt->error ( "too many registers in operand (use brackets)" );
+                }
+                else
+                {
+                    if ( operand->baseReg == Reg_Invalid )
+                        operand->baseReg = ( Reg ) exp->toInteger();
+                    else if ( operand->indexReg == Reg_Invalid )
+                    {
+                        operand->indexReg = ( Reg ) exp->toInteger();
+                        operand->scale = 1;
+                    }
+                    else
+                    {
+                        stmt->error ( "too many registers memory operand" );
+                    }
+                }
+            }
+            else if ( exp->op == TOKvar )
+            {
+                VarDeclaration * v = ( ( VarExp * ) exp )->var->isVarDeclaration();
+
+                if ( v && v->storage_class & STCfield )
+                {
+                    operand->constDisplacement += v->offset;
+                    if ( ! operand->inBracket )
+                        operand->hasNumber = 1;
+                }
+                else
+                {
+                    if ( v && v->type->isscalar() )
+                    {
+                        // DMD doesn't check Tcomplex*, and counts Tcomplex32 as Tfloat64
+                        TY ty = v->type->toBasetype()->ty;
+                        operand->dataSizeHint = ty == Tfloat80 || ty == Timaginary80 ?
+                                                Extended_Ptr : ( PtrType ) v->type->size ( 0 );
+                    }
+
+                    if ( ! operand->symbolDisplacement.dim )
+                    {
+                        if ( is_offset && ! operand->inBracket )
+                            operand->isOffset = 1;
+                        operand->symbolDisplacement.push ( exp );
+                    }
+                    else
+                    {
+                        stmt->error ( "too many symbols in operand" );
+                    }
+                }
+            }
+            else if ( exp->op == TOKidentifier || exp->op == TOKdsymbol )
+            {
+                // %% localsize could be treated as a simple constant..
+                // change to addSymbolDisp(e)
+                if ( ! operand->symbolDisplacement.dim )
+                {
+                    operand->symbolDisplacement.push ( exp );
+                }
+                else
+                {
+                    stmt->error ( "too many symbols in operand" );
+                }
+            }
+            else if ( exp == Handled )
+            {
+                // nothing
+            }
+            else
+            {
+                stmt->error ( "invalid operand" );
             }
         }
-        else
+
+        void invalidExpression()
         {
-            insnTemplate->writestring((char*) fmt);
-            insnTemplate->printf("<<%s%d>>", (mode==Mode_Input)?"in":"out", asmcode->args.dim);
-            asmcode->args.push( new AsmArg(type, e, mode) );
+            // %% report operand number
+            stmt->error ( "invalid expression" );
         }
-    }
-    void addOperand2(const char * fmtpre, const char * fmtpost, AsmArgType type, Expression * e, AsmCode * asmcode, AsmArgMode mode = Mode_Input) {
-        assert(!sc->func->naked);
-        insnTemplate->writestring((char*) fmtpre);
-        insnTemplate->printf("<<%s%d>>", (mode==Mode_Input)?"in":"out", asmcode->args.dim);
-        insnTemplate->writestring((char*) fmtpost);
-        asmcode->args.push( new AsmArg(type, e, mode) );
-    }
-
-    void addLabel(char* id) {
-        insnTemplate->writestring(sc->func->mangle());
-        insnTemplate->writestring("_");
-        insnTemplate->writestring(id);
-    }
-
-    /* Determines whether the operand is a register, memory reference
-       or immediate.  Immediate addresses are currently classified as
-       memory.  This function is called before the exact instructions
-       is known and thus, should not use opInfo. */
-    void classifyOperand(Operand * operand) {
-	operand->cls = classifyOperand1(operand);
-    }
-    
-    OperandClass classifyOperand1(Operand * operand) {
-	bool is_localsize = false;
-	bool really_have_symbol = false;
-
-	if (operand->symbolDisplacement.dim) {
-	    is_localsize = isLocalSize( (Expression *) operand->symbolDisplacement.data[0] );
-	    really_have_symbol = ! is_localsize;
-	}
-
-	if (operand->isOffset && ! operand->hasBracket)
-	    return Opr_Immediate;
-	
-	if (operand->hasBracket || really_have_symbol) { // %% redo for 'offset' function
-	    if (operand->reg != Reg_Invalid) {
-		invalidExpression();
-		return Opr_Invalid;
-	    }
-
-	    return Opr_Mem;
-	}
-
-	if (operand->reg != Reg_Invalid && operand->constDisplacement != 0) {
-	    invalidExpression();
-	    return Opr_Invalid;
-	}
-	
-	if (operand->segmentPrefix != Reg_Invalid) {
-	    if (operand->reg != Reg_Invalid) {
-		invalidExpression();
-		return Opr_Invalid;
-	    }
-
-	    return Opr_Mem;
-	}
-
-	if (operand->reg != Reg_Invalid && ! operand->hasNumber)
-	    return Opr_Reg;
-
-	// should check immediate given (operand->hasNumber);
-	//
-	if (operand->hasNumber || is_localsize) {
-	    // size determination not correct if there are symbols Opr_Immediate
-	    if (operand->dataSize == Default_Ptr) {
-		if (operand->constDisplacement < 0x100)
-		    operand->dataSize = Byte_Ptr;
-		else if (operand->constDisplacement < 0x10000)
-		    operand->dataSize = Short_Ptr;
-		else
-		    operand->dataSize = Int_Ptr;
-	    }
-	    return Opr_Immediate;
-	}
-
-	// probably a bug,?
-	stmt->error("invalid operand");
-	return Opr_Invalid;
-    }
-
-    void writeReg(Reg reg) {
-	insnTemplate->writestring((char*) "%");
-	insnTemplate->write(regInfo[reg].gccName.c_str(), regInfo[reg].gccName.length());
-    }
-
-    bool opTakesLabel() {
-	switch(op) {
-	case Op_Branch:
-	case Op_CBranch:
-	case Op_Loop:
-	    return true;
-	default:
-	    return false;
-	}
-    }
 
-    bool getTypeChar(TypeNeeded needed, PtrType ptrtype, char & type_char)
-    {
-	switch (needed) {
-	case Byte_NoType:
-	    return ptrtype == Byte_Ptr;
-	case Word_Types:
-	    if (ptrtype == Byte_Ptr)
-		return false;
-	    // drop through
-	case Int_Types:
-	    switch (ptrtype) {
-	    case Byte_Ptr:  type_char = 'b'; break;
-	    case Short_Ptr: type_char = 'w'; break;
-	    case Int_Ptr:   type_char = 'l'; break;
-	    default:
-		// %% these may be too strict
-		return false;
-	    }
-	    break;
-	case FPInt_Types:
-	    switch (ptrtype) {
-	    case Short_Ptr: type_char = 0;   break;
-	    case Int_Ptr:   type_char = 'l'; break;
-	    case QWord_Ptr: type_char = 'q'; break;
-	    default:
-		return false;
-	    }
-	    break;
-	case FP_Types:
-	    switch (ptrtype) {
-	    case Float_Ptr:    type_char = 's'; break;
-	    case Double_Ptr:   type_char = 'l'; break;
-	    case Extended_Ptr: type_char = 't'; break;
-	    default:
-		return false;
-	    }
-	    break;
-	default:
-	    return false;
-	}
-	return true;
-    }
-
-    // also set impl clobbers
-    bool formatInstruction(int nOperands, AsmCode * asmcode) {
-	const char *fmt;
-	const char *mnemonic;
-	char type_char = 0;
-	bool use_star;
-	AsmArgMode mode;
+        Expression * intOp ( TOK op, Expression * e1, Expression * e2 )
+        {
+            Expression * e;
+            if ( isIntExp ( e1 ) && ( ! e2 || isIntExp ( e2 ) ) )
+            {
+                switch ( op )
+                {
+                    case TOKadd:
+                        if ( e2 )
+                            e = new AddExp ( stmt->loc, e1, e2 );
+                        else
+                            e = e1;
+                        break;
+                    case TOKmin:
+                        if ( e2 )
+                            e = new MinExp ( stmt->loc, e1, e2 );
+                        else
+                            e = new NegExp ( stmt->loc, e1 );
+                        break;
+                    case TOKmul:
+                        e = new MulExp ( stmt->loc, e1, e2 );
+                        break;
+                    case TOKdiv:
+                        e = new DivExp ( stmt->loc, e1, e2 );
+                        break;
+                    case TOKmod:
+                        e = new ModExp ( stmt->loc, e1, e2 );
+                        break;
+                    case TOKshl:
+                        e = new ShlExp ( stmt->loc, e1, e2 );
+                        break;
+                    case TOKshr:
+                        e = new ShrExp ( stmt->loc, e1, e2 );
+                        break;
+                    case TOKushr:
+                        e = new UshrExp ( stmt->loc, e1, e2 );
+                        break;
+                    case TOKnot:
+                        e = new NotExp ( stmt->loc, e1 );
+                        break;
+                    case TOKtilde:
+                        e = new ComExp ( stmt->loc, e1 );
+                        break;
+                    default:
+                        assert ( 0 );
+                }
+                e = e->semantic ( sc );
+                return e->optimize ( WANTvalue | WANTinterpret );
+            }
+            else
+            {
+                stmt->error ( "expected integer operand(s) for '%s'", Token::tochars[op] );
+                return newIntExp ( 0 );
+            }
+        }
 
-	insnTemplate = new OutBuffer;
-	// %% todo: special case for something..
-	if (opInfo->linkType == Out_Mnemonic)
-	    mnemonic = alternateMnemonics[opInfo->link];
-	else
-	    mnemonic = opIdent->string;
-
-	if (opInfo->needsType) {
-	    PtrType exact_type = Default_Ptr;
-	    PtrType min_type = Default_Ptr;
-	    PtrType hint_type = Default_Ptr;
+        void parseOperand()
+        {
+            Expression * exp = parseAsmExp();
+            slotExp ( exp );
+            if ( isRegExp ( exp ) )
+                operand->dataSize = ( PtrType ) regInfo[exp->toInteger() ].size;
+        }
 
-	    /* Default types: This attempts to match the observed behavior of DMD */
-	    switch (opInfo->needsType) {
-	    case Int_Types:   min_type = Byte_Ptr; break;
-	    case Word_Types:  min_type = Short_Ptr; break;
-	    case FPInt_Types:
-		if (op == Op_Fis_ST) // integer math instructions 
-		    min_type = Int_Ptr;
-		else // compare, load, store
-		    min_type = Short_Ptr;
-		break;
-	    case FP_Types:    min_type = Float_Ptr; break;
-	    }
-	    if (op == Op_push && operands[0].cls == Opr_Immediate)
-		min_type = Int_Ptr;
-	    
-	    for (int i = 0; i < nOperands; i++) {
-		if (hint_type == Default_Ptr &&
-		    ! (opInfo->operands[i] & Opr_NoType))
-		    hint_type = operands[i].dataSizeHint;
-		    
-		if ((opInfo->operands[i] & Opr_NoType) ||
-		    operands[i].dataSize == Default_Ptr)
-		    continue;
-		if (operands[i].cls == Opr_Immediate) {
-		    min_type = operands[i].dataSize > min_type ?
-			operands[i].dataSize : min_type;
-		} else {
-		    exact_type = operands[i].dataSize; // could check for conflicting types
-		    break;
-		}
-	    }
+        Expression * parseAsmExp()
+        {
+            return parseShiftExp();
+        }
 
-	    bool type_ok;
-	    if (exact_type == Default_Ptr) {
-		type_ok = getTypeChar((TypeNeeded) opInfo->needsType, hint_type, type_char);
-		if (! type_ok)
-		    type_ok = getTypeChar((TypeNeeded) opInfo->needsType, min_type, type_char);
-	    } else
-		type_ok = getTypeChar((TypeNeeded) opInfo->needsType, exact_type, type_char);
+        Expression * parseShiftExp()
+        {
+            Expression * e1 = parseAddExp();
+            Expression * e2;
 
-	    if (! type_ok) {
-		stmt->error("invalid operand size");
-		return false;
-	    }
-	} else if (op == Op_Branch) {
-	    if (operands[0].dataSize == Far_Ptr) // %% type=Far_Ptr not set by Seg:Ofss OTOH, we don't support that..
-		insnTemplate->writebyte('l');
-	} else if (op == Op_fxch) {
-	    // gas won't accept the two-operand form
-	    if (operands[1].cls == Opr_Reg && operands[1].reg == Reg_ST) {
-		nOperands = 1;
-	    } else {
-		stmt->error("invalid operands");
-		return false;
-	    }
-	}
-	
-	switch (op) {
-	case Op_SizedStack:
-	    {
-		int mlen = strlen(mnemonic);
-		if (mnemonic[mlen-1] == 'd')
-		    insnTemplate->write(mnemonic, mlen-1);
-		else {
-		    insnTemplate->writestring((char*) mnemonic);
-		    insnTemplate->writebyte('w');
-		}
-	    }
-	    break;
-	case Op_cmpsd:
-	case Op_insX:
-	case Op_lodsX:
-	case Op_movsd:
-	case Op_outsX:
-	case Op_scasX:
-	case Op_stosX:
-	    {
-		int mlen = strlen(mnemonic);
-		if (mnemonic[mlen-1] == 'd') {
-		    insnTemplate->write(mnemonic, mlen-1);
-		    insnTemplate->writebyte('l');
-		} else {
-		    insnTemplate->writestring((char*) mnemonic);
-		}
-	    }
-	    break;
-	case Op_movsx:
-	case Op_movzx:
-	    {
-		char tc_1;
-		int mlen = strlen(mnemonic);
-		PtrType op1_size = operands[1].dataSize;
-		if (op1_size == Default_Ptr)
-		    op1_size = operands[1].dataSizeHint;
-		// Need type char for source arg
-		switch (op1_size) {
-		case Byte_Ptr: 
-		case Default_Ptr:
-		    tc_1 = 'b';
-		    break;
-		case Short_Ptr:
-		    tc_1 = 'w';
-		    break;
-		default:
-		    stmt->error("invalid operand size/type");
-		    return false;
-		}
-		assert(type_char != 0);
-		insnTemplate->write(mnemonic, mlen-1);
-		insnTemplate->writebyte(tc_1);
-		insnTemplate->writebyte(type_char);
-	    }
-	    break;
-	default:
-	    insnTemplate->writestring((char*) mnemonic);
-	    if (type_char)
-		insnTemplate->writebyte(type_char);
-	    break;
-	}
+            while ( 1 )
+            {
+                TOK tv = token->value;
+                switch ( tv )
+                {
+                    case TOKshl:
+                    case TOKshr:
+                    case TOKushr:
+                        nextToken();
+                        e2 = parseAddExp();
+                        e1 = intOp ( tv, e1, e2 );
+                        continue;
+                    default:
+                        break;
+                }
+                break;
+            }
+            return e1;
+        }
 
-	switch (opInfo->implicitClobbers & Clb_DXAX_Mask) {
-	case Clb_SizeAX:
-	case Clb_EAX:
-	    asmcode->regs[Reg_EAX] = true;
-	    break;
-	case Clb_SizeDXAX:
-	    asmcode->regs[Reg_EAX] = true;
-	    if (type_char != 'b')
-		asmcode->regs[Reg_EDX] = true;
-	    break;
-	default:
-	    // nothing
-	    break;
-	}
-
-	if (opInfo->implicitClobbers & Clb_DI)
-	    asmcode->regs[Reg_EDI] = true;
-	if (opInfo->implicitClobbers & Clb_SI)
-	    asmcode->regs[Reg_ESI] = true;
-	if (opInfo->implicitClobbers & Clb_CX)
-	    asmcode->regs[Reg_ECX] = true;
-	if (opInfo->implicitClobbers & Clb_SP)
-	    asmcode->regs[Reg_ESP] = true;
-	if (opInfo->implicitClobbers & Clb_ST)
-	{
-	    /* Can't figure out how to tell GCC that an
-	       asm statement leaves an arg pushed on the stack.
-	       Maybe if the statment had and input or output
-	       operand it would work...  In any case, clobbering
-	       all FP prevents incorrect code generation. */
-	    asmcode->regs[Reg_ST] = true;
-	    asmcode->regs[Reg_ST1] = true;
-	    asmcode->regs[Reg_ST2] = true;
-	    asmcode->regs[Reg_ST3] = true;
-	    asmcode->regs[Reg_ST4] = true;
-	    asmcode->regs[Reg_ST5] = true;
-	    asmcode->regs[Reg_ST6] = true;
-	    asmcode->regs[Reg_ST7] = true;
-	}
-	if (opInfo->implicitClobbers & Clb_Flags)
-	    asmcode->regs[Reg_EFLAGS] = true;
-	if (op == Op_cpuid) {
-	    asmcode->regs[Reg_EAX] = true;
-	    asmcode->regs[Reg_ECX] = true;
-	    asmcode->regs[Reg_EDX] = true;
-	}
-
-	insnTemplate->writebyte(' ');
-	for (int i__ = 0; i__ < nOperands; i__++) {
-	    int i;
-	    if (i__ != 0)
-		insnTemplate->writestring((char*) ", ");
-
-	    fmt = "$";
-    
-	    switch (op) {
-	    case Op_mul:
-		// gas won't accept the two-operand form; skip to the source operand
-		i__ = 1;
-		// drop through
-	    case Op_bound:
-	    case Op_enter:
-		i = i__;
-		break;
-	    default:
-		i = nOperands - 1 - i__; // operand = & operands[ nOperands - 1 - i ];
-		break;
-	    }
-	    operand = & operands[ i ];
+        Expression * parseAddExp()
+        {
+            Expression * e1 = parseMultExp();
+            Expression * e2;
 
-	    switch (operand->cls) {
-	    case Opr_Immediate:
-		// for implementing offset:
-		// $var + $7 // fails
-		// $var + 7  // ok
-		// $7 + $var // ok
-
-		// DMD doesn't seem to allow this
-		/*
-		if (opInfo->takesLabel())  tho... (near ptr <Number> would be abs?)
-		    fmt = "$a"; // GAS won't accept "jmp $42"; must be "jmp 42" (rel) or "jmp *42" (abs)
-		*/
-		if (opTakesLabel()/*opInfo->takesLabel()*/) {
-		    // "relative addressing not allowed in branch instructions" ..
-		    stmt->error("integer constant not allowed in branch instructions");
-		    return false;
-		}
-
-		if (operand->symbolDisplacement.dim &&
-		    isLocalSize( (Expression *) operand->symbolDisplacement.data[0] )) {
-		    // handle __LOCAL_SIZE, which in this constant, is an immediate
-		    // should do this in slotexp..
-		    addOperand("$", Arg_LocalSize,
-			(Expression *) operand->symbolDisplacement.data[0], asmcode);
-		    if (operand->constDisplacement)
-			insnTemplate->writebyte('+');
-		    else
-			break;
-		}
-
-		if (operand->symbolDisplacement.dim) {
-		    fmt = "$a";
-		    addOperand("$", Arg_Pointer,
-			(Expression *) operand->symbolDisplacement.data[0],
-			asmcode);
-
-		    if (operand->constDisplacement)
-			insnTemplate->writebyte('+');
-		    else
-			// skip the addOperand(fmt, Arg_Integer...) below
-			break;
-		}
-		addOperand(fmt, Arg_Integer, newIntExp(operand->constDisplacement), asmcode);
-		break;
-	    case Opr_Reg:
-		if (opInfo->operands[i] & Opr_Dest) {
-		    Reg clbr_reg = (Reg) regInfo[operand->reg].baseReg;
-		    if (clbr_reg != Reg_Invalid) {
-			asmcode->regs[clbr_reg] = true;
-		    }
-		}
-		if (opTakesLabel()/*opInfo->takesLabel()*/)
-		    insnTemplate->writebyte('*');
-		writeReg(operand->reg);
-		/*
-		insnTemplate->writestring("%");
-		insnTemplate->writestring(regInfo[operand->reg].name);
-		*/
-		break;
-	    case Opr_Mem:
-		// better: use output operands for simple variable references
-		if ( (opInfo->operands[i] & Opr_Update) == Opr_Update) {
-		    mode = Mode_Update;
-		} else if (opInfo->operands[i] & Opr_Dest) {
-		    mode = Mode_Output;
-		} else {
-		    mode = Mode_Input;
-		}
-		
-		use_star = opTakesLabel();//opInfo->takesLabel();
-		if (operand->segmentPrefix != Reg_Invalid) {
-		    writeReg(operand->segmentPrefix);
-		    insnTemplate->writebyte(':');
-		}
-		if (operand->symbolDisplacement.dim) {
-		    Expression * e = (Expression *) operand->symbolDisplacement.data[0];
-		    Declaration * decl = 0;
-
-		    if (e->op == TOKvar)
-			decl = ((VarExp *) e)->var;
+            while ( 1 )
+            {
+                TOK tv = token->value;
+                switch ( tv )
+                {
+                    case TOKadd:
+                        nextToken();
+                        e2 = parseMultExp();
+                        if ( isIntExp ( e1 ) && isIntExp ( e2 ) )
+                            e1 = intOp ( tv, e1, e2 );
+                        else
+                        {
+                            slotExp ( e1 );
+                            slotExp ( e2 );
+                            e1 = Handled;
+                        }
+                        continue;
+                    case TOKmin:
+                        // Note: no support for symbol address difference
+                        nextToken();
+                        e2 = parseMultExp();
+                        if ( isIntExp ( e1 ) && isIntExp ( e2 ) )
+                            e1 = intOp ( tv, e1, e2 );
+                        else
+                        {
+                            slotExp ( e1 );
+                            e2 = intOp ( TOKmin, e2, NULL ); // verifies e2 is an int
+                            slotExp ( e2 );
+                            e1 = Handled;
+                        }
+                        continue;
+                    default:
+                        break;
+                }
+                break;
+            }
+            return e1;
+        }
 
-		    if (operand->baseReg != Reg_Invalid &&
-			decl && ! decl->isDataseg()) {
-
-			// Use the offset from frame pointer
-
-			/* GCC doesn't give the front end access to stack offsets
-			   when optimization is turned on (3.x) or at all (4.x).
-			   
-			   Try to convert var[EBP] (or var[ESP] for naked funcs) to
-			   a memory expression that does not require us to know
-			   the stack offset.
-			*/
-
-			if (operand->indexReg == Reg_Invalid &&
-			    decl->isVarDeclaration() &&
-			    ( ((operand->baseReg == Reg_EBP || (operand->baseReg == Reg_RBP)) && ! sc->func->naked ) ||
-			      ((operand->baseReg == Reg_ESP || (operand->baseReg == Reg_RSP)) && sc->func->naked)) ) 
-			  {
-
-                if (mode == Mode_Output)
+        bool tryScale ( Expression * e1, Expression * e2 )
+        {
+            Expression * et;
+            if ( isIntExp ( e1 ) && isRegExp ( e2 ) )
+            {
+                et = e1;
+                e1 = e2;
+                e2 = et;
+                goto do_scale;
+            }
+            else if ( isRegExp ( e1 ) && isIntExp ( e2 ) )
+            {
+            do_scale:
+                if ( ! operand->inBracket )
                 {
-                    e = new AddrExp(0, e);
-                    e->type = decl->type->pointerTo();
-                }
-
-#if !IN_LLVM
-			    /* DMD uses the same frame offsets for naked functions. */
-			    if (sc->func->naked)
-				operand->constDisplacement += 4;
-
-			    if (operand->constDisplacement) {
-				e = new AddExp(0, e,
-				    new IntegerExp(0, operand->constDisplacement,
-					Type::tint32));
-				e->type = decl->type->pointerTo();
-			    }
-			    e = new PtrExp(0, e);
-			    e->type = decl->type;
-#endif
-			    operand->constDisplacement = 0;
-			    operand->baseReg = Reg_Invalid;
-
-			    addOperand(fmt, Arg_Memory, e, asmcode, mode);
-			    
-			} else {
-			    addOperand2("${",":a}", Arg_FrameRelative, e, asmcode);
-			}
-			if (opInfo->operands[i] & Opr_Dest)
-			    asmcode->clobbersMemory = 1;
-		    } else  {
-			// Plain memory reference to variable
-			
-			/* If in a reg, DMD moves to memory.. even with -O, so we'll do the same
-			   by always using the "m" contraint.
-
-			   In order to get the correct output for function and label symbols,
-			   the %an format must be used with the "p" constraint.
-			*/
-			if (isDollar(e)) {
-			    error("dollar labels are not supported", stmt->loc.toChars());
-			    asmcode->dollarLabel = 1;
-			} else if (e->op == TOKdsymbol) {
-			    LabelDsymbol * lbl = (LabelDsymbol *) ((DsymbolExp *) e)->s;
-			    stmt->isBranchToLabel = lbl->ident;
-
-			    use_star = false;
-			    addLabel(lbl->ident->toChars());
-			} else if ((decl && decl->isCodeseg())) { // if function or label
-			    use_star = false;
-			    addOperand2("${", ":c}", Arg_Pointer, e, asmcode);
-			} else {
-			    if (use_star) {
-				insnTemplate->writebyte('*');
-				use_star = false;
-			    }
-
-                if (!sc->func->naked) { // no addrexp in naked asm please :)
-                Type* tt = e->type->pointerTo();
-			    e = new AddrExp(0, e);
-			    e->type = tt;
+                    invalidExpression(); // maybe should allow, e.g. DS:EBX+EAX*4
                 }
 
-			    addOperand(fmt, Arg_Memory, e, asmcode, mode);
-			}
-		    }
-		}
-		if (use_star)
-		    insnTemplate->writebyte('*');
-		if (operand->segmentPrefix != Reg_Invalid || operand->constDisplacement) {
-		    if (operand->symbolDisplacement.dim)
-			insnTemplate->writebyte('+');
-		    //addOperand(fmt, Arg_Integer, newIntExp(operand->constDisplacement), asmcode);
-		    insnTemplate->printf("%d", operand->constDisplacement);
-		    if (opInfo->operands[i] & Opr_Dest)
-			asmcode->clobbersMemory = 1;
-		}
-		if (operand->baseReg != Reg_Invalid || operand->indexReg != Reg_Invalid) {
-		    insnTemplate->writebyte('(');
-		    if (operand->baseReg != Reg_Invalid)
-			writeReg(operand->baseReg);
-		    if (operand->indexReg != Reg_Invalid) {
-			insnTemplate->writebyte(',');
-			writeReg(operand->indexReg);
-			if (operand->scale) {
-			    insnTemplate->printf(",%d", operand->scale);
-			}
-		    }
-		    insnTemplate->writebyte(')');
-		    if (opInfo->operands[i] & Opr_Dest)
-			asmcode->clobbersMemory = 1;
-		}
-		break;
-	    case Opr_Invalid:
-		return false;
-	    }
-	}
+                if ( operand->scale || operand->indexReg != Reg_Invalid )
+                {
+                    invalidExpression();
+                    return true;
+                }
 
-	asmcode->insnTemplateLen = insnTemplate->offset;
-	asmcode->insnTemplate = (char*) insnTemplate->extractData();
-	return true;
-    }
+                operand->indexReg = ( Reg ) e1->toInteger();
+                operand->scale = e2->toInteger();
+                switch ( operand->scale )
+                {
+                    case 1:
+                    case 2:
+                    case 4:
+                    case 8:
+                        // ok; do nothing
+                        break;
+                    default:
+                        stmt->error ( "invalid index register scale '%d'", operand->scale );
+                        return true;
+                }
 
-    bool isIntExp(Expression * exp) {
-	if (exp->op == TOKint64)
-	    return 1;
-	if (exp->op == TOKvar) {
-	    Declaration * v = ((VarExp *) exp)->var;
-	    if (v->isConst() && v->type->isintegral())
-		return 1;
-	}
-	return 0;
-    }
-    bool isRegExp(Expression * exp) { return exp->op == TOKmod; } // ewww.%%
-    bool isLocalSize(Expression * exp) {
-	// cleanup: make a static var
-	return exp->op == TOKidentifier && ((IdentifierExp *) exp)->ident == Id::__LOCAL_SIZE;
-    }
-    bool isDollar(Expression * exp) {
-	return exp->op == TOKidentifier && ((IdentifierExp *) exp)->ident == Id::__dollar;
-    }
+                return true;
+            }
+            return false;
+        }
 
-    Expression * newRegExp(int regno) {
-	IntegerExp * e = new IntegerExp(regno);
-	e->op = TOKmod;
-	return e;
-    }
-
-    Expression * newIntExp(int v /* %% type */) {
-	// Only handles 32-bit numbers as this is IA-32.
-	return new IntegerExp(stmt->loc, v, Type::tint32);
-    }
+        Expression * parseMultExp()
+        {
+            Expression * e1 = parseBrExp();
+            Expression * e2;
 
-    void slotExp(Expression * exp) {
-	/*
-	  if offset, make a note
-	
-	  if integer, add to immediate
-	  if reg:
-	      if not in bracket, set reg (else error)
-	      if in bracket:
-		 if not base, set base
-		 if not index, set index
-		 else, error
-	  if symbol:
-	    set symbol field
-	 */
+            while ( 1 )
+            {
+                TOK tv = token->value;
+                switch ( tv )
+                {
+                    case TOKmul:
+                        nextToken();
+                        e2 = parseMultExp();
+                        if ( isIntExp ( e1 ) && isIntExp ( e2 ) )
+                            e1 = intOp ( tv, e1, e2 );
+                        else if ( tryScale ( e1,e2 ) )
+                            e1 = Handled;
+                        else
+                            invalidExpression();
+                        continue;
+                    case TOKdiv:
+                    case TOKmod:
+                        nextToken();
+                        e2 = parseMultExp();
+                        e1 = intOp ( tv, e1, e2 );
+                        continue;
+                    default:
+                        break;
+                }
+                break;
+            }
+            return e1;
+        }
 
-	bool is_offset = false;
-	if (exp->op == TOKaddress) {
-	    exp = ((AddrExp *) exp)->e1;
-	    is_offset = true;
-	}
-	
-	if (isIntExp(exp)) {
-	    if (is_offset)
-		invalidExpression();
-	    operand->constDisplacement += exp->toInteger();
-	    if (! operand->inBracket)
-		operand->hasNumber = 1;
-	} else if (isRegExp(exp)) {
-	    if (is_offset)
-		invalidExpression();
-	    if (! operand->inBracket) {
-		if (operand->reg == Reg_Invalid)
-		    operand->reg = (Reg) exp->toInteger();
-		else
-		    stmt->error("too many registers in operand (use brackets)");
-	    } else {
-		if (operand->baseReg == Reg_Invalid)
-		    operand->baseReg = (Reg) exp->toInteger();
-		else if (operand->indexReg == Reg_Invalid) {
-		    operand->indexReg = (Reg) exp->toInteger();
-		    operand->scale = 1;
-		} else {
-		    stmt->error("too many registers memory operand");
-		}
-	    }
-	} else if (exp->op == TOKvar) {
-	    VarDeclaration * v = ((VarExp *) exp)->var->isVarDeclaration();
+        Expression * parseBrExp()
+        {
+            // %% check (why is bracket lower precends..)
+            // 3+4[eax] -> 3 + (4 [EAX]) ..
+
+            // only one bracked allowed, so this doesn't quite handle
+            // the spec'd syntax
+            Expression * e;
+
+            if ( token->value == TOKlbracket )
+                e = Handled;
+            else
+                e = parseUnaExp();
 
-	    if (v && v->storage_class & STCfield) {
-		operand->constDisplacement += v->offset;
-		if (! operand->inBracket)
-		    operand->hasNumber = 1;
-	    } else {
-		if (v && v->type->isscalar())
-		{
-		    // DMD doesn't check Tcomplex*, and counts Tcomplex32 as Tfloat64
-		    TY ty = v->type->toBasetype()->ty;
-		    operand->dataSizeHint = ty == Tfloat80 || ty == Timaginary80 ?
-			Extended_Ptr : (PtrType) v->type->size(0);
-		}
-		
-		if (! operand->symbolDisplacement.dim) {
-		    if (is_offset && ! operand->inBracket)
-			operand->isOffset = 1;
-		    operand->symbolDisplacement.push( exp );
-		} else {
-		    stmt->error("too many symbols in operand");
-		}
-	    }
-	} else if (exp->op == TOKidentifier || exp->op == TOKdsymbol) {
-	    // %% localsize could be treated as a simple constant..
-	    // change to addSymbolDisp(e)
-	    if (! operand->symbolDisplacement.dim) {
-		operand->symbolDisplacement.push( exp );
-	    } else {
-		stmt->error("too many symbols in operand");
-	    }
-	} else if (exp == Handled) {
-	    // nothing
-	} else {
-	    stmt->error("invalid operand");
-	}
-    }
+            // DMD allows multiple bracket expressions.
+            while ( token->value == TOKlbracket )
+            {
+                nextToken();
+
+                operand->inBracket = operand->hasBracket = 1;
+                slotExp ( parseAsmExp() );
+                operand->inBracket = 0;
 
-    void invalidExpression() {
-	// %% report operand number
-	stmt->error("invalid expression");
-    }
+                if ( token->value == TOKrbracket )
+                    nextToken();
+                else
+                    stmt->error ( "missing ']'" );
+            }
+
+            return e;
+        }
 
-    Expression * intOp(TOK op, Expression * e1, Expression * e2) {
-	Expression * e;
-	if (isIntExp(e1) && (! e2 || isIntExp(e2))) {
-	    switch (op) {
-	    case TOKadd:
-		if (e2)
-		    e = new AddExp(stmt->loc, e1, e2);
-		else
-		    e = e1;
-		break;
-	    case TOKmin:
-		if (e2)
-		    e = new MinExp(stmt->loc, e1, e2);
-		else
-		    e = new NegExp(stmt->loc, e1);
-		break;
-	    case TOKmul:
-		e = new MulExp(stmt->loc, e1, e2);
-		break;
-	    case TOKdiv:
-		e = new DivExp(stmt->loc, e1, e2);
-		break;
-	    case TOKmod:
-		e = new ModExp(stmt->loc, e1, e2);
-		break;
-	    case TOKshl:
-		e = new ShlExp(stmt->loc, e1, e2);
-		break;
-	    case TOKshr:
-		e = new ShrExp(stmt->loc, e1, e2);
-		break;
-	    case TOKushr:
-		e = new UshrExp(stmt->loc, e1, e2);
-		break;
-	    case TOKnot:
-		e = new NotExp(stmt->loc, e1);
-		break;
-	    case TOKtilde:
-		e = new ComExp(stmt->loc, e1);
-		break;
-	    default:
-		assert(0);
-	    }
-	    e = e->semantic(sc);
-	    return e->optimize(WANTvalue | WANTinterpret);
-	} else {
-	    stmt->error("expected integer operand(s) for '%s'", Token::tochars[op]);
-	    return newIntExp(0);
-	}
-    }
+        PtrType isPtrType ( Token * tok )
+        {
+            switch ( tok->value )
+            {
+                case TOKint8: return Byte_Ptr;
+                case TOKint16: return Short_Ptr;
+                case TOKint32: return Int_Ptr;
+                    // 'long ptr' isn't accepted?
+                case TOKfloat32: return Float_Ptr;
+                case TOKfloat64: return Double_Ptr;
+                case TOKfloat80: return Extended_Ptr;
+                case TOKidentifier:
+                    for ( int i = 0; i < N_PtrNames; i++ )
+                        if ( tok->ident == ptrTypeIdentTable[i] )
+                            return ptrTypeValueTable[i];
+                    break;
+                default:
+                    break;
+            }
+            return Default_Ptr;
+        }
 
-    void parseOperand() {
-	Expression * exp = parseAsmExp();
-	slotExp(exp);
-	if (isRegExp(exp))
-	    operand->dataSize = (PtrType) regInfo[exp->toInteger()].size;
-    }
+        Expression * parseUnaExp()
+        {
+            Expression * e = NULL;
+            PtrType ptr_type;
 
-    Expression * parseAsmExp() {
-	return parseShiftExp();
-    }
-
-    Expression * parseShiftExp() {
-	Expression * e1 = parseAddExp();
-	Expression * e2;
+            // First, check for type prefix.
+            if ( token->value != TOKeof &&
+                    peekToken()->value == TOKidentifier &&
+                    peekToken()->ident == Id::ptr )
+            {
 
-	while (1) {
-	    TOK tv = token->value;
-	    switch (tv) {
-	    case TOKshl:
-	    case TOKshr:
-	    case TOKushr:
-		nextToken();
-		e2 = parseAddExp();
-		e1 = intOp(tv, e1, e2);
-		continue;
-	    default:
-		break;
-	    }
-	    break;
-	}
-	return e1;
-    }
-
-    Expression * parseAddExp() {
-	Expression * e1 = parseMultExp();
-	Expression * e2;
+                ptr_type = isPtrType ( token );
+                if ( ptr_type != Default_Ptr )
+                {
+                    if ( operand->dataSize == Default_Ptr )
+                        operand->dataSize = ptr_type;
+                    else
+                        stmt->error ( "multiple specifications of operand size" );
+                }
+                else
+                    stmt->error ( "unknown operand size '%s'", token->toChars() );
+                nextToken();
+                nextToken();
+                return parseAsmExp();
+            }
 
-	while (1) {
-	    TOK tv = token->value;
-	    switch (tv) {
-	    case TOKadd:
-		nextToken();
-		e2 = parseMultExp();
-		if (isIntExp(e1) && isIntExp(e2))
-		    e1 = intOp(tv, e1, e2);
-		else {
-		    slotExp(e1);
-		    slotExp(e2);
-		    e1 = Handled;
-		}
-		continue;
-	    case TOKmin:
-		// Note: no support for symbol address difference
-		nextToken();
-		e2 = parseMultExp();
-		if (isIntExp(e1) && isIntExp(e2))
-		    e1 = intOp(tv, e1, e2);
-		else {
-		    slotExp(e1);
-		    e2 = intOp(TOKmin, e2, NULL); // verifies e2 is an int
-		    slotExp(e2);
-		    e1 = Handled;
-		}
-		continue;
-	    default:
-		break;
-	    }
-	    break;
-	}
-	return e1;
-    }
+            TOK tv = token->value;
+            switch ( tv )
+            {
+                case TOKidentifier:
+                    if ( token->ident == ident_seg )
+                    {
+                        nextToken();
+                        stmt->error ( "'seg' not supported" );
+                        e = parseAsmExp();
+                    }
+                    else if ( token->ident == Id::offset ||
+                              token->ident == Id::offsetof )
+                    {
+                        if ( token->ident == Id::offset && ! global.params.useDeprecated )
+                            stmt->error ( "offset deprecated, use offsetof" );
+                        nextToken();
+                        e = parseAsmExp();
+                        e = new AddrExp ( stmt->loc, e );
+                    }
+                    else
+                    {
+                        // primary exp
+                        break;
+                    }
+                    return e;
+                case TOKadd:
+                case TOKmin:
+                case TOKnot:
+                case TOKtilde:
+                    nextToken();
+                    e = parseUnaExp();
+                    return intOp ( tv, e, NULL );
+                default:
+                    // primary exp
+                    break;
+            }
+            return parsePrimaryExp();
+        }
 
-    bool tryScale(Expression * e1, Expression * e2) {
-	Expression * et;
-	if (isIntExp(e1) && isRegExp(e2)) {
-	    et = e1;
-	    e1 = e2;
-	    e2 = et;
-	    goto do_scale;
-	} else if (isRegExp(e1) && isIntExp(e2)) {
-	do_scale:
-	    if (! operand->inBracket) {
-		invalidExpression(); // maybe should allow, e.g. DS:EBX+EAX*4
-	    }
-	    
-	    if (operand->scale || operand->indexReg != Reg_Invalid) {
-		invalidExpression();
-		return true;
-	    }
+        Expression * parsePrimaryExp()
+        {
+            Expression * e;
+            Identifier * ident = NULL;
 
-	    operand->indexReg = (Reg) e1->toInteger();
-	    operand->scale = e2->toInteger();
-	    switch (operand->scale) {
-	    case 1:
-	    case 2:
-	    case 4:
-	    case 8:
-		// ok; do nothing
-		break;
-	    default:
-		stmt->error("invalid index register scale '%d'", operand->scale);
-		return true;
-	    }
-	    
-	    return true;
-	}
-	return false;
-    }
-
-    Expression * parseMultExp() {
-	Expression * e1 = parseBrExp();
-	Expression * e2;
+            switch ( token->value )
+            {
+                case TOKint32v:
+                case TOKuns32v:
+                case TOKint64v:
+                case TOKuns64v:
+                    // semantic here?
+                    // %% for tok64 really should use 64bit type
+                    e = new IntegerExp ( stmt->loc, token->uns64value, Type::tint32 );
+                    nextToken();
+                    break;
+                case TOKfloat32v:
+                case TOKfloat64v:
+                case TOKfloat80v:
+                    // %% need different types?
+                    e = new RealExp ( stmt->loc, token->float80value, Type::tfloat80 );
+                    nextToken();
+                    break;
+                case TOKidentifier:
+                {
+                    ident = token->ident;
+                    nextToken();
 
-	while (1) {
-	    TOK tv = token->value;
-	    switch (tv) {
-	    case TOKmul:
-		nextToken();
-		e2 = parseMultExp();
-		if (isIntExp(e1) && isIntExp(e2))
-		    e1 = intOp(tv, e1, e2);
-		else if (tryScale(e1,e2))
-		    e1 = Handled;
-		else
-		    invalidExpression();
-		continue;
-	    case TOKdiv:
-	    case TOKmod:
-		nextToken();
-		e2 = parseMultExp();
-		e1 = intOp(tv, e1, e2);
-		continue;
-	    default:
-		break;
-	    }
-	    break;
-	}
-	return e1;
-    }
+                    if ( ident == Id::__LOCAL_SIZE )
+                    {
+                        return new IdentifierExp ( stmt->loc, ident );
+                    }
+                    else if ( ident == Id::__dollar )
+                    {
+                    do_dollar:
+                        return new IdentifierExp ( stmt->loc, ident );
+                    }
+                    else
+                    {
+                        e = new IdentifierExp ( stmt->loc, ident );
+                    }
 
-    Expression * parseBrExp() {
-	// %% check (why is bracket lower precends..)
-	// 3+4[eax] -> 3 + (4 [EAX]) ..
-	
-	// only one bracked allowed, so this doesn't quite handle
-	// the spec'd syntax
-	Expression * e;
-	
-	if (token->value == TOKlbracket)
-	    e = Handled;
-	else
-	    e = parseUnaExp();
-
-	// DMD allows multiple bracket expressions.
-	while (token->value == TOKlbracket) {
-	    nextToken();
-	    
-	    operand->inBracket = operand->hasBracket = 1;
-	    slotExp(parseAsmExp());
-	    operand->inBracket = 0;
-
-	    if (token->value == TOKrbracket)
-		nextToken();
-	    else
-		stmt->error("missing ']'");
-	}
-
-	return e;
-    }
-
-    PtrType isPtrType(Token * tok) {
-	switch (tok->value) {
-	case TOKint8: return Byte_Ptr;
-	case TOKint16: return Short_Ptr;
-	case TOKint32: return Int_Ptr;
-	    // 'long ptr' isn't accepted?
-	case TOKfloat32: return Float_Ptr;
-	case TOKfloat64: return Double_Ptr;
-	case TOKfloat80: return Extended_Ptr;
-	case TOKidentifier:
-	    for (int i = 0; i < N_PtrNames; i++)
-		if (tok->ident == ptrTypeIdentTable[i])
-		    return ptrTypeValueTable[i];
-	    break;
-	default:
-	    break;
-	}
-	return Default_Ptr;
-    }
-
-    Expression * parseUnaExp() {
-	Expression * e = NULL;
-	PtrType ptr_type;
-	
-	// First, check for type prefix.
-	if (token->value != TOKeof &&
-	    peekToken()->value == TOKidentifier &&
-	    peekToken()->ident == Id::ptr) {
-
-	    ptr_type = isPtrType(token);
-	    if (ptr_type != Default_Ptr) {
-		if (operand->dataSize == Default_Ptr)
-		    operand->dataSize = ptr_type;
-		else
-		    stmt->error("multiple specifications of operand size");
-	    } else
-		stmt->error("unknown operand size '%s'", token->toChars());
-	    nextToken();
-	    nextToken();
-	    return parseAsmExp();
-	}
+                    // If this is more than one component ref, it gets complicated: *(&Field + n)
+                    // maybe just do one step at a time..
+                    // simple case is Type.f -> VarDecl(field)
+                    // actually, DMD only supports on level...
+                    // X.y+Y.z[EBX] is supported, tho..
+                    // %% doesn't handle properties (check%%)
+                    while ( token->value == TOKdot )
+                    {
+                        nextToken();
+                        if ( token->value == TOKidentifier )
+                        {
+                            e = new DotIdExp ( stmt->loc, e, token->ident );
+                            nextToken();
+                        }
+                        else
+                        {
+                            stmt->error ( "expected identifier" );
+                            return Handled;
+                        }
+                    }
 
-	TOK tv = token->value;
-	switch (tv) {
-	case TOKidentifier:
-	    if (token->ident == ident_seg) {
-		nextToken();
-		stmt->error("'seg' not supported");
-		e = parseAsmExp();
-	    } else if (token->ident == Id::offset ||
-		       token->ident == Id::offsetof) {
-		if (token->ident == Id::offset && ! global.params.useDeprecated)
-		    stmt->error("offset deprecated, use offsetof");
-		nextToken();
-		e = parseAsmExp();
-		e = new AddrExp(stmt->loc, e);
-	    } else {
-		// primary exp
-		break;
-	    }
-	    return e;
-	case TOKadd:
-	case TOKmin:
-	case TOKnot:
-	case TOKtilde:
-	    nextToken();
-	    e = parseUnaExp();
-	    return intOp(tv, e, NULL);
-	default:
-	    // primary exp
-	    break;
-	}
-	return parsePrimaryExp();
-    }
+                    // check for reg first then dotexp is an error?
+                    if ( e->op == TOKidentifier )
+                    {
+                        for ( int i = 0; i < N_Regs; i++ )
+                        {
+                            if ( ident == regInfo[i].ident )
+                            {
+                                if ( ( Reg ) i == Reg_ST && token->value == TOKlparen )
+                                {
+                                    nextToken();
+                                    switch ( token->value )
+                                    {
+                                    case TOKint32v: case TOKuns32v:
+                                    case TOKint64v: case TOKuns64v:
+                                            if ( token->uns64value < 8 )
+                                                e = newRegExp ( ( Reg ) ( Reg_ST + token->uns64value ) );
+                                            else
+                                            {
+                                                stmt->error ( "invalid floating point register index" );
+                                                e = Handled;
+                                            }
+                                            nextToken();
+                                            if ( token->value == TOKrparen )
+                                                nextToken();
+                                            else
+                                                stmt->error ( "expected ')'" );
+                                            return e;
+                                        default:
+                                            break;
+                                    }
+                                    invalidExpression();
+                                    return Handled;
+                                }
+                                else if ( token->value == TOKcolon )
+                                {
+                                    nextToken();
+                                    if ( operand->segmentPrefix != Reg_Invalid )
+                                        stmt->error ( "too many segment prefixes" );
+                                    else if ( i >= Reg_CS && i <= Reg_GS )
+                                        operand->segmentPrefix = ( Reg ) i;
+                                    else
+                                        stmt->error ( "'%s' is not a segment register", ident->string );
+                                    return parseAsmExp();
+                                }
+                                else
+                                {
+                                    return newRegExp ( ( Reg ) i );
+                                }
+                            }
+                        }
+                    }
 
-    Expression * parsePrimaryExp() {
-	Expression * e;
-	Identifier * ident = NULL;
-	
-	switch (token->value) {
-	case TOKint32v:
-	case TOKuns32v:
-	case TOKint64v:
-	case TOKuns64v:
-	    // semantic here?
-	    // %% for tok64 really should use 64bit type
-	    e = new IntegerExp(stmt->loc, token->uns64value, Type::tint32);
-	    nextToken();
-	    break;
-	case TOKfloat32v:
-	case TOKfloat64v:
-	case TOKfloat80v:
-	    // %% need different types?
-        e = new RealExp(stmt->loc, token->float80value, Type::tfloat80);
-	    nextToken();
-	    break;
-	case TOKidentifier:
-	    {
-		ident = token->ident;
-		nextToken();
-		
-		if (ident == Id::__LOCAL_SIZE) {
-		    return new IdentifierExp(stmt->loc, ident);
-		} else if (ident == Id::__dollar) {
-		do_dollar:
-		    return new IdentifierExp(stmt->loc, ident);
-		} else {
-		    e = new IdentifierExp(stmt->loc, ident);
-		}
+                    if ( opTakesLabel() /*opInfo->takesLabel()*/ && e->op == TOKidentifier )
+                    {
+                        // DMD uses labels secondarily to other symbols, so check
+                        // if IdentifierExp::semantic won't find anything.
+                        Dsymbol *scopesym;
+
+                        if ( ! sc->search ( stmt->loc, ident, & scopesym ) )
+                            return new DsymbolExp ( stmt->loc,
+                                                    sc->func->searchLabel ( ident ) );
+                    }
+
+                    e = e->semantic ( sc );
 
-		// If this is more than one component ref, it gets complicated: *(&Field + n)
-		// maybe just do one step at a time..
-		// simple case is Type.f -> VarDecl(field)
-		// actually, DMD only supports on level...
-		// X.y+Y.z[EBX] is supported, tho..
-		// %% doesn't handle properties (check%%)
-		while (token->value == TOKdot) {
-		    nextToken();
-		    if (token->value == TOKidentifier) {
-			e = new DotIdExp(stmt->loc, e, token->ident);
-			nextToken();
-		    } else {
-			stmt->error("expected identifier");
-			return Handled;
-		    }
-		}
+                    // Special case for floating point constant declarations.
+                    if ( e->op == TOKfloat64 )
+                    {
+                        Dsymbol * sym = sc->search ( stmt->loc, ident, NULL );
+                        if ( sym )
+                        {
+                            VarDeclaration *v = sym->isVarDeclaration();
+                            if ( v )
+                            {
+                                Expression *ve = new VarExp ( stmt->loc, v );
+                                ve->type = e->type;
+                                e = ve;
+                            }
+                        }
+                    }
+                    return e;
+                }
+                break;
+                case TOKdollar:
+                    nextToken();
+                    ident = Id::__dollar;
+                    goto do_dollar;
+                    break;
+                default:
+                    invalidExpression();
+                    return Handled;
+            }
+            return e;
+        }
+
+        void doAlign()
+        {
+            // .align bits vs. bytes...
+            // apparently a.out platforms use bits instead of bytes...
 
-		// check for reg first then dotexp is an error?
-		if (e->op == TOKidentifier) {
-		    for (int i = 0; i < N_Regs; i++) {
-			if (ident == regInfo[i].ident) {
-			    if ( (Reg) i == Reg_ST && token->value == TOKlparen) {
-				nextToken();
-				switch (token->value) {
-				case TOKint32v: case TOKuns32v:
-				case TOKint64v: case TOKuns64v:
-				    if (token->uns64value < 8)
-					e = newRegExp( (Reg) (Reg_ST + token->uns64value) );
-				    else {
-					stmt->error("invalid floating point register index");
-					e = Handled;
-				    }
-				    nextToken();
-				    if (token->value == TOKrparen)
-					nextToken();
-				    else
-					stmt->error("expected ')'");
-				    return e;
-				default:
-				    break;
-				}
-				invalidExpression();
-				return Handled;
-			    } else if (token->value == TOKcolon) {
-				nextToken();
-				if (operand->segmentPrefix != Reg_Invalid)
-				    stmt->error("too many segment prefixes");
-				else if (i >= Reg_CS && i <= Reg_GS)
-				    operand->segmentPrefix = (Reg) i;
-				else
-				    stmt->error("'%s' is not a segment register", ident->string);
-				return parseAsmExp();
-			    } else {
-				return newRegExp( (Reg) i );
-			    }
-			}
-		    }
-		}
-		
-		if (opTakesLabel()/*opInfo->takesLabel()*/ && e->op == TOKidentifier) {
-		    // DMD uses labels secondarily to other symbols, so check
-		    // if IdentifierExp::semantic won't find anything.
-		    Dsymbol *scopesym;
-		    
-		    if ( ! sc->search(stmt->loc, ident, & scopesym) )		    
-			return new DsymbolExp(stmt->loc,
-			    sc->func->searchLabel( ident ));
-		}
+            // parse primary: DMD allows 'MyAlign' (const int) but not '2+2'
+            // GAS is padding with NOPs last time I checked.
+            Expression * e = parseAsmExp()->optimize ( WANTvalue | WANTinterpret );
+            uinteger_t align = e->toUInteger();
 
-		e = e->semantic(sc);
+            if ( ( align & ( align - 1 ) ) == 0 )
+            {
+                //FIXME: This printf is not portable. The use of `align` varies from system to system;
+                // on i386 using a.out, .align `n` will align on a 2^`n` boundary instead of an `n` boundary
+#ifdef HAVE_GAS_BALIGN_AND_P2ALIGN
+                insnTemplate->printf ( ".balign\t%u", ( unsigned ) align );
+#else
+                insnTemplate->printf ( ".align\t%u", ( unsigned ) align );
+#endif
+            }
+            else
+            {
+                stmt->error ( "alignment must be a power of 2, not %u", ( unsigned ) align );
+            }
 
-		// Special case for floating point constant declarations.
-		if (e->op == TOKfloat64) {
-		    Dsymbol * sym = sc->search(stmt->loc, ident, NULL);
-		    if ( sym ) {
-			VarDeclaration *v = sym->isVarDeclaration();
-			if ( v ) {
-			    Expression *ve = new VarExp(stmt->loc, v);
-			    ve->type = e->type;
-			    e = ve;
-			}
-		    }			    
-		}
-		return e;
-	    }
-	    break;
-	case TOKdollar:
-	    nextToken();
-	    ident = Id::__dollar;
-	    goto do_dollar;
-	    break;
-	default:
-	    invalidExpression();
-	    return Handled;
-	}
-	return e;
-    }
+            setAsmCode();
+        }
 
-    void doAlign() {
-	// .align bits vs. bytes...
-	// apparently a.out platforms use bits instead of bytes...
-
-	// parse primary: DMD allows 'MyAlign' (const int) but not '2+2'
-	// GAS is padding with NOPs last time I checked.
-	Expression * e = parseAsmExp()->optimize(WANTvalue | WANTinterpret);
-	uinteger_t align = e->toUInteger();
-
-	if ((align & (align - 1)) == 0) {
-	    //FIXME: This printf is not portable. The use of `align` varies from system to system; 
-	    // on i386 using a.out, .align `n` will align on a 2^`n` boundary instead of an `n` boundary
-#ifdef HAVE_GAS_BALIGN_AND_P2ALIGN 
-	    insnTemplate->printf(".balign\t%u", (unsigned) align);
+        void doEven()
+        {
+            // .align for GAS is in bits, others probably use bytes..
+#ifdef HAVE_GAS_BALIGN_AND_P2ALIGN
+            insnTemplate->writestring ( ( char * ) ".align\t2" );
 #else
-	    insnTemplate->printf(".align\t%u", (unsigned) align);
+            insnTemplate->writestring ( ( char * ) ".align\t2" );
 #endif
-	} else {
-	    stmt->error("alignment must be a power of 2, not %u", (unsigned) align);
-	}
+            setAsmCode();
+        }
 
-	setAsmCode();
-    }
+        void doNaked()
+        {
+            // %% can we assume sc->func != 0?
+            sc->func->naked = 1;
+        }
 
-    void doEven() {
-	// .align for GAS is in bits, others probably use bytes..
-#ifdef HAVE_GAS_BALIGN_AND_P2ALIGN 
-	insnTemplate->writestring((char *) ".align\t2");
-#else
-	insnTemplate->writestring((char *) ".align\t2");
-#endif
-	setAsmCode();
-    }
+        void doData()
+        {
+            static const char * directives[] = { ".byte", ".short", ".long", ".long",
+                                                 "", "", ""
+                                               };
+// FIXME
+            /*
+                machine_mode mode;
 
-    void doNaked() {
-	// %% can we assume sc->func != 0?
-	sc->func->naked = 1;
-    }
-
-    void doData() {
-	static const char * directives[] = { ".byte", ".short", ".long", ".long",
-					     "", "", "" };
-// FIXME
-/*
-	machine_mode mode;
-
-	insnTemplate->writestring((char*) directives[op - Op_db]);
-	insnTemplate->writebyte(' ');
+                insnTemplate->writestring((char*) directives[op - Op_db]);
+                insnTemplate->writebyte(' ');
 
-	do {
-	    // DMD is pretty strict here, not even constant expressions are allowed..
-	    switch (op) {
-	    case Op_db:
-	    case Op_ds:
-	    case Op_di:
-	    case Op_dl:
-		if (token->value == TOKint32v || token->value == TOKuns32v ||
-		    token->value == TOKint64v || token->value == TOKuns64v) {
-		    // As per usual with GNU, assume at least 32-bit host
-		    if (op != Op_dl)
-			insnTemplate->printf("%u", (d_uns32) token->uns64value);
-		    else {
-			// Output two .longS.  GAS has .quad, but would have to rely on 'L' format ..
-			// just need to use HOST_WIDE_INT_PRINT_DEC
-			insnTemplate->printf("%u,%u",
-			    (d_uns32) token->uns64value, (d_uns32) (token->uns64value >> 32));
-		    }
-		} else {
-		    stmt->error("expected integer constant");
-		}
-		break;
-	    case Op_df:
-		mode = SFmode;
-		goto do_float;
-	    case Op_dd:
-		mode = DFmode;
-		goto do_float;
-	    case Op_de:
-#ifndef TARGET_80387
-#define XFmode TFmode
-#endif
-		mode = XFmode; // not TFmode
-		// drop through
-	    do_float:
-		if (token->value == TOKfloat32v || token->value == TOKfloat64v ||
-		    token->value == TOKfloat80v) {
-		    long words[3];
-		    real_to_target(words, & token->float80value.rv(), mode);
-		    // don't use directives..., just use .long like GCC
-		    insnTemplate->printf(".long\t%u", words[0]);
-		    if (mode != SFmode)
-			insnTemplate->printf(",%u", words[1]);
-		    // DMD outputs 10 bytes, so we need to switch to .short here
-		    if (mode == XFmode)
-			insnTemplate->printf("\n\t.short\t%u", words[2]);
-		} else {
-		    stmt->error("expected float constant");
-		}
-		break;
-	    default:
-		abort();
-	    }
-	    
-	    nextToken();	    
-	    if (token->value == TOKcomma) {
-		insnTemplate->writebyte(',');
-		nextToken();
-	    } else if (token->value == TOKeof) {
-		break;
-	    } else {
-		stmt->error("expected comma");
-	    }
-	} while (1);
+                do {
+                    // DMD is pretty strict here, not even constant expressions are allowed..
+                    switch (op) {
+                    case Op_db:
+                    case Op_ds:
+                    case Op_di:
+                    case Op_dl:
+                    if (token->value == TOKint32v || token->value == TOKuns32v ||
+                        token->value == TOKint64v || token->value == TOKuns64v) {
+                        // As per usual with GNU, assume at least 32-bit host
+                        if (op != Op_dl)
+                        insnTemplate->printf("%u", (d_uns32) token->uns64value);
+                        else {
+                        // Output two .longS.  GAS has .quad, but would have to rely on 'L' format ..
+                        // just need to use HOST_WIDE_INT_PRINT_DEC
+                        insnTemplate->printf("%u,%u",
+                            (d_uns32) token->uns64value, (d_uns32) (token->uns64value >> 32));
+                        }
+                    } else {
+                        stmt->error("expected integer constant");
+                    }
+                    break;
+                    case Op_df:
+                    mode = SFmode;
+                    goto do_float;
+                    case Op_dd:
+                    mode = DFmode;
+                    goto do_float;
+                    case Op_de:
+            #ifndef TARGET_80387
+            #define XFmode TFmode
+            #endif
+                    mode = XFmode; // not TFmode
+                    // drop through
+                    do_float:
+                    if (token->value == TOKfloat32v || token->value == TOKfloat64v ||
+                        token->value == TOKfloat80v) {
+                        long words[3];
+                        real_to_target(words, & token->float80value.rv(), mode);
+                        // don't use directives..., just use .long like GCC
+                        insnTemplate->printf(".long\t%u", words[0]);
+                        if (mode != SFmode)
+                        insnTemplate->printf(",%u", words[1]);
+                        // DMD outputs 10 bytes, so we need to switch to .short here
+                        if (mode == XFmode)
+                        insnTemplate->printf("\n\t.short\t%u", words[2]);
+                    } else {
+                        stmt->error("expected float constant");
+                    }
+                    break;
+                    default:
+                    abort();
+                    }
 
-	setAsmCode();*/
-    }
-};
+                    nextToken();
+                    if (token->value == TOKcomma) {
+                    insnTemplate->writebyte(',');
+                    nextToken();
+                    } else if (token->value == TOKeof) {
+                    break;
+                    } else {
+                    stmt->error("expected comma");
+                    }
+                } while (1);
+
+                setAsmCode();*/
+        }
+    };
 
 #if D_GCC_VER < 40
 // struct rtx was modified for c++; this macro from rtl.h needs to
 // be modified accordingly.
 #undef XEXP
-#define XEXP(RTX, N)	(RTL_CHECK2 (RTX, N, 'e', 'u').rt_rtx)
+#define XEXP(RTX, N)    (RTL_CHECK2 (RTX, N, 'e', 'u').rt_rtx)
 #endif
 
 // FIXME
-    #define HOST_WIDE_INT long
-bool getFrameRelativeValue(LLValue* decl, HOST_WIDE_INT * result)
-{
-    assert(0);
+#define HOST_WIDE_INT long
+    bool getFrameRelativeValue ( LLValue* decl, HOST_WIDE_INT * result )
+    {
+        assert ( 0 );
 // FIXME
 //     // Using this instead of DECL_RTL for struct args seems like a
 //     // good way to get hit by a truck because it may not agree with
 //     // non-asm access, but asm code wouldn't know what GCC does anyway. */
 //     rtx r = DECL_INCOMING_RTL(decl);
 //     rtx e1, e2;
-// 
+//
 //     // Local variables don't have DECL_INCOMING_RTL
 //     if (r == NULL_RTX)
-// 	r = DECL_RTL(decl);
-// 
+//  r = DECL_RTL(decl);
+//
 //     if (r != NULL_RTX && GET_CODE(r) == MEM /* && r->frame_related */ ) {
-// 	r = XEXP(r, 0);
-// 	if (GET_CODE(r) == PLUS) {
-// 	    e1 = XEXP(r, 0);
-// 	    e2 = XEXP(r, 1);
-// 	    if (e1 == virtual_incoming_args_rtx && GET_CODE(e2) == CONST_INT) {
-// 		*result = INTVAL(e2) + 8; // %% 8 is 32-bit specific...
-// 		return true;
-// 	    } else if (e1 == virtual_stack_vars_rtx && GET_CODE(e2) == CONST_INT) {
-// 		*result = INTVAL(e2); // %% 8 is 32-bit specific...
-// 		return true;
-// 	    }
-// 	} else if (r == virtual_incoming_args_rtx) {
-// 	    *result = 8;
-// 	    return true; // %% same as above
-// 	}
-// 	// shouldn't have virtual_stack_vars_rtx by itself
+//  r = XEXP(r, 0);
+//  if (GET_CODE(r) == PLUS) {
+//      e1 = XEXP(r, 0);
+//      e2 = XEXP(r, 1);
+//      if (e1 == virtual_incoming_args_rtx && GET_CODE(e2) == CONST_INT) {
+//      *result = INTVAL(e2) + 8; // %% 8 is 32-bit specific...
+//      return true;
+//      } else if (e1 == virtual_stack_vars_rtx && GET_CODE(e2) == CONST_INT) {
+//      *result = INTVAL(e2); // %% 8 is 32-bit specific...
+//      return true;
+//      }
+//  } else if (r == virtual_incoming_args_rtx) {
+//      *result = 8;
+//      return true; // %% same as above
+//  }
+//  // shouldn't have virtual_stack_vars_rtx by itself
 //     }
-//     
-    return false;
-}
+//
+        return false;
+    }
 
 
-struct AsmParser : public AsmParserCommon
-{
-    virtual void run(Scope* sc, AsmStatement* asmst) {
-        AsmProcessor ap(sc, asmst);
-        ap.run();
-    }
+    struct AsmParser : public AsmParserCommon
+    {
+        virtual void run ( Scope* sc, AsmStatement* asmst )
+        {
+            AsmProcessor ap ( sc, asmst );
+            ap.run();
+        }
 
-    virtual std::string getRegName(int i) {
-        return regInfo[i].gccName;
-    }
-};
+        virtual std::string getRegName ( int i )
+        {
+            return regInfo[i].gccName;
+        }
+    };
 
 }