From: Julian Seward Date: Wed, 30 Jun 2004 16:37:16 +0000 (+0000) Subject: Try to get x86 instruction representation to something sane, and fix X-Git-Tag: svn/VALGRIND_3_0_1^2~1307 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=ce9eeea10a82b07ca8965282e8b0dea75a90b55d;p=thirdparty%2Fvalgrind.git Try to get x86 instruction representation to something sane, and fix up the selector accordingly. git-svn-id: svn://svn.valgrind.org/vex/trunk@27 --- diff --git a/VEX/include/ir_defs.h b/VEX/include/ir_defs.h index e666146e20..ae3082cd41 100644 --- a/VEX/include/ir_defs.h +++ b/VEX/include/ir_defs.h @@ -116,7 +116,7 @@ typedef struct _IRExpr* addr; } LDle; struct { - struct _IRConst* con; + IRConst* con; } Const; } Iex; } @@ -187,19 +187,19 @@ typedef IRNextTag; typedef - struct _IRNext { + struct { IRNextTag tag; union { struct { - struct _IRConst* dst; + IRConst* dst; } UJump; struct { - struct _IRExpr* cond; - struct _IRConst* dst0; - struct _IRConst* dst1; + IRExpr* cond; + IRConst* dst0; + IRConst* dst1; } CJump01; struct { - struct _IRExpr* dst; + IRExpr* dst; } IJump; } Inx; } diff --git a/VEX/include/x86h_defs.h b/VEX/include/x86h_defs.h index 30c1185719..e60a9e38a4 100644 --- a/VEX/include/x86h_defs.h +++ b/VEX/include/x86h_defs.h @@ -23,8 +23,8 @@ extern void ppHRegX86 ( FILE*, HReg ); typedef enum { - Xam_IR, - Xam_IRRS + Xam_IR, /* Immediate + Reg */ + Xam_IRRS /* Immediate + Reg1 + (Reg2 << Shift) */ } X86AModeTag; @@ -52,19 +52,19 @@ extern X86AMode* X86AMode_IRRS ( UInt, HReg, HReg, Int ); extern void ppX86AMode ( FILE*, X86AMode* ); -/* --------- Operands. Not all are valid for all insns. --------- */ +/* --------- Operand, which can be reg, immediate or memory. --------- */ typedef enum { - Xop_Imm, - Xop_Reg, - Xop_Mem + Xrmi_Imm, + Xrmi_Reg, + Xrmi_Mem } - X86OperandTag; + X86RMITag; typedef struct { - X86OperandTag tag; + X86RMITag tag; union { struct { UInt imm32; @@ -76,33 +76,109 @@ typedef X86AMode* am; } Mem; } - Xop; + Xrmi; } - X86Operand; + X86RMI; -extern X86Operand* X86Operand_Imm ( UInt ); -extern X86Operand* X86Operand_Reg ( HReg ); -extern X86Operand* X86Operand_Mem ( X86AMode* ); +extern X86RMI* X86RMI_Imm ( UInt ); +extern X86RMI* X86RMI_Reg ( HReg ); +extern X86RMI* X86RMI_Mem ( X86AMode* ); -extern void ppX86Operand ( FILE*, X86Operand* ); +extern void ppX86RMI ( FILE*, X86RMI* ); + + +/* --------- Operand, which can be reg or immediate only. --------- */ + +typedef + enum { + Xri_Imm, + Xri_Reg + } + X86RITag; + +typedef + struct { + X86RITag tag; + union { + struct { + UInt imm32; + } Imm; + struct { + HReg reg; + } Reg; + } + Xri; + } + X86RI; + +extern X86RI* X86RI_Imm ( UInt ); +extern X86RI* X86RI_Reg ( HReg ); + +extern void ppX86RI ( FILE*, X86RI* ); + + +/* --------- Operand, which can be reg or memory only. --------- */ + +typedef + enum { + Xrm_Reg, + Xrm_Mem + } + X86RMTag; + +typedef + struct { + X86RMTag tag; + union { + struct { + HReg reg; + } Reg; + struct { + X86AMode* am; + } Mem; + } + Xrm; + } + X86RM; + +extern X86RM* X86RM_Reg ( HReg ); +extern X86RM* X86RM_Mem ( X86AMode* ); + +extern void ppX86RM ( FILE*, X86RM* ); /* --------- Instructions. --------- */ +/* --------- */ typedef - enum { Xalu_ADD, Xalu_SUB, Xalu_ADC, Xalu_SBB, Xalu_AND, Xalu_OR, Xalu_XOR } + enum { + Xalu_MOV, + Xalu_ADD, Xalu_SUB, Xalu_ADC, Xalu_SBB, + Xalu_AND, Xalu_OR, Xalu_XOR + } X86AluOp; extern void ppX86AluOp ( FILE*, X86AluOp ); +/* --------- */ +typedef + enum { + Xsh_SHL, Xsh_SHR, Xsh_SAR, + Xsh_ROL, Xsh_ROR + } + X86ShiftOp; + +extern void ppX86ShiftOp ( FILE*, X86ShiftOp ); + + +/* --------- */ typedef enum { - Xin_LD32, /* 32-bit integer load */ - Xin_ST32, /* 32-bit integer store */ - Xin_Alu32, /* 32-bit arith/logical, R-R, R-M, M-R */ - Xin_Mov32, /* 32-bit move R-R R-M M-R I-R I-M */ - Xin_Alu16 /* 16-bit arith/logical, R-R, R-M, M-R */ + Xin_Alu32R, /* 32-bit mov/arith/logical, dst=REG */ + Xin_Alu32M, /* 32-bit mov/arith/logical, dst=MEM */ + Xin_Sh32, /* 32-bit shift/rotate, dst=REG or MEM */ + Xin_RET } X86InstrTag; @@ -112,37 +188,31 @@ typedef struct { X86InstrTag tag; union { - struct { - HReg src; - X86AMode* dst; - } ST32; - struct { - X86AMode* src; - HReg dst; - } LD32; struct { - X86AluOp op; - X86Operand* src; - X86Operand* dst; - } Alu32; + X86AluOp op; + X86RMI* src; + HReg dst; + } Alu32R; struct { - X86Operand* src; - X86Operand* dst; - } Mov32; + X86AluOp op; + X86RI* src; + X86AMode* dst; + } Alu32M; struct { - X86AluOp op; - X86Operand* src; - X86Operand* dst; - } Alu16; + X86ShiftOp op; + UInt src; /* shift amount, or 0 means %cl */ + X86RM* dst; + } Sh32; + struct { + } RET; } Xin; } X86Instr; -extern X86Instr* X86Instr_ST32 ( HReg, X86AMode* ); -extern X86Instr* X86Instr_LD32 ( X86AMode*, HReg ); -extern X86Instr* X86Instr_Alu32 ( X86AluOp, X86Operand*, X86Operand* ); -extern X86Instr* X86Instr_Mov32 ( X86Operand*, X86Operand* ); -extern X86Instr* X86Instr_Alu16 ( X86AluOp, X86Operand*, X86Operand* ); +extern X86Instr* X86Instr_Alu32R ( X86AluOp, X86RMI*, HReg ); +extern X86Instr* X86Instr_Alu32M ( X86AluOp, X86RI*, X86AMode* ); +extern X86Instr* X86Instr_Sh32 ( X86ShiftOp, UInt, X86RM* ); +extern X86Instr* X86Instr_RET ( void ); extern void ppX86Instr ( FILE*, X86Instr* ); diff --git a/VEX/isel_x86.c b/VEX/isel_x86.c index 93ae6a33b6..340301e92a 100644 --- a/VEX/isel_x86.c +++ b/VEX/isel_x86.c @@ -90,6 +90,18 @@ static HReg newVRegI ( ISelEnv* env ) /*--- ISEL: Integer expressions ---*/ /*---------------------------------------------------------*/ +/* forwards ... */ +static X86RMI* iselIntExpr_RMI ( ISelEnv* env, IRExpr* e ); + + +static X86Instr* mk_MOV_RR ( HReg src, HReg dst ) +{ + assert(hregClass(src) == HRcInt); + assert(hregClass(dst) == HRcInt); + return X86Instr_Alu32R(Xalu_MOV, X86RMI_Reg(src), dst); +} + + /* Select insns for an integer-typed expression, and add them to the code list. Return a vreg holding the result. The vreg MUST NOT BE MODIFIED. If you want to modify it, ask for a new vreg, copy it in @@ -97,7 +109,7 @@ static HReg newVRegI ( ISelEnv* env ) best to map both vregs to the same real register, so the copies will often disappear later in the game. */ -HReg iselExprI ( ISelEnv* env, IRExpr* e ) +static HReg iselIntExpr_R ( ISelEnv* env, IRExpr* e ) { assert(e); assert(typeOfIRExpr(env->type_env,e) == Ity_I32); @@ -108,20 +120,18 @@ HReg iselExprI ( ISelEnv* env, IRExpr* e ) return lookupIRTemp(env, e->Iex.Tmp.tmp); case Iex_Binop: - /* Add32(x,y) */ + /* Add32(x,y). For commutative ops we assume any literal + values are on the second operand. */ if (e->Iex.Binop.op == Iop_Add32) { - HReg res = newVRegI(env); - HReg src = iselExprI(env, e->Iex.Binop.arg1); - HReg dst = iselExprI(env, e->Iex.Binop.arg2); - addInstr(env, X86Instr_Mov32( - X86Operand_Reg(dst), - X86Operand_Reg(res))); - addInstr(env, X86Instr_Alu32( - Xalu_ADD, X86Operand_Reg(src), - X86Operand_Reg(res)) ); - return res; + HReg dst = newVRegI(env); + HReg reg = iselIntExpr_R(env, e->Iex.Binop.arg1); + X86RMI* rmi = iselIntExpr_RMI(env, e->Iex.Binop.arg2); + addInstr(env, mk_MOV_RR(reg,dst)); + addInstr(env, X86Instr_Alu32R(Xalu_ADD, rmi, dst)); + return dst; } +#if 0 /* 32-bit literals */ case Iex_Const: { switch (e->Iex.Const.con->tag) { @@ -135,6 +145,7 @@ HReg iselExprI ( ISelEnv* env, IRExpr* e ) default: break; } } +#endif default: break; @@ -146,11 +157,15 @@ HReg iselExprI ( ISelEnv* env, IRExpr* e ) } -/* Similarly, return an AMode which computes the value of the - specified expression, possibly also adding insns to the code list - as a result. +/*---------------------------------------------------------*/ +/*--- ISEL: Integer expression auxiliaries ---*/ +/*---------------------------------------------------------*/ + +/* Return an AMode which computes the value of the specified + expression, possibly also adding insns to the code list as a + result. */ -X86AMode* iselAMode ( ISelEnv* env, IRExpr* e ) +static X86AMode* iselIntExpr_AMode ( ISelEnv* env, IRExpr* e ) { assert(e); assert(typeOfIRExpr(env->type_env,e) == Ity_I32); @@ -164,8 +179,8 @@ X86AMode* iselAMode ( ISelEnv* env, IRExpr* e ) && e->Iex.Binop.arg2->Iex.Binop.arg2->Iex.Const.con->tag == Ico_U32) { UInt shift = e->Iex.Binop.arg2->Iex.Binop.arg2->Iex.Const.con->Ico.U32; if (shift == 2 || shift == 4 || shift == 8) { - HReg r1 = iselExprI(env, e->Iex.Binop.arg1); - HReg r2 = iselExprI(env, e->Iex.Binop.arg2->Iex.Binop.arg1 ); + HReg r1 = iselIntExpr_R(env, e->Iex.Binop.arg1); + HReg r2 = iselIntExpr_R(env, e->Iex.Binop.arg2->Iex.Binop.arg1 ); return X86AMode_IRRS(0, r1, r2, shift); } } @@ -175,36 +190,87 @@ X86AMode* iselAMode ( ISelEnv* env, IRExpr* e ) && e->Iex.Binop.op == Iop_Add32 && e->Iex.Binop.arg2->tag == Iex_Const && e->Iex.Binop.arg2->Iex.Const.con->tag == Ico_U32) { - HReg r1 = iselExprI(env, e->Iex.Binop.arg1); + HReg r1 = iselIntExpr_R(env, e->Iex.Binop.arg1); return X86AMode_IR(r1, e->Iex.Binop.arg2->Iex.Const.con->Ico.U32); } /* Doesn't match anything in particular. Generate it into a register and use that. */ { - HReg r1 = iselExprI(env, e); + HReg r1 = iselIntExpr_R(env, e); return X86AMode_IR(r1, 0); } } +/* Similarly, calculate an expression into an X86RMI operand. */ + +static X86RMI* iselIntExpr_RMI ( ISelEnv* env, IRExpr* e ) +{ + assert(e); + assert(typeOfIRExpr(env->type_env,e) == Ity_I32); + + /* special case: immediate */ + if (e->tag == Iex_Const + && e->Iex.Const.con->tag == Ico_U32) { + return X86RMI_Imm(e->Iex.Const.con->Ico.U32); + } + + /* special case: load from memory */ + + /* default case: calculate into a register and return that */ + { + HReg r = iselIntExpr_R ( env, e ); + return X86RMI_Reg(r); + } +} + + +/* Calculate an expression into an X86RI operand. */ + +static X86RI* iselIntExpr_RI ( ISelEnv* env, IRExpr* e ) +{ + assert(e); + assert(typeOfIRExpr(env->type_env,e) == Ity_I32); + + /* special case: immediate */ + if (e->tag == Iex_Const + && e->Iex.Const.con->tag == Ico_U32) { + return X86RI_Imm(e->Iex.Const.con->Ico.U32); + } + + /* default case: calculate into a register and return that */ + { + HReg r = iselIntExpr_R ( env, e ); + return X86RI_Reg(r); + } +} + + /*---------------------------------------------------------*/ /*--- ISEL: Statements ---*/ /*---------------------------------------------------------*/ void iselStmt ( ISelEnv* env, IRStmt* stmt ) { + fprintf(stdout, "-- "); + ppIRStmt(stdout, stmt); + fprintf(stdout, "\n"); + switch (stmt->tag) { case Ist_Put: if (stmt->Ist.Put.size == 4) { - HReg ebp = mkHReg(5, HRcInt, False); - HReg reg = iselExprI(env, stmt->Ist.Put.expr); + /* We're going to write to memory, so compute the + RHS into an X86RI. */ + HReg ebp = mkHReg(5, HRcInt, False); + X86RI* ri = iselIntExpr_RI(env, stmt->Ist.Put.expr); addInstr(env, - X86Instr_ST32(reg, - X86AMode_IR(stmt->Ist.Put.offset, - ebp) - )); + X86Instr_Alu32M( + Xalu_MOV, + ri, + X86AMode_IR(stmt->Ist.Put.offset,ebp) + )); return; } @@ -221,8 +287,22 @@ void iselStmt ( ISelEnv* env, IRStmt* stmt ) void iselNext ( ISelEnv* env, IRNext* next ) { + fprintf(stdout, "-- "); + ppIRNext(stdout, next); + fprintf(stdout, "\n"); + switch (next->tag) { - default: + case Inx_UJump: { + HReg eax = mkHReg(0, HRcInt, False); + assert(next->Inx.UJump.dst->tag == Ico_U32); + addInstr(env, X86Instr_Alu32R( + Xalu_MOV, + X86RMI_Imm(next->Inx.UJump.dst->Ico.U32), + eax)); + addInstr(env, X86Instr_RET()); + return; + } + default: ppIRNext(stderr, next); panic("iselNext"); } @@ -267,6 +347,7 @@ void /* not really, but for the time being ... */ } env->vregmap[i].vreg = hreg; } + env->ctr = 100; //env->n_vregmap; /* Ok, finally we can iterate over the statements. */ for (stmt = bb->stmts; stmt; stmt=stmt->link) diff --git a/VEX/x86h_defs.c b/VEX/x86h_defs.c index 0f3549a84a..bad05b88b3 100644 --- a/VEX/x86h_defs.c +++ b/VEX/x86h_defs.c @@ -87,42 +87,102 @@ void ppX86AMode ( FILE* f, X86AMode* am ) { } -/* --------- X86Operand. Not all are valid for all insns. --------- */ +/* --------- Operand, which can be reg, immediate or memory. --------- */ -X86Operand* X86Operand_Imm ( UInt imm32 ) { - X86Operand* op = malloc(sizeof(X86Operand)); - op->tag = Xop_Imm; - op->Xop.Imm.imm32 = imm32; +X86RMI* X86RMI_Imm ( UInt imm32 ) { + X86RMI* op = malloc(sizeof(X86RMI)); + op->tag = Xrmi_Imm; + op->Xrmi.Imm.imm32 = imm32; return op; } -X86Operand* X86Operand_Reg ( HReg reg ) { - X86Operand* op = malloc(sizeof(X86Operand)); - op->tag = Xop_Reg; - op->Xop.Reg.reg = reg; +X86RMI* X86RMI_Reg ( HReg reg ) { + X86RMI* op = malloc(sizeof(X86RMI)); + op->tag = Xrmi_Reg; + op->Xrmi.Reg.reg = reg; return op; } -X86Operand* X86Operand_Mem ( X86AMode* am ) { - X86Operand* op = malloc(sizeof(X86Operand)); - op->tag = Xop_Mem; - op->Xop.Mem.am = am; +X86RMI* X86RMI_Mem ( X86AMode* am ) { + X86RMI* op = malloc(sizeof(X86RMI)); + op->tag = Xrmi_Mem; + op->Xrmi.Mem.am = am; return op; } -void ppX86Operand ( FILE* f, X86Operand* op ) { +void ppX86RMI ( FILE* f, X86RMI* op ) { switch (op->tag) { - case Xop_Imm: - fprintf(f, "$0x%x", op->Xop.Imm.imm32); + case Xrmi_Imm: + fprintf(f, "$0x%x", op->Xrmi.Imm.imm32); return; - case Xop_Reg: - ppHRegX86(f, op->Xop.Reg.reg); + case Xrmi_Reg: + ppHRegX86(f, op->Xrmi.Reg.reg); return; - case Xop_Mem: - ppX86AMode(f, op->Xop.Mem.am); + case Xrmi_Mem: + ppX86AMode(f, op->Xrmi.Mem.am); return; default: - panic("ppX86Operand"); + panic("ppX86RMI"); + } +} + + +/* --------- Operand, which can be reg or immediate only. --------- */ + +X86RI* X86RI_Imm ( UInt imm32 ) { + X86RI* op = malloc(sizeof(X86RI)); + op->tag = Xri_Imm; + op->Xri.Imm.imm32 = imm32; + return op; +} + +X86RI* X86RI_Reg ( HReg reg ) { + X86RI* op = malloc(sizeof(X86RI)); + op->tag = Xri_Reg; + op->Xri.Reg.reg = reg; + return op; +} + +void ppX86RI ( FILE* f, X86RI* op ) { + switch (op->tag) { + case Xri_Imm: + fprintf(f, "$0x%x", op->Xri.Imm.imm32); + return; + case Xri_Reg: + ppHRegX86(f, op->Xri.Reg.reg); + return; + default: + panic("ppX86RI"); + } +} + + +/* --------- Operand, which can be reg or memory only. --------- */ + +X86RM* X86RM_Reg ( HReg reg ) { + X86RM* op = malloc(sizeof(X86RM)); + op->tag = Xrm_Reg; + op->Xrm.Reg.reg = reg; + return op; +} + +X86RM* X86RM_Mem ( X86AMode* am ) { + X86RM* op = malloc(sizeof(X86RM)); + op->tag = Xrm_Mem; + op->Xrm.Mem.am = am; + return op; +} + +void ppX86RM ( FILE* f, X86RM* op ) { + switch (op->tag) { + case Xrm_Mem: + ppX86AMode(f, op->Xrm.Mem.am); + return; + case Xrm_Reg: + ppHRegX86(f, op->Xrm.Reg.reg); + return; + default: + panic("ppX86RM"); } } @@ -132,6 +192,7 @@ void ppX86Operand ( FILE* f, X86Operand* op ) { void ppX86AluOp ( FILE* f, X86AluOp op ) { Char* name; switch (op) { + case Xalu_MOV: name = "mov"; break; case Xalu_ADD: name = "add"; break; case Xalu_SUB: name = "sub"; break; case Xalu_ADC: name = "adc"; break; @@ -144,81 +205,80 @@ void ppX86AluOp ( FILE* f, X86AluOp op ) { fprintf(f, "%s", name); } -X86Instr* X86Instr_ST32 ( HReg src, X86AMode* dst ) { - X86Instr* i = malloc(sizeof(X86Instr)); - i->tag = Xin_ST32; - i->Xin.ST32.src = src; - i->Xin.ST32.dst = dst; - return i; +void ppX86ShiftOp ( FILE* f, X86ShiftOp op ) { + Char* name; + switch (op) { + case Xsh_SHL: name = "shl"; break; + case Xsh_SHR: name = "shr"; break; + case Xsh_SAR: name = "sar"; break; + case Xsh_ROL: name = "rol"; break; + case Xsh_ROR: name = "ror"; break; + default: panic("ppX86ShiftOp"); + } + fprintf(f, "%s", name); } -X86Instr* X86Instr_LD32 ( X86AMode* src, HReg dst ) { - X86Instr* i = malloc(sizeof(X86Instr)); - i->tag = Xin_LD32; - i->Xin.LD32.src = src; - i->Xin.LD32.dst = dst; +X86Instr* X86Instr_Alu32R ( X86AluOp op, X86RMI* src, HReg dst ) { + X86Instr* i = malloc(sizeof(X86Instr)); + i->tag = Xin_Alu32R; + i->Xin.Alu32R.op = op; + i->Xin.Alu32R.src = src; + i->Xin.Alu32R.dst = dst; return i; } -X86Instr* X86Instr_Alu32 ( X86AluOp op, X86Operand* src, X86Operand* dst ) { - X86Instr* i = malloc(sizeof(X86Instr)); - i->tag = Xin_Alu32; - i->Xin.Alu32.op = op; - i->Xin.Alu32.src = src; - i->Xin.Alu32.dst = dst; +X86Instr* X86Instr_Alu32M ( X86AluOp op, X86RI* src, X86AMode* dst ) { + X86Instr* i = malloc(sizeof(X86Instr)); + i->tag = Xin_Alu32M; + i->Xin.Alu32M.op = op; + i->Xin.Alu32M.src = src; + i->Xin.Alu32M.dst = dst; return i; } -X86Instr* X86Instr_Mov32 ( X86Operand* src, X86Operand* dst ) { - X86Instr* i = malloc(sizeof(X86Instr)); - i->tag = Xin_Mov32; - i->Xin.Mov32.src = src; - i->Xin.Mov32.dst = dst; +X86Instr* X86Instr_Sh32 ( X86ShiftOp op, UInt src, X86RM* dst ) { + X86Instr* i = malloc(sizeof(X86Instr)); + i->tag = Xin_Sh32; + i->Xin.Sh32.op = op; + i->Xin.Sh32.src = src; + i->Xin.Sh32.dst = dst; return i; } -X86Instr* X86Instr_Alu16 ( X86AluOp op, X86Operand* src, X86Operand* dst ) { - X86Instr* i = malloc(sizeof(X86Instr)); - i->tag = Xin_Alu16; - i->Xin.Alu16.op = op; - i->Xin.Alu16.src = src; - i->Xin.Alu16.dst = dst; +X86Instr* X86Instr_RET ( void ) { + X86Instr* i = malloc(sizeof(X86Instr)); + i->tag = Xin_RET; return i; } + void ppX86Instr ( FILE* f, X86Instr* i ) { switch (i->tag) { - case Xin_ST32: - fprintf(f, "movl "); - ppHRegX86(f, i->Xin.ST32.src); - fprintf(f, ","); - ppX86AMode(f, i->Xin.ST32.dst); - return; - case Xin_LD32: - fprintf(f, "movl "); - ppX86AMode(f, i->Xin.LD32.src); + case Xin_Alu32R: + ppX86AluOp(f, i->Xin.Alu32R.op); + fprintf(f, "l "); + ppX86RMI(f, i->Xin.Alu32R.src); fprintf(f, ","); - ppHRegX86(f, i->Xin.LD32.dst); + ppHRegX86(f, i->Xin.Alu32R.dst); return; - case Xin_Alu32: - ppX86AluOp(f, i->Xin.Alu32.op); + case Xin_Alu32M: + ppX86AluOp(f, i->Xin.Alu32M.op); fprintf(f, "l "); - ppX86Operand(f, i->Xin.Alu32.src); + ppX86RI(f, i->Xin.Alu32M.src); fprintf(f, ","); - ppX86Operand(f, i->Xin.Alu32.dst); + ppX86AMode(f, i->Xin.Alu32M.dst); return; - case Xin_Mov32: - fprintf(f, "movl "); - ppX86Operand(f, i->Xin.Mov32.src); - fprintf(f, ","); - ppX86Operand(f, i->Xin.Mov32.dst); + case Xin_Sh32: + ppX86ShiftOp(f, i->Xin.Sh32.op); + fprintf(f, "l "); + if (i->Xin.Sh32.src == 0) + fprintf(f, " %%cl,"); + else + fprintf(f, " $%d,", i->Xin.Sh32.src); + ppX86RM(f, i->Xin.Sh32.dst); return; - case Xin_Alu16: - ppX86AluOp(f, i->Xin.Alu16.op); - fprintf(f, "w "); - ppX86Operand(f, i->Xin.Alu16.src); - fprintf(f, ","); - ppX86Operand(f, i->Xin.Alu16.dst); + case Xin_RET: + fprintf(f, "ret"); return; default: panic("ppX86Instr");