diff options
Diffstat (limited to 'arch/mips')
28 files changed, 4986 insertions, 0 deletions
diff --git a/arch/mips/SConscript b/arch/mips/SConscript new file mode 100644 index 000000000..b8efa7ef9 --- /dev/null +++ b/arch/mips/SConscript @@ -0,0 +1,83 @@ +# -*- mode:python -*- + +# Copyright (c) 2004-2005 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. + +import os +import sys +from os.path import isdir + +# Import build environment variable from SConstruct. +Import('env') + +################################################### +# +# Define needed sources. +# +################################################### + +# Base sources used by all configurations. +base_sources = Split(''' + faults.cc + isa_traits.cc + ''') + +# Full-system sources +full_system_sources = Split(''' + memory.cc + arguments.cc + mips34k.cc + osfpal.cc + stacktrace.cc + vtophys.cc + ''') + +# Syscall emulation (non-full-system) sources +syscall_emulation_sources = Split(''' + common_syscall_emul.cc + linux_process.cc + tru64_process.cc + ''') + +# Set up complete list of sources based on configuration. +sources = base_sources + +if env['FULL_SYSTEM']: + sources += full_system_sources +else: + sources += syscall_emulation_sources + +# Convert file names to SCons File objects. This takes care of the +# path relative to the top of the directory tree. +sources = [File(s) for s in sources] + +# Add in files generated by the ISA description. +isa_desc_files = env.ISADesc('isa/main.isa') +# Only non-header files need to be compiled. +isa_desc_sources = [f for f in isa_desc_files if not f.path.endswith('.hh')] +sources += isa_desc_sources + +Return('sources') diff --git a/arch/mips/faults.cc b/arch/mips/faults.cc new file mode 100644 index 000000000..142dfe0a4 --- /dev/null +++ b/arch/mips/faults.cc @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2003-2005 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. + */ + +#include "arch/mips/faults.hh" + +ResetFaultType * const ResetFault = + new ResetFaultType("reset", 1, 0x0001); +ArithmeticFaultType * const ArithmeticFault = + new ArithmeticFaultType("arith", 3, 0x0501); +InterruptFaultType * const InterruptFault = + new InterruptFaultType("interrupt", 4, 0x0101); +NDtbMissFaultType * const NDtbMissFault = + new NDtbMissFaultType("dtb_miss_single", 5, 0x0201); +PDtbMissFaultType * const PDtbMissFault = + new PDtbMissFaultType("dtb_miss_double", 6, 0x0281); +DtbPageFaultType * const DtbPageFault = + new DtbPageFaultType("dfault", 8, 0x0381); +DtbAcvFaultType * const DtbAcvFault = + new DtbAcvFaultType("dfault", 9, 0x0381); +ItbMissFaultType * const ItbMissFault = + new ItbMissFaultType("itbmiss", 10, 0x0181); +ItbPageFaultType * const ItbPageFault = + new ItbPageFaultType("itbmiss", 11, 0x0181); +ItbAcvFaultType * const ItbAcvFault = + new ItbAcvFaultType("iaccvio", 12, 0x0081); +UnimplementedOpcodeFaultType * const UnimplementedOpcodeFault = + new UnimplementedOpcodeFaultType("opdec", 13, 0x0481); +FloatEnableFaultType * const FloatEnableFault = + new FloatEnableFaultType("fen", 14, 0x0581); +PalFaultType * const PalFault = + new PalFaultType("pal", 15, 0x2001); +IntegerOverflowFaultType * const IntegerOverflowFault = + new IntegerOverflowFaultType("intover", 16, 0x0501); + +Fault ** ListOfFaults[] = { + (Fault **)&NoFault, + (Fault **)&ResetFault, + (Fault **)&MachineCheckFault, + (Fault **)&ArithmeticFault, + (Fault **)&InterruptFault, + (Fault **)&NDtbMissFault, + (Fault **)&PDtbMissFault, + (Fault **)&AlignmentFault, + (Fault **)&DtbPageFault, + (Fault **)&DtbAcvFault, + (Fault **)&ItbMissFault, + (Fault **)&ItbPageFault, + (Fault **)&ItbAcvFault, + (Fault **)&UnimplementedOpcodeFault, + (Fault **)&FloatEnableFault, + (Fault **)&PalFault, + (Fault **)&IntegerOverflowFault, + }; + +int NumFaults = sizeof(ListOfFaults) / sizeof(Fault **); diff --git a/arch/mips/faults.hh b/arch/mips/faults.hh new file mode 100644 index 000000000..c1cb956b0 --- /dev/null +++ b/arch/mips/faults.hh @@ -0,0 +1,160 @@ +/* + * Copyright (c) 2003-2005 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. + */ + +#ifndef __MIPS_FAULTS_HH__ +#define __MIPS_FAULTS_HH__ + +#include "sim/faults.hh" +#include "arch/isa_traits.hh" //For the Addr type + +class MipsFault : public FaultBase +{ + public: + MipsFault(char * newName, int newId, Addr newVect) + : FaultBase(newName, newId), vect(newVect) + {;} + + Addr vect; +}; + +extern class ResetFaultType : public MipsFault +{ + public: + ResetFaultType(char * newName, int newId, Addr newVect) + : MipsFault(newName, newId, newVect) + {;} +} * const ResetFault; + +extern class ArithmeticFaultType : public MipsFault +{ + public: + ArithmeticFaultType(char * newName, int newId, Addr newVect) + : MipsFault(newName, newId, newVect) + {;} +} * const ArithmeticFault; + +extern class InterruptFaultType : public MipsFault +{ + public: + InterruptFaultType(char * newName, int newId, Addr newVect) + : MipsFault(newName, newId, newVect) + {;} +} * const InterruptFault; + +extern class NDtbMissFaultType : public MipsFault +{ + public: + NDtbMissFaultType(char * newName, int newId, Addr newVect) + : MipsFault(newName, newId, newVect) + {;} +} * const NDtbMissFault; + +extern class PDtbMissFaultType : public MipsFault +{ + public: + PDtbMissFaultType(char * newName, int newId, Addr newVect) + : MipsFault(newName, newId, newVect) + {;} +} * const PDtbMissFault; + +extern class DtbPageFaultType : public MipsFault +{ + public: + DtbPageFaultType(char * newName, int newId, Addr newVect) + : MipsFault(newName, newId, newVect) + {;} +} * const DtbPageFault; + +extern class DtbAcvFaultType : public MipsFault +{ + public: + DtbAcvFaultType(char * newName, int newId, Addr newVect) + : MipsFault(newName, newId, newVect) + {;} +} * const DtbAcvFault; + +extern class ItbMissFaultType : public MipsFault +{ + public: + ItbMissFaultType(char * newName, int newId, Addr newVect) + : MipsFault(newName, newId, newVect) + {;} +} * const ItbMissFault; + +extern class ItbPageFaultType : public MipsFault +{ + public: + ItbPageFaultType(char * newName, int newId, Addr newVect) + : MipsFault(newName, newId, newVect) + {;} +} * const ItbPageFault; + +extern class ItbAcvFaultType : public MipsFault +{ + public: + ItbAcvFaultType(char * newName, int newId, Addr newVect) + : MipsFault(newName, newId, newVect) + {;} +} * const ItbAcvFault; + +extern class UnimplementedOpcodeFaultType : public MipsFault +{ + public: + UnimplementedOpcodeFaultType(char * newName, int newId, Addr newVect) + : MipsFault(newName, newId, newVect) + {;} +} * const UnimplementedOpcodeFault; + +extern class FloatEnableFaultType : public MipsFault +{ + public: + FloatEnableFaultType(char * newName, int newId, Addr newVect) + : MipsFault(newName, newId, newVect) + {;} +} * const FloatEnableFault; + +extern class PalFaultType : public MipsFault +{ + public: + PalFaultType(char * newName, int newId, Addr newVect) + : MipsFault(newName, newId, newVect) + {;} +} * const PalFault; + +extern class IntegerOverflowFaultType : public MipsFault +{ + public: + IntegerOverflowFaultType(char * newName, int newId, Addr newVect) + : MipsFault(newName, newId, newVect) + {;} +} * const IntegerOverflowFault; + +extern Fault ** ListOfFaults[]; +extern int NumFaults; + +#endif // __FAULTS_HH__ diff --git a/arch/mips/isa/base.isa b/arch/mips/isa/base.isa new file mode 100644 index 000000000..4125b5101 --- /dev/null +++ b/arch/mips/isa/base.isa @@ -0,0 +1,96 @@ +// -*- mode:c++ -*- + +//////////////////////////////////////////////////////////////////// +// +// Base class for MIPS instructions, and some support functions +// + +//Outputs to decoder.hh +output header {{ + +#define R31 31 +#include "arch/mips/faults.hh" +#include "arch/mips/isa_traits.hh" + + using namespace MipsISA; + + + /** + * Base class for all MIPS static instructions. + */ + class MipsStaticInst : public StaticInst + { + protected: + + /// Make MipsISA register dependence tags directly visible in + /// this class and derived classes. Maybe these should really + /// live here and not in the MipsISA namespace. + /*enum DependenceTags { + FP_Base_DepTag = MipsISA::FP_Base_DepTag, + Fpcr_DepTag = MipsISA::Fpcr_DepTag, + Uniq_DepTag = MipsISA::Uniq_DepTag, + IPR_Base_DepTag = MipsISA::IPR_Base_DepTag + };*/ + + // Constructor + MipsStaticInst(const char *mnem, MachInst _machInst, OpClass __opClass) + : StaticInst(mnem, _machInst, __opClass) + { + } + + /// Print a register name for disassembly given the unique + /// dependence tag number (FP or int). + void printReg(std::ostream &os, int reg) const; + + std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; + }; + +}}; + +//Ouputs to decoder.cc +output decoder {{ + + void MipsStaticInst::printReg(std::ostream &os, int reg) const + { + if (reg < FP_Base_DepTag) { + ccprintf(os, "r%d", reg); + } + else { + ccprintf(os, "f%d", reg - FP_Base_DepTag); + } + } + + std::string MipsStaticInst::generateDisassembly(Addr pc, const SymbolTable *symtab) const + { + std::stringstream ss; + + ccprintf(ss, "%-10s ", mnemonic); + + // just print the first two source regs... if there's + // a third one, it's a read-modify-write dest (Rc), + // e.g. for CMOVxx + if(_numSrcRegs > 0) + { + printReg(ss, _srcRegIdx[0]); + } + + if(_numSrcRegs > 1) + { + ss << ","; + printReg(ss, _srcRegIdx[1]); + } + + // just print the first dest... if there's a second one, + // it's generally implicit + if(_numDestRegs > 0) + { + if(_numSrcRegs > 0) + ss << ","; + printReg(ss, _destRegIdx[0]); + } + + return ss.str(); + } + +}}; + diff --git a/arch/mips/isa/bitfields.isa b/arch/mips/isa/bitfields.isa new file mode 100644 index 000000000..58d487ad2 --- /dev/null +++ b/arch/mips/isa/bitfields.isa @@ -0,0 +1,67 @@ +// -*- mode:c++ -*- + +//////////////////////////////////////////////////////////////////// +// +// Bitfield definitions. +// + +def bitfield OPCODE <31:26>; +def bitfield OPCODE_HI <31:29>; +def bitfield OPCODE_LO <28:26>; + +def bitfield REGIMM <20:16>; +def bitfield REGIMM_HI <20:19>; +def bitfield REGIMM_LO <18:16>; + +def bitfield FUNCTION < 5: 0>; +def bitfield FUNCTION_HI < 5: 3>; +def bitfield FUNCTION_LO < 2: 0>; + +// Integer operate format +def bitfield RT <20:16>; +def bitfield RT_HI <20:19>; +def bitfield RT_LO <18:16>; + +def bitfield RS <25:21>; +def bitfield RS_MSB <25:25>; +def bitfield RS_HI <25:24>; +def bitfield RS_LO <23:21>; + +def bitfield RD <15:11>; + +def bitfield INTIMM <15: 0>; // integer immediate (literal) + +// Floating-point operate format +def bitfield FMT <25:21>; +def bitfield FR <25:21>; +def bitfield FT <20:16>; +def bitfield FS <15:11>; +def bitfield FD <10:6>; + +def bitfield CC <20:18>; +def bitfield ND <17:17>; +def bitfield TF <16:16>; +def bitfield MOVCI <16:16>; +def bitfield MOVCF <16:16>; +def bitfield SRL <21:21>; +def bitfield SRLV < 6: 6>; +def bitfield SA <10: 6>; + +// CP0 Register Select +def bitfield SEL < 2: 0>; + +// Interrupts +def bitfield SC < 5: 5>; + +// Branch format +def bitfield OFFSET <15: 0>; // displacement + +// Jmp format +def bitfield JMPTARG <25: 0>; +def bitfield HINT <10: 6>; + +def bitfield SYSCALLCODE <25: 6>; +def bitfield TRAPCODE <15:13>; + +// M5 instructions +def bitfield M5FUNC <7:0>; diff --git a/arch/mips/isa/decoder.isa b/arch/mips/isa/decoder.isa new file mode 100644 index 000000000..3f054f6a5 --- /dev/null +++ b/arch/mips/isa/decoder.isa @@ -0,0 +1,930 @@ +// -*- mode:c++ -*- + +//////////////////////////////////////////////////////////////////// +// +// The actual MIPS32 ISA decoder +// ----------------------------- +// The following instructions are specified in the MIPS32 ISA +// Specification. Decoding closely follows the style specified +// in the MIPS32 ISAthe specification document starting with Table +// A-2 (document available @ www.mips.com) +// +//@todo: Distinguish "unknown/future" use insts from "reserved" +// ones +decode OPCODE_HI default Unknown::unknown() { + + // Derived From ... Table A-2 MIPS32 ISA Manual + 0x0: decode OPCODE_LO { + + 0x0: decode FUNCTION_HI { + 0x0: decode FUNCTION_LO { + 0x1: decode MOVCI { + format BasicOp { + 0: movf({{ if (xc->readMiscReg(FPCR,0) != CC) Rd = Rs}}); + 1: movt({{ if (xc->readMiscReg(FPCR,0) == CC) Rd = Rs}}); + } + } + + format BasicOp { + + //Table A-3 Note: "1. Specific encodings of the rt, rd, and sa fields + //are used to distinguish among the SLL, NOP, SSNOP and EHB functions." + + 0x0: decode RS { + 0x0: decode RT default BasicOp::sll({{ Rd = Rt.uw << SA; }}) { + 0x0: decode RD{ + 0x0: decode HINT { + 0x0:nop({{}}); //really sll r0,r0,0 + 0x1:ssnop({{}});//really sll r0,r0,1 + 0x3:ehb({{}}); //really sll r0,r0,3 + } + } + } + } + + 0x2: decode SRL { + 0: srl({{ Rd = Rt.uw >> SA; }}); + + //Hardcoded assuming 32-bit ISA, probably need parameter here + 1: rotr({{ Rd = (Rt.uw << (32 - SA)) | (Rt.uw >> SA);}}); + } + + 0x3: sra({{ Rd = Rt.sw >> SA; }}); + + 0x4: sllv({{ Rd = Rt.uw << Rs<4:0>; }}); + + 0x6: decode SRLV { + 0: srlv({{ Rd = Rt.uw >> Rs<4:0>; }}); + + //Hardcoded assuming 32-bit ISA, probably need parameter here + 1: rotrv({{ Rd = (Rt.uw << (32 - Rs<4:0>)) | (Rt.uw >> Rs<4:0>);}}); + } + + 0x7: srav({{ Rd = Rt.sw >> Rs<4:0>; }}); + } + } + + 0x1: decode FUNCTION_LO { + + //Table A-3 Note: "Specific encodings of the hint field are used + //to distinguish JR from JR.HB and JALR from JALR.HB" + format Jump { + 0x0: decode HINT { + 0:jr({{ NNPC = Rs & ~1; }},IsReturn); + + 1:jr_hb({{ NNPC = Rs & ~1; clear_exe_inst_hazards(); }},IsReturn); + } + + 0x1: decode HINT { + 0: jalr({{ NNPC = Rs; }},IsCall,IsReturn); + + 1: jalr_hb({{ NNPC = Rs; clear_exe_inst_hazards();}},IsCall,IsReturn); + } + } + + format BasicOp { + 0x2: movz({{ if (Rt == 0) Rd = Rs; }}); + 0x3: movn({{ if (Rt != 0) Rd = Rs; }}); + } + + format WarnUnimpl { + 0x4: syscall();//{{ xc->syscall()}},IsNonSpeculative + 0x5: break(); + 0x7: sync(); + } + } + + 0x2: decode FUNCTION_LO { + format BasicOp { + 0x0: mfhi({{ Rd = xc->readMiscReg(Hi); }}); + 0x1: mthi({{ xc->setMiscReg(Hi,Rs); }}); + 0x2: mflo({{ Rd = xc->readMiscReg(Lo); }}); + 0x3: mtlo({{ xc->setMiscReg(Lo,Rs); }}); + } + } + + 0x3: decode FUNCTION_LO { + format IntOp { + 0x0: mult({{ + int64_t temp1 = Rs.sw * Rt.sw; + xc->setMiscReg(Hi,temp1<63:32>); + xc->setMiscReg(Lo,temp1<31:0>); + }}); + + 0x1: multu({{ + int64_t temp1 = Rs.uw * Rt.uw; + xc->setMiscReg(Hi,temp1<63:32>); + xc->setMiscReg(Lo,temp1<31:0>); + }}); + + 0x2: div({{ + xc->setMiscReg(Hi,Rs.sw % Rt.sw); + xc->setMiscReg(Lo,Rs.sw / Rt.sw); + }}); + + 0x3: divu({{ + xc->setMiscReg(Hi,Rs.uw % Rt.uw); + xc->setMiscReg(Lo,Rs.uw / Rt.uw); + }}); + } + } + + 0x4: decode FUNCTION_LO { + format IntOp { + 0x0: add({{ Rd.sw = Rs.sw + Rt.sw;/*Trap on Overflow*/}}); + 0x1: addu({{ Rd.sw = Rs.sw + Rt.sw;}}); + 0x2: sub({{ Rd.sw = Rs.sw - Rt.sw; /*Trap on Overflow*/}}); + 0x3: subu({{ Rd.sw = Rs.sw - Rt.uw;}}); + 0x4: and({{ Rd = Rs & Rt;}}); + 0x5: or({{ Rd = Rs | Rt;}}); + 0x6: xor({{ Rd = Rs ^ Rt;}}); + 0x7: nor({{ Rd = ~(Rs | Rt);}}); + } + } + + 0x5: decode FUNCTION_LO { + format IntOp{ + 0x2: slt({{ Rd.sw = ( Rs.sw < Rt.sw ) ? 1 : 0}}); + 0x3: sltu({{ Rd.uw = ( Rs.uw < Rt.uw ) ? 1 : 0}}); + } + } + + 0x6: decode FUNCTION_LO { + format Trap { + 0x0: tge({{ cond = (Rs.sw >= Rt.sw); }}); + 0x1: tgeu({{ cond = (Rs.uw >= Rt.uw); }}); + 0x2: tlt({{ cond = (Rs.sw < Rt.sw); }}); + 0x3: tltu({{ cond = (Rs.uw >= Rt.uw); }}); + 0x4: teq({{ cond = (Rs.sw == Rt.sw); }}); + 0x6: tne({{ cond = (Rs.sw != Rt.sw); }}); + } + } + } + + 0x1: decode REGIMM_HI { + 0x0: decode REGIMM_LO { + format Branch { + 0x0: bltz({{ cond = (Rs.sw < 0); }}); + 0x1: bgez({{ cond = (Rs.sw >= 0); }}); + } + + format BranchLikely { + //MIPS obsolete instructions + 0x2: bltzl({{ cond = (Rs.sw < 0); }}); + 0x3: bgezl({{ cond = (Rs.sw >= 0); }}); + } + } + + 0x1: decode REGIMM_LO { + format Trap { + 0x0: tgei( {{ cond = (Rs.sw >= INTIMM); }}); + 0x1: tgeiu({{ cond = (Rs.uw >= INTIMM); }}); + 0x2: tlti( {{ cond = (Rs.sw < INTIMM); }}); + 0x3: tltiu({{ cond = (Rs.uw < INTIMM); }}); + 0x4: teqi( {{ cond = (Rs.sw == INTIMM);}}); + 0x6: tnei( {{ cond = (Rs.sw != INTIMM);}}); + } + } + + 0x2: decode REGIMM_LO { + format Branch { + 0x0: bltzal({{ cond = (Rs.sw < 0); }}, IsCall,IsReturn); + 0x1: bgezal({{ cond = (Rs.sw >= 0); }}, IsCall,IsReturn); + } + + format BranchLikely { + //Will be removed in future MIPS releases + 0x2: bltzall({{ cond = (Rs.sw < 0); }}, IsCall, IsReturn); + 0x3: bgezall({{ cond = (Rs.sw >= 0); }}, IsCall, IsReturn); + } + } + + 0x3: decode REGIMM_LO { + format WarnUnimpl { + 0x7: synci(); + } + } + } + + format Jump { + 0x2: j({{ NNPC = (NPC & 0xF0000000) | (JMPTARG << 2);}}); + + 0x3: jal({{ NNPC = (NPC & 0xF0000000) | (JMPTARG << 2); }},IsCall,IsReturn); + } + + format Branch { + 0x4: beq({{ cond = (Rs.sw == Rt.sw); }}); + 0x5: bne({{ cond = (Rs.sw != Rt.sw); }}); + 0x6: blez({{ cond = (Rs.sw <= 0); }}); + 0x7: bgtz({{ cond = (Rs.sw > 0); }}); + } + } + + 0x1: decode OPCODE_LO { + format IntOp { + 0x0: addi({{ Rt.sw = Rs.sw + imm; /*Trap If Overflow*/}}); + 0x1: addiu({{ Rt.sw = Rs.sw + imm;}}); + 0x2: slti({{ Rt.sw = ( Rs.sw < imm) ? 1 : 0 }}); + 0x3: sltiu({{ Rt.sw = ( Rs.sw < imm ) ? 1 : 0 }}); + 0x4: andi({{ Rt.sw = Rs.sw & INTIMM;}}); + 0x5: ori({{ Rt.sw = Rs.sw | INTIMM;}}); + 0x6: xori({{ Rt.sw = Rs.sw ^ INTIMM;}}); + 0x7: lui({{ Rt = INTIMM << 16}}); + } + } + + 0x2: decode OPCODE_LO { + + //Table A-11 MIPS32 COP0 Encoding of rs Field + 0x0: decode RS_MSB { + 0x0: decode RS { + format System { + 0x0: mfc0({{ + //uint64_t reg_num = Rd.uw; + + Rt = xc->readMiscReg(RD << 5 | SEL); + }}); + + 0x4: mtc0({{ + //uint64_t reg_num = Rd.uw; + + xc->setMiscReg(RD << 5 | SEL,Rt); + }}); + + 0x8: mftr({{ + //The contents of the coprocessor 0 register specified by the + //combination of rd and sel are loaded into general register + //rt. Note that not all coprocessor 0 registers support the + //sel field. In those instances, the sel field must be zero. + + //MT Code Needed Here + }}); + + 0xC: mttr({{ + //The contents of the coprocessor 0 register specified by the + //combination of rd and sel are loaded into general register + //rt. Note that not all coprocessor 0 registers support the + //sel field. In those instances, the sel field must be zero. + + //MT Code Needed Here + }}); + + + 0xA: rdpgpr({{ + //Accessing Previous Shadow Set Register Number + //uint64_t prev = xc->readMiscReg(SRSCtl)/*[PSS]*/; + //uint64_t reg_num = Rt.uw; + + //Rd = xc->regs.IntRegFile[prev]; + //Rd = xc->shadowIntRegFile[prev][reg_num]; + }}); + + 0xB: decode RD { + + 0x0: decode SC { + 0x0: dvpe({{ + int idx; + int sel; + getMiscRegIdx(MVPControl,idx,sel); + Rt.sw = xc->readMiscReg(idx,sel); + xc->setMiscReg(idx,sel); + }}); + + 0x1: evpe({{ + int idx; + int sel; + getMiscRegIdx(MVPControl,idx,sel); + Rt.sw = xc->readMiscReg(idx,sel); + xc->setMiscReg(idx,sel,1); + }}); + } + + 0x1: decode SC { + 0x0: dmt({{ + int idx; + int sel; + getMiscRegIdx(VPEControl,idx,sel); + Rt.sw = xc->readMiscReg(idx,sel); + xc->setMiscReg(idx,sel); + }}); + + 0x1: emt({{ + int idx; + int sel; + getMiscRegIdx(VPEControl,idx,sel); + Rt.sw = xc->readMiscReg(idx,sel); + xc->setMiscReg(idx,sel,1); + }}); + } + + 0xC: decode SC { + 0x0: di({{ + int idx; + int sel; + getMiscRegIdx(Status,idx,sel); + Rt.sw = xc->readMiscReg(idx,sel); + xc->setMiscReg(idx,sel); + }}); + + 0x1: ei({{ + int idx; + int sel; + getMiscRegIdx(Status,idx,sel); + Rt.sw = xc->readMiscReg(idx,sel); + xc->setMiscReg(idx,sel,1); + }}); + } + } + + 0xE: wrpgpr({{ + //Accessing Previous Shadow Set Register Number + //uint64_t prev = xc->readMiscReg(SRSCtl/*[PSS]*/); + //uint64_t reg_num = Rd.uw; + + //xc->regs.IntRegFile[prev]; + //xc->shadowIntRegFile[prev][reg_num] = Rt; + }}); + } + } + + //Table A-12 MIPS32 COP0 Encoding of Function Field When rs=CO + 0x1: decode FUNCTION { + format System { + 0x01: tlbr({{ }}); + 0x02: tlbwi({{ }}); + 0x06: tlbwr({{ }}); + 0x08: tlbp({{ }}); + } + + format WarnUnimpl { + 0x18: eret(); + 0x1F: deret(); + 0x20: wait(); + } + } + } + + //Table A-13 MIPS32 COP1 Encoding of rs Field + 0x1: decode RS_MSB { + + 0x0: decode RS_HI { + 0x0: decode RS_LO { + format FloatOp { + 0x0: mfc1({{ /*Rt.uw = Fs.ud<31:0>;*/ }}); + 0x2: cfc1({{ /*Rt.uw = xc->readMiscReg(FPCR[Fs]);*/}}); + 0x3: mfhc1({{ /*Rt.uw = Fs.ud<63:32>*/;}}); + 0x4: mtc1({{ /*Fs = Rt.uw*/}}); + 0x6: ctc1({{ /*xc->setMiscReg(FPCR[Fs],Rt);*/}}); + 0x7: mthc1({{ /*Fs<63:32> = Rt.uw*/}}); + } + } + + 0x1: decode ND { + 0x0: decode TF { + format Branch { + 0x0: bc1f({{ cond = (xc->readMiscReg(FPCR) == 0); }}); + 0x1: bc1t({{ cond = (xc->readMiscReg(FPCR) == 1); }}); + } + } + + 0x1: decode TF { + format BranchLikely { + 0x0: bc1fl({{ cond = (xc->readMiscReg(FPCR) == 0); }}); + 0x1: bc1tl({{ cond = (xc->readMiscReg(FPCR) == 1); }}); + } + } + } + } + + 0x1: decode RS_HI { + 0x2: decode RS_LO { + + //Table A-14 MIPS32 COP1 Encoding of Function Field When rs=S + //(( single-word )) + 0x0: decode RS_HI { + 0x0: decode RS_LO { + format FloatOp { + 0x0: adds({{ Fd.sf = Fs.sf + Ft.sf;}}); + 0x1: subs({{ Fd.sf = Fs.sf - Ft.sf;}}); + 0x2: muls({{ Fd.sf = Fs.sf * Ft.sf;}}); + 0x3: divs({{ Fd.sf = Fs.sf / Ft.sf;}}); + 0x4: sqrts({{ Fd.sf = sqrt(Fs.sf);}}); + 0x5: abss({{ Fd.sf = fabs(Fs.sf);}}); + 0x6: movs({{ Fd.sf = Fs.sf;}}); + 0x7: negs({{ Fd.sf = -1 * Fs.sf;}}); + } + } + + 0x1: decode RS_LO { + //only legal for 64 bit-FP + format Float64Op { + 0x0: round_l_s({{ Fd = convert_and_round(Fs.sf,RND_NEAREST,FP_LONG,FP_SINGLE);}}); + 0x1: trunc_l_s({{ Fd = convert_and_round(Fs.sf,RND_ZERO,FP_LONG,FP_SINGLE);}}); + 0x2: ceil_l_s({{ Fd = convert_and_round(Fs.sf,RND_UP,FP_LONG,FP_SINGLE);}}); + 0x3: floor_l_s({{ Fd = convert_and_round(Fs.sf,RND_DOWN,FP_LONG,FP_SINGLE);}}); + } + + format FloatOp { + 0x4: round_w_s({{ Fd = convert_and_round(Fs.sf,RND_NEAREST,FP_WORD,FP_SINGLE);}}); + 0x5: trunc_w_s({{ Fd = convert_and_round(Fs.sf,RND_ZERO,FP_WORD,FP_SINGLE);}}); + 0x6: ceil_w_s({{ Fd = convert_and_round(Fs.sf,RND_UP,FP_WORD,FP_SINGLE);}}); + 0x7: floor_w_s({{ Fd = convert_and_round(Fs.sf,RND_DOWN,FP_WORD,FP_SINGLE);}}); + } + } + + 0x2: decode RS_LO { + 0x1: decode MOVCF { + format FloatOp { + 0x0: movfs({{if (xc->readMiscReg(FPCR) != CC) Fd = Fs; }}); + 0x1: movts({{if (xc->readMiscReg(FPCR) == CC) Fd = Fs;}}); + } + } + + format BasicOp { + 0x2: movzs({{ if (Rt == 0) Fd = Fs; }}); + 0x3: movns({{ if (Rt != 0) Fd = Fs; }}); + } + + format Float64Op { + 0x5: recips({{ Fd = 1 / Fs; }}); + 0x6: rsqrts({{ Fd = 1 / sqrt((double)Fs.ud);}}); + } + } + + 0x4: decode RS_LO { + + format FloatOp { + 0x1: cvt_d_s({{ int rnd_mode = xc->readMiscReg(FCSR); + Fd = convert_and_round(Fs.sf,rnd_mode,FP_DOUBLE,FP_SINGLE); + }}); + + 0x4: cvt_w_s({{ int rnd_mode = xc->readMiscReg(FCSR); + Fd = convert_and_round(Fs.sf,rnd_mode,FP_WORD,FP_SINGLE); + }}); + } + + //only legal for 64 bit + format Float64Op { + 0x5: cvt_l_s({{ int rnd_mode = xc->readMiscReg(FCSR); + Fd = convert_and_round(Fs.sf,rnd_mode,FP_LONG,FP_SINGLE); + }}); + + 0x6: cvt_ps_s({{ /*Fd.df = Fs.df<31:0> | Ft.df<31:0>;*/ }}); + } + } + } + + //Table A-15 MIPS32 COP1 Encoding of Function Field When rs=D + 0x1: decode RS_HI { + 0x0: decode RS_LO { + format FloatOp { + 0x0: addd({{ Fd.df = Fs.df + Ft.df;}}); + 0x1: subd({{ Fd.df = Fs.df - Ft.df;}}); + 0x2: muld({{ Fd.df = Fs.df * Ft.df;}}); + 0x3: divd({{ Fd.df = Fs.df / Ft.df;}}); + 0x4: sqrtd({{ Fd.df = sqrt(Fs.df);}}); + 0x5: absd({{ Fd.df = fabs(Fs.df);}}); + 0x6: movd({{ Fd.df = Fs.df;}}); + 0x7: negd({{ Fd.df = -1 * Fs.df;}}); + } + } + + 0x1: decode RS_LO { + //only legal for 64 bit + format Float64Op { + 0x0: round_l_d({{ Fd = convert_and_round(Fs.df,RND_NEAREST,FP_LONG,FP_DOUBLE); }}); + 0x1: trunc_l_d({{ Fd = convert_and_round(Fs.df,RND_ZERO,FP_LONG,FP_DOUBLE);}}); + 0x2: ceil_l_d({{ Fd = convert_and_round(Fs.df,RND_UP,FP_LONG,FP_DOUBLE);}}); + 0x3: floor_l_d({{ Fd = convert_and_round(Fs.df,RND_DOWN,FP_LONG,FP_DOUBLE);}}); + } + + format FloatOp { + 0x4: round_w_d({{ Fd = convert_and_round(Fs.df,RND_NEAREST,FP_LONG,FP_DOUBLE); }}); + 0x5: trunc_w_d({{ Fd = convert_and_round(Fs.df,RND_ZERO,FP_LONG,FP_DOUBLE); }}); + 0x6: ceil_w_d({{ Fd = convert_and_round(Fs.df,RND_UP,FP_LONG,FP_DOUBLE); }}); + 0x7: floor_w_d({{ Fd = convert_and_round(Fs.df,RND_DOWN,FP_LONG,FP_DOUBLE); }}); + } + } + + 0x2: decode RS_LO { + 0x1: decode MOVCF { + format FloatOp { + 0x0: movfd({{if (xc->readMiscReg(FPCR) != CC) Fd.df = Fs.df; }}); + 0x1: movtd({{if (xc->readMiscReg(FPCR) == CC) Fd.df = Fs.df; }}); + } + } + + format BasicOp { + 0x2: movzd({{ if (Rt == 0) Fd.df = Fs.df; }}); + 0x3: movnd({{ if (Rt != 0) Fd.df = Fs.df; }}); + } + + format Float64Op { + 0x5: recipd({{ Fd.df = 1 / Fs.df}}); + 0x6: rsqrtd({{ Fd.df = 1 / sqrt(Fs.df) }}); + } + } + + 0x4: decode RS_LO { + format FloatOp { + 0x0: cvt_s_d({{ + int rnd_mode = xc->readMiscReg(FCSR); + Fd = convert_and_round(Fs.df,rnd_mode,FP_SINGLE,FP_DOUBLE); + }}); + + 0x4: cvt_w_d({{ + int rnd_mode = xc->readMiscReg(FCSR); + Fd = convert_and_round(Fs.df,rnd_mode,FP_WORD,FP_DOUBLE); + }}); + } + + //only legal for 64 bit + format Float64Op { + 0x5: cvt_l_d({{ + int rnd_mode = xc->readMiscReg(FCSR); + Fd = convert_and_round(Fs.df,rnd_mode,FP_LONG,FP_DOUBLE); + }}); + } + } + } + + //Table A-16 MIPS32 COP1 Encoding of Function Field When rs=W + 0x4: decode FUNCTION { + format FloatOp { + 0x20: cvt_s({{ + int rnd_mode = xc->readMiscReg(FCSR); + Fd = convert_and_round(Fs.df,rnd_mode,FP_SINGLE,FP_WORD); + }}); + + 0x21: cvt_d({{ + int rnd_mode = xc->readMiscReg(FCSR); + Fd = convert_and_round(Fs.df,rnd_mode,FP_DOUBLE,FP_WORD); + }}); + } + } + + //Table A-16 MIPS32 COP1 Encoding of Function Field When rs=L1 + //Note: "1. Format type L is legal only if 64-bit floating point operations + //are enabled." + 0x5: decode FUNCTION_HI { + format FloatOp { + 0x10: cvt_s_l({{ + int rnd_mode = xc->readMiscReg(FCSR); + Fd = convert_and_round(Fs.df,rnd_mode,FP_SINGLE,FP_LONG); + }}); + + 0x11: cvt_d_l({{ + int rnd_mode = xc->readMiscReg(FCSR); + Fd = convert_and_round(Fs.df,rnd_mode,FP_DOUBLE,FP_LONG); + }}); + } + } + + //Table A-17 MIPS64 COP1 Encoding of Function Field When rs=PS1 + //Note: "1. Format type PS is legal only if 64-bit floating point operations + //are enabled. " + 0x6: decode RS_HI { + 0x0: decode RS_LO { + format Float64Op { + 0x0: addps({{ //Must Check for Exception Here... Supposed to Operate on Upper and + //Lower Halves Independently but we take simulator shortcut + Fd.df = Fs.df + Ft.df; + }}); + + 0x1: subps({{ //Must Check for Exception Here... Supposed to Operate on Upper and + //Lower Halves Independently but we take simulator shortcut + Fd.df = Fs.df - Ft.df; + }}); + + 0x2: mulps({{ //Must Check for Exception Here... Supposed to Operate on Upper and + //Lower Halves Independently but we take simulator shortcut + Fd.df = Fs.df * Ft.df; + }}); + + 0x5: absps({{ //Must Check for Exception Here... Supposed to Operate on Upper and + //Lower Halves Independently but we take simulator shortcut + Fd.df = fabs(Fs.df); + }}); + + 0x6: movps({{ //Must Check for Exception Here... Supposed to Operate on Upper and + //Lower Halves Independently but we take simulator shortcut + //Fd.df = Fs<31:0> | Ft<31:0>; + }}); + + 0x7: negps({{ //Must Check for Exception Here... Supposed to Operate on Upper and + //Lower Halves Independently but we take simulator shortcut + Fd.df = -1 * Fs.df; + }}); + } + } + + 0x2: decode RS_LO { + 0x1: decode MOVCF { + format Float64Op { + 0x0: movfps({{if (xc->readMiscReg(FPCR) != CC) Fd = Fs;}}); + 0x1: movtps({{if (xc->readMiscReg(FPCR) == CC) Fd = Fs;}}); + } + } + + format BasicOp { + 0x2: movzps({{if (xc->readMiscReg(FPCR) != CC) Fd = Fs; }}); + 0x3: movnps({{if (xc->readMiscReg(FPCR) == CC) Fd = Fs; }}); + } + + } + + 0x4: decode RS_LO { + 0x0: Float64Op::cvt_s_pu({{ + int rnd_mode = xc->readMiscReg(FCSR); + Fd = convert_and_round(Fs.df,rnd_mode,FP_DOUBLE,FP_PS_HI); + }}); + } + + 0x5: decode RS_LO { + format Float64Op { + 0x0: cvt_s_pl({{ + int rnd_mode = xc->readMiscReg(FCSR); + Fd = convert_and_round(Fs.df,rnd_mode,FP_SINGLE,FP_PS_LO); + }}); + 0x4: pll({{ /*Fd.df = Fs<31:0> | Ft<31:0>*/}}); + 0x5: plu({{ /*Fd.df = Fs<31:0> | Ft<63:32>*/}}); + 0x6: pul({{ /*Fd.df = Fs<63:32> | Ft<31:0>*/}}); + 0x7: puu({{ /*Fd.df = Fs<63:32 | Ft<63:32>*/}}); + } + } + } + } + } + } + + //Table A-19 MIPS32 COP2 Encoding of rs Field + 0x2: decode RS_MSB { + 0x0: decode RS_HI { + 0x0: decode RS_LO { + format WarnUnimpl { + 0x0: mfc2(); + 0x2: cfc2(); + 0x3: mfhc2(); + 0x4: mtc2(); + 0x6: ctc2(); + 0x7: mftc2(); + } + } + + 0x1: decode ND { + 0x0: decode TF { + format WarnUnimpl { + 0x0: bc2f(); + 0x1: bc2t(); + } + } + + 0x1: decode TF { + format WarnUnimpl { + 0x0: bc2fl(); + 0x1: bc2tl(); + } + } + } + } + } + + //Table A-20 MIPS64 COP1X Encoding of Function Field 1 + //Note: "COP1X instructions are legal only if 64-bit floating point + //operations are enabled." + 0x3: decode FUNCTION_HI { + 0x0: decode FUNCTION_LO { + format LoadMemory2 { + 0x0: lwxc1({{ EA = Rs + Rt; }},{{ /*F_t<31:0> = Mem.sf; */}}); + 0x1: ldxc1({{ EA = Rs + Rt; }},{{ /*F_t<63:0> = Mem.df;*/ }}); + 0x5: luxc1({{ //Need to make EA<2:0> = 0 + EA = Rs + Rt; + }}, + {{ /*F_t<31:0> = Mem.df; */}}); + } + } + + 0x1: decode FUNCTION_LO { + format StoreMemory2 { + 0x0: swxc1({{ EA = Rs + Rt; }},{{ /*Mem.sf = Ft<31:0>; */}}); + 0x1: sdxc1({{ EA = Rs + Rt; }},{{ /*Mem.df = Ft<63:0> */}}); + 0x5: suxc1({{ //Need to make EA<2:0> = 0 + EA = Rs + Rt; + }}, + {{ /*Mem.df = F_t<63:0>;*/}}); + } + + 0x7: WarnUnimpl::prefx(); + } + + format FloatOp { + 0x3: WarnUnimpl::alnv_ps(); + + format BasicOp { + 0x4: decode FUNCTION_LO { + 0x0: madd_s({{ Fd.sf = (Fs.sf * Fs.sf) + Fr.sf; }}); + 0x1: madd_d({{ Fd.df = (Fs.df * Fs.df) + Fr.df; }}); + 0x6: madd_ps({{ + //Must Check for Exception Here... Supposed to Operate on Upper and + //Lower Halves Independently but we take simulator shortcut + Fd.df = (Fs.df * Fs.df) + Fr.df; + }}); + } + + 0x5: decode FUNCTION_LO { + 0x0: msub_s({{ Fd.sf = (Fs.sf * Fs.sf) - Fr.sf; }}); + 0x1: msub_d({{ Fd.df = (Fs.df * Fs.df) - Fr.df; }}); + 0x6: msub_ps({{ + //Must Check for Exception Here... Supposed to Operate on Upper and + //Lower Halves Independently but we take simulator shortcut + Fd.df = (Fs.df * Fs.df) - Fr.df; + }}); + } + + 0x6: decode FUNCTION_LO { + 0x0: nmadd_s({{ Fd.sf = (-1 * Fs.sf * Fs.sf) - Fr.sf; }}); + 0x1: nmadd_d({{ Fd.df = (-1 * Fs.df * Fs.df) + Fr.df; }}); + 0x6: nmadd_ps({{ + //Must Check for Exception Here... Supposed to Operate on Upper and + //Lower Halves Independently but we take simulator shortcut + Fd.df = (-1 * Fs.df * Fs.df) + Fr.df; + }}); + } + + 0x7: decode FUNCTION_LO { + 0x0: nmsub_s({{ Fd.sf = (-1 * Fs.sf * Fs.sf) - Fr.sf; }}); + 0x1: nmsub_d({{ Fd.df = (-1 * Fs.df * Fs.df) - Fr.df; }}); + 0x6: nmsub_ps({{ + //Must Check for Exception Here... Supposed to Operate on Upper and + //Lower Halves Independently but we take simulator shortcut + Fd.df = (-1 * Fs.df * Fs.df) + Fr.df; + }}); + } + } + } + } + + //MIPS obsolete instructions + format BranchLikely { + 0x4: beql({{ cond = (Rs.sw == 0); }}); + 0x5: bnel({{ cond = (Rs.sw != 0); }}); + 0x6: blezl({{ cond = (Rs.sw <= 0); }}); + 0x7: bgtzl({{ cond = (Rs.sw > 0); }}); + } + } + + 0x3: decode OPCODE_LO default FailUnimpl::reserved() { + + //Table A-5 MIPS32 SPECIAL2 Encoding of Function Field + 0x4: decode FUNCTION_HI { + + 0x0: decode FUNCTION_LO { + format IntOp { + 0x0: madd({{ + int64_t temp1 = xc->readMiscReg(Hi) << 32 | xc->readMiscReg(Lo) >> 32; + temp1 = temp1 + (Rs.sw * Rt.sw); + xc->setMiscReg(Hi,temp1<63:32>); + xc->setMiscReg(Lo,temp1<31:0>); + }}); + + 0x1: maddu({{ + int64_t temp1 = xc->readMiscReg(Hi) << 32 | xc->readMiscReg(Lo) >> 32; + temp1 = temp1 + (Rs.uw * Rt.uw); + xc->setMiscReg(Hi,temp1<63:32>); + xc->setMiscReg(Lo,temp1<31:0>); + }}); + + 0x2: mul({{ Rd.sw = Rs.sw * Rt.sw; }}); + + 0x4: msub({{ + int64_t temp1 = xc->readMiscReg(Hi) << 32 | xc->readMiscReg(Lo) >> 32; + temp1 = temp1 - (Rs.sw * Rt.sw); + xc->setMiscReg(Hi,temp1<63:32>); + xc->setMiscReg(Lo,temp1<31:0>); + }}); + + 0x5: msubu({{ + int64_t temp1 = xc->readMiscReg(Hi) << 32 | xc->readMiscReg(Lo) >> 32; + temp1 = temp1 - (Rs.uw * Rt.uw); + xc->setMiscReg(Hi,temp1<63:32>); + xc->setMiscReg(Lo,temp1<31:0>); + }}); + } + } + + 0x4: decode FUNCTION_LO { + format BasicOp { + 0x0: clz({{ + /*int cnt = 0; + int idx = 0; + while ( Rs.uw<idx> != 1) { + cnt++; + idx--; + } + + Rd.uw = cnt;*/ + }}); + + 0x1: clo({{ + /*int cnt = 0; + int idx = 0; + while ( Rs.uw<idx> != 0) { + cnt++; + idx--; + } + + Rd.uw = cnt;*/ + }}); + } + } + + 0x7: decode FUNCTION_LO { + 0x7: WarnUnimpl::sdbbp(); + } + } + + //Table A-6 MIPS32 SPECIAL3 Encoding of Function Field for Release 2 of the Architecture + 0x7: decode FUNCTION_HI { + + 0x0: decode FUNCTION_LO { + format WarnUnimpl { + 0x1: ext(); + 0x4: ins(); + } + } + + 0x1: decode FUNCTION_LO { + format WarnUnimpl { + 0x0: fork(); + 0x1: yield(); + } + } + + + //Table A-10 MIPS32 BSHFL Encoding of sa Field + 0x4: decode SA { + + 0x02: WarnUnimpl::wsbh(); + + format BasicOp { + 0x10: seb({{ Rd.sw = /* sext32(Rt<7>,24) | */ Rt<7:0>}}); + 0x18: seh({{ Rd.sw = /* sext32(Rt<15>,16) | */ Rt<15:0>}}); + } + } + + 0x6: decode FUNCTION_LO { + 0x7: BasicOp::rdhwr({{ /*Rt = xc->hwRegs[RD];*/ }}); + } + } + } + + 0x4: decode OPCODE_LO default FailUnimpl::reserved() { + format LoadMemory { + 0x0: lb({{ Rt.sw = Mem.sb; }}); + 0x1: lh({{ Rt.sw = Mem.sh; }}); + 0x2: lwl({{ Rt.sw = Mem.sw; }});//, WordAlign); + 0x3: lw({{ Rt.sw = Mem.sb; }}); + 0x4: lbu({{ Rt.uw = Mem.ub; }}); + 0x5: lhu({{ Rt.uw = Mem.uh; }}); + 0x6: lwr({{ Rt.uw = Mem.uw; }});//, WordAlign); + } + + 0x7: FailUnimpl::reserved(); + } + + 0x5: decode OPCODE_LO default FailUnimpl::reserved() { + format StoreMemory { + 0x0: sb({{ Mem.ub = Rt<7:0>; }}); + 0x1: sh({{ Mem.uh = Rt<15:0>; }}); + 0x2: swl({{ Mem.ub = Rt<31:0>; }});//,WordAlign); + 0x3: sw({{ Mem.ub = Rt<31:0>; }}); + 0x6: swr({{ Mem.ub = Rt<31:0>; }});//,WordAlign); + } + + format WarnUnimpl { + 0x7: cache(); + } + + } + + 0x6: decode OPCODE_LO default FailUnimpl::reserved() { + 0x0: WarnUnimpl::ll(); + + format LoadMemory { + 0x1: lwc1({{ /*F_t<31:0> = Mem.sf; */}}); + 0x5: ldc1({{ /*F_t<63:0> = Mem.df; */}}); + } + } + + + 0x7: decode OPCODE_LO default FailUnimpl::reserved() { + 0x0: WarnUnimpl::sc(); + + format StoreMemory { + 0x1: swc1({{ //Mem.sf = Ft<31:0>; }}); + 0x5: sdc1({{ //Mem.df = Ft<63:0>; }}); + } + } +} + + diff --git a/arch/mips/isa/formats.isa b/arch/mips/isa/formats.isa new file mode 100644 index 000000000..f7a9e4ce2 --- /dev/null +++ b/arch/mips/isa/formats.isa @@ -0,0 +1,35 @@ +// -*- mode:c++ -*- + +//Templates from this format are used later +//Include the basic format +##include "m5/arch/mips/isa/formats/basic.isa" + +//Include the basic format +##include "m5/arch/mips/isa/formats/noop.isa" + +//Include utility formats/functions +##include "m5/arch/mips/isa/formats/util.isa" + +//Include the cop0 formats +##include "m5/arch/mips/isa/formats/cop0.isa" + +//Include the integer formats +##include "m5/arch/mips/isa/formats/int.isa" + +//Include the floatOp format +##include "m5/arch/mips/isa/formats/fp.isa" + +//Include the mem format +##include "m5/arch/mips/isa/formats/mem.isa" + +//Include the trap format +##include "m5/arch/mips/isa/formats/trap.isa" + +//Include the branch format +##include "m5/arch/mips/isa/formats/branch.isa" + +//Include the noop format +##include "m5/arch/mips/isa/formats/unimp.isa" + +//Include the noop format +##include "m5/arch/mips/isa/formats/unknown.isa" diff --git a/arch/mips/isa/formats/basic.isa b/arch/mips/isa/formats/basic.isa new file mode 100644 index 000000000..c02af7ddc --- /dev/null +++ b/arch/mips/isa/formats/basic.isa @@ -0,0 +1,66 @@ +// -*- mode:c++ -*- + +// Declarations for execute() methods. +def template BasicExecDeclare {{ + Fault execute(%(CPU_exec_context)s *, Trace::InstRecord *) const; +}}; + +// Basic instruction class declaration template. +def template BasicDeclare {{ + /** + * Static instruction class for "%(mnemonic)s". + */ + class %(class_name)s : public %(base_class)s + { + public: + /// Constructor. + %(class_name)s(MachInst machInst); + %(BasicExecDeclare)s + }; +}}; + +// Basic instruction class constructor template. +def template BasicConstructor {{ + inline %(class_name)s::%(class_name)s(MachInst machInst) : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s) + { + %(constructor)s; + } +}}; + +// Basic instruction class execute method template. +def template BasicExecute {{ + Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, Trace::InstRecord *traceData) const + { + Fault fault = NoFault; + + %(fp_enable_check)s; + %(op_decl)s; + %(op_rd)s; + %(code)s; + + if(fault == NoFault) + { + %(op_wb)s; + } + return fault; + } +}}; + +// Basic decode template. +def template BasicDecode {{ + return new %(class_name)s(machInst); +}}; + +// Basic decode template, passing mnemonic in as string arg to constructor. +def template BasicDecodeWithMnemonic {{ + return new %(class_name)s("%(mnemonic)s", machInst); +}}; + +// The most basic instruction format... used only for a few misc. insts +def format BasicOp(code, *flags) {{ + iop = InstObjParams(name, Name, 'MipsStaticInst', CodeBlock(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/arch/mips/isa/formats/branch.isa b/arch/mips/isa/formats/branch.isa new file mode 100644 index 000000000..0d2ad7855 --- /dev/null +++ b/arch/mips/isa/formats/branch.isa @@ -0,0 +1,322 @@ +// -*- mode:c++ -*- + +//////////////////////////////////////////////////////////////////// +// +// Control transfer instructions +// + +output header {{ + +#include <iostream> + using namespace std; + + /** + * Base class for instructions whose disassembly is not purely a + * function of the machine instruction (i.e., it depends on the + * PC). This class overrides the disassemble() method to check + * the PC and symbol table values before re-using a cached + * disassembly string. This is necessary for branches and jumps, + * where the disassembly string includes the target address (which + * may depend on the PC and/or symbol table). + */ + class PCDependentDisassembly : public MipsStaticInst + { + protected: + /// Cached program counter from last disassembly + mutable Addr cachedPC; + + /// Cached symbol table pointer from last disassembly + mutable const SymbolTable *cachedSymtab; + + /// Constructor + PCDependentDisassembly(const char *mnem, MachInst _machInst, + OpClass __opClass) + : MipsStaticInst(mnem, _machInst, __opClass), + cachedPC(0), cachedSymtab(0) + { + } + + const std::string & + disassemble(Addr pc, const SymbolTable *symtab) const; + }; + + /** + * Base class for branches (PC-relative control transfers), + * conditional or unconditional. + */ + class Branch : public PCDependentDisassembly + { + protected: + /// target address (signed) Displacement . + int32_t disp; + + /// Constructor. + Branch(const char *mnem, MachInst _machInst, OpClass __opClass) + : PCDependentDisassembly(mnem, _machInst, __opClass), + disp(OFFSET << 2) + { + //If Bit 17 is 1 then Sign Extend + if ( (disp & 0x00020000) > 0 ) { + disp |= 0xFFFE0000; + } + } + + Addr branchTarget(Addr branchPC) const; + + std::string + generateDisassembly(Addr pc, const SymbolTable *symtab) const; + }; + + /** + * Base class for branch likely branches (PC-relative control transfers), + */ + class BranchLikely : public PCDependentDisassembly + { + protected: + /// target address (signed) Displacement . + int32_t disp; + + /// Constructor. + BranchLikely(const char *mnem, MachInst _machInst, OpClass __opClass) + : PCDependentDisassembly(mnem, _machInst, __opClass), + disp(OFFSET << 2) + { + + } + + Addr branchTarget(Addr branchPC) const; + + std::string + generateDisassembly(Addr pc, const SymbolTable *symtab) const; + }; + + /** + * Base class for jumps (register-indirect control transfers). In + * the Mips ISA, these are always unconditional. + */ + class Jump : public PCDependentDisassembly + { + protected: + + /// Displacement to target address (signed). + int32_t disp; + + uint32_t target; + + public: + /// Constructor + Jump(const char *mnem, MachInst _machInst, OpClass __opClass) + : PCDependentDisassembly(mnem, _machInst, __opClass), + disp(JMPTARG << 2) + { + } + + Addr branchTarget(ExecContext *xc) const; + + std::string + generateDisassembly(Addr pc, const SymbolTable *symtab) const; + }; +}}; + +output decoder {{ + Addr + Branch::branchTarget(Addr branchPC) const + { + return branchPC + 4 + disp; + } + + Addr + BranchLikely::branchTarget(Addr branchPC) const + { + return branchPC + 4 + disp; + } + + Addr + Jump::branchTarget(ExecContext *xc) const + { + Addr NPC = xc->readPC() + 4; + uint64_t Rb = xc->readIntReg(_srcRegIdx[0]); + return (Rb & ~3) | (NPC & 1); + } + + const std::string & + PCDependentDisassembly::disassemble(Addr pc, + const SymbolTable *symtab) const + { + if (!cachedDisassembly || + pc != cachedPC || symtab != cachedSymtab) + { + if (cachedDisassembly) + delete cachedDisassembly; + + cachedDisassembly = + new std::string(generateDisassembly(pc, symtab)); + cachedPC = pc; + cachedSymtab = symtab; + } + + return *cachedDisassembly; + } + + std::string + Branch::generateDisassembly(Addr pc, const SymbolTable *symtab) const + { + std::stringstream ss; + + ccprintf(ss, "%-10s ", mnemonic); + + // There's only one register arg (RA), but it could be + // either a source (the condition for conditional + // branches) or a destination (the link reg for + // unconditional branches) + if (_numSrcRegs == 1) { + printReg(ss, _srcRegIdx[0]); + ss << ","; + } else if(_numSrcRegs == 2) { + printReg(ss, _srcRegIdx[0]); + ss << ","; + printReg(ss, _srcRegIdx[1]); + ss << ","; + } + + Addr target = pc + 8 + disp; + + std::string str; + if (symtab && symtab->findSymbol(target, str)) + ss << str; + else + ccprintf(ss, "0x%x", target); + + return ss.str(); + } + + std::string + BranchLikely::generateDisassembly(Addr pc, const SymbolTable *symtab) const + { + std::stringstream ss; + + ccprintf(ss, "%-10s ", mnemonic); + + // There's only one register arg (RA), but it could be + // either a source (the condition for conditional + // branches) or a destination (the link reg for + // unconditional branches) + if (_numSrcRegs > 0) { + printReg(ss, _srcRegIdx[0]); + ss << ","; + } + else if (_numDestRegs > 0) { + printReg(ss, _destRegIdx[0]); + ss << ","; + } + + Addr target = pc + 4 + disp; + + std::string str; + if (symtab && symtab->findSymbol(target, str)) + ss << str; + else + ccprintf(ss, "0x%x", target); + + return ss.str(); + } + + std::string + Jump::generateDisassembly(Addr pc, const SymbolTable *symtab) const + { + std::stringstream ss; + + ccprintf(ss, "%-10s ", mnemonic); + + if ( mnemonic == "jal" ) { + Addr npc = pc + 4; + ccprintf(ss,"0x%x",(npc & 0xF0000000) | disp); + } else if (_numSrcRegs == 0) { + std::string str; + if (symtab && symtab->findSymbol(disp, str)) + ss << str; + else + ccprintf(ss, "0x%x", disp); + } else if (_numSrcRegs == 1) { + printReg(ss, _srcRegIdx[0]); + } else if(_numSrcRegs == 2) { + printReg(ss, _srcRegIdx[0]); + ss << ","; + printReg(ss, _srcRegIdx[1]); + } else { + panic(">= 3 Source Registers!!!"); + } + + return ss.str(); + } +}}; + +def format Branch(code,*flags) {{ + #Add Link Code if Link instruction + strlen = len(name) + if name[strlen-2:] == 'al': + code += 'r31 = NNPC;\n' + + #Condition code + code = 'bool cond;\n' + code + code += 'if (cond) {\n' + code += ' NNPC = NPC + disp;\n' + code += '} else {\n' + code += ' NNPC = NNPC;\n' + code += '} \n' + + code += 'cout << hex << "NPC: " << NPC << " + " << disp << " = " << NNPC << endl;' + + iop = InstObjParams(name, Name, 'Branch', CodeBlock(code), + ('IsDirectControl', 'IsCondControl')) + + header_output = BasicDeclare.subst(iop) + decoder_output = BasicConstructor.subst(iop) + decode_block = BasicDecode.subst(iop) + exec_output = BasicExecute.subst(iop) +}}; + + +def format BranchLikely(code,*flags) {{ + #Add Link Code if Link instruction + strlen = len(name) + if name[strlen-3:] == 'all': + code += 'r31 = NNPC;\n' + + #Condition code + code = 'bool cond;\n' + code + code += 'if (cond) {' + code += 'NNPC = NPC + disp;\n' + code += '} \n' + + + iop = InstObjParams(name, Name, 'Branch', CodeBlock(code), + ('IsDirectControl', 'IsCondControl','IsCondDelaySlot')) + + header_output = BasicDeclare.subst(iop) + decoder_output = BasicConstructor.subst(iop) + decode_block = BasicDecode.subst(iop) + exec_output = BasicExecute.subst(iop) +}}; + +def format Jump(code,*flags) {{ + #Add Link Code if Link instruction + strlen = len(name) + if strlen > 1 and name[1:] == 'al': + code = 'r31 = NNPC;\n' + code + + #code += 'if(NNPC == 0x80000638) { NNPC = r31; cout << "SKIPPING JUMP TO SIM_GET_MEM_CONF" << endl;}' + #code += 'target = NNPC;' + + iop = InstObjParams(name, Name, 'Jump', CodeBlock(code),\ + ('IsIndirectControl', 'IsUncondControl')) + + header_output = BasicDeclare.subst(iop) + decoder_output = BasicConstructor.subst(iop) + decode_block = BasicDecode.subst(iop) + exec_output = BasicExecute.subst(iop) +}}; + + + + diff --git a/arch/mips/isa/formats/fp.isa b/arch/mips/isa/formats/fp.isa new file mode 100644 index 000000000..34b71acf7 --- /dev/null +++ b/arch/mips/isa/formats/fp.isa @@ -0,0 +1,49 @@ +// -*- mode:c++ -*- + +//////////////////////////////////////////////////////////////////// +// +// Floating Point operate instructions +// + +output header {{ + /** + * Base class for FP operations. + */ + class FPOp : public MipsStaticInst + { + protected: + + /// Constructor + FPOp(const char *mnem, MachInst _machInst, OpClass __opClass) : MipsStaticInst(mnem, _machInst, __opClass) + { + } + + std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; + }; +}}; + +output decoder {{ + std::string FPOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const + { + return "Disassembly of integer instruction\n"; + } +}}; + + +// Primary format for integer operate instructions: +def format FloatOp(code, *flags) {{ + iop = InstObjParams(name, Name, 'MipsStaticInst', CodeBlock(code), flags) + header_output = BasicDeclare.subst(iop) + decoder_output = BasicConstructor.subst(iop) + decode_block = BasicDecode.subst(iop) + exec_output = BasicExecute.subst(iop) +}}; + +// Primary format for integer operate instructions: +def format Float64Op(code, *flags) {{ + iop = InstObjParams(name, Name, 'MipsStaticInst', CodeBlock(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/arch/mips/isa/formats/int.isa b/arch/mips/isa/formats/int.isa new file mode 100644 index 000000000..a47844bee --- /dev/null +++ b/arch/mips/isa/formats/int.isa @@ -0,0 +1,130 @@ +// -*- mode:c++ -*- + +//////////////////////////////////////////////////////////////////// +// +// Integer operate instructions +// + +//Outputs to decoder.hh +output header {{ +#include <iostream> + using namespace std; + /** + * Base class for integer operations. + */ + class IntOp : public MipsStaticInst + { + protected: + + /// Constructor + IntOp(const char *mnem, MachInst _machInst, OpClass __opClass) : + MipsStaticInst(mnem, _machInst, __opClass) + { + } + + std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; + }; + + class IntImmOp : public MipsStaticInst + { + protected: + + int32_t imm; + + /// Constructor + IntImmOp(const char *mnem, MachInst _machInst, OpClass __opClass) : + MipsStaticInst(mnem, _machInst, __opClass),imm(INTIMM) + { + //If Bit 15 is 1 then Sign Extend + int32_t temp = imm & 0x00008000; + + if (temp > 0 && mnemonic != "lui") { + imm |= 0xFFFF0000; + } + } + + std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; + + + }; + +}}; + +//Outputs to decoder.cc +output decoder {{ + std::string IntOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const + { + std::stringstream ss; + + ccprintf(ss, "%-10s ", mnemonic); + + // just print the first dest... if there's a second one, + // it's generally implicit + if (_numDestRegs > 0) { + printReg(ss, _destRegIdx[0]); + } + + ss << ","; + + // just print the first two source regs... if there's + // a third one, it's a read-modify-write dest (Rc), + // e.g. for CMOVxx + if (_numSrcRegs > 0) { + printReg(ss, _srcRegIdx[0]); + } + + if (_numSrcRegs > 1) { + ss << ","; + printReg(ss, _srcRegIdx[1]); + } + + return ss.str(); + } + + std::string IntImmOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const + { + std::stringstream ss; + + ccprintf(ss, "%-10s ", mnemonic); + + if (_numDestRegs > 0) { + printReg(ss, _destRegIdx[0]); + } + + ss << ","; + + if (_numSrcRegs > 0) { + printReg(ss, _srcRegIdx[0]); + ss << ","; + } + + if( mnemonic == "lui") + ccprintf(ss, "%08p ", imm); + else + ss << (int) imm; + + return ss.str(); + } + +}}; + +//Used by decoder.isa +def format IntOp(code, *opt_flags) {{ + orig_code = code + cblk = CodeBlock(code) + + # Figure out if we are creating a IntImmOp or a IntOp + # by looking at the instruction name + iop = InstObjParams(name, Name, 'IntOp', cblk, opt_flags) + strlen = len(name) + if name[strlen-1] == 'i' or name[strlen-2:] == 'iu': + iop = InstObjParams(name, Name, 'IntImmOp', cblk, opt_flags) + + header_output = BasicDeclare.subst(iop) + decoder_output = BasicConstructor.subst(iop) + decode_block = OperateNopCheckDecode.subst(iop) + exec_output = BasicExecute.subst(iop) +}}; + + + diff --git a/arch/mips/isa/formats/mem.isa b/arch/mips/isa/formats/mem.isa new file mode 100644 index 000000000..8a07e63d4 --- /dev/null +++ b/arch/mips/isa/formats/mem.isa @@ -0,0 +1,469 @@ +// -*- mode:c++ -*- + +// Copyright (c) 2003-2005 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. + +output header {{ + /** + * Base class for general Mips memory-format instructions. + */ + class Memory : public MipsStaticInst + { + protected: + + /// Memory request flags. See mem_req_base.hh. + unsigned memAccessFlags; + /// Pointer to EAComp object. + const StaticInstPtr eaCompPtr; + /// Pointer to MemAcc object. + const StaticInstPtr memAccPtr; + + /// Displacement for EA calculation (signed). + int32_t disp; + + /// Constructor + Memory(const char *mnem, MachInst _machInst, OpClass __opClass, + StaticInstPtr _eaCompPtr = nullStaticInstPtr, + StaticInstPtr _memAccPtr = nullStaticInstPtr) + : MipsStaticInst(mnem, _machInst, __opClass), + memAccessFlags(0), eaCompPtr(_eaCompPtr), memAccPtr(_memAccPtr), + disp(OFFSET) + { + //If Bit 15 is 1 then Sign Extend + int32_t temp = disp & 0x00008000; + + if (temp > 0) { + disp |= 0xFFFF0000; + } + } + + std::string + generateDisassembly(Addr pc, const SymbolTable *symtab) const; + + public: + + const StaticInstPtr &eaCompInst() const { return eaCompPtr; } + const StaticInstPtr &memAccInst() const { return memAccPtr; } + }; + +}}; + + +output decoder {{ + std::string + Memory::generateDisassembly(Addr pc, const SymbolTable *symtab) const + { + return csprintf("%-10s %c%d,%d(r%d)", mnemonic, + flags[IsFloating] ? 'f' : 'r', RT, disp, RS); + } + +}}; + +def format LoadAddress(code) {{ + iop = InstObjParams(name, Name, 'MemoryDisp32', CodeBlock(code)) + header_output = BasicDeclare.subst(iop) + decoder_output = BasicConstructor.subst(iop) + decode_block = BasicDecode.subst(iop) + exec_output = BasicExecute.subst(iop) +}}; + + +def template LoadStoreDeclare {{ + /** + * Static instruction class for "%(mnemonic)s". + */ + class %(class_name)s : public %(base_class)s + { + protected: + + /** + * "Fake" effective address computation class for "%(mnemonic)s". + */ + class EAComp : public %(base_class)s + { + public: + /// Constructor + EAComp(MachInst machInst); + + %(BasicExecDeclare)s + }; + + /** + * "Fake" memory access instruction class for "%(mnemonic)s". + */ + class MemAcc : public %(base_class)s + { + public: + /// Constructor + MemAcc(MachInst machInst); + + %(BasicExecDeclare)s + }; + + public: + + /// Constructor. + %(class_name)s(MachInst machInst); + + %(BasicExecDeclare)s + + %(InitiateAccDeclare)s + + %(CompleteAccDeclare)s + }; +}}; + + +def template InitiateAccDeclare {{ + Fault initiateAcc(%(CPU_exec_context)s *, Trace::InstRecord *) const; +}}; + + +def template CompleteAccDeclare {{ + Fault completeAcc(uint8_t *, %(CPU_exec_context)s *, Trace::InstRecord *) const; +}}; + + +def template LoadStoreConstructor {{ + /** TODO: change op_class to AddrGenOp or something (requires + * creating new member of OpClass enum in op_class.hh, updating + * config files, etc.). */ + inline %(class_name)s::EAComp::EAComp(MachInst machInst) + : %(base_class)s("%(mnemonic)s (EAComp)", machInst, IntAluOp) + { + %(ea_constructor)s; + } + + inline %(class_name)s::MemAcc::MemAcc(MachInst machInst) + : %(base_class)s("%(mnemonic)s (MemAcc)", machInst, %(op_class)s) + { + %(memacc_constructor)s; + } + + inline %(class_name)s::%(class_name)s(MachInst machInst) + : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s, + new EAComp(machInst), new MemAcc(machInst)) + { + %(constructor)s; + } +}}; + + +def template EACompExecute {{ + Fault + %(class_name)s::EAComp::execute(%(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + Addr EA; + Fault fault = NoFault; + + %(fp_enable_check)s; + %(op_decl)s; + %(op_rd)s; + %(code)s; + + if (fault == NoFault) { + %(op_wb)s; + xc->setEA(EA); + } + + return fault; + } +}}; + +def template LoadMemAccExecute {{ + Fault + %(class_name)s::MemAcc::execute(%(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + Addr EA; + Fault fault = NoFault; + + %(fp_enable_check)s; + %(op_decl)s; + %(op_rd)s; + EA = xc->getEA(); + + if (fault == NoFault) { + fault = xc->read(EA, (uint%(mem_acc_size)d_t&)Mem, memAccessFlags); + %(code)s; + } + + if (fault == NoFault) { + %(op_wb)s; + } + + return fault; + } +}}; + + +def template LoadExecute {{ + Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + Addr EA; + Fault fault = NoFault; + + %(fp_enable_check)s; + %(op_decl)s; + %(op_rd)s; + %(ea_code)s; + + if (fault == NoFault) { + fault = xc->read(EA, (uint%(mem_acc_size)d_t&)Mem, memAccessFlags); + %(memacc_code)s; + } + + if (fault == NoFault) { + %(op_wb)s; + } + + return fault; + } +}}; + + +def template LoadInitiateAcc {{ + Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + Addr EA; + Fault fault = NoFault; + + %(fp_enable_check)s; + %(op_src_decl)s; + %(op_rd)s; + %(ea_code)s; + + if (fault == NoFault) { + fault = xc->read(EA, (uint%(mem_acc_size)d_t &)Mem, memAccessFlags); + } + + return fault; + } +}}; + + +def template LoadCompleteAcc {{ + Fault %(class_name)s::completeAcc(uint8_t *data, + %(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + Fault fault = NoFault; + + %(fp_enable_check)s; + %(op_src_decl)s; + %(op_dest_decl)s; + + memcpy(&Mem, data, sizeof(Mem)); + + if (fault == NoFault) { + %(memacc_code)s; + } + + if (fault == NoFault) { + %(op_wb)s; + } + + return fault; + } +}}; + + +def template StoreMemAccExecute {{ + Fault + %(class_name)s::MemAcc::execute(%(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + Addr EA; + Fault fault = NoFault; + uint64_t write_result = 0; + + %(fp_enable_check)s; + %(op_decl)s; + %(op_rd)s; + EA = xc->getEA(); + + if (fault == NoFault) { + %(code)s; + } + + if (fault == NoFault) { + fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA, + memAccessFlags, &write_result); + if (traceData) { traceData->setData(Mem); } + } + + if (fault == NoFault) { + %(postacc_code)s; + } + + if (fault == NoFault) { + %(op_wb)s; + } + + return fault; + } +}}; + + +def template StoreExecute {{ + Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + Addr EA; + Fault fault = NoFault; + uint64_t write_result = 0; + + %(fp_enable_check)s; + %(op_decl)s; + %(op_rd)s; + %(ea_code)s; + + if (fault == NoFault) { + %(memacc_code)s; + } + + if (fault == NoFault) { + fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA, + memAccessFlags, &write_result); + if (traceData) { traceData->setData(Mem); } + } + + if (fault == NoFault) { + %(postacc_code)s; + } + + if (fault == NoFault) { + %(op_wb)s; + } + + return fault; + } +}}; + +def template StoreInitiateAcc {{ + Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + Addr EA; + Fault fault = NoFault; + uint64_t write_result = 0; + + %(fp_enable_check)s; + %(op_src_decl)s; + %(op_dest_decl)s; + %(op_rd)s; + %(ea_code)s; + + if (fault == NoFault) { + %(memacc_code)s; + } + + if (fault == NoFault) { + fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA, + memAccessFlags, &write_result); + if (traceData) { traceData->setData(Mem); } + } + + return fault; + } +}}; + + +def template StoreCompleteAcc {{ + Fault %(class_name)s::completeAcc(uint8_t *data, + %(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + Fault fault = NoFault; + uint64_t write_result = 0; + + %(fp_enable_check)s; + %(op_dest_decl)s; + + memcpy(&write_result, data, sizeof(write_result)); + + if (fault == NoFault) { + %(postacc_code)s; + } + + if (fault == NoFault) { + %(op_wb)s; + } + + return fault; + } +}}; + +// load instructions use Rt as dest, so check for +// Rt == 31 to detect nops +def template LoadNopCheckDecode {{ + { + MipsStaticInst *i = new %(class_name)s(machInst); + if (RT == 0) { + i = makeNop(i); + } + return i; + } +}}; + +def format LoadMemory(memacc_code, ea_code = {{ EA = Rs + disp; }}, + mem_flags = [], inst_flags = []) {{ + (header_output, decoder_output, decode_block, exec_output) = \ + LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, + decode_template = LoadNopCheckDecode, + exec_template_base = 'Load') +}}; + + +def format StoreMemory(memacc_code, ea_code = {{ EA = Rs + disp; }}, + mem_flags = [], inst_flags = []) {{ + (header_output, decoder_output, decode_block, exec_output) = \ + LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, + exec_template_base = 'Store') +}}; + +//FP loads are offloaded to these formats for now ... +def format LoadMemory2(ea_code = {{ EA = Rs + disp; }}, memacc_code = {{ }}, + mem_flags = [], inst_flags = []) {{ + (header_output, decoder_output, decode_block, exec_output) = \ + LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, + decode_template = LoadNopCheckDecode, + exec_template_base = 'Load') +}}; + + +//FP stores are offloaded to these formats for now ... +def format StoreMemory2(ea_code = {{ EA = Rs + disp; }},memacc_code = {{ }}, + mem_flags = [], inst_flags = []) {{ + (header_output, decoder_output, decode_block, exec_output) = \ + LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, + decode_template = LoadNopCheckDecode, + exec_template_base = 'Store') +}}; + diff --git a/arch/mips/isa/formats/noop.isa b/arch/mips/isa/formats/noop.isa new file mode 100644 index 000000000..d35179005 --- /dev/null +++ b/arch/mips/isa/formats/noop.isa @@ -0,0 +1,90 @@ +// -*- mode:c++ -*- + +//////////////////////////////////////////////////////////////////// +// +// Nop +// + +output header {{ + /** + * Static instruction class for no-ops. This is a leaf class. + */ + class Nop : public MipsStaticInst + { + /// Disassembly of original instruction. + const std::string originalDisassembly; + + public: + /// Constructor + Nop(const std::string _originalDisassembly, MachInst _machInst) + : MipsStaticInst("nop", _machInst, No_OpClass), + originalDisassembly(_originalDisassembly) + { + flags[IsNop] = true; + } + + ~Nop() { } + + std::string + generateDisassembly(Addr pc, const SymbolTable *symtab) const; + + %(BasicExecDeclare)s + }; +}}; + +output decoder {{ + std::string Nop::generateDisassembly(Addr pc, + const SymbolTable *symtab) const + { +#ifdef SS_COMPATIBLE_DISASSEMBLY + return originalDisassembly; +#else + return csprintf("%-10s (%s)", "nop", originalDisassembly); +#endif + } + + /// Helper function for decoding nops. Substitute Nop object + /// for original inst passed in as arg (and delete latter). + inline + MipsStaticInst * + makeNop(MipsStaticInst *inst) + { + MipsStaticInst *nop = new Nop(inst->disassemble(0), inst->machInst); + delete inst; + return nop; + } +}}; + +output exec {{ + Fault + Nop::execute(%(CPU_exec_context)s *, Trace::InstRecord *) const + { + return NoFault; + } +}}; + +// integer & FP operate instructions use RT as dest, so check for +// RT == 0 to detect nops +def template OperateNopCheckDecode {{ + { + MipsStaticInst *i = new %(class_name)s(machInst); + + //if (RD == 0) { + // i = makeNop(i); + //} + + return i; + } +}}; + + +// Like BasicOperate format, but generates NOP if RC/FC == 31 +def format BasicOperateWithNopCheck(code, *opt_args) {{ + iop = InstObjParams(name, Name, 'MipsStaticInst', CodeBlock(code), + opt_args) + header_output = BasicDeclare.subst(iop) + decoder_output = BasicConstructor.subst(iop) + decode_block = OperateNopCheckDecode.subst(iop) + exec_output = BasicExecute.subst(iop) +}}; + diff --git a/arch/mips/isa/formats/tlbop.isa b/arch/mips/isa/formats/tlbop.isa new file mode 100644 index 000000000..f5e4076f2 --- /dev/null +++ b/arch/mips/isa/formats/tlbop.isa @@ -0,0 +1,53 @@ +//////////////////////////////////////////////////////////////////// +// +// TlbOp instructions +// + +output header {{ + /** + * Base class for integer operations. + */ + class TlbOp : public MipsStaticInst + { + protected: + + /// Constructor + TlbOp(const char *mnem, MachInst _machInst, OpClass __opClass) : MipsStaticInst(mnem, _machInst, __opClass) + { + } + + std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; + }; +}}; + +output decoder {{ + std::string TlbOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const + { + return "Disassembly of integer instruction\n"; + } +}}; + +def template TlbOpExecute {{ + Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, Trace::InstRecord *traceData) const + { + //Call into the trap handler with the appropriate fault + return No_Fault; + } + + //Write the resulting state to the execution context + %(op_wb)s; + + return No_Fault; + } +}}; + +// Primary format for integer operate instructions: +def format TlbOp(code, *opt_flags) {{ + orig_code = code + cblk = CodeBlock(code) + iop = InstObjParams(name, Name, 'MipsStaticInst', cblk, opt_flags) + header_output = BasicDeclare.subst(iop) + decoder_output = BasicConstructor.subst(iop) + decode_block = BasicDecodeWithMnemonic.subst(iop) + exec_output = TlbOpExecute.subst(iop) +}}; diff --git a/arch/mips/isa/formats/trap.isa b/arch/mips/isa/formats/trap.isa new file mode 100644 index 000000000..6884d4fa8 --- /dev/null +++ b/arch/mips/isa/formats/trap.isa @@ -0,0 +1,52 @@ +//////////////////////////////////////////////////////////////////// +// +// Trap instructions +// + +output header {{ + /** + * Base class for integer operations. + */ + class Trap : public MipsStaticInst + { + protected: + + /// Constructor + Trap(const char *mnem, MachInst _machInst, OpClass __opClass) : MipsStaticInst(mnem, _machInst, __opClass) + { + } + + std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; + }; +}}; + +output decoder {{ + std::string Trap::generateDisassembly(Addr pc, const SymbolTable *symtab) const + { + return "Disassembly of integer instruction\n"; + } +}}; + +def template TrapExecute {{ + Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, Trace::InstRecord *traceData) const + { + //Call into the trap handler with the appropriate fault + return No_Fault; + } + + //Write the resulting state to the execution context + %(op_wb)s; + + return No_Fault; + } +}}; + +// Primary format for integer operate instructions: +def format Trap(code, *flags) {{ + code = 'bool cond;\n' + code; + iop = InstObjParams(name, Name, 'MipsStaticInst', CodeBlock(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/arch/mips/isa/formats/unimp.isa b/arch/mips/isa/formats/unimp.isa new file mode 100644 index 000000000..adbd5b5b1 --- /dev/null +++ b/arch/mips/isa/formats/unimp.isa @@ -0,0 +1,165 @@ +// -*- mode:c++ -*- + +// Copyright (c) 2003-2005 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. + +output header {{ + /** + * Static instruction class for unimplemented instructions that + * cause simulator termination. Note that these are recognized + * (legal) instructions that the simulator does not support; the + * 'Unknown' class is used for unrecognized/illegal instructions. + * This is a leaf class. + */ + class FailUnimplemented : public MipsStaticInst + { + public: + /// Constructor + FailUnimplemented(const char *_mnemonic, MachInst _machInst) + : MipsStaticInst(_mnemonic, _machInst, No_OpClass) + { + // don't call execute() (which panics) if we're on a + // speculative path + flags[IsNonSpeculative] = true; + } + + %(BasicExecDeclare)s + + std::string + generateDisassembly(Addr pc, const SymbolTable *symtab) const; + }; + + /** + * Base class for unimplemented instructions that cause a warning + * to be printed (but do not terminate simulation). This + * implementation is a little screwy in that it will print a + * warning for each instance of a particular unimplemented machine + * instruction, not just for each unimplemented opcode. Should + * probably make the 'warned' flag a static member of the derived + * class. + */ + class WarnUnimplemented : public MipsStaticInst + { + private: + /// Have we warned on this instruction yet? + mutable bool warned; + + public: + /// Constructor + WarnUnimplemented(const char *_mnemonic, MachInst _machInst) + : MipsStaticInst(_mnemonic, _machInst, No_OpClass), warned(false) + { + // don't call execute() (which panics) if we're on a + // speculative path + flags[IsNonSpeculative] = true; + } + + %(BasicExecDeclare)s + + std::string + generateDisassembly(Addr pc, const SymbolTable *symtab) const; + }; +}}; + +output decoder {{ + std::string + FailUnimplemented::generateDisassembly(Addr pc, + const SymbolTable *symtab) const + { + return csprintf("%-10s (unimplemented)", mnemonic); + } + + std::string + WarnUnimplemented::generateDisassembly(Addr pc, + const SymbolTable *symtab) const + { +#ifdef SS_COMPATIBLE_DISASSEMBLY + return csprintf("%-10s", mnemonic); +#else + return csprintf("%-10s (unimplemented)", mnemonic); +#endif + } +}}; + +output exec {{ + Fault + FailUnimplemented::execute(%(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + panic("attempt to execute unimplemented instruction '%s' " + "(inst 0x%08x, opcode 0x%x)", mnemonic, machInst, OPCODE); + return UnimplementedOpcodeFault; + } + + Fault + WarnUnimplemented::execute(%(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + if (!warned) { + warn("instruction '%s' unimplemented\n", mnemonic); + warned = true; + } + + return NoFault; + } +}}; + + +def format FailUnimpl() {{ + iop = InstObjParams(name, 'FailUnimplemented') + decode_block = BasicDecodeWithMnemonic.subst(iop) +}}; + +def format WarnUnimpl() {{ + iop = InstObjParams(name, 'WarnUnimplemented') + decode_block = BasicDecodeWithMnemonic.subst(iop) +}}; + +output header {{ + /** + * Static instruction class for unknown (illegal) instructions. + * These cause simulator termination if they are executed in a + * non-speculative mode. This is a leaf class. + */ + class Unknown : public MipsStaticInst + { + public: + /// Constructor + Unknown(MachInst _machInst) + : MipsStaticInst("unknown", _machInst, No_OpClass) + { + // don't call execute() (which panics) if we're on a + // speculative path + flags[IsNonSpeculative] = true; + } + + %(BasicExecDeclare)s + + std::string + generateDisassembly(Addr pc, const SymbolTable *symtab) const; + }; +}}; + diff --git a/arch/mips/isa/formats/unknown.isa b/arch/mips/isa/formats/unknown.isa new file mode 100644 index 000000000..4601b3684 --- /dev/null +++ b/arch/mips/isa/formats/unknown.isa @@ -0,0 +1,52 @@ +// -*- mode:c++ -*- + +// Copyright (c) 2003-2005 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. + +output decoder {{ + std::string + Unknown::generateDisassembly(Addr pc, const SymbolTable *symtab) const + { + return csprintf("%-10s (inst 0x%x, opcode 0x%x)", + "unknown", machInst, OPCODE); + } +}}; + +output exec {{ + Fault + Unknown::execute(%(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + panic("attempt to execute unknown instruction " + "(inst 0x%08x, opcode 0x%x)", machInst, OPCODE); + return UnimplementedOpcodeFault; + } +}}; + +def format Unknown() {{ + decode_block = 'return new Unknown(machInst);\n' +}}; + diff --git a/arch/mips/isa/formats/util.isa b/arch/mips/isa/formats/util.isa new file mode 100644 index 000000000..db4bf204a --- /dev/null +++ b/arch/mips/isa/formats/util.isa @@ -0,0 +1,148 @@ +// -*- mode:c++ -*- + +let {{ +def LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, + postacc_code = '', base_class = 'Memory', + decode_template = BasicDecode, exec_template_base = ''): + # Make sure flags are in lists (convert to lists if not). + mem_flags = makeList(mem_flags) + inst_flags = makeList(inst_flags) + + # add hook to get effective addresses into execution trace output. + ea_code += '\nif (traceData) { traceData->setAddr(EA); }\n' + + # generate code block objects + ea_cblk = CodeBlock(ea_code) + memacc_cblk = CodeBlock(memacc_code) + postacc_cblk = CodeBlock(postacc_code) + + # Some CPU models execute the memory operation as an atomic unit, + # while others want to separate them into an effective address + # computation and a memory access operation. As a result, we need + # to generate three StaticInst objects. Note that the latter two + # are nested inside the larger "atomic" one. + + # generate InstObjParams for EAComp object + ea_iop = InstObjParams(name, Name, base_class, ea_cblk, inst_flags) + + # generate InstObjParams for MemAcc object + memacc_iop = InstObjParams(name, Name, base_class, memacc_cblk, inst_flags) + # in the split execution model, the MemAcc portion is responsible + # for the post-access code. + memacc_iop.postacc_code = postacc_cblk.code + + # generate InstObjParams for InitiateAcc, CompleteAcc object + # The code used depends on the template being used + if (exec_template_base == 'Load'): + initiateacc_cblk = CodeBlock(ea_code + memacc_code) + completeacc_cblk = CodeBlock(memacc_code + postacc_code) + elif (exec_template_base == 'Store'): + initiateacc_cblk = CodeBlock(ea_code + memacc_code) + completeacc_cblk = CodeBlock(postacc_code) + else: + initiateacc_cblk = '' + completeacc_cblk = '' + + initiateacc_iop = InstObjParams(name, Name, base_class, initiateacc_cblk, + inst_flags) + + completeacc_iop = InstObjParams(name, Name, base_class, completeacc_cblk, + inst_flags) + + if (exec_template_base == 'Load'): + initiateacc_iop.ea_code = ea_cblk.code + initiateacc_iop.memacc_code = memacc_cblk.code + completeacc_iop.memacc_code = memacc_cblk.code + completeacc_iop.postacc_code = postacc_cblk.code + elif (exec_template_base == 'Store'): + initiateacc_iop.ea_code = ea_cblk.code + initiateacc_iop.memacc_code = memacc_cblk.code + completeacc_iop.postacc_code = postacc_cblk.code + + # generate InstObjParams for unified execution + cblk = CodeBlock(ea_code + memacc_code + postacc_code) + iop = InstObjParams(name, Name, base_class, cblk, inst_flags) + + iop.ea_constructor = ea_cblk.constructor + iop.ea_code = ea_cblk.code + iop.memacc_constructor = memacc_cblk.constructor + iop.memacc_code = memacc_cblk.code + iop.postacc_code = postacc_cblk.code + + if mem_flags: + s = '\n\tmemAccessFlags = ' + string.join(mem_flags, '|') + ';' + iop.constructor += s + memacc_iop.constructor += s + + # select templates + memAccExecTemplate = eval(exec_template_base + 'MemAccExecute') + fullExecTemplate = eval(exec_template_base + 'Execute') + initiateAccTemplate = eval(exec_template_base + 'InitiateAcc') + completeAccTemplate = eval(exec_template_base + 'CompleteAcc') + + # (header_output, decoder_output, decode_block, exec_output) + return (LoadStoreDeclare.subst(iop), LoadStoreConstructor.subst(iop), + decode_template.subst(iop), + EACompExecute.subst(ea_iop) + + memAccExecTemplate.subst(memacc_iop) + + fullExecTemplate.subst(iop) + + initiateAccTemplate.subst(initiateacc_iop) + + completeAccTemplate.subst(completeacc_iop)) +}}; + + +output exec {{ + +using namespace MipsISA; + + + /// CLEAR ALL CPU INST/EXE HAZARDS + inline void + clear_exe_inst_hazards() + { + //CODE HERE + } + + + /// Check "FP enabled" machine status bit. Called when executing any FP + /// instruction in full-system mode. + /// @retval Full-system mode: NoFault if FP is enabled, FenFault + /// if not. Non-full-system mode: always returns NoFault. +#if FULL_SYSTEM + inline Fault checkFpEnableFault(%(CPU_exec_context)s *xc) + { + Fault fault = NoFault; // dummy... this ipr access should not fault + if (!Mips34k::ICSR_FPE(xc->readIpr(MipsISA::IPR_ICSR, fault))) { + fault = FloatEnableFault; + } + return fault; + } +#else + inline Fault checkFpEnableFault(%(CPU_exec_context)s *xc) + { + return NoFault; + } +#endif + + double convert_and_round(float w, int x, int y, int z) + { + double temp = .34000; + + return temp; + } + + enum FPTypes{ + FP_SINGLE, + FP_DOUBLE, + FP_LONG, + FP_PS_LO, + FP_PS_HI, + FP_WORD, + RND_NEAREST, + RND_ZERO, + RND_UP, + RND_DOWN + }; +}}; + + diff --git a/arch/mips/isa/includes.isa b/arch/mips/isa/includes.isa new file mode 100644 index 000000000..da919be00 --- /dev/null +++ b/arch/mips/isa/includes.isa @@ -0,0 +1,39 @@ +//////////////////////////////////////////////////////////////////// +// +// Output include file directives. +// + +output header {{ +#include <sstream> +#include <iostream> +#include <iomanip> + +#include "cpu/static_inst.hh" +#include "mem/mem_req.hh" // some constructors use MemReq flags +}}; + +output decoder {{ +#include "base/cprintf.hh" +#include "base/loader/symtab.hh" +#include "cpu/exec_context.hh" // for Jump::branchTarget() + +#include <math.h> +#if defined(linux) +#include <fenv.h> +#endif +}}; + +output exec {{ +#include <math.h> +#if defined(linux) +#include <fenv.h> +#endif + +#ifdef FULL_SYSTEM +//#include "arch/alpha/pseudo_inst.hh" +#endif +#include "cpu/base.hh" +#include "cpu/exetrace.hh" +#include "sim/sim_exit.hh" +}}; + diff --git a/arch/mips/isa/main.isa b/arch/mips/isa/main.isa new file mode 100644 index 000000000..411e398b4 --- /dev/null +++ b/arch/mips/isa/main.isa @@ -0,0 +1,52 @@ +// -*- mode:c++ -*- + +// Copyright (c) 2003-2005 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. + +##include "m5/arch/mips/isa/includes.isa" + +//////////////////////////////////////////////////////////////////// +// +// Namespace statement. Everything below this line will be in the +// MipsISAInst namespace. +// + +namespace MipsISA; + +//Include the bitfield definitions +##include "m5/arch/mips/isa/bitfields.isa" + +//Include the operand_types and operand definitions +##include "m5/arch/mips/isa/operands.isa" + +//Include the base class for mips instructions, and some support code +##include "m5/arch/mips/isa/base.isa" + +//Include the definitions for the instruction formats +##include "m5/arch/mips/isa/formats.isa" + +//Include the decoder definition +##include "m5/arch/mips/isa/decoder.isa" diff --git a/arch/mips/isa/operands.isa b/arch/mips/isa/operands.isa new file mode 100644 index 000000000..13870337b --- /dev/null +++ b/arch/mips/isa/operands.isa @@ -0,0 +1,33 @@ +def operand_types {{ + 'sb' : ('signed int', 8), + 'ub' : ('unsigned int', 8), + 'sh' : ('signed int', 16), + 'uh' : ('unsigned int', 16), + 'sw' : ('signed int', 32), + 'uw' : ('unsigned int', 32), + 'sd' : ('signed int', 64), + 'ud' : ('unsigned int', 64), + 'sf' : ('float', 32), + 'df' : ('float', 64), + 'qf' : ('float', 128) +}}; + +def operands {{ + 'Rd': ('IntReg', 'uw', 'RD', 'IsInteger', 1), + 'Rs': ('IntReg', 'uw', 'RS', 'IsInteger', 2), + 'Rt': ('IntReg', 'uw', 'RT', 'IsInteger', 3), + 'r31': ('IntReg', 'uw','R31','IsInteger', 4), + 'R0': ('IntReg', 'uw','R0', 'IsInteger', 5), + + 'IntImm': ('IntReg', 'uw', 'INTIMM', 'IsInteger', 3), + + 'Fd': ('FloatReg', 'sf', 'FD', 'IsFloating', 1), + 'Fs': ('FloatReg', 'sf', 'FS', 'IsFloating', 2), + 'Ft': ('FloatReg', 'sf', 'FT', 'IsFloating', 3), + 'Fr': ('FloatReg', 'sf', 'FR', 'IsFloating', 3), + + 'Mem': ('Mem', 'ud', None, ('IsMemRef', 'IsLoad', 'IsStore'), 4), + + 'NPC': ('NPC', 'uw', None, ( None, None, 'IsControl' ), 4), + 'NNPC':('NNPC', 'uw', None, ( None, None, 'IsControl' ), 4) +}}; diff --git a/arch/mips/isa_traits.cc b/arch/mips/isa_traits.cc new file mode 100644 index 000000000..d01fa6bd4 --- /dev/null +++ b/arch/mips/isa_traits.cc @@ -0,0 +1,403 @@ +/* + * Copyright (c) 2003-2005 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. + */ + +#include "arch/mips/isa_traits.hh" +#include "config/full_system.hh" +#include "cpu/static_inst.hh" +#include "sim/serialize.hh" + +using namespace MipsISA; + + +//Function now Obsolete in current state. +//If anyting this should return the correct miscreg index +//but that is handled implicitly with enums anyway +void +MipsISA::getMiscRegIdx(int reg_name,int &idx, int &sel) +{ + switch(reg_name) + { + case Index: idx = 0; sel = 0; break; //0-0 Index into the TLB array + case MVPControl: idx = 0; sel = 1; break; //0-1 Per-processor register containing global + case MVPConf0: idx = 0; sel = 2; break; //0-2 Per-processor register containing global + case MVPConf1: idx = 0; sel = 3; break; //0-3 Per-processor register containing global + case Random: idx = 1; sel = 3; break; //1-0 Randomly generated index into the TLB array + case VPEControl: idx = 1; sel = 1; break; //1-1 Per-VPE register containing relatively volatile + //thread configuration data + case VPEConf0: idx = 1; sel = 2; break; //1-2 Per-VPE multi-thread configuration + //information + case VPEConf1: idx = 1; sel = 3; break; //1-3 Per-VPE multi-thread configuration + //information + case YQMask: idx = 1; sel = 4; break; //Per-VPE register defining which YIELD + //qualifier bits may be used without generating + //an exception + case VPESchedule: idx = 1; sel = 5; break; + case VPEScheFBack: idx = 1; sel = 6; break; + case VPEOpt: idx = 1; sel = 7; break; + case EntryLo0: idx = 1; sel = 5; break; + case TCStatus: idx = 1; sel = 5; break; + case TCBind: idx = 1; sel = 5; break; + case TCRestart: idx = 1; sel = 5; break; + case TCHalt: idx = 1; sel = 5; break; + case TCContext: idx = 1; sel = 5; break; + case TCSchedule: idx = 1; sel = 5; break; + case TCScheFBack: panic("Accessing Unimplemented CP0 Register"); break; + case EntryLo1: panic("Accessing Unimplemented CP0 Register"); break; + case Context: panic("Accessing Unimplemented CP0 Register"); break; + case ContextConfig: panic("Accessing Unimplemented CP0 Register"); break; + //case PageMask: panic("Accessing Unimplemented CP0 Register"); break; + case PageGrain: panic("Accessing Unimplemented CP0 Register"); break; + case Wired: panic("Accessing Unimplemented CP0 Register"); break; + case SRSConf0: panic("Accessing Unimplemented CP0 Register"); break; + case SRSConf1: panic("Accessing Unimplemented CP0 Register"); break; + case SRSConf2: panic("Accessing Unimplemented CP0 Register"); break; + case SRSConf3: panic("Accessing Unimplemented CP0 Register"); break; + case SRSConf4: panic("Accessing Unimplemented CP0 Register"); break; + case BadVAddr: panic("Accessing Unimplemented CP0 Register"); break; + case Count: panic("Accessing Unimplemented CP0 Register"); break; + case EntryHi: panic("Accessing Unimplemented CP0 Register"); break; + case Compare: panic("Accessing Unimplemented CP0 Register"); break; + case Status: idx = 12; sel = 0; break; //12-0 Processor status and control + case IntCtl: idx = 12; sel = 1; break; //12-1 Interrupt system status and control + case SRSCtl: idx = 12; sel = 2; break; //12-2 Shadow register set status and control + case SRSMap: idx = 12; sel = 3; break; //12-3 Shadow set IPL mapping + case Cause: idx = 13; sel = 0; break; //13-0 Cause of last general exception + case EPC: idx = 14; sel = 0; break; //14-0 Program counter at last exception + case PrId: idx = 15; sel = 0; break; //15-0 Processor identification and revision + case EBase: idx = 15; sel = 1; break; //15-1 Exception vector base register + case Config: panic("Accessing Unimplemented CP0 Register"); break; + case Config1: panic("Accessing Unimplemented CP0 Register"); break; + case Config2: panic("Accessing Unimplemented CP0 Register"); break; + case Config3: panic("Accessing Unimplemented CP0 Register"); break; + case LLAddr: panic("Accessing Unimplemented CP0 Register"); break; + case WatchLo: panic("Accessing Unimplemented CP0 Register"); break; + case WatchHi: panic("Accessing Unimplemented CP0 Register"); break; + case Debug: panic("Accessing Unimplemented CP0 Register"); break; + case TraceControl1: panic("Accessing Unimplemented CP0 Register"); break; + case TraceControl2: panic("Accessing Unimplemented CP0 Register"); break; + case UserTraceData: panic("Accessing Unimplemented CP0 Register"); break; + case TraceBPC: panic("Accessing Unimplemented CP0 Register"); break; + case DEPC: panic("Accessing Unimplemented CP0 Register"); break; + case PerfCnt: panic("Accessing Unimplemented CP0 Register"); break; + case ErrCtl: panic("Accessing Unimplemented CP0 Register"); break; + case CacheErr0: panic("Accessing Unimplemented CP0 Register"); break; + case CacheErr1: panic("Accessing Unimplemented CP0 Register"); break; + case CacheErr2: panic("Accessing Unimplemented CP0 Register"); break; + case CacheErr3: panic("Accessing Unimplemented CP0 Register"); break; + case TagLo: panic("Accessing Unimplemented CP0 Register"); break; + case DataLo: panic("Accessing Unimplemented CP0 Register"); break; + case TagHi: panic("Accessing Unimplemented CP0 Register"); break; + case DataHi: panic("Accessing Unimplemented CP0 Register"); break; + case ErrorEPC: panic("Accessing Unimplemented CP0 Register"); break; + + default: + panic("Accessing Unimplemented Misc. Register"); + } +} + +void RegFile::coldReset() +{ + //CP0 Random Reg: + //Randomly generated index into the TLB array + miscRegs[Random] = 0x0000003f; + + //CP0 Wired Reg. + miscRegs[Wired] = 0x0000000; + + //CP0 HWRENA + miscRegs[HWRena] = 0x0000000; + + //CP0 Status Reg. + miscRegs[Status] = 0x0400004; + + //CP0 INTCNTL + miscRegs[IntCtl] = 0xfc00000; + + //CP0 SRSCNTL + miscRegs[SRSCtl] = 0x0c00000; + + //CP0 SRSMAP + miscRegs[SRSMap] = 0x0000000; + + //CP0 Cause + miscRegs[Cause] = 0x0000000; + + //CP0 Processor ID + miscRegs[PrId] = 0x0019300; + + //CP0 EBASE + miscRegs[EBase] = 0x8000000; + + //CP0 Config Reg. + miscRegs[Config] = 0x80040482; + + //CP0 Config 1 Reg. + miscRegs[Config1] = 0xfee3719e; + + //CP0 Config 2 Reg. + miscRegs[Config2] = 0x8000000; + + //CP0 Config 3 Reg. + miscRegs[Config3] = 0x0000020; + + //CP0 Config 7 Reg. + miscRegs[Config7] = 0x0000000; + + //CP0 Debug + miscRegs[Debug] = 0x0201800; + + //CP0 PERFCNTL1 + miscRegs[PerfCnt0] = 0x0000000; + + //CP0 PERFCNTL2 + miscRegs[PerfCnt1] = 0x0000000; + +} + +void RegFile::createCP0Regs() +{ +//Resize Coprocessor Register Banks to +// the number specified in MIPS32K VOL.III +// Chapter 8 + /* + //Cop-0 Regs. Bank 0: Index, + miscRegs[0].resize(4); + + //Cop-0 Regs. Bank 1: + miscRegs[1].resize(8); + + //Cop-0 Regs. Bank 2: + miscRegs[2].resize(8); + + //Cop-0 Regs. Bank 3: + miscRegs[3].resize(1); + + //Cop-0 Regs. Bank 4: + miscRegs[4].resize(2); + + //Cop-0 Regs. Bank 5: + miscRegs[5].resize(2); + + //Cop-0 Regs. Bank 6: + miscRegs[6].resize(6); + + //Cop-0 Regs. Bank 7: + miscRegs[7].resize(1); + + //Cop-0 Regs. Bank 8: + miscRegs[8].resize(1); + + //Cop-0 Regs. Bank 9: + miscRegs[9].resize(1); + + //Cop-0 Regs. Bank 10: + miscRegs[10].resize(1); + + //Cop-0 Regs. Bank 11: + miscRegs[11].resize(1); + + //Cop-0 Regs. Bank 12: + miscRegs[12].resize(4); + + //Cop-0 Regs. Bank 13: + miscRegs[13].resize(1); + + //Cop-0 Regs. Bank 14: + miscRegs[14].resize(1); + + //Cop-0 Regs. Bank 15: + miscRegs[15].resize(2); + + //Cop-0 Regs. Bank 16: + miscRegs[16].resize(4); + + //Cop-0 Regs. Bank 17: + miscRegs[17].resize(1); + + //Cop-0 Regs. Bank 18: + miscRegs[18].resize(8); + + //Cop-0 Regs. Bank 19: + miscRegs[19].resize(8); + + //Cop-0 Regs. Bank 20: + miscRegs[20].resize(1); + + //Cop-0 Regs. Bank 21: + //miscRegs[21].resize(1); + //Reserved for future extensions + + //Cop-0 Regs. Bank 22: + //miscRegs[22].resize(4); + //Available for implementation dependent use + + //Cop-0 Regs. Bank 23: + miscRegs[23].resize(5); + + //Cop-0 Regs. Bank 24: + miscRegs[24].resize(1); + + //Cop-0 Regs. Bank 25: + miscRegs[25].resize(8); + + //Cop-0 Regs. Bank 26: + miscRegs[26].resize(1); + + //Cop-0 Regs. Bank 27: + miscRegs[27].resize(4); + + //Cop-0 Regs. Bank 28: + miscRegs[28].resize(8); + + //Cop-0 Regs. Bank 29: + miscRegs[29].resize(8); + + //Cop-0 Regs. Bank 30: + miscRegs[30].resize(1); + + //Cop-0 Regs. Bank 31: + miscRegs[31].resize(1);*/ + +} + + +const Addr MipsISA::PageShift = 13; +const Addr MipsISA::PageBytes = ULL(1) << PageShift; +const Addr MipsISA::PageMask = ~(PageBytes - 1); +const Addr MipsISA::PageOffset = PageBytes - 1; + +#if FULL_SYSTEM + +//////////////////////////////////////////////////////////////////////// +// +// Translation stuff +// + +const Addr MipsISA::PteShift = 3; +const Addr MipsISA::NPtePageShift = PageShift - PteShift; +const Addr MipsISA::NPtePage = ULL(1) << NPtePageShift; +const Addr MipsISA::PteMask = NPtePage - 1; + +// User Virtual +const Addr MipsISA::USegBase = ULL(0x0); +const Addr MipsISA::USegEnd = ULL(0x000003ffffffffff); + +// Kernel Direct Mapped +const Addr MipsISA::K0SegBase = ULL(0xfffffc0000000000); +const Addr MipsISA::K0SegEnd = ULL(0xfffffdffffffffff); + +// Kernel Virtual +const Addr MipsISA::K1SegBase = ULL(0xfffffe0000000000); +const Addr MipsISA::K1SegEnd = ULL(0xffffffffffffffff); + +#endif + +// Mips UNOP (sll r0,r0,r0) +const MachInst MipsISA::NoopMachInst = 0x00000000; + +static inline Addr +TruncPage(Addr addr) +{ return addr & ~(MipsISA::PageBytes - 1); } + +static inline Addr +RoundPage(Addr addr) +{ return (addr + MipsISA::PageBytes - 1) & ~(MipsISA::PageBytes - 1); } + +void +RegFile::serialize(std::ostream &os) +{ + SERIALIZE_ARRAY(intRegFile, NumIntRegs); + SERIALIZE_ARRAY(floatRegFile.q, NumFloatRegs); + //SERIALIZE_SCALAR(miscRegs.fpcr); + //SERIALIZE_SCALAR(miscRegs.uniq); + //SERIALIZE_SCALAR(miscRegs.lock_flag); + //SERIALIZE_SCALAR(miscRegs.lock_addr); + SERIALIZE_SCALAR(pc); + SERIALIZE_SCALAR(npc); + SERIALIZE_SCALAR(nnpc); +#if FULL_SYSTEM + SERIALIZE_ARRAY(palregs, NumIntRegs); + SERIALIZE_ARRAY(ipr, NumInternalProcRegs); + SERIALIZE_SCALAR(intrflag); + SERIALIZE_SCALAR(pal_shadow); +#endif +} + + +void +RegFile::unserialize(Checkpoint *cp, const std::string §ion) +{ + UNSERIALIZE_ARRAY(intRegFile, NumIntRegs); + UNSERIALIZE_ARRAY(floatRegFile.q, NumFloatRegs); + //UNSERIALIZE_SCALAR(miscRegs.fpcr); + //UNSERIALIZE_SCALAR(miscRegs.uniq); + //UNSERIALIZE_SCALAR(miscRegs.lock_flag); + //UNSERIALIZE_SCALAR(miscRegs.lock_addr); + UNSERIALIZE_SCALAR(pc); + UNSERIALIZE_SCALAR(npc); + UNSERIALIZE_SCALAR(nnpc); +#if FULL_SYSTEM + UNSERIALIZE_ARRAY(palregs, NumIntRegs); + UNSERIALIZE_ARRAY(ipr, NumInternalProcRegs); + UNSERIALIZE_SCALAR(intrflag); + UNSERIALIZE_SCALAR(pal_shadow); +#endif +} + + +#if FULL_SYSTEM +void +PTE::serialize(std::ostream &os) +{ + SERIALIZE_SCALAR(tag); + SERIALIZE_SCALAR(ppn); + SERIALIZE_SCALAR(xre); + SERIALIZE_SCALAR(xwe); + SERIALIZE_SCALAR(asn); + SERIALIZE_SCALAR(asma); + SERIALIZE_SCALAR(fonr); + SERIALIZE_SCALAR(fonw); + SERIALIZE_SCALAR(valid); +} + + +void +PTE::unserialize(Checkpoint *cp, const std::string §ion) +{ + UNSERIALIZE_SCALAR(tag); + UNSERIALIZE_SCALAR(ppn); + UNSERIALIZE_SCALAR(xre); + UNSERIALIZE_SCALAR(xwe); + UNSERIALIZE_SCALAR(asn); + UNSERIALIZE_SCALAR(asma); + UNSERIALIZE_SCALAR(fonr); + UNSERIALIZE_SCALAR(fonw); + UNSERIALIZE_SCALAR(valid); +} + +#endif //FULL_SYSTEM diff --git a/arch/mips/isa_traits.hh b/arch/mips/isa_traits.hh new file mode 100644 index 000000000..1dfa0dc7a --- /dev/null +++ b/arch/mips/isa_traits.hh @@ -0,0 +1,546 @@ +/* + * Copyright (c) 2003-2005 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. + */ + +#ifndef __ARCH_MIPS_ISA_TRAITS_HH__ +#define __ARCH_MIPS_ISA_TRAITS_HH__ + +//#include "arch/mips/misc_regfile.hh" +#include "base/misc.hh" +#include "config/full_system.hh" +#include "sim/host.hh" +#include "sim/faults.hh" + +#include <vector> + +class FastCPU; +class FullCPU; +class Checkpoint; + +namespace LittleEndianGuest {}; +using namespace LittleEndianGuest; + +#define TARGET_MIPS + +class StaticInst; +class StaticInstPtr; + +namespace MIPS34K { +int DTB_ASN_ASN(uint64_t reg); +int ITB_ASN_ASN(uint64_t reg); +}; + +namespace MipsISA +{ + typedef uint32_t MachInst; +// typedef uint64_t Addr; + typedef uint8_t RegIndex; + + enum { + MemoryEnd = 0xffffffffffffffffULL, + + NumIntRegs = 32, + NumFloatRegs = 32, + NumMiscRegs = 258, //account for hi,lo regs + + MaxRegsOfAnyType = 32, + // Static instruction parameters + MaxInstSrcRegs = 3, + MaxInstDestRegs = 2, + + // semantically meaningful register indices + ZeroReg = 0, // architecturally meaningful + // the rest of these depend on the ABI + StackPointerReg = 30, + GlobalPointerReg = 29, + ProcedureValueReg = 27, + ReturnAddressReg = 26, + ReturnValueReg = 0, + FramePointerReg = 15, + ArgumentReg0 = 16, + ArgumentReg1 = 17, + ArgumentReg2 = 18, + ArgumentReg3 = 19, + ArgumentReg4 = 20, + ArgumentReg5 = 21, + + LogVMPageSize = 13, // 8K bytes + VMPageSize = (1 << LogVMPageSize), + + BranchPredAddrShiftAmt = 2, // instructions are 4-byte aligned + + WordBytes = 4, + HalfwordBytes = 2, + ByteBytes = 1, + DepNA = 0, + }; + + // These enumerate all the registers for dependence tracking. + enum DependenceTags { + // 0..31 are the integer regs 0..31 + // 32..63 are the FP regs 0..31, i.e. use (reg + FP_Base_DepTag) + FP_Base_DepTag = 32, + Ctrl_Base_DepTag = 64, + Fpcr_DepTag = 64, // floating point control register + Uniq_DepTag = 65, + IPR_Base_DepTag = 66, + MiscReg_DepTag = 67 + }; + + typedef uint64_t IntReg; + typedef IntReg IntRegFile[NumIntRegs]; + + // floating point register file entry type + typedef union { + uint64_t q; + double d; + } FloatReg; + + typedef union { + uint64_t q[NumFloatRegs]; // integer qword view + double d[NumFloatRegs]; // double-precision floating point view + } FloatRegFile; + + // cop-0/cop-1 system control register file + typedef uint64_t MiscReg; +//typedef MiscReg MiscRegFile[NumMiscRegs]; + class MiscRegFile { + public: + MiscReg + protected: + uint64_t fpcr; // floating point condition codes + uint64_t uniq; // process-unique register + bool lock_flag; // lock flag for LL/SC + Addr lock_addr; // lock address for LL/SC + + MiscReg miscRegFile[NumMiscRegs]; + + public: + //These functions should be removed once the simplescalar cpu model + //has been replaced. + int getInstAsid(); + int getDataAsid(); + + MiscReg readReg(int misc_reg) + { return miscRegFile[misc_reg]; } + + MiscReg readRegWithEffect(int misc_reg, Fault &fault, ExecContext *xc) + { return miscRegFile[misc_reg];} + + Fault setReg(int misc_reg, const MiscReg &val) + { miscRegFile[misc_reg] = val; return NoFault; } + + Fault setRegWithEffect(int misc_reg, const MiscReg &val, + ExecContext *xc) + { miscRegFile[misc_reg] = val; return NoFault; } + +#if FULL_SYSTEM + void clearIprs() { }; + + protected: + InternalProcReg ipr[NumInternalProcRegs]; // Internal processor regs + + private: + MiscReg readIpr(int idx, Fault &fault, ExecContext *xc) { } + + Fault setIpr(int idx, uint64_t val, ExecContext *xc) { } +#endif + friend class RegFile; + }; + + enum MiscRegTags { + //Coprocessor 0 Registers + //Reference MIPS32 Arch. for Programmers, Vol. III, Ch.8 + //(Register Number-Register Select) Summary of Register + //------------------------------------------------------ + Index = 0, //0-0 Index into the TLB array + + MVPControl = 1, //0-1 Per-processor register containing global + //MIPS® MT configuration data + + MVPConf0 = 2, //0-2 Per-processor register containing global + //MIPS® MT configuration data + + MVPConf1 = 3, //0-3 Per-processor register containing global + //MIPS® MT configuration data + + Random = 8, //1-0 Randomly generated index into the TLB array + + VPEControl = 9, //1-1 Per-VPE register containing relatively volatile + //thread configuration data + + VPEConf0 = 10, //1-2 Per-VPE multi-thread configuration + //information + + + VPEConf1 = 11, //1-2 Per-VPE multi-thread configuration + //information + + YQMask = 12, //Per-VPE register defining which YIELD + //qualifier bits may be used without generating + //an exception + + VPESchedule = 13, + VPEScheFBack = 14, + VPEOpt = 15, + EntryLo0 = 16, // Bank 3: 16 - 23 + TCStatus = 17, + TCBind = 18, + TCRestart = 19, + TCHalt = 20, + TCContext = 21, + TCSchedule = 22, + TCScheFBack = 23, + + EntryLo1 = 24,// Bank 4: 24 - 31 + + Context = 32, // Bank 5: 32 - 39 + ContextConfig = 33, + + //PageMask = 40, //Bank 6: 40 - 47 + PageGrain = 41, + + Wired = 48, //Bank 7:48 - 55 + SRSConf0 = 49, + SRSConf1 = 50, + SRSConf2 = 51, + SRSConf3 = 52, + SRSConf4 = 53, + BadVAddr = 54, + + HWRena = 56,//Bank 8:56 - 63 + + Count = 64, //Bank 9:64 - 71 + + EntryHi = 72,//Bank 10:72 - 79 + + Compare = 80,//Bank 11:80 - 87 + + Status = 88,//Bank 12:88 - 96 //12-0 Processor status and control + IntCtl = 89, //12-1 Interrupt system status and control + SRSCtl = 90, //12-2 Shadow register set status and control + SRSMap = 91, //12-3 Shadow set IPL mapping + + Cause = 97,//97-104 //13-0 Cause of last general exception + + EPC = 105,//105-112 //14-0 Program counter at last exception + + PRId = 113//113-120, //15-0 Processor identification and revision + EBase = 114, //15-1 Exception vector base register + + Config = 121,//Bank 16: 121-128 + Config1 = 122, + Config2 = 123, + Config3 = 124, + Config6 = 127, + Config7 = 128, + + + LLAddr = 129,//Bank 17: 129-136 + + WatchLo0 = 137,//Bank 18: 137-144 + WatchLo1 = 138, + WatchLo2 = 139, + WatchLo3 = 140, + WatchLo4 = 141, + WatchLo5 = 142, + WatchLo6 = 143, + WatchLo7 = 144, + + WatchHi0 = 145,//Bank 19: 145-152 + WatchHi1 = 146, + WatchHi2 = 147, + WatchHi3 = 148, + WatchHi4 = 149, + WatchHi5 = 150, + WatchHi6 = 151, + WatchHi7 = 152, + + XCContext64 = 153,//Bank 20: 153-160 + + //Bank 21: 161-168 + + //Bank 22: 169-176 + + Debug = 177, //Bank 23: 177-184 + TraceControl1 = 178, + TraceControl2 = 179, + UserTraceData = 180, + TraceBPC = 181, + + DEPC = 185,//Bank 24: 185-192 + + PerfCnt0 = 193,//Bank 25: 193 - 200 + PerfCnt1 = 194, + PerfCnt2 = 195, + PerfCnt3 = 196, + PerfCnt4 = 197, + PerfCnt5 = 198, + PerfCnt6 = 199, + PerfCnt7 = 200, + + ErrCtl = 201, //Bank 26: 201 - 208 + + CacheErr0 = 209, //Bank 27: 209 - 216 + CacheErr1 = 210, + CacheErr2 = 211, + CacheErr3 = 212, + + TagLo0 = 217,//Bank 28: 217 - 224 + DataLo1 = 218, + TagLo2 = 219, + DataLo3 = 220, + TagLo4 = 221, + DataLo5 = 222, + TagLo6 = 223, + DataLo7 = 234, + + TagHi0 = 233,//Bank 29: 233 - 240 + DataHi1 = 234, + TagHi2 = 235, + DataHi3 = 236, + TagHi4 = 237, + DataHi5 = 238, + TagHi6 = 239, + DataHi7 = 240, + + + ErrorEPC = 249,//Bank 30: 241 - 248 + + DESAVE = 257,//Bank 31: 249-256 + + //More Misc. Regs + Hi, + Lo, + FCSR, + FPCR, + + //Alpha Regs, but here now, for + //compiling sake + UNIQ, + LockAddr, + LockFlag + }; + +extern const Addr PageShift; +extern const Addr PageBytes; +extern const Addr PageMask; +extern const Addr PageOffset; + +#if FULL_SYSTEM + + typedef uint64_t InternalProcReg; + +#include "arch/mips/isa_fullsys_traits.hh" + +#else + enum { + NumInternalProcRegs = 0 + }; +#endif + + enum { + TotalNumRegs = + NumIntRegs + NumFloatRegs + NumMiscRegs + NumInternalProcRegs + }; + + enum { + TotalDataRegs = NumIntRegs + NumFloatRegs + }; + + typedef union { + IntReg intreg; + FloatReg fpreg; + MiscReg ctrlreg; + } AnyReg; + + struct RegFile { + IntRegFile intRegFile; // (signed) integer register file + FloatRegFile floatRegFile; // floating point register file + MiscRegFile miscRegs; // control register file + + + Addr pc; // program counter + Addr npc; // next-cycle program counter + Addr nnpc; // next-next-cycle program counter + // used to implement branch delay slot + // not real register + + MiscReg hi; // MIPS HI Register + MiscReg lo; // MIPS LO Register + + +#if FULL_SYSTEM + IntReg palregs[NumIntRegs]; // PAL shadow registers + InternalProcReg ipr[NumInternalProcRegs]; // internal processor regs + int intrflag; // interrupt flag + bool pal_shadow; // using pal_shadow registers + inline int instAsid() { return MIPS34K::ITB_ASN_ASN(ipr[IPR_ITB_ASN]); } + inline int dataAsid() { return MIPS34K::DTB_ASN_ASN(ipr[IPR_DTB_ASN]); } +#endif // FULL_SYSTEM + + //void initCP0Regs(); + void serialize(std::ostream &os); + void unserialize(Checkpoint *cp, const std::string §ion); + + void createCP0Regs(); + void coldReset(); + }; + + StaticInstPtr decodeInst(MachInst); + + // return a no-op instruction... used for instruction fetch faults + extern const MachInst NoopMachInst; + + enum annotes { + ANNOTE_NONE = 0, + // An impossible number for instruction annotations + ITOUCH_ANNOTE = 0xffffffff, + }; + + void getMiscRegIdx(int reg_name,int &idx, int &sel); + + + static inline bool isCallerSaveIntegerRegister(unsigned int reg) { + panic("register classification not implemented"); + return (reg >= 1 && reg <= 8 || reg >= 22 && reg <= 25 || reg == 27); + } + + static inline bool isCalleeSaveIntegerRegister(unsigned int reg) { + panic("register classification not implemented"); + return (reg >= 9 && reg <= 15); + } + + static inline bool isCallerSaveFloatRegister(unsigned int reg) { + panic("register classification not implemented"); + return false; + } + + static inline bool isCalleeSaveFloatRegister(unsigned int reg) { + panic("register classification not implemented"); + return false; + } + + static inline Addr alignAddress(const Addr &addr, + unsigned int nbytes) { + return (addr & ~(nbytes - 1)); + } + + // Instruction address compression hooks + static inline Addr realPCToFetchPC(const Addr &addr) { + return addr; + } + + static inline Addr fetchPCToRealPC(const Addr &addr) { + return addr; + } + + // the size of "fetched" instructions (not necessarily the size + // of real instructions for PISA) + static inline size_t fetchInstSize() { + return sizeof(MachInst); + } + + static inline MachInst makeRegisterCopy(int dest, int src) { + panic("makeRegisterCopy not implemented"); + return 0; + } + + // Machine operations + + void saveMachineReg(AnyReg &savereg, const RegFile ®_file, + int regnum); + + void restoreMachineReg(RegFile ®s, const AnyReg ®, + int regnum); + +#if 0 + static void serializeSpecialRegs(const Serializable::Proxy &proxy, + const RegFile ®s); + + static void unserializeSpecialRegs(const IniFile *db, + const std::string &category, + ConfigNode *node, + RegFile ®s); +#endif + + /** + * Function to insure ISA semantics about 0 registers. + * @param xc The execution context. + */ + template <class XC> + void zeroRegisters(XC *xc); + + const Addr MaxAddr = (Addr)-1; +}; + +#if !FULL_SYSTEM +class SyscallReturn { + public: + template <class T> + SyscallReturn(T v, bool s) + { + retval = (uint64_t)v; + success = s; + } + + template <class T> + SyscallReturn(T v) + { + success = (v >= 0); + retval = (uint64_t)v; + } + + ~SyscallReturn() {} + + SyscallReturn& operator=(const SyscallReturn& s) { + retval = s.retval; + success = s.success; + return *this; + } + + bool successful() { return success; } + uint64_t value() { return retval; } + + + private: + uint64_t retval; + bool success; +}; + +#endif + + +#if FULL_SYSTEM +//typedef TheISA::InternalProcReg InternalProcReg; +//const int NumInternalProcRegs = TheISA::NumInternalProcRegs; +//const int NumInterruptLevels = TheISA::NumInterruptLevels; + +#include "arch/mips/mips34k.hh" +#endif + +#endif // __ARCH_MIPS_ISA_TRAITS_HH__ diff --git a/arch/mips/linux_process.cc b/arch/mips/linux_process.cc new file mode 100644 index 000000000..1d4f62350 --- /dev/null +++ b/arch/mips/linux_process.cc @@ -0,0 +1,588 @@ +/* + * Copyright (c) 2003-2005 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. + */ + +#include "arch/mips/common_syscall_emul.hh" +#include "arch/mips/linux_process.hh" +#include "arch/mips/isa_traits.hh" + +#include "base/trace.hh" +#include "cpu/exec_context.hh" +#include "kern/linux/linux.hh" +#include "mem/functional/functional.hh" + +#include "sim/process.hh" +#include "sim/syscall_emul.hh" + +using namespace std; +using namespace MipsISA; + +/// Target uname() handler. +static SyscallReturn +unameFunc(SyscallDesc *desc, int callnum, Process *process, + ExecContext *xc) +{ + TypedBufferArg<Linux::utsname> name(xc->getSyscallArg(0)); + + strcpy(name->sysname, "Linux"); + strcpy(name->nodename, "m5.eecs.umich.edu"); + strcpy(name->release, "2.4.20"); + strcpy(name->version, "#1 Mon Aug 18 11:32:15 EDT 2003"); + strcpy(name->machine, "mips"); + + name.copyOut(xc->mem); + return 0; +} + +/// Target osf_getsysyinfo() handler. Even though this call is +/// borrowed from Tru64, the subcases that get used appear to be +/// different in practice from those used by Tru64 processes. +static SyscallReturn +osf_getsysinfoFunc(SyscallDesc *desc, int callnum, Process *process, + ExecContext *xc) +{ + unsigned op = xc->getSyscallArg(0); + // unsigned nbytes = xc->getSyscallArg(2); + + switch (op) { + + case 45: { // GSI_IEEE_FP_CONTROL + TypedBufferArg<uint64_t> fpcr(xc->getSyscallArg(1)); + // I don't think this exactly matches the HW FPCR + *fpcr = 0; + fpcr.copyOut(xc->mem); + return 0; + } + + default: + cerr << "osf_getsysinfo: unknown op " << op << endl; + abort(); + break; + } + + return 1; +} + +/// Target osf_setsysinfo() handler. +static SyscallReturn +osf_setsysinfoFunc(SyscallDesc *desc, int callnum, Process *process, + ExecContext *xc) +{ + unsigned op = xc->getSyscallArg(0); + // unsigned nbytes = xc->getSyscallArg(2); + + switch (op) { + + case 14: { // SSI_IEEE_FP_CONTROL + TypedBufferArg<uint64_t> fpcr(xc->getSyscallArg(1)); + // I don't think this exactly matches the HW FPCR + fpcr.copyIn(xc->mem); + DPRINTFR(SyscallVerbose, "osf_setsysinfo(SSI_IEEE_FP_CONTROL): " + " setting FPCR to 0x%x\n", gtoh(*(uint64_t*)fpcr)); + return 0; + } + + default: + cerr << "osf_setsysinfo: unknown op " << op << endl; + abort(); + break; + } + + return 1; +} + + +SyscallDesc MipsLinuxProcess::syscallDescs[] = { + /* 0 */ SyscallDesc("osf_syscall", unimplementedFunc), + /* 1 */ SyscallDesc("exit", exitFunc), + /* 2 */ SyscallDesc("fork", unimplementedFunc), + /* 3 */ SyscallDesc("read", readFunc), + /* 4 */ SyscallDesc("write", writeFunc), + /* 5 */ SyscallDesc("osf_old_open", unimplementedFunc), + /* 6 */ SyscallDesc("close", closeFunc), + /* 7 */ SyscallDesc("osf_wait4", unimplementedFunc), + /* 8 */ SyscallDesc("osf_old_creat", unimplementedFunc), + /* 9 */ SyscallDesc("link", unimplementedFunc), + /* 10 */ SyscallDesc("unlink", unlinkFunc), + /* 11 */ SyscallDesc("osf_execve", unimplementedFunc), + /* 12 */ SyscallDesc("chdir", unimplementedFunc), + /* 13 */ SyscallDesc("fchdir", unimplementedFunc), + /* 14 */ SyscallDesc("mknod", unimplementedFunc), + /* 15 */ SyscallDesc("chmod", chmodFunc<Linux>), + /* 16 */ SyscallDesc("chown", chownFunc), + /* 17 */ SyscallDesc("brk", obreakFunc), + /* 18 */ SyscallDesc("osf_getfsstat", unimplementedFunc), + /* 19 */ SyscallDesc("lseek", lseekFunc), + /* 20 */ SyscallDesc("getxpid", getpidFunc), + /* 21 */ SyscallDesc("osf_mount", unimplementedFunc), + /* 22 */ SyscallDesc("umount", unimplementedFunc), + /* 23 */ SyscallDesc("setuid", setuidFunc), + /* 24 */ SyscallDesc("getxuid", getuidFunc), + /* 25 */ SyscallDesc("exec_with_loader", unimplementedFunc), + /* 26 */ SyscallDesc("osf_ptrace", unimplementedFunc), + /* 27 */ SyscallDesc("osf_nrecvmsg", unimplementedFunc), + /* 28 */ SyscallDesc("osf_nsendmsg", unimplementedFunc), + /* 29 */ SyscallDesc("osf_nrecvfrom", unimplementedFunc), + /* 30 */ SyscallDesc("osf_naccept", unimplementedFunc), + /* 31 */ SyscallDesc("osf_ngetpeername", unimplementedFunc), + /* 32 */ SyscallDesc("osf_ngetsockname", unimplementedFunc), + /* 33 */ SyscallDesc("access", unimplementedFunc), + /* 34 */ SyscallDesc("osf_chflags", unimplementedFunc), + /* 35 */ SyscallDesc("osf_fchflags", unimplementedFunc), + /* 36 */ SyscallDesc("sync", unimplementedFunc), + /* 37 */ SyscallDesc("kill", unimplementedFunc), + /* 38 */ SyscallDesc("osf_old_stat", unimplementedFunc), + /* 39 */ SyscallDesc("setpgid", unimplementedFunc), + /* 40 */ SyscallDesc("osf_old_lstat", unimplementedFunc), + /* 41 */ SyscallDesc("dup", unimplementedFunc), + /* 42 */ SyscallDesc("pipe", unimplementedFunc), + /* 43 */ SyscallDesc("osf_set_program_attributes", unimplementedFunc), + /* 44 */ SyscallDesc("osf_profil", unimplementedFunc), + /* 45 */ SyscallDesc("open", openFunc<Linux>), + /* 46 */ SyscallDesc("osf_old_sigaction", unimplementedFunc), + /* 47 */ SyscallDesc("getxgid", getgidFunc), + /* 48 */ SyscallDesc("osf_sigprocmask", ignoreFunc), + /* 49 */ SyscallDesc("osf_getlogin", unimplementedFunc), + /* 50 */ SyscallDesc("osf_setlogin", unimplementedFunc), + /* 51 */ SyscallDesc("acct", unimplementedFunc), + /* 52 */ SyscallDesc("sigpending", unimplementedFunc), + /* 53 */ SyscallDesc("osf_classcntl", unimplementedFunc), + /* 54 */ SyscallDesc("ioctl", ioctlFunc<Linux>), + /* 55 */ SyscallDesc("osf_reboot", unimplementedFunc), + /* 56 */ SyscallDesc("osf_revoke", unimplementedFunc), + /* 57 */ SyscallDesc("symlink", unimplementedFunc), + /* 58 */ SyscallDesc("readlink", unimplementedFunc), + /* 59 */ SyscallDesc("execve", unimplementedFunc), + /* 60 */ SyscallDesc("umask", unimplementedFunc), + /* 61 */ SyscallDesc("chroot", unimplementedFunc), + /* 62 */ SyscallDesc("osf_old_fstat", unimplementedFunc), + /* 63 */ SyscallDesc("getpgrp", unimplementedFunc), + /* 64 */ SyscallDesc("getpagesize", getpagesizeFunc), + /* 65 */ SyscallDesc("osf_mremap", unimplementedFunc), + /* 66 */ SyscallDesc("vfork", unimplementedFunc), + /* 67 */ SyscallDesc("stat", statFunc<Linux>), + /* 68 */ SyscallDesc("lstat", lstatFunc<Linux>), + /* 69 */ SyscallDesc("osf_sbrk", unimplementedFunc), + /* 70 */ SyscallDesc("osf_sstk", unimplementedFunc), + /* 71 */ SyscallDesc("mmap", mmapFunc<Linux>), + /* 72 */ SyscallDesc("osf_old_vadvise", unimplementedFunc), + /* 73 */ SyscallDesc("munmap", munmapFunc), + /* 74 */ SyscallDesc("mprotect", ignoreFunc), + /* 75 */ SyscallDesc("madvise", unimplementedFunc), + /* 76 */ SyscallDesc("vhangup", unimplementedFunc), + /* 77 */ SyscallDesc("osf_kmodcall", unimplementedFunc), + /* 78 */ SyscallDesc("osf_mincore", unimplementedFunc), + /* 79 */ SyscallDesc("getgroups", unimplementedFunc), + /* 80 */ SyscallDesc("setgroups", unimplementedFunc), + /* 81 */ SyscallDesc("osf_old_getpgrp", unimplementedFunc), + /* 82 */ SyscallDesc("setpgrp", unimplementedFunc), + /* 83 */ SyscallDesc("osf_setitimer", unimplementedFunc), + /* 84 */ SyscallDesc("osf_old_wait", unimplementedFunc), + /* 85 */ SyscallDesc("osf_table", unimplementedFunc), + /* 86 */ SyscallDesc("osf_getitimer", unimplementedFunc), + /* 87 */ SyscallDesc("gethostname", gethostnameFunc), + /* 88 */ SyscallDesc("sethostname", unimplementedFunc), + /* 89 */ SyscallDesc("getdtablesize", unimplementedFunc), + /* 90 */ SyscallDesc("dup2", unimplementedFunc), + /* 91 */ SyscallDesc("fstat", fstatFunc<Linux>), + /* 92 */ SyscallDesc("fcntl", fcntlFunc), + /* 93 */ SyscallDesc("osf_select", unimplementedFunc), + /* 94 */ SyscallDesc("poll", unimplementedFunc), + /* 95 */ SyscallDesc("fsync", unimplementedFunc), + /* 96 */ SyscallDesc("setpriority", unimplementedFunc), + /* 97 */ SyscallDesc("socket", unimplementedFunc), + /* 98 */ SyscallDesc("connect", unimplementedFunc), + /* 99 */ SyscallDesc("accept", unimplementedFunc), + /* 100 */ SyscallDesc("getpriority", unimplementedFunc), + /* 101 */ SyscallDesc("send", unimplementedFunc), + /* 102 */ SyscallDesc("recv", unimplementedFunc), + /* 103 */ SyscallDesc("sigreturn", unimplementedFunc), + /* 104 */ SyscallDesc("bind", unimplementedFunc), + /* 105 */ SyscallDesc("setsockopt", unimplementedFunc), + /* 106 */ SyscallDesc("listen", unimplementedFunc), + /* 107 */ SyscallDesc("osf_plock", unimplementedFunc), + /* 108 */ SyscallDesc("osf_old_sigvec", unimplementedFunc), + /* 109 */ SyscallDesc("osf_old_sigblock", unimplementedFunc), + /* 110 */ SyscallDesc("osf_old_sigsetmask", unimplementedFunc), + /* 111 */ SyscallDesc("sigsuspend", unimplementedFunc), + /* 112 */ SyscallDesc("osf_sigstack", ignoreFunc), + /* 113 */ SyscallDesc("recvmsg", unimplementedFunc), + /* 114 */ SyscallDesc("sendmsg", unimplementedFunc), + /* 115 */ SyscallDesc("osf_old_vtrace", unimplementedFunc), + /* 116 */ SyscallDesc("osf_gettimeofday", unimplementedFunc), + /* 117 */ SyscallDesc("osf_getrusage", unimplementedFunc), + /* 118 */ SyscallDesc("getsockopt", unimplementedFunc), + /* 119 */ SyscallDesc("numa_syscalls", unimplementedFunc), + /* 120 */ SyscallDesc("readv", unimplementedFunc), + /* 121 */ SyscallDesc("writev", writevFunc<Linux>), + /* 122 */ SyscallDesc("osf_settimeofday", unimplementedFunc), + /* 123 */ SyscallDesc("fchown", fchownFunc), + /* 124 */ SyscallDesc("fchmod", fchmodFunc<Linux>), + /* 125 */ SyscallDesc("recvfrom", unimplementedFunc), + /* 126 */ SyscallDesc("setreuid", unimplementedFunc), + /* 127 */ SyscallDesc("setregid", unimplementedFunc), + /* 128 */ SyscallDesc("rename", renameFunc), + /* 129 */ SyscallDesc("truncate", unimplementedFunc), + /* 130 */ SyscallDesc("ftruncate", unimplementedFunc), + /* 131 */ SyscallDesc("flock", unimplementedFunc), + /* 132 */ SyscallDesc("setgid", unimplementedFunc), + /* 133 */ SyscallDesc("sendto", unimplementedFunc), + /* 134 */ SyscallDesc("shutdown", unimplementedFunc), + /* 135 */ SyscallDesc("socketpair", unimplementedFunc), + /* 136 */ SyscallDesc("mkdir", unimplementedFunc), + /* 137 */ SyscallDesc("rmdir", unimplementedFunc), + /* 138 */ SyscallDesc("osf_utimes", unimplementedFunc), + /* 139 */ SyscallDesc("osf_old_sigreturn", unimplementedFunc), + /* 140 */ SyscallDesc("osf_adjtime", unimplementedFunc), + /* 141 */ SyscallDesc("getpeername", unimplementedFunc), + /* 142 */ SyscallDesc("osf_gethostid", unimplementedFunc), + /* 143 */ SyscallDesc("osf_sethostid", unimplementedFunc), + /* 144 */ SyscallDesc("getrlimit", getrlimitFunc<Linux>), + /* 145 */ SyscallDesc("setrlimit", ignoreFunc), + /* 146 */ SyscallDesc("osf_old_killpg", unimplementedFunc), + /* 147 */ SyscallDesc("setsid", unimplementedFunc), + /* 148 */ SyscallDesc("quotactl", unimplementedFunc), + /* 149 */ SyscallDesc("osf_oldquota", unimplementedFunc), + /* 150 */ SyscallDesc("getsockname", unimplementedFunc), + /* 151 */ SyscallDesc("osf_pread", unimplementedFunc), + /* 152 */ SyscallDesc("osf_pwrite", unimplementedFunc), + /* 153 */ SyscallDesc("osf_pid_block", unimplementedFunc), + /* 154 */ SyscallDesc("osf_pid_unblock", unimplementedFunc), + /* 155 */ SyscallDesc("osf_signal_urti", unimplementedFunc), + /* 156 */ SyscallDesc("sigaction", ignoreFunc), + /* 157 */ SyscallDesc("osf_sigwaitprim", unimplementedFunc), + /* 158 */ SyscallDesc("osf_nfssvc", unimplementedFunc), + /* 159 */ SyscallDesc("osf_getdirentries", unimplementedFunc), + /* 160 */ SyscallDesc("osf_statfs", unimplementedFunc), + /* 161 */ SyscallDesc("osf_fstatfs", unimplementedFunc), + /* 162 */ SyscallDesc("unknown #162", unimplementedFunc), + /* 163 */ SyscallDesc("osf_async_daemon", unimplementedFunc), + /* 164 */ SyscallDesc("osf_getfh", unimplementedFunc), + /* 165 */ SyscallDesc("osf_getdomainname", unimplementedFunc), + /* 166 */ SyscallDesc("setdomainname", unimplementedFunc), + /* 167 */ SyscallDesc("unknown #167", unimplementedFunc), + /* 168 */ SyscallDesc("unknown #168", unimplementedFunc), + /* 169 */ SyscallDesc("osf_exportfs", unimplementedFunc), + /* 170 */ SyscallDesc("unknown #170", unimplementedFunc), + /* 171 */ SyscallDesc("unknown #171", unimplementedFunc), + /* 172 */ SyscallDesc("unknown #172", unimplementedFunc), + /* 173 */ SyscallDesc("unknown #173", unimplementedFunc), + /* 174 */ SyscallDesc("unknown #174", unimplementedFunc), + /* 175 */ SyscallDesc("unknown #175", unimplementedFunc), + /* 176 */ SyscallDesc("unknown #176", unimplementedFunc), + /* 177 */ SyscallDesc("unknown #177", unimplementedFunc), + /* 178 */ SyscallDesc("unknown #178", unimplementedFunc), + /* 179 */ SyscallDesc("unknown #179", unimplementedFunc), + /* 180 */ SyscallDesc("unknown #180", unimplementedFunc), + /* 181 */ SyscallDesc("osf_alt_plock", unimplementedFunc), + /* 182 */ SyscallDesc("unknown #182", unimplementedFunc), + /* 183 */ SyscallDesc("unknown #183", unimplementedFunc), + /* 184 */ SyscallDesc("osf_getmnt", unimplementedFunc), + /* 185 */ SyscallDesc("unknown #185", unimplementedFunc), + /* 186 */ SyscallDesc("unknown #186", unimplementedFunc), + /* 187 */ SyscallDesc("osf_alt_sigpending", unimplementedFunc), + /* 188 */ SyscallDesc("osf_alt_setsid", unimplementedFunc), + /* 189 */ SyscallDesc("unknown #189", unimplementedFunc), + /* 190 */ SyscallDesc("unknown #190", unimplementedFunc), + /* 191 */ SyscallDesc("unknown #191", unimplementedFunc), + /* 192 */ SyscallDesc("unknown #192", unimplementedFunc), + /* 193 */ SyscallDesc("unknown #193", unimplementedFunc), + /* 194 */ SyscallDesc("unknown #194", unimplementedFunc), + /* 195 */ SyscallDesc("unknown #195", unimplementedFunc), + /* 196 */ SyscallDesc("unknown #196", unimplementedFunc), + /* 197 */ SyscallDesc("unknown #197", unimplementedFunc), + /* 198 */ SyscallDesc("unknown #198", unimplementedFunc), + /* 199 */ SyscallDesc("osf_swapon", unimplementedFunc), + /* 200 */ SyscallDesc("msgctl", unimplementedFunc), + /* 201 */ SyscallDesc("msgget", unimplementedFunc), + /* 202 */ SyscallDesc("msgrcv", unimplementedFunc), + /* 203 */ SyscallDesc("msgsnd", unimplementedFunc), + /* 204 */ SyscallDesc("semctl", unimplementedFunc), + /* 205 */ SyscallDesc("semget", unimplementedFunc), + /* 206 */ SyscallDesc("semop", unimplementedFunc), + /* 207 */ SyscallDesc("osf_utsname", unimplementedFunc), + /* 208 */ SyscallDesc("lchown", unimplementedFunc), + /* 209 */ SyscallDesc("osf_shmat", unimplementedFunc), + /* 210 */ SyscallDesc("shmctl", unimplementedFunc), + /* 211 */ SyscallDesc("shmdt", unimplementedFunc), + /* 212 */ SyscallDesc("shmget", unimplementedFunc), + /* 213 */ SyscallDesc("osf_mvalid", unimplementedFunc), + /* 214 */ SyscallDesc("osf_getaddressconf", unimplementedFunc), + /* 215 */ SyscallDesc("osf_msleep", unimplementedFunc), + /* 216 */ SyscallDesc("osf_mwakeup", unimplementedFunc), + /* 217 */ SyscallDesc("msync", unimplementedFunc), + /* 218 */ SyscallDesc("osf_signal", unimplementedFunc), + /* 219 */ SyscallDesc("osf_utc_gettime", unimplementedFunc), + /* 220 */ SyscallDesc("osf_utc_adjtime", unimplementedFunc), + /* 221 */ SyscallDesc("unknown #221", unimplementedFunc), + /* 222 */ SyscallDesc("osf_security", unimplementedFunc), + /* 223 */ SyscallDesc("osf_kloadcall", unimplementedFunc), + /* 224 */ SyscallDesc("unknown #224", unimplementedFunc), + /* 225 */ SyscallDesc("unknown #225", unimplementedFunc), + /* 226 */ SyscallDesc("unknown #226", unimplementedFunc), + /* 227 */ SyscallDesc("unknown #227", unimplementedFunc), + /* 228 */ SyscallDesc("unknown #228", unimplementedFunc), + /* 229 */ SyscallDesc("unknown #229", unimplementedFunc), + /* 230 */ SyscallDesc("unknown #230", unimplementedFunc), + /* 231 */ SyscallDesc("unknown #231", unimplementedFunc), + /* 232 */ SyscallDesc("unknown #232", unimplementedFunc), + /* 233 */ SyscallDesc("getpgid", unimplementedFunc), + /* 234 */ SyscallDesc("getsid", unimplementedFunc), + /* 235 */ SyscallDesc("sigaltstack", ignoreFunc), + /* 236 */ SyscallDesc("osf_waitid", unimplementedFunc), + /* 237 */ SyscallDesc("osf_priocntlset", unimplementedFunc), + /* 238 */ SyscallDesc("osf_sigsendset", unimplementedFunc), + /* 239 */ SyscallDesc("osf_set_speculative", unimplementedFunc), + /* 240 */ SyscallDesc("osf_msfs_syscall", unimplementedFunc), + /* 241 */ SyscallDesc("osf_sysinfo", unimplementedFunc), + /* 242 */ SyscallDesc("osf_uadmin", unimplementedFunc), + /* 243 */ SyscallDesc("osf_fuser", unimplementedFunc), + /* 244 */ SyscallDesc("osf_proplist_syscall", unimplementedFunc), + /* 245 */ SyscallDesc("osf_ntp_adjtime", unimplementedFunc), + /* 246 */ SyscallDesc("osf_ntp_gettime", unimplementedFunc), + /* 247 */ SyscallDesc("osf_pathconf", unimplementedFunc), + /* 248 */ SyscallDesc("osf_fpathconf", unimplementedFunc), + /* 249 */ SyscallDesc("unknown #249", unimplementedFunc), + /* 250 */ SyscallDesc("osf_uswitch", unimplementedFunc), + /* 251 */ SyscallDesc("osf_usleep_thread", unimplementedFunc), + /* 252 */ SyscallDesc("osf_audcntl", unimplementedFunc), + /* 253 */ SyscallDesc("osf_audgen", unimplementedFunc), + /* 254 */ SyscallDesc("sysfs", unimplementedFunc), + /* 255 */ SyscallDesc("osf_subsys_info", unimplementedFunc), + /* 256 */ SyscallDesc("osf_getsysinfo", osf_getsysinfoFunc), + /* 257 */ SyscallDesc("osf_setsysinfo", osf_setsysinfoFunc), + /* 258 */ SyscallDesc("osf_afs_syscall", unimplementedFunc), + /* 259 */ SyscallDesc("osf_swapctl", unimplementedFunc), + /* 260 */ SyscallDesc("osf_memcntl", unimplementedFunc), + /* 261 */ SyscallDesc("osf_fdatasync", unimplementedFunc), + /* 262 */ SyscallDesc("unknown #262", unimplementedFunc), + /* 263 */ SyscallDesc("unknown #263", unimplementedFunc), + /* 264 */ SyscallDesc("unknown #264", unimplementedFunc), + /* 265 */ SyscallDesc("unknown #265", unimplementedFunc), + /* 266 */ SyscallDesc("unknown #266", unimplementedFunc), + /* 267 */ SyscallDesc("unknown #267", unimplementedFunc), + /* 268 */ SyscallDesc("unknown #268", unimplementedFunc), + /* 269 */ SyscallDesc("unknown #269", unimplementedFunc), + /* 270 */ SyscallDesc("unknown #270", unimplementedFunc), + /* 271 */ SyscallDesc("unknown #271", unimplementedFunc), + /* 272 */ SyscallDesc("unknown #272", unimplementedFunc), + /* 273 */ SyscallDesc("unknown #273", unimplementedFunc), + /* 274 */ SyscallDesc("unknown #274", unimplementedFunc), + /* 275 */ SyscallDesc("unknown #275", unimplementedFunc), + /* 276 */ SyscallDesc("unknown #276", unimplementedFunc), + /* 277 */ SyscallDesc("unknown #277", unimplementedFunc), + /* 278 */ SyscallDesc("unknown #278", unimplementedFunc), + /* 279 */ SyscallDesc("unknown #279", unimplementedFunc), + /* 280 */ SyscallDesc("unknown #280", unimplementedFunc), + /* 281 */ SyscallDesc("unknown #281", unimplementedFunc), + /* 282 */ SyscallDesc("unknown #282", unimplementedFunc), + /* 283 */ SyscallDesc("unknown #283", unimplementedFunc), + /* 284 */ SyscallDesc("unknown #284", unimplementedFunc), + /* 285 */ SyscallDesc("unknown #285", unimplementedFunc), + /* 286 */ SyscallDesc("unknown #286", unimplementedFunc), + /* 287 */ SyscallDesc("unknown #287", unimplementedFunc), + /* 288 */ SyscallDesc("unknown #288", unimplementedFunc), + /* 289 */ SyscallDesc("unknown #289", unimplementedFunc), + /* 290 */ SyscallDesc("unknown #290", unimplementedFunc), + /* 291 */ SyscallDesc("unknown #291", unimplementedFunc), + /* 292 */ SyscallDesc("unknown #292", unimplementedFunc), + /* 293 */ SyscallDesc("unknown #293", unimplementedFunc), + /* 294 */ SyscallDesc("unknown #294", unimplementedFunc), + /* 295 */ SyscallDesc("unknown #295", unimplementedFunc), + /* 296 */ SyscallDesc("unknown #296", unimplementedFunc), + /* 297 */ SyscallDesc("unknown #297", unimplementedFunc), + /* 298 */ SyscallDesc("unknown #298", unimplementedFunc), + /* 299 */ SyscallDesc("unknown #299", unimplementedFunc), +/* + * Linux-specific system calls begin at 300 + */ + /* 300 */ SyscallDesc("bdflush", unimplementedFunc), + /* 301 */ SyscallDesc("sethae", unimplementedFunc), + /* 302 */ SyscallDesc("mount", unimplementedFunc), + /* 303 */ SyscallDesc("old_adjtimex", unimplementedFunc), + /* 304 */ SyscallDesc("swapoff", unimplementedFunc), + /* 305 */ SyscallDesc("getdents", unimplementedFunc), + /* 306 */ SyscallDesc("create_module", unimplementedFunc), + /* 307 */ SyscallDesc("init_module", unimplementedFunc), + /* 308 */ SyscallDesc("delete_module", unimplementedFunc), + /* 309 */ SyscallDesc("get_kernel_syms", unimplementedFunc), + /* 310 */ SyscallDesc("syslog", unimplementedFunc), + /* 311 */ SyscallDesc("reboot", unimplementedFunc), + /* 312 */ SyscallDesc("clone", unimplementedFunc), + /* 313 */ SyscallDesc("uselib", unimplementedFunc), + /* 314 */ SyscallDesc("mlock", unimplementedFunc), + /* 315 */ SyscallDesc("munlock", unimplementedFunc), + /* 316 */ SyscallDesc("mlockall", unimplementedFunc), + /* 317 */ SyscallDesc("munlockall", unimplementedFunc), + /* 318 */ SyscallDesc("sysinfo", unimplementedFunc), + /* 319 */ SyscallDesc("_sysctl", unimplementedFunc), + /* 320 */ SyscallDesc("was sys_idle", unimplementedFunc), + /* 321 */ SyscallDesc("oldumount", unimplementedFunc), + /* 322 */ SyscallDesc("swapon", unimplementedFunc), + /* 323 */ SyscallDesc("times", ignoreFunc), + /* 324 */ SyscallDesc("personality", unimplementedFunc), + /* 325 */ SyscallDesc("setfsuid", unimplementedFunc), + /* 326 */ SyscallDesc("setfsgid", unimplementedFunc), + /* 327 */ SyscallDesc("ustat", unimplementedFunc), + /* 328 */ SyscallDesc("statfs", unimplementedFunc), + /* 329 */ SyscallDesc("fstatfs", unimplementedFunc), + /* 330 */ SyscallDesc("sched_setparam", unimplementedFunc), + /* 331 */ SyscallDesc("sched_getparam", unimplementedFunc), + /* 332 */ SyscallDesc("sched_setscheduler", unimplementedFunc), + /* 333 */ SyscallDesc("sched_getscheduler", unimplementedFunc), + /* 334 */ SyscallDesc("sched_yield", unimplementedFunc), + /* 335 */ SyscallDesc("sched_get_priority_max", unimplementedFunc), + /* 336 */ SyscallDesc("sched_get_priority_min", unimplementedFunc), + /* 337 */ SyscallDesc("sched_rr_get_interval", unimplementedFunc), + /* 338 */ SyscallDesc("afs_syscall", unimplementedFunc), + /* 339 */ SyscallDesc("uname", unameFunc), + /* 340 */ SyscallDesc("nanosleep", unimplementedFunc), + /* 341 */ SyscallDesc("mremap", unimplementedFunc), + /* 342 */ SyscallDesc("nfsservctl", unimplementedFunc), + /* 343 */ SyscallDesc("setresuid", unimplementedFunc), + /* 344 */ SyscallDesc("getresuid", unimplementedFunc), + /* 345 */ SyscallDesc("pciconfig_read", unimplementedFunc), + /* 346 */ SyscallDesc("pciconfig_write", unimplementedFunc), + /* 347 */ SyscallDesc("query_module", unimplementedFunc), + /* 348 */ SyscallDesc("prctl", unimplementedFunc), + /* 349 */ SyscallDesc("pread", unimplementedFunc), + /* 350 */ SyscallDesc("pwrite", unimplementedFunc), + /* 351 */ SyscallDesc("rt_sigreturn", unimplementedFunc), + /* 352 */ SyscallDesc("rt_sigaction", ignoreFunc), + /* 353 */ SyscallDesc("rt_sigprocmask", unimplementedFunc), + /* 354 */ SyscallDesc("rt_sigpending", unimplementedFunc), + /* 355 */ SyscallDesc("rt_sigtimedwait", unimplementedFunc), + /* 356 */ SyscallDesc("rt_sigqueueinfo", unimplementedFunc), + /* 357 */ SyscallDesc("rt_sigsuspend", unimplementedFunc), + /* 358 */ SyscallDesc("select", unimplementedFunc), + /* 359 */ SyscallDesc("gettimeofday", gettimeofdayFunc<Linux>), + /* 360 */ SyscallDesc("settimeofday", unimplementedFunc), + /* 361 */ SyscallDesc("getitimer", unimplementedFunc), + /* 362 */ SyscallDesc("setitimer", unimplementedFunc), + /* 363 */ SyscallDesc("utimes", utimesFunc<Linux>), + /* 364 */ SyscallDesc("getrusage", getrusageFunc<Linux>), + /* 365 */ SyscallDesc("wait4", unimplementedFunc), + /* 366 */ SyscallDesc("adjtimex", unimplementedFunc), + /* 367 */ SyscallDesc("getcwd", unimplementedFunc), + /* 368 */ SyscallDesc("capget", unimplementedFunc), + /* 369 */ SyscallDesc("capset", unimplementedFunc), + /* 370 */ SyscallDesc("sendfile", unimplementedFunc), + /* 371 */ SyscallDesc("setresgid", unimplementedFunc), + /* 372 */ SyscallDesc("getresgid", unimplementedFunc), + /* 373 */ SyscallDesc("dipc", unimplementedFunc), + /* 374 */ SyscallDesc("pivot_root", unimplementedFunc), + /* 375 */ SyscallDesc("mincore", unimplementedFunc), + /* 376 */ SyscallDesc("pciconfig_iobase", unimplementedFunc), + /* 377 */ SyscallDesc("getdents64", unimplementedFunc), + /* 378 */ SyscallDesc("gettid", unimplementedFunc), + /* 379 */ SyscallDesc("readahead", unimplementedFunc), + /* 380 */ SyscallDesc("security", unimplementedFunc), + /* 381 */ SyscallDesc("tkill", unimplementedFunc), + /* 382 */ SyscallDesc("setxattr", unimplementedFunc), + /* 383 */ SyscallDesc("lsetxattr", unimplementedFunc), + /* 384 */ SyscallDesc("fsetxattr", unimplementedFunc), + /* 385 */ SyscallDesc("getxattr", unimplementedFunc), + /* 386 */ SyscallDesc("lgetxattr", unimplementedFunc), + /* 387 */ SyscallDesc("fgetxattr", unimplementedFunc), + /* 388 */ SyscallDesc("listxattr", unimplementedFunc), + /* 389 */ SyscallDesc("llistxattr", unimplementedFunc), + /* 390 */ SyscallDesc("flistxattr", unimplementedFunc), + /* 391 */ SyscallDesc("removexattr", unimplementedFunc), + /* 392 */ SyscallDesc("lremovexattr", unimplementedFunc), + /* 393 */ SyscallDesc("fremovexattr", unimplementedFunc), + /* 394 */ SyscallDesc("futex", unimplementedFunc), + /* 395 */ SyscallDesc("sched_setaffinity", unimplementedFunc), + /* 396 */ SyscallDesc("sched_getaffinity", unimplementedFunc), + /* 397 */ SyscallDesc("tuxcall", unimplementedFunc), + /* 398 */ SyscallDesc("io_setup", unimplementedFunc), + /* 399 */ SyscallDesc("io_destroy", unimplementedFunc), + /* 400 */ SyscallDesc("io_getevents", unimplementedFunc), + /* 401 */ SyscallDesc("io_submit", unimplementedFunc), + /* 402 */ SyscallDesc("io_cancel", unimplementedFunc), + /* 403 */ SyscallDesc("unknown #403", unimplementedFunc), + /* 404 */ SyscallDesc("unknown #404", unimplementedFunc), + /* 405 */ SyscallDesc("exit_group", exitFunc), // exit all threads... + /* 406 */ SyscallDesc("lookup_dcookie", unimplementedFunc), + /* 407 */ SyscallDesc("sys_epoll_create", unimplementedFunc), + /* 408 */ SyscallDesc("sys_epoll_ctl", unimplementedFunc), + /* 409 */ SyscallDesc("sys_epoll_wait", unimplementedFunc), + /* 410 */ SyscallDesc("remap_file_pages", unimplementedFunc), + /* 411 */ SyscallDesc("set_tid_address", unimplementedFunc), + /* 412 */ SyscallDesc("restart_syscall", unimplementedFunc), + /* 413 */ SyscallDesc("fadvise64", unimplementedFunc), + /* 414 */ SyscallDesc("timer_create", unimplementedFunc), + /* 415 */ SyscallDesc("timer_settime", unimplementedFunc), + /* 416 */ SyscallDesc("timer_gettime", unimplementedFunc), + /* 417 */ SyscallDesc("timer_getoverrun", unimplementedFunc), + /* 418 */ SyscallDesc("timer_delete", unimplementedFunc), + /* 419 */ SyscallDesc("clock_settime", unimplementedFunc), + /* 420 */ SyscallDesc("clock_gettime", unimplementedFunc), + /* 421 */ SyscallDesc("clock_getres", unimplementedFunc), + /* 422 */ SyscallDesc("clock_nanosleep", unimplementedFunc), + /* 423 */ SyscallDesc("semtimedop", unimplementedFunc), + /* 424 */ SyscallDesc("tgkill", unimplementedFunc), + /* 425 */ SyscallDesc("stat64", unimplementedFunc), + /* 426 */ SyscallDesc("lstat64", lstat64Func<Linux>), + /* 427 */ SyscallDesc("fstat64", fstat64Func<Linux>), + /* 428 */ SyscallDesc("vserver", unimplementedFunc), + /* 429 */ SyscallDesc("mbind", unimplementedFunc), + /* 430 */ SyscallDesc("get_mempolicy", unimplementedFunc), + /* 431 */ SyscallDesc("set_mempolicy", unimplementedFunc), + /* 432 */ SyscallDesc("mq_open", unimplementedFunc), + /* 433 */ SyscallDesc("mq_unlink", unimplementedFunc), + /* 434 */ SyscallDesc("mq_timedsend", unimplementedFunc), + /* 435 */ SyscallDesc("mq_timedreceive", unimplementedFunc), + /* 436 */ SyscallDesc("mq_notify", unimplementedFunc), + /* 437 */ SyscallDesc("mq_getsetattr", unimplementedFunc), + /* 438 */ SyscallDesc("waitid", unimplementedFunc), + /* 439 */ SyscallDesc("add_key", unimplementedFunc), + /* 440 */ SyscallDesc("request_key", unimplementedFunc), + /* 441 */ SyscallDesc("keyctl", unimplementedFunc) +}; + +MipsLinuxProcess::MipsLinuxProcess(const std::string &name, + ObjectFile *objFile, + int stdin_fd, + int stdout_fd, + int stderr_fd, + std::vector<std::string> &argv, + std::vector<std::string> &envp) + : LiveProcess(name, objFile, stdin_fd, stdout_fd, stderr_fd, argv, envp), + Num_Syscall_Descs(sizeof(syscallDescs) / sizeof(SyscallDesc)) +{ + init_regs->intRegFile[0] = 0; +} + + + +SyscallDesc* +MipsLinuxProcess::getDesc(int callnum) +{ + if (callnum < 0 || callnum > Num_Syscall_Descs) + return NULL; + return &syscallDescs[callnum]; +} diff --git a/arch/mips/linux_process.hh b/arch/mips/linux_process.hh new file mode 100644 index 000000000..5408a6c44 --- /dev/null +++ b/arch/mips/linux_process.hh @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2003-2004 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. + */ + +#ifndef __MIPS_LINUX_PROCESS_HH__ +#define __MIPS_LINUX_PROCESS_HH__ + +#include "sim/process.hh" + + +/// A process with emulated Mips/Linux syscalls. +class MipsLinuxProcess : public LiveProcess +{ + public: + /// Constructor. + MipsLinuxProcess(const std::string &name, + ObjectFile *objFile, + int stdin_fd, int stdout_fd, int stderr_fd, + std::vector<std::string> &argv, + std::vector<std::string> &envp); + + virtual SyscallDesc* getDesc(int callnum); + + /// The target system's hostname. + static const char *hostname; + + /// Array of syscall descriptors, indexed by call number. + static SyscallDesc syscallDescs[]; + + const int Num_Syscall_Descs; +}; + + +#endif // __MIPS_LINUX_PROCESS_HH__ diff --git a/arch/mips/process.cc b/arch/mips/process.cc new file mode 100644 index 000000000..6de44fe9f --- /dev/null +++ b/arch/mips/process.cc @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2003-2004 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. + */ + +#include "arch/mips/process.hh" + +namespace MipsISA +{ + +LiveProcess * +createProcess(const string &nm, ObjectFile * objFile, + int stdin_fd, int stdout_fd, int stderr_fd, + vector<string> &argv, vector<string> &envp) +{ + LiveProcess * process = NULL; + if (objFile->getArch() != ObjectFile::MIPS) + fatal("Object file does not match architecture."); + switch (objFile->getOpSys()) { + case ObjectFile::Linux: + process = new MipsLinuxProcess(nm, objFile, + stdin_fd, stdout_fd, stderr_fd, + argv, envp); + break; + + default: + fatal("Unknown/unsupported operating system."); + } + return process; +} + +} // namespace MipsISA + diff --git a/arch/mips/process.hh b/arch/mips/process.hh new file mode 100644 index 000000000..ab4323107 --- /dev/null +++ b/arch/mips/process.hh @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2003-2004 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. + */ + +#ifndef __MIPS_PROCESS_HH__ +#define __MIPS_PROCESS_HH__ + +#include "arch/mips/linux_process.hh" +#include "base/loader/object_file.hh" + +namespace MipsISA +{ + +LiveProcess * +createProcess(const string &nm, ObjectFile * objFile, + int stdin_fd, int stdout_fd, int stderr_fd, + vector<string> &argv, vector<string> &envp); + +} // namespace MipsISA + +#endif // __MIPS_PROCESS_HH__ diff --git a/arch/mips/stacktrace.hh b/arch/mips/stacktrace.hh new file mode 100644 index 000000000..1d8d97a79 --- /dev/null +++ b/arch/mips/stacktrace.hh @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2005 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. + */ + +#ifndef __ARCH_ALPHA_STACKTRACE_HH__ +#define __ARCH_ALPHA_STACKTRACE_HH__ + +#include "base/trace.hh" +#include "cpu/static_inst.hh" + +class ExecContext; +class StackTrace; + +class ProcessInfo +{ + private: + ExecContext *xc; + + int thread_info_size; + int task_struct_size; + int task_off; + int pid_off; + int name_off; + + public: + ProcessInfo(ExecContext *_xc); + + Addr task(Addr ksp) const; + int pid(Addr ksp) const; + std::string name(Addr ksp) const; +}; + +class StackTrace +{ + protected: + typedef TheISA::MachInst MachInst; + private: + ExecContext *xc; + std::vector<Addr> stack; + + private: + bool isEntry(Addr addr); + bool decodePrologue(Addr sp, Addr callpc, Addr func, int &size, Addr &ra); + bool decodeSave(MachInst inst, int ®, int &disp); + bool decodeStack(MachInst inst, int &disp); + + void trace(ExecContext *xc, bool is_call); + + public: + StackTrace(); + StackTrace(ExecContext *xc, StaticInstPtr inst); + ~StackTrace(); + + void clear() + { + xc = 0; + stack.clear(); + } + + bool valid() const { return xc != NULL; } + bool trace(ExecContext *xc, StaticInstPtr inst); + + public: + const std::vector<Addr> &getstack() const { return stack; } + + static const int user = 1; + static const int console = 2; + static const int unknown = 3; + +#if TRACING_ON + private: + void dump(); + + public: + void dprintf() { if (DTRACE(Stack)) dump(); } +#else + public: + void dprintf() {} +#endif +}; + +inline bool +StackTrace::trace(ExecContext *xc, StaticInstPtr inst) +{ + if (!inst->isCall() && !inst->isReturn()) + return false; + + if (valid()) + clear(); + + trace(xc, !inst->isReturn()); + return true; +} + +#endif // __ARCH_ALPHA_STACKTRACE_HH__ |