diff options
Diffstat (limited to 'src/arch/x86/isa')
38 files changed, 2106 insertions, 997 deletions
diff --git a/src/arch/x86/isa/base.isa b/src/arch/x86/isa/base.isa deleted file mode 100644 index eed969b47..000000000 --- a/src/arch/x86/isa/base.isa +++ /dev/null @@ -1,303 +0,0 @@ -// Copyright (c) 2007 The Hewlett-Packard Development Company -// All rights reserved. -// -// Redistribution and use of this software in source and binary forms, -// with or without modification, are permitted provided that the -// following conditions are met: -// -// The software must be used only for Non-Commercial Use which means any -// use which is NOT directed to receiving any direct monetary -// compensation for, or commercial advantage from such use. Illustrative -// examples of non-commercial use are academic research, personal study, -// teaching, education and corporate research & development. -// Illustrative examples of commercial use are distributing products for -// commercial advantage and providing services using the software for -// commercial advantage. -// -// If you wish to use this software or functionality therein that may be -// covered by patents for commercial use, please contact: -// Director of Intellectual Property Licensing -// Office of Strategy and Technology -// Hewlett-Packard Company -// 1501 Page Mill Road -// Palo Alto, California 94304 -// -// Redistributions of source code must retain the above copyright notice, -// this list of conditions and the following disclaimer. Redistributions -// in binary form must reproduce the above copyright notice, this list of -// conditions and the following disclaimer in the documentation and/or -// other materials provided with the distribution. Neither the name of -// the COPYRIGHT HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. No right of -// sublicense is granted herewith. Derivatives of the software and -// output created using the software may be prepared, but only for -// Non-Commercial Uses. Derivatives of the software may be shared with -// others provided: (i) the others agree to abide by the list of -// conditions herein which includes the Non-Commercial Use restrictions; -// and (ii) such Derivatives of the software include the above copyright -// notice to acknowledge the contribution from this software where -// applicable, this list of conditions and the disclaimer below. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// Authors: Gabe Black - -//////////////////////////////////////////////////////////////////// -// -// Base class for sparc instructions, and some support functions -// - -let {{ - # This class will help make dealing with output a little less verbose - class OutputBlocks(object): - def __init__(self, header_output="", - decoder_output="", - decode_block="", - exec_output=""): - self.header_output = header_output - self.decoder_output = decoder_output - self.decode_block = decode_block - self.exec_output = exec_output - - def append(self, blocks): - if isinstance(blocks, list) or isinstance(blocks, tuple): - assert(len(blocks) == 4) - self.header_output += blocks[0] - self.decoder_output += blocks[1] - self.decode_block += blocks[2] - self.exec_output += blocks[3] - else: - self.header_output += blocks.header_output - self.decoder_output += blocks.decoder_output - self.decode_block += blocks.decode_block - self.exec_output += blocks.exec_output - - def makeList(self): - return (self.header_output, - self.decoder_output, - self.decode_block, - self.exec_output) -}}; - -output header {{ - - /** - * Base class for all X86 static instructions. - */ - BitUnion64(X86IntReg) - Bitfield<63,0> R; - Bitfield<31,0> E; - Bitfield<15,0> X; - Bitfield<15,8> H; - Bitfield<7, 0> L; - EndBitUnion(X86IntReg) - - class X86StaticInst : public StaticInst - { - protected: - // Constructor. - X86StaticInst(const char *mnem, - ExtMachInst _machInst, OpClass __opClass) - : StaticInst(mnem, _machInst, __opClass) - { - } - - std::string generateDisassembly(Addr pc, - const SymbolTable *symtab) const; - - void printReg(std::ostream &os, int reg) const; - void printSrcReg(std::ostream &os, int reg) const; - void printDestReg(std::ostream &os, int reg) const; - - inline uint64_t merge(uint64_t into, uint64_t val, int size) const - { - X86IntReg reg; - reg = into; - //FIXME This needs to be handle high bytes as well - switch(size) - { - case 1: - reg.L = val; - break; - case 2: - reg.X = val; - break; - case 4: - //XXX Check if this should be zeroed or sign extended - reg = 0; - reg.E = val; - break; - case 8: - reg.R = val; - break; - default: - panic("Tried to merge with unrecognized size %d.\n", size); - } - return val; - } - - inline uint64_t pick(uint64_t from, int size) - { - X86IntReg reg; - reg = from; - switch(size) - { - case 1: - return reg.L; - case 2: - return reg.E; - case 4: - return reg.X; - case 8: - return reg.R; - default: - panic("Tried to pick with unrecognized size %d.\n", size); - } - } - - }; -}}; - -output decoder {{ - - inline void printMnemonic(std::ostream &os, const char * mnemonic) - { - ccprintf(os, "\t%s ", mnemonic); - } - - inline void printMnemonic(std::ostream &os, - const char * instMnemonic, const char * mnemonic) - { - ccprintf(os, "\t%s : %s ", instMnemonic, mnemonic); - } - - void printSegment(std::ostream &os, int segment) - { - switch (segment) - { - case 0: - ccprintf(os, "ES"); - break; - case 1: - ccprintf(os, "CS"); - break; - case 2: - ccprintf(os, "SS"); - break; - case 3: - ccprintf(os, "DS"); - break; - case 4: - ccprintf(os, "FS"); - break; - case 5: - ccprintf(os, "GS"); - break; - default: - panic("Unrecognized segment %d\n", segment); - } - } - - void - X86StaticInst::printSrcReg(std::ostream &os, int reg) const - { - if(_numSrcRegs > reg) - printReg(os, _srcRegIdx[reg]); - } - - void - X86StaticInst::printDestReg(std::ostream &os, int reg) const - { - if(_numDestRegs > reg) - printReg(os, _destRegIdx[reg]); - } - - void - X86StaticInst::printReg(std::ostream &os, int reg) const - { - if (reg < FP_Base_DepTag) { - //FIXME These should print differently depending on the - //mode etc, but for now this will get the point across - switch (reg) { - case INTREG_RAX: - ccprintf(os, "rax"); - break; - case INTREG_RBX: - ccprintf(os, "rbx"); - break; - case INTREG_RCX: - ccprintf(os, "rcx"); - break; - case INTREG_RDX: - ccprintf(os, "rdx"); - break; - case INTREG_RSP: - ccprintf(os, "rsp"); - break; - case INTREG_RBP: - ccprintf(os, "rbp"); - break; - case INTREG_RSI: - ccprintf(os, "rsi"); - break; - case INTREG_RDI: - ccprintf(os, "rdi"); - break; - case INTREG_R8W: - ccprintf(os, "r8"); - break; - case INTREG_R9W: - ccprintf(os, "r9"); - break; - case INTREG_R10W: - ccprintf(os, "r10"); - break; - case INTREG_R11W: - ccprintf(os, "r11"); - break; - case INTREG_R12W: - ccprintf(os, "r12"); - break; - case INTREG_R13W: - ccprintf(os, "r13"); - break; - case INTREG_R14W: - ccprintf(os, "r14"); - break; - case INTREG_R15W: - ccprintf(os, "r15"); - break; - default: - ccprintf(os, "t%d", reg - NUM_INTREGS); - } - } else if (reg < Ctrl_Base_DepTag) { - ccprintf(os, "%%f%d", reg - FP_Base_DepTag); - } else { - switch (reg - Ctrl_Base_DepTag) { - default: - ccprintf(os, "%%ctrl%d", reg - Ctrl_Base_DepTag); - } - } - } - - std::string X86StaticInst::generateDisassembly(Addr pc, - const SymbolTable *symtab) const - { - std::stringstream ss; - - printMnemonic(ss, mnemonic); - - return ss.str(); - } -}}; diff --git a/src/arch/x86/isa/bitfields.isa b/src/arch/x86/isa/bitfields.isa index 8707bbb4c..43fee5fef 100644 --- a/src/arch/x86/isa/bitfields.isa +++ b/src/arch/x86/isa/bitfields.isa @@ -67,11 +67,12 @@ def bitfield REX_B rex.b; //Legacy prefixes def bitfield LEGACY legacy; +def bitfield LEGACY_DECODEVAL legacy.decodeVal; def bitfield LEGACY_REPNE legacy.repne; def bitfield LEGACY_REP legacy.rep; def bitfield LEGACY_LOCK legacy.lock; -def bitfield LEGACY_ADDR legacy.addr; def bitfield LEGACY_OP legacy.op; +def bitfield LEGACY_ADDR legacy.addr; def bitfield LEGACY_SEG legacy.seg; // Pieces of the opcode diff --git a/src/arch/x86/isa/decoder/one_byte_opcodes.isa b/src/arch/x86/isa/decoder/one_byte_opcodes.isa index 484f8160d..b28f2029c 100644 --- a/src/arch/x86/isa/decoder/one_byte_opcodes.isa +++ b/src/arch/x86/isa/decoder/one_byte_opcodes.isa @@ -61,178 +61,130 @@ 0x1: decode OPCODE_OP_TOP5 { format WarnUnimpl { 0x00: decode OPCODE_OP_BOTTOM3 { - 0x4: ADD(); - 0x5: ADD(); 0x6: decode MODE_SUBMODE { - 0x0: This_should_be_an_illegal_instruction(); + 0x0: Inst::UD2(); default: push_ES(); } 0x7: decode MODE_SUBMODE { - 0x0: This_should_be_an_illegal_instruction(); + 0x0: Inst::UD2(); default: pop_ES(); } - default: ADD(); + default: MultiInst::ADD(OPCODE_OP_BOTTOM3, + [Eb,Gb], [Ev,Gv], + [Gb,Eb], [Gv,Ev], + [rAl,Ib], [rAx,Iz]); } 0x01: decode OPCODE_OP_BOTTOM3 { - 0x0: or_Eb_Gb(); - 0x1: or_Ev_Gv(); - 0x2: or_Gb_Eb(); - 0x3: or_Gv_Ev(); - 0x4: or_Al_Ib(); - 0x5: or_rAX_Iz(); 0x6: decode MODE_SUBMODE { - 0x0: This_should_be_an_illegal_instruction(); + 0x0: Inst::UD2(); default: push_CS(); } //Any time this is seen, it should generate a two byte opcode 0x7: M5InternalError::error( {{"Saw a one byte opcode whose value was 0x0F!"}}); + default: MultiInst::OR(OPCODE_OP_BOTTOM3, + [Eb,Gb], [Ev,Gv], + [Gb,Eb], [Gv,Ev], + [rAl,Ib], [rAx,Iz]); } 0x02: decode OPCODE_OP_BOTTOM3 { - 0x0: adc_Eb_Gb(); - 0x1: adc_Ev_Gv(); - 0x2: adc_Gb_Eb(); - 0x3: adc_Gv_Ev(); - 0x4: adc_Al_Ib(); - 0x5: adc_rAX_Iz(); 0x6: decode MODE_SUBMODE { - 0x0: This_should_be_an_illegal_instruction(); + 0x0: Inst::UD2(); default: push_SS(); } 0x7: decode MODE_SUBMODE { - 0x0: This_should_be_an_illegal_instruction(); + 0x0: Inst::UD2(); default: pop_SS(); } + default: MultiInst::ADC(OPCODE_OP_BOTTOM3, + [Eb,Gb], [Ev,Gv], + [Gb,Eb], [Gv,Ev], + [rAl,Ib], [rAx,Iz]); } 0x03: decode OPCODE_OP_BOTTOM3 { - 0x0: sbb_Eb_Gb(); - 0x1: sbb_Ev_Gv(); - 0x2: sbb_Gb_Eb(); - 0x3: sbb_Gv_Ev(); - 0x4: sbb_Al_Ib(); - 0x5: sbb_rAX_Iz(); 0x6: decode MODE_SUBMODE { - 0x0: This_should_be_an_illegal_instruction(); + 0x0: Inst::UD2(); default: push_DS(); } 0x7: decode MODE_SUBMODE { - 0x0: This_should_be_an_illegal_instruction(); + 0x0: Inst::UD2(); default: pop_DS(); } + default: MultiInst::SBB(OPCODE_OP_BOTTOM3, + [Eb,Gb], [Ev,Gv], + [Gb,Eb], [Gv,Ev], + [rAl,Ib], [rAx,Iz]); } 0x04: decode OPCODE_OP_BOTTOM3 { - 0x0: and_Eb_Gb(); - 0x1: and_Ev_Gv(); - 0x2: and_Gb_Eb(); - 0x3: and_Gv_Ev(); - 0x4: and_Al_Ib(); - 0x5: and_rAX_Iz(); 0x6: M5InternalError::error( {{"Tried to execute the ES segment override prefix!"}}); 0x7: decode MODE_SUBMODE { - 0x0: This_should_be_an_illegal_instruction(); + 0x0: Inst::UD2(); default: daa(); } + default: MultiInst::AND(OPCODE_OP_BOTTOM3, + [Eb,Gb], [Ev,Gv], + [Gb,Eb], [Gv,Ev], + [rAl,Ib], [rAx,Iz]); } 0x05: decode OPCODE_OP_BOTTOM3 { - 0x0: sub_Eb_Gb(); - 0x1: sub_Ev_Gv(); - 0x2: sub_Gb_Eb(); - 0x3: sub_Gv_Ev(); - 0x4: sub_Al_Ib(); - 0x5: sub_rAX_Iz(); 0x6: M5InternalError::error( {{"Tried to execute the CS segment override prefix!"}}); 0x7: das(); + default: MultiInst::SUB(OPCODE_OP_BOTTOM3, + [Eb,Gb], [Ev,Gv], + [Gb,Eb], [Gv,Ev], + [rAl,Ib], [rAx,Iz]); } 0x06: decode OPCODE_OP_BOTTOM3 { - 0x4: Inst::XOR(rAl,Ib); - 0x5: Inst::XOR(rAx,Iz); 0x6: M5InternalError::error( {{"Tried to execute the SS segment override prefix!"}}); 0x7: decode MODE_SUBMODE { - 0x0: This_should_be_an_illegal_instruction(); + 0x0: Inst::UD2(); default: aaa(); } default: MultiInst::XOR(OPCODE_OP_BOTTOM3, [Eb,Gb], [Ev,Gv], - [Gb,Eb], [Gv,Ev]); + [Gb,Eb], [Gv,Ev], + [rAl,Ib], [rAx,Iz]); } 0x07: decode OPCODE_OP_BOTTOM3 { - 0x0: cmp_Eb_Gb(); - 0x1: cmp_Ev_Gv(); - 0x2: cmp_Gb_Eb(); - 0x3: cmp_Gv_Ev(); - 0x4: cmp_Al_Ib(); - 0x5: cmp_rAX_Iz(); 0x6: M5InternalError::error( {{"Tried to execute the DS segment override prefix!"}}); 0x7: decode MODE_SUBMODE { - 0x0: This_should_be_an_illegal_instruction(); + 0x0: Inst::UD2(); default: aas(); } + default: MultiInst::CMP(OPCODE_OP_BOTTOM3, + [Eb,Gb], [Ev,Gv], + [Gb,Eb], [Gv,Ev], + [rAl,Ib], [rAx,Iz]); } 0x08: decode MODE_SUBMODE { 0x0: M5InternalError::error ( {{"Tried to execute an REX prefix!"}}); - default: decode OPCODE_OP_BOTTOM3 { - 0x0: inc_eAX(); - 0x1: inc_eCX(); - 0x2: inc_eDX(); - 0x3: inc_eBX(); - 0x4: inc_eSP(); - 0x5: inc_eBP(); - 0x6: inc_eSI(); - 0x7: inc_eDI(); - } + default: Inst::INC(B); } 0x09: decode MODE_SUBMODE { 0x0: M5InternalError::error ( {{"Tried to execute an REX prefix!"}}); - default: decode OPCODE_OP_BOTTOM3 { - 0x0: dec_eAX(); - 0x1: dec_eCX(); - 0x2: dec_eDX(); - 0x3: dec_eBX(); - 0x4: dec_eSP(); - 0x5: dec_eBP(); - 0x6: dec_eSI(); - 0x7: dec_eDI(); - } + default: Inst::DEC(B); } format Inst { - 0x0A: decode OPCODE_OP_BOTTOM3 { - 0x0: PUSH(rAx); - 0x1: PUSH(rCx); - 0x2: PUSH(rDx); - 0x3: PUSH(rBx); - 0x4: PUSH(rSP); - 0x5: PUSH(rBP); - 0x6: PUSH(rSI); - 0x7: PUSH(rDI); - } - 0x0B: decode OPCODE_OP_BOTTOM3 { - 0x0: POP(rAx); - 0x1: POP(rCx); - 0x2: POP(rDx); - 0x3: POP(rBx); - 0x4: POP(rSP); - 0x5: POP(rBP); - 0x6: POP(rSI); - 0x7: POP(rDI); - } + 0x0A: PUSH(B); + 0x0B: POP(B); } 0x0C: decode OPCODE_OP_BOTTOM3 { 0x0: decode MODE_SUBMODE { - 0x0: This_should_be_an_illegal_instruction(); + 0x0: Inst::UD2(); default: pusha(); } 0x1: decode MODE_SUBMODE { - 0x0: This_should_be_an_illegal_instruction(); + 0x0: Inst::UD2(); default: popa(); } 0x2: decode MODE_SUBMODE { - 0x0: This_should_be_an_illegal_instruction(); + 0x0: Inst::UD2(); default: bound_Gv_Ma(); } 0x3: decode MODE_SUBMODE { @@ -258,58 +210,82 @@ 0x6: outs_Dx_Xb(); 0x7: outs_Dx_Xz(); } - 0x0E: decode OPCODE_OP_BOTTOM3 { - 0x0: jo_Jb(); - 0x1: jno_Jb(); - 0x2: jb_Jb(); - 0x3: jnb_Jb(); - 0x4: jz_Jb(); - 0x5: jnz_Jb(); - 0x6: jbe_Jb(); - 0x7: jnbe_Jb(); - } - 0x0F: decode OPCODE_OP_BOTTOM3 { - 0x0: js_Jb(); - 0x1: jns_Jb(); - 0x2: jp_Jb(); - 0x3: jnp_Jb(); - 0x4: jl_Jb(); - 0x5: jnl_Jb(); - 0x6: jle_Jb(); - 0x7: jnke_Jb(); - } - 0x10: decode OPCODE_OP_BOTTOM3 { - 0x0: group1_Eb_Ib(); - //0x1: group1_Ev_Iz(); - 0x1: decode MODRM_REG { - 0x0: add_Ev_Iz(); - 0x1: or_Ev_Ibz(); - 0x2: adc_Ev_Iz(); - 0x3: sbb_Ev_Iz(); - 0x4: Inst::AND(Ev,Iz); - 0x5: Inst::SUB(Ev,Iz); - 0x6: xor_Ev_Iz(); - 0x7: cmp_Ev_Iz(); - } - 0x2: decode MODE_SUBMODE { - 0x0: This_should_be_an_illegal_instruction(); - default: group1_Eb_Ib(); + format Inst { + 0x0E: decode OPCODE_OP_BOTTOM3 { + 0x0: JO(Jb); + 0x1: JNO(Jb); + 0x2: JB(Jb); + 0x3: JNB(Jb); + 0x4: JZ(Jb); + 0x5: JNZ(Jb); + 0x6: JBE(Jb); + 0x7: JNBE(Jb); + } + 0x0F: decode OPCODE_OP_BOTTOM3 { + 0x0: JS(Jb); + 0x1: JNS(Jb); + 0x2: JP(Jb); + 0x3: JNP(Jb); + 0x4: JL(Jb); + 0x5: JNL(Jb); + 0x6: JLE(Jb); + 0x7: JNLE(Jb); } - //0x3: group1_Ev_Ib(); - 0x3: decode MODRM_REG { - 0x0: add_Eb_Ib(); - 0x1: or_Eb_Ib(); - 0x2: adc_Eb_Ib(); - 0x3: sbb_Eb_Ib(); - 0x4: Inst::AND(Eb,Ib); - 0x5: sub_Eb_Ib(); - 0x6: xor_Eb_Ib(); - 0x7: cmp_Eb_Ib(); + } + format Inst { + 0x10: decode OPCODE_OP_BOTTOM3 { + //0x0: group1_Eb_Ib(); + 0x0: decode MODRM_REG { + 0x0: ADD(Eb,Ib); + 0x1: OR(Eb,Ib); + 0x2: ADC(Eb,Ib); + 0x3: SBB(Eb,Ib); + 0x4: AND(Eb,Ib); + 0x5: SUB(Eb,Ib); + 0x6: XOR(Eb,Ib); + 0x7: CMP(Eb,Ib); + } + //0x1: group1_Ev_Iz(); + 0x1: decode MODRM_REG { + 0x0: ADD(Ev,Iz); + 0x1: OR(Ev,Iz); + 0x2: ADC(Ev,Iz); + 0x3: SBB(Ev,Iz); + 0x4: AND(Ev,Iz); + 0x5: SUB(Ev,Iz); + 0x6: XOR(Ev,Iz); + 0x7: CMP(Ev,Iz); + } + 0x2: decode MODE_SUBMODE { + 0x0: UD2(); + //default: group1_Eb_Ib(); + default: decode MODRM_REG { + 0x0: ADD(Eb,Ib); + 0x1: OR(Eb,Ib); + 0x2: ADC(Eb,Ib); + 0x3: SBB(Eb,Ib); + 0x4: AND(Eb,Ib); + 0x5: SUB(Eb,Ib); + 0x6: XOR(Eb,Ib); + 0x7: CMP(Eb,Ib); + } + } + //0x3: group1_Ev_Ib(); + 0x3: decode MODRM_REG { + 0x0: ADD(Ev,Ib); + 0x1: OR(Ev,Ib); + 0x2: ADC(Ev,Ib); + 0x3: SBB(Ev,Ib); + 0x4: AND(Ev,Ib); + 0x5: SUB(Ev,Ib); + 0x6: XOR(Ev,Ib); + 0x7: CMP(Ev,Ib); + } + 0x4: TEST(Eb,Gb); + 0x5: TEST(Ev,Gv); + 0x6: XCHG(Eb,Gb); + 0x7: XCHG(Ev,Gv); } - 0x4: Inst::TEST(Eb,Gb); - 0x5: Inst::TEST(Ev,Gv); - 0x6: xchg_Eb_Gb(); - 0x7: xchg_Ev_Gv(); } 0x11: decode OPCODE_OP_BOTTOM3 { 0x0: Inst::MOV(Eb,Gb); @@ -322,21 +298,15 @@ 0x7: group10_Ev(); //Make sure this is Ev } 0x12: decode OPCODE_OP_BOTTOM3 { - default: nop_or_pause(); //Check for repe prefix - 0x1: xchg_rCX_rAX(); - 0x2: xchg_rDX_rAX(); - 0x3: xchg_rVX_rAX(); - 0x4: xchg_rSP_rAX(); - 0x5: xchg_rBP_rAX(); - 0x6: xchg_rSI_rAX(); - 0x7: xchg_rDI_rAX(); + 0x0: Inst::NOP(); //XXX repe makes this a "pause" + default: xchg_B_rAX(); } 0x13: decode OPCODE_OP_BOTTOM3 { 0x0: cbw_or_cwde_or_cdqe_rAX(); 0x1: cwd_or_cdq_or_cqo_rAX_rDX(); 0x2: decode MODE_SUBMODE { - 0x0: This_should_be_an_illegal_instruction(); - default: call_Ap(); + 0x0: Inst::UD2(); + default: call_far_Ap(); } 0x3: fwait(); //aka wait 0x4: pushf_Fv(); @@ -344,11 +314,11 @@ //Both of these should be illegal only if CPUID.AHF64=0, //according to sandpile.org 0x6: decode MODE_SUBMODE { - 0x0: This_should_be_an_illegal_instruction(); + 0x0: Inst::UD2(); default: sahf(); } 0x7: decode MODE_SUBMODE { - 0x0: This_should_be_an_illegal_instruction(); + 0x0: Inst::UD2(); default: lahf(); } } @@ -372,48 +342,52 @@ 0x6: scas_Yb_Al(); 0x7: scas_Yv_rAX(); } - 0x16: decode OPCODE_OP_BOTTOM3 { - 0x0: mov_Al_Ib(); - 0x1: mov_Cl_Ib(); - 0x2: mov_Dl_Ib(); - 0x3: mov_Bl_Ib(); - 0x4: mov_Ah_Ib(); - 0x5: mov_Ch_Ib(); - 0x6: mov_Dh_Ib(); - 0x7: mov_Bh_Ib(); - } format Inst { - 0x17: decode OPCODE_OP_BOTTOM3 { - 0x0: MOV(rAX,Iv); - 0x1: MOV(rCX,Iv); - 0x2: MOV(rDX,Iv); - 0x3: MOV(rBX,Iv); - 0x4: MOV(rSP,Iv); - 0x5: MOV(rBP,Iv); - 0x6: MOV(rSI,Iv); - 0x7: MOV(rDI,Iv); - } - } - 0x18: decode OPCODE_OP_BOTTOM3 { - 0x0: group2_Eb_Ib(); - 0x1: group2_Ev_Ib(); - 0x2: ret_near_Iw(); - 0x3: ret_near(); - 0x4: decode MODE_SUBMODE { - 0x0: This_should_be_an_illegal_instruction(); - default: les_Gz_Mp(); - } - 0x5: decode MODE_SUBMODE { - 0x0: This_should_be_an_illegal_instruction(); - default: lds_Gz_Mp(); - } - //0x6: group12_Eb_Ib(); - 0x6: decode MODRM_REG { - 0x0: Inst::MOV(Eb,Ib); - } - //0x7: group12_Ev_Iz(); - 0x7: decode MODRM_REG { - 0x0: Inst::MOV(Ev,Iz); + 0x16: MOV(B,Ib); + 0x17: MOV(B,Iv); + 0x18: decode OPCODE_OP_BOTTOM3 { + //0x0: group2_Eb_Ib(); + 0x0: decode MODRM_REG { + 0x0: ROL(Eb,Ib); + 0x1: ROR(Eb,Ib); + 0x2: RCL(Eb,Ib); + 0x3: RCR(Eb,Ib); + 0x4: SAL(Eb,Ib); + 0x5: SHR(Eb,Ib); + 0x6: SAL(Eb,Ib); + 0x7: SAR(Eb,Ib); + } + //0x1: group2_Ev_Ib(); + 0x1: decode MODRM_REG { + 0x0: ROL(Ev,Ib); + 0x1: ROR(Ev,Ib); + 0x2: RCL(Ev,Ib); + 0x3: RCR(Ev,Ib); + 0x4: SAL(Ev,Ib); + 0x5: SHR(Ev,Ib); + 0x6: SAL(Ev,Ib); + 0x7: SAR(Ev,Ib); + } + 0x2: RET_NEAR(Iw); + 0x3: RET_NEAR(); + 0x4: decode MODE_SUBMODE { + 0x0: UD2(); + default: WarnUnimpl::les_Gz_Mp(); + } + 0x5: decode MODE_SUBMODE { + 0x0: UD2(); + default: WarnUnimpl::lds_Gz_Mp(); + } + //0x6: group12_Eb_Ib(); + 0x6: decode MODRM_REG { + 0x0: MOV(Eb,Ib); + default: UD2(); + } + //0x7: group12_Ev_Iz(); + 0x7: decode MODRM_REG { + 0x0: MOV(Ev,Iz); + default: UD2(); + } } } 0x19: decode OPCODE_OP_BOTTOM3 { @@ -424,7 +398,7 @@ 0x4: int3(); 0x5: int_Ib(); 0x6: decode MODE_SUBMODE { - 0x0: This_should_be_an_illegal_instruction(); + 0x0: Inst::UD2(); default: into(); } 0x7: iret(); @@ -435,15 +409,15 @@ 0x2: group2_Eb_Cl(); 0x3: group2_Ev_Cl(); 0x4: decode MODE_SUBMODE { - 0x0: This_should_be_an_illegal_instruction(); + 0x0: Inst::UD2(); default: aam_Ib(); } 0x5: decode MODE_SUBMODE { - 0x0: This_should_be_an_illegal_instruction(); + 0x0: Inst::UD2(); default: aad_Ib(); } 0x6: decode MODE_SUBMODE { - 0x0: This_should_be_an_illegal_instruction(); + 0x0: Inst::UD2(); default: salc(); } 0x7: xlat(); @@ -469,13 +443,13 @@ 0x7: out_Ib_eAX(); } 0x1D: decode OPCODE_OP_BOTTOM3 { - 0x0: Inst::CALL(Jz); - 0x1: jmp_Jz(); + 0x0: Inst::CALL_NEAR(Jz); + 0x1: Inst::JMP(Jz); 0x2: decode MODE_SUBMODE { - 0x0: This_should_be_an_illegal_instruction(); - default: jmp_Ap(); + 0x0: Inst::UD2(); + default: jmp_far_Ap(); } - 0x3: jmp_Jb(); + 0x3: Inst::JMP(Jb); 0x4: in_Al_Dx(); 0x5: in_eAX_Dx(); 0x6: out_Dx_Al(); @@ -501,8 +475,25 @@ 0x3: sti(); 0x4: cld(); 0x5: std(); - 0x6: group4(); - 0x7: group5(); + 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(); + } + } } } default: FailUnimpl::oneByteOps(); diff --git a/src/arch/x86/isa/decoder/two_byte_opcodes.isa b/src/arch/x86/isa/decoder/two_byte_opcodes.isa index f05c33bdb..e5631d37b 100644 --- a/src/arch/x86/isa/decoder/two_byte_opcodes.isa +++ b/src/arch/x86/isa/decoder/two_byte_opcodes.isa @@ -58,7 +58,7 @@ // Decode the two byte opcodes // 0x2: decode OPCODE_PREFIXA { - 0xF0: decode OPCODE_OP_TOP5 { + 0x0F: decode OPCODE_OP_TOP5 { format WarnUnimpl { 0x00: decode OPCODE_OP_BOTTOM3 { 0x00: group6(); @@ -67,23 +67,25 @@ 0x03: lsl_Gv_Ew(); //sandpile.org doesn't seem to know what this is... ? 0x04: loadall_or_reset_or_hang(); - //sandpile.org says (AMD) after syscall, so I might want to check - //if that means amd64 or AMD machines - 0x05: loadall_or_syscall(); +#if FULL_SYSTEM + 0x05: syscall(); +#else + 0x05: SyscallInst::syscall('xc->syscall(rax)'); +#endif 0x06: clts(); //sandpile.org says (AMD) after sysret, so I might want to check //if that means amd64 or AMD machines 0x07: loadall_or_sysret(); } 0x01: decode OPCODE_OP_BOTTOM3 { - 0x0: holderholder(); - 0x1: holder(); - 0x2: holder(); - 0x3: holder(); - 0x4: holder(); - 0x5: holder(); - 0x6: holder(); - 0x7: holder(); + 0x0: invd(); + 0x1: wbinvd(); + 0x2: Inst::UD2(); + 0x3: UD2(); + 0x4: Inst::UD2(); + 0x5: threednow(); + 0x6: threednow(); + 0x7: threednow(); } 0x02: decode OPCODE_OP_BOTTOM3 { 0x0: holder(); @@ -96,14 +98,14 @@ 0x7: holder(); } 0x03: decode OPCODE_OP_BOTTOM3 { - 0x0: holder(); - 0x1: holder(); - 0x2: holder(); - 0x3: holder(); - 0x4: holder(); - 0x5: holder(); - 0x6: holder(); - 0x7: holder(); + 0x0: group17(); + 0x1: group17(); + 0x2: group17(); + 0x3: group17(); + 0x4: group17(); + 0x5: group17(); + 0x6: group17(); + 0x7: group17(); } 0x04: decode OPCODE_OP_BOTTOM3 { 0x0: holder(); @@ -126,44 +128,44 @@ 0x7: holder(); } 0x06: decode OPCODE_OP_BOTTOM3 { - 0x0: holder(); - 0x1: holder(); - 0x2: holder(); - 0x3: holder(); - 0x4: holder(); - 0x5: holder(); - 0x6: holder(); - 0x7: holder(); + 0x0: wrmsr(); + 0x1: rdtsc(); + 0x2: rdmsr(); + 0x3: rdpmc(); + 0x4: sysenter(); + 0x5: sysexit(); + 0x6: Inst::UD2(); + 0x7: getsec(); } 0x07: decode OPCODE_OP_BOTTOM3 { - 0x0: holder(); - 0x1: holder(); - 0x2: holder(); - 0x3: holder(); - 0x4: holder(); - 0x5: holder(); - 0x6: holder(); - 0x7: holder(); + 0x0: three_byte_opcode(); + 0x1: three_byte_opcode(); + 0x2: three_byte_opcode(); + 0x3: three_byte_opcode(); + 0x4: three_byte_opcode(); + 0x5: three_byte_opcode(); + 0x6: three_byte_opcode(); + 0x7: three_byte_opcode(); } 0x08: decode OPCODE_OP_BOTTOM3 { - 0x0: holder(); - 0x1: holder(); - 0x2: holder(); - 0x3: holder(); - 0x4: holder(); - 0x5: holder(); - 0x6: holder(); - 0x7: holder(); + 0x0: cmovo_Gv_Ev(); + 0x1: cmovno_Gv_Ev(); + 0x2: cmovb_Gv_Ev(); + 0x3: cmovnb_Gv_Ev(); + 0x4: cmovz_Gv_Ev(); + 0x5: cmovnz_Gv_Ev(); + 0x6: cmovbe_Gv_Ev(); + 0x7: cmovnbe_Gv_Ev(); } 0x09: decode OPCODE_OP_BOTTOM3 { - 0x0: holder(); - 0x1: holder(); - 0x2: holder(); - 0x3: holder(); - 0x4: holder(); - 0x5: holder(); - 0x6: holder(); - 0x7: holder(); + 0x0: cmovs_Gv_Ev(); + 0x1: cmovns_Gv_Ev(); + 0x2: cmovp_Gv_Ev(); + 0x3: cmovnp_Gv_Ev(); + 0x4: cmovl_Gv_Ev(); + 0x5: cmovnl_Gv_Ev(); + 0x6: cmovle_Gv_Ev(); + 0x7: cmovnle_Gv_Ev(); } 0x0A: decode OPCODE_OP_BOTTOM3 { 0x0: holder(); @@ -225,85 +227,87 @@ 0x6: holder(); 0x7: holder(); } - 0x10: decode OPCODE_OP_BOTTOM3 { - 0x0: holder(); - 0x1: holder(); - 0x2: holder(); - 0x3: holder(); - 0x4: holder(); - 0x5: holder(); - 0x6: holder(); - 0x7: holder(); - } - 0x11: decode OPCODE_OP_BOTTOM3 { - 0x0: holder(); - 0x1: holder(); - 0x2: holder(); - 0x3: holder(); - 0x4: holder(); - 0x5: holder(); - 0x6: holder(); - 0x7: holder(); + format Inst { + 0x10: decode OPCODE_OP_BOTTOM3 { + 0x0: JO(Jz); + 0x1: JNO(Jz); + 0x2: JB(Jz); + 0x3: JNB(Jz); + 0x4: JZ(Jz); + 0x5: JNZ(Jz); + 0x6: JBE(Jz); + 0x7: JNBE(Jz); + } + 0x11: decode OPCODE_OP_BOTTOM3 { + 0x0: JS(Jz); + 0x1: JNS(Jz); + 0x2: JP(Jz); + 0x3: JNP(Jz); + 0x4: JL(Jz); + 0x5: JNL(Jz); + 0x6: JLE(Jz); + 0x7: JNLE(Jz); + } } 0x12: decode OPCODE_OP_BOTTOM3 { - 0x0: holder(); - 0x1: holder(); - 0x2: holder(); - 0x3: holder(); - 0x4: holder(); - 0x5: holder(); - 0x6: holder(); - 0x7: holder(); + 0x0: seto_Eb(); + 0x1: setno_Eb(); + 0x2: setb_Eb(); + 0x3: setnb_Eb(); + 0x4: setz_Eb(); + 0x5: setnz_Eb(); + 0x6: setbe_Eb(); + 0x7: setnbe_Eb(); } 0x13: decode OPCODE_OP_BOTTOM3 { - 0x0: holder(); - 0x1: holder(); - 0x2: holder(); - 0x3: holder(); - 0x4: holder(); - 0x5: holder(); - 0x6: holder(); - 0x7: holder(); + 0x0: sets_Eb(); + 0x1: setns_Eb(); + 0x2: setp_Eb(); + 0x3: setnp_Eb(); + 0x4: setl_Eb(); + 0x5: setnl_Eb(); + 0x6: setle_Eb(); + 0x7: setnle_Eb(); } 0x14: decode OPCODE_OP_BOTTOM3 { - 0x0: holder(); - 0x1: holder(); - 0x2: holder(); - 0x3: holder(); - 0x4: holder(); - 0x5: holder(); - 0x6: holder(); - 0x7: holder(); + 0x0: push_fs(); + 0x1: pop_fs(); + 0x2: cpuid(); + 0x3: bt_Ev_Gv(); + 0x4: shld_Ev_Gv_Ib(); + 0x5: shld_Ev_Gv_rCl(); + 0x6: xbts_and_cmpxchg(); + 0x7: ibts_and_cmpxchg(); } 0x15: decode OPCODE_OP_BOTTOM3 { - 0x0: holder(); - 0x1: holder(); - 0x2: holder(); - 0x3: holder(); - 0x4: holder(); - 0x5: holder(); - 0x6: holder(); - 0x7: holder(); + 0x0: push_gs(); + 0x1: pop_gs(); + 0x2: rsm_smm(); + 0x3: bts_Ev_Gv(); + 0x4: shrd_Ev_Gv_Ib(); + 0x5: shrd_Ev_Gv_rCl(); + 0x6: group16(); + 0x7: Inst::IMUL(Gv,Ev); } 0x16: decode OPCODE_OP_BOTTOM3 { - 0x0: holder(); - 0x1: holder(); - 0x2: holder(); - 0x3: holder(); - 0x4: holder(); - 0x5: holder(); - 0x6: holder(); - 0x7: holder(); + 0x0: cmpxchg_Eb_Gb(); + 0x1: cmpxchg_Ev_Gv(); + 0x2: lss_Gz_Mp(); + 0x3: btr_Ev_Gv(); + 0x4: lfs_Gz_Mp(); + 0x5: lgs_Gz_Mp(); + 0x6: Inst::MOVZX_B(Gv,Eb); + 0x7: Inst::MOVZX_W(Gv,Ew); } 0x17: decode OPCODE_OP_BOTTOM3 { - 0x0: holder(); - 0x1: holder(); - 0x2: holder(); - 0x3: holder(); - 0x4: holder(); - 0x5: holder(); - 0x6: holder(); - 0x7: holder(); + 0x0: jmpe_Jz(); // IA-64? + 0x1: group11_UD2(); + 0x2: group8_Ev_Ib(); + 0x3: btc_Ev_Gv(); + 0x4: bsf_Gv_Ev(); + 0x5: bsr_Gv_Ev(); + 0x6: Inst::MOVSX_B(Gv,Eb); + 0x7: Inst::MOVSX_W(Gv,Ew); } 0x18: decode OPCODE_OP_BOTTOM3 { 0x0: holder(); @@ -315,16 +319,7 @@ 0x6: holder(); 0x7: holder(); } - 0x19: decode OPCODE_OP_BOTTOM3 { - 0x0: holder(); - 0x1: holder(); - 0x2: holder(); - 0x3: holder(); - 0x4: holder(); - 0x5: holder(); - 0x6: holder(); - 0x7: holder(); - } + 0x19: bswap_B(); 0x1A: decode OPCODE_OP_BOTTOM3 { 0x0: holder(); 0x1: holder(); diff --git a/src/arch/x86/isa/formats/error.isa b/src/arch/x86/isa/formats/error.isa index 8ac2ea44d..e85eff762 100644 --- a/src/arch/x86/isa/formats/error.isa +++ b/src/arch/x86/isa/formats/error.isa @@ -64,7 +64,7 @@ def template ErrorDecode {{ { - panic("X86 decoder internal error: '%%s' %%s", + panic("X86 decoder internal error: '%s' %s", %(message)s, machInst); } }}; diff --git a/src/arch/x86/isa/formats/formats.isa b/src/arch/x86/isa/formats/formats.isa index d763c05bc..1e7bb4a74 100644 --- a/src/arch/x86/isa/formats/formats.isa +++ b/src/arch/x86/isa/formats/formats.isa @@ -98,3 +98,7 @@ //Include a format which implements a batch of instructions which do the same //thing on a variety of inputs ##include "multi.isa" + +//Include a format which makes instructions who's sole purpose is to generate +//a syscall. +##include "syscall.isa" diff --git a/src/arch/x86/isa/formats/syscall.isa b/src/arch/x86/isa/formats/syscall.isa new file mode 100644 index 000000000..8b860dba4 --- /dev/null +++ b/src/arch/x86/isa/formats/syscall.isa @@ -0,0 +1,112 @@ +// -*- mode:c++ -*- + +// Copyright (c) 2007 The Hewlett-Packard Development Company +// All rights reserved. +// +// Redistribution and use of this software in source and binary forms, +// with or without modification, are permitted provided that the +// following conditions are met: +// +// The software must be used only for Non-Commercial Use which means any +// use which is NOT directed to receiving any direct monetary +// compensation for, or commercial advantage from such use. Illustrative +// examples of non-commercial use are academic research, personal study, +// teaching, education and corporate research & development. +// Illustrative examples of commercial use are distributing products for +// commercial advantage and providing services using the software for +// commercial advantage. +// +// If you wish to use this software or functionality therein that may be +// covered by patents for commercial use, please contact: +// Director of Intellectual Property Licensing +// Office of Strategy and Technology +// Hewlett-Packard Company +// 1501 Page Mill Road +// Palo Alto, California 94304 +// +// Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. Redistributions +// in binary form must reproduce the above copyright notice, this list of +// conditions and the following disclaimer in the documentation and/or +// other materials provided with the distribution. Neither the name of +// the COPYRIGHT HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. No right of +// sublicense is granted herewith. Derivatives of the software and +// output created using the software may be prepared, but only for +// Non-Commercial Uses. Derivatives of the software may be shared with +// others provided: (i) the others agree to abide by the list of +// conditions herein which includes the Non-Commercial Use restrictions; +// and (ii) such Derivatives of the software include the above copyright +// notice to acknowledge the contribution from this software where +// applicable, this list of conditions and the disclaimer below. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Authors: Gabe Black + +//////////////////////////////////////////////////////////////////// +// +// "Format" which describes an instruction whose only purpose is to +// call a syscall in SE mode. +// + +output header {{ + class SyscallInst : public X86ISA::X86StaticInst + { + public: + /// Constructor + SyscallInst(const char *_mnemonic, ExtMachInst _machInst, + OpClass __opClass) : + X86ISA::X86StaticInst(_mnemonic, _machInst, __opClass) + { + } + + std::string generateDisassembly(Addr pc, + const SymbolTable *symtab) const; + }; +}}; + +output decoder {{ + std::string SyscallInst::generateDisassembly(Addr PC, + const SymbolTable *symtab) const + { + std::stringstream response; + + printMnemonic(response, mnemonic); + ccprintf(response, " "); + printReg(response, _srcRegIdx[0], machInst.opSize); + return response.str(); + } +}}; + +def template SyscallExecute {{ + Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + Fault fault = NoFault; + %(op_decl)s; + %(op_rd)s; + %(code)s; + return fault; + } +}}; + +def format SyscallInst(code, *opt_flags) {{ + iop = InstObjParams(name, Name, 'SyscallInst', code, opt_flags) + header_output = BasicDeclare.subst(iop) + decoder_output = BasicConstructor.subst(iop) + decode_block = BasicDecode.subst(iop) + exec_output = SyscallExecute.subst(iop) +}}; + diff --git a/src/arch/x86/isa/formats/unimp.isa b/src/arch/x86/isa/formats/unimp.isa index 12fa8387b..183beb3b8 100644 --- a/src/arch/x86/isa/formats/unimp.isa +++ b/src/arch/x86/isa/formats/unimp.isa @@ -68,12 +68,12 @@ output header {{ * 'Unknown' class is used for unrecognized/illegal instructions. * This is a leaf class. */ - class FailUnimplemented : public X86StaticInst + class FailUnimplemented : public X86ISA::X86StaticInst { public: /// Constructor FailUnimplemented(const char *_mnemonic, ExtMachInst _machInst) - : X86StaticInst(_mnemonic, _machInst, No_OpClass) + : X86ISA::X86StaticInst(_mnemonic, _machInst, No_OpClass) { // don't call execute() (which panics) if we're on a // speculative path @@ -95,7 +95,7 @@ output header {{ * probably make the 'warned' flag a static member of the derived * class. */ - class WarnUnimplemented : public X86StaticInst + class WarnUnimplemented : public X86ISA::X86StaticInst { private: /// Have we warned on this instruction yet? @@ -104,7 +104,7 @@ output header {{ public: /// Constructor WarnUnimplemented(const char *_mnemonic, ExtMachInst _machInst) - : X86StaticInst(_mnemonic, _machInst, No_OpClass), warned(false) + : X86ISA::X86StaticInst(_mnemonic, _machInst, No_OpClass), warned(false) { // don't call execute() (which panics) if we're on a // speculative path diff --git a/src/arch/x86/isa/includes.isa b/src/arch/x86/isa/includes.isa index 4f27c72f5..58aef7b1d 100644 --- a/src/arch/x86/isa/includes.isa +++ b/src/arch/x86/isa/includes.isa @@ -97,6 +97,9 @@ output header {{ #include <iostream> #include "arch/x86/emulenv.hh" +#include "arch/x86/insts/microldstop.hh" +#include "arch/x86/insts/microregop.hh" +#include "arch/x86/insts/static_inst.hh" #include "arch/x86/isa_traits.hh" #include "arch/x86/regfile.hh" #include "arch/x86/types.hh" @@ -108,6 +111,7 @@ output header {{ output decoder {{ #include "arch/x86/faults.hh" +#include "arch/x86/miscregs.hh" #include "arch/x86/segmentregs.hh" #include "base/cprintf.hh" #include "base/loader/symtab.hh" diff --git a/src/arch/x86/isa/insts/__init__.py b/src/arch/x86/isa/insts/__init__.py index 717690926..f5c4e3113 100644 --- a/src/arch/x86/isa/insts/__init__.py +++ b/src/arch/x86/isa/insts/__init__.py @@ -69,7 +69,8 @@ categories = ["arithmetic", "rotate_and_shift", "semaphores", "string", - "system_calls"] + "system_calls", + "system"] microcode = ''' # X86 microcode diff --git a/src/arch/x86/isa/insts/arithmetic/add_and_subtract.py b/src/arch/x86/isa/insts/arithmetic/add_and_subtract.py index 809b9ac7c..05aa6cd69 100644 --- a/src/arch/x86/isa/insts/arithmetic/add_and_subtract.py +++ b/src/arch/x86/isa/insts/arithmetic/add_and_subtract.py @@ -54,23 +54,227 @@ # Authors: Gabe Black microcode = ''' +def macroop ADD_R_R +{ + add reg, reg, regm +}; + +def macroop ADD_R_I +{ + limm t1, imm + add reg, reg, t1 +}; + +def macroop ADD_M_I +{ + limm t2, imm + ld t1, ds, [scale, index, base], disp + add t1, t1, t2 + st t1, ds, [scale, index, base], disp +}; + +def macroop ADD_P_I +{ + rdip t7 + limm t2, imm + ld t1, ds, [scale, index, base], disp + add t1, t1, t2 + st t1, ds, [scale, index, base], disp +}; + +def macroop ADD_M_R +{ + ld t1, ds, [scale, index, base], disp + add t1, t1, reg + st t1, ds, [scale, index, base], disp +}; + +def macroop ADD_P_R +{ + rdip t7 + ld t1, ds, [scale, index, base], disp + add t1, t1, reg + st t1, ds, [scale, index, base], disp +}; + +def macroop ADD_R_M +{ + ld t1, ds, [scale, index, base], disp + add reg, reg, t1 +}; + +def macroop ADD_R_P +{ + rdip t7 + ld t1, ds, [scale, index, base], disp + add reg, reg, t1 +}; + +def macroop SUB_R_R +{ + sub reg, reg, regm +}; + def macroop SUB_R_I { - subi reg, reg, imm + limm t1, imm + sub reg, reg, t1 +}; + +def macroop SUB_R_M +{ + ld t1, ds, [scale, index, base], disp + sub reg, reg, t1 +}; + +def macroop SUB_R_P +{ + rdip t7 + ld t1, ds, [scale, index, base], disp + sub reg, reg, t1 }; def macroop SUB_M_I { + limm t2, imm ld t1, ds, [scale, index, base], disp - subi t1, t1, imm + sub t1, t1, t2 st t1, ds, [scale, index, base], disp }; def macroop SUB_P_I { rdip t7 + limm t2, imm + ld t1, ds, [scale, index, base], disp + sub t1, t1, t2 + st t1, ds, [scale, index, base], disp +}; + +def macroop SUB_M_R +{ + ld t1, ds, [scale, index, base], disp + sub t1, t1, reg + st t1, ds, [scale, index, base], disp +}; + +def macroop SUB_P_R +{ + rdip t7 + ld t1, ds, [scale, index, base], disp + sub t1, t1, reg + st t1, ds, [scale, index, base], disp +}; + +def macroop ADC_R_R +{ + adc reg, reg, regm +}; + +def macroop ADC_R_I +{ + limm t1, imm + adc reg, reg, t1 +}; + +def macroop ADC_M_I +{ + limm t2, imm + ld t1, ds, [scale, index, base], disp + adc t1, t1, t2 + st t1, ds, [scale, index, base], disp +}; + +def macroop ADC_P_I +{ + rdip t7 + limm t2, imm + ld t1, ds, [scale, index, base], disp + adc t1, t1, t2 + st t1, ds, [scale, index, base], disp +}; + +def macroop ADC_M_R +{ + ld t1, ds, [scale, index, base], disp + adc t1, t1, reg + st t1, ds, [scale, index, base], disp +}; + +def macroop ADC_P_R +{ + rdip t7 + ld t1, ds, [scale, index, base], disp + adc t1, t1, reg + st t1, ds, [scale, index, base], disp +}; + +def macroop ADC_R_M +{ + ld t1, ds, [scale, index, base], disp + adc reg, reg, t1 +}; + +def macroop ADC_R_P +{ + rdip t7 + ld t1, ds, [scale, index, base], disp + adc reg, reg, t1 +}; + +def macroop SBB_R_R +{ + sbb reg, reg, regm +}; + +def macroop SBB_R_I +{ + limm t1, imm + sbb reg, reg, t1 +}; + +def macroop SBB_R_M +{ + ld t1, ds, [scale, index, base], disp + sbb reg, reg, t1 +}; + +def macroop SBB_R_P +{ + rdip t7 + ld t1, ds, [scale, index, base], disp + sbb reg, reg, t1 +}; + +def macroop SBB_M_I +{ + limm t2, imm + ld t1, ds, [scale, index, base], disp + sbb t1, t1, t2 + st t1, ds, [scale, index, base], disp +}; + +def macroop SBB_P_I +{ + rdip t7 + limm t2, imm + ld t1, ds, [scale, index, base], disp + sbb t1, t1, t2 + st t1, ds, [scale, index, base], disp +}; + +def macroop SBB_M_R +{ + ld t1, ds, [scale, index, base], disp + sbb t1, t1, reg + st t1, ds, [scale, index, base], disp +}; + +def macroop SBB_P_R +{ + rdip t7 ld t1, ds, [scale, index, base], disp - subi t1, t1, imm + sbb t1, t1, reg st t1, ds, [scale, index, base], disp }; ''' diff --git a/src/arch/x86/isa/insts/arithmetic/increment_and_decrement.py b/src/arch/x86/isa/insts/arithmetic/increment_and_decrement.py index c504d47ce..eed39c10c 100644 --- a/src/arch/x86/isa/insts/arithmetic/increment_and_decrement.py +++ b/src/arch/x86/isa/insts/arithmetic/increment_and_decrement.py @@ -53,7 +53,47 @@ # # Authors: Gabe Black -microcode = "" +microcode = ''' +def macroop INC_R +{ + addi reg, reg, 1, flags=(OF, SF, ZF, AF, PF) +}; + +def macroop INC_M +{ + ld t1, ds, [scale, index, base], disp + addi t1, t1, 1, flags=(OF, SF, ZF, AF, PF) + st t1, ds, [scale, index, base], disp +}; + +def macroop INC_P +{ + rdip t7 + ld t1, ds, [0, t0, t7], disp + addi reg, reg, 1, flags=(OF, SF, ZF, AF, PF) + st t1, ds, [0, t0, t7], disp +}; + +def macroop DEC_R +{ + subi reg, reg, 1, flags=(OF, SF, ZF, AF, PF) +}; + +def macroop DEC_M +{ + ld t1, ds, [scale, index, base], disp + subi t1, t1, 1, flags=(OF, SF, ZF, AF, PF) + st t1, ds, [scale, index, base], disp +}; + +def macroop DEC_P +{ + rdip t7 + ld t1, ds, [0, t0, t7], disp + subi reg, reg, 1, flags=(OF, SF, ZF, AF, PF) + st t1, ds, [0, t0, t7], disp +}; +''' #let {{ # class DEC(Inst): # "GenFault ${new UnimpInstFault}" diff --git a/src/arch/x86/isa/insts/arithmetic/multiply_and_divide.py b/src/arch/x86/isa/insts/arithmetic/multiply_and_divide.py index 662022e6a..8697bef65 100644 --- a/src/arch/x86/isa/insts/arithmetic/multiply_and_divide.py +++ b/src/arch/x86/isa/insts/arithmetic/multiply_and_divide.py @@ -53,7 +53,31 @@ # # Authors: Gabe Black -microcode = "" +microcode = ''' + +# +# Two operand signed multiply. These should set the CF and OF flags if the +# result is too large for the destination register +# + +def macroop IMUL_R_R +{ + mul1s reg, reg, regm +}; + +def macroop IMUL_R_M +{ + ld t1, ds, [scale, index, base], disp + mul1s reg, reg, t1 +}; + +def macroop IMUL_R_P +{ + rdip t7 + ld t1, ds, [scale, index, base], disp + mul1s reg, reg, t1 +}; +''' #let {{ # class MUL(Inst): # "GenFault ${new UnimpInstFault}" diff --git a/src/arch/x86/isa/insts/compare_and_test/compare.py b/src/arch/x86/isa/insts/compare_and_test/compare.py index 12b5b859f..8f5890b23 100644 --- a/src/arch/x86/isa/insts/compare_and_test/compare.py +++ b/src/arch/x86/isa/insts/compare_and_test/compare.py @@ -53,8 +53,56 @@ # # Authors: Gabe Black -microcode = "" -#let {{ -# class CMP(Inst): -# "GenFault ${new UnimpInstFault}" -#}}; +microcode = ''' +def macroop CMP_R_M +{ + ld t1, ds, [scale, index, base], disp + sub t0, reg, t1, flags=(OF, SF, ZF, AF, PF, CF) +}; + +def macroop CMP_R_P +{ + rdip t7 + ld t1, ds, [0, t0, t7], disp + sub t0, reg, t1, flags=(OF, SF, ZF, AF, PF, CF) +}; + +def macroop CMP_M_I +{ + limm t2, imm + ld t1, ds, [scale, index, base], disp + sub t0, t1, t2, flags=(OF, SF, ZF, AF, PF, CF) +}; + +def macroop CMP_P_I +{ + limm t2, imm + rdip t7 + ld t1, ds, [0, t0, t7], disp + sub t0, t1, t2, flags=(OF, SF, ZF, AF, PF, CF) +}; + +def macroop CMP_M_R +{ + ld t1, ds, [scale, index, base], disp + sub t0, t1, reg, flags=(OF, SF, ZF, AF, PF, CF) +}; + +def macroop CMP_P_R +{ + rdip t7 + ld t1, ds, [0, t0, t7], disp + sub t0, t1, reg, flags=(OF, SF, ZF, AF, PF, CF) +}; + +def macroop CMP_R_R +{ + sub t0, reg, regm, flags=(OF, SF, ZF, AF, PF, CF) +}; + +def macroop CMP_R_I +{ + limm t1, imm + sub t0, reg, t1, flags=(OF, SF, ZF, AF, PF, CF) +}; +''' diff --git a/src/arch/x86/isa/insts/compare_and_test/test.py b/src/arch/x86/isa/insts/compare_and_test/test.py index 89d406912..8da33899a 100644 --- a/src/arch/x86/isa/insts/compare_and_test/test.py +++ b/src/arch/x86/isa/insts/compare_and_test/test.py @@ -57,39 +57,39 @@ microcode = ''' def macroop TEST_M_R { ld t1, ds, [scale, index, base], disp - and t0, t1, reg + and t0, t1, reg, flags=(SF, ZF, PF) }; def macroop TEST_P_R { rdip t7 - ld t1, ds, [scale, index, base], disp - and t0, t1, reg + ld t1, ds, [0, t0, t7], disp + and t0, t1, reg, flags=(SF, ZF, PF) }; def macroop TEST_R_R { - and t0, reg, regm + and t0, reg, regm, flags=(SF, ZF, PF) }; def macroop TEST_M_I { ld t1, ds, [scale, index, base], disp limm t2, imm - and t0, t1, t2 + and t0, t1, t2, flags=(SF, ZF, PF) }; def macroop TEST_P_I { rdip t7 - ld t1, ds, [scale, index, base], disp + ld t1, ds, [0, t0, t7], disp limm t2, imm - and t0, t1, t2 + and t0, t1, t2, flags=(SF, ZF, PF) }; def macroop TEST_R_I { limm t1, imm - and t0, reg, t1 + and t0, reg, t1, flags=(SF, ZF, PF) }; ''' diff --git a/src/arch/x86/isa/insts/control_transfer/call.py b/src/arch/x86/isa/insts/control_transfer/call.py index 530162bfd..c5bb66e58 100644 --- a/src/arch/x86/isa/insts/control_transfer/call.py +++ b/src/arch/x86/isa/insts/control_transfer/call.py @@ -54,16 +54,51 @@ # Authors: Gabe Black microcode = ''' -def macroop CALL_I +def macroop CALL_NEAR_I { - # Make the default data size of pops 64 bits in 64 bit mode + # Make the default data size of calls 64 bits in 64 bit mode + .adjust_env oszIn64Override + + 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 - limm t2, imm 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 e90e5b12b..158861a3d 100644 --- a/src/arch/x86/isa/insts/control_transfer/jump.py +++ b/src/arch/x86/isa/insts/control_transfer/jump.py @@ -53,8 +53,192 @@ # # Authors: Gabe Black -microcode = "" -#let {{ -# class JMP(Inst): -# "GenFault ${new UnimpInstFault}" -#}}; +microcode = ''' +def macroop JZ_I +{ + # Make the defualt data size of jumps 64 bits in 64 bit mode + .adjust_env oszIn64Override + + rdip t1 + limm t2, imm + wrip t1, t2, flags=(CZF,) +}; + +def macroop JNZ_I +{ + # Make the defualt data size of jumps 64 bits in 64 bit mode + .adjust_env oszIn64Override + + rdip t1 + limm t2, imm + wrip t1, t2, flags=(nCZF,) +}; + +def macroop JB_I +{ + # Make the default data size of jumps 64 bits in 64 bit mode + .adjust_env oszIn64Override + + rdip t1 + limm t2, imm + wrip t1, t2, flags=(CCF,) +}; + +def macroop JNB_I +{ + # Make the default data size of jumps 64 bits in 64 bit mode + .adjust_env oszIn64Override + + rdip t1 + limm t2, imm + wrip t1, t2, flags=(nCCF,) +}; + +def macroop JBE_I +{ + # Make the default data size of jumps 64 bits in 64 bit mode + .adjust_env oszIn64Override + + rdip t1 + limm t2, imm + wrip t1, t2, flags=(CCvZF,) +}; + +def macroop JNBE_I +{ + # Make the default data size of jumps 64 bits in 64 bit mode + .adjust_env oszIn64Override + + rdip t1 + limm t2, imm + wrip t1, t2, flags=(nCCvZF,) +}; + +def macroop JS_I +{ + # Make the default data size of jumps 64 bits in 64 bit mode + .adjust_env oszIn64Override + + rdip t1 + limm t2, imm + wrip t1, t2, flags=(CSF,) +}; + +def macroop JNS_I +{ + # Make the default data size of jumps 64 bits in 64 bit mode + .adjust_env oszIn64Override + + rdip t1 + limm t2, imm + wrip t1, t2, flags=(nCSF,) +}; + +def macroop JP_I +{ + # Make the default data size of jumps 64 bits in 64 bit mode + .adjust_env oszIn64Override + + rdip t1 + limm t2, imm + wrip t1, t2, flags=(CPF,) +}; + +def macroop JNP_I +{ + # Make the default data size of jumps 64 bits in 64 bit mode + .adjust_env oszIn64Override + + rdip t1 + limm t2, imm + wrip t1, t2, flags=(nCPF,) +}; + +def macroop JL_I +{ + # Make the default data size of jumps 64 bits in 64 bit mode + .adjust_env oszIn64Override + + rdip t1 + limm t2, imm + wrip t1, t2, flags=(CSxOF,) +}; + +def macroop JNL_I +{ + # Make the default data size of jumps 64 bits in 64 bit mode + .adjust_env oszIn64Override + + rdip t1 + limm t2, imm + wrip t1, t2, flags=(nCSxOF,) +}; + +def macroop JLE_I +{ + # Make the default data size of jumps 64 bits in 64 bit mode + .adjust_env oszIn64Override + + rdip t1 + limm t2, imm + wrip t1, t2, flags=(CSxOvZF,) +}; + +def macroop JNLE_I +{ + # Make the default data size of jumps 64 bits in 64 bit mode + .adjust_env oszIn64Override + + rdip t1 + limm t2, imm + wrip t1, t2, flags=(nCSxOvZF,) +}; + +def macroop JO_I +{ + # Make the default data size of jumps 64 bits in 64 bit mode + .adjust_env oszIn64Override + + rdip t1 + limm t2, imm + wrip t1, t2, flags=(COF,) +}; + +def macroop JNO_I +{ + # Make the default data size of jumps 64 bits in 64 bit mode + .adjust_env oszIn64Override + + rdip t1 + limm t2, imm + wrip t1, t2, flags=(nCOF,) +}; + +def macroop JMP_I +{ + # Make the default data size of jumps 64 bits in 64 bit mode + .adjust_env oszIn64Override + + rdip t1 + limm t2, imm + wrip t1, t2 +}; + +def macroop JMP_R +{ + wripi reg, 0 +}; + +def macroop JMP_M +{ + ld t1, ds, [scale, index, base], disp + 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/control_transfer/xreturn.py b/src/arch/x86/isa/insts/control_transfer/xreturn.py index aaffa2b92..0000cd3c1 100644 --- a/src/arch/x86/isa/insts/control_transfer/xreturn.py +++ b/src/arch/x86/isa/insts/control_transfer/xreturn.py @@ -53,8 +53,26 @@ # # Authors: Gabe Black -microcode = "" -#let {{ -# class RET(Inst): -# "GenFault ${new UnimpInstFault}" -#}}; +microcode = ''' +def macroop RET_NEAR +{ + # Make the default data size of rets 64 bits in 64 bit mode + .adjust_env oszIn64Override + + ld t1, ss, [0, t0, rsp] + addi rsp, rsp, dsz + wripi t1, 0 +}; + +def macroop RET_NEAR_I +{ + # Make the default data size of rets 64 bits in 64 bit mode + .adjust_env oszIn64Override + + limm t2, imm + ld t1, ss, [0, t0, rsp] + addi rsp, rsp, dsz + add rsp, rsp, t2 + wripi t1, 0 +}; +''' diff --git a/src/arch/x86/isa/insts/data_transfer/__init__.py b/src/arch/x86/isa/insts/data_transfer/__init__.py index eda173b34..365f95eaa 100644 --- a/src/arch/x86/isa/insts/data_transfer/__init__.py +++ b/src/arch/x86/isa/insts/data_transfer/__init__.py @@ -55,7 +55,8 @@ categories = ["conditional_move", "move", - "stack_operations"] + "stack_operations", + "xchg"] microcode = "" for category in categories: diff --git a/src/arch/x86/isa/insts/data_transfer/move.py b/src/arch/x86/isa/insts/data_transfer/move.py index c85dd7cc4..bbc55e47c 100644 --- a/src/arch/x86/isa/insts/data_transfer/move.py +++ b/src/arch/x86/isa/insts/data_transfer/move.py @@ -54,6 +54,11 @@ # Authors: Gabe Black microcode = ''' + +# +# Regular moves +# + def macroop MOV_R_R { mov reg, reg, regm }; @@ -64,7 +69,7 @@ def macroop MOV_M_R { def macroop MOV_P_R { rdip t7 - st reg, ds, [scale, index, base], disp + st reg, ds, [0, t0, t7], disp }; def macroop MOV_R_M { @@ -73,7 +78,7 @@ def macroop MOV_R_M { def macroop MOV_R_P { rdip t7 - ld reg, ds, [scale, index, base], disp + ld reg, ds, [0, t0, t7], disp }; def macroop MOV_R_I { @@ -88,22 +93,90 @@ def macroop MOV_M_I { def macroop MOV_P_I { rdip t7 limm t1, imm - st t1, ds, [scale, index, base], disp + st t1, ds, [0, t0, t7], disp }; +# +# Sign extending moves +# + def macroop MOVSXD_R_R { - sext reg, regm, dsz + sext reg, regm, 32 }; def macroop MOVSXD_R_M { - ld t1, ds, [scale, index, base], disp - sext reg, t1, dsz + ld t1, ds, [scale, index, base], disp, dataSize=4 + sext reg, t1, 32 }; def macroop MOVSXD_R_P { rdip t7 - ld t1, ds, [scale, index, base], disp - sext reg, t1, dsz + ld t1, ds, [0, t0, t7], disp, dataSize=4 + sext reg, t1, 32 +}; + +def macroop MOVSX_B_R_R { + sext reg, regm, 8 +}; + +def macroop MOVSX_B_R_M { + ld reg, ds, [scale, index, base], disp, dataSize=1 + sext reg, reg, 8 +}; + +def macroop MOVSX_B_R_P { + rdip t7 + ld reg, ds, [0, t0, t7], disp, dataSize=1 + sext reg, reg, 8 +}; + +def macroop MOVSX_W_R_R { + sext reg, regm, 16 +}; + +def macroop MOVSX_W_R_M { + ld reg, ds, [scale, index, base], disp, dataSize=2 + sext reg, reg, 16 +}; + +def macroop MOVSX_W_R_P { + rdip t7 + ld reg, ds, [0, t0, t7], disp, dataSize=2 + sext reg, reg, 16 +}; + +# +# Zero extending moves +# + +def macroop MOVZX_B_R_R { + zext reg, regm, 8 +}; + +def macroop MOVZX_B_R_M { + ld t1, ds, [scale, index, base], disp, dataSize=1 + zext reg, t1, 8 +}; + +def macroop MOVZX_B_R_P { + rdip t7 + ld t1, ds, [0, t0, t7], disp, dataSize=1 + zext reg, t1, 8 +}; + +def macroop MOVZX_W_R_R { + zext reg, regm, 16 +}; + +def macroop MOVZX_W_R_M { + ld t1, ds, [scale, index, base], disp, dataSize=2 + zext reg, t1, 16 +}; + +def macroop MOVZX_W_R_P { + rdip t7 + ld t1, ds, [0, t0, t7], disp, dataSize=2 + zext reg, t1, 16 }; ''' #let {{ 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/data_transfer/xchg.py b/src/arch/x86/isa/insts/data_transfer/xchg.py new file mode 100644 index 000000000..4f401deb7 --- /dev/null +++ b/src/arch/x86/isa/insts/data_transfer/xchg.py @@ -0,0 +1,98 @@ +# Copyright (c) 2007 The Hewlett-Packard Development Company +# All rights reserved. +# +# Redistribution and use of this software in source and binary forms, +# with or without modification, are permitted provided that the +# following conditions are met: +# +# The software must be used only for Non-Commercial Use which means any +# use which is NOT directed to receiving any direct monetary +# compensation for, or commercial advantage from such use. Illustrative +# examples of non-commercial use are academic research, personal study, +# teaching, education and corporate research & development. +# Illustrative examples of commercial use are distributing products for +# commercial advantage and providing services using the software for +# commercial advantage. +# +# If you wish to use this software or functionality therein that may be +# covered by patents for commercial use, please contact: +# Director of Intellectual Property Licensing +# Office of Strategy and Technology +# Hewlett-Packard Company +# 1501 Page Mill Road +# Palo Alto, California 94304 +# +# Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. Redistributions +# in binary form must reproduce the above copyright notice, this list of +# conditions and the following disclaimer in the documentation and/or +# other materials provided with the distribution. Neither the name of +# the COPYRIGHT HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. No right of +# sublicense is granted herewith. Derivatives of the software and +# output created using the software may be prepared, but only for +# Non-Commercial Uses. Derivatives of the software may be shared with +# others provided: (i) the others agree to abide by the list of +# conditions herein which includes the Non-Commercial Use restrictions; +# and (ii) such Derivatives of the software include the above copyright +# notice to acknowledge the contribution from this software where +# applicable, this list of conditions and the disclaimer below. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Authors: Gabe Black + +microcode = ''' + +# All the memory versions need to use LOCK, regardless of if it was set + +def macroop XCHG_R_R +{ + # Use the xor trick instead of moves to reduce register pressure. + # This probably doesn't make much of a difference, but it's easy. + xor reg, reg, regm + xor regm, regm, reg + xor reg, reg, regm +}; + +def macroop XCHG_R_M +{ + ld t1, ds, [scale, index, base], disp + st reg, ds, [scale, index, base], disp + mov reg, reg, t1 +}; + +def macroop XCHG_R_P +{ + rdip t7 + ld t1, ds, [0, t0, t7], disp + st reg, ds, [0, t0, t7], disp + mov reg, reg, t1 +}; + +def macroop XCHG_M_R +{ + ld t1, ds, [scale, index, base], disp + st reg, ds, [scale, index, base], disp + mov reg, reg, t1 +}; + +def macroop XCHG_P_R +{ + rdip t7 + ld t1, ds, [0, t0, t7], disp + st reg, ds, [0, t0, t7], disp + mov reg, reg, t1 +}; +''' diff --git a/src/arch/x86/isa/insts/logical.py b/src/arch/x86/isa/insts/logical.py index 2fd369d60..f99638cac 100644 --- a/src/arch/x86/isa/insts/logical.py +++ b/src/arch/x86/isa/insts/logical.py @@ -54,6 +54,62 @@ # Authors: Gabe Black microcode = ''' +def macroop OR_R_R +{ + or reg, reg, regm +}; + +def macroop OR_M_I +{ + limm t2, imm + ld t1, ds, [scale, index, base], disp + or t1, t1, t2 + st t1, ds, [scale, index, base], disp +}; + +def macroop OR_P_I +{ + limm t2, imm + rdip t7 + ld t1, ds, [0, t0, t7], disp + or t1, t1, t2 + st t1, ds, [0, t0, t7], disp +}; + +def macroop OR_M_R +{ + ld t1, ds, [scale, index, base], disp + or t1, t1, reg + st t1, ds, [scale, index, base], disp +}; + +def macroop OR_P_R +{ + rdip t7 + ld t1, ds, [0, t0, t7], disp + or t1, t1, reg + st t1, ds, [0, t0, t7], disp +}; + +def macroop OR_R_M +{ + ld t1, ds, [scale, index, base], disp + or reg, reg, t1 +}; + +def macroop OR_R_P +{ + rdip t7 + ld t1, ds, [0, t0, t7], disp + or reg, reg, t1 +}; + +def macroop OR_R_I +{ + limm t1, imm + or reg, reg, t1 +}; + def macroop XOR_R_R { xor reg, reg, regm @@ -65,6 +121,23 @@ def macroop XOR_R_I xor reg, reg, t1 }; +def macroop XOR_M_I +{ + limm t2, imm + ld t1, ds, [scale, index, base], disp + xor t1, t1, t2 + st t1, ds, [scale, index, base], disp +}; + +def macroop XOR_P_I +{ + limm t2, imm + rdip t7 + ld t1, ds, [scale, index, base], disp + xor t1, t1, t2 + st t1, ds, [scale, index, base], disp +}; + def macroop XOR_M_R { ld t1, ds, [scale, index, base], disp @@ -93,6 +166,24 @@ def macroop XOR_R_P xor reg, reg, t1 }; +def macroop AND_R_R +{ + and reg, reg, regm +}; + +def macroop AND_R_M +{ + ld t1, ds, [scale, index, base], disp + and reg, reg, t1 +}; + +def macroop AND_R_P +{ + rdip t7 + ld t1, ds, [scale, index, base], disp + and reg, reg, t1 +}; + def macroop AND_R_I { limm t1, imm @@ -115,6 +206,21 @@ def macroop AND_P_I and t2, t2, t1 st t2, ds, [scale, index, base], disp }; + +def macroop AND_M_R +{ + ld t1, ds, [scale, index, base], disp + and t1, t1, reg + st t1, ds, [scale, index, base], disp +}; + +def macroop AND_P_R +{ + rdip t7 + ld t1, ds, [scale, index, base], disp + and t1, t1, reg + st t1, ds, [scale, index, base], disp +}; ''' #let {{ #microcodeString = ''' diff --git a/src/arch/x86/isa/insts/no_operation.py b/src/arch/x86/isa/insts/no_operation.py index 1a287aea7..306ee2797 100644 --- a/src/arch/x86/isa/insts/no_operation.py +++ b/src/arch/x86/isa/insts/no_operation.py @@ -53,8 +53,9 @@ # # Authors: Gabe Black -microcode = "" -#let {{ -# class NOP(Inst): -# "GenFault ${new UnimpInstFault}" -#}}; +microcode = ''' +def macroop NOP +{ + fault "NoFault" +}; +''' 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..0988f8815 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,90 @@ # # 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 +}; + +def macroop RCL_R_I +{ + rcl reg, reg, imm +}; + +def macroop RCL_M_I +{ + ld t1, ds, [scale, index, base], disp + rcl t1, t1, imm + st t1, ds, [scale, index, base], disp +}; + +def macroop RCL_P_I +{ + rdip t7 + ld t1, ds, [0, t0, t7], disp + rcl t1, t1, imm + st t1, ds, [0, t0, t7], disp +}; + +def macroop RCR_R_I +{ + rcr reg, reg, imm +}; + +def macroop RCR_M_I +{ + ld t1, ds, [scale, index, base], disp + rcr t1, t1, imm + st t1, ds, [scale, index, base], disp +}; + +def macroop RCR_P_I +{ + rdip t7 + ld t1, ds, [0, t0, t7], disp + rcr 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 f72794657..5a04317d9 100644 --- a/src/arch/x86/isa/insts/rotate_and_shift/shift.py +++ b/src/arch/x86/isa/insts/rotate_and_shift/shift.py @@ -53,7 +53,67 @@ # # Authors: Gabe Black -microcode = "" +microcode = ''' +def macroop SAL_R_I +{ + sll reg, reg, imm +}; + +def macroop SAL_M_I +{ + ld t1, ds, [scale, index, base], disp + sll t1, t1, imm + st t1, ds, [scale, index, base], disp +}; + +def macroop SAL_P_I +{ + rdip t7 + ld t1, ds, [0, t0, t7], disp + 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): # "GenFault ${new UnimpInstFault}" diff --git a/src/arch/x86/isa/insts/system/__init__.py b/src/arch/x86/isa/insts/system/__init__.py new file mode 100644 index 000000000..72e3bdf0a --- /dev/null +++ b/src/arch/x86/isa/insts/system/__init__.py @@ -0,0 +1,62 @@ +# Copyright (c) 2007 The Hewlett-Packard Development Company +# All rights reserved. +# +# Redistribution and use of this software in source and binary forms, +# with or without modification, are permitted provided that the +# following conditions are met: +# +# The software must be used only for Non-Commercial Use which means any +# use which is NOT directed to receiving any direct monetary +# compensation for, or commercial advantage from such use. Illustrative +# examples of non-commercial use are academic research, personal study, +# teaching, education and corporate research & development. +# Illustrative examples of commercial use are distributing products for +# commercial advantage and providing services using the software for +# commercial advantage. +# +# If you wish to use this software or functionality therein that may be +# covered by patents for commercial use, please contact: +# Director of Intellectual Property Licensing +# Office of Strategy and Technology +# Hewlett-Packard Company +# 1501 Page Mill Road +# Palo Alto, California 94304 +# +# Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. Redistributions +# in binary form must reproduce the above copyright notice, this list of +# conditions and the following disclaimer in the documentation and/or +# other materials provided with the distribution. Neither the name of +# the COPYRIGHT HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. No right of +# sublicense is granted herewith. Derivatives of the software and +# output created using the software may be prepared, but only for +# Non-Commercial Uses. Derivatives of the software may be shared with +# others provided: (i) the others agree to abide by the list of +# conditions herein which includes the Non-Commercial Use restrictions; +# and (ii) such Derivatives of the software include the above copyright +# notice to acknowledge the contribution from this software where +# applicable, this list of conditions and the disclaimer below. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Authors: Gabe Black + +categories = ["undefined_operation"] + +microcode = "" +for category in categories: + exec "import %s as cat" % category + microcode += cat.microcode + diff --git a/src/arch/x86/isa/insts/system/undefined_operation.py b/src/arch/x86/isa/insts/system/undefined_operation.py new file mode 100644 index 000000000..e5544b6e7 --- /dev/null +++ b/src/arch/x86/isa/insts/system/undefined_operation.py @@ -0,0 +1,61 @@ +# Copyright (c) 2007 The Hewlett-Packard Development Company +# All rights reserved. +# +# Redistribution and use of this software in source and binary forms, +# with or without modification, are permitted provided that the +# following conditions are met: +# +# The software must be used only for Non-Commercial Use which means any +# use which is NOT directed to receiving any direct monetary +# compensation for, or commercial advantage from such use. Illustrative +# examples of non-commercial use are academic research, personal study, +# teaching, education and corporate research & development. +# Illustrative examples of commercial use are distributing products for +# commercial advantage and providing services using the software for +# commercial advantage. +# +# If you wish to use this software or functionality therein that may be +# covered by patents for commercial use, please contact: +# Director of Intellectual Property Licensing +# Office of Strategy and Technology +# Hewlett-Packard Company +# 1501 Page Mill Road +# Palo Alto, California 94304 +# +# Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. Redistributions +# in binary form must reproduce the above copyright notice, this list of +# conditions and the following disclaimer in the documentation and/or +# other materials provided with the distribution. Neither the name of +# the COPYRIGHT HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. No right of +# sublicense is granted herewith. Derivatives of the software and +# output created using the software may be prepared, but only for +# Non-Commercial Uses. Derivatives of the software may be shared with +# others provided: (i) the others agree to abide by the list of +# conditions herein which includes the Non-Commercial Use restrictions; +# and (ii) such Derivatives of the software include the above copyright +# notice to acknowledge the contribution from this software where +# applicable, this list of conditions and the disclaimer below. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Authors: Gabe Black + +microcode = ''' +def macroop UD2 +{ + fault "new X86Fault" +}; +''' diff --git a/src/arch/x86/isa/main.isa b/src/arch/x86/isa/main.isa index fed8903c0..73cebc12b 100644 --- a/src/arch/x86/isa/main.isa +++ b/src/arch/x86/isa/main.isa @@ -79,8 +79,8 @@ namespace X86ISA; //Include the bitfield definitions ##include "bitfields.isa" -//Include the base class for x86 instructions, and some support code. -##include "base.isa" +//Include the OutputBlocks class which is used to bundle output. +##include "outputblock.isa" //Include the definitions for the instruction formats ##include "formats/formats.isa" diff --git a/src/arch/x86/isa/microasm.isa b/src/arch/x86/isa/microasm.isa index ee2b92f53..213468b0b 100644 --- a/src/arch/x86/isa/microasm.isa +++ b/src/arch/x86/isa/microasm.isa @@ -56,9 +56,9 @@ // Authors: Gabe Black //Include the definitions of the micro ops. -//These are StaticInst classes which stand on their own and make up an -//internal instruction set, and also python representations which are passed -//into the microcode assembler. +//These are python representations of static insts which stand on their own +//and make up an internal instruction set. They are used by the micro +//assembler. ##include "microops/microops.isa" //Include code to build macroops in both C++ and python. @@ -96,6 +96,19 @@ let {{ assembler.symbols["r%s" % reg] = "INTREG_R%s" % reg.upper() assembler.symbols.update(symbols) + for flag in ('CF', 'PF', 'ECF', 'AF', 'EZF', 'ZF', 'SF', 'OF'): + assembler.symbols[flag] = flag + "Bit" + + for cond in ('True', 'False', 'ECF', 'EZF', 'SZnZF', + 'MSTRZ', 'STRZ', 'MSTRC', 'STRZnZF', + 'OF', 'CF', 'ZF', 'CvZF', + 'SF', 'PF', 'SxOF', 'SxOvZF'): + assembler.symbols["C%s" % cond] = "ConditionTests::%s" % cond + assembler.symbols["nC%s" % cond] = "ConditionTests::Not%s" % cond + + assembler.symbols["CTrue"] = "ConditionTests::True" + assembler.symbols["CFalse"] = "ConditionTests::False" + # Code literal which forces a default 64 bit operand size in 64 bit mode. assembler.symbols["oszIn64Override"] = ''' if (machInst.mode.submode == SixtyFourBitMode && diff --git a/src/arch/x86/isa/microops/base.isa b/src/arch/x86/isa/microops/base.isa index 79ac4493a..71fc3b3a5 100644 --- a/src/arch/x86/isa/microops/base.isa +++ b/src/arch/x86/isa/microops/base.isa @@ -61,42 +61,6 @@ let {{ microopClasses = {} }}; -//A class which is the base of all x86 micro ops. It provides a function to -//set necessary flags appropriately. -output header {{ - class X86MicroopBase : public X86StaticInst - { - protected: - const char * instMnem; - uint8_t opSize; - uint8_t addrSize; - - X86MicroopBase(ExtMachInst _machInst, - const char *mnem, const char *_instMnem, - bool isMicro, bool isDelayed, - bool isFirst, bool isLast, - OpClass __opClass) : - X86StaticInst(mnem, _machInst, __opClass), - instMnem(_instMnem) - { - flags[IsMicroop] = isMicro; - flags[IsDelayedCommit] = isDelayed; - flags[IsFirstMicroop] = isFirst; - flags[IsLastMicroop] = isLast; - } - - std::string generateDisassembly(Addr pc, - const SymbolTable *symtab) const - { - std::stringstream ss; - - ccprintf(ss, "\t%s.%s", instMnem, mnemonic); - - return ss.str(); - } - }; -}}; - ////////////////////////////////////////////////////////////////////////// // // Base class for the python representation of x86 microops diff --git a/src/arch/x86/isa/microops/ldstop.isa b/src/arch/x86/isa/microops/ldstop.isa index fbff899a0..ccf519963 100644 --- a/src/arch/x86/isa/microops/ldstop.isa +++ b/src/arch/x86/isa/microops/ldstop.isa @@ -59,63 +59,6 @@ // ////////////////////////////////////////////////////////////////////////// -output header {{ - /** - * Base class for load and store ops - */ - class LdStOp : public X86MicroopBase - { - protected: - const uint8_t scale; - const RegIndex index; - const RegIndex base; - const uint64_t disp; - const uint8_t segment; - const RegIndex data; - const uint8_t dataSize; - const uint8_t addressSize; - - //Constructor - LdStOp(ExtMachInst _machInst, - const char * mnem, const char * _instMnem, - bool isMicro, bool isDelayed, bool isFirst, bool isLast, - uint8_t _scale, RegIndex _index, RegIndex _base, - uint64_t _disp, uint8_t _segment, - RegIndex _data, - uint8_t _dataSize, uint8_t _addressSize, - OpClass __opClass) : - X86MicroopBase(machInst, mnem, _instMnem, - isMicro, isDelayed, isFirst, isLast, __opClass), - scale(_scale), index(_index), base(_base), - disp(_disp), segment(_segment), - data(_data), - dataSize(_dataSize), addressSize(_addressSize) - {} - - std::string generateDisassembly(Addr pc, - const SymbolTable *symtab) const; - }; -}}; - -output decoder {{ - std::string LdStOp::generateDisassembly(Addr pc, - const SymbolTable *symtab) const - { - std::stringstream response; - - printMnemonic(response, instMnem, mnemonic); - printReg(response, data); - response << ", "; - printSegment(response, segment); - ccprintf(response, ":[%d*", scale); - printReg(response, index); - response << " + "; - printReg(response, base); - ccprintf(response, " + %#x]", disp); - return response.str(); - } -}}; - // LEA template def template MicroLeaExecute {{ @@ -180,7 +123,25 @@ def template MicroLoadExecute {{ %(ea_code)s; DPRINTF(X86, "%s : %s: The address is %#x\n", instMnem, mnemonic, EA); - fault = xc->read(EA, (%(mem_acc_type)s%(mem_acc_size)s_t&)Mem, 0); + unsigned flags = 0; + switch(dataSize) + { + case 1: + fault = xc->read(EA, (uint8_t&)Mem, flags); + break; + case 2: + fault = xc->read(EA, (uint16_t&)Mem, flags); + break; + case 4: + fault = xc->read(EA, (uint32_t&)Mem, flags); + break; + case 8: + fault = xc->read(EA, (uint64_t&)Mem, flags); + break; + default: + panic("Bad operand size!\n"); + } + if(fault == NoFault) { %(code)s; @@ -206,7 +167,24 @@ def template MicroLoadInitiateAcc {{ %(ea_code)s; DPRINTF(X86, "%s : %s: The address is %#x\n", instMnem, mnemonic, EA); - fault = xc->read(EA, (%(mem_acc_type)s%(mem_acc_size)s_t&)Mem, 0); + unsigned flags = 0; + switch(dataSize) + { + case 1: + fault = xc->read(EA, (uint8_t&)Mem, flags); + break; + case 2: + fault = xc->read(EA, (uint16_t&)Mem, flags); + break; + case 4: + fault = xc->read(EA, (uint32_t&)Mem, flags); + break; + case 8: + fault = xc->read(EA, (uint64_t&)Mem, flags); + break; + default: + panic("Bad operand size!\n"); + } return fault; } @@ -252,8 +230,25 @@ def template MicroStoreExecute {{ if(fault == NoFault) { - fault = xc->write((%(mem_acc_type)s%(mem_acc_size)s_t)Mem, - EA, 0, 0); + unsigned flags = 0; + uint64_t *res = 0; + switch(dataSize) + { + case 1: + fault = xc->write((uint8_t&)Mem, EA, flags, res); + break; + case 2: + fault = xc->write((uint16_t&)Mem, EA, flags, res); + break; + case 4: + fault = xc->write((uint32_t&)Mem, EA, flags, res); + break; + case 8: + fault = xc->write((uint64_t&)Mem, EA, flags, res); + break; + default: + panic("Bad operand size!\n"); + } } if(fault == NoFault) { @@ -280,8 +275,25 @@ def template MicroStoreInitiateAcc {{ if(fault == NoFault) { - fault = xc->write((%(mem_acc_type)s%(mem_acc_size)s_t)Mem, - EA, 0, 0); + unsigned flags = 0; + uint64_t *res = 0; + switch(dataSize) + { + case 1: + fault = xc->write((uint8_t&)Mem, EA, flags, res); + break; + case 2: + fault = xc->write((uint16_t&)Mem, EA, flags, res); + break; + case 4: + fault = xc->write((uint32_t&)Mem, EA, flags, res); + break; + case 8: + fault = xc->write((uint64_t&)Mem, EA, flags, res); + break; + default: + panic("Bad operand size!\n"); + } } if(fault == NoFault) { @@ -382,12 +394,12 @@ def template MicroLdStOpConstructor {{ let {{ class LdStOp(X86Microop): - def __init__(self, data, segment, addr, disp): + def __init__(self, data, segment, addr, disp, dataSize): self.data = data [self.scale, self.index, self.base] = addr self.disp = disp self.segment = segment - self.dataSize = "env.dataSize" + self.dataSize = dataSize self.addressSize = "env.addressSize" def getAllocator(self, *microFlags): @@ -424,7 +436,7 @@ let {{ name = mnemonic.lower() # Build up the all register version of this micro op - iop = InstObjParams(name, Name, 'LdStOp', + iop = InstObjParams(name, Name, 'X86ISA::LdStOp', {"code": code, "ea_code": calculateEA}) header_output += MicroLdStOpDeclare.subst(iop) decoder_output += MicroLdStOpConstructor.subst(iop) @@ -433,8 +445,10 @@ let {{ exec_output += MicroLoadCompleteAcc.subst(iop) class LoadOp(LdStOp): - def __init__(self, data, segment, addr, disp = 0): - super(LoadOp, self).__init__(data, segment, addr, disp) + def __init__(self, data, segment, addr, + disp = 0, dataSize="env.dataSize"): + super(LoadOp, self).__init__(data, segment, + addr, disp, dataSize) self.className = Name self.mnemonic = name @@ -451,7 +465,7 @@ let {{ name = mnemonic.lower() # Build up the all register version of this micro op - iop = InstObjParams(name, Name, 'LdStOp', + iop = InstObjParams(name, Name, 'X86ISA::LdStOp', {"code": code, "ea_code": calculateEA}) header_output += MicroLdStOpDeclare.subst(iop) decoder_output += MicroLdStOpConstructor.subst(iop) @@ -460,24 +474,28 @@ let {{ exec_output += MicroStoreCompleteAcc.subst(iop) class StoreOp(LdStOp): - def __init__(self, data, segment, addr, disp = 0): - super(LoadOp, self).__init__(data, segment, addr, disp) + def __init__(self, data, segment, addr, + disp = 0, dataSize="env.dataSize"): + super(StoreOp, self).__init__(data, segment, + addr, disp, dataSize) self.className = Name self.mnemonic = name microopClasses[name] = StoreOp - defineMicroLoadOp('St', 'Mem = Data;') + defineMicroStoreOp('St', 'Mem = Data;') - iop = InstObjParams("lea", "Lea", 'LdStOp', + iop = InstObjParams("lea", "Lea", 'X86ISA::LdStOp', {"code": "Data = merge(Data, EA, dataSize);", "ea_code": calculateEA}) header_output += MicroLeaDeclare.subst(iop) decoder_output += MicroLdStOpConstructor.subst(iop) exec_output += MicroLeaExecute.subst(iop) class LeaOp(LdStOp): - def __init__(self, data, segment, addr, disp = 0): - super(LeaOp, self).__init__(data, segment, addr, disp) + def __init__(self, data, segment, addr, + disp = 0, dataSize="env.dataSize"): + super(LeaOp, self).__init__(data, segment, + addr, disp, dataSize) self.className = "Lea" self.mnemonic = "lea" diff --git a/src/arch/x86/isa/microops/limmop.isa b/src/arch/x86/isa/microops/limmop.isa index 141d7523f..37180d7fa 100644 --- a/src/arch/x86/isa/microops/limmop.isa +++ b/src/arch/x86/isa/microops/limmop.isa @@ -72,11 +72,12 @@ def template MicroLimmOpExecute {{ }}; def template MicroLimmOpDeclare {{ - class %(class_name)s : public X86MicroopBase + class %(class_name)s : public X86ISA::X86MicroopBase { protected: const RegIndex dest; const uint64_t imm; + const uint8_t dataSize; void buildMe(); std::string generateDisassembly(Addr pc, @@ -86,11 +87,11 @@ def template MicroLimmOpDeclare {{ %(class_name)s(ExtMachInst _machInst, const char * instMnem, bool isMicro, bool isDelayed, bool isFirst, bool isLast, - RegIndex _dest, uint64_t _imm); + RegIndex _dest, uint64_t _imm, uint8_t _dataSize); %(class_name)s(ExtMachInst _machInst, const char * instMnem, - RegIndex _dest, uint64_t _imm); + RegIndex _dest, uint64_t _imm, uint8_t _dataSize); %(BasicExecDeclare)s }; @@ -103,7 +104,7 @@ def template MicroLimmOpDisassembly {{ std::stringstream response; printMnemonic(response, instMnem, mnemonic); - printReg(response, dest); + printReg(response, dest, dataSize); response << ", "; ccprintf(response, "%#x", imm); return response.str(); @@ -119,10 +120,10 @@ def template MicroLimmOpConstructor {{ inline %(class_name)s::%(class_name)s( ExtMachInst machInst, const char * instMnem, - RegIndex _dest, uint64_t _imm) : + RegIndex _dest, uint64_t _imm, uint8_t _dataSize) : %(base_class)s(machInst, "%(mnemonic)s", instMnem, false, false, false, false, %(op_class)s), - dest(_dest), imm(_imm) + dest(_dest), imm(_imm), dataSize(_dataSize) { buildMe(); } @@ -130,10 +131,10 @@ def template MicroLimmOpConstructor {{ inline %(class_name)s::%(class_name)s( ExtMachInst machInst, const char * instMnem, bool isMicro, bool isDelayed, bool isFirst, bool isLast, - RegIndex _dest, uint64_t _imm) : + RegIndex _dest, uint64_t _imm, uint8_t _dataSize) : %(base_class)s(machInst, "%(mnemonic)s", instMnem, isMicro, isDelayed, isFirst, isLast, %(op_class)s), - dest(_dest), imm(_imm) + dest(_dest), imm(_imm), dataSize(_dataSize) { buildMe(); } @@ -146,14 +147,16 @@ let {{ self.mnemonic = "limm" self.dest = dest self.imm = imm + self.dataSize = "env.dataSize" def getAllocator(self, *microFlags): allocator = '''new %(class_name)s(machInst, mnemonic - %(flags)s, %(dest)s, %(imm)s)''' % { + %(flags)s, %(dest)s, %(imm)s, %(dataSize)s)''' % { "class_name" : self.className, "mnemonic" : self.mnemonic, "flags" : self.microFlagsText(microFlags), - "dest" : self.dest, "imm" : self.imm } + "dest" : self.dest, "imm" : self.imm, + "dataSize" : self.dataSize} return allocator microopClasses["limm"] = LimmOp diff --git a/src/arch/x86/isa/microops/regop.isa b/src/arch/x86/isa/microops/regop.isa index 65b75fab8..dbbe11c90 100644 --- a/src/arch/x86/isa/microops/regop.isa +++ b/src/arch/x86/isa/microops/regop.isa @@ -59,100 +59,6 @@ // ////////////////////////////////////////////////////////////////////////// -output header {{ - /** - * Base classes for RegOps which provides a generateDisassembly method. - */ - class RegOp : public X86MicroopBase - { - protected: - const RegIndex src1; - const RegIndex src2; - const RegIndex dest; - const bool setStatus; - const uint8_t dataSize; - const uint8_t ext; - - // Constructor - RegOp(ExtMachInst _machInst, - const char *mnem, const char *_instMnem, - bool isMicro, bool isDelayed, - bool isFirst, bool isLast, - RegIndex _src1, RegIndex _src2, RegIndex _dest, - bool _setStatus, uint8_t _dataSize, uint8_t _ext, - OpClass __opClass) : - X86MicroopBase(_machInst, mnem, _instMnem, - isMicro, isDelayed, isFirst, isLast, - __opClass), - src1(_src1), src2(_src2), dest(_dest), - setStatus(_setStatus), dataSize(_dataSize), ext(_ext) - { - } - - std::string generateDisassembly(Addr pc, - const SymbolTable *symtab) const; - }; - - class RegOpImm : public X86MicroopBase - { - protected: - const RegIndex src1; - const uint8_t imm8; - const RegIndex dest; - const bool setStatus; - const uint8_t dataSize; - const uint8_t ext; - - // Constructor - RegOpImm(ExtMachInst _machInst, - const char * mnem, const char *_instMnem, - bool isMicro, bool isDelayed, - bool isFirst, bool isLast, - RegIndex _src1, uint8_t _imm8, RegIndex _dest, - bool _setStatus, uint8_t _dataSize, uint8_t _ext, - OpClass __opClass) : - X86MicroopBase(_machInst, mnem, _instMnem, - isMicro, isDelayed, isFirst, isLast, - __opClass), - src1(_src1), imm8(_imm8), dest(_dest), - setStatus(_setStatus), dataSize(_dataSize), ext(_ext) - { - } - - std::string generateDisassembly(Addr pc, - const SymbolTable *symtab) const; - }; -}}; - -output decoder {{ - std::string RegOp::generateDisassembly(Addr pc, - const SymbolTable *symtab) const - { - std::stringstream response; - - printMnemonic(response, instMnem, mnemonic); - printReg(response, dest); - response << ", "; - printReg(response, src1); - response << ", "; - printReg(response, src2); - return response.str(); - } - - std::string RegOpImm::generateDisassembly(Addr pc, - const SymbolTable *symtab) const - { - std::stringstream response; - - printMnemonic(response, instMnem, mnemonic); - printReg(response, dest); - response << ", "; - printReg(response, src1); - ccprintf(response, ", %#x", imm8); - return response.str(); - } -}}; - def template MicroRegOpExecute {{ Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, Trace::InstRecord *traceData) const @@ -161,8 +67,16 @@ def template MicroRegOpExecute {{ %(op_decl)s; %(op_rd)s; - %(code)s; - %(flag_code)s; + + if(%(cond_check)s) + { + %(code)s; + %(flag_code)s; + } + else + { + %(else_code)s; + } //Write the resulting state to the execution context if(fault == NoFault) @@ -181,8 +95,16 @@ def template MicroRegOpImmExecute {{ %(op_decl)s; %(op_rd)s; - %(code)s; - %(flag_code)s; + + if(%(cond_check)s) + { + %(code)s; + %(flag_code)s; + } + else + { + %(else_code)s; + } //Write the resulting state to the execution context if(fault == NoFault) @@ -204,12 +126,12 @@ def template MicroRegOpDeclare {{ const char * instMnem, bool isMicro, bool isDelayed, bool isFirst, bool isLast, RegIndex _src1, RegIndex _src2, RegIndex _dest, - bool _setStatus, uint8_t _dataSize, uint8_t _ext); + uint8_t _dataSize, uint16_t _ext); %(class_name)s(ExtMachInst _machInst, const char * instMnem, RegIndex _src1, RegIndex _src2, RegIndex _dest, - bool _setStatus, uint8_t _dataSize, uint8_t _ext); + uint8_t _dataSize, uint16_t _ext); %(BasicExecDeclare)s }; @@ -227,12 +149,12 @@ def template MicroRegOpImmDeclare {{ const char * instMnem, bool isMicro, bool isDelayed, bool isFirst, bool isLast, RegIndex _src1, uint8_t _imm8, RegIndex _dest, - bool _setStatus, uint8_t _dataSize, uint8_t _ext); + uint8_t _dataSize, uint16_t _ext); %(class_name)sImm(ExtMachInst _machInst, const char * instMnem, RegIndex _src1, uint8_t _imm8, RegIndex _dest, - bool _setStatus, uint8_t _dataSize, uint8_t _ext); + uint8_t _dataSize, uint16_t _ext); %(BasicExecDeclare)s }; @@ -248,10 +170,10 @@ def template MicroRegOpConstructor {{ inline %(class_name)s::%(class_name)s( ExtMachInst machInst, const char * instMnem, RegIndex _src1, RegIndex _src2, RegIndex _dest, - bool _setStatus, uint8_t _dataSize, uint8_t _ext) : + uint8_t _dataSize, uint16_t _ext) : %(base_class)s(machInst, "%(mnemonic)s", instMnem, false, false, false, false, - _src1, _src2, _dest, _setStatus, _dataSize, _ext, + _src1, _src2, _dest, _dataSize, _ext, %(op_class)s) { buildMe(); @@ -261,10 +183,10 @@ def template MicroRegOpConstructor {{ ExtMachInst machInst, const char * instMnem, bool isMicro, bool isDelayed, bool isFirst, bool isLast, RegIndex _src1, RegIndex _src2, RegIndex _dest, - bool _setStatus, uint8_t _dataSize, uint8_t _ext) : + uint8_t _dataSize, uint16_t _ext) : %(base_class)s(machInst, "%(mnemonic)s", instMnem, isMicro, isDelayed, isFirst, isLast, - _src1, _src2, _dest, _setStatus, _dataSize, _ext, + _src1, _src2, _dest, _dataSize, _ext, %(op_class)s) { buildMe(); @@ -281,10 +203,10 @@ def template MicroRegOpImmConstructor {{ inline %(class_name)sImm::%(class_name)sImm( ExtMachInst machInst, const char * instMnem, RegIndex _src1, uint8_t _imm8, RegIndex _dest, - bool _setStatus, uint8_t _dataSize, uint8_t _ext) : + uint8_t _dataSize, uint16_t _ext) : %(base_class)s(machInst, "%(mnemonic)s", instMnem, false, false, false, false, - _src1, _imm8, _dest, _setStatus, _dataSize, _ext, + _src1, _imm8, _dest, _dataSize, _ext, %(op_class)s) { buildMe(); @@ -294,10 +216,10 @@ def template MicroRegOpImmConstructor {{ ExtMachInst machInst, const char * instMnem, bool isMicro, bool isDelayed, bool isFirst, bool isLast, RegIndex _src1, uint8_t _imm8, RegIndex _dest, - bool _setStatus, uint8_t _dataSize, uint8_t _ext) : + uint8_t _dataSize, uint16_t _ext) : %(base_class)s(machInst, "%(mnemonic)s", instMnem, isMicro, isDelayed, isFirst, isLast, - _src1, _imm8, _dest, _setStatus, _dataSize, _ext, + _src1, _imm8, _dest, _dataSize, _ext, %(op_class)s) { buildMe(); @@ -305,46 +227,74 @@ def template MicroRegOpImmConstructor {{ }}; let {{ + class X86MicroMeta(type): + def __new__(mcls, name, bases, dict): + abstract = False + if "abstract" in dict: + abstract = dict['abstract'] + del dict['abstract'] + + cls = type.__new__(mcls, name, bases, dict) + if not abstract: + allClasses[name] = cls + return cls + + class XXX86Microop(object): + __metaclass__ = X86MicroMeta + abstract = True + class RegOp(X86Microop): - def __init__(self, dest, src1, src2, setStatus): + abstract = True + def __init__(self, dest, src1, src2, flags, dataSize): self.dest = dest self.src1 = src1 self.src2 = src2 - self.setStatus = setStatus - self.dataSize = "env.dataSize" - self.ext = 0 + self.flags = flags + self.dataSize = dataSize + if flags is None: + self.ext = 0 + else: + if not isinstance(flags, (list, tuple)): + raise Exception, "flags must be a list or tuple of flags" + self.ext = " | ".join(flags) + self.className += "Flags" def getAllocator(self, *microFlags): allocator = '''new %(class_name)s(machInst, mnemonic %(flags)s, %(src1)s, %(src2)s, %(dest)s, - %(setStatus)s, %(dataSize)s, %(ext)s)''' % { + %(dataSize)s, %(ext)s)''' % { "class_name" : self.className, "flags" : self.microFlagsText(microFlags), "src1" : self.src1, "src2" : self.src2, "dest" : self.dest, - "setStatus" : self.cppBool(self.setStatus), "dataSize" : self.dataSize, "ext" : self.ext} return allocator class RegOpImm(X86Microop): - def __init__(self, dest, src1, imm8, setStatus): + abstract = True + def __init__(self, dest, src1, imm8, flags, dataSize): self.dest = dest self.src1 = src1 self.imm8 = imm8 - self.setStatus = setStatus - self.dataSize = "env.dataSize" - self.ext = 0 + self.flags = flags + self.dataSize = dataSize + if flags is None: + self.ext = 0 + else: + if not isinstance(flags, (list, tuple)): + raise Exception, "flags must be a list or tuple of flags" + self.ext = " | ".join(flags) + self.className += "Flags" def getAllocator(self, *microFlags): allocator = '''new %(class_name)s(machInst, mnemonic %(flags)s, %(src1)s, %(imm8)s, %(dest)s, - %(setStatus)s, %(dataSize)s, %(ext)s)''' % { + %(dataSize)s, %(ext)s)''' % { "class_name" : self.className, "flags" : self.microFlagsText(microFlags), "src1" : self.src1, "imm8" : self.imm8, "dest" : self.dest, - "setStatus" : self.cppBool(self.setStatus), "dataSize" : self.dataSize, "ext" : self.ext} return allocator @@ -358,7 +308,8 @@ let {{ decoder_output = "" exec_output = "" - def setUpMicroRegOp(name, Name, base, code, child, flagCode): + # A function which builds the C++ classes that implement the microops + def setUpMicroRegOp(name, Name, base, code, flagCode = "", condCheck = "true", elseCode = ";"): global header_output global decoder_output global exec_output @@ -366,14 +317,21 @@ let {{ iop = InstObjParams(name, Name, base, {"code" : code, - "flag_code" : flagCode}) + "flag_code" : flagCode, + "cond_check" : condCheck, + "else_code" : elseCode}) header_output += MicroRegOpDeclare.subst(iop) decoder_output += MicroRegOpConstructor.subst(iop) exec_output += MicroRegOpExecute.subst(iop) - microopClasses[name] = child - def defineMicroRegOp(mnemonic, code, flagCode): + checkCCFlagBits = "checkCondition(ccFlagBits)" + genCCFlagBits = "ccFlagBits = genFlags(ccFlagBits, ext, DestReg, SrcReg1, %s);" + + + # This creates a python representations of a microop which are a cross + # product of reg/immediate and flag/no flag versions. + def defineMicroRegOp(mnemonic, code, subtract = False, cc=False, elseCode=";"): Name = mnemonic name = mnemonic.lower() @@ -384,36 +342,47 @@ let {{ regCode = matcher.sub("SrcReg2", code) immCode = matcher.sub("imm8", code) - # Build the all register version of this micro op + if subtract: + secondSrc = "-op2, true" + else: + secondSrc = "op2" + + if not cc: + flagCode = genCCFlagBits % secondSrc + condCode = "true" + else: + flagCode = "" + condCode = checkCCFlagBits + + regFlagCode = matcher.sub("SrcReg2", flagCode) + immFlagCode = matcher.sub("imm8", flagCode) + class RegOpChild(RegOp): - def __init__(self, dest, src1, src2, setStatus=False): - super(RegOpChild, self).__init__(dest, src1, src2, setStatus) - self.className = Name - self.mnemonic = name + mnemonic = name + className = Name + def __init__(self, dest, src1, src2, flags=None, dataSize="env.dataSize"): + super(RegOpChild, self).__init__(dest, src1, src2, flags, dataSize) + + microopClasses[name] = RegOpChild - setUpMicroRegOp(name, Name, "RegOp", regCode, RegOpChild, flagCode); + setUpMicroRegOp(name, Name, "X86ISA::RegOp", regCode); + setUpMicroRegOp(name, Name + "Flags", "X86ISA::RegOp", regCode, + flagCode = regFlagCode, condCheck = condCode, elseCode = elseCode); - # Build the immediate version of this micro op class RegOpChildImm(RegOpImm): - def __init__(self, dest, src1, src2, setStatus=False): - super(RegOpChildImm, self).__init__(dest, src1, src2, setStatus) - self.className = Name + "Imm" - self.mnemonic = name + "i" - - setUpMicroRegOp(name + "i", Name + "Imm", "RegOpImm", immCode, RegOpChildImm, flagCode); - - defineMicroRegOp('Add', 'DestReg = merge(DestReg, SrcReg1 + op2, dataSize)', "") #Needs to set OF,CF,SF - defineMicroRegOp('Or', 'DestReg = merge(DestReg, SrcReg1 | op2, dataSize)', "") - defineMicroRegOp('Adc', 'DestReg = merge(DestReg, SrcReg1 + op2, dataSize)', "") #Needs to add in CF, set OF,CF,SF - defineMicroRegOp('Sbb', 'DestReg = merge(DestReg, SrcReg1 - op2, dataSize)', "") #Needs to subtract CF, set OF,CF,SF - defineMicroRegOp('And', 'DestReg = merge(DestReg, SrcReg1 & op2, dataSize)', "") - defineMicroRegOp('Sub', 'DestReg = merge(DestReg, SrcReg1 - op2, dataSize)', "") #Needs to set OF,CF,SF - defineMicroRegOp('Xor', 'DestReg = merge(DestReg, SrcReg1 ^ op2, dataSize)', "") - defineMicroRegOp('Cmp', 'DestReg = merge(DestReg, DestReg - op2, dataSize)', "") #Needs to set OF,CF,SF and not DestReg - defineMicroRegOp('Mov', 'DestReg = merge(SrcReg1, op2, dataSize)', "") + mnemonic = name + 'i' + className = Name + 'Imm' + def __init__(self, dest, src1, src2, flags=None, dataSize="env.dataSize"): + super(RegOpChildImm, self).__init__(dest, src1, src2, flags, dataSize) + + microopClasses[name + 'i'] = RegOpChildImm + + setUpMicroRegOp(name + "i", Name + "Imm", "X86ISA::RegOpImm", immCode); + setUpMicroRegOp(name + "i", Name + "ImmFlags", "X86ISA::RegOpImm", immCode, + flagCode = immFlagCode, condCheck = condCode, elseCode = elseCode); # This has it's own function because Wr ops have implicit destinations - def defineMicroRegOpWr(mnemonic, code): + def defineMicroRegOpWr(mnemonic, code, elseCode=";"): Name = mnemonic name = mnemonic.lower() @@ -424,25 +393,29 @@ let {{ regCode = matcher.sub("SrcReg2", code) immCode = matcher.sub("imm8", code) - # Build the all register version of this micro op class RegOpChild(RegOp): - def __init__(self, src1, src2): - super(RegOpChild, self).__init__("NUM_INTREGS", src1, src2, False) - self.className = Name - self.mnemonic = name + mnemonic = name + className = Name + def __init__(self, src1, src2, flags=None, dataSize="env.dataSize"): + super(RegOpChild, self).__init__("NUM_INTREGS", src1, src2, flags, dataSize) + + microopClasses[name] = RegOpChild - setUpMicroRegOp(name, Name, "RegOp", regCode, RegOpChild, ""); + setUpMicroRegOp(name, Name, "X86ISA::RegOp", regCode); + setUpMicroRegOp(name, Name + "Flags", "X86ISA::RegOp", regCode, + condCheck = checkCCFlagBits, elseCode = elseCode); - # Build the immediate version of this micro op class RegOpChildImm(RegOpImm): - def __init__(self, src1, src2): - super(RegOpChildImm, self).__init__("NUM_INTREGS", src1, src2, False) - self.className = Name + "Imm" - self.mnemonic = name + "i" + mnemonic = name + 'i' + className = Name + 'Imm' + def __init__(self, src1, src2, flags=None, dataSize="env.dataSize"): + super(RegOpChildImm, self).__init__("NUM_INTREGS", src1, src2, flags, dataSize) - setUpMicroRegOp(name + "i", Name + "Imm", "RegOpImm", immCode, RegOpChildImm, ""); + microopClasses[name + 'i'] = RegOpChildImm - defineMicroRegOpWr('Wrip', 'RIP = SrcReg1 + op2') + setUpMicroRegOp(name + 'i', Name + "Imm", "X86ISA::RegOpImm", immCode); + setUpMicroRegOp(name + 'i', Name + "ImmFlags", "X86ISA::RegOpImm", immCode, + condCheck = checkCCFlagBits, elseCode = elseCode); # This has it's own function because Rd ops don't always have two parameters def defineMicroRegOpRd(mnemonic, code): @@ -450,30 +423,136 @@ let {{ name = mnemonic.lower() class RegOpChild(RegOp): - def __init__(self, dest, src1 = "NUM_INTREGS"): - super(RegOpChild, self).__init__(dest, src1, "NUM_INTREGS", False) + def __init__(self, dest, src1 = "NUM_INTREGS", dataSize="env.dataSize"): + super(RegOpChild, self).__init__(dest, src1, "NUM_INTREGS", None, dataSize) self.className = Name self.mnemonic = name - setUpMicroRegOp(name, Name, "RegOp", code, RegOpChild, ""); + microopClasses[name] = RegOpChild - defineMicroRegOpRd('Rdip', 'DestReg = RIP') + setUpMicroRegOp(name, Name, "X86ISA::RegOp", code); def defineMicroRegOpImm(mnemonic, code): Name = mnemonic name = mnemonic.lower() class RegOpChild(RegOpImm): - def __init__(self, dest, src1, src2): - super(RegOpChild, self).__init__(dest, src1, src2, False) + def __init__(self, dest, src1, src2, dataSize="env.dataSize"): + super(RegOpChild, self).__init__(dest, src1, src2, None, dataSize) self.className = Name self.mnemonic = name - setUpMicroRegOp(name, Name, "RegOpImm", code, RegOpChild, ""); + microopClasses[name] = RegOpChild + + 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', ''' + uint8_t shiftAmt = + (op2 & ((dataSize == 8) ? mask(4) : mask(3))); + if(shiftAmt) + { + CCFlagBits flags = ccFlagBits; + uint64_t top = flags.CF << (dataSize * 8 - shiftAmt); + if(shiftAmt > 1) + top |= SrcReg1 << (dataSize * 8 - shiftAmt - 1); + uint64_t bottom = bits(SrcReg1, dataSize * 8, shiftAmt); + DestReg = merge(DestReg, top | bottom, dataSize); + } + else + DestReg = DestReg; + ''') + 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', ''' + uint8_t shiftAmt = + (op2 & ((dataSize == 8) ? mask(4) : mask(3))); + if(shiftAmt) + { + CCFlagBits flags = ccFlagBits; + uint64_t top = SrcReg1 << shiftAmt; + uint64_t bottom = flags.CF << (shiftAmt - 1); + if(shiftAmt > 1) + bottom |= + bits(SrcReg1, dataSize * 8 - 1, + dataSize * 8 - shiftAmt + 1); + DestReg = merge(DestReg, top | bottom, dataSize); + } + else + DestReg = DestReg; + ''') + + 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); val = sign_bit ? (val | ~mask(imm8)) : val; DestReg = merge(DestReg, val, dataSize);''') + + defineMicroRegOpImm('Zext', 'DestReg = bits(SrcReg1, imm8-1, 0);') }}; diff --git a/src/arch/x86/isa/microops/specop.isa b/src/arch/x86/isa/microops/specop.isa index b56223390..5c9e8dda9 100644 --- a/src/arch/x86/isa/microops/specop.isa +++ b/src/arch/x86/isa/microops/specop.isa @@ -60,7 +60,7 @@ ////////////////////////////////////////////////////////////////////////// output header {{ - class MicroFault : public X86MicroopBase + class MicroFault : public X86ISA::X86MicroopBase { protected: Fault fault; @@ -75,6 +75,9 @@ output header {{ Fault _fault); %(BasicExecDeclare)s + + std::string generateDisassembly(Addr pc, + const SymbolTable *symtab) const; }; }}; @@ -106,6 +109,22 @@ output decoder {{ } }}; +output decoder {{ + std::string MicroFault::generateDisassembly(Addr pc, + const SymbolTable *symtab) const + { + std::stringstream response; + + printMnemonic(response, instMnem, mnemonic); + if(fault) + response << fault->name(); + else + response << "No Fault"; + + return response.str(); + } +}}; + let {{ class Fault(X86Microop): def __init__(self, fault): diff --git a/src/arch/x86/isa/operands.isa b/src/arch/x86/isa/operands.isa index b2ac17d66..406c74a1f 100644 --- a/src/arch/x86/isa/operands.isa +++ b/src/arch/x86/isa/operands.isa @@ -102,6 +102,8 @@ def operands {{ 'Base': ('IntReg', 'uqw', 'base', 'IsInteger', 4), 'Index': ('IntReg', 'uqw', 'index', 'IsInteger', 5), 'Data': ('IntReg', 'uqw', 'data', 'IsInteger', 6), + 'rax': ('IntReg', 'uqw', 'INTREG_RAX', 'IsInteger', 7), 'RIP': ('NPC', 'uqw', None, (None, None, 'IsControl'), 10), + 'ccFlagBits': ('IntReg', 'uqw', 'NUM_INTREGS + NumMicroIntRegs', None, 20), 'Mem': ('Mem', 'uqw', None, ('IsMemRef', 'IsLoad', 'IsStore'), 100) }}; diff --git a/src/arch/x86/isa/outputblock.isa b/src/arch/x86/isa/outputblock.isa new file mode 100644 index 000000000..342d6ac4b --- /dev/null +++ b/src/arch/x86/isa/outputblock.isa @@ -0,0 +1,91 @@ +// Copyright (c) 2007 The Hewlett-Packard Development Company +// All rights reserved. +// +// Redistribution and use of this software in source and binary forms, +// with or without modification, are permitted provided that the +// following conditions are met: +// +// The software must be used only for Non-Commercial Use which means any +// use which is NOT directed to receiving any direct monetary +// compensation for, or commercial advantage from such use. Illustrative +// examples of non-commercial use are academic research, personal study, +// teaching, education and corporate research & development. +// Illustrative examples of commercial use are distributing products for +// commercial advantage and providing services using the software for +// commercial advantage. +// +// If you wish to use this software or functionality therein that may be +// covered by patents for commercial use, please contact: +// Director of Intellectual Property Licensing +// Office of Strategy and Technology +// Hewlett-Packard Company +// 1501 Page Mill Road +// Palo Alto, California 94304 +// +// Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. Redistributions +// in binary form must reproduce the above copyright notice, this list of +// conditions and the following disclaimer in the documentation and/or +// other materials provided with the distribution. Neither the name of +// the COPYRIGHT HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. No right of +// sublicense is granted herewith. Derivatives of the software and +// output created using the software may be prepared, but only for +// Non-Commercial Uses. Derivatives of the software may be shared with +// others provided: (i) the others agree to abide by the list of +// conditions herein which includes the Non-Commercial Use restrictions; +// and (ii) such Derivatives of the software include the above copyright +// notice to acknowledge the contribution from this software where +// applicable, this list of conditions and the disclaimer below. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Authors: Gabe Black + +//////////////////////////////////////////////////////////////////// +// +// Output blocks which group together code generated by the parser. +// + +let {{ + # This class will help make dealing with output a little less verbose + class OutputBlocks(object): + def __init__(self, header_output="", + decoder_output="", + decode_block="", + exec_output=""): + self.header_output = header_output + self.decoder_output = decoder_output + self.decode_block = decode_block + self.exec_output = exec_output + + def append(self, blocks): + if isinstance(blocks, list) or isinstance(blocks, tuple): + assert(len(blocks) == 4) + self.header_output += blocks[0] + self.decoder_output += blocks[1] + self.decode_block += blocks[2] + self.exec_output += blocks[3] + else: + self.header_output += blocks.header_output + self.decoder_output += blocks.decoder_output + self.decode_block += blocks.decode_block + self.exec_output += blocks.exec_output + + def makeList(self): + return (self.header_output, + self.decoder_output, + self.decode_block, + self.exec_output) +}}; diff --git a/src/arch/x86/isa/specialize.isa b/src/arch/x86/isa/specialize.isa index 3183f32ba..5165ea206 100644 --- a/src/arch/x86/isa/specialize.isa +++ b/src/arch/x86/isa/specialize.isa @@ -118,6 +118,7 @@ let {{ ModRMRegIndex = "(MODRM_REG | (REX_R << 3))" ModRMRMIndex = "(MODRM_RM | (REX_B << 3))" + InstRegIndex = "(OPCODE_OP_BOTTOM3 | (REX_B << 3))" # This function specializes the given piece of code to use a particular # set of argument types described by "opTypes". @@ -143,6 +144,10 @@ let {{ else: print "Didn't recognize fixed register size %s!" % opType.rsize Name += "_R" + elif opType.tag == "B": + # This refers to registers whose index is encoded as part of the opcode + Name += "_R" + env.addReg(InstRegIndex) elif opType.tag == "M": # This refers to memory. The macroop constructor sets up modrm # addressing. Non memory modrm settings should cause an error. |