diff options
Diffstat (limited to 'src/arch/x86/isa')
54 files changed, 2727 insertions, 983 deletions
diff --git a/src/arch/x86/isa/decoder/one_byte_opcodes.isa b/src/arch/x86/isa/decoder/one_byte_opcodes.isa index 332ae1641..817986232 100644 --- a/src/arch/x86/isa/decoder/one_byte_opcodes.isa +++ b/src/arch/x86/isa/decoder/one_byte_opcodes.isa @@ -1,4 +1,4 @@ -// Copyright (c) 2007 The Hewlett-Packard Development Company +// Copyright (c) 2007-2008 The Hewlett-Packard Development Company // All rights reserved. // // Redistribution and use of this software in source and binary forms, @@ -418,12 +418,27 @@ default: Inst::RET_FAR(); } 0x4: int3(); +#if FULL_SYSTEM 0x5: int_Ib(); +#else + // Really only the LSB matters, but the predecoder will sign + // extend it, and there's no easy way to specify only checking + // the first byte. + 0x5: decode IMMEDIATE { + 0xffffffffffffff80: + SyscallInst::int80('xc->syscall(Rax)', IsSyscall); + default: int_Ib(); + } +#endif 0x6: decode MODE_SUBMODE { 0x0: Inst::UD2(); default: into(); } - 0x7: iret(); + 0x7: decode MODE_SUBMODE { + 0x4: Inst::IRET_REAL(); + 0x3: Inst::IRET_VIRT(); + default: Inst::IRET_PROT(); + } } } 0x1A: decode OPCODE_OP_BOTTOM3 { @@ -549,8 +564,8 @@ 0x1F: decode OPCODE_OP_BOTTOM3 { 0x0: CLC(); 0x1: STC(); - 0x2: WarnUnimpl::cli(); - 0x3: WarnUnimpl::sti(); + 0x2: CLI(); + 0x3: STI(); 0x4: CLD(); 0x5: STD(); //0x6: group4(); diff --git a/src/arch/x86/isa/decoder/two_byte_opcodes.isa b/src/arch/x86/isa/decoder/two_byte_opcodes.isa index 8135a1fdb..1ee62142a 100644 --- a/src/arch/x86/isa/decoder/two_byte_opcodes.isa +++ b/src/arch/x86/isa/decoder/two_byte_opcodes.isa @@ -93,8 +93,8 @@ 0x00: decode MODRM_REG { 0x0: sldt_Mw_or_Rv(); 0x1: str_Mw_or_Rv(); - 0x2: lldt_Mw_or_Rv(); - 0x3: ltr_Mw_or_Rv(); + 0x2: Inst::LLDT(Ew); + 0x3: Inst::LTR(Ew); 0x4: verr_Mw_or_Rv(); 0x5: verw_Mw_or_Rv(); //0x6: jmpe_Ev(); // IA-64 @@ -128,7 +128,7 @@ 0x4: smsw_Rv(); 0x6: lmsw_Rv(); 0x7: decode MODRM_RM { - 0x0: swapgs(); + 0x0: Inst::SWAPGS(); 0x1: rdtscp(); default: Inst::UD2(); } @@ -163,17 +163,117 @@ } 0x02: lar_Gv_Ew(); 0x03: lsl_Gv_Ew(); - //sandpile.org doesn't seem to know what this is... ? - 0x04: loadall_or_reset_or_hang(); + // sandpile.org doesn't seem to know what this is...? We'll + // use it for pseudo instructions. We've got 16 bits of space + // to play with so there can be quite a few pseudo + // instructions. + //0x04: loadall_or_reset_or_hang(); + 0x4: decode IMMEDIATE { + format BasicOperate { #if FULL_SYSTEM - 0x05: syscall(); + 0x00: m5arm({{ + PseudoInst::arm(xc->tcBase()); + }}, IsNonSpeculative); + 0x01: m5quiesce({{ + PseudoInst::quiesce(xc->tcBase()); + }}, IsNonSpeculative); + 0x02: m5quiesceNs({{ + PseudoInst::quiesceNs(xc->tcBase(), Rdi); + }}, IsNonSpeculative); + 0x03: m5quiesceCycle({{ + PseudoInst::quiesceCycles(xc->tcBase(), Rdi); + }}, IsNonSpeculative); + 0x04: m5quiesceTime({{ + Rax = PseudoInst::quiesceTime(xc->tcBase()); + }}, IsNonSpeculative); +#endif + 0x07: m5rpns({{ + Rax = PseudoInst::rpns(xc->tcBase()); + }}, IsNonSpeculative); + 0x21: m5exit({{ + PseudoInst::m5exit(xc->tcBase(), Rdi); + }}, IsNonSpeculative); +#if FULL_SYSTEM + 0x30: m5initparam({{ + Rax = xc->tcBase()->getCpuPtr()-> + system->init_param; + }}, IsNonSpeculative); + 0x31: m5loadsymbol({{ + PseudoInst::loadsymbol(xc->tcBase()); + }}, IsNonSpeculative); +#endif + 0x40: m5resetstats({{ + PseudoInst::resetstats(xc->tcBase(), Rdi, Rsi); + }}, IsNonSpeculative); + 0x41: m5dumpstats({{ + PseudoInst::dumpstats(xc->tcBase(), Rdi, Rsi); + }}, IsNonSpeculative); + 0x42: m5dumpresetstats({{ + PseudoInst::dumpresetstats(xc->tcBase(), Rdi, Rsi); + }}, IsNonSpeculative); + 0x43: m5checkpoint({{ + PseudoInst::m5checkpoint(xc->tcBase(), Rdi, Rsi); + }}, IsNonSpeculative); +#if FULL_SYSTEM + 0x50: m5readfile({{ + Rax = PseudoInst::readfile( + xc->tcBase(), Rdi, Rsi, Rdx); + }}, IsNonSpeculative); +#endif + 0x51: m5debugbreak({{ + PseudoInst::debugbreak(xc->tcBase()); + }}, IsNonSpeculative); + 0x52: m5switchcpu({{ + PseudoInst::switchcpu(xc->tcBase()); + }}, IsNonSpeculative); +#if FULL_SYSTEM + 0x53: m5addsymbol({{ + PseudoInst::addsymbol(xc->tcBase(), Rdi, Rsi); + }}, IsNonSpeculative); +#endif + 0x54: m5panic({{ + panic("M5 panic instruction called at pc=%#x.\n", + xc->readPC()); + }}, IsNonSpeculative); + 0x55: m5reserved1({{ + warn("M5 reserved opcode 1 ignored.\n"); + }}, IsNonSpeculative); + 0x56: m5reserved2({{ + warn("M5 reserved opcode 2 ignored.\n"); + }}, IsNonSpeculative); + 0x57: m5reserved3({{ + warn("M5 reserved opcode 3 ignored.\n"); + }}, IsNonSpeculative); + 0x58: m5reserved4({{ + warn("M5 reserved opcode 4 ignored.\n"); + }}, IsNonSpeculative); + 0x59: m5reserved5({{ + warn("M5 reserved opcode 5 ignored.\n"); + }}, IsNonSpeculative); + default: Inst::UD2(); + } + } +#if FULL_SYSTEM + 0x05: decode MODE_MODE { + 0x0: decode MODE_SUBMODE { + 0x0: Inst::SYSCALL_64(); + 0x1: Inst::SYSCALL_COMPAT(); + } + 0x1: Inst::SYSCALL_LEGACY(); + } #else - 0x05: SyscallInst::syscall('xc->syscall(rax)', IsSyscall); + 0x05: SyscallInst::syscall('xc->syscall(Rax)', IsSyscall); #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(); + 0x06: Inst::CLTS(); + 0x07: decode MODE_SUBMODE { + 0x0: decode OPSIZE { + // Return to 64 bit mode. + 0x8: Inst::SYSRET_TO_64(); + // Return to compatibility mode. + default: Inst::SYSRET_TO_COMPAT(); + } + default: Inst::SYSRET_NON_64(); + } } 0x01: decode OPCODE_OP_BOTTOM3 { 0x0: invd(); @@ -181,9 +281,9 @@ 0x2: Inst::UD2(); 0x3: Inst::UD2(); 0x4: Inst::UD2(); - 0x5: threednow(); - 0x6: threednow(); - 0x7: threednow(); + 0x5: Inst::PREFETCH(Mb); + 0x6: FailUnimpl::femms(); + 0x7: FailUnimpl::threednow(); } 0x02: decode LEGACY_DECODEVAL { // no prefix @@ -235,7 +335,7 @@ //group17(); 0x0: decode MODRM_REG { 0x0: prefetch_nta(); - 0x1: prefetch_t0(); + 0x1: Inst::PREFETCH_T0(Mb); 0x2: prefetch_t1(); 0x3: prefetch_t2(); default: Inst::HINT_NOP(); @@ -252,9 +352,9 @@ // no prefix 0x0: decode OPCODE_OP_BOTTOM3 { 0x0: Inst::MOV(Rd,Cd); - 0x1: mov_Rd_Dd(); + 0x1: Inst::MOV(Rd,Dd); 0x2: Inst::MOV(Cd,Rd); - 0x3: mov_Dd_Rd(); + 0x3: Inst::MOV(Dd,Rd); 0x4: mov_Rd_Td(); 0x6: mov_Td_Rd(); default: Inst::UD2(); @@ -317,10 +417,14 @@ } 0x06: decode OPCODE_OP_BOTTOM3 { 0x0: Inst::WRMSR(); - 0x1: rdtsc(); + 0x1: Inst::RDTSC(); 0x2: Inst::RDMSR(); 0x3: rdpmc(); +#if FULL_SYSTEM 0x4: sysenter(); +#else + 0x4: SyscallInst::sysenter('xc->syscall(Rax)', IsSyscall); +#endif 0x5: sysexit(); 0x6: Inst::UD2(); 0x7: getsec(); @@ -707,7 +811,14 @@ 0x14: decode OPCODE_OP_BOTTOM3 { 0x0: push_fs(); 0x1: pop_fs(); - 0x2: Inst::CPUID(rAd); + 0x2: CPUIDInst::CPUID({{ + CpuidResult result; + success = doCpuid(xc->tcBase(), Rax, result); + Rax = result.rax; + Rbx = result.rbx; + Rcx = result.rcx; + Rdx = result.rdx; + }}); 0x3: Inst::BT(Ev,Gv); 0x4: shld_Ev_Gv_Ib(); 0x5: shld_Ev_Gv_rCl(); @@ -719,20 +830,28 @@ 0x1: pop_gs(); 0x2: rsm_smm(); 0x3: Inst::BTS(Ev,Gv); - 0x4: shrd_Ev_Gv_Ib(); + 0x4: Inst::SHRD(Ev,Gv,Ib); 0x5: shrd_Ev_Gv_rCl(); //0x6: group16(); - 0x6: decode MODRM_MOD { - 0x3: decode MODRM_REG { - 0x5: lfence(); - 0x6: mfence(); - 0x7: sfence(); + 0x6: decode MODRM_REG { + 0x0: fxsave(); + 0x1: fxrstor(); + 0x2: ldmxcsr(); + 0x3: stmxcsr(); + 0x4: Inst::UD2(); + 0x5: decode MODRM_MOD { + 0x3: BasicOperate::LFENCE( + {{/*Nothing*/}}, IsReadBarrier); default: Inst::UD2(); } - default: decode MODRM_REG { - 0x0: fxsave(); - 0x1: fxrstor(); - 0x7: clflush(); + 0x6: decode MODRM_MOD { + 0x3: BasicOperate::MFENCE( + {{/*Nothing*/}}, IsMemBarrier); + default: Inst::UD2(); + } + 0x7: decode MODRM_MOD { + 0x3: BasicOperate::SFENCE( + {{/*Nothing*/}}, IsWriteBarrier); default: Inst::UD2(); } } @@ -775,8 +894,8 @@ 0x7: Inst::MOVSX_W(Gv,Ev); } 0x18: decode OPCODE_OP_BOTTOM3 { - 0x0: xadd_Eb_Gb(); - 0x1: xadd_Ev_Gv(); + 0x0: Inst::XADD(Eb,Gb); + 0x1: Inst::XADD(Ev,Gv); //0x7: group9(); 0x7: decode MODRM_REG { 0x1: cmpxchg_Mq(); @@ -820,7 +939,11 @@ default: Inst::UD2(); } } - 0x19: bswap_B(); + 0x19: decode OPSIZE { + 4: Inst::BSWAP_D(Bd); + 8: Inst::BSWAP_Q(Bq); + default: Inst::UD2(); + } 0x1A: decode LEGACY_DECODEVAL { // no prefix 0x0: decode OPCODE_OP_BOTTOM3 { diff --git a/src/arch/x86/isa/formats/basic.isa b/src/arch/x86/isa/formats/basic.isa index 7aea7085f..b96bae238 100644 --- a/src/arch/x86/isa/formats/basic.isa +++ b/src/arch/x86/isa/formats/basic.isa @@ -147,3 +147,11 @@ def template BasicDecode {{ def template BasicDecodeWithMnemonic {{ return new %(class_name)s("%(mnemonic)s", machInst); }}; + +def format BasicOperate(code, *flags) {{ + iop = InstObjParams(name, Name, 'X86ISA::X86StaticInst', code, flags) + header_output = BasicDeclare.subst(iop) + decoder_output = BasicConstructor.subst(iop) + decode_block = BasicDecode.subst(iop) + exec_output = BasicExecute.subst(iop) +}}; diff --git a/src/arch/x86/isa/formats/cpuid.isa b/src/arch/x86/isa/formats/cpuid.isa new file mode 100644 index 000000000..204270556 --- /dev/null +++ b/src/arch/x86/isa/formats/cpuid.isa @@ -0,0 +1,110 @@ +// Copyright (c) 2008 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 header {{ + class CPUIDInst : public X86ISA::X86StaticInst + { + public: + static const RegIndex foldOBit = 0; + /// Constructor + CPUIDInst(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 CPUIDInst::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 CPUIDExecute {{ + Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + // If the CPUID instruction used a valid function number, this will + // be set to true. Otherwise, the instruction does nothing. + bool success; + %(op_decl)s; + %(op_rd)s; + %(code)s; + if (success) { + %(op_wb)s; + } + return NoFault; + } +}}; + +def format CPUIDInst(code, *opt_flags) {{ + iop = InstObjParams(name, Name, 'CPUIDInst', code, opt_flags) + header_output = BasicDeclare.subst(iop) + decoder_output = BasicConstructor.subst(iop) + decode_block = BasicDecode.subst(iop) + exec_output = CPUIDExecute.subst(iop) +}}; + diff --git a/src/arch/x86/isa/formats/formats.isa b/src/arch/x86/isa/formats/formats.isa index 6906413c0..81179ab45 100644 --- a/src/arch/x86/isa/formats/formats.isa +++ b/src/arch/x86/isa/formats/formats.isa @@ -85,6 +85,9 @@ //Templates from this format are used later ##include "basic.isa" +//Include a format to generate a CPUID instruction. +##include "cpuid.isa" + //Include the "unknown" format ##include "unknown.isa" diff --git a/src/arch/x86/isa/includes.isa b/src/arch/x86/isa/includes.isa index 6724ea9b0..8626f117a 100644 --- a/src/arch/x86/isa/includes.isa +++ b/src/arch/x86/isa/includes.isa @@ -26,7 +26,7 @@ // // Authors: Gabe Black -// Copyright (c) 2007 The Hewlett-Packard Development Company +// Copyright (c) 2007-2008 The Hewlett-Packard Development Company // All rights reserved. // // Redistribution and use of this software in source and binary forms, @@ -97,6 +97,7 @@ output header {{ #include <iostream> #include "arch/x86/emulenv.hh" +#include "arch/x86/insts/macroop.hh" #include "arch/x86/insts/microfpop.hh" #include "arch/x86/insts/microldstop.hh" #include "arch/x86/insts/microregop.hh" @@ -113,10 +114,13 @@ output header {{ output decoder {{ #include "arch/x86/faults.hh" #include "arch/x86/floatregs.hh" +#include "arch/x86/microcode_rom.hh" #include "arch/x86/miscregs.hh" #include "arch/x86/segmentregs.hh" +#include "arch/x86/tlb.hh" #include "base/cprintf.hh" #include "base/loader/symtab.hh" +#include "base/misc.hh" #include "cpu/thread_context.hh" // for Jump::branchTarget() #include "mem/packet.hh" @@ -144,6 +148,7 @@ output exec {{ #include <limits> #include <cmath> +#include "arch/x86/cpuid.hh" #include "arch/x86/miscregs.hh" #include "arch/x86/tlb.hh" #include "base/bigint.hh" @@ -152,6 +157,8 @@ output exec {{ #include "sim/sim_exit.hh" #include "mem/packet.hh" #include "mem/packet_access.hh" +#include "mem/request.hh" +#include "sim/pseudo_inst.hh" using namespace X86ISA; using namespace std; diff --git a/src/arch/x86/isa/insts/__init__.py b/src/arch/x86/isa/insts/__init__.py index 0ef617a87..d7a8bde19 100644 --- a/src/arch/x86/isa/insts/__init__.py +++ b/src/arch/x86/isa/insts/__init__.py @@ -53,7 +53,8 @@ # # Authors: Gabe Black -categories = ["general_purpose", +categories = ["romutil", + "general_purpose", "simd128", "simd64", "system", diff --git a/src/arch/x86/isa/insts/general_purpose/__init__.py b/src/arch/x86/isa/insts/general_purpose/__init__.py index 4f77cb233..23f955f08 100644 --- a/src/arch/x86/isa/insts/general_purpose/__init__.py +++ b/src/arch/x86/isa/insts/general_purpose/__init__.py @@ -65,7 +65,6 @@ categories = ["arithmetic", "load_segment_registers", "logical", "no_operation", - "processor_information", "rotate_and_shift", "semaphores", "string", diff --git a/src/arch/x86/isa/insts/general_purpose/arithmetic/multiply_and_divide.py b/src/arch/x86/isa/insts/general_purpose/arithmetic/multiply_and_divide.py index a9b53acac..19d1c7789 100644 --- a/src/arch/x86/isa/insts/general_purpose/arithmetic/multiply_and_divide.py +++ b/src/arch/x86/isa/insts/general_purpose/arithmetic/multiply_and_divide.py @@ -246,7 +246,7 @@ def macroop DIV_B_R divLoopTop: div2 t1, rax, t1, dataSize=1 div2 t1, rax, t1, flags=(EZF,), dataSize=1 - bri t0, label("divLoopTop"), flags=(nCEZF,) + br label("divLoopTop"), flags=(nCEZF,) #Unload the answer divq rax, dataSize=1 @@ -269,7 +269,7 @@ def macroop DIV_B_M divLoopTop: div2 t1, rax, t1, dataSize=1 div2 t1, rax, t1, flags=(EZF,), dataSize=1 - bri t0, label("divLoopTop"), flags=(nCEZF,) + br label("divLoopTop"), flags=(nCEZF,) #Unload the answer divq rax, dataSize=1 @@ -293,7 +293,7 @@ def macroop DIV_B_P divLoopTop: div2 t1, rax, t1, dataSize=1 div2 t1, rax, t1, flags=(EZF,), dataSize=1 - bri t0, label("divLoopTop"), flags=(nCEZF,) + br label("divLoopTop"), flags=(nCEZF,) #Unload the answer divq rax, dataSize=1 @@ -321,7 +321,7 @@ divLoopTop: div2 t1, rax, t1 div2 t1, rax, t1 div2 t1, rax, t1, flags=(EZF,) - bri t0, label("divLoopTop"), flags=(nCEZF,) + br label("divLoopTop"), flags=(nCEZF,) #Unload the answer divq rax @@ -347,7 +347,7 @@ divLoopTop: div2 t1, rax, t1 div2 t1, rax, t1 div2 t1, rax, t1, flags=(EZF,) - bri t0, label("divLoopTop"), flags=(nCEZF,) + br label("divLoopTop"), flags=(nCEZF,) #Unload the answer divq rax @@ -374,7 +374,7 @@ divLoopTop: div2 t1, rax, t1 div2 t1, rax, t1 div2 t1, rax, t1, flags=(EZF,) - bri t0, label("divLoopTop"), flags=(nCEZF,) + br label("divLoopTop"), flags=(nCEZF,) #Unload the answer divq rax @@ -422,7 +422,7 @@ def macroop IDIV_B_R divLoopTop: div2 t4, t1, t4, dataSize=1 div2 t4, t1, t4, flags=(EZF,), dataSize=1 - bri t0, label("divLoopTop"), flags=(nCEZF,) + br label("divLoopTop"), flags=(nCEZF,) #Unload the answer divq t5, dataSize=1 @@ -495,7 +495,7 @@ def macroop IDIV_B_M divLoopTop: div2 t4, t1, t4, dataSize=1 div2 t4, t1, t4, flags=(EZF,), dataSize=1 - bri t0, label("divLoopTop"), flags=(nCEZF,) + br label("divLoopTop"), flags=(nCEZF,) #Unload the answer divq t5, dataSize=1 @@ -569,7 +569,7 @@ def macroop IDIV_B_P divLoopTop: div2 t4, t1, t4, dataSize=1 div2 t4, t1, t4, flags=(EZF,), dataSize=1 - bri t0, label("divLoopTop"), flags=(nCEZF,) + br label("divLoopTop"), flags=(nCEZF,) #Unload the answer divq t5, dataSize=1 @@ -646,7 +646,7 @@ divLoopTop: div2 t4, t1, t4 div2 t4, t1, t4 div2 t4, t1, t4, flags=(EZF,) - bri t0, label("divLoopTop"), flags=(nCEZF,) + br label("divLoopTop"), flags=(nCEZF,) #Unload the answer divq t5 @@ -721,7 +721,7 @@ divLoopTop: div2 t4, t1, t4 div2 t4, t1, t4 div2 t4, t1, t4, flags=(EZF,) - bri t0, label("divLoopTop"), flags=(nCEZF,) + br label("divLoopTop"), flags=(nCEZF,) #Unload the answer divq t5 @@ -797,7 +797,7 @@ divLoopTop: div2 t4, t1, t4 div2 t4, t1, t4 div2 t4, t1, t4, flags=(EZF,) - bri t0, label("divLoopTop"), flags=(nCEZF,) + br label("divLoopTop"), flags=(nCEZF,) #Unload the answer divq t5 diff --git a/src/arch/x86/isa/insts/general_purpose/cache_and_memory_management.py b/src/arch/x86/isa/insts/general_purpose/cache_and_memory_management.py index b5fc43fcd..dbd2d8b84 100644 --- a/src/arch/x86/isa/insts/general_purpose/cache_and_memory_management.py +++ b/src/arch/x86/isa/insts/general_purpose/cache_and_memory_management.py @@ -53,20 +53,42 @@ # # Authors: Gabe Black -microcode = "" +microcode = ''' +def macroop PREFETCH_M +{ + ld t0, seg, sib, disp, dataSize=1, prefetch=True +}; + +def macroop PREFETCH_P +{ + rdip t7 + ld t0, seg, riprel, disp, dataSize=1, prefetch=True +}; + +def macroop PREFETCH_T0_M +{ + ld t0, seg, sib, disp, dataSize=1, prefetch=True +}; + +def macroop PREFETCH_T0_P +{ + rdip t7 + ld t0, seg, riprel, disp, dataSize=1, prefetch=True +}; + +''' + #let {{ # class LFENCE(Inst): -# "GenFault ${new UnimpInstFault}" +# "GenFault ${new UnimpInstFault}" # class SFENCE(Inst): -# "GenFault ${new UnimpInstFault}" +# "GenFault ${new UnimpInstFault}" # class MFENCE(Inst): -# "GenFault ${new UnimpInstFault}" +# "GenFault ${new UnimpInstFault}" # class PREFETCHlevel(Inst): -# "GenFault ${new UnimpInstFault}" -# class PREFETCH(Inst): -# "GenFault ${new UnimpInstFault}" +# "GenFault ${new UnimpInstFault}" # class PREFETCHW(Inst): -# "GenFault ${new UnimpInstFault}" +# "GenFault ${new UnimpInstFault}" # class CLFLUSH(Inst): -# "GenFault ${new UnimpInstFault}" +# "GenFault ${new UnimpInstFault}" #}}; diff --git a/src/arch/x86/isa/insts/general_purpose/compare_and_test/bit_scan.py b/src/arch/x86/isa/insts/general_purpose/compare_and_test/bit_scan.py index 71059e80d..22364e038 100644 --- a/src/arch/x86/isa/insts/general_purpose/compare_and_test/bit_scan.py +++ b/src/arch/x86/isa/insts/general_purpose/compare_and_test/bit_scan.py @@ -82,11 +82,11 @@ # Authors: Gabe Black microcode = ''' -def macroop BSF_R_R { +def macroop BSR_R_R { # Determine if the input was zero, and also move it to a temp reg. movi t1, t1, t0, dataSize=8 and t1, regm, regm, flags=(ZF,) - bri t0, label("end"), flags=(CZF,) + br label("end"), flags=(CZF,) # Zero out the result register movi reg, reg, 0x0 @@ -125,20 +125,19 @@ def macroop BSF_R_R { srli t3, t1, 1, dataSize=8, flags=(EZF,) ori t4, reg, 0x1 mov reg, reg, t4, flags=(nCEZF,) - mov t1, t1, t3, flags=(nCEZF,) end: fault "NoFault" }; -def macroop BSF_R_M { +def macroop BSR_R_M { movi t1, t1, t0, dataSize=8 ld t1, seg, sib, disp # Determine if the input was zero, and also move it to a temp reg. and t1, t1, t1, flags=(ZF,) - bri t0, label("end"), flags=(CZF,) + br label("end"), flags=(CZF,) # Zero out the result register movi reg, reg, 0x0 @@ -177,13 +176,12 @@ def macroop BSF_R_M { srli t3, t1, 1, dataSize=8, flags=(EZF,) ori t4, reg, 0x1 mov reg, reg, t4, flags=(nCEZF,) - mov t1, t1, t3, flags=(nCEZF,) end: fault "NoFault" }; -def macroop BSF_R_P { +def macroop BSR_R_P { rdip t7 movi t1, t1, t0, dataSize=8 @@ -191,7 +189,7 @@ def macroop BSF_R_P { # Determine if the input was zero, and also move it to a temp reg. and t1, t1, t1, flags=(ZF,) - bri t0, label("end"), flags=(CZF,) + br label("end"), flags=(CZF,) # Zero out the result register movi reg, reg, 0x0 @@ -230,17 +228,16 @@ def macroop BSF_R_P { srli t3, t1, 1, dataSize=8, flags=(EZF,) ori t4, reg, 0x1 mov reg, reg, t4, flags=(nCEZF,) - mov t1, t1, t3, flags=(nCEZF,) end: fault "NoFault" }; -def macroop BSR_R_R { +def macroop BSF_R_R { # Determine if the input was zero, and also move it to a temp reg. mov t1, t1, t0, dataSize=8 and t1, regm, regm, flags=(ZF,) - bri t0, label("end"), flags=(CZF,) + br label("end"), flags=(CZF,) # Zero out the result register movi reg, reg, 0 @@ -248,48 +245,54 @@ def macroop BSR_R_R { subi t2, t1, 1 xor t1, t2, t1 + # Bit 6 - srli t3, t1, 32, dataSize=8 - andi t3, t3, 32 - or reg, reg, t3 + srli t3, t1, 32, dataSize=8, flags=(EZF,) + ori t4, reg, 32 + mov reg, reg, t4, flags=(nCEZF,) + mov t1, t1, t3, flags=(nCEZF,) # Bit 5 - srli t3, t1, 16, dataSize=8 - andi t3, t3, 16 - or reg, reg, t3 + srli t3, t1, 16, dataSize=8, flags=(EZF,) + ori t4, reg, 16 + mov reg, reg, t4, flags=(nCEZF,) + mov t1, t1, t3, flags=(nCEZF,) # Bit 4 - srli t3, t1, 8, dataSize=8 - andi t3, t3, 8 - or reg, reg, t3 + srli t3, t1, 8, dataSize=8, flags=(EZF,) + ori t4, reg, 8 + mov reg, reg, t4, flags=(nCEZF,) + mov t1, t1, t3, flags=(nCEZF,) # Bit 3 - srli t3, t1, 4, dataSize=8 - andi t3, t3, 4 - or reg, reg, t3 + srli t3, t1, 4, dataSize=8, flags=(EZF,) + ori t4, reg, 4 + mov reg, reg, t4, flags=(nCEZF,) + mov t1, t1, t3, flags=(nCEZF,) # Bit 2 - srli t3, t1, 2, dataSize=8 - andi t3, t3, 2 - or reg, reg, t3 + srli t3, t1, 2, dataSize=8, flags=(EZF,) + ori t4, reg, 2 + mov reg, reg, t4, flags=(nCEZF,) + mov t1, t1, t3, flags=(nCEZF,) # Bit 1 - srli t3, t1, 1, dataSize=8 - andi t3, t3, 1 - or reg, reg, t3 + srli t3, t1, 1, dataSize=8, flags=(EZF,) + ori t4, reg, 1 + mov reg, reg, t4, flags=(nCEZF,) end: fault "NoFault" }; -def macroop BSR_R_M { +def macroop BSF_R_M { mov t1, t1, t0, dataSize=8 ld t1, seg, sib, disp # Determine if the input was zero, and also move it to a temp reg. and t1, t1, t1, flags=(ZF,) - bri t0, label("end"), flags=(CZF,) + br label("end"), flags=(CZF,) # Zero out the result register mov reg, reg, t0 @@ -298,40 +301,46 @@ def macroop BSR_R_M { xor t1, t2, t1 # Bit 6 - srli t3, t1, 32, dataSize=8 - andi t3, t3, 32 - or reg, reg, t3 + srli t3, t1, 32, dataSize=8, flags=(EZF,) + ori t4, reg, 32 + mov reg, reg, t4, flags=(nCEZF,) + mov t1, t1, t3, flags=(nCEZF,) # Bit 5 - srli t3, t1, 16, dataSize=8 - andi t3, t3, 16 - or reg, reg, t3 + srli t3, t1, 16, dataSize=8, flags=(EZF,) + ori t4, reg, 16 + mov reg, reg, t4, flags=(nCEZF,) + mov t1, t1, t3, flags=(nCEZF,) # Bit 4 - srli t3, t1, 8, dataSize=8 - andi t3, t3, 8 - or reg, reg, t3 + srli t3, t1, 8, dataSize=8, flags=(EZF,) + ori t4, reg, 8 + mov reg, reg, t4, flags=(nCEZF,) + mov t1, t1, t3, flags=(nCEZF,) # Bit 3 - srli t3, t1, 4, dataSize=8 - andi t3, t3, 4 - or reg, reg, t3 + srli t3, t1, 4, dataSize=8, flags=(EZF,) + ori t4, reg, 4 + mov reg, reg, t4, flags=(nCEZF,) + mov t1, t1, t3, flags=(nCEZF,) # Bit 2 - srli t3, t1, 2, dataSize=8 - andi t3, t3, 2 - or reg, reg, t3 + srli t3, t1, 2, dataSize=8, flags=(EZF,) + ori t4, reg, 2 + mov reg, reg, t4, flags=(nCEZF,) + mov t1, t1, t3, flags=(nCEZF,) # Bit 1 - srli t3, t1, 1, dataSize=8 - andi t3, t3, 1 - or reg, reg, t3 + srli t3, t1, 1, dataSize=8, flags=(EZF,) + ori t4, reg, 1 + mov reg, reg, t4, flags=(nCEZF,) + mov t1, t1, t3, flags=(nCEZF,) end: fault "NoFault" }; -def macroop BSR_R_P { +def macroop BSF_R_P { rdip t7 mov t1, t1, t0, dataSize=8 @@ -339,7 +348,7 @@ def macroop BSR_R_P { # Determine if the input was zero, and also move it to a temp reg. and t1, t1, t1, flags=(ZF,) - bri t0, label("end"), flags=(CZF,) + br label("end"), flags=(CZF,) # Zero out the result register mov reg, reg, t0 @@ -348,34 +357,40 @@ def macroop BSR_R_P { xor t1, t2, t1 # Bit 6 - srli t3, t1, 32, dataSize=8 - andi t3, t3, 32 - or reg, reg, t3 + srli t3, t1, 32, dataSize=8, flags=(EZF,) + ori t4, reg, 32 + mov reg, reg, t4, flags=(nCEZF,) + mov t1, t1, t3, flags=(nCEZF,) # Bit 5 - srli t3, t1, 16, dataSize=8 - andi t3, t3, 16 - or reg, reg, t3 + srli t3, t1, 16, dataSize=8, flags=(EZF,) + ori t4, reg, 16 + mov reg, reg, t4, flags=(nCEZF,) + mov t1, t1, t3, flags=(nCEZF,) # Bit 4 - srli t3, t1, 8, dataSize=8 - andi t3, t3, 8 - or reg, reg, t3 + srli t3, t1, 8, dataSize=8, flags=(EZF,) + ori t4, reg, 8 + mov reg, reg, t4, flags=(nCEZF,) + mov t1, t1, t3, flags=(nCEZF,) # Bit 3 - srli t3, t1, 4, dataSize=8 - andi t3, t3, 4 - or reg, reg, t3 + srli t3, t1, 4, dataSize=8, flags=(EZF,) + ori t4, reg, 4 + mov reg, reg, t4, flags=(nCEZF,) + mov t1, t1, t3, flags=(nCEZF,) # Bit 2 - srli t3, t1, 2, dataSize=8 - andi t3, t3, 2 - or reg, reg, t3 + srli t3, t1, 2, dataSize=8, flags=(EZF,) + ori t4, reg, 2 + mov reg, reg, t4, flags=(nCEZF,) + mov t1, t1, t3, flags=(nCEZF,) # Bit 1 - srli t3, t1, 1, dataSize=8 - andi t3, t3, 1 - or reg, reg, t3 + srli t3, t1, 1, dataSize=8, flags=(EZF,) + ori t4, reg, 1 + mov reg, reg, t4, flags=(nCEZF,) + mov t1, t1, t3, flags=(nCEZF,) end: fault "NoFault" diff --git a/src/arch/x86/isa/insts/general_purpose/control_transfer/call.py b/src/arch/x86/isa/insts/general_purpose/control_transfer/call.py index 45a7822fb..7abafe253 100644 --- a/src/arch/x86/isa/insts/general_purpose/control_transfer/call.py +++ b/src/arch/x86/isa/insts/general_purpose/control_transfer/call.py @@ -103,5 +103,5 @@ def macroop CALL_NEAR_P ''' #let {{ # class CALL(Inst): -# "GenFault ${new UnimpInstFault}" +# "GenFault ${new UnimpInstFault}" #}}; diff --git a/src/arch/x86/isa/insts/general_purpose/control_transfer/interrupts_and_exceptions.py b/src/arch/x86/isa/insts/general_purpose/control_transfer/interrupts_and_exceptions.py index 7039b4b5c..8203f7c2c 100644 --- a/src/arch/x86/isa/insts/general_purpose/control_transfer/interrupts_and_exceptions.py +++ b/src/arch/x86/isa/insts/general_purpose/control_transfer/interrupts_and_exceptions.py @@ -1,4 +1,4 @@ -# Copyright (c) 2007 The Hewlett-Packard Development Company +# Copyright (c) 2007-2008 The Hewlett-Packard Development Company # All rights reserved. # # Redistribution and use of this software in source and binary forms, @@ -53,16 +53,194 @@ # # Authors: Gabe Black -microcode = "" +microcode = ''' +def macroop IRET_REAL { + panic "Real mode iret isn't implemented!" +}; + +def macroop IRET_PROT { + .adjust_env oszIn64Override + + # Check for a nested task. This isn't supported at the moment. + rflag t1, NT + panic "Task switching with iret is unimplemented!", flags=(nCEZF,) + + #t1 = temp_RIP + #t2 = temp_CS + #t3 = temp_RFLAGS + #t4 = handy m5 register + + # Pop temp_RIP, temp_CS, and temp_RFLAGS + ld t1, ss, [1, t0, rsp], "0 * env.stackSize", dataSize=ssz + ld t2, ss, [1, t0, rsp], "1 * env.stackSize", dataSize=ssz + ld t3, ss, [1, t0, rsp], "2 * env.stackSize", dataSize=ssz + + # Read the handy m5 register for use later + rdm5reg t4 + + +### +### Handle if we're returning to virtual 8086 mode. +### + + #IF ((temp_RFLAGS.VM=1) && (CPL=0) && (LEGACY_MODE)) + # IRET_FROM_PROTECTED_TO_VIRTUAL + + #temp_RFLAGS.VM != 1 + rcri t0, t3, 18, flags=(ECF,) + br label("protToVirtFallThrough"), flags=(nCECF,) + + #CPL=0 + andi t0, t4, 0x30, flags=(EZF,) + br label("protToVirtFallThrough"), flags=(nCEZF,) + + #(LEGACY_MODE) + rcri t0, t4, 1, flags=(ECF,) + br label("protToVirtFallThrough"), flags=(nCECF,) + + panic "iret to virtual mode not supported" + +protToVirtFallThrough: + + + + #temp_CPL = temp_CS.rpl + andi t5, t2, 0x3 + + +### +### Read in the info for the new CS segment. +### + + #CS = READ_DESCRIPTOR (temp_CS, iret_chk) + andi t0, t2, 0xFC, flags=(EZF,), dataSize=2 + br label("processCSDescriptor"), flags=(CEZF,) + andi t6, t2, 0xF8, dataSize=8 + andi t0, t2, 0x4, flags=(EZF,), dataSize=2 + br label("globalCSDescriptor"), flags=(CEZF,) + ld t8, tsl, [1, t0, t6], dataSize=8 + br label("processCSDescriptor") +globalCSDescriptor: + ld t8, tsg, [1, t0, t6], dataSize=8 +processCSDescriptor: + chks t2, t6, dataSize=8 + + +### +### Get the new stack pointer and stack segment off the old stack if necessary, +### and piggyback on the logic to check the new RIP value. +### + #IF ((64BIT_MODE) || (temp_CPL!=CPL)) + #{ + + #(64BIT_MODE) + andi t0, t4, 0xE, flags=(EZF,) + # Since we just found out we're in 64 bit mode, take advantage and + # do the appropriate RIP checks. + br label("doPopStackStuffAndCheckRIP"), flags=(CEZF,) + + # Here, we know we're -not- in 64 bit mode, so we should do the + # appropriate/other RIP checks. + # if temp_RIP > CS.limit throw #GP(0) + rdlimit t6, cs, dataSize=8 + subi t0, t1, t6, flags=(ECF,) + fault "new GeneralProtection(0)", flags=(CECF,) + + #(temp_CPL!=CPL) + srli t7, t4, 4 + xor t7, t7, t5 + andi t0, t7, 0x3, flags=(EZF,) + br label("doPopStackStuff"), flags=(nCEZF,) + # We can modify user visible state here because we're know + # we're done with things that can fault. + addi rsp, rsp, "3 * env.stackSize" + br label("fallThroughPopStackStuff") + +doPopStackStuffAndCheckRIP: + # Check if the RIP is canonical. + sra t7, t1, 47, flags=(EZF,), dataSize=ssz + # if t7 isn't 0 or -1, it wasn't canonical. + br label("doPopStackStuff"), flags=(CEZF,) + addi t0, t7, 1, flags=(EZF,), dataSize=ssz + fault "new GeneralProtection(0)", flags=(nCEZF,) + +doPopStackStuff: + # POP.v temp_RSP + ld t6, ss, [1, t0, rsp], "3 * env.dataSize", dataSize=ssz + # POP.v temp_SS + ld t9, ss, [1, t0, rsp], "4 * env.dataSize", dataSize=ssz + # SS = READ_DESCRIPTOR (temp_SS, ss_chk) + andi t0, t9, 0xFC, flags=(EZF,), dataSize=2 + br label("processSSDescriptor"), flags=(CEZF,) + andi t7, t9, 0xF8, dataSize=8 + andi t0, t9, 0x4, flags=(EZF,), dataSize=2 + br label("globalSSDescriptor"), flags=(CEZF,) + ld t7, tsl, [1, t0, t7], dataSize=8 + br label("processSSDescriptor") +globalSSDescriptor: + ld t7, tsg, [1, t0, t7], dataSize=8 +processSSDescriptor: + chks t9, t7, dataSize=8 + + # This actually updates state which is wrong. It should wait until we know + # we're not going to fault. Unfortunately, that's hard to do. + wrdl ss, t7, t9 + wrsel ss, t9 + +### +### From this point downwards, we can't fault. We can update user visible state. +### + # RSP.s = temp_RSP + mov rsp, rsp, t6, dataSize=ssz + + #} + +fallThroughPopStackStuff: + + # Update CS + wrdl cs, t8, t2 + wrsel cs, t2 + + #CPL = temp_CPL + + #IF (changing CPL) + #{ + srli t7, t4, 4 + xor t7, t7, t5 + andi t0, t7, 0x3, flags=(EZF,) + br label("skipSegmentSquashing"), flags=(CEZF,) + + # The attribute register needs to keep track of more info before this will + # work the way it needs to. + # FOR (seg = ES, DS, FS, GS) + # IF ((seg.attr.dpl < cpl && ((seg.attr.type = 'data') + # || (seg.attr.type = 'non-conforming-code'))) + # { + # seg = NULL + # } + #} + +skipSegmentSquashing: + + # Ignore this for now. + #RFLAGS.v = temp_RFLAGS + wrflags t0, t3 + # VIF,VIP,IOPL only changed if (old_CPL = 0) + # IF only changed if (old_CPL <= old_RFLAGS.IOPL) + # VM unchanged + # RF cleared + + #RIP = temp_RIP + wrip t0, t1, dataSize=ssz +}; + +def macroop IRET_VIRT { + panic "Virtual mode iret isn't implemented!" +}; +''' #let {{ # class INT(Inst): -# "GenFault ${new UnimpInstFault}" +# "GenFault ${new UnimpInstFault}" # class INTO(Inst): -# "GenFault ${new UnimpInstFault}" -# class IRET(Inst): -# "GenFault ${new UnimpInstFault}" -# class IRETD(Inst): -# "GenFault ${new UnimpInstFault}" -# class IRETQ(Inst): -# "GenFault ${new UnimpInstFault}" +# "GenFault ${new UnimpInstFault}" #}}; diff --git a/src/arch/x86/isa/insts/general_purpose/control_transfer/xreturn.py b/src/arch/x86/isa/insts/general_purpose/control_transfer/xreturn.py index 0b2e81cbd..57ec9da26 100644 --- a/src/arch/x86/isa/insts/general_purpose/control_transfer/xreturn.py +++ b/src/arch/x86/isa/insts/general_purpose/control_transfer/xreturn.py @@ -1,4 +1,4 @@ -# Copyright (c) 2007 The Hewlett-Packard Development Company +# Copyright (c) 2007-2008 The Hewlett-Packard Development Company # All rights reserved. # # Redistribution and use of this software in source and binary forms, @@ -85,7 +85,7 @@ def macroop RET_FAR { ld t1, ss, [1, t0, rsp] # Get the return CS - ld t2, ss, [1, t0, rsp], dsz + ld t2, ss, [1, t0, rsp], ssz # Get the rpl andi t3, t2, 0x3 @@ -96,14 +96,23 @@ def macroop RET_FAR { # that doesn't happen yet. # Do stuff if they're equal - chks t4, t2, flags=(EZF,) - fault "new GeneralProtection(0)", flags=(CEZF,) - ld t3, flatseg, [1, t0, t4], addressSize=8, dataSize=8 - wrdl cs, t3, t2 + andi t0, t2, 0xFC, flags=(EZF,), dataSize=2 + br label("processDescriptor"), flags=(CEZF,) + andi t3, t2, 0xF8, dataSize=8 + andi t0, t2, 0x4, flags=(EZF,), dataSize=2 + br label("globalDescriptor"), flags=(CEZF,) + ld t3, tsl, [1, t0, t3], dataSize=8 + br label("processDescriptor") +globalDescriptor: + ld t3, tsg, [1, t0, t3], dataSize=8 +processDescriptor: + chks t2, t3, IretCheck, dataSize=8 # There should be validity checks on the RIP checks here, but I'll do # that later. + wrdl cs, t3, t2 + wrsel cs, t2 wrip t0, t1 - bri t0, label("end") + br label("end") # Do other stuff if they're not. end: diff --git a/src/arch/x86/isa/insts/general_purpose/data_conversion/ascii_adjust.py b/src/arch/x86/isa/insts/general_purpose/data_conversion/ascii_adjust.py index a1e322e56..2cbdd1ad8 100644 --- a/src/arch/x86/isa/insts/general_purpose/data_conversion/ascii_adjust.py +++ b/src/arch/x86/isa/insts/general_purpose/data_conversion/ascii_adjust.py @@ -56,11 +56,11 @@ microcode = "" #let {{ # class AAA(Inst): -# "GenFault ${new UnimpInstFault}" +# "GenFault ${new UnimpInstFault}" # class AAD(Inst): -# "GenFault ${new UnimpInstFault}" +# "GenFault ${new UnimpInstFault}" # class AAM(Inst): -# "GenFault ${new UnimpInstFault}" +# "GenFault ${new UnimpInstFault}" # class AAS(Inst): -# "GenFault ${new UnimpInstFault}" +# "GenFault ${new UnimpInstFault}" #}}; diff --git a/src/arch/x86/isa/insts/general_purpose/data_conversion/bcd_adjust.py b/src/arch/x86/isa/insts/general_purpose/data_conversion/bcd_adjust.py index 213724768..d220fdeb6 100644 --- a/src/arch/x86/isa/insts/general_purpose/data_conversion/bcd_adjust.py +++ b/src/arch/x86/isa/insts/general_purpose/data_conversion/bcd_adjust.py @@ -56,7 +56,7 @@ microcode = "" #let {{ # class DAA(Inst): -# "GenFault ${new UnimpInstFault}" +# "GenFault ${new UnimpInstFault}" # class DAS(Inst): -# "GenFault ${new UnimpInstFault}" +# "GenFault ${new UnimpInstFault}" #}}; diff --git a/src/arch/x86/isa/insts/general_purpose/data_conversion/endian_conversion.py b/src/arch/x86/isa/insts/general_purpose/data_conversion/endian_conversion.py index b98d09816..ac2343462 100644 --- a/src/arch/x86/isa/insts/general_purpose/data_conversion/endian_conversion.py +++ b/src/arch/x86/isa/insts/general_purpose/data_conversion/endian_conversion.py @@ -53,8 +53,26 @@ # # Authors: Gabe Black -microcode = "" +microcode = ''' +def macroop BSWAP_D_R +{ + roli reg, reg, 8, dataSize=2 + roli reg, reg, 16, dataSize=4 + roli reg, reg, 8, dataSize=2 +}; + +def macroop BSWAP_Q_R +{ + roli reg, reg, 8, dataSize=2 + roli reg, reg, 16, dataSize=4 + roli reg, reg, 8, dataSize=2 + roli reg, reg, 32, dataSize=8 + roli reg, reg, 8, dataSize=2 + roli reg, reg, 16, dataSize=4 + roli reg, reg, 8, dataSize=2 +}; +''' #let {{ # class BSWAP(Inst): -# "GenFault ${new UnimpInstFault}" +# "GenFault ${new UnimpInstFault}" #}}; diff --git a/src/arch/x86/isa/insts/general_purpose/data_conversion/extract_sign_mask.py b/src/arch/x86/isa/insts/general_purpose/data_conversion/extract_sign_mask.py index 1e0810594..01fa280fc 100644 --- a/src/arch/x86/isa/insts/general_purpose/data_conversion/extract_sign_mask.py +++ b/src/arch/x86/isa/insts/general_purpose/data_conversion/extract_sign_mask.py @@ -56,7 +56,7 @@ microcode = "" #let {{ # class MOVMSKPS(Inst): -# "GenFault ${new UnimpInstFault}" +# "GenFault ${new UnimpInstFault}" # class MOVMSKPD(Inst): -# "GenFault ${new UnimpInstFault}" +# "GenFault ${new UnimpInstFault}" #}}; diff --git a/src/arch/x86/isa/insts/general_purpose/data_conversion/translate.py b/src/arch/x86/isa/insts/general_purpose/data_conversion/translate.py index d6ae7885a..c334693e5 100644 --- a/src/arch/x86/isa/insts/general_purpose/data_conversion/translate.py +++ b/src/arch/x86/isa/insts/general_purpose/data_conversion/translate.py @@ -55,7 +55,7 @@ microcode = ''' def macroop XLAT { - zexti t1, rax, 7 + zexti t1, rax, 7, dataSize=8 # Here, t1 can be used directly. The value of al is supposed to be treated # as unsigned. Since we zero extended it from 8 bits above and the address # size has to be at least 16 bits, t1 will not be sign extended. diff --git a/src/arch/x86/isa/insts/general_purpose/data_transfer/move.py b/src/arch/x86/isa/insts/general_purpose/data_transfer/move.py index 3b8608c48..60c046d04 100644 --- a/src/arch/x86/isa/insts/general_purpose/data_transfer/move.py +++ b/src/arch/x86/isa/insts/general_purpose/data_transfer/move.py @@ -1,4 +1,4 @@ -# Copyright (c) 2007 The Hewlett-Packard Development Company +# Copyright (c) 2007-2008 The Hewlett-Packard Development Company # All rights reserved. # # Redistribution and use of this software in source and binary forms, @@ -126,18 +126,19 @@ def macroop MOVSXD_R_P { }; def macroop MOVSX_B_R_R { - sexti reg, regm, 7 + mov t1, t1, regm, dataSize=1 + sexti reg, t1, 7 }; def macroop MOVSX_B_R_M { - ld reg, seg, sib, disp, dataSize=1 - sexti reg, reg, 7 + ld t1, seg, sib, disp, dataSize=1 + sexti reg, t1, 7 }; def macroop MOVSX_B_R_P { rdip t7 - ld reg, seg, riprel, disp, dataSize=1 - sexti reg, reg, 7 + ld t1, seg, riprel, disp, dataSize=1 + sexti reg, t1, 7 }; def macroop MOVSX_W_R_R { @@ -160,7 +161,8 @@ def macroop MOVSX_W_R_P { # def macroop MOVZX_B_R_R { - zexti reg, regm, 7 + mov t1, t1, regm, dataSize=1 + zexti reg, t1, 7 }; def macroop MOVZX_B_R_M { @@ -190,13 +192,25 @@ def macroop MOVZX_W_R_P { }; def macroop MOV_C_R { + .adjust_env maxOsz wrcr reg, regm }; def macroop MOV_R_C { + .adjust_env maxOsz rdcr reg, regm }; +def macroop MOV_D_R { + .adjust_env maxOsz + wrdr reg, regm +}; + +def macroop MOV_R_D { + .adjust_env maxOsz + rddr reg, regm +}; + def macroop MOV_R_S { rdsel reg, regm }; @@ -213,7 +227,7 @@ def macroop MOV_P_S { }; def macroop MOV_REAL_S_R { - zext t2, regm, 15 + zexti t2, regm, 15, dataSize=8 slli t3, t2, 2, dataSize=8 wrsel reg, regm wrbase reg, t3 @@ -221,87 +235,121 @@ def macroop MOV_REAL_S_R { def macroop MOV_REAL_S_M { ld t1, seg, sib, disp, dataSize=2 - zext t2, t1, 15 + zexti t2, t1, 15, dataSize=8 slli t3, t2, 2, dataSize=8 wrsel reg, t1 wrbase reg, t3 }; def macroop MOV_REAL_S_P { - rdip t7 - ld t1, seg, riprel, disp, dataSize=2 - zext t2, t1, 15 - slli t3, t2, 2, dataSize=8 - wrsel reg, t1 - wrbase reg, t3 + panic "RIP relative addressing shouldn't happen in real mode" }; def macroop MOV_S_R { - chks t1, regm, flags=(EZF,), dataSize=8 - bri t0, label("end"), flags=(CEZF,) - ld t2, flatseg, [1, t0, t1], addressSize=8, dataSize=8 - wrdl reg, t2, regm -end: + andi t0, regm, 0xFC, flags=(EZF,), dataSize=2 + br label("processDescriptor"), flags=(CEZF,) + andi t2, regm, 0xF8, dataSize=8 + andi t0, regm, 0x4, flags=(EZF,), dataSize=2 + br label("globalDescriptor"), flags=(CEZF,) + ld t3, tsl, [1, t0, t2], dataSize=8, addressSize=8 + br label("processDescriptor") +globalDescriptor: + ld t3, tsg, [1, t0, t2], dataSize=8, addressSize=8 +processDescriptor: + chks regm, t3, dataSize=8 + wrdl reg, t3, regm wrsel reg, regm }; def macroop MOV_S_M { ld t1, seg, sib, disp, dataSize=2 - chks t2, t1, flags=(EZF,), dataSize=8 - bri t0, label("end"), flags=(CEZF,) - ld t2, flatseg, [1, t0, t1], addressSize=8, dataSize=8 - wrdl reg, t2, t1 -end: + andi t0, t1, 0xFC, flags=(EZF,), dataSize=2 + br label("processDescriptor"), flags=(CEZF,) + andi t2, t1, 0xF8, dataSize=8 + andi t0, t1, 0x4, flags=(EZF,), dataSize=2 + br label("globalDescriptor"), flags=(CEZF,) + ld t3, tsl, [1, t0, t2], dataSize=8, addressSize=8 + br label("processDescriptor") +globalDescriptor: + ld t3, tsg, [1, t0, t2], dataSize=8, addressSize=8 +processDescriptor: + chks t1, t3, dataSize=8 + wrdl reg, t3, t1 wrsel reg, t1 }; def macroop MOV_S_P { rdip t7 ld t1, seg, riprel, disp, dataSize=2 - chks t2, t1, flags=(EZF,), dataSize=8 - bri t0, label("end"), flags=(CEZF,) - ld t2, flatseg, [1, t0, t1], addressSize=8, dataSize=8 - wrdl reg, t2, t1 -end: + andi t0, t1, 0xFC, flags=(EZF,), dataSize=2 + br label("processDescriptor"), flags=(CEZF,) + andi t2, t1, 0xF8, dataSize=8 + andi t0, t1, 0x4, flags=(EZF,), dataSize=2 + br label("globalDescriptor"), flags=(CEZF,) + ld t3, tsl, [1, t0, t2], dataSize=8, addressSize=8 + br label("processDescriptor") +globalDescriptor: + ld t3, tsg, [1, t0, t2], dataSize=8, addressSize=8 +processDescriptor: + chks t1, t3, dataSize=8 + wrdl reg, t3, t1 wrsel reg, t1 }; def macroop MOVSS_S_R { - chks t1, regm, flags=(EZF,), dataSize=8 - # This actually needs to use the selector as the error code, but it would - # be hard to get that information into the instruction at the moment. - fault "new GeneralProtection(0)", flags=(CEZF,) - ld t2, flatseg, [1, t0, t1], addressSize=8, dataSize=8 - wrdl reg, t2, regm + andi t0, regm, 0xFC, flags=(EZF,), dataSize=2 + br label("processDescriptor"), flags=(CEZF,) + andi t2, regm, 0xF8, dataSize=8 + andi t0, regm, 0x4, flags=(EZF,), dataSize=2 + br label("globalDescriptor"), flags=(CEZF,) + ld t3, tsl, [1, t0, t2], dataSize=8, addressSize=8 + br label("processDescriptor") +globalDescriptor: + ld t3, tsg, [1, t0, t2], dataSize=8, addressSize=8 +processDescriptor: + chks regm, t3, SSCheck, dataSize=8 + wrdl reg, t3, regm wrsel reg, regm }; def macroop MOVSS_S_M { ld t1, seg, sib, disp, dataSize=2 - chks t2, t1, flags=(EZF,), dataSize=8 - # This actually needs to use the selector as the error code, but it would - # be hard to get that information into the instruction at the moment. - fault "new GeneralProtection(0)", flags=(CEZF,) - ld t2, flatseg, [1, t0, t1], addressSize=8, dataSize=8 - wrdl reg, t2, t1 + andi t0, t1, 0xFC, flags=(EZF,), dataSize=2 + br label("processDescriptor"), flags=(CEZF,) + andi t2, t1, 0xF8, dataSize=8 + andi t0, t1, 0x4, flags=(EZF,), dataSize=2 + br label("globalDescriptor"), flags=(CEZF,) + ld t3, tsl, [1, t0, t2], dataSize=8, addressSize=8 + br label("processDescriptor") +globalDescriptor: + ld t3, tsg, [1, t0, t2], dataSize=8, addressSize=8 +processDescriptor: + chks t1, t3, SSCheck, dataSize=8 + wrdl reg, t3, t1 wrsel reg, t1 }; def macroop MOVSS_S_P { rdip t7 ld t1, seg, riprel, disp, dataSize=2 - chks t2, t1, flags=(EZF,), dataSize=8 - # This actually needs to use the selector as the error code, but it would - # be hard to get that information into the instruction at the moment. - fault "new GeneralProtection(0)", flags=(CEZF,) - ld t2, flatseg, [1, t0, t1], addressSize=8, dataSize=8 - wrdl reg, t2, t1 + andi t0, t1, 0xFC, flags=(EZF,), dataSize=2 + br label("processDescriptor"), flags=(CEZF,) + andi t2, t1, 0xF8, dataSize=8 + andi t0, t1, 0x4, flags=(EZF,), dataSize=2 + br label("globalDescriptor"), flags=(CEZF,) + ld t3, tsl, [1, t0, t2], dataSize=8, addressSize=8 + br label("processDescriptor") +globalDescriptor: + ld t3, tsg, [1, t0, t2], dataSize=8, addressSize=8 +processDescriptor: + chks t1, t3, SSCheck, dataSize=8 + wrdl reg, t3, t1 wrsel reg, t1 }; ''' #let {{ # class MOVD(Inst): -# "GenFault ${new UnimpInstFault}" +# "GenFault ${new UnimpInstFault}" # class MOVNTI(Inst): -# "GenFault ${new UnimpInstFault}" +# "GenFault ${new UnimpInstFault}" #}}; diff --git a/src/arch/x86/isa/insts/general_purpose/data_transfer/stack_operations.py b/src/arch/x86/isa/insts/general_purpose/data_transfer/stack_operations.py index 6c51f3171..82fdffc63 100644 --- a/src/arch/x86/isa/insts/general_purpose/data_transfer/stack_operations.py +++ b/src/arch/x86/isa/insts/general_purpose/data_transfer/stack_operations.py @@ -1,4 +1,4 @@ -# Copyright (c) 2007 The Hewlett-Packard Development Company +# Copyright (c) 2007-2008 The Hewlett-Packard Development Company # All rights reserved. # # Redistribution and use of this software in source and binary forms, @@ -58,8 +58,8 @@ def macroop POP_R { # Make the default data size of pops 64 bits in 64 bit mode .adjust_env oszIn64Override - ld t1, ss, [1, t0, rsp] - addi rsp, rsp, dsz + ld t1, ss, [1, t0, rsp], dataSize=ssz + addi rsp, rsp, ssz, dataSize=asz mov reg, reg, t1 }; @@ -67,10 +67,10 @@ def macroop POP_M { # Make the default data size of pops 64 bits in 64 bit mode .adjust_env oszIn64Override - ld t1, ss, [1, t0, rsp] - cda seg, sib, disp - addi rsp, rsp, dsz - st t1, seg, sib, disp + ld t1, ss, [1, t0, rsp], dataSize=ssz + cda seg, sib, disp, dataSize=ssz + addi rsp, rsp, ssz, dataSize=asz + st t1, seg, sib, disp, dataSize=ssz }; def macroop POP_P { @@ -78,17 +78,17 @@ def macroop POP_P { .adjust_env oszIn64Override rdip t7 - ld t1, ss, [1, t0, rsp] - cda seg, sib, disp - addi rsp, rsp, dsz - st t1, seg, riprel, disp + ld t1, ss, [1, t0, rsp], dataSize=ssz + cda seg, sib, disp, dataSize=ssz + addi rsp, rsp, ssz, dataSize=asz + st t1, seg, riprel, disp, dataSize=ssz }; def macroop PUSH_R { # Make the default data size of pops 64 bits in 64 bit mode .adjust_env oszIn64Override - stupd reg, ss, [1, t0, rsp], "-env.dataSize" + stupd reg, ss, [1, t0, rsp], "-env.stackSize", dataSize=ssz }; def macroop PUSH_I { @@ -96,15 +96,15 @@ def macroop PUSH_I { .adjust_env oszIn64Override limm t1, imm - stupd t1, ss, [1, t0, rsp], "-env.dataSize" + stupd t1, ss, [1, t0, rsp], "-env.stackSize", dataSize=ssz }; def macroop PUSH_M { # Make the default data size of pops 64 bits in 64 bit mode .adjust_env oszIn64Override - ld t1, seg, sib, disp - stupd t1, ss, [1, t0, rsp], "-env.dataSize" + ld t1, seg, sib, disp, dataSize=ssz + stupd t1, ss, [1, t0, rsp], "-env.stackSize", dataSize=ssz }; def macroop PUSH_P { @@ -112,48 +112,48 @@ def macroop PUSH_P { .adjust_env oszIn64Override rdip t7 - ld t1, seg, riprel, disp - stupd t1, ss, [1, t0, rsp], "-env.dataSize" + ld t1, seg, riprel, disp, dataSize=ssz + stupd t1, ss, [1, t0, rsp], "-env.stackSize", dataSize=ssz }; def macroop PUSHA { # Check all the stack addresses. We'll assume that if the beginning and # end are ok, then the stuff in the middle should be as well. - cda ss, [1, t0, rsp], "-env.dataSize" - cda ss, [1, t0, rsp], "-8 * env.dataSize" - stupd rax, ss, [1, t0, rsp], "-env.dataSize" - stupd rcx, ss, [1, t0, rsp], "-env.dataSize" - stupd rdx, ss, [1, t0, rsp], "-env.dataSize" - stupd rbx, ss, [1, t0, rsp], "-env.dataSize" - stupd rsp, ss, [1, t0, rsp], "-env.dataSize" - stupd rbp, ss, [1, t0, rsp], "-env.dataSize" - stupd rsi, ss, [1, t0, rsp], "-env.dataSize" - stupd rdi, ss, [1, t0, rsp], "-env.dataSize" + cda ss, [1, t0, rsp], "-env.stackSize", dataSize=ssz + cda ss, [1, t0, rsp], "-8 * env.stackSize", dataSize=ssz + stupd rax, ss, [1, t0, rsp], "-env.stackSize", dataSize=ssz + stupd rcx, ss, [1, t0, rsp], "-env.stackSize", dataSize=ssz + stupd rdx, ss, [1, t0, rsp], "-env.stackSize", dataSize=ssz + stupd rbx, ss, [1, t0, rsp], "-env.stackSize", dataSize=ssz + stupd rsp, ss, [1, t0, rsp], "-env.stackSize", dataSize=ssz + stupd rbp, ss, [1, t0, rsp], "-env.stackSize", dataSize=ssz + stupd rsi, ss, [1, t0, rsp], "-env.stackSize", dataSize=ssz + stupd rdi, ss, [1, t0, rsp], "-env.stackSize", dataSize=ssz }; def macroop POPA { # Check all the stack addresses. We'll assume that if the beginning and # end are ok, then the stuff in the middle should be as well. - ld t1, ss, [1, t0, rsp], "0 * env.dataSize" - ld t2, ss, [1, t0, rsp], "7 * env.dataSize" - mov rdi, rdi, t1 - ld rsi, ss, [1, t0, rsp], "1 * env.dataSize" - ld rbp, ss, [1, t0, rsp], "2 * env.dataSize" - ld rbx, ss, [1, t0, rsp], "4 * env.dataSize" - ld rdx, ss, [1, t0, rsp], "5 * env.dataSize" - ld rcx, ss, [1, t0, rsp], "6 * env.dataSize" - mov rax, rax, t2 - addi rsp, rsp, "8 * env.dataSize" + ld t1, ss, [1, t0, rsp], "0 * env.stackSize", dataSize=ssz + ld t2, ss, [1, t0, rsp], "7 * env.stackSize", dataSize=ssz + mov rdi, rdi, t1, dataSize=ssz + ld rsi, ss, [1, t0, rsp], "1 * env.stackSize", dataSize=ssz + ld rbp, ss, [1, t0, rsp], "2 * env.stackSize", dataSize=ssz + ld rbx, ss, [1, t0, rsp], "4 * env.stackSize", dataSize=ssz + ld rdx, ss, [1, t0, rsp], "5 * env.stackSize", dataSize=ssz + ld rcx, ss, [1, t0, rsp], "6 * env.stackSize", dataSize=ssz + mov rax, rax, t2, dataSize=ssz + addi rsp, rsp, "8 * env.stackSize", dataSize=asz }; def macroop LEAVE { # Make the default data size of pops 64 bits in 64 bit mode .adjust_env oszIn64Override - mov t1, t1, rbp - ld rbp, ss, [1, t0, t1] - mov rsp, rsp, t1 - addi rsp, rsp, dsz + mov t1, t1, rbp, dataSize=asz + ld rbp, ss, [1, t0, t1], dataSize=ssz + mov rsp, rsp, t1, dataSize=asz + addi rsp, rsp, ssz, dataSize=asz }; def macroop ENTER_I_I { @@ -162,41 +162,41 @@ def macroop ENTER_I_I { # Pull the different components out of the immediate limm t1, imm - zexti t2, t1, 15, dataSize=2 + zexti t2, t1, 15, dataSize=8 srl t1, t1, 16 - zexti t1, t1, 5 + zexti t1, t1, 5, dataSize=8 # t1 is now the masked nesting level, and t2 is the amount of storage. # Push rbp. - stupd rbp, ss, [1, t0, rsp], "-env.dataSize" + stupd rbp, ss, [1, t0, rsp], "-env.stackSize", dataSize=ssz # Save the stack pointer for later - mov t6, t6, rsp + mov t6, t6, rsp, dataSize=asz # If the nesting level is zero, skip all this stuff. subi t0, t1, t0, flags=(EZF,), dataSize=2 - bri t0, label("skipLoop"), flags=(CEZF,) + br label("skipLoop"), flags=(CEZF,) # If the level was 1, only push the saved rbp subi t0, t1, 1, flags=(EZF,) - bri t0, label("bottomOfLoop"), flags=(CEZF,) + br label("bottomOfLoop"), flags=(CEZF,) limm t4, "ULL(-1)", dataSize=8 topOfLoop: - ld t5, ss, [dsz, t4, rbp] - stupd t5, ss, [1, t0, rsp], "-env.dataSize" + ld t5, ss, [ssz, t4, rbp], dataSize=ssz + stupd t5, ss, [1, t0, rsp], "-env.stackSize" # If we're not done yet, loop subi t4, t4, 1, dataSize=8 add t0, t4, t1, flags=(EZF,) - bri t0, label("topOfLoop"), flags=(nCEZF,) + br label("topOfLoop"), flags=(nCEZF,) bottomOfLoop: # Push the old rbp onto the stack - stupd t6, ss, [1, t0, rsp], "-env.dataSize" + stupd t6, ss, [1, t0, rsp], "-env.stackSize" skipLoop: - sub rsp, rsp, t2 - mov rbp, rbp, t6 + sub rsp, rsp, t2, dataSize=asz + mov rbp, rbp, t6, dataSize=asz }; ''' diff --git a/src/arch/x86/isa/insts/general_purpose/flags/push_and_pop.py b/src/arch/x86/isa/insts/general_purpose/flags/push_and_pop.py index fe60350c1..59f6aaec2 100644 --- a/src/arch/x86/isa/insts/general_purpose/flags/push_and_pop.py +++ b/src/arch/x86/isa/insts/general_purpose/flags/push_and_pop.py @@ -1,4 +1,4 @@ -# Copyright (c) 2007 The Hewlett-Packard Development Company +# Copyright (c) 2007-2008 The Hewlett-Packard Development Company # All rights reserved. # # Redistribution and use of this software in source and binary forms, @@ -57,17 +57,15 @@ microcode = ''' def macroop PUSHF { .adjust_env oszIn64Override - # This should really read the whole flags register, not just user flags. - ruflags t1 - stupd t1, ss, [1, t0, rsp], "-env.dataSize" + rflags t1 + stupd t1, ss, [1, t0, rsp], "-env.stackSize", dataSize=ssz }; def macroop POPF { .adjust_env oszIn64Override - ld t1, ss, [1, t0, rsp] - addi rsp, rsp, dsz - # This should really write the whole flags register, not just user flags. - wruflags t1, t0 + ld t1, ss, [1, t0, rsp], dataSize=ssz + addi rsp, rsp, ssz + wrflags t1, t0 }; ''' diff --git a/src/arch/x86/isa/insts/general_purpose/flags/set_and_clear.py b/src/arch/x86/isa/insts/general_purpose/flags/set_and_clear.py index 4c655e0b2..e151dc61d 100644 --- a/src/arch/x86/isa/insts/general_purpose/flags/set_and_clear.py +++ b/src/arch/x86/isa/insts/general_purpose/flags/set_and_clear.py @@ -1,4 +1,4 @@ -# Copyright (c) 2007 The Hewlett-Packard Development Company +# Copyright (c) 2007-2008 The Hewlett-Packard Development Company # All rights reserved. # # Redistribution and use of this software in source and binary forms, @@ -84,10 +84,18 @@ def macroop CMC { ruflags t1 wruflagsi t1, "CFBit" }; + +def macroop STI { + rflags t1 + limm t2, "IFBit" + or t1, t1, t2 + wrflags t1, t0 +}; + +def macroop CLI { + rflags t1 + limm t2, "~IFBit" + and t1, t1, t2 + wrflags t1, t0 +}; ''' -#let {{ -# class CLI(Inst): -# "GenFault ${new UnimpInstFault}" -# class STI(Inst): -# "GenFault ${new UnimpInstFault}" -#}}; diff --git a/src/arch/x86/isa/insts/general_purpose/input_output/general_io.py b/src/arch/x86/isa/insts/general_purpose/input_output/general_io.py index 1986a322e..4e3c9b316 100644 --- a/src/arch/x86/isa/insts/general_purpose/input_output/general_io.py +++ b/src/arch/x86/isa/insts/general_purpose/input_output/general_io.py @@ -84,25 +84,23 @@ microcode = ''' def macroop IN_R_I { .adjust_imm trimImm(8) - limm t1, "IntAddrPrefixIO", dataSize=8 - ld reg, intseg, [1, t1, t0], imm, addressSize=8 + limm t1, imm, dataSize=asz + ld reg, intseg, [1, t1, t0], "IntAddrPrefixIO << 3", addressSize=8 }; def macroop IN_R_R { - limm t1, "IntAddrPrefixIO", dataSize=8 - zexti t2, regm, 15, dataSize=2 - ld reg, intseg, [1, t1, t2], addressSize=8 + zexti t2, regm, 15, dataSize=8 + ld reg, intseg, [1, t2, t0], "IntAddrPrefixIO << 3", addressSize=8 }; def macroop OUT_I_R { .adjust_imm trimImm(8) - limm t1, "IntAddrPrefixIO", dataSize=8 - st reg, intseg, [1, t1, t0], imm, addressSize=8 + limm t1, imm, dataSize=8 + st reg, intseg, [1, t1, t0], "IntAddrPrefixIO << 3", addressSize=8 }; def macroop OUT_R_R { - limm t1, "IntAddrPrefixIO", dataSize=8 - zexti t2, reg, 15, dataSize=2 - st regm, intseg, [1, t1, t2], addressSize=8 + zexti t2, reg, 15, dataSize=8 + st regm, intseg, [1, t2, t0], "IntAddrPrefixIO << 3", addressSize=8 }; ''' diff --git a/src/arch/x86/isa/insts/general_purpose/input_output/string_io.py b/src/arch/x86/isa/insts/general_purpose/input_output/string_io.py index b44203d9c..b3bc5ab67 100644 --- a/src/arch/x86/isa/insts/general_purpose/input_output/string_io.py +++ b/src/arch/x86/isa/insts/general_purpose/input_output/string_io.py @@ -1,4 +1,4 @@ -# Copyright (c) 2007 The Hewlett-Packard Development Company +# Copyright (c) 2007-2008 The Hewlett-Packard Development Company # All rights reserved. # # Redistribution and use of this software in source and binary forms, @@ -61,32 +61,33 @@ def macroop INS_M_R { subi t4, t0, dsz, dataSize=asz mov t3, t3, t4, flags=(nCEZF,), dataSize=asz - limm t1, "IntAddrPrefixIO" - zexti t2, reg, 15, dataSize=2 + zexti t2, reg, 15, dataSize=8 - ld t6, intseg, [1, t1, t2], addressSize=8 + ld t6, intseg, [1, t2, t0], "IntAddrPrefixIO << 3", addressSize=8 st t6, es, [1, t0, rdi] add rdi, rdi, t3, dataSize=asz }; def macroop INS_E_M_R { + and t0, rcx, rcx, flags=(EZF,), dataSize=asz + br label("end"), flags=(CEZF,) # Find the constant we need to either add or subtract from rdi ruflag t0, 10 movi t3, t3, dsz, flags=(CEZF,), dataSize=asz subi t4, t0, dsz, dataSize=asz mov t3, t3, t4, flags=(nCEZF,), dataSize=asz - limm t1, "IntAddrPrefixIO" - zexti t2, reg, 15, dataSize=2 + zexti t2, reg, 15, dataSize=8 topOfLoop: - ld t6, intseg, [1, t1, t2], addressSize=8 + ld t6, intseg, [1, t2, t0], "IntAddrPrefixIO << 3", addressSize=8 st t6, es, [1, t0, rdi] subi rcx, rcx, 1, flags=(EZF,), dataSize=asz add rdi, rdi, t3, dataSize=asz - bri t0, label("topOfLoop"), flags=(nCEZF,) + br label("topOfLoop"), flags=(nCEZF,) +end: fault "NoFault" }; @@ -97,32 +98,33 @@ def macroop OUTS_R_M { subi t4, t0, dsz, dataSize=asz mov t3, t3, t4, flags=(nCEZF,), dataSize=asz - limm t1, "IntAddrPrefixIO" - zexti t2, reg, 15, dataSize=2 + zexti t2, reg, 15, dataSize=8 ld t6, ds, [1, t0, rsi] - st t6, intseg, [1, t1, t2], addressSize=8 + st t6, intseg, [1, t2, t0], "IntAddrPrefixIO << 3", addressSize=8 add rsi, rsi, t3, dataSize=asz }; def macroop OUTS_E_R_M { + and t0, rcx, rcx, flags=(EZF,), dataSize=asz + br label("end"), flags=(CEZF,) # Find the constant we need to either add or subtract from rdi ruflag t0, 10 movi t3, t3, dsz, flags=(CEZF,), dataSize=asz subi t4, t0, dsz, dataSize=asz mov t3, t3, t4, flags=(nCEZF,), dataSize=asz - limm t1, "IntAddrPrefixIO" - zexti t2, reg, 15, dataSize=2 + zexti t2, reg, 15, dataSize=8 topOfLoop: ld t6, ds, [1, t0, rsi] - st t6, intseg, [1, t1, t2], addressSize=8 + st t6, intseg, [1, t2, t0], "IntAddrPrefixIO << 3", addressSize=8 subi rcx, rcx, 1, flags=(EZF,), dataSize=asz add rsi, rsi, t3, dataSize=asz - bri t0, label("topOfLoop"), flags=(nCEZF,) + br label("topOfLoop"), flags=(nCEZF,) +end: fault "NoFault" }; ''' diff --git a/src/arch/x86/isa/insts/general_purpose/load_segment_registers.py b/src/arch/x86/isa/insts/general_purpose/load_segment_registers.py index 8aec4b99e..e6633ee1a 100644 --- a/src/arch/x86/isa/insts/general_purpose/load_segment_registers.py +++ b/src/arch/x86/isa/insts/general_purpose/load_segment_registers.py @@ -56,17 +56,17 @@ microcode = "" #let {{ # class LDS(Inst): -# "GenFault ${new UnimpInstFault}" +# "GenFault ${new UnimpInstFault}" # class LES(Inst): -# "GenFault ${new UnimpInstFault}" +# "GenFault ${new UnimpInstFault}" # class LFS(Inst): -# "GenFault ${new UnimpInstFault}" +# "GenFault ${new UnimpInstFault}" # class LGS(Inst): -# "GenFault ${new UnimpInstFault}" +# "GenFault ${new UnimpInstFault}" # class LSS(Inst): -# "GenFault ${new UnimpInstFault}" +# "GenFault ${new UnimpInstFault}" # class MOV_SEG(Inst): -# "GenFault ${new UnimpInstFault}" +# "GenFault ${new UnimpInstFault}" # class POP(Inst): -# "GenFault ${new UnimpInstFault}" +# "GenFault ${new UnimpInstFault}" #}}; diff --git a/src/arch/x86/isa/insts/general_purpose/processor_information.py b/src/arch/x86/isa/insts/general_purpose/processor_information.py deleted file mode 100644 index 6070169ac..000000000 --- a/src/arch/x86/isa/insts/general_purpose/processor_information.py +++ /dev/null @@ -1,405 +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 - -microcode = ''' -def macroop CPUID_R { - -# -# Find which type of cpuid function it is by checking bit 31. Also clear that -# bit to form an offset into the functions of that type. -# - limm t1, 0x80000000, dataSize=4 - and t2, t1, rax, flags=(EZF,) - # clear the bit - xor t1, t2, rax - -# -# Do range checking on the offset -# - # If EZF is set, the function is standard and the max is 0x1. - movi t2, t2, 0x1, flags=(CEZF,) - # If EZF is cleared, the function is extended and the max is 0x18. - movi t2, t2, 0x18, flags=(nCEZF,) - subi t0, t1, t2, flags=(ECF,) - # ECF will be set if the offset is too large. - bri t0, label("end"), flags=(nCECF,) - - -# -# Jump to the right portion -# - movi t2, t2, label("standardStart"), flags=(CEZF,) - movi t2, t2, label("extendedStart"), flags=(nCEZF,) - # This gives each function 8 microops to use. It's wasteful because only - # 5 will be needed, but a multiply would be expensive. In the system - # described in the RISC86 patent, the fifth instruction would really be - # the sequencing field on an op quad, so each function would be implemented - # by -exactly- one op quad. Since we're approximating, this should be ok. - slli t1, t1, 3 - br t2, t1 - -############################################################################# -############################################################################# - -# -# Standard functions. -# - -standardStart: - -# 0x00000000 -- Processor Vendor and Largest Standard Function Number - limm rax, 0x00000001, dataSize=4 - limm rbx, 0x68747541, dataSize=4 - limm rdx, 0x69746e65, dataSize=4 - limm rcx, 0x444d4163, dataSize=4 - bri t0, label("end") - fault "NoFault" - fault "NoFault" - fault "NoFault" - -# 0x00000001 -- Family, Model, Stepping Identifiers - limm rax, 0x00020f51, dataSize=4 - limm rbx, 0x00000405, dataSize=4 - limm rdx, 0xe3d3fbff, dataSize=4 - limm rcx, 0x00000001, dataSize=4 - bri t0, label("end") - fault "NoFault" - fault "NoFault" - fault "NoFault" - -# -# Extended functions. -# - -extendedStart: - -# 0x80000000 -- Processor Vendor and Largest Extended Function Number - limm rax, 0x80000018, dataSize=4 - limm rbx, 0x68747541, dataSize=4 - limm rdx, 0x69746e65, dataSize=4 - limm rcx, 0x444d4163, dataSize=4 - bri t0, label("end") - fault "NoFault" - fault "NoFault" - fault "NoFault" - -# 0x80000001 -- EAX: AMD Family, Model, Stepping -# EBX: BrandId Identifier -# ECX: Feature Identifiers -# EDX: Feature Identifiers - limm rax, 0x00020f51, dataSize=4 - limm rbx, 0x00000405, dataSize=4 - limm rdx, 0xe3d3fbff, dataSize=4 - limm rcx, 0x00000001, dataSize=4 - bri t0, label("end") - fault "NoFault" - fault "NoFault" - fault "NoFault" - -# 0x80000002 -- Processor Name String Identifier - # JUNK VALUES - limm rax, 0x80000018, dataSize=4 - limm rbx, 0x68747541, dataSize=4 - limm rdx, 0x69746e65, dataSize=4 - limm rcx, 0x444d4163, dataSize=4 - bri t0, label("end") - fault "NoFault" - fault "NoFault" - fault "NoFault" - -# 0x80000003 -- Processor Name String Identifier - # JUNK VALUES - limm rax, 0x80000018, dataSize=4 - limm rbx, 0x68747541, dataSize=4 - limm rdx, 0x69746e65, dataSize=4 - limm rcx, 0x444d4163, dataSize=4 - bri t0, label("end") - fault "NoFault" - fault "NoFault" - fault "NoFault" - -# 0x80000004 -- Processor Name String Identifier - # JUNK VALUES - limm rax, 0x80000018, dataSize=4 - limm rbx, 0x68747541, dataSize=4 - limm rdx, 0x69746e65, dataSize=4 - limm rcx, 0x444d4163, dataSize=4 - bri t0, label("end") - fault "NoFault" - fault "NoFault" - fault "NoFault" - -# 0x80000005 -- L1 Cache and TLB Identifiers - limm rax, 0xff08ff08, dataSize=4 - limm rbx, 0xff20ff20, dataSize=4 - limm rdx, 0x40020140, dataSize=4 - limm rcx, 0x40020140, dataSize=4 - bri t0, label("end") - fault "NoFault" - fault "NoFault" - fault "NoFault" - -# 0x80000006 -- L2/L3 Cache and L2 TLB Identifiers - limm rax, 0x00000000, dataSize=4 - limm rbx, 0x42004200, dataSize=4 - limm rdx, 0x00000000, dataSize=4 - limm rcx, 0x04008140, dataSize=4 - bri t0, label("end") - fault "NoFault" - fault "NoFault" - fault "NoFault" - -# 0x80000007 -- Advanced Power Management Information - # JUNK VALUES - limm rax, 0x80000018, dataSize=4 - limm rbx, 0x68747541, dataSize=4 - limm rdx, 0x69746e65, dataSize=4 - limm rcx, 0x444d4163, dataSize=4 - bri t0, label("end") - fault "NoFault" - fault "NoFault" - fault "NoFault" - -# 0x80000008 -- Long Mode Address Size Identification - # JUNK VALUES - limm rax, 0x80000018, dataSize=4 - limm rbx, 0x68747541, dataSize=4 - limm rdx, 0x69746e65, dataSize=4 - limm rcx, 0x444d4163, dataSize=4 - bri t0, label("end") - fault "NoFault" - fault "NoFault" - fault "NoFault" - -# 0x80000009 -- Reserved - # JUNK VALUES - limm rax, 0x80000018, dataSize=4 - limm rbx, 0x68747541, dataSize=4 - limm rdx, 0x69746e65, dataSize=4 - limm rcx, 0x444d4163, dataSize=4 - bri t0, label("end") - fault "NoFault" - fault "NoFault" - fault "NoFault" - -# 0x8000000A -- SVM Revision and Feature Identification - # JUNK VALUES - limm rax, 0x80000018, dataSize=4 - limm rbx, 0x68747541, dataSize=4 - limm rdx, 0x69746e65, dataSize=4 - limm rcx, 0x444d4163, dataSize=4 - bri t0, label("end") - fault "NoFault" - fault "NoFault" - fault "NoFault" - -# 0x8000000B -- Reserved - # JUNK VALUES - limm rax, 0x80000018, dataSize=4 - limm rbx, 0x68747541, dataSize=4 - limm rdx, 0x69746e65, dataSize=4 - limm rcx, 0x444d4163, dataSize=4 - bri t0, label("end") - fault "NoFault" - fault "NoFault" - fault "NoFault" - -# 0x8000000C -- Reserved - # JUNK VALUES - limm rax, 0x80000018, dataSize=4 - limm rbx, 0x68747541, dataSize=4 - limm rdx, 0x69746e65, dataSize=4 - limm rcx, 0x444d4163, dataSize=4 - bri t0, label("end") - fault "NoFault" - fault "NoFault" - fault "NoFault" - -# 0x8000000D -- Reserved - # JUNK VALUES - limm rax, 0x80000018, dataSize=4 - limm rbx, 0x68747541, dataSize=4 - limm rdx, 0x69746e65, dataSize=4 - limm rcx, 0x444d4163, dataSize=4 - bri t0, label("end") - fault "NoFault" - fault "NoFault" - fault "NoFault" - -# 0x8000000E -- Reserved - # JUNK VALUES - limm rax, 0x80000018, dataSize=4 - limm rbx, 0x68747541, dataSize=4 - limm rdx, 0x69746e65, dataSize=4 - limm rcx, 0x444d4163, dataSize=4 - bri t0, label("end") - fault "NoFault" - fault "NoFault" - fault "NoFault" - -# 0x8000000F -- Reserved - # JUNK VALUES - limm rax, 0x80000018, dataSize=4 - limm rbx, 0x68747541, dataSize=4 - limm rdx, 0x69746e65, dataSize=4 - limm rcx, 0x444d4163, dataSize=4 - bri t0, label("end") - fault "NoFault" - fault "NoFault" - fault "NoFault" - -# 0x80000010 -- Reserved - # JUNK VALUES - limm rax, 0x80000018, dataSize=4 - limm rbx, 0x68747541, dataSize=4 - limm rdx, 0x69746e65, dataSize=4 - limm rcx, 0x444d4163, dataSize=4 - bri t0, label("end") - fault "NoFault" - fault "NoFault" - fault "NoFault" - -# 0x80000011 -- Reserved - # JUNK VALUES - limm rax, 0x80000018, dataSize=4 - limm rbx, 0x68747541, dataSize=4 - limm rdx, 0x69746e65, dataSize=4 - limm rcx, 0x444d4163, dataSize=4 - bri t0, label("end") - fault "NoFault" - fault "NoFault" - fault "NoFault" - -# 0x80000012 -- Reserved - # JUNK VALUES - limm rax, 0x80000018, dataSize=4 - limm rbx, 0x68747541, dataSize=4 - limm rdx, 0x69746e65, dataSize=4 - limm rcx, 0x444d4163, dataSize=4 - bri t0, label("end") - fault "NoFault" - fault "NoFault" - fault "NoFault" - -# 0x80000013 -- Reserved - # JUNK VALUES - limm rax, 0x80000018, dataSize=4 - limm rbx, 0x68747541, dataSize=4 - limm rdx, 0x69746e65, dataSize=4 - limm rcx, 0x444d4163, dataSize=4 - bri t0, label("end") - fault "NoFault" - fault "NoFault" - fault "NoFault" - -# 0x80000014 -- Reserved - # JUNK VALUES - limm rax, 0x80000018, dataSize=4 - limm rbx, 0x68747541, dataSize=4 - limm rdx, 0x69746e65, dataSize=4 - limm rcx, 0x444d4163, dataSize=4 - bri t0, label("end") - fault "NoFault" - fault "NoFault" - fault "NoFault" - -# 0x80000015 -- Reserved - # JUNK VALUES - limm rax, 0x80000018, dataSize=4 - limm rbx, 0x68747541, dataSize=4 - limm rdx, 0x69746e65, dataSize=4 - limm rcx, 0x444d4163, dataSize=4 - bri t0, label("end") - fault "NoFault" - fault "NoFault" - fault "NoFault" - -# 0x80000016 -- Reserved - # JUNK VALUES - limm rax, 0x80000018, dataSize=4 - limm rbx, 0x68747541, dataSize=4 - limm rdx, 0x69746e65, dataSize=4 - limm rcx, 0x444d4163, dataSize=4 - bri t0, label("end") - fault "NoFault" - fault "NoFault" - fault "NoFault" - -# 0x80000017 -- Reserved - # JUNK VALUES - limm rax, 0x80000018, dataSize=4 - limm rbx, 0x68747541, dataSize=4 - limm rdx, 0x69746e65, dataSize=4 - limm rcx, 0x444d4163, dataSize=4 - bri t0, label("end") - fault "NoFault" - fault "NoFault" - fault "NoFault" - -# 0x80000018 -- Reserved - # JUNK VALUES - limm rax, 0x80000018, dataSize=4 - limm rbx, 0x68747541, dataSize=4 - limm rdx, 0x69746e65, dataSize=4 - limm rcx, 0x444d4163, dataSize=4 - bri t0, label("end") - fault "NoFault" - fault "NoFault" - fault "NoFault" - -end: - fault "NoFault" -}; -''' diff --git a/src/arch/x86/isa/insts/general_purpose/rotate_and_shift/shift.py b/src/arch/x86/isa/insts/general_purpose/rotate_and_shift/shift.py index ed7d761b8..caaeca974 100644 --- a/src/arch/x86/isa/insts/general_purpose/rotate_and_shift/shift.py +++ b/src/arch/x86/isa/insts/general_purpose/rotate_and_shift/shift.py @@ -56,13 +56,13 @@ microcode = ''' def macroop SAL_R_I { - slli reg, reg, imm, flags=(SF,ZF,PF) + slli reg, reg, imm, flags=(CF,OF,SF,ZF,PF) }; def macroop SAL_M_I { ldst t1, seg, sib, disp - slli t1, t1, imm, flags=(SF,ZF,PF) + slli t1, t1, imm, flags=(CF,OF,SF,ZF,PF) st t1, seg, sib, disp }; @@ -70,19 +70,19 @@ def macroop SAL_P_I { rdip t7 ldst t1, seg, riprel, disp - slli t1, t1, imm, flags=(SF,ZF,PF) + slli t1, t1, imm, flags=(CF,OF,SF,ZF,PF) st t1, seg, riprel, disp }; def macroop SAL_1_R { - slli reg, reg, 1, flags=(SF,ZF,PF) + slli reg, reg, 1, flags=(CF,OF,SF,ZF,PF) }; def macroop SAL_1_M { ldst t1, seg, sib, disp - slli t1, t1, 1, flags=(SF,ZF,PF) + slli t1, t1, 1, flags=(CF,OF,SF,ZF,PF) st t1, seg, sib, disp }; @@ -90,19 +90,19 @@ def macroop SAL_1_P { rdip t7 ldst t1, seg, riprel, disp - slli t1, t1, 1, flags=(SF,ZF,PF) + slli t1, t1, 1, flags=(CF,OF,SF,ZF,PF) st t1, seg, riprel, disp }; def macroop SAL_R_R { - sll reg, reg, regm, flags=(SF,ZF,PF) + sll reg, reg, regm, flags=(CF,OF,SF,ZF,PF) }; def macroop SAL_M_R { ldst t1, seg, sib, disp - sll t1, t1, reg, flags=(SF,ZF,PF) + sll t1, t1, reg, flags=(CF,OF,SF,ZF,PF) st t1, seg, sib, disp }; @@ -110,19 +110,19 @@ def macroop SAL_P_R { rdip t7 ldst t1, seg, riprel, disp - sll t1, t1, reg, flags=(SF,ZF,PF) + sll t1, t1, reg, flags=(CF,OF,SF,ZF,PF) st t1, seg, riprel, disp }; def macroop SHR_R_I { - srli reg, reg, imm, flags=(SF,ZF,PF) + srli reg, reg, imm, flags=(CF,OF,SF,ZF,PF) }; def macroop SHR_M_I { ldst t1, seg, sib, disp - srli t1, t1, imm, flags=(SF,ZF,PF) + srli t1, t1, imm, flags=(CF,OF,SF,ZF,PF) st t1, seg, sib, disp }; @@ -130,19 +130,19 @@ def macroop SHR_P_I { rdip t7 ldst t1, seg, riprel, disp - srli t1, t1, imm, flags=(SF,ZF,PF) + srli t1, t1, imm, flags=(CF,OF,SF,ZF,PF) st t1, seg, riprel, disp }; def macroop SHR_1_R { - srli reg, reg, 1, flags=(SF,ZF,PF) + srli reg, reg, 1, flags=(CF,OF,SF,ZF,PF) }; def macroop SHR_1_M { ldst t1, seg, sib, disp - srli t1, t1, 1, flags=(SF,ZF,PF) + srli t1, t1, 1, flags=(CF,OF,SF,ZF,PF) st t1, seg, sib, disp }; @@ -150,19 +150,19 @@ def macroop SHR_1_P { rdip t7 ldst t1, seg, riprel, disp - srli t1, t1, 1, flags=(SF,ZF,PF) + srli t1, t1, 1, flags=(CF,OF,SF,ZF,PF) st t1, seg, riprel, disp }; def macroop SHR_R_R { - srl reg, reg, regm, flags=(SF,ZF,PF) + srl reg, reg, regm, flags=(CF,OF,SF,ZF,PF) }; def macroop SHR_M_R { ldst t1, seg, sib, disp - srl t1, t1, reg, flags=(SF,ZF,PF) + srl t1, t1, reg, flags=(CF,OF,SF,ZF,PF) st t1, seg, sib, disp }; @@ -170,19 +170,54 @@ def macroop SHR_P_R { rdip t7 ldst t1, seg, riprel, disp - srl t1, t1, reg, flags=(SF,ZF,PF) + srl t1, t1, reg, flags=(CF,OF,SF,ZF,PF) + st t1, seg, riprel, disp +}; + +# SHRD will not set OF correctly when the shift count is 1. +def macroop SHRD_R_R_I +{ + srli t1, reg, imm, flags=(CF,) + rori t2, regm, imm + srli t3, regm, imm + xor t2, t2, t3 + or reg, t1, t2 +}; + +# SHRD will not set OF correctly when the shift count is 1. +def macroop SHRD_M_R_I +{ + ldst t1, seg, sib, disp + srli t1, t1, imm, flags=(CF,) + rori t2, reg, imm + srli t3, reg, imm + xor t2, t2, t3 + or t1, t1, t2 + st t1, seg, sib, disp +}; + +# SHRD will not set OF correctly when the shift count is 1. +def macroop SHRD_P_R_I +{ + rdip t7 + ldst t1, seg, riprel, disp + srli t1, t1, imm, flags=(CF,) + rori t2, reg, imm + srli t3, reg, imm + xor t2, t2, t3 + or t1, t1, t2 st t1, seg, riprel, disp }; def macroop SAR_R_I { - srai reg, reg, imm, flags=(SF,ZF,PF) + srai reg, reg, imm, flags=(CF,OF,SF,ZF,PF) }; def macroop SAR_M_I { ldst t1, seg, sib, disp - srai t1, t1, imm, flags=(SF,ZF,PF) + srai t1, t1, imm, flags=(CF,OF,SF,ZF,PF) st t1, seg, sib, disp }; @@ -190,19 +225,19 @@ def macroop SAR_P_I { rdip t7 ldst t1, seg, riprel, disp - srai t1, t1, imm, flags=(SF,ZF,PF) + srai t1, t1, imm, flags=(CF,OF,SF,ZF,PF) st t1, seg, riprel, disp }; def macroop SAR_1_R { - srai reg, reg, 1, flags=(SF,ZF,PF) + srai reg, reg, 1, flags=(CF,OF,SF,ZF,PF) }; def macroop SAR_1_M { ldst t1, seg, sib, disp - srai t1, t1, 1, flags=(SF,ZF,PF) + srai t1, t1, 1, flags=(CF,OF,SF,ZF,PF) st t1, seg, sib, disp }; @@ -210,19 +245,19 @@ def macroop SAR_1_P { rdip t7 ldst t1, seg, riprel, disp - srai t1, t1, 1, flags=(SF,ZF,PF) + srai t1, t1, 1, flags=(CF,OF,SF,ZF,PF) st t1, seg, riprel, disp }; def macroop SAR_R_R { - sra reg, reg, regm, flags=(SF,ZF,PF) + sra reg, reg, regm, flags=(CF,OF,SF,ZF,PF) }; def macroop SAR_M_R { ldst t1, seg, sib, disp - sra t1, t1, reg, flags=(SF,ZF,PF) + sra t1, t1, reg, flags=(CF,OF,SF,ZF,PF) st t1, seg, sib, disp }; @@ -230,7 +265,7 @@ def macroop SAR_P_R { rdip t7 ldst t1, seg, riprel, disp - sra t1, t1, reg, flags=(SF,ZF,PF) + sra t1, t1, reg, flags=(CF,OF,SF,ZF,PF) st t1, seg, riprel, disp }; ''' diff --git a/src/arch/x86/isa/insts/general_purpose/semaphores.py b/src/arch/x86/isa/insts/general_purpose/semaphores.py index 27a31dbd9..f23241863 100644 --- a/src/arch/x86/isa/insts/general_purpose/semaphores.py +++ b/src/arch/x86/isa/insts/general_purpose/semaphores.py @@ -78,10 +78,30 @@ def macroop CMPXCHG_P_R { st t1, seg, riprel, disp mov rax, rax, t1, flags=(nCZF,) }; + +def macroop XADD_M_R { + ldst t1, seg, sib, disp + add t2, t1, reg, flags=(OF,SF,ZF,AF,PF,CF) + st t2, seg, sib, disp + mov reg, reg, t1 +}; + +def macroop XADD_P_R { + rdip t7 + ldst t1, seg, riprel, disp + add t2, t1, reg, flags=(OF,SF,ZF,AF,PF,CF) + st t2, seg, riprel, disp + mov reg, reg, t1 +}; + +def macroop XADD_R_R { + add t2, regm, reg, flags=(OF,SF,ZF,AF,PF,CF) + mov regm, regm, reg + mov reg, reg, t2 +}; + ''' #let {{ -# class XADD(Inst): -# "GenFault ${new UnimpInstFault}" # class XCHG(Inst): -# "GenFault ${new UnimpInstFault}" +# "GenFault ${new UnimpInstFault}" #}}; diff --git a/src/arch/x86/isa/insts/general_purpose/string/compare_strings.py b/src/arch/x86/isa/insts/general_purpose/string/compare_strings.py index 71b8511b4..561b8a415 100644 --- a/src/arch/x86/isa/insts/general_purpose/string/compare_strings.py +++ b/src/arch/x86/isa/insts/general_purpose/string/compare_strings.py @@ -1,4 +1,4 @@ -# Copyright (c) 2007 The Hewlett-Packard Development Company +# Copyright (c) 2007-2008 The Hewlett-Packard Development Company # All rights reserved. # # Redistribution and use of this software in source and binary forms, @@ -75,12 +75,16 @@ def macroop CMPS_M_M { # def macroop CMPS_E_M_M { + and t0, rcx, rcx, flags=(EZF,), dataSize=asz + br label("end"), flags=(CEZF,) + # Find the constant we need to either add or subtract from rdi ruflag t0, 10 movi t3, t3, dsz, flags=(CEZF,), dataSize=asz subi t4, t0, dsz, dataSize=asz mov t3, t3, t4, flags=(nCEZF,), dataSize=asz +topOfLoop: ld t1, seg, [1, t0, rsi] ld t2, es, [1, t0, rdi] sub t0, t1, t2, flags=(OF, SF, ZF, AF, PF, CF) @@ -88,17 +92,22 @@ def macroop CMPS_E_M_M { subi rcx, rcx, 1, flags=(EZF,), dataSize=asz add rdi, rdi, t3, dataSize=asz add rsi, rsi, t3, dataSize=asz - bri t0, 4, flags=(CSTRZnEZF,) + br label("topOfLoop"), flags=(CSTRZnEZF,) +end: fault "NoFault" }; def macroop CMPS_N_M_M { + and t0, rcx, rcx, flags=(EZF,), dataSize=asz + br label("end"), flags=(CEZF,) + # Find the constant we need to either add or subtract from rdi ruflag t0, 10 movi t3, t3, dsz, flags=(CEZF,), dataSize=asz subi t4, t0, dsz, dataSize=asz mov t3, t3, t4, flags=(nCEZF,), dataSize=asz +topOfLoop: ld t1, seg, [1, t0, rsi] ld t2, es, [1, t0, rdi] sub t0, t1, t2, flags=(OF, SF, ZF, AF, PF, CF) @@ -106,7 +115,8 @@ def macroop CMPS_N_M_M { subi rcx, rcx, 1, flags=(EZF,), dataSize=asz add rdi, rdi, t3, dataSize=asz add rsi, rsi, t3, dataSize=asz - bri t0, 4, flags=(CSTRnZnEZF,) + br label("topOfLoop"), flags=(CSTRnZnEZF,) +end: fault "NoFault" }; ''' diff --git a/src/arch/x86/isa/insts/general_purpose/string/load_string.py b/src/arch/x86/isa/insts/general_purpose/string/load_string.py index 61525c2f2..14198701a 100644 --- a/src/arch/x86/isa/insts/general_purpose/string/load_string.py +++ b/src/arch/x86/isa/insts/general_purpose/string/load_string.py @@ -1,4 +1,4 @@ -# Copyright (c) 2007 The Hewlett-Packard Development Company +# Copyright (c) 2007-2008 The Hewlett-Packard Development Company # All rights reserved. # # Redistribution and use of this software in source and binary forms, @@ -61,12 +61,14 @@ def macroop LODS_M { subi t4, t0, dsz, dataSize=asz mov t3, t3, t4, flags=(nCEZF,), dataSize=asz - ld rax, seg, [1, t0, rdi] + ld rax, seg, [1, t0, rsi] - add rdi, rdi, t3, dataSize=asz + add rsi, rsi, t3, dataSize=asz }; def macroop LODS_E_M { + and t0, rcx, rcx, flags=(EZF,), dataSize=asz + br label("end"), flags=(CEZF,) # Find the constant we need to either add or subtract from rdi ruflag t0, 10 movi t3, t3, dsz, flags=(CEZF,), dataSize=asz @@ -74,11 +76,12 @@ def macroop LODS_E_M { mov t3, t3, t4, flags=(nCEZF,), dataSize=asz topOfLoop: - ld rax, seg, [1, t0, rdi] + ld rax, seg, [1, t0, rsi] subi rcx, rcx, 1, flags=(EZF,), dataSize=asz - add rdi, rdi, t3, dataSize=asz - bri t0, label("topOfLoop"), flags=(nCEZF,) + add rsi, rsi, t3, dataSize=asz + br label("topOfLoop"), flags=(nCEZF,) +end: fault "NoFault" }; ''' diff --git a/src/arch/x86/isa/insts/general_purpose/string/move_string.py b/src/arch/x86/isa/insts/general_purpose/string/move_string.py index b64acfdc2..18faa38e2 100644 --- a/src/arch/x86/isa/insts/general_purpose/string/move_string.py +++ b/src/arch/x86/isa/insts/general_purpose/string/move_string.py @@ -1,4 +1,4 @@ -# Copyright (c) 2007 The Hewlett-Packard Development Company +# Copyright (c) 2007-2008 The Hewlett-Packard Development Company # All rights reserved. # # Redistribution and use of this software in source and binary forms, @@ -69,6 +69,8 @@ def macroop MOVS_M_M { }; def macroop MOVS_E_M_M { + and t0, rcx, rcx, flags=(EZF,), dataSize=asz + br label("end"), flags=(CEZF,) # Find the constant we need to either add or subtract from rdi ruflag t0, 10 movi t3, t3, dsz, flags=(CEZF,), dataSize=asz @@ -82,7 +84,8 @@ topOfLoop: subi rcx, rcx, 1, flags=(EZF,), dataSize=asz add rdi, rdi, t3, dataSize=asz add rsi, rsi, t3, dataSize=asz - bri t0, label("topOfLoop"), flags=(nCEZF,) + br label("topOfLoop"), flags=(nCEZF,) +end: fault "NoFault" }; ''' diff --git a/src/arch/x86/isa/insts/general_purpose/string/scan_string.py b/src/arch/x86/isa/insts/general_purpose/string/scan_string.py index b038cc00a..5b0e74aad 100644 --- a/src/arch/x86/isa/insts/general_purpose/string/scan_string.py +++ b/src/arch/x86/isa/insts/general_purpose/string/scan_string.py @@ -1,4 +1,4 @@ -# Copyright (c) 2007 The Hewlett-Packard Development Company +# Copyright (c) 2007-2008 The Hewlett-Packard Development Company # All rights reserved. # # Redistribution and use of this software in source and binary forms, @@ -73,34 +73,44 @@ def macroop SCAS_M { # def macroop SCAS_E_M { + and t0, rcx, rcx, flags=(EZF,), dataSize=asz + br label("end"), flags=(CEZF,) + # Find the constant we need to either add or subtract from rdi ruflag t0, 10 movi t2, t2, dsz, flags=(CEZF,), dataSize=asz subi t3, t0, dsz, dataSize=asz mov t2, t2, t3, flags=(nCEZF,), dataSize=asz +topOfLoop: ld t1, es, [1, t0, rdi] sub t0, t1, rax, flags=(OF, SF, ZF, AF, PF, CF) subi rcx, rcx, 1, flags=(EZF,), dataSize=asz add rdi, rdi, t2, dataSize=asz - bri t0, 4, flags=(CSTRZnEZF,) + br label("topOfLoop"), flags=(CSTRZnEZF,) +end: fault "NoFault" }; def macroop SCAS_N_M { + and t0, rcx, rcx, flags=(EZF,), dataSize=asz + br label("end"), flags=(CEZF,) + # Find the constant we need to either add or subtract from rdi ruflag t0, 10 movi t2, t2, dsz, flags=(CEZF,), dataSize=asz subi t3, t0, dsz, dataSize=asz mov t2, t2, t3, flags=(nCEZF,), dataSize=asz +topOfLoop: ld t1, es, [1, t0, rdi] sub t0, t1, rax, flags=(OF, SF, ZF, AF, PF, CF) subi rcx, rcx, 1, flags=(EZF,), dataSize=asz add rdi, rdi, t2, dataSize=asz - bri t0, 4, flags=(CSTRnZnEZF,) + br label("topOfLoop"), flags=(CSTRnZnEZF,) +end: fault "NoFault" }; diff --git a/src/arch/x86/isa/insts/general_purpose/string/store_string.py b/src/arch/x86/isa/insts/general_purpose/string/store_string.py index a8d558929..fe9917ce6 100644 --- a/src/arch/x86/isa/insts/general_purpose/string/store_string.py +++ b/src/arch/x86/isa/insts/general_purpose/string/store_string.py @@ -1,4 +1,4 @@ -# Copyright (c) 2007 The Hewlett-Packard Development Company +# Copyright (c) 2007-2008 The Hewlett-Packard Development Company # All rights reserved. # # Redistribution and use of this software in source and binary forms, @@ -67,6 +67,8 @@ def macroop STOS_M { }; def macroop STOS_E_M { + and t0, rcx, rcx, flags=(EZF,), dataSize=asz + br label("end"), flags=(CEZF,) # Find the constant we need to either add or subtract from rdi ruflag t0, 10 movi t3, t3, dsz, flags=(CEZF,), dataSize=asz @@ -78,7 +80,8 @@ topOfLoop: subi rcx, rcx, 1, flags=(EZF,), dataSize=asz add rdi, rdi, t3, dataSize=asz - bri t0, label("topOfLoop"), flags=(nCEZF,) + br label("topOfLoop"), flags=(nCEZF,) +end: fault "NoFault" }; ''' diff --git a/src/arch/x86/isa/insts/general_purpose/system_calls.py b/src/arch/x86/isa/insts/general_purpose/system_calls.py index e056bea84..67607d5f8 100644 --- a/src/arch/x86/isa/insts/general_purpose/system_calls.py +++ b/src/arch/x86/isa/insts/general_purpose/system_calls.py @@ -53,14 +53,183 @@ # # Authors: Gabe Black -microcode = "" +microcode = ''' +def macroop SYSCALL_64 +{ + # All 1s. + limm t1, "(uint64_t)(-1)" + + # Save the next RIP. + rdip rcx + + # Stick rflags with RF masked into r11. + rflags t2 + limm t3, "~RFBit" + andi r11, t2, t3, dataSize=8 + + rdval t3, star + srli t3, t3, 32, dataSize=8 + andi t3, t3, 0xFC, dataSize=1 + + # Set up CS. + wrsel cs, t3 + wrbase cs, t0, dataSize=8 + wrlimit cs, t1, dataSize=4 + # Not writable, read/execute-able, not expandDown, + # dpl=0, defaultSize=0, long mode + limm t4, ((0 << 0) | (1 << 1) | (0 << 2) | \ + (0 << 3) | (0 << 5) | (1 << 6)) + wrattr cs, t4 + + # Set up SS. + addi t3, t3, 8 + wrsel ss, t3 + wrbase ss, t0, dataSize=8 + wrlimit ss, t1, dataSize=4 + # Writable, readable, not expandDown, + # dpl=0, defaultSize=0, not long mode + limm t4, ((1 << 0) | (1 << 1) | (0 << 2) | \ + (0 << 3) | (0 << 5) | (0 << 6)) + wrattr ss, t4 + + # Set the new rip. + rdval t7, lstar + wrip t0, t7 + + # Mask the flags against sf_mask and leave RF turned off. + rdval t3, sf_mask, dataSize=8 + xor t3, t3, t1, dataSize=8 + and t3, t3, r11, dataSize=8 + wrflags t3, t0 +}; + +def macroop SYSCALL_COMPAT +{ + # All 1s. + limm t1, "(uint64_t)(-1)" + + # Save the next RIP. + rdip rcx + + # Stick rflags with RF masked into r11. + rflags t2 + limm t3, "~RFBit" + andi r11, t2, t3, dataSize=8 + + rdval t3, star + srli t3, t3, 32, dataSize=8 + andi t3, t3, 0xFC, dataSize=1 + + # Set up CS. + wrsel cs, t3 + wrbase cs, t0, dataSize=8 + wrlimit cs, t1, dataSize=4 + # Not writable, read/execute-able, not expandDown, + # dpl=0, defaultSize=0, long mode + limm t4, ((0 << 0) | (1 << 1) | (0 << 2) | \ + (0 << 3) | (0 << 5) | (1 << 6)) + wrattr cs, t4 + + # Set up SS. + addi t3, t3, 8 + wrsel ss, t3 + wrbase ss, t0, dataSize=8 + wrlimit ss, t1, dataSize=4 + # Writable, readable, not expandDown, + # dpl=0, defaultSize=0, not long mode + limm t4, ((1 << 0) | (1 << 1) | (0 << 2) | \ + (0 << 3) | (0 << 5) | (0 << 6)) + wrattr ss, t4 + + # Set the new rip. + rdval t7, cstar + wrip t0, t7 + + # Mask the flags against sf_mask and leave RF turned off. + rdval t3, sf_mask, dataSize=8 + xor t3, t3, t1, dataSize=8 + and t3, t3, r11, dataSize=8 + wrflags t3, t0 +}; + +def macroop SYSCALL_LEGACY +{ + panic "The syscall instruction isn't implemented in legacy mode." +}; + +def macroop SYSRET_TO_64 +{ + # All 1s. + limm t1, "(uint64_t)(-1)" + + rdval t3, star + srli t3, t3, 48, dataSize=8 + ori t3, t3, 3, dataSize=1 + + # Set rflags to r11 with RF and VM cleared. + limm t4, "~(RFBit | VMBit)" + and t4, t4, r11, dataSize=8 + wrflags t4, t0 + + # Set up CS. + addi t4, t3, 16, dataSize=8 + wrsel cs, t4 + wrbase cs, t0, dataSize=8 + wrlimit cs, t1, dataSize=4 + # Not writable, read/execute-able, not expandDown, + # dpl=3, defaultSize=0, long mode + limm t4, ((0 << 0) | (1 << 1) | (0 << 2) | \ + (3 << 3) | (0 << 5) | (1 << 6)) + wrattr cs, t4 + + # Only the selector is changed for SS. + addi t4, t3, 8, dataSize=8 + wrsel ss, t4 + + # Set the RIP back. + wrip rcx, t0, dataSize=8 +}; + +def macroop SYSRET_TO_COMPAT +{ + # All 1s. + limm t1, "(uint64_t)(-1)" + + rdval t3, star + srli t3, t3, 48, dataSize=8 + ori t3, t3, 3, dataSize=1 + + # Set rflags to r11 with RF and VM cleared. + limm t4, "~(RFBit | VMBit)" + and t4, t4, r11, dataSize=8 + wrflags t4, t0 + + # Set up CS. + wrsel cs, t3 + wrbase cs, t0, dataSize=8 + wrlimit cs, t1, dataSize=4 + # Not writable, read/execute-able, not expandDown, + # dpl=3, defaultSize=1, not long mode + limm t4, ((0 << 0) | (1 << 1) | (0 << 2) | \ + (3 << 3) | (1 << 5) | (0 << 6)) + wrattr cs, t4 + + # Only the selector is changed for SS. + addi t4, t3, 8, dataSize=8 + wrsel ss, t4 + + # Set the RIP back. + wrip rcx, t0, dataSize=8 +}; + +def macroop SYSRET_NON_64 +{ + panic "The sysret instruction isn't implemented in legacy mode." +}; +''' #let {{ # class SYSENTER(Inst): -# "GenFault ${new UnimpInstFault}" +# "GenFault ${new UnimpInstFault}" # class SYSEXIT(Inst): -# "GenFault ${new UnimpInstFault}" -# class SYSCALL(Inst): -# "GenFault ${new UnimpInstFault}" -# class SYSRET(Inst): -# "GenFault ${new UnimpInstFault}" +# "GenFault ${new UnimpInstFault}" #}}; diff --git a/src/arch/x86/isa/insts/romutil.py b/src/arch/x86/isa/insts/romutil.py new file mode 100644 index 000000000..e47259eb3 --- /dev/null +++ b/src/arch/x86/isa/insts/romutil.py @@ -0,0 +1,212 @@ +# Copyright (c) 2008 The Regents of The University of Michigan +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: 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 holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# 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 + +intCodeTemplate = ''' +def rom +{ + # This vectors the CPU into an interrupt handler in long mode. + # On entry, t1 is set to the vector of the interrupt and t7 is the current + # ip. We need that because rdip returns the next ip. + extern %(startLabel)s: + + # + # Get the 64 bit interrupt or trap gate descriptor from the IDT + # + + # Load the gate descriptor from the IDT + slli t4, t1, 4, dataSize=8 + ld t2, idtr, [1, t0, t4], 8, dataSize=8, addressSize=8, atCPL0=True + ld t4, idtr, [1, t0, t4], dataSize=8, addressSize=8, atCPL0=True + + # Make sure the descriptor is a legal gate. + chks t1, t4, %(gateCheckType)s + + # + # Get the target CS descriptor using the selector in the gate + # descriptor. + # + srli t10, t4, 16, dataSize=8 + andi t5, t10, 0xF8, dataSize=8 + andi t0, t10, 0x4, flags=(EZF,), dataSize=2 + br rom_local_label("%(startLabel)s_globalDescriptor"), flags=(CEZF,) + ld t3, tsl, [1, t0, t5], dataSize=8, addressSize=8, atCPL0=True + br rom_local_label("%(startLabel)s_processDescriptor") +%(startLabel)s_globalDescriptor: + ld t3, tsg, [1, t0, t5], dataSize=8, addressSize=8, atCPL0=True +%(startLabel)s_processDescriptor: + chks t10, t3, IntCSCheck, dataSize=8 + wrdl hs, t3, t10, dataSize=8 + + # Stick the target offset in t9. + wrdh t9, t4, t2, dataSize=8 + + + # + # Figure out where the stack should be + # + + # Record what we might set the stack selector to. + rdsel t11, ss + + # Check if we're changing privelege level. At this point we can assume + # we're going to a DPL that's less than or equal to the CPL. + rdattr t10, hs, dataSize=8 + srli t10, t10, 3, dataSize=8 + andi t10, t10, 3, dataSize=8 + rdattr t5, cs, dataSize=8 + srli t5, t5, 3, dataSize=8 + andi t5, t5, 0x3, dataSize=8 + sub t0, t5, t10, flags=(EZF,), dataSize=8 + # We're going to change priviledge, so zero out the stack selector. We + # need to let the IST have priority so we don't branch yet. + wrsel t11, t0, flags=(nCEZF,) + + # Check the IST field of the gate descriptor + srli t12, t4, 32, dataSize=8 + andi t12, t12, 0x7, dataSize=8 + subi t0, t12, 1, flags=(ECF,), dataSize=8 + br rom_local_label("%(startLabel)s_istStackSwitch"), flags=(nCECF,) + br rom_local_label("%(startLabel)s_cplStackSwitch"), flags=(nCEZF,) + + # If we're here, it's because the stack isn't being switched. + # Set t6 to the new aligned rsp. + mov t6, t6, rsp, dataSize=8 + br rom_local_label("%(startLabel)s_stackSwitched") + +%(startLabel)s_istStackSwitch: + ld t6, tr, [8, t12, t0], 0x1c, dataSize=8, addressSize=8, atCPL0=True + br rom_local_label("%(startLabel)s_stackSwitched") + +%(startLabel)s_cplStackSwitch: + # Get the new rsp from the TSS + ld t6, tr, [8, t10, t0], 4, dataSize=8, addressSize=8, atCPL0=True + +%(startLabel)s_stackSwitched: + + andi t6, t6, 0xF0, dataSize=1 + subi t6, t6, 40 + %(errorCodeSize)d, dataSize=8 + + ## + ## Point of no return. + ## We're now going to irrevocably modify visible state. + ## Anything bad that's going to happen should have happened by now or will + ## happen right now. + ## + wrip t0, t9, dataSize=8 + + # + # Set up the target code segment. Do this now so we have the right + # permissions when setting up the stack frame. + # + srli t5, t4, 16, dataSize=8 + andi t5, t5, 0xFF, dataSize=8 + wrdl cs, t3, t5, dataSize=8 + # Tuck away the old CS for use below + limm t10, 0, dataSize=8 + rdsel t10, cs, dataSize=2 + wrsel cs, t5, dataSize=2 + + # Check that we can access everything we need to on the stack + ldst t0, hs, [1, t0, t6], dataSize=8, addressSize=8 + ldst t0, hs, [1, t0, t6], \ + 32 + %(errorCodeSize)d, dataSize=8, addressSize=8 + + + # + # Build up the interrupt stack frame + # + + + # Write out the contents of memory + %(errorCodeCode)s + st t7, hs, [1, t0, t6], %(errorCodeSize)d, dataSize=8, addressSize=8 + st t10, hs, [1, t0, t6], 8 + %(errorCodeSize)d, dataSize=8, addressSize=8 + rflags t10, dataSize=8 + st t10, hs, [1, t0, t6], 16 + %(errorCodeSize)d, dataSize=8, addressSize=8 + st rsp, hs, [1, t0, t6], 24 + %(errorCodeSize)d, dataSize=8, addressSize=8 + rdsel t5, ss, dataSize=2 + st t5, hs, [1, t0, t6], 32 + %(errorCodeSize)d, dataSize=8, addressSize=8 + + # Set the stack segment + mov rsp, rsp, t6, dataSize=8 + wrsel ss, t11, dataSize=2 + + # + # Adjust rflags which is still in t10 from above + # + + # Set IF to the lowest bit of the original gate type. + # The type field of the original gate starts at bit 40. + + # Set the TF, NT, and RF bits. We'll flip them at the end. + limm t6, (1 << 8) | (1 << 14) | (1 << 16) + or t10, t10, t6 + srli t5, t4, 40, dataSize=8 + srli t7, t10, 9, dataSize=8 + xor t5, t7, t5, dataSize=8 + andi t5, t5, 1, dataSize=8 + slli t5, t5, 9, dataSize=8 + or t6, t5, t6, dataSize=8 + + # Put the results into rflags + wrflags t6, t10 + + eret +}; +''' + +microcode = \ +intCodeTemplate % {\ + "startLabel" : "longModeInterrupt", + "gateCheckType" : "IntGateCheck", + "errorCodeSize" : 0, + "errorCodeCode" : "" +} + \ +intCodeTemplate % {\ + "startLabel" : "longModeSoftInterrupt", + "gateCheckType" : "SoftIntGateCheck", + "errorCodeSize" : 0, + "errorCodeCode" : "" +} + \ +intCodeTemplate % {\ + "startLabel" : "longModeInterruptWithError", + "gateCheckType" : "IntGateCheck", + "errorCodeSize" : 8, + "errorCodeCode" : ''' + st t15, hs, [1, t0, t6], dataSize=8, addressSize=8 + ''' +} + \ +''' +def rom +{ + # This vectors the CPU into an interrupt handler in legacy mode. + extern legacyModeInterrupt: + panic "Legacy mode interrupts not implemented (in microcode)" + eret +}; +''' diff --git a/src/arch/x86/isa/insts/system/__init__.py b/src/arch/x86/isa/insts/system/__init__.py index 409a929f5..0dec9ebda 100644 --- a/src/arch/x86/isa/insts/system/__init__.py +++ b/src/arch/x86/isa/insts/system/__init__.py @@ -81,7 +81,8 @@ # # Authors: Gabe Black -categories = ["halt", +categories = ["control_registers", + "halt", "invlpg", "undefined_operation", "msrs", diff --git a/src/arch/x86/isa/insts/system/control_registers.py b/src/arch/x86/isa/insts/system/control_registers.py new file mode 100644 index 000000000..902c01abb --- /dev/null +++ b/src/arch/x86/isa/insts/system/control_registers.py @@ -0,0 +1,35 @@ +# Copyright (c) 2009 The Regents of The University of Michigan +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: 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 holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# 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 CLTS { + rdcr t1, 0, dataSize=8 + andi t1, t1, 0xF7, dataSize=1 + wrcr 0, t1, dataSize=8 +}; +''' diff --git a/src/arch/x86/isa/insts/system/msrs.py b/src/arch/x86/isa/insts/system/msrs.py index 1acb4c792..7f283c8c1 100644 --- a/src/arch/x86/isa/insts/system/msrs.py +++ b/src/arch/x86/isa/insts/system/msrs.py @@ -84,8 +84,8 @@ microcode = ''' def macroop RDMSR { - limm t1, "IntAddrPrefixMSR >> 3" - ld t2, intseg, [8, t1, rcx], dataSize=8, addressSize=4 + ld t2, intseg, [8, rcx, t0], "IntAddrPrefixMSR << 3", \ + dataSize=8, addressSize=8 mov rax, rax, t2, dataSize=4 srli t2, t2, 32, dataSize=8 mov rdx, rdx, t2, dataSize=4 @@ -93,10 +93,18 @@ def macroop RDMSR def macroop WRMSR { - limm t1, "IntAddrPrefixMSR >> 3" mov t2, t2, rax, dataSize=4 slli t3, rdx, 32, dataSize=8 or t2, t2, t3, dataSize=8 - st t2, intseg, [8, t1, rcx], dataSize=8, addressSize=4 + st t2, intseg, [8, rcx, t0], "IntAddrPrefixMSR << 3", \ + dataSize=8, addressSize=8 +}; + +def macroop RDTSC +{ + rdtsc t1 + mov rax, rax, t1, dataSize=4 + srli t1, t1, 32, dataSize=8 + mov rdx, rdx, t1, dataSize=4 }; ''' diff --git a/src/arch/x86/isa/insts/system/segmentation.py b/src/arch/x86/isa/insts/system/segmentation.py index 97846f79c..acbca9f6e 100644 --- a/src/arch/x86/isa/insts/system/segmentation.py +++ b/src/arch/x86/isa/insts/system/segmentation.py @@ -56,7 +56,7 @@ microcode = ''' def macroop LGDT_M { - .adjust_env oszForPseudoDesc + .adjust_env maxOsz # Get the limit ld t1, seg, sib, disp, dataSize=2 @@ -68,7 +68,7 @@ def macroop LGDT_M def macroop LGDT_P { - .adjust_env oszForPseudoDesc + .adjust_env maxOsz rdip t7 # Get the limit @@ -86,34 +86,34 @@ def macroop LGDT_P def macroop LGDT_16_M { - .adjust_env oszForPseudoDesc + .adjust_env maxOsz # Get the limit ld t1, seg, sib, disp, dataSize=2 # Get the base ld t2, seg, sib, 'adjustedDisp + 2', dataSize=4 - zexti t2, t2, 23 + zexti t2, t2, 23, dataSize=8 wrbase tsg, t2 wrlimit tsg, t1 }; def macroop LGDT_16_P { - .adjust_env oszForPseudoDesc + .adjust_env maxOsz rdip t7 # Get the limit ld t1, seg, riprel, disp, dataSize=2 # Get the base ld t2, seg, riprel, 'adjustedDisp + 2', dataSize=4 - zexti t2, t2, 23 + zexti t2, t2, 23, dataSize=8 wrbase tsg, t2 wrlimit tsg, t1 }; def macroop LIDT_M { - .adjust_env oszForPseudoDesc + .adjust_env maxOsz # Get the limit ld t1, seg, sib, disp, dataSize=2 @@ -125,7 +125,7 @@ def macroop LIDT_M def macroop LIDT_P { - .adjust_env oszForPseudoDesc + .adjust_env maxOsz rdip t7 # Get the limit @@ -143,28 +143,135 @@ def macroop LIDT_P def macroop LIDT_16_M { - .adjust_env oszForPseudoDesc + .adjust_env maxOsz # Get the limit ld t1, seg, sib, disp, dataSize=2 # Get the base ld t2, seg, sib, 'adjustedDisp + 2', dataSize=4 - zexti t2, t2, 23 + zexti t2, t2, 23, dataSize=8 wrbase idtr, t2 wrlimit idtr, t1 }; def macroop LIDT_16_P { - .adjust_env oszForPseudoDesc + .adjust_env maxOsz rdip t7 # Get the limit ld t1, seg, riprel, disp, dataSize=2 # Get the base ld t2, seg, riprel, 'adjustedDisp + 2', dataSize=4 - zexti t2, t2, 23 + zexti t2, t2, 23, dataSize=8 wrbase idtr, t2 wrlimit idtr, t1 }; + +def macroop LTR_R +{ + chks reg, t0, TRCheck + limm t4, 0 + srli t4, reg, 3, dataSize=2 + ldst t1, tsg, [8, t4, t0], dataSize=8 + ld t2, tsg, [8, t4, t0], 8, dataSize=8 + chks reg, t1, TSSCheck + wrdh t3, t1, t2 + wrdl tr, t1, reg + wrbase tr, t3, dataSize=8 + ori t1, t1, (1 << 9) + st t1, tsg, [8, t4, t0], dataSize=8 +}; + +def macroop LTR_M +{ + ld t5, seg, sib, disp, dataSize=2 + chks t5, t0, TRCheck + limm t4, 0 + srli t4, t5, 3, dataSize=2 + ldst t1, tsg, [8, t4, t0], dataSize=8 + ld t2, tsg, [8, t4, t0], 8, dataSize=8 + chks t5, t1, TSSCheck + wrdh t3, t1, t2 + wrdl tr, t1, t5 + wrbase tr, t3, dataSize=8 + ori t1, t1, (1 << 9) + st t1, tsg, [8, t4, t0], dataSize=8 +}; + +def macroop LTR_P +{ + rdip t7 + ld t5, seg, riprel, disp, dataSize=2 + chks t5, t0, TRCheck + limm t4, 0 + srli t4, t5, 3, dataSize=2 + ldst t1, tsg, [8, t4, t0], dataSize=8 + ld t2, tsg, [8, t4, t0], 8, dataSize=8 + chks t5, t1, TSSCheck + wrdh t3, t1, t2 + wrdl tr, t1, t5 + wrbase tr, t3, dataSize=8 + ori t1, t1, (1 << 9) + st t1, tsg, [8, t4, t0], dataSize=8 +}; + +def macroop LLDT_R +{ + chks reg, t0, InGDTCheck, flags=(EZF,) + br label("end"), flags=(CEZF,) + limm t4, 0 + srli t4, reg, 3, dataSize=2 + ldst t1, tsg, [8, t4, t0], dataSize=8 + ld t2, tsg, [8, t4, t0], 8, dataSize=8 + chks reg, t1, LDTCheck + wrdh t3, t1, t2 + wrdl tr, t1, reg + wrbase tr, t3, dataSize=8 +end: + fault "NoFault" +}; + +def macroop LLDT_M +{ + ld t5, seg, sib, disp, dataSize=2 + chks t5, t0, InGDTCheck, flags=(EZF,) + br label("end"), flags=(CEZF,) + limm t4, 0 + srli t4, t5, 3, dataSize=2 + ldst t1, tsg, [8, t4, t0], dataSize=8 + ld t2, tsg, [8, t4, t0], 8, dataSize=8 + chks t5, t1, LDTCheck + wrdh t3, t1, t2 + wrdl tr, t1, t5 + wrbase tr, t3, dataSize=8 +end: + fault "NoFault" +}; + +def macroop LLDT_P +{ + rdip t7 + ld t5, seg, riprel, disp, dataSize=2 + chks t5, t0, InGDTCheck, flags=(EZF,) + br label("end"), flags=(CEZF,) + limm t4, 0 + srli t4, t5, 3, dataSize=2 + ldst t1, tsg, [8, t4, t0], dataSize=8 + ld t2, tsg, [8, t4, t0], 8, dataSize=8 + chks t5, t1, LDTCheck + wrdh t3, t1, t2 + wrdl tr, t1, t5 + wrbase tr, t3, dataSize=8 +end: + fault "NoFault" +}; + +def macroop SWAPGS +{ + rdval t1, kernel_gs_base, dataSize=8 + rdbase t2, gs, dataSize=8 + wrbase gs, t1, dataSize=8 + wrval kernel_gs_base, t2, dataSize=8 +}; ''' diff --git a/src/arch/x86/isa/macroop.isa b/src/arch/x86/isa/macroop.isa index 4818b926c..3a836ff68 100644 --- a/src/arch/x86/isa/macroop.isa +++ b/src/arch/x86/isa/macroop.isa @@ -72,41 +72,13 @@ def template MacroExecPanic {{ output header {{ // Base class for combinationally generated macroops - class Macroop : public StaticInst + class Macroop : public X86ISA::MacroopBase { - protected: - const uint32_t numMicroops; - - //Constructor. + public: Macroop(const char *mnem, ExtMachInst _machInst, - uint32_t _numMicroops) - : StaticInst(mnem, _machInst, No_OpClass), - numMicroops(_numMicroops) - { - assert(numMicroops); - microops = new StaticInstPtr[numMicroops]; - flags[IsMacroop] = true; - } - - ~Macroop() - { - delete [] microops; - } - - StaticInstPtr * microops; - - StaticInstPtr fetchMicroop(MicroPC microPC) - { - assert(microPC < numMicroops); - return microops[microPC]; - } - - std::string generateDisassembly(Addr pc, - const SymbolTable *symtab) const - { - return mnemonic; - } - + uint32_t _numMicroops, X86ISA::EmulEnv _env) + : MacroopBase(mnem, _machInst, _numMicroops, _env) + {} %(MacroExecPanic)s }; }}; @@ -130,22 +102,42 @@ def template MacroDeclare {{ %(declareLabels)s public: // Constructor. - %(class_name)s(ExtMachInst machInst, X86ISA::EmulEnv env); + %(class_name)s(ExtMachInst machInst, X86ISA::EmulEnv _env); + + std::string + generateDisassembly(Addr pc, const SymbolTable *symtab) const; }; }; }}; +def template MacroDisassembly {{ + std::string + X86Macroop::%(class_name)s::generateDisassembly(Addr pc, + const SymbolTable *symtab) const + { + std::stringstream out; + out << mnemonic << "\t"; + + int regSize = %(regSize)s; + %(disassembly)s + // Shut up gcc. + regSize = regSize; + return out.str(); + } +}}; + // Basic instruction class constructor template. def template MacroConstructor {{ inline X86Macroop::%(class_name)s::%(class_name)s( - ExtMachInst machInst, EmulEnv env) - : %(base_class)s("%(mnemonic)s", machInst, %(num_microops)s) + ExtMachInst machInst, EmulEnv _env) + : %(base_class)s("%(mnemonic)s", machInst, %(num_microops)s, _env) { %(adjust_env)s; %(adjust_imm)s; %(adjust_disp)s; - %(do_modrm)s; + %(init_env)s; %(constructor)s; + const char *macrocodeBlock = "%(class_name)s"; //alloc_microops is the code that sets up the microops //array in the parent class. %(alloc_microops)s; @@ -174,7 +166,7 @@ let {{ } self.declared = False self.adjust_env = "" - self.doModRM = "" + self.init_env = "" self.adjust_imm = ''' uint64_t adjustedImm = IMMEDIATE; //This is to pacify gcc in case the immediate isn't used. @@ -186,7 +178,12 @@ let {{ adjustedDisp = adjustedDisp; ''' def getAllocator(self, env): - return "new X86Macroop::%s(machInst, %s)" % (self.name, env.getAllocator()) + return "new X86Macroop::%s(machInst, %s)" % \ + (self.name, env.getAllocator()) + def getMnemonic(self): + mnemonic = self.name.lower() + mnemonic = re.match(r'[^_]*', mnemonic).group(0) + return mnemonic def getDeclaration(self): #FIXME This first parameter should be the mnemonic. I need to #write some code which pulls that out @@ -194,32 +191,46 @@ let {{ for (label, microop) in self.labels.items(): declareLabels += "const static uint64_t label_%s = %d;\n" \ % (label, microop.micropc) - iop = InstObjParams(self.name, self.name, "Macroop", + iop = InstObjParams(self.getMnemonic(), self.name, "Macroop", {"code" : "", "declareLabels" : declareLabels }) return MacroDeclare.subst(iop); - def getDefinition(self): + def getDefinition(self, env): #FIXME This first parameter should be the mnemonic. I need to #write some code which pulls that out numMicroops = len(self.microops) allocMicroops = '' micropc = 0 for op in self.microops: + isLast = (micropc == numMicroops - 1) allocMicroops += \ "microops[%d] = %s;\n" % \ - (micropc, op.getAllocator(True, False, - micropc == 0, - micropc == numMicroops - 1)) + (micropc, op.getAllocator(True, not isLast, + micropc == 0, isLast)) micropc += 1 - iop = InstObjParams(self.name, self.name, "Macroop", + if env.useStackSize: + useStackSize = "true" + else: + useStackSize = "false" + if env.memoryInst: + memoryInst = "true" + else: + memoryInst = "false" + regSize = '''(%s || (env.base == INTREG_RSP && %s) ? + env.stackSize : + env.dataSize)''' % (useStackSize, memoryInst) + iop = InstObjParams(self.getMnemonic(), self.name, "Macroop", {"code" : "", "num_microops" : numMicroops, "alloc_microops" : allocMicroops, "adjust_env" : self.adjust_env, "adjust_imm" : self.adjust_imm, "adjust_disp" : self.adjust_disp, - "do_modrm" : self.doModRM}) - return MacroConstructor.subst(iop); + "disassembly" : env.disassembly, + "regSize" : regSize, + "init_env" : self.initEnv}) + return MacroConstructor.subst(iop) + \ + MacroDisassembly.subst(iop); }}; let {{ @@ -235,6 +246,16 @@ let {{ self.dataSize = "OPSIZE" self.stackSize = "STACKSIZE" self.doModRM = False + self.disassembly = "" + self.firstArgument = True + self.useStackSize = False + self.memoryInst = False + + def addToDisassembly(self, code): + if not self.firstArgument: + self.disassembly += "out << \", \";\n" + self.firstArgument = False + self.disassembly += code def getAllocator(self): if self.size == 'b': @@ -283,6 +304,7 @@ let {{ let {{ doModRMString = "env.doModRM(machInst);\n" + noModRMString = "env.setSeg(machInst);\n" def genMacroop(Name, env): blocks = OutputBlocks() if not macroopDict.has_key(Name): @@ -290,9 +312,11 @@ let {{ macroop = macroopDict[Name] if not macroop.declared: if env.doModRM: - macroop.doModRM = doModRMString + macroop.initEnv = doModRMString + else: + macroop.initEnv = noModRMString blocks.header_output = macroop.getDeclaration() - blocks.decoder_output = macroop.getDefinition() + blocks.decoder_output = macroop.getDefinition(env) macroop.declared = True blocks.decode_block = "return %s;\n" % macroop.getAllocator(env) return blocks diff --git a/src/arch/x86/isa/microasm.isa b/src/arch/x86/isa/microasm.isa index 78ae34f52..c7c6dae2e 100644 --- a/src/arch/x86/isa/microasm.isa +++ b/src/arch/x86/isa/microasm.isa @@ -1,6 +1,6 @@ // -*- mode:c++ -*- -// Copyright (c) 2007 The Hewlett-Packard Development Company +// Copyright (c) 2007-2008 The Hewlett-Packard Development Company // All rights reserved. // // Redistribution and use of this software in source and binary forms, @@ -64,23 +64,32 @@ //Include code to build macroops in both C++ and python. ##include "macroop.isa" +//Include code to fill out the microcode ROM in both C++ and python. +##include "rom.isa" + let {{ import sys sys.path[0:0] = ["src/arch/x86/isa/"] from insts import microcode # print microcode - from micro_asm import MicroAssembler, Rom_Macroop, Rom - mainRom = Rom('main ROM') + from micro_asm import MicroAssembler, Rom_Macroop + mainRom = X86MicrocodeRom('main ROM') assembler = MicroAssembler(X86Macroop, microopClasses, mainRom, Rom_Macroop) # Add in symbols for the microcode registers - for num in range(15): + for num in range(16): assembler.symbols["t%d" % num] = "NUM_INTREGS+%d" % num - for num in range(7): + for num in range(8): assembler.symbols["ufp%d" % num] = "FLOATREG_MICROFP(%d)" % num # Add in symbols for the segment descriptor registers - for letter in ("C", "D", "E", "F", "G", "S"): + for letter in ("C", "D", "E", "F", "G", "H", "S"): assembler.symbols["%ss" % letter.lower()] = "SEGMENT_REG_%sS" % letter + # Add in symbols for the various checks of segment selectors. + for check in ("NoCheck", "CSCheck", "CallGateCheck", "IntGateCheck", + "SoftIntGateCheck", "SSCheck", "IretCheck", "IntCSCheck", + "TRCheck", "TSSCheck", "InGDTCheck", "LDTCheck"): + assembler.symbols[check] = "Seg%s" % check + for reg in ("TR", "IDTR"): assembler.symbols[reg.lower()] = "SYS_SEGMENT_REG_%s" % reg @@ -129,13 +138,15 @@ let {{ # like the internal segment above assembler.symbols["flatseg"] = "SEGMENT_REG_LS" - for reg in ('ax', 'bx', 'cx', 'dx', 'sp', 'bp', 'si', 'di'): + for reg in ('ax', 'bx', 'cx', 'dx', 'sp', 'bp', 'si', 'di', \ + '8', '9', '10', '11', '12', '13', '14', '15'): assembler.symbols["r%s" % reg] = "INTREG_R%s" % reg.upper() - for reg in range(15): + for reg in range(16): assembler.symbols["cr%d" % reg] = "MISCREG_CR%d" % reg - for flag in ('CF', 'PF', 'ECF', 'AF', 'EZF', 'ZF', 'SF', 'OF'): + for flag in ('CF', 'PF', 'ECF', 'AF', 'EZF', 'ZF', 'SF', 'OF', \ + 'TF', 'IF', 'NT', 'RF', 'VM', 'AC', 'VIF', 'VIP', 'ID'): assembler.symbols[flag] = flag + "Bit" for cond in ('True', 'False', 'ECF', 'EZF', 'SZnZF', @@ -150,6 +161,11 @@ let {{ assembler.symbols["CTrue"] = "ConditionTests::True" assembler.symbols["CFalse"] = "ConditionTests::False" + for reg in ('sysenter_cs', 'sysenter_esp', 'sysenter_eip', + 'star', 'lstar', 'cstar', 'sf_mask', + 'kernel_gs_base'): + assembler.symbols[reg] = "MISCREG_%s" % reg.upper() + # Code literal which forces a default 64 bit operand size in 64 bit mode. assembler.symbols["oszIn64Override"] = ''' if (machInst.mode.submode == SixtyFourBitMode && @@ -157,7 +173,7 @@ let {{ env.dataSize = 8; ''' - assembler.symbols["oszForPseudoDesc"] = ''' + assembler.symbols["maxOsz"] = ''' if (machInst.mode.submode == SixtyFourBitMode) env.dataSize = 8; else @@ -174,10 +190,23 @@ let {{ assembler.symbols["label"] = labeler + def rom_labeler(labelStr): + return "romMicroPC(RomLabels::extern_label_%s)" % labelStr + + assembler.symbols["rom_label"] = rom_labeler + + def rom_local_labeler(labelStr): + return "romMicroPC(RomLabels::label_%s)" % labelStr + + assembler.symbols["rom_local_label"] = rom_local_labeler + def stack_index(index): return "(NUM_FLOATREGS + (((%s) + 8) %% 8))" % index assembler.symbols["st"] = stack_index macroopDict = assembler.assemble(microcode) + + decoder_output += mainRom.getDefinition() + header_output += mainRom.getDeclaration() }}; diff --git a/src/arch/x86/isa/microops/base.isa b/src/arch/x86/isa/microops/base.isa index 75658a26c..f1007bf71 100644 --- a/src/arch/x86/isa/microops/base.isa +++ b/src/arch/x86/isa/microops/base.isa @@ -69,6 +69,29 @@ let {{ let {{ class X86Microop(object): + + generatorNameTemplate = "generate_%s_%d" + + generatorTemplate = ''' + StaticInstPtr + ''' + generatorNameTemplate + '''(StaticInstPtr curMacroop) + { + static const char *macrocodeBlock = romMnemonic; + static const ExtMachInst dummyExtMachInst; + static const EmulEnv dummyEmulEnv(0, 0, 1, 1, 1); + + Macroop * macroop = dynamic_cast<Macroop *>(curMacroop.get()); + const ExtMachInst &machInst = + macroop ? macroop->getExtMachInst() : dummyExtMachInst; + const EmulEnv &env = + macroop ? macroop->getEmulEnv() : dummyEmulEnv; + // env may not be used in the microop's constructor. + RegIndex reg = env.reg; + reg = reg; + using namespace RomLabels; + return %s; + } + ''' def __init__(self, name): self.name = name @@ -91,4 +114,12 @@ let {{ def getAllocator(self, mnemonic, *microFlags): return 'new %s(machInst, %s)' % \ (self.className, mnemonic, self.microFlagsText(microFlags)) + + def getGeneratorDef(self, micropc): + return self.generatorTemplate % \ + (self.className, micropc, \ + self.getAllocator(True, True, False, False)) + + def getGenerator(self, micropc): + return self.generatorNameTemplate % (self.className, micropc) }}; diff --git a/src/arch/x86/isa/microops/debug.isa b/src/arch/x86/isa/microops/debug.isa new file mode 100644 index 000000000..38fee59bb --- /dev/null +++ b/src/arch/x86/isa/microops/debug.isa @@ -0,0 +1,229 @@ +// Copyright (c) 2008 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 + +////////////////////////////////////////////////////////////////////////// +// +// Debug Microops +// +////////////////////////////////////////////////////////////////////////// + +output header {{ + class MicroDebugBase : public X86ISA::X86MicroopBase + { + protected: + std::string message; + uint8_t cc; + + public: + MicroDebugBase(ExtMachInst _machInst, const char * mnem, + const char * instMnem, + bool isMicro, bool isDelayed, bool isFirst, bool isLast, + std::string _message, uint8_t _cc); + + MicroDebugBase(ExtMachInst _machInst, const char * mnem, + const char * instMnem, std::string _message, uint8_t _cc); + + std::string generateDisassembly(Addr pc, + const SymbolTable *symtab) const; + }; +}}; + +def template MicroDebugDeclare {{ + class %(class_name)s : public %(base_class)s + { + private: + void buildMe(); + public: + %(class_name)s(ExtMachInst _machInst, const char * instMnem, + bool isMicro, bool isDelayed, bool isFirst, bool isLast, + std::string _message, uint8_t _cc); + + %(class_name)s(ExtMachInst _machInst, const char * instMnem, + std::string _message, uint8_t _cc); + + %(BasicExecDeclare)s + }; +}}; + +def template MicroDebugExecute {{ + Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + %(op_decl)s + %(op_rd)s + if (%(cond_test)s) { + %(func)s("%s\n", message); + } + return NoFault; + } +}}; + +output decoder {{ + inline MicroDebugBase::MicroDebugBase( + ExtMachInst machInst, const char * mnem, const char * instMnem, + std::string _message, uint8_t _cc) : + X86MicroopBase(machInst, mnem, instMnem, + false, false, false, false, No_OpClass), + message(_message), cc(_cc) + { + } + + inline MicroDebugBase::MicroDebugBase( + ExtMachInst machInst, const char * mnem, const char * instMnem, + bool isMicro, bool isDelayed, bool isFirst, bool isLast, + std::string _message, uint8_t _cc) : + X86MicroopBase(machInst, mnem, instMnem, + isMicro, isDelayed, isFirst, isLast, No_OpClass), + message(_message), cc(_cc) + { + } +}}; + +def template MicroDebugConstructor {{ + + inline void %(class_name)s::buildMe() + { + %(constructor)s; + } + + inline %(class_name)s::%(class_name)s( + ExtMachInst machInst, const char * instMnem, + std::string _message, uint8_t _cc) : + %(base_class)s(machInst, "%(func)s", instMnem, _message, _cc) + { + buildMe(); + } + + inline %(class_name)s::%(class_name)s( + ExtMachInst machInst, const char * instMnem, + bool isMicro, bool isDelayed, bool isFirst, bool isLast, + std::string _message, uint8_t _cc) : + %(base_class)s(machInst, "%(func)s", instMnem, + isMicro, isDelayed, isFirst, isLast, _message, _cc) + { + buildMe(); + } +}}; + +output decoder {{ + std::string MicroDebugBase::generateDisassembly(Addr pc, + const SymbolTable *symtab) const + { + std::stringstream response; + + printMnemonic(response, instMnem, mnemonic); + response << "\"" << message << "\""; + + return response.str(); + } +}}; + +let {{ + class MicroDebug(X86Microop): + def __init__(self, message, flags=None): + self.message = message + if flags: + if not isinstance(flags, (list, tuple)): + raise Exception, "flags must be a list or tuple of flags" + self.cond = " | ".join(flags) + self.className += "Flags" + else: + self.cond = "0" + + def getAllocator(self, *microFlags): + allocator = '''new %(class_name)s(machInst, macrocodeBlock + %(flags)s, "%(message)s", %(cc)s)''' % { + "class_name" : self.className, + "flags" : self.microFlagsText(microFlags), + "message" : self.message, + "cc" : self.cond} + return allocator + + exec_output = "" + header_output = "" + decoder_output = "" + + def buildDebugMicro(func): + global exec_output, header_output, decoder_output + + iop = InstObjParams(func, "Micro%sFlags" % func.capitalize(), + "MicroDebugBase", + {"code": "", + "func": func, + "cond_test": "checkCondition(ccFlagBits, cc)"}) + exec_output += MicroDebugExecute.subst(iop) + header_output += MicroDebugDeclare.subst(iop) + decoder_output += MicroDebugConstructor.subst(iop) + + iop = InstObjParams(func, "Micro%s" % func.capitalize(), + "MicroDebugBase", + {"code": "", + "func": func, + "cond_test": "true"}) + exec_output += MicroDebugExecute.subst(iop) + header_output += MicroDebugDeclare.subst(iop) + decoder_output += MicroDebugConstructor.subst(iop) + + class MicroDebugChild(MicroDebug): + className = "Micro%s" % func.capitalize() + + global microopClasses + microopClasses[func] = MicroDebugChild + + buildDebugMicro("panic") + buildDebugMicro("fatal") + buildDebugMicro("warn") + buildDebugMicro("warn_once") +}}; diff --git a/src/arch/x86/isa/microops/fpop.isa b/src/arch/x86/isa/microops/fpop.isa index 2919aa277..d4acfdbf4 100644 --- a/src/arch/x86/isa/microops/fpop.isa +++ b/src/arch/x86/isa/microops/fpop.isa @@ -245,7 +245,7 @@ let {{ self.className += "Top" def getAllocator(self, *microFlags): - return '''new %(class_name)s(machInst, mnemonic + return '''new %(class_name)s(machInst, macrocodeBlock %(flags)s, %(src1)s, %(src2)s, %(dest)s, %(dataSize)s, %(spm)d)''' % { "class_name" : self.className, diff --git a/src/arch/x86/isa/microops/ldstop.isa b/src/arch/x86/isa/microops/ldstop.isa index cb63e7cd9..af94cf31e 100644 --- a/src/arch/x86/isa/microops/ldstop.isa +++ b/src/arch/x86/isa/microops/ldstop.isa @@ -124,14 +124,16 @@ def template MicroLeaDeclare {{ uint8_t _scale, RegIndex _index, RegIndex _base, uint64_t _disp, uint8_t _segment, RegIndex _data, - uint8_t _dataSize, uint8_t _addressSize); + uint8_t _dataSize, uint8_t _addressSize, + Request::FlagsType _memFlags); %(class_name)s(ExtMachInst _machInst, const char * instMnem, uint8_t _scale, RegIndex _index, RegIndex _base, uint64_t _disp, uint8_t _segment, RegIndex _data, - uint8_t _dataSize, uint8_t _addressSize); + uint8_t _dataSize, uint8_t _addressSize, + Request::FlagsType _memFlags); %(BasicExecDeclare)s }; @@ -151,11 +153,13 @@ def template MicroLoadExecute {{ %(ea_code)s; DPRINTF(X86, "%s : %s: The address is %#x\n", instMnem, mnemonic, EA); - fault = read(xc, EA, Mem, (%(mem_flags)s) | segment); + fault = read(xc, EA, Mem, memFlags); - if(fault == NoFault) - { + if (fault == NoFault) { %(code)s; + } else if (memFlags & Request::PF_EXCLUSIVE) { + // For prefetches, ignore any faults/exceptions. + return NoFault; } if(fault == NoFault) { @@ -178,7 +182,7 @@ def template MicroLoadInitiateAcc {{ %(ea_code)s; DPRINTF(X86, "%s : %s: The address is %#x\n", instMnem, mnemonic, EA); - fault = read(xc, EA, Mem, (%(mem_flags)s) | segment); + fault = read(xc, EA, Mem, memFlags); return fault; } @@ -194,7 +198,7 @@ def template MicroLoadCompleteAcc {{ %(op_decl)s; %(op_rd)s; - Mem = pkt->get<typeof(Mem)>(); + Mem = get(pkt); %(code)s; @@ -225,9 +229,10 @@ def template MicroStoreExecute {{ if(fault == NoFault) { - fault = write(xc, Mem, EA, (%(mem_flags)s) | segment); + fault = write(xc, Mem, EA, memFlags); if(fault == NoFault) { + %(post_code)s; %(op_wb)s; } } @@ -252,20 +257,20 @@ def template MicroStoreInitiateAcc {{ if(fault == NoFault) { - fault = write(xc, Mem, EA, (%(mem_flags)s) | segment); - if(fault == NoFault) - { - %(op_wb)s; - } + write(xc, Mem, EA, memFlags); } return fault; } }}; def template MicroStoreCompleteAcc {{ - Fault %(class_name)s::completeAcc(PacketPtr, %(CPU_exec_context)s * xc, - Trace::InstRecord * traceData) const + Fault %(class_name)s::completeAcc(PacketPtr pkt, + %(CPU_exec_context)s * xc, Trace::InstRecord * traceData) const { + %(op_decl)s; + %(op_rd)s; + %(complete_code)s; + %(op_wb)s; return NoFault; } }}; @@ -295,14 +300,16 @@ def template MicroLdStOpDeclare {{ uint8_t _scale, RegIndex _index, RegIndex _base, uint64_t _disp, uint8_t _segment, RegIndex _data, - uint8_t _dataSize, uint8_t _addressSize); + uint8_t _dataSize, uint8_t _addressSize, + Request::FlagsType _memFlags); %(class_name)s(ExtMachInst _machInst, const char * instMnem, uint8_t _scale, RegIndex _index, RegIndex _base, uint64_t _disp, uint8_t _segment, RegIndex _data, - uint8_t _dataSize, uint8_t _addressSize); + uint8_t _dataSize, uint8_t _addressSize, + Request::FlagsType _memFlags); %(BasicExecDeclare)s @@ -324,12 +331,13 @@ def template MicroLdStOpConstructor {{ uint8_t _scale, RegIndex _index, RegIndex _base, uint64_t _disp, uint8_t _segment, RegIndex _data, - uint8_t _dataSize, uint8_t _addressSize) : + uint8_t _dataSize, uint8_t _addressSize, + Request::FlagsType _memFlags) : %(base_class)s(machInst, "%(mnemonic)s", instMnem, false, false, false, false, _scale, _index, _base, _disp, _segment, _data, - _dataSize, _addressSize, %(op_class)s) + _dataSize, _addressSize, _memFlags, %(op_class)s) { buildMe(); } @@ -340,12 +348,13 @@ def template MicroLdStOpConstructor {{ uint8_t _scale, RegIndex _index, RegIndex _base, uint64_t _disp, uint8_t _segment, RegIndex _data, - uint8_t _dataSize, uint8_t _addressSize) : + uint8_t _dataSize, uint8_t _addressSize, + Request::FlagsType _memFlags) : %(base_class)s(machInst, "%(mnemonic)s", instMnem, isMicro, isDelayed, isFirst, isLast, _scale, _index, _base, _disp, _segment, _data, - _dataSize, _addressSize, %(op_class)s) + _dataSize, _addressSize, _memFlags, %(op_class)s) { buildMe(); } @@ -353,26 +362,35 @@ def template MicroLdStOpConstructor {{ let {{ class LdStOp(X86Microop): - def __init__(self, data, segment, addr, disp, dataSize, addressSize): + def __init__(self, data, segment, addr, disp, + dataSize, addressSize, baseFlags, atCPL0, prefetch): self.data = data [self.scale, self.index, self.base] = addr self.disp = disp self.segment = segment self.dataSize = dataSize self.addressSize = addressSize + self.memFlags = baseFlags + if atCPL0: + self.memFlags += " | (CPL0FlagBit << FlagShift)" + if prefetch: + self.memFlags += " | Request::PF_EXCLUSIVE" + self.memFlags += " | (machInst.legacy.addr ? " + \ + "(AddrSizeFlagBit << FlagShift) : 0)" def getAllocator(self, *microFlags): - allocator = '''new %(class_name)s(machInst, mnemonic + allocator = '''new %(class_name)s(machInst, macrocodeBlock %(flags)s, %(scale)s, %(index)s, %(base)s, %(disp)s, %(segment)s, %(data)s, - %(dataSize)s, %(addressSize)s)''' % { + %(dataSize)s, %(addressSize)s, %(memFlags)s)''' % { "class_name" : self.className, "flags" : self.microFlagsText(microFlags), "scale" : self.scale, "index" : self.index, "base" : self.base, "disp" : self.disp, "segment" : self.segment, "data" : self.data, - "dataSize" : self.dataSize, "addressSize" : self.addressSize} + "dataSize" : self.dataSize, "addressSize" : self.addressSize, + "memFlags" : self.memFlags} return allocator }}; @@ -384,9 +402,11 @@ let {{ decoder_output = "" exec_output = "" - calculateEA = "EA = SegBase + scale * Index + Base + disp;" + calculateEA = ''' + EA = bits(SegBase + scale * Index + Base + disp, addressSize * 8 - 1, 0); + ''' - def defineMicroLoadOp(mnemonic, code, mem_flags=0): + def defineMicroLoadOp(mnemonic, code, mem_flags="0"): global header_output global decoder_output global exec_output @@ -397,8 +417,7 @@ let {{ # Build up the all register version of this micro op iop = InstObjParams(name, Name, 'X86ISA::LdStOp', {"code": code, - "ea_code": calculateEA, - "mem_flags": mem_flags}) + "ea_code": calculateEA}) header_output += MicroLdStOpDeclare.subst(iop) decoder_output += MicroLdStOpConstructor.subst(iop) exec_output += MicroLoadExecute.subst(iop) @@ -407,19 +426,24 @@ let {{ class LoadOp(LdStOp): def __init__(self, data, segment, addr, disp = 0, - dataSize="env.dataSize", addressSize="env.addressSize"): - super(LoadOp, self).__init__(data, segment, - addr, disp, dataSize, addressSize) + dataSize="env.dataSize", + addressSize="env.addressSize", + atCPL0=False, prefetch=False): + super(LoadOp, self).__init__(data, segment, addr, + disp, dataSize, addressSize, mem_flags, + atCPL0, prefetch) self.className = Name self.mnemonic = name microopClasses[name] = LoadOp defineMicroLoadOp('Ld', 'Data = merge(Data, Mem, dataSize);') - defineMicroLoadOp('Ldst', 'Data = merge(Data, Mem, dataSize);', 'StoreCheck') + defineMicroLoadOp('Ldst', 'Data = merge(Data, Mem, dataSize);', + 'X86ISA::StoreCheck') defineMicroLoadOp('Ldfp', 'FpData.uqw = Mem;') - def defineMicroStoreOp(mnemonic, code, mem_flags=0): + def defineMicroStoreOp(mnemonic, code, \ + postCode="", completeCode="", mem_flags="0"): global header_output global decoder_output global exec_output @@ -430,8 +454,9 @@ let {{ # Build up the all register version of this micro op iop = InstObjParams(name, Name, 'X86ISA::LdStOp', {"code": code, - "ea_code": calculateEA, - "mem_flags": mem_flags}) + "post_code": postCode, + "complete_code": completeCode, + "ea_code": calculateEA}) header_output += MicroLdStOpDeclare.subst(iop) decoder_output += MicroLdStOpConstructor.subst(iop) exec_output += MicroStoreExecute.subst(iop) @@ -440,26 +465,26 @@ let {{ class StoreOp(LdStOp): def __init__(self, data, segment, addr, disp = 0, - dataSize="env.dataSize", addressSize="env.addressSize"): - super(StoreOp, self).__init__(data, segment, - addr, disp, dataSize, addressSize) + dataSize="env.dataSize", + addressSize="env.addressSize", + atCPL0=False): + super(StoreOp, self).__init__(data, segment, addr, + disp, dataSize, addressSize, mem_flags, atCPL0, False) self.className = Name self.mnemonic = name microopClasses[name] = StoreOp - defineMicroStoreOp('St', 'Mem = Data;') + defineMicroStoreOp('St', 'Mem = pick(Data, 2, dataSize);') defineMicroStoreOp('Stfp', 'Mem = FpData.uqw;') - defineMicroStoreOp('Stupd', ''' - Mem = Data; - Base = merge(Base, EA - SegBase, addressSize); - '''); - + defineMicroStoreOp('Stupd', 'Mem = pick(Data, 2, dataSize);', + 'Base = merge(Base, EA - SegBase, addressSize);', + 'Base = merge(Base, pkt->req->getVaddr() - SegBase, addressSize);'); + defineMicroStoreOp('Cda', 'Mem = 0;', mem_flags="Request::NO_ACCESS") iop = InstObjParams("lea", "Lea", 'X86ISA::LdStOp', {"code": "Data = merge(Data, EA, dataSize);", - "ea_code": calculateEA, - "mem_flags": 0}) + "ea_code": calculateEA}) header_output += MicroLeaDeclare.subst(iop) decoder_output += MicroLdStOpConstructor.subst(iop) exec_output += MicroLeaExecute.subst(iop) @@ -468,7 +493,7 @@ let {{ def __init__(self, data, segment, addr, disp = 0, dataSize="env.dataSize", addressSize="env.addressSize"): super(LeaOp, self).__init__(data, segment, - addr, disp, dataSize, addressSize) + addr, disp, dataSize, addressSize, "0", False, False) self.className = "Lea" self.mnemonic = "lea" @@ -477,38 +502,28 @@ let {{ iop = InstObjParams("tia", "Tia", 'X86ISA::LdStOp', {"code": "xc->demapPage(EA, 0);", - "ea_code": calculateEA, - "mem_flags": 0}) + "ea_code": calculateEA}) header_output += MicroLeaDeclare.subst(iop) decoder_output += MicroLdStOpConstructor.subst(iop) exec_output += MicroLeaExecute.subst(iop) class TiaOp(LdStOp): def __init__(self, segment, addr, disp = 0, - dataSize="env.dataSize", addressSize="env.addressSize"): + dataSize="env.dataSize", + addressSize="env.addressSize"): super(TiaOp, self).__init__("NUM_INTREGS", segment, - addr, disp, dataSize, addressSize) + addr, disp, dataSize, addressSize, "0", False, False) self.className = "Tia" self.mnemonic = "tia" microopClasses["tia"] = TiaOp - iop = InstObjParams("cda", "Cda", 'X86ISA::LdStOp', - {"code": ''' - Addr paddr; - fault = xc->translateDataWriteAddr(EA, paddr, - dataSize, (1 << segment)); - ''', - "ea_code": calculateEA}) - header_output += MicroLeaDeclare.subst(iop) - decoder_output += MicroLdStOpConstructor.subst(iop) - exec_output += MicroLeaExecute.subst(iop) - class CdaOp(LdStOp): def __init__(self, segment, addr, disp = 0, - dataSize="env.dataSize", addressSize="env.addressSize"): + dataSize="env.dataSize", + addressSize="env.addressSize", atCPL0=False): super(CdaOp, self).__init__("NUM_INTREGS", segment, - addr, disp, dataSize, addressSize) + addr, disp, dataSize, addressSize, "0", atCPL0, False) self.className = "Cda" self.mnemonic = "cda" diff --git a/src/arch/x86/isa/microops/limmop.isa b/src/arch/x86/isa/microops/limmop.isa index 6686444fd..4e75ab8b0 100644 --- a/src/arch/x86/isa/microops/limmop.isa +++ b/src/arch/x86/isa/microops/limmop.isa @@ -154,7 +154,7 @@ let {{ self.dataSize = dataSize def getAllocator(self, *microFlags): - allocator = '''new %(class_name)s(machInst, mnemonic + allocator = '''new %(class_name)s(machInst, macrocodeBlock %(flags)s, %(dest)s, %(imm)s, %(dataSize)s)''' % { "class_name" : self.className, "mnemonic" : self.mnemonic, diff --git a/src/arch/x86/isa/microops/microops.isa b/src/arch/x86/isa/microops/microops.isa index 53f34d3f2..19266f6d6 100644 --- a/src/arch/x86/isa/microops/microops.isa +++ b/src/arch/x86/isa/microops/microops.isa @@ -1,4 +1,4 @@ -// Copyright (c) 2007 The Hewlett-Packard Development Company +// Copyright (c) 2007-2008 The Hewlett-Packard Development Company // All rights reserved. // // Redistribution and use of this software in source and binary forms, @@ -68,5 +68,11 @@ //Load/store microop definitions ##include "ldstop.isa" +//Control flow microop definitions +##include "seqop.isa" + //Miscellaneous microop definitions ##include "specop.isa" + +//Microops for printing out debug messages through M5 +##include "debug.isa" diff --git a/src/arch/x86/isa/microops/regop.isa b/src/arch/x86/isa/microops/regop.isa index e761f0034..f9bc82119 100644 --- a/src/arch/x86/isa/microops/regop.isa +++ b/src/arch/x86/isa/microops/regop.isa @@ -1,4 +1,4 @@ -// Copyright (c) 2007 The Hewlett-Packard Development Company +// Copyright (c) 2007-2008 The Hewlett-Packard Development Company // All rights reserved. // // Redistribution and use of this software in source and binary forms, @@ -231,6 +231,21 @@ output header {{ void divide(uint64_t dividend, uint64_t divisor, uint64_t "ient, uint64_t &remainder); + + enum SegmentSelectorCheck { + SegNoCheck, SegCSCheck, SegCallGateCheck, SegIntGateCheck, + SegSoftIntGateCheck, SegSSCheck, SegIretCheck, SegIntCSCheck, + SegTRCheck, SegTSSCheck, SegInGDTCheck, SegLDTCheck + }; + + enum LongModeDescriptorType { + LDT64 = 2, + AvailableTSS64 = 9, + BusyTSS64 = 0xb, + CallGate64 = 0xc, + IntGate64 = 0xe, + TrapGate64 = 0xf + }; }}; output decoder {{ @@ -424,7 +439,7 @@ let {{ className = self.className if self.mnemonic == self.base_mnemonic + 'i': className += "Imm" - allocator = '''new %(class_name)s(machInst, mnemonic + allocator = '''new %(class_name)s(machInst, macrocodeBlock %(flags)s, %(src1)s, %(op2)s, %(dest)s, %(dataSize)s, %(ext)s)''' % { "class_name" : className, @@ -838,19 +853,28 @@ let {{ code = 'RIP = psrc1 + sop2 + CSBase' else_code="RIP = RIP;" - class Br(WrRegOp, CondRegOp): - code = 'nuIP = psrc1 + op2;' - else_code='nuIP = nuIP;' - class Wruflags(WrRegOp): code = 'ccFlagBits = psrc1 ^ op2' + class Wrflags(WrRegOp): + code = ''' + MiscReg newFlags = psrc1 ^ op2; + MiscReg userFlagMask = 0xDD5; + // Get only the user flags + ccFlagBits = newFlags & userFlagMask; + // Get everything else + nccFlagBits = newFlags & ~userFlagMask; + ''' + class Rdip(RdRegOp): code = 'DestReg = RIP - CSBase' class Ruflags(RdRegOp): code = 'DestReg = ccFlagBits' + class Rflags(RdRegOp): + code = 'DestReg = ccFlagBits | nccFlagBits' + class Ruflag(RegOp): code = ''' int flag = bits(ccFlagBits, imm8); @@ -863,6 +887,20 @@ let {{ super(Ruflag, self).__init__(dest, \ "NUM_INTREGS", imm, flags, dataSize) + class Rflag(RegOp): + code = ''' + MiscReg flagMask = 0x3F7FDD5; + MiscReg flags = (nccFlagBits | ccFlagBits) & flagMask; + int flag = bits(flags, imm8); + DestReg = merge(DestReg, flag, dataSize); + ccFlagBits = (flag == 0) ? (ccFlagBits | EZFBit) : + (ccFlagBits & ~EZFBit); + ''' + def __init__(self, dest, imm, flags=None, \ + dataSize="env.dataSize"): + super(Rflag, self).__init__(dest, \ + "NUM_INTREGS", imm, flags, dataSize) + class Sext(RegOp): code = ''' IntReg val = psrc1; @@ -883,17 +921,53 @@ let {{ ''' class Zext(RegOp): - code = 'DestReg = bits(psrc1, op2, 0);' + code = 'DestReg = merge(DestReg, bits(psrc1, op2, 0), dataSize);' + + class Rddr(RegOp): + def __init__(self, dest, src1, flags=None, dataSize="env.dataSize"): + super(Rddr, self).__init__(dest, \ + src1, "NUM_INTREGS", flags, dataSize) + code = ''' + CR4 cr4 = CR4Op; + DR7 dr7 = DR7Op; + if ((cr4.de == 1 && (src1 == 4 || src1 == 5)) || src1 >= 8) { + fault = new InvalidOpcode(); + } else if (dr7.gd) { + fault = new DebugException(); + } else { + DestReg = merge(DestReg, DebugSrc1, dataSize); + } + ''' + + class Wrdr(RegOp): + def __init__(self, dest, src1, flags=None, dataSize="env.dataSize"): + super(Wrdr, self).__init__(dest, \ + src1, "NUM_INTREGS", flags, dataSize) + code = ''' + CR4 cr4 = CR4Op; + DR7 dr7 = DR7Op; + if ((cr4.de == 1 && (dest == 4 || dest == 5)) || dest >= 8) { + fault = new InvalidOpcode(); + } else if ((dest == 6 || dest == 7) && + bits(psrc1, 63, 32) && + machInst.mode.mode == LongMode) { + fault = new GeneralProtection(0); + } else if (dr7.gd) { + fault = new DebugException(); + } else { + DebugDest = psrc1; + } + ''' class Rdcr(RegOp): def __init__(self, dest, src1, flags=None, dataSize="env.dataSize"): super(Rdcr, self).__init__(dest, \ src1, "NUM_INTREGS", flags, dataSize) code = ''' - if (dest == 1 || (dest > 4 && dest < 8) || (dest > 8)) { + if (src1 == 1 || (src1 > 4 && src1 < 8) || (src1 > 8)) { fault = new InvalidOpcode(); } else { - DestReg = ControlSrc1; + DestReg = merge(DestReg, ControlSrc1, dataSize); } ''' @@ -950,7 +1024,7 @@ let {{ ''' # Microops for manipulating segmentation registers - class SegOp(RegOp): + class SegOp(CondRegOp): abstract = True def __init__(self, dest, src1, flags=None, dataSize="env.dataSize"): super(SegOp, self).__init__(dest, \ @@ -971,74 +1045,223 @@ let {{ SegSelDest = psrc1; ''' + class WrAttr(SegOp): + code = ''' + SegAttrDest = psrc1; + ''' + class Rdbase(SegOp): code = ''' - DestReg = SegBaseDest; + DestReg = merge(DestReg, SegBaseSrc1, dataSize); ''' class Rdlimit(SegOp): code = ''' - DestReg = SegLimitSrc1; + DestReg = merge(DestReg, SegLimitSrc1, dataSize); + ''' + + class RdAttr(SegOp): + code = ''' + DestReg = merge(DestReg, SegAttrSrc1, dataSize); ''' class Rdsel(SegOp): code = ''' - DestReg = SegSelSrc1; + DestReg = merge(DestReg, SegSelSrc1, dataSize); ''' - class Chks(SegOp): + class Rdval(RegOp): + def __init__(self, dest, src1, flags=None, dataSize="env.dataSize"): + super(Rdval, self).__init__(dest, \ + src1, "NUM_INTREGS", flags, dataSize) code = ''' - // The selector is in source 1. - SegSelector selector = psrc1; - - // Compute the address of the descriptor and set DestReg to it. - if (selector.ti) { - // A descriptor in the LDT - Addr target = (selector.esi << 3) + LDTRBase; - if (!LDTRSel || (selector.esi << 3) + dataSize > LDTRLimit) - fault = new GeneralProtection(selector & mask(16)); - DestReg = target; - } else { - // A descriptor in the GDT - Addr target = (selector.esi << 3) + GDTRBase; - if ((selector.esi << 3) + dataSize > GDTRLimit) - fault = new GeneralProtection(selector & mask(16)); - DestReg = target; + DestReg = MiscRegSrc1; + ''' + + class Wrval(RegOp): + def __init__(self, dest, src1, flags=None, dataSize="env.dataSize"): + super(Wrval, self).__init__(dest, \ + src1, "NUM_INTREGS", flags, dataSize) + code = ''' + MiscRegDest = SrcReg1; + ''' + + class Chks(RegOp): + def __init__(self, dest, src1, src2=0, + flags=None, dataSize="env.dataSize"): + super(Chks, self).__init__(dest, + src1, src2, flags, dataSize) + code = ''' + // The selector is in source 1 and can be at most 16 bits. + SegSelector selector = DestReg; + SegDescriptor desc = SrcReg1; + HandyM5Reg m5reg = M5Reg; + + switch (imm8) + { + case SegNoCheck: + break; + case SegCSCheck: + panic("CS checks for far calls/jumps not implemented.\\n"); + break; + case SegCallGateCheck: + panic("CS checks for far calls/jumps through call gates" + "not implemented.\\n"); + break; + case SegSoftIntGateCheck: + // Check permissions. + if (desc.dpl < m5reg.cpl) { + fault = new GeneralProtection(selector); + } + // Fall through on purpose + case SegIntGateCheck: + // Make sure the gate's the right type. + if ((m5reg.mode == LongMode && (desc.type & 0xe) != 0xe) || + ((desc.type & 0x6) != 0x6)) { + fault = new GeneralProtection(0); + } + break; + case SegSSCheck: + if (selector.si || selector.ti) { + if (!desc.p) { + fault = new StackFault(selector); + } + } else { + if ((m5reg.submode != SixtyFourBitMode || + m5reg.cpl == 3) || + !(desc.s == 1 && + desc.type.codeOrData == 0 && desc.type.w) || + (desc.dpl != m5reg.cpl) || + (selector.rpl != m5reg.cpl)) { + fault = new GeneralProtection(selector); + } + } + break; + case SegIretCheck: + { + if ((!selector.si && !selector.ti) || + (selector.rpl < m5reg.cpl) || + !(desc.s == 1 && desc.type.codeOrData == 1) || + (!desc.type.c && desc.dpl != selector.rpl) || + (desc.type.c && desc.dpl > selector.rpl)) { + fault = new GeneralProtection(selector); + } else if (!desc.p) { + fault = new SegmentNotPresent(selector); + } + break; + } + case SegIntCSCheck: + if (m5reg.mode == LongMode) { + if (desc.l != 1 || desc.d != 0) { + fault = new GeneralProtection(selector); + } + } else { + panic("Interrupt CS checks not implemented " + "in legacy mode.\\n"); + } + break; + case SegTRCheck: + if (!selector.si || selector.ti) { + fault = new GeneralProtection(selector); + } + break; + case SegTSSCheck: + if (!desc.p) { + fault = new SegmentNotPresent(selector); + } else if (!(desc.type == 0x9 || + (desc.type == 1 && + m5reg.mode != LongMode))) { + fault = new GeneralProtection(selector); + } + break; + case SegInGDTCheck: + if (selector.ti) { + fault = new GeneralProtection(selector); + } + break; + case SegLDTCheck: + if (!desc.p) { + fault = new SegmentNotPresent(selector); + } else if (desc.type != 0x2) { + fault = new GeneralProtection(selector); + } + break; + default: + panic("Undefined segment check type.\\n"); } ''' flag_code = ''' // Check for a NULL selector and set ZF,EZF appropriately. ccFlagBits = ccFlagBits & ~(ext & (ZFBit | EZFBit)); - if (!selector.esi && !selector.ti) + if (!selector.si && !selector.ti) ccFlagBits = ccFlagBits | (ext & (ZFBit | EZFBit)); ''' class Wrdh(RegOp): code = ''' + SegDescriptor desc = SrcReg1; + + uint64_t target = bits(SrcReg2, 31, 0) << 32; + switch(desc.type) { + case LDT64: + case AvailableTSS64: + case BusyTSS64: + replaceBits(target, 23, 0, desc.baseLow); + replaceBits(target, 31, 24, desc.baseHigh); + break; + case CallGate64: + case IntGate64: + case TrapGate64: + replaceBits(target, 15, 0, bits(desc, 15, 0)); + replaceBits(target, 31, 16, bits(desc, 63, 48)); + break; + default: + panic("Wrdh used with wrong descriptor type!\\n"); + } + DestReg = target; + ''' + + class Wrtsc(WrRegOp): + code = ''' + TscOp = psrc1; + ''' + + class Rdtsc(RdRegOp): + code = ''' + DestReg = TscOp; + ''' + class Rdm5reg(RdRegOp): + code = ''' + DestReg = M5Reg; ''' class Wrdl(RegOp): code = ''' SegDescriptor desc = SrcReg1; - SegAttr attr = 0; - attr.dpl = desc.dpl; - attr.defaultSize = desc.d; - if (!desc.s) { - SegBaseDest = SegBaseDest; - SegLimitDest = SegLimitDest; - SegAttrDest = SegAttrDest; - panic("System segment encountered.\\n"); - } else { - if (!desc.p) - panic("Segment not present.\\n"); - if (desc.type.codeOrData) { - attr.readable = desc.type.r; - attr.longMode = desc.l; - } else { - attr.expandDown = desc.type.e; + SegSelector selector = SrcReg2; + if (selector.si || selector.ti) { + SegAttr attr = 0; + attr.dpl = desc.dpl; + attr.defaultSize = desc.d; + if (!desc.s) { + // The expand down bit happens to be set for gates. + if (desc.type.e) { + panic("Gate descriptor encountered.\\n"); + } attr.readable = 1; - attr.writable = desc.type.w; + attr.writable = 1; + } else { + if (!desc.p) + panic("Segment not present.\\n"); + if (desc.type.codeOrData) { + attr.readable = desc.type.r; + attr.longMode = desc.l; + } else { + attr.expandDown = desc.type.e; + attr.readable = 1; + attr.writable = desc.type.w; + } } Addr base = desc.baseLow | (desc.baseHigh << 24); Addr limit = desc.limitLow | (desc.limitHigh << 16); @@ -1047,6 +1270,10 @@ let {{ SegBaseDest = base; SegLimitDest = limit; SegAttrDest = attr; + } else { + SegBaseDest = SegBaseDest; + SegLimitDest = SegLimitDest; + SegAttrDest = SegAttrDest; } ''' }}; diff --git a/src/arch/x86/isa/microops/seqop.isa b/src/arch/x86/isa/microops/seqop.isa new file mode 100644 index 000000000..332519b87 --- /dev/null +++ b/src/arch/x86/isa/microops/seqop.isa @@ -0,0 +1,251 @@ +// Copyright (c) 2008 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 header {{ + class SeqOpBase : public X86ISA::X86MicroopBase + { + protected: + uint16_t target; + uint8_t cc; + + public: + SeqOpBase(ExtMachInst _machInst, const char * instMnem, + const char * mnemonic, + bool isMicro, bool isDelayed, bool isFirst, bool isLast, + uint16_t _target, uint8_t _cc); + + SeqOpBase(ExtMachInst _machInst, const char * instMnem, + const char * mnemonic, + uint16_t _target, uint8_t _cc); + + std::string generateDisassembly(Addr pc, + const SymbolTable *symtab) const; + }; +}}; + +def template SeqOpDeclare {{ + class %(class_name)s : public %(base_class)s + { + private: + void buildMe(); + public: + %(class_name)s(ExtMachInst _machInst, const char * instMnem, + bool isMicro, bool isDelayed, bool isFirst, bool isLast, + uint16_t _target, uint8_t _cc); + + %(class_name)s(ExtMachInst _machInst, const char * instMnem, + uint16_t _target, uint8_t _cc); + + %(BasicExecDeclare)s + }; +}}; + +def template SeqOpExecute {{ + Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + %(op_decl)s; + %(op_rd)s; + if (%(cond_test)s) { + %(code)s; + } else { + %(else_code)s; + } + %(op_wb)s; + return NoFault; + } +}}; + +output decoder {{ + inline SeqOpBase::SeqOpBase( + ExtMachInst machInst, const char * mnemonic, const char * instMnem, + uint16_t _target, uint8_t _cc) : + X86MicroopBase(machInst, mnemonic, instMnem, + false, false, false, false, No_OpClass), + target(_target), cc(_cc) + { + } + + inline SeqOpBase::SeqOpBase( + ExtMachInst machInst, const char * mnemonic, const char * instMnem, + bool isMicro, bool isDelayed, bool isFirst, bool isLast, + uint16_t _target, uint8_t _cc) : + X86MicroopBase(machInst, mnemonic, instMnem, + isMicro, isDelayed, isFirst, isLast, No_OpClass), + target(_target), cc(_cc) + { + } +}}; + +def template SeqOpConstructor {{ + + inline void %(class_name)s::buildMe() + { + %(constructor)s; + } + + inline %(class_name)s::%(class_name)s( + ExtMachInst machInst, const char * instMnem, + uint16_t _target, uint8_t _cc) : + %(base_class)s(machInst, "%(mnemonic)s", instMnem, _target, _cc) + { + buildMe(); + } + + inline %(class_name)s::%(class_name)s( + ExtMachInst machInst, const char * instMnem, + bool isMicro, bool isDelayed, bool isFirst, bool isLast, + uint16_t _target, uint8_t _cc) : + %(base_class)s(machInst, "%(mnemonic)s", instMnem, + isMicro, isDelayed, isFirst, isLast, _target, _cc) + { + buildMe(); + } +}}; + +output decoder {{ + std::string SeqOpBase::generateDisassembly(Addr pc, + const SymbolTable *symtab) const + { + std::stringstream response; + + printMnemonic(response, instMnem, mnemonic); + ccprintf(response, "%#x", target); + + return response.str(); + } +}}; + +let {{ + class SeqOp(X86Microop): + def __init__(self, target, flags=None): + self.target = target + if flags: + if not isinstance(flags, (list, tuple)): + raise Exception, "flags must be a list or tuple of flags" + self.cond = " | ".join(flags) + self.className += "Flags" + else: + self.cond = "0" + + def getAllocator(self, *microFlags): + allocator = '''new %(class_name)s(machInst, macrocodeBlock + %(flags)s, %(target)s, %(cc)s)''' % { + "class_name" : self.className, + "flags" : self.microFlagsText(microFlags), + "target" : self.target, + "cc" : self.cond} + return allocator + + class Br(SeqOp): + className = "MicroBranch" + + def getAllocator(self, *microFlags): + (is_micro, is_delayed, is_first, is_last) = microFlags + is_last = False + is_delayed = True + microFlags = (is_micro, is_delayed, is_first, is_last) + return super(Br, self).getAllocator(*microFlags) + + class Eret(SeqOp): + target = "normalMicroPC(0)" + className = "Eret" + + def __init__(self, flags=None): + if flags: + if not isinstance(flags, (list, tuple)): + raise Exception, "flags must be a list or tuple of flags" + self.cond = " | ".join(flags) + self.className += "Flags" + else: + self.cond = "0" + + def getAllocator(self, *microFlags): + (is_micro, is_delayed, is_first, is_last) = microFlags + is_last = True + is_delayed = False + microFlags = (is_micro, is_delayed, is_first, is_last) + return super(Eret, self).getAllocator(*microFlags) + + iop = InstObjParams("br", "MicroBranchFlags", "SeqOpBase", + {"code": "nuIP = target", + "else_code": "nuIP = nuIP", + "cond_test": "checkCondition(ccFlagBits, cc)"}) + exec_output += SeqOpExecute.subst(iop) + header_output += SeqOpDeclare.subst(iop) + decoder_output += SeqOpConstructor.subst(iop) + iop = InstObjParams("br", "MicroBranch", "SeqOpBase", + {"code": "nuIP = target", + "else_code": "nuIP = nuIP", + "cond_test": "true"}) + exec_output += SeqOpExecute.subst(iop) + header_output += SeqOpDeclare.subst(iop) + decoder_output += SeqOpConstructor.subst(iop) + microopClasses["br"] = Br + + iop = InstObjParams("eret", "EretFlags", "SeqOpBase", + {"code": "", "else_code": "", + "cond_test": "checkCondition(ccFlagBits, cc)"}) + exec_output += SeqOpExecute.subst(iop) + header_output += SeqOpDeclare.subst(iop) + decoder_output += SeqOpConstructor.subst(iop) + iop = InstObjParams("eret", "Eret", "SeqOpBase", + {"code": "", "else_code": "", + "cond_test": "true"}) + exec_output += SeqOpExecute.subst(iop) + header_output += SeqOpDeclare.subst(iop) + decoder_output += SeqOpConstructor.subst(iop) + microopClasses["eret"] = Eret +}}; diff --git a/src/arch/x86/isa/microops/specop.isa b/src/arch/x86/isa/microops/specop.isa index 6bcc7ff91..c6e172ef1 100644 --- a/src/arch/x86/isa/microops/specop.isa +++ b/src/arch/x86/isa/microops/specop.isa @@ -1,4 +1,4 @@ -// Copyright (c) 2007 The Hewlett-Packard Development Company +// Copyright (c) 2007-2008 The Hewlett-Packard Development Company // All rights reserved. // // Redistribution and use of this software in source and binary forms, @@ -95,6 +95,9 @@ output header {{ } %(BasicExecDeclare)s + + std::string generateDisassembly(Addr pc, + const SymbolTable *symtab) const; }; }}; @@ -201,6 +204,16 @@ output decoder {{ return response.str(); } + + std::string MicroHalt::generateDisassembly(Addr pc, + const SymbolTable *symtab) const + { + std::stringstream response; + + printMnemonic(response, instMnem, mnemonic); + + return response.str(); + } }}; let {{ @@ -217,7 +230,7 @@ let {{ self.cond = "0" def getAllocator(self, *microFlags): - allocator = '''new %(class_name)s(machInst, mnemonic + allocator = '''new %(class_name)s(machInst, macrocodeBlock %(flags)s, %(fault)s, %(cc)s)''' % { "class_name" : self.className, "flags" : self.microFlagsText(microFlags), @@ -244,7 +257,7 @@ let {{ pass def getAllocator(self, *microFlags): - return "new MicroHalt(machInst, mnemonic %s)" % \ + return "new MicroHalt(machInst, macrocodeBlock %s)" % \ self.microFlagsText(microFlags) microopClasses["halt"] = Halt diff --git a/src/arch/x86/isa/operands.isa b/src/arch/x86/isa/operands.isa index 9345158e9..ab1e9a851 100644 --- a/src/arch/x86/isa/operands.isa +++ b/src/arch/x86/isa/operands.isa @@ -26,7 +26,7 @@ // // Authors: Gabe Black -// Copyright (c) 2007 The Hewlett-Packard Development Company +// Copyright (c) 2007-2008 The Hewlett-Packard Development Company // All rights reserved. // // Redistribution and use of this software in source and binary forms, @@ -109,7 +109,14 @@ def operands {{ 'Quotient': ('IntReg', 'uqw', 'INTREG_IMPLICIT(2)', 'IsInteger', 9), 'Remainder': ('IntReg', 'uqw', 'INTREG_IMPLICIT(3)', 'IsInteger', 10), 'Divisor': ('IntReg', 'uqw', 'INTREG_IMPLICIT(4)', 'IsInteger', 11), - 'rax': ('IntReg', 'uqw', '(INTREG_RAX)', 'IsInteger', 12), + 'Rax': ('IntReg', 'uqw', '(INTREG_RAX)', 'IsInteger', 12), + 'Rbx': ('IntReg', 'uqw', '(INTREG_RBX)', 'IsInteger', 13), + 'Rcx': ('IntReg', 'uqw', '(INTREG_RCX)', 'IsInteger', 14), + 'Rdx': ('IntReg', 'uqw', '(INTREG_RDX)', 'IsInteger', 15), + 'Rsp': ('IntReg', 'uqw', '(INTREG_RSP)', 'IsInteger', 16), + 'Rbp': ('IntReg', 'uqw', '(INTREG_RBP)', 'IsInteger', 17), + 'Rsi': ('IntReg', 'uqw', '(INTREG_RSI)', 'IsInteger', 18), + 'Rdi': ('IntReg', 'uqw', '(INTREG_RDI)', 'IsInteger', 19), 'FpSrcReg1': ('FloatReg', 'df', 'src1', 'IsFloating', 20), 'FpSrcReg2': ('FloatReg', 'df', 'src2', 'IsFloating', 21), 'FpDestReg': ('FloatReg', 'df', 'dest', 'IsFloating', 22), @@ -117,10 +124,13 @@ def operands {{ 'RIP': ('NPC', 'uqw', None, (None, None, 'IsControl'), 50), 'uIP': ('UPC', 'uqw', None, (None, None, 'IsControl'), 51), 'nuIP': ('NUPC', 'uqw', None, (None, None, 'IsControl'), 52), + # This holds the condition code portion of the flag register. The + # nccFlagBits version holds the rest. 'ccFlagBits': ('IntReg', 'uqw', 'INTREG_PSEUDO(0)', None, 60), - # The TOP register should needs to be more protected so that later + # These register should needs to be more protected so that later # instructions don't map their indexes with an old value. - 'TOP': ('ControlReg', 'ub', 'MISCREG_X87_TOP', None, 61), + 'nccFlagBits': ('ControlReg', 'uqw', 'MISCREG_RFLAGS', None, 61), + 'TOP': ('ControlReg', 'ub', 'MISCREG_X87_TOP', None, 62), # The segment base as used by memory instructions. 'SegBase': ('ControlReg', 'uqw', 'MISCREG_SEG_EFF_BASE(segment)', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 70), @@ -128,23 +138,31 @@ def operands {{ # original instruction. 'ControlDest': ('ControlReg', 'uqw', 'MISCREG_CR(dest)', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 100), 'ControlSrc1': ('ControlReg', 'uqw', 'MISCREG_CR(src1)', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 101), - 'SegBaseDest': ('ControlReg', 'uqw', 'MISCREG_SEG_BASE(dest)', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 102), - 'SegBaseSrc1': ('ControlReg', 'uqw', 'MISCREG_SEG_BASE(src1)', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 103), - 'SegLimitDest': ('ControlReg', 'uqw', 'MISCREG_SEG_LIMIT(dest)', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 104), - 'SegLimitSrc1': ('ControlReg', 'uqw', 'MISCREG_SEG_LIMIT(src1)', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 105), - 'SegSelDest': ('ControlReg', 'uqw', 'MISCREG_SEG_SEL(dest)', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 106), - 'SegSelSrc1': ('ControlReg', 'uqw', 'MISCREG_SEG_SEL(src1)', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 107), - 'SegAttrDest': ('ControlReg', 'uqw', 'MISCREG_SEG_ATTR(dest)', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 108), - 'SegAttrSrc1': ('ControlReg', 'uqw', 'MISCREG_SEG_ATTR(src1)', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 109), + 'DebugDest': ('ControlReg', 'uqw', 'MISCREG_DR(dest)', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 102), + 'DebugSrc1': ('ControlReg', 'uqw', 'MISCREG_DR(src1)', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 103), + 'SegBaseDest': ('ControlReg', 'uqw', 'MISCREG_SEG_BASE(dest)', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 104), + 'SegBaseSrc1': ('ControlReg', 'uqw', 'MISCREG_SEG_BASE(src1)', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 105), + 'SegLimitDest': ('ControlReg', 'uqw', 'MISCREG_SEG_LIMIT(dest)', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 106), + 'SegLimitSrc1': ('ControlReg', 'uqw', 'MISCREG_SEG_LIMIT(src1)', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 107), + 'SegSelDest': ('ControlReg', 'uqw', 'MISCREG_SEG_SEL(dest)', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 108), + 'SegSelSrc1': ('ControlReg', 'uqw', 'MISCREG_SEG_SEL(src1)', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 109), + 'SegAttrDest': ('ControlReg', 'uqw', 'MISCREG_SEG_ATTR(dest)', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 110), + 'SegAttrSrc1': ('ControlReg', 'uqw', 'MISCREG_SEG_ATTR(src1)', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 111), # Operands to access specific control registers directly. 'EferOp': ('ControlReg', 'uqw', 'MISCREG_EFER', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 200), 'CR4Op': ('ControlReg', 'uqw', 'MISCREG_CR4', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 201), - 'LDTRBase': ('ControlReg', 'uqw', 'MISCREG_TSL_BASE', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 202), - 'LDTRLimit': ('ControlReg', 'uqw', 'MISCREG_TSL_LIMIT', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 203), - 'LDTRSel': ('ControlReg', 'uqw', 'MISCREG_TSL', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 204), - 'GDTRBase': ('ControlReg', 'uqw', 'MISCREG_TSG_BASE', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 205), - 'GDTRLimit': ('ControlReg', 'uqw', 'MISCREG_TSG_LIMIT', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 206), - 'CSBase': ('ControlReg', 'udw', 'MISCREG_CS_EFF_BASE', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 207), + 'DR7Op': ('ControlReg', 'uqw', 'MISCREG_DR7', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 202), + 'LDTRBase': ('ControlReg', 'uqw', 'MISCREG_TSL_BASE', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 203), + 'LDTRLimit': ('ControlReg', 'uqw', 'MISCREG_TSL_LIMIT', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 204), + 'LDTRSel': ('ControlReg', 'uqw', 'MISCREG_TSL', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 205), + 'GDTRBase': ('ControlReg', 'uqw', 'MISCREG_TSG_BASE', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 206), + 'GDTRLimit': ('ControlReg', 'uqw', 'MISCREG_TSG_LIMIT', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 207), + 'CSBase': ('ControlReg', 'udw', 'MISCREG_CS_EFF_BASE', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 208), + 'CSAttr': ('ControlReg', 'udw', 'MISCREG_CS_ATTR', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 209), + 'MiscRegDest': ('ControlReg', 'uqw', 'dest', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 210), + 'MiscRegSrc1': ('ControlReg', 'uqw', 'src1', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 211), + 'TscOp': ('ControlReg', 'uqw', 'MISCREG_TSC', (None, None, ['IsSerializeAfter', 'IsSerializing', 'IsNonSpeculative']), 212), + 'M5Reg': ('ControlReg', 'uqw', 'MISCREG_M5_REG', (None, None, None), 213), 'Mem': ('Mem', 'uqw', None, ('IsMemRef', 'IsLoad', 'IsStore'), 300) }}; diff --git a/src/arch/x86/isa/rom.isa b/src/arch/x86/isa/rom.isa new file mode 100644 index 000000000..7d3eb8670 --- /dev/null +++ b/src/arch/x86/isa/rom.isa @@ -0,0 +1,90 @@ +// Copyright (c) 2008 The Regents of The University of Michigan +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: 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 holders nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// 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 + +def template MicroRomConstructor {{ + + %(define_generators)s + const MicroPC X86ISA::MicrocodeRom::numMicroops = %(num_microops)s; + + X86ISA::MicrocodeRom::MicrocodeRom() + { + using namespace RomLabels; + genFuncs = new GenFunc[numMicroops]; + %(alloc_generators)s; + } +}}; + +let {{ + from micro_asm import Rom + + class X86MicrocodeRom(Rom): + def __init__(self, name): + super(X86MicrocodeRom, self).__init__(name) + self.directives = {} + + def add_microop(self, mnemonic, microop): + microop.mnemonic = mnemonic + microop.micropc = len(self.microops) + self.microops.append(microop) + + + def getDeclaration(self): + declareLabels = "namespace RomLabels {\n" + for (label, microop) in self.labels.items(): + declareLabels += "const static uint64_t label_%s = %d;\n" \ + % (label, microop.micropc) + for (label, microop) in self.externs.items(): + declareLabels += \ + "const static MicroPC extern_label_%s = %d;\n" \ + % (label, microop.micropc) + declareLabels += "}\n" + return declareLabels; + + def getDefinition(self): + numMicroops = len(self.microops) + allocGenerators = '' + micropc = 0 + define_generators = ''' + namespace + { + static const char romMnemonic[] = "Microcode_ROM"; + ''' + for op in self.microops: + define_generators += op.getGeneratorDef(micropc) + allocGenerators += "genFuncs[%d] = %s;\n" % \ + (micropc, op.getGenerator(micropc)) + micropc += 1 + define_generators += "}\n" + iop = InstObjParams(self.name, self.name, "MicrocodeRom", + {"code" : "", + "define_generators" : define_generators, + "num_microops" : numMicroops, + "alloc_generators" : allocGenerators + }) + return MicroRomConstructor.subst(iop); +}}; diff --git a/src/arch/x86/isa/specialize.isa b/src/arch/x86/isa/specialize.isa index abf734307..b74363470 100644 --- a/src/arch/x86/isa/specialize.isa +++ b/src/arch/x86/isa/specialize.isa @@ -86,8 +86,17 @@ let {{ let {{ def doRipRelativeDecode(Name, opTypes, env): # print "RIPing %s with opTypes %s" % (Name, opTypes) - normBlocks = specializeInst(Name + "_M", copy.copy(opTypes), copy.copy(env)) - ripBlocks = specializeInst(Name + "_P", copy.copy(opTypes), copy.copy(env)) + env.memoryInst = True + normEnv = copy.copy(env) + normEnv.addToDisassembly( + '''printMem(out, env.seg, env.scale, env.index, env.base, + machInst.displacement, env.addressSize, false);''') + normBlocks = specializeInst(Name + "_M", copy.copy(opTypes), normEnv) + ripEnv = copy.copy(env) + ripEnv.addToDisassembly( + '''printMem(out, env.seg, 1, 0, 0, + machInst.displacement, env.addressSize, true);''') + ripBlocks = specializeInst(Name + "_P", copy.copy(opTypes), ripEnv) blocks = OutputBlocks() blocks.append(normBlocks) @@ -138,12 +147,17 @@ let {{ #Figure out what to do with fixed register operands #This is the index to use, so we should stick it some place. if opType.reg in ("A", "B", "C", "D"): - env.addReg("INTREG_R%sX" % opType.reg) + regString = "INTREG_R%sX" % opType.reg else: - env.addReg("INTREG_R%s" % opType.reg) + regString = "INTREG_R%s" % opType.reg + env.addReg(regString) + env.addToDisassembly( + "printReg(out, %s, regSize);\n" % regString) Name += "_R" elif opType.tag == "B": # This refers to registers whose index is encoded as part of the opcode + env.addToDisassembly( + "printReg(out, %s, regSize);\n" % InstRegIndex) Name += "_R" env.addReg(InstRegIndex) elif opType.tag == "M": @@ -156,24 +170,34 @@ let {{ elif opType.tag == "C": # A control register indexed by the "reg" field env.addReg(ModRMRegIndex) + env.addToDisassembly( + "ccprintf(out, \"CR%%d\", %s);\n" % ModRMRegIndex) Name += "_C" elif opType.tag == "D": # A debug register indexed by the "reg" field env.addReg(ModRMRegIndex) + env.addToDisassembly( + "ccprintf(out, \"DR%%d\", %s);\n" % ModRMRegIndex) Name += "_D" elif opType.tag == "S": # A segment selector register indexed by the "reg" field env.addReg(ModRMRegIndex) + env.addToDisassembly( + "printSegment(out, %s);\n" % ModRMRegIndex) Name += "_S" elif opType.tag in ("G", "P", "T", "V"): # Use the "reg" field of the ModRM byte to select the register env.addReg(ModRMRegIndex) + env.addToDisassembly( + "printReg(out, %s, regSize);\n" % ModRMRegIndex) Name += "_R" elif opType.tag in ("E", "Q", "W"): # This might refer to memory or to a register. We need to # divide it up farther. regEnv = copy.copy(env) regEnv.addReg(ModRMRMIndex) + regEnv.addToDisassembly( + "printReg(out, %s, regSize);\n" % ModRMRMIndex) # This refers to memory. The macroop constructor should set up # modrm addressing. memEnv = copy.copy(env) @@ -183,6 +207,8 @@ let {{ (doRipRelativeDecode, Name, copy.copy(opTypes), memEnv)) elif opType.tag in ("I", "J"): # Immediates + env.addToDisassembly( + "ccprintf(out, \"%#x\", machInst.immediate);\n") Name += "_I" elif opType.tag == "O": # Immediate containing a memory offset @@ -190,10 +216,22 @@ let {{ elif opType.tag in ("PR", "R", "VR"): # Non register modrm settings should cause an error env.addReg(ModRMRMIndex) + env.addToDisassembly( + "printReg(out, %s, regSize);\n" % ModRMRMIndex) Name += "_R" elif opType.tag in ("X", "Y"): # This type of memory addressing is for string instructions. # They'll use the right index and segment internally. + if opType.tag == "X": + env.addToDisassembly( + '''printMem(out, env.seg, + 1, X86ISA::ZeroReg, X86ISA::INTREG_RSI, 0, + env.addressSize, false);''') + else: + env.addToDisassembly( + '''printMem(out, SEGMENT_REG_ES, + 1, X86ISA::ZeroReg, X86ISA::INTREG_RDI, 0, + env.addressSize, false);''') Name += "_M" else: raise Exception, "Unrecognized tag %s." % opType.tag |