From fc1b7d62b7e8e5cf59956875720dbd1deb68af93 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Fri, 20 Jul 2007 23:16:03 -0700 Subject: [PATCH] Fixed the distinction between far and near versions of jmp, call and ret. Implemented some shifts, rotates, and pushes. --HG-- extra : convert_revision : fcb06189ff213e82da16ac43231feb308cb3a285 --- src/arch/x86/isa/decoder/one_byte_opcodes.isa | 54 ++++----- .../x86/isa/insts/control_transfer/call.py | 39 ++++++- .../x86/isa/insts/control_transfer/jump.py | 6 + .../insts/data_transfer/stack_operations.py | 19 ++++ .../x86/isa/insts/rotate_and_shift/rotate.py | 46 +++++++- .../x86/isa/insts/rotate_and_shift/shift.py | 40 +++++++ src/arch/x86/isa/microops/regop.isa | 106 ++++++++++++------ 7 files changed, 245 insertions(+), 65 deletions(-) diff --git a/src/arch/x86/isa/decoder/one_byte_opcodes.isa b/src/arch/x86/isa/decoder/one_byte_opcodes.isa index 2c2d68785..329a03f40 100644 --- a/src/arch/x86/isa/decoder/one_byte_opcodes.isa +++ b/src/arch/x86/isa/decoder/one_byte_opcodes.isa @@ -306,7 +306,7 @@ 0x1: cwd_or_cdq_or_cqo_rAX_rDX(); 0x2: decode MODE_SUBMODE { 0x0: Inst::UD2(); - default: call_Ap(); + default: call_far_Ap(); } 0x3: fwait(); //aka wait 0x4: pushf_Fv(); @@ -356,25 +356,25 @@ 0x18: decode OPCODE_OP_BOTTOM3 { //0x0: group2_Eb_Ib(); 0x0: decode MODRM_REG { - 0x0: rol_Eb_Ib(); - 0x1: ror_Eb_Ib(); + 0x0: Inst::ROL(Eb,Ib); + 0x1: Inst::ROR(Eb,Ib); 0x2: rcl_Eb_Ib(); 0x3: rcr_Eb_Ib(); 0x4: Inst::SAL(Eb,Ib); - 0x5: shr_Eb_Ib(); + 0x5: Inst::SHR(Eb,Ib); 0x6: Inst::SAL(Eb,Ib); - 0x7: sar_Eb_Ib(); + 0x7: Inst::SAR(Eb,Ib); } //0x1: group2_Ev_Ib(); 0x1: decode MODRM_REG { - 0x0: rol_Ev_Ib(); - 0x1: ror_Ev_Ib(); + 0x0: Inst::ROL(Ev,Ib); + 0x1: Inst::ROR(Ev,Ib); 0x2: rcl_Ev_Ib(); 0x3: rcr_Ev_Ib(); 0x4: Inst::SAL(Ev,Ib); - 0x5: shr_Ev_Ib(); + 0x5: Inst::SHR(Ev,Ib); 0x6: Inst::SAL(Ev,Ib); - 0x7: sar_Ev_Ib(); + 0x7: Inst::SAR(Ev,Ib); } 0x2: ret_near_Iw(); 0x3: Inst::RET_NEAR(); @@ -452,7 +452,7 @@ 0x1: Inst::JMP(Jz); 0x2: decode MODE_SUBMODE { 0x0: Inst::UD2(); - default: jmp_Ap(); + default: jmp_far_Ap(); } 0x3: Inst::JMP(Jb); 0x4: in_Al_Dx(); @@ -480,22 +480,24 @@ 0x3: sti(); 0x4: cld(); 0x5: std(); - //0x6: group4(); - 0x6: decode MODRM_REG { - 0x0: Inst::INC(Eb); - 0x1: Inst::DEC(Eb); - default: Inst::UD2(); - } - //0x7: group5(); - 0x7: decode MODRM_REG { - 0x0: Inst::INC(Ev); - 0x1: Inst::DEC(Ev); - 0x2: call_Ev(); - 0x3: call_Mp(); - 0x4: jmp_Ev(); - 0x5: jmp_Mp(); - 0x6: push_Ev(); - 0x7: Inst::UD2(); + format Inst { + //0x6: group4(); + 0x6: decode MODRM_REG { + 0x0: INC(Eb); + 0x1: DEC(Eb); + default: UD2(); + } + //0x7: group5(); + 0x7: decode MODRM_REG { + 0x0: INC(Ev); + 0x1: DEC(Ev); + 0x2: CALL_NEAR(Ev); + 0x3: WarnUnimpl::call_far_Mp(); + 0x4: JMP(Ev); + 0x5: WarnUnimpl::jmp_far_Mp(); + 0x6: PUSH(Ev); + 0x7: UD2(); + } } } } diff --git a/src/arch/x86/isa/insts/control_transfer/call.py b/src/arch/x86/isa/insts/control_transfer/call.py index c40080d85..c5bb66e58 100644 --- a/src/arch/x86/isa/insts/control_transfer/call.py +++ b/src/arch/x86/isa/insts/control_transfer/call.py @@ -59,11 +59,46 @@ def macroop CALL_NEAR_I # Make the default data size of calls 64 bits in 64 bit mode .adjust_env oszIn64Override - limm t2, imm + limm t1, imm + rdip t7 + subi rsp, rsp, dsz + st t7, ss, [0, t0, rsp] + wrip t7, t1 +}; + +def macroop CALL_NEAR_R +{ + # Make the default data size of calls 64 bits in 64 bit mode + .adjust_env oszIn64Override + rdip t1 subi rsp, rsp, dsz st t1, ss, [0, t0, rsp] - wrip t1, t2 + wripi reg, 0 +}; + +def macroop CALL_NEAR_M +{ + # Make the default data size of calls 64 bits in 64 bit mode + .adjust_env oszIn64Override + + rdip t7 + ld t1, ds, [scale, index, base], disp + subi rsp, rsp, dsz + st t7, ss, [0, t0, rsp] + wripi t1, 0 +}; + +def macroop CALL_NEAR_P +{ + # Make the default data size of calls 64 bits in 64 bit mode + .adjust_env oszIn64Override + + rdip t7 + ld t1, ds, [0, t0, t7], disp + subi rsp, rsp, dsz + st t7, ss, [0, t0, rsp] + wripi t1, 0 }; ''' #let {{ diff --git a/src/arch/x86/isa/insts/control_transfer/jump.py b/src/arch/x86/isa/insts/control_transfer/jump.py index 489eb9e39..158861a3d 100644 --- a/src/arch/x86/isa/insts/control_transfer/jump.py +++ b/src/arch/x86/isa/insts/control_transfer/jump.py @@ -235,4 +235,10 @@ def macroop JMP_M wripi t1, 0 }; +def macroop JMP_P +{ + rdip t7 + ld t1, ds, [0, t0, t7], disp + wripi t1, 0 +}; ''' diff --git a/src/arch/x86/isa/insts/data_transfer/stack_operations.py b/src/arch/x86/isa/insts/data_transfer/stack_operations.py index 585437b8c..c381dc4f4 100644 --- a/src/arch/x86/isa/insts/data_transfer/stack_operations.py +++ b/src/arch/x86/isa/insts/data_transfer/stack_operations.py @@ -69,6 +69,25 @@ def macroop PUSH_R { subi rsp, rsp, dsz st reg, ss, [0, t0, rsp] }; + +def macroop PUSH_M { + # Make the default data size of pops 64 bits in 64 bit mode + .adjust_env oszIn64Override + + ld t1, ds, [scale, index, base], disp + subi rsp, rsp, dsz + st t1, ss, [0, t0, rsp] +}; + +def macroop PUSH_P { + # Make the default data size of pops 64 bits in 64 bit mode + .adjust_env oszIn64Override + + rdip t7 + ld t1, ds, [0, t0, t7], disp + subi rsp, rsp, dsz + st t1, ss, [0, t0, rsp] +}; ''' #let {{ # class POPA(Inst): diff --git a/src/arch/x86/isa/insts/rotate_and_shift/rotate.py b/src/arch/x86/isa/insts/rotate_and_shift/rotate.py index e3aaf0043..5330b1ac5 100644 --- a/src/arch/x86/isa/insts/rotate_and_shift/rotate.py +++ b/src/arch/x86/isa/insts/rotate_and_shift/rotate.py @@ -53,14 +53,50 @@ # # Authors: Gabe Black -microcode = "" +microcode = ''' +def macroop ROL_R_I +{ + rol reg, reg, imm +}; + +def macroop ROL_M_I +{ + ld t1, ds, [scale, index, base], disp + rol t1, t1, imm + st t1, ds, [scale, index, base], disp +}; + +def macroop ROL_P_I +{ + rdip t7 + ld t1, ds, [0, t0, t7], disp + rol t1, t1, imm + st t1, ds, [0, t0, t7], disp +}; + +def macroop ROR_R_I +{ + ror reg, reg, imm +}; + +def macroop ROR_M_I +{ + ld t1, ds, [scale, index, base], disp + ror t1, t1, imm + st t1, ds, [scale, index, base], disp +}; + +def macroop ROR_P_I +{ + rdip t7 + ld t1, ds, [0, t0, t7], disp + ror t1, t1, imm + st t1, ds, [0, t0, t7], disp +}; +''' #let {{ # class RCL(Inst): # "GenFault ${new UnimpInstFault}" # class RCR(Inst): # "GenFault ${new UnimpInstFault}" -# class ROL(Inst): -# "GenFault ${new UnimpInstFault}" -# class ROR(Inst): -# "GenFault ${new UnimpInstFault}" #}}; diff --git a/src/arch/x86/isa/insts/rotate_and_shift/shift.py b/src/arch/x86/isa/insts/rotate_and_shift/shift.py index b1c86a921..5a04317d9 100644 --- a/src/arch/x86/isa/insts/rotate_and_shift/shift.py +++ b/src/arch/x86/isa/insts/rotate_and_shift/shift.py @@ -73,6 +73,46 @@ def macroop SAL_P_I sll t1, t1, imm st t1, ds, [0, t0, t7], disp }; + +def macroop SHR_R_I +{ + srl reg, reg, imm +}; + +def macroop SHR_M_I +{ + ld t1, ds, [scale, index, base], disp + srl t1, t1, imm + st t1, ds, [scale, index, base], disp +}; + +def macroop SHR_P_I +{ + rdip t7 + ld t1, ds, [0, t0, t7], disp + srl t1, t1, imm + st t1, ds, [0, t0, t7], disp +}; + +def macroop SAR_R_I +{ + sra reg, reg, imm +}; + +def macroop SAR_M_I +{ + ld t1, ds, [scale, index, base], disp + sra t1, t1, imm + st t1, ds, [scale, index, base], disp +}; + +def macroop SAR_P_I +{ + rdip t7 + ld t1, ds, [0, t0, t7], disp + sra t1, t1, imm + st t1, ds, [0, t0, t7], disp +}; ''' #let {{ # class SAL(Inst): diff --git a/src/arch/x86/isa/microops/regop.isa b/src/arch/x86/isa/microops/regop.isa index d2002b4fb..1f4de5642 100644 --- a/src/arch/x86/isa/microops/regop.isa +++ b/src/arch/x86/isa/microops/regop.isa @@ -381,34 +381,6 @@ let {{ setUpMicroRegOp(name + "i", Name + "ImmFlags", "X86ISA::RegOpImm", immCode, flagCode = immFlagCode, condCheck = condCode, elseCode = elseCode); - defineMicroRegOp('Add', 'DestReg = merge(DestReg, SrcReg1 + op2, dataSize)') - defineMicroRegOp('Or', 'DestReg = merge(DestReg, SrcReg1 | op2, dataSize)') - defineMicroRegOp('Adc', ''' - CCFlagBits flags = ccFlagBits; - DestReg = merge(DestReg, SrcReg1 + op2 + flags.CF, dataSize); - ''') - defineMicroRegOp('Sbb', ''' - CCFlagBits flags = ccFlagBits; - DestReg = merge(DestReg, SrcReg1 - op2 - flags.CF, dataSize); - ''', True) - defineMicroRegOp('And', 'DestReg = merge(DestReg, SrcReg1 & op2, dataSize)') - defineMicroRegOp('Sub', 'DestReg = merge(DestReg, SrcReg1 - op2, dataSize)', True) - defineMicroRegOp('Xor', 'DestReg = merge(DestReg, SrcReg1 ^ op2, dataSize)') - # defineMicroRegOp('Cmp', 'DestReg = merge(DestReg, DestReg - op2, dataSize)', True) - defineMicroRegOp('Mul1s', 'DestReg = merge(DestReg, DestReg * op2, dataSize)') - defineMicroRegOp('Mov', 'DestReg = merge(SrcReg1, op2, dataSize)', - elseCode='DestReg=DestReg;', cc=True) - - # Shift instructions - defineMicroRegOp('Sll', ''' - uint8_t shiftAmt = (op2 & ((dataSize == 8) ? mask(4) : mask(3))); - DestReg = merge(DestReg, SrcReg1 << shiftAmt, dataSize); - ''') - # There are special rules for the flag for a single bit shift - defineMicroRegOp('Bll', ''' - DestReg = merge(DestReg, SrcReg1 << 1, dataSize); - ''') - # This has it's own function because Wr ops have implicit destinations def defineMicroRegOpWr(mnemonic, code, elseCode=";"): Name = mnemonic @@ -445,8 +417,6 @@ let {{ setUpMicroRegOp(name + 'i', Name + "ImmFlags", "X86ISA::RegOpImm", immCode, condCheck = checkCCFlagBits, elseCode = elseCode); - defineMicroRegOpWr('Wrip', 'RIP = SrcReg1 + op2', elseCode="RIP = RIP;") - # This has it's own function because Rd ops don't always have two parameters def defineMicroRegOpRd(mnemonic, code): Name = mnemonic @@ -462,8 +432,6 @@ let {{ setUpMicroRegOp(name, Name, "X86ISA::RegOp", code); - defineMicroRegOpRd('Rdip', 'DestReg = RIP') - def defineMicroRegOpImm(mnemonic, code): Name = mnemonic name = mnemonic.lower() @@ -478,6 +446,80 @@ let {{ setUpMicroRegOp(name, Name, "X86ISA::RegOpImm", code); + defineMicroRegOp('Add', 'DestReg = merge(DestReg, SrcReg1 + op2, dataSize)') + defineMicroRegOp('Or', 'DestReg = merge(DestReg, SrcReg1 | op2, dataSize)') + defineMicroRegOp('Adc', ''' + CCFlagBits flags = ccFlagBits; + DestReg = merge(DestReg, SrcReg1 + op2 + flags.CF, dataSize); + ''') + defineMicroRegOp('Sbb', ''' + CCFlagBits flags = ccFlagBits; + DestReg = merge(DestReg, SrcReg1 - op2 - flags.CF, dataSize); + ''', True) + defineMicroRegOp('And', 'DestReg = merge(DestReg, SrcReg1 & op2, dataSize)') + defineMicroRegOp('Sub', 'DestReg = merge(DestReg, SrcReg1 - op2, dataSize)', True) + defineMicroRegOp('Xor', 'DestReg = merge(DestReg, SrcReg1 ^ op2, dataSize)') + # defineMicroRegOp('Cmp', 'DestReg = merge(DestReg, DestReg - op2, dataSize)', True) + defineMicroRegOp('Mul1s', 'DestReg = merge(DestReg, DestReg * op2, dataSize)') + defineMicroRegOp('Mov', 'DestReg = merge(SrcReg1, op2, dataSize)', + elseCode='DestReg=DestReg;', cc=True) + + # Shift instructions + defineMicroRegOp('Sll', ''' + uint8_t shiftAmt = (op2 & ((dataSize == 8) ? mask(4) : mask(3))); + DestReg = merge(DestReg, SrcReg1 << shiftAmt, dataSize); + ''') + defineMicroRegOp('Srl', ''' + uint8_t shiftAmt = (op2 & ((dataSize == 8) ? mask(4) : mask(3))); + // Because what happens to the bits shift -in- on a right shift + // is not defined in the C/C++ standard, we have to mask them out + // to be sure they're zero. + uint64_t logicalMask = mask(dataSize * 8 - shiftAmt); + DestReg = merge(DestReg, (SrcReg1 >> shiftAmt) & logicalMask, dataSize); + ''') + defineMicroRegOp('Sra', ''' + uint8_t shiftAmt = (op2 & ((dataSize == 8) ? mask(4) : mask(3))); + // Because what happens to the bits shift -in- on a right shift + // is not defined in the C/C++ standard, we have to sign extend + // them manually to be sure. + uint64_t arithMask = + -bits(op2, dataSize * 8 - 1) << (dataSize * 8 - shiftAmt); + DestReg = merge(DestReg, (SrcReg1 >> shiftAmt) | arithMask, dataSize); + ''') + defineMicroRegOp('Ror', ''' + uint8_t shiftAmt = + (op2 & ((dataSize == 8) ? mask(4) : mask(3))); + if(shiftAmt) + { + uint64_t top = SrcReg1 << (dataSize * 8 - shiftAmt); + uint64_t bottom = bits(SrcReg1, dataSize * 8, shiftAmt); + DestReg = merge(DestReg, top | bottom, dataSize); + } + else + DestReg = DestReg; + ''') + defineMicroRegOp('Rcr', ''' + ''') + defineMicroRegOp('Rol', ''' + uint8_t shiftAmt = + (op2 & ((dataSize == 8) ? mask(4) : mask(3))); + if(shiftAmt) + { + uint64_t top = SrcReg1 << shiftAmt; + uint64_t bottom = + bits(SrcReg1, dataSize * 8 - 1, dataSize * 8 - shiftAmt); + DestReg = merge(DestReg, top | bottom, dataSize); + } + else + DestReg = DestReg; + ''') + defineMicroRegOp('Rcl', ''' + ''') + + defineMicroRegOpWr('Wrip', 'RIP = SrcReg1 + op2', elseCode="RIP = RIP;") + + defineMicroRegOpRd('Rdip', 'DestReg = RIP') + defineMicroRegOpImm('Sext', ''' IntReg val = SrcReg1; int sign_bit = bits(val, imm8-1, imm8-1);