diff options
Diffstat (limited to 'src/arch')
69 files changed, 3468 insertions, 1494 deletions
diff --git a/src/arch/SConscript b/src/arch/SConscript index bc517341a..59cea6211 100644 --- a/src/arch/SConscript +++ b/src/arch/SConscript @@ -48,12 +48,12 @@ sources = [] # List of headers to generate isa_switch_hdrs = Split(''' arguments.hh - constants.hh faults.hh isa_traits.hh process.hh regfile.hh stacktrace.hh + syscallreturn.hh tlb.hh types.hh utility.hh @@ -140,8 +140,15 @@ def isa_desc_emitter(target, source, env): # Pieces are in place, so create the builder. python = sys.executable # use same Python binary used to run scons -isa_desc_builder = Builder(action=python + ' $SOURCES $TARGET.dir $CPU_MODELS', - emitter = isa_desc_emitter) + +# Also include the CheckerCPU as one of the models if it is being +# enabled via command line. +if env['USE_CHECKER']: + isa_desc_builder = Builder(action=python + ' $SOURCES $TARGET.dir $CPU_MODELS CheckerCPU', + emitter = isa_desc_emitter) +else: + isa_desc_builder = Builder(action=python + ' $SOURCES $TARGET.dir $CPU_MODELS', + emitter = isa_desc_emitter) env.Append(BUILDERS = { 'ISADesc' : isa_desc_builder }) diff --git a/src/arch/alpha/ev5.cc b/src/arch/alpha/ev5.cc index ae3b668ea..796ed07de 100644 --- a/src/arch/alpha/ev5.cc +++ b/src/arch/alpha/ev5.cc @@ -29,9 +29,10 @@ * Nathan Binkert */ -#include "arch/alpha/tlb.hh" +#include "arch/alpha/faults.hh" #include "arch/alpha/isa_traits.hh" #include "arch/alpha/osfpal.hh" +#include "arch/alpha/tlb.hh" #include "base/kgdb.h" #include "base/remote_gdb.hh" #include "base/stats/events.hh" diff --git a/src/arch/alpha/faults.hh b/src/arch/alpha/faults.hh index 11a568174..3ef4d5521 100644 --- a/src/arch/alpha/faults.hh +++ b/src/arch/alpha/faults.hh @@ -32,7 +32,7 @@ #ifndef __ALPHA_FAULTS_HH__ #define __ALPHA_FAULTS_HH__ -#include "arch/alpha/isa_traits.hh" +#include "arch/alpha/pagetable.hh" #include "sim/faults.hh" // The design of the "name" and "vect" functions is in sim/faults.hh diff --git a/src/arch/alpha/freebsd/system.cc b/src/arch/alpha/freebsd/system.cc index 7cf68e0db..8d50e1612 100644 --- a/src/arch/alpha/freebsd/system.cc +++ b/src/arch/alpha/freebsd/system.cc @@ -97,6 +97,7 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(FreebsdAlphaSystem) Param<Tick> boot_cpu_frequency; SimObjectParam<PhysicalMemory *> physmem; + SimpleEnumParam<System::MemoryMode> mem_mode; Param<string> kernel; Param<string> console; @@ -115,6 +116,8 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(FreebsdAlphaSystem) INIT_PARAM(boot_cpu_frequency, "Frequency of the boot CPU"), INIT_PARAM(physmem, "phsyical memory"), + INIT_ENUM_PARAM(mem_mode, "Memory Mode, (1=atomic, 2=timing)", + System::MemoryModeStrings), INIT_PARAM(kernel, "file that contains the kernel code"), INIT_PARAM(console, "file that contains the console code"), INIT_PARAM(pal, "file that contains palcode"), @@ -133,6 +136,7 @@ CREATE_SIM_OBJECT(FreebsdAlphaSystem) p->name = getInstanceName(); p->boot_cpu_frequency = boot_cpu_frequency; p->physmem = physmem; + p->mem_mode = mem_mode; p->kernel_path = kernel; p->console_path = console; p->palcode = pal; diff --git a/src/arch/alpha/isa/mem.isa b/src/arch/alpha/isa/mem.isa index 08a0a2343..a5dda7fc6 100644 --- a/src/arch/alpha/isa/mem.isa +++ b/src/arch/alpha/isa/mem.isa @@ -668,7 +668,6 @@ def LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, + completeAccTemplate.subst(completeacc_iop)) }}; - def format LoadOrNop(memacc_code, ea_code = {{ EA = Rb + disp; }}, mem_flags = [], inst_flags = []) {{ (header_output, decoder_output, decode_block, exec_output) = \ diff --git a/src/arch/alpha/isa_traits.hh b/src/arch/alpha/isa_traits.hh index 663b144ab..72e38ae3e 100644 --- a/src/arch/alpha/isa_traits.hh +++ b/src/arch/alpha/isa_traits.hh @@ -35,81 +35,252 @@ namespace LittleEndianGuest {} #include "arch/alpha/types.hh" -#include "arch/alpha/constants.hh" -#include "arch/alpha/regfile.hh" #include "config/full_system.hh" #include "sim/host.hh" class StaticInstPtr; -#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; -}; +namespace AlphaISA +{ + + using namespace LittleEndianGuest; + + // 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 = 40, + Ctrl_Base_DepTag = 72, + Fpcr_DepTag = 72, // floating point control register + Uniq_DepTag = 73, + Lock_Flag_DepTag = 74, + Lock_Addr_DepTag = 75, + IPR_Base_DepTag = 76 + }; + + StaticInstPtr decodeInst(ExtMachInst); + + const Addr PageShift = 13; + const Addr PageBytes = ULL(1) << PageShift; + const Addr PageMask = ~(PageBytes - 1); + const Addr PageOffset = PageBytes - 1; -#endif #if FULL_SYSTEM -#include "arch/alpha/isa_fullsys_traits.hh" -#endif + //////////////////////////////////////////////////////////////////////// + // + // Translation stuff + // -namespace AlphaISA -{ + const Addr PteShift = 3; + const Addr NPtePageShift = PageShift - PteShift; + const Addr NPtePage = ULL(1) << NPtePageShift; + const Addr PteMask = NPtePage - 1; -using namespace LittleEndianGuest; + // User Virtual + const Addr USegBase = ULL(0x0); + const Addr USegEnd = ULL(0x000003ffffffffff); -// redirected register map, really only used for the full system case. -extern const int reg_redir[NumIntRegs]; + // Kernel Direct Mapped + const Addr K0SegBase = ULL(0xfffffc0000000000); + const Addr K0SegEnd = ULL(0xfffffdffffffffff); - StaticInstPtr decodeInst(ExtMachInst); + // Kernel Virtual + const Addr K1SegBase = ULL(0xfffffe0000000000); + const Addr K1SegEnd = ULL(0xffffffffffffffff); + + // For loading... XXX This maybe could be USegEnd?? --ali + const Addr LoadAddrMask = ULL(0xffffffffff); + + //////////////////////////////////////////////////////////////////////// + // + // Interrupt levels + // + enum InterruptLevels + { + INTLEVEL_SOFTWARE_MIN = 4, + INTLEVEL_SOFTWARE_MAX = 19, + + INTLEVEL_EXTERNAL_MIN = 20, + INTLEVEL_EXTERNAL_MAX = 34, + + INTLEVEL_IRQ0 = 20, + INTLEVEL_IRQ1 = 21, + INTINDEX_ETHERNET = 0, + INTINDEX_SCSI = 1, + INTLEVEL_IRQ2 = 22, + INTLEVEL_IRQ3 = 23, + + INTLEVEL_SERIAL = 33, + + NumInterruptLevels = INTLEVEL_EXTERNAL_MAX + }; + + + // EV5 modes + enum mode_type + { + mode_kernel = 0, // kernel + mode_executive = 1, // executive (unused by unix) + mode_supervisor = 2, // supervisor (unused by unix) + mode_user = 3, // user mode + mode_number // number of modes + }; + +#endif -#if !FULL_SYSTEM - static inline void setSyscallReturn(SyscallReturn return_value, RegFile *regs) +#if FULL_SYSTEM + //////////////////////////////////////////////////////////////////////// + // + // Internal Processor Reigsters + // + enum md_ipr_names { - // check for error condition. Alpha syscall convention is to - // indicate success/failure in reg a3 (r19) and put the - // return value itself in the standard return value reg (v0). - if (return_value.successful()) { - // no error - regs->setIntReg(SyscallSuccessReg, 0); - regs->setIntReg(ReturnValueReg, return_value.value()); - } else { - // got an error, return details - regs->setIntReg(SyscallSuccessReg, (IntReg)-1); - regs->setIntReg(ReturnValueReg, -return_value.value()); - } - } + IPR_ISR = 0x100, // interrupt summary register + IPR_ITB_TAG = 0x101, // ITLB tag register + IPR_ITB_PTE = 0x102, // ITLB page table entry register + IPR_ITB_ASN = 0x103, // ITLB address space register + IPR_ITB_PTE_TEMP = 0x104, // ITLB page table entry temp register + IPR_ITB_IA = 0x105, // ITLB invalidate all register + IPR_ITB_IAP = 0x106, // ITLB invalidate all process register + IPR_ITB_IS = 0x107, // ITLB invalidate select register + IPR_SIRR = 0x108, // software interrupt request register + IPR_ASTRR = 0x109, // asynchronous system trap request register + IPR_ASTER = 0x10a, // asynchronous system trap enable register + IPR_EXC_ADDR = 0x10b, // exception address register + IPR_EXC_SUM = 0x10c, // exception summary register + IPR_EXC_MASK = 0x10d, // exception mask register + IPR_PAL_BASE = 0x10e, // PAL base address register + IPR_ICM = 0x10f, // instruction current mode + IPR_IPLR = 0x110, // interrupt priority level register + IPR_INTID = 0x111, // interrupt ID register + IPR_IFAULT_VA_FORM = 0x112, // formatted faulting virtual addr register + IPR_IVPTBR = 0x113, // virtual page table base register + IPR_HWINT_CLR = 0x115, // H/W interrupt clear register + IPR_SL_XMIT = 0x116, // serial line transmit register + IPR_SL_RCV = 0x117, // serial line receive register + IPR_ICSR = 0x118, // instruction control and status register + IPR_IC_FLUSH = 0x119, // instruction cache flush control + IPR_IC_PERR_STAT = 0x11a, // inst cache parity error status register + IPR_PMCTR = 0x11c, // performance counter register + + // PAL temporary registers... + // register meanings gleaned from osfpal.s source code + IPR_PALtemp0 = 0x140, // local scratch + IPR_PALtemp1 = 0x141, // local scratch + IPR_PALtemp2 = 0x142, // entUna + IPR_PALtemp3 = 0x143, // CPU specific impure area pointer + IPR_PALtemp4 = 0x144, // memory management temp + IPR_PALtemp5 = 0x145, // memory management temp + IPR_PALtemp6 = 0x146, // memory management temp + IPR_PALtemp7 = 0x147, // entIF + IPR_PALtemp8 = 0x148, // intmask + IPR_PALtemp9 = 0x149, // entSys + IPR_PALtemp10 = 0x14a, // ?? + IPR_PALtemp11 = 0x14b, // entInt + IPR_PALtemp12 = 0x14c, // entArith + IPR_PALtemp13 = 0x14d, // reserved for platform specific PAL + IPR_PALtemp14 = 0x14e, // reserved for platform specific PAL + IPR_PALtemp15 = 0x14f, // reserved for platform specific PAL + IPR_PALtemp16 = 0x150, // scratch / whami<7:0> / mces<4:0> + IPR_PALtemp17 = 0x151, // sysval + IPR_PALtemp18 = 0x152, // usp + IPR_PALtemp19 = 0x153, // ksp + IPR_PALtemp20 = 0x154, // PTBR + IPR_PALtemp21 = 0x155, // entMM + IPR_PALtemp22 = 0x156, // kgp + IPR_PALtemp23 = 0x157, // PCBB + + IPR_DTB_ASN = 0x200, // DTLB address space number register + IPR_DTB_CM = 0x201, // DTLB current mode register + IPR_DTB_TAG = 0x202, // DTLB tag register + IPR_DTB_PTE = 0x203, // DTLB page table entry register + IPR_DTB_PTE_TEMP = 0x204, // DTLB page table entry temporary register + + IPR_MM_STAT = 0x205, // data MMU fault status register + IPR_VA = 0x206, // fault virtual address register + IPR_VA_FORM = 0x207, // formatted virtual address register + IPR_MVPTBR = 0x208, // MTU virtual page table base register + IPR_DTB_IAP = 0x209, // DTLB invalidate all process register + IPR_DTB_IA = 0x20a, // DTLB invalidate all register + IPR_DTB_IS = 0x20b, // DTLB invalidate single register + IPR_ALT_MODE = 0x20c, // alternate mode register + IPR_CC = 0x20d, // cycle counter register + IPR_CC_CTL = 0x20e, // cycle counter control register + IPR_MCSR = 0x20f, // MTU control register + + IPR_DC_FLUSH = 0x210, + IPR_DC_PERR_STAT = 0x212, // Dcache parity error status register + IPR_DC_TEST_CTL = 0x213, // Dcache test tag control register + IPR_DC_TEST_TAG = 0x214, // Dcache test tag register + IPR_DC_TEST_TAG_TEMP = 0x215, // Dcache test tag temporary register + IPR_DC_MODE = 0x216, // Dcache mode register + IPR_MAF_MODE = 0x217, // miss address file mode register + + NumInternalProcRegs // number of IPR registers + }; +#else + const int NumInternalProcRegs = 0; #endif + + // Constants Related to the number of registers + + const int NumIntArchRegs = 32; + const int NumPALShadowRegs = 8; + const int NumFloatArchRegs = 32; + // @todo: Figure out what this number really should be. + const int NumMiscArchRegs = 32; + + const int NumIntRegs = NumIntArchRegs + NumPALShadowRegs; + const int NumFloatRegs = NumFloatArchRegs; + const int NumMiscRegs = NumMiscArchRegs; + + const int TotalNumRegs = NumIntRegs + NumFloatRegs + + NumMiscRegs + NumInternalProcRegs; + + const int TotalDataRegs = NumIntRegs + NumFloatRegs; + + // Static instruction parameters + const int MaxInstSrcRegs = 3; + const int MaxInstDestRegs = 2; + + // semantically meaningful register indices + const int ZeroReg = 31; // architecturally meaningful + // the rest of these depend on the ABI + const int StackPointerReg = 30; + const int GlobalPointerReg = 29; + const int ProcedureValueReg = 27; + const int ReturnAddressReg = 26; + const int ReturnValueReg = 0; + const int FramePointerReg = 15; + const int ArgumentReg0 = 16; + const int ArgumentReg1 = 17; + const int ArgumentReg2 = 18; + const int ArgumentReg3 = 19; + const int ArgumentReg4 = 20; + const int ArgumentReg5 = 21; + const int SyscallNumReg = ReturnValueReg; + const int SyscallPseudoReturnReg = ArgumentReg4; + const int SyscallSuccessReg = 19; + + const int LogVMPageSize = 13; // 8K bytes + const int VMPageSize = (1 << LogVMPageSize); + + const int BranchPredAddrShiftAmt = 2; // instructions are 4-byte aligned + + const int MachineBytes = 8; + const int WordBytes = 4; + const int HalfwordBytes = 2; + const int ByteBytes = 1; + + // return a no-op instruction... used for instruction fetch faults + // Alpha UNOP (ldq_u r31,0(r0)) + const ExtMachInst NoopMachInst = 0x2ffe0000; + + // redirected register map, really only used for the full system case. + extern const int reg_redir[NumIntRegs]; + }; #endif // __ARCH_ALPHA_ISA_TRAITS_HH__ diff --git a/src/arch/alpha/linux/linux.cc b/src/arch/alpha/linux/linux.cc index bc0d48e0d..e6908a572 100644 --- a/src/arch/alpha/linux/linux.cc +++ b/src/arch/alpha/linux/linux.cc @@ -30,6 +30,8 @@ #include "arch/alpha/linux/linux.hh" +#include <fcntl.h> + // open(2) flags translation table OpenFlagTransTable AlphaLinux::openFlagTable[] = { #ifdef _MSC_VER diff --git a/src/arch/alpha/linux/system.cc b/src/arch/alpha/linux/system.cc index 9fe63c390..ef4e18cb5 100644 --- a/src/arch/alpha/linux/system.cc +++ b/src/arch/alpha/linux/system.cc @@ -191,6 +191,7 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(LinuxAlphaSystem) Param<Tick> boot_cpu_frequency; SimObjectParam<PhysicalMemory *> physmem; + SimpleEnumParam<System::MemoryMode> mem_mode; Param<string> kernel; Param<string> console; @@ -209,6 +210,8 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(LinuxAlphaSystem) INIT_PARAM(boot_cpu_frequency, "Frequency of the boot CPU"), INIT_PARAM(physmem, "phsyical memory"), + INIT_ENUM_PARAM(mem_mode, "Memory Mode, (1=atomic, 2=timing)", + System::MemoryModeStrings), INIT_PARAM(kernel, "file that contains the kernel code"), INIT_PARAM(console, "file that contains the console code"), INIT_PARAM(pal, "file that contains palcode"), @@ -227,6 +230,7 @@ CREATE_SIM_OBJECT(LinuxAlphaSystem) p->name = getInstanceName(); p->boot_cpu_frequency = boot_cpu_frequency; p->physmem = physmem; + p->mem_mode = mem_mode; p->kernel_path = kernel; p->console_path = console; p->palcode = pal; diff --git a/src/arch/alpha/pagetable.hh b/src/arch/alpha/pagetable.hh new file mode 100644 index 000000000..3108c0a3e --- /dev/null +++ b/src/arch/alpha/pagetable.hh @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2002-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. + * + * Authors: Nathan Binkert + * Steve Reinhardt + */ + +#ifndef __ARCH_ALPHA_PAGETABLE_H__ +#define __ARCH_ALPHA_PAGETABLE_H__ + +#include "arch/alpha/isa_traits.hh" +#include "arch/alpha/utility.hh" +#include "config/full_system.hh" + +namespace AlphaISA { + +#if FULL_SYSTEM + struct VAddr + { + static const int ImplBits = 43; + static const Addr ImplMask = (ULL(1) << ImplBits) - 1; + static const Addr UnImplMask = ~ImplMask; + + VAddr(Addr a) : addr(a) {} + Addr addr; + operator Addr() const { return addr; } + const VAddr &operator=(Addr a) { addr = a; return *this; } + + Addr vpn() const { return (addr & ImplMask) >> PageShift; } + Addr page() const { return addr & PageMask; } + Addr offset() const { return addr & PageOffset; } + + Addr level3() const + { return AlphaISA::PteAddr(addr >> PageShift); } + Addr level2() const + { return AlphaISA::PteAddr(addr >> NPtePageShift + PageShift); } + Addr level1() const + { return AlphaISA::PteAddr(addr >> 2 * NPtePageShift + PageShift); } + }; + + struct PageTableEntry + { + PageTableEntry(uint64_t e) : entry(e) {} + uint64_t entry; + operator uint64_t() const { return entry; } + const PageTableEntry &operator=(uint64_t e) { entry = e; return *this; } + const PageTableEntry &operator=(const PageTableEntry &e) + { entry = e.entry; return *this; } + + Addr _pfn() const { return (entry >> 32) & 0xffffffff; } + Addr _sw() const { return (entry >> 16) & 0xffff; } + int _rsv0() const { return (entry >> 14) & 0x3; } + bool _uwe() const { return (entry >> 13) & 0x1; } + bool _kwe() const { return (entry >> 12) & 0x1; } + int _rsv1() const { return (entry >> 10) & 0x3; } + bool _ure() const { return (entry >> 9) & 0x1; } + bool _kre() const { return (entry >> 8) & 0x1; } + bool _nomb() const { return (entry >> 7) & 0x1; } + int _gh() const { return (entry >> 5) & 0x3; } + bool _asm() const { return (entry >> 4) & 0x1; } + bool _foe() const { return (entry >> 3) & 0x1; } + bool _fow() const { return (entry >> 2) & 0x1; } + bool _for() const { return (entry >> 1) & 0x1; } + bool valid() const { return (entry >> 0) & 0x1; } + + Addr paddr() const { return _pfn() << PageShift; } + }; + + // ITB/DTB page table entry + struct PTE + { + Addr tag; // virtual page number tag + Addr ppn; // physical page number + uint8_t xre; // read permissions - VMEM_PERM_* mask + uint8_t xwe; // write permissions - VMEM_PERM_* mask + uint8_t asn; // address space number + bool asma; // address space match + bool fonr; // fault on read + bool fonw; // fault on write + bool valid; // valid page table entry + + void serialize(std::ostream &os); + void unserialize(Checkpoint *cp, const std::string §ion); + }; +#endif +}; +#endif // __ARCH_ALPHA_PAGETABLE_H__ + diff --git a/src/arch/alpha/process.cc b/src/arch/alpha/process.cc index 970292cd8..32fb97229 100644 --- a/src/arch/alpha/process.cc +++ b/src/arch/alpha/process.cc @@ -29,7 +29,7 @@ * Ali Saidi */ -#include "arch/alpha/constants.hh" +#include "arch/alpha/isa_traits.hh" #include "arch/alpha/process.hh" #include "base/loader/object_file.hh" #include "base/misc.hh" diff --git a/src/arch/alpha/regfile.hh b/src/arch/alpha/regfile.hh index 9ecad6f42..43b48a0ab 100644 --- a/src/arch/alpha/regfile.hh +++ b/src/arch/alpha/regfile.hh @@ -32,14 +32,34 @@ #define __ARCH_ALPHA_REGFILE_HH__ #include "arch/alpha/types.hh" -#include "arch/alpha/constants.hh" +#include "arch/alpha/isa_traits.hh" #include "sim/faults.hh" +#include <string> + +//XXX These should be implemented by someone who knows the alpha stuff better + class Checkpoint; class ThreadContext; namespace AlphaISA { + + static inline std::string getIntRegName(RegIndex) + { + return ""; + } + + static inline std::string getFloatRegName(RegIndex) + { + return ""; + } + + static inline std::string getMiscRegName(RegIndex) + { + return ""; + } + class IntRegFile { protected: @@ -268,14 +288,7 @@ namespace AlphaISA void serialize(std::ostream &os); void unserialize(Checkpoint *cp, const std::string §ion); - enum ContextParam - { - CONTEXT_PALMODE - }; - - typedef bool ContextVal; - - void changeContext(ContextParam param, ContextVal val) + void changeContext(RegContextParam param, RegContextVal val) { //This would be an alternative place to call/implement //the swapPALShadow function diff --git a/src/arch/alpha/syscallreturn.hh b/src/arch/alpha/syscallreturn.hh new file mode 100644 index 000000000..803c3b7da --- /dev/null +++ b/src/arch/alpha/syscallreturn.hh @@ -0,0 +1,87 @@ +/* + * 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. + * + * Authors: Steve Reinhardt + * Gabe Black + */ + +#ifndef __ARCH_ALPHA_SYSCALLRETURN_HH__ +#define __ARCH_ALPHA_SYSCALLRETURN_HH__ + +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; +}; + +namespace AlphaISA +{ + static inline void setSyscallReturn(SyscallReturn return_value, RegFile *regs) + { + // check for error condition. Alpha syscall convention is to + // indicate success/failure in reg a3 (r19) and put the + // return value itself in the standard return value reg (v0). + if (return_value.successful()) { + // no error + regs->setIntReg(SyscallSuccessReg, 0); + regs->setIntReg(ReturnValueReg, return_value.value()); + } else { + // got an error, return details + regs->setIntReg(SyscallSuccessReg, (IntReg)-1); + regs->setIntReg(ReturnValueReg, -return_value.value()); + } + } +} + +#endif diff --git a/src/arch/alpha/system.cc b/src/arch/alpha/system.cc index dce7365aa..a7e615531 100644 --- a/src/arch/alpha/system.cc +++ b/src/arch/alpha/system.cc @@ -221,6 +221,7 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(AlphaSystem) Param<Tick> boot_cpu_frequency; SimObjectParam<PhysicalMemory *> physmem; + SimpleEnumParam<System::MemoryMode> mem_mode; Param<std::string> kernel; Param<std::string> console; @@ -239,6 +240,8 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(AlphaSystem) INIT_PARAM(boot_cpu_frequency, "Frequency of the boot CPU"), INIT_PARAM(physmem, "phsyical memory"), + INIT_ENUM_PARAM(mem_mode, "Memory Mode, (1=atomic, 2=timing)", + System::MemoryModeStrings), INIT_PARAM(kernel, "file that contains the kernel code"), INIT_PARAM(console, "file that contains the console code"), INIT_PARAM(pal, "file that contains palcode"), @@ -257,6 +260,7 @@ CREATE_SIM_OBJECT(AlphaSystem) p->name = getInstanceName(); p->boot_cpu_frequency = boot_cpu_frequency; p->physmem = physmem; + p->mem_mode = mem_mode; p->kernel_path = kernel; p->console_path = console; p->palcode = pal; diff --git a/src/arch/alpha/tlb.cc b/src/arch/alpha/tlb.cc index c6684274b..bab44c434 100644 --- a/src/arch/alpha/tlb.cc +++ b/src/arch/alpha/tlb.cc @@ -33,7 +33,9 @@ #include <string> #include <vector> +#include "arch/alpha/pagetable.hh" #include "arch/alpha/tlb.hh" +#include "arch/alpha/faults.hh" #include "base/inifile.hh" #include "base/str.hh" #include "base/trace.hh" diff --git a/src/arch/alpha/tlb.hh b/src/arch/alpha/tlb.hh index 07d01fa5c..955460649 100644 --- a/src/arch/alpha/tlb.hh +++ b/src/arch/alpha/tlb.hh @@ -36,9 +36,11 @@ #include "arch/alpha/ev5.hh" #include "arch/alpha/isa_traits.hh" -#include "arch/alpha/faults.hh" +#include "arch/alpha/utility.hh" +#include "arch/alpha/vtophys.hh" #include "base/statistics.hh" #include "mem/request.hh" +#include "sim/faults.hh" #include "sim/sim_object.hh" class ThreadContext; diff --git a/src/arch/alpha/tru64/system.cc b/src/arch/alpha/tru64/system.cc index 6c0edc1ee..3ef1e4d3c 100644 --- a/src/arch/alpha/tru64/system.cc +++ b/src/arch/alpha/tru64/system.cc @@ -95,6 +95,7 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(Tru64AlphaSystem) Param<Tick> boot_cpu_frequency; SimObjectParam<PhysicalMemory *> physmem; + SimpleEnumParam<System::MemoryMode> mem_mode; Param<string> kernel; Param<string> console; @@ -113,6 +114,8 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(Tru64AlphaSystem) INIT_PARAM(boot_cpu_frequency, "frequency of the boot cpu"), INIT_PARAM(physmem, "phsyical memory"), + INIT_ENUM_PARAM(mem_mode, "Memory Mode, (1=atomic, 2=timing)", + System::MemoryModeStrings), INIT_PARAM(kernel, "file that contains the kernel code"), INIT_PARAM(console, "file that contains the console code"), INIT_PARAM(pal, "file that contains palcode"), @@ -131,6 +134,7 @@ CREATE_SIM_OBJECT(Tru64AlphaSystem) p->name = getInstanceName(); p->boot_cpu_frequency = boot_cpu_frequency; p->physmem = physmem; + p->mem_mode = mem_mode; p->kernel_path = kernel; p->console_path = console; p->palcode = pal; diff --git a/src/arch/alpha/types.hh b/src/arch/alpha/types.hh index 5859052e9..ae42552d8 100644 --- a/src/arch/alpha/types.hh +++ b/src/arch/alpha/types.hh @@ -32,7 +32,7 @@ #ifndef __ARCH_ALPHA_TYPES_HH__ #define __ARCH_ALPHA_TYPES_HH__ -#include "sim/host.hh" +#include <inttypes.h> namespace AlphaISA { @@ -56,6 +56,13 @@ namespace AlphaISA MiscReg ctrlreg; } AnyReg; + enum RegContextParam + { + CONTEXT_PALMODE + }; + + typedef bool RegContextVal; + enum annotes { ANNOTE_NONE = 0, // An impossible number for instruction annotations diff --git a/src/arch/alpha/utility.hh b/src/arch/alpha/utility.hh index ec136091c..d3ccc0444 100644 --- a/src/arch/alpha/utility.hh +++ b/src/arch/alpha/utility.hh @@ -34,7 +34,7 @@ #include "config/full_system.hh" #include "arch/alpha/types.hh" -#include "arch/alpha/constants.hh" +#include "arch/alpha/isa_traits.hh" #include "arch/alpha/regfile.hh" #include "base/misc.hh" diff --git a/src/arch/alpha/vtophys.hh b/src/arch/alpha/vtophys.hh index 472c694ff..32b999c37 100644 --- a/src/arch/alpha/vtophys.hh +++ b/src/arch/alpha/vtophys.hh @@ -33,22 +33,24 @@ #define __ARCH_ALPHA_VTOPHYS_H__ #include "arch/alpha/isa_traits.hh" +#include "arch/alpha/pagetable.hh" +#include "arch/alpha/utility.hh" class ThreadContext; class FunctionalPort; namespace AlphaISA { -PageTableEntry -kernel_pte_lookup(FunctionalPort *mem, Addr ptbr, AlphaISA::VAddr vaddr); + PageTableEntry + kernel_pte_lookup(FunctionalPort *mem, Addr ptbr, AlphaISA::VAddr vaddr); -Addr vtophys(Addr vaddr); -Addr vtophys(ThreadContext *tc, Addr vaddr); + Addr vtophys(Addr vaddr); + Addr vtophys(ThreadContext *tc, Addr vaddr); -void CopyOut(ThreadContext *tc, void *dst, Addr src, size_t len); -void CopyIn(ThreadContext *tc, Addr dst, void *src, size_t len); -void CopyStringOut(ThreadContext *tc, char *dst, Addr vaddr, size_t maxlen); -void CopyStringIn(ThreadContext *tc, char *src, Addr vaddr); + void CopyOut(ThreadContext *tc, void *dst, Addr src, size_t len); + void CopyIn(ThreadContext *tc, Addr dst, void *src, size_t len); + void CopyStringOut(ThreadContext *tc, char *dst, Addr vaddr, size_t maxlen); + void CopyStringIn(ThreadContext *tc, char *src, Addr vaddr); }; #endif // __ARCH_ALPHA_VTOPHYS_H__ diff --git a/src/arch/mips/faults.cc b/src/arch/mips/faults.cc index cfeb045eb..2a8ab1df5 100644 --- a/src/arch/mips/faults.cc +++ b/src/arch/mips/faults.cc @@ -25,13 +25,15 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * Authors: Korey Sewell + * Authors: Gabe Black + * Korey Sewell */ #include "arch/mips/faults.hh" #include "cpu/thread_context.hh" #include "cpu/base.hh" #include "base/trace.hh" + #if !FULL_SYSTEM #include "sim/process.hh" #include "mem/page_table.hh" @@ -110,35 +112,6 @@ FaultName IntegerOverflowFault::_name = "intover"; FaultVect IntegerOverflowFault::_vect = 0x0501; FaultStat IntegerOverflowFault::_count; -#if FULL_SYSTEM - -void MipsFault::invoke(ThreadContext * tc) -{ - FaultBase::invoke(tc); - countStat()++; - - // exception restart address - if (setRestartAddress() || !tc->inPalMode()) - tc->setMiscReg(MipsISA::IPR_EXC_ADDR, tc->readPC()); - - if (skipFaultingInstruction()) { - // traps... skip faulting instruction. - tc->setMiscReg(MipsISA::IPR_EXC_ADDR, - tc->readMiscReg(MipsISA::IPR_EXC_ADDR) + 4); - } - - tc->setPC(tc->readMiscReg(MipsISA::IPR_PAL_BASE) + vect()); - tc->setNextPC(tc->readPC() + sizeof(MachInst)); -} - -void ArithmeticFault::invoke(ThreadContext * tc) -{ - FaultBase::invoke(tc); - panic("Arithmetic traps are unimplemented!"); -} - -#else //!FULL_SYSTEM - void PageTableFault::invoke(ThreadContext *tc) { Process *p = tc->getProcessPtr(); @@ -159,6 +132,5 @@ void PageTableFault::invoke(ThreadContext *tc) } } -#endif } // namespace MipsISA diff --git a/src/arch/mips/faults.hh b/src/arch/mips/faults.hh index 95c61cfbc..9d2c5df32 100644 --- a/src/arch/mips/faults.hh +++ b/src/arch/mips/faults.hh @@ -25,7 +25,8 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * Authors: Korey Sewell + * Authors: Gabe Black + * Korey Sewell */ #ifndef __MIPS_FAULTS_HH__ diff --git a/src/arch/mips/isa/base.isa b/src/arch/mips/isa/base.isa index f07b06e03..7c042f16f 100644 --- a/src/arch/mips/isa/base.isa +++ b/src/arch/mips/isa/base.isa @@ -79,21 +79,27 @@ output decoder {{ ccprintf(ss, "%-10s ", mnemonic); - if(_numDestRegs > 0){ - printReg(ss, _destRegIdx[0]); + // Need to find standard way to not print + // this info. Maybe add bool variable to + // class? + if (mnemonic != "syscall") { + if(_numDestRegs > 0){ + printReg(ss, _destRegIdx[0]); + } + + if(_numSrcRegs > 0) { + ss << ", "; + printReg(ss, _srcRegIdx[0]); + } + + if(_numSrcRegs > 1) { + ss << ", "; + printReg(ss, _srcRegIdx[1]); + } } - if(_numSrcRegs > 0) { - ss << ", "; - printReg(ss, _srcRegIdx[0]); - } - - if(_numSrcRegs > 1) { - ss << ", "; - printReg(ss, _srcRegIdx[1]); - } - - + // Should we define a separate inst. class + // just for two insts? if(mnemonic == "sll" || mnemonic == "sra"){ ccprintf(ss,", %d",SA); } diff --git a/src/arch/mips/isa/decoder.isa b/src/arch/mips/isa/decoder.isa index 9ac982e34..d65e3eb94 100644 --- a/src/arch/mips/isa/decoder.isa +++ b/src/arch/mips/isa/decoder.isa @@ -133,7 +133,8 @@ decode OPCODE_HI default Unknown::unknown() { format BasicOp { 0x2: movz({{ Rd = (Rt == 0) ? Rs : Rd; }}); 0x3: movn({{ Rd = (Rt != 0) ? Rs : Rd; }}); - 0x4: syscall({{ xc->syscall(R2); }}, IsNonSpeculative); + 0x4: syscall({{ xc->syscall(R2); }}, + IsSerializeAfter, IsNonSpeculative); 0x7: sync({{ ; }}, IsMemBarrier); } @@ -1089,7 +1090,7 @@ decode OPCODE_HI default Unknown::unknown() { 0x0: StoreCond::sc({{ Mem.uw = Rt.uw;}}, {{ uint64_t tmp = write_result; Rt.uw = (tmp == 0 || tmp == 1) ? tmp : Rt.uw; - }}, mem_flags=LOCKED); + }}, mem_flags=LOCKED, inst_flags = IsStoreConditional); format StoreMemory { 0x1: swc1({{ Mem.uw = Ft.uw; }}); diff --git a/src/arch/mips/isa/formats/basic.isa b/src/arch/mips/isa/formats/basic.isa index 29dafd541..29a445b2c 100644 --- a/src/arch/mips/isa/formats/basic.isa +++ b/src/arch/mips/isa/formats/basic.isa @@ -26,7 +26,8 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // -// Authors: Korey Sewell +// Authors: Steve Reinhardt +// Korey Sewell // Declarations for execute() methods. def template BasicExecDeclare {{ @@ -85,7 +86,7 @@ def template BasicDecodeWithMnemonic {{ return new %(class_name)s("%(mnemonic)s", machInst); }}; -// The most basic instruction format... used only for a few misc. insts +// The most basic instruction format... def format BasicOp(code, *flags) {{ iop = InstObjParams(name, Name, 'MipsStaticInst', CodeBlock(code), flags) header_output = BasicDeclare.subst(iop) diff --git a/src/arch/mips/isa/formats/branch.isa b/src/arch/mips/isa/formats/branch.isa index 5230ce9cc..8c89fbfa2 100644 --- a/src/arch/mips/isa/formats/branch.isa +++ b/src/arch/mips/isa/formats/branch.isa @@ -36,7 +36,6 @@ output header {{ #include <iostream> - using namespace std; /** * Base class for instructions whose disassembly is not purely a @@ -235,10 +234,11 @@ def format Branch(code,*opt_flags) {{ else: inst_flags += (x, ) + #Take into account uncond. branch instruction if 'cond == 1' in code: - inst_flags += ('IsCondControl', ) + inst_flags += ('IsUnCondControl', ) else: - inst_flags += ('IsUncondControl', ) + inst_flags += ('IsCondControl', ) #Condition code code = 'bool cond;\n' + code diff --git a/src/arch/mips/isa/formats/int.isa b/src/arch/mips/isa/formats/int.isa index 56a4ec204..654dd8921 100644 --- a/src/arch/mips/isa/formats/int.isa +++ b/src/arch/mips/isa/formats/int.isa @@ -34,7 +34,6 @@ // output header {{ #include <iostream> - using namespace std; /** * Base class for integer operations. */ diff --git a/src/arch/mips/isa/formats/mem.isa b/src/arch/mips/isa/formats/mem.isa index f03f7becd..d6b0c2938 100644 --- a/src/arch/mips/isa/formats/mem.isa +++ b/src/arch/mips/isa/formats/mem.isa @@ -26,7 +26,7 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // -// Authors: Gabe Black +// Authors: Steve Reinhardt // Korey Sewell //////////////////////////////////////////////////////////////////// @@ -162,7 +162,7 @@ def template InitiateAccDeclare {{ def template CompleteAccDeclare {{ - Fault completeAcc(uint8_t *, %(CPU_exec_context)s *, Trace::InstRecord *) const; + Fault completeAcc(Packet *, %(CPU_exec_context)s *, Trace::InstRecord *) const; }}; @@ -288,7 +288,7 @@ def template LoadInitiateAcc {{ def template LoadCompleteAcc {{ - Fault %(class_name)s::completeAcc(uint8_t *data, + Fault %(class_name)s::completeAcc(Packet *pkt, %(CPU_exec_context)s *xc, Trace::InstRecord *traceData) const { @@ -297,7 +297,7 @@ def template LoadCompleteAcc {{ %(fp_enable_check)s; %(op_decl)s; - memcpy(&Mem, data, sizeof(Mem)); + Mem = pkt->get<typeof(Mem)>(); if (fault == NoFault) { %(memacc_code)s; @@ -390,7 +390,6 @@ def template StoreInitiateAcc {{ { Addr EA; Fault fault = NoFault; - uint64_t write_result = 0; %(fp_enable_check)s; %(op_decl)s; @@ -403,7 +402,7 @@ def template StoreInitiateAcc {{ if (fault == NoFault) { fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA, - memAccessFlags, &write_result); + memAccessFlags, NULL); if (traceData) { traceData->setData(Mem); } } @@ -413,17 +412,38 @@ def template StoreInitiateAcc {{ def template StoreCompleteAcc {{ - Fault %(class_name)s::completeAcc(uint8_t *data, + Fault %(class_name)s::completeAcc(Packet *pkt, + %(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + Fault fault = NoFault; + + %(fp_enable_check)s; + %(op_dest_decl)s; + + if (fault == NoFault) { + %(postacc_code)s; + } + + if (fault == NoFault) { + %(op_wb)s; + } + + return fault; + } +}}; + +def template StoreCondCompleteAcc {{ + Fault %(class_name)s::completeAcc(Packet *pkt, %(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)); + uint64_t write_result = pkt->req->getScResult(); if (fault == NoFault) { %(postacc_code)s; @@ -489,7 +509,7 @@ def template MiscInitiateAcc {{ def template MiscCompleteAcc {{ - Fault %(class_name)s::completeAcc(uint8_t *data, + Fault %(class_name)s::completeAcc(Packet *pkt, %(CPU_exec_context)s *xc, Trace::InstRecord *traceData) const { @@ -580,5 +600,5 @@ def format StoreCond(memacc_code, postacc_code, mem_flags = [], inst_flags = []) {{ (header_output, decoder_output, decode_block, exec_output) = \ LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, - postacc_code, exec_template_base = 'Store') + postacc_code, exec_template_base = 'StoreCond') }}; diff --git a/src/arch/mips/isa/formats/util.isa b/src/arch/mips/isa/formats/util.isa index 0cc375af3..73164bc0d 100644 --- a/src/arch/mips/isa/formats/util.isa +++ b/src/arch/mips/isa/formats/util.isa @@ -65,7 +65,7 @@ def LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, if (exec_template_base == 'Load'): initiateacc_cblk = CodeBlock(ea_code + memacc_code) completeacc_cblk = CodeBlock(memacc_code + postacc_code) - elif (exec_template_base == 'Store'): + elif (exec_template_base.startswith('Store')): initiateacc_cblk = CodeBlock(ea_code + memacc_code) completeacc_cblk = CodeBlock(postacc_code) else: @@ -83,7 +83,7 @@ def LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, 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'): + elif (exec_template_base.startswith('Store')): initiateacc_iop.ea_code = ea_cblk.code initiateacc_iop.memacc_code = memacc_cblk.code completeacc_iop.postacc_code = postacc_cblk.code @@ -104,6 +104,13 @@ def LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, memacc_iop.constructor += s # select templates + + # define aliases... most StoreCond templates are the same as the + # corresponding Store templates (only CompleteAcc is different). + StoreCondMemAccExecute = StoreMemAccExecute + StoreCondExecute = StoreExecute + StoreCondInitiateAcc = StoreInitiateAcc + memAccExecTemplate = eval(exec_template_base + 'MemAccExecute') fullExecTemplate = eval(exec_template_base + 'Execute') initiateAccTemplate = eval(exec_template_base + 'InitiateAcc') @@ -118,7 +125,6 @@ def LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, + initiateAccTemplate.subst(initiateacc_iop) + completeAccTemplate.subst(completeacc_iop)) }}; - output header {{ std::string inst2string(MachInst machInst); }}; @@ -127,7 +133,7 @@ output decoder {{ std::string inst2string(MachInst machInst) { - string str = ""; + std::string str = ""; uint32_t mask = 0x80000000; for(int i=0; i < 32; i++) { diff --git a/src/arch/mips/isa_traits.cc b/src/arch/mips/isa_traits.cc index 85acc4e8c..3a8cb46a5 100644 --- a/src/arch/mips/isa_traits.cc +++ b/src/arch/mips/isa_traits.cc @@ -30,15 +30,13 @@ */ #include "arch/mips/isa_traits.hh" -//#include "config/full_system.hh" -#include "cpu/static_inst.hh" +#include "arch/mips/regfile/regfile.hh" #include "sim/serialize.hh" #include "base/bitfield.hh" using namespace MipsISA; using namespace std; - void MipsISA::copyRegs(ThreadContext *src, ThreadContext *dest) { @@ -46,6 +44,12 @@ MipsISA::copyRegs(ThreadContext *src, ThreadContext *dest) } void +MipsISA::copyMiscRegs(ThreadContext *src, ThreadContext *dest) +{ + panic("Copy Misc. Regs Not Implemented Yet\n"); +} + +void MipsISA::MiscRegFile::copyMiscRegs(ThreadContext *tc) { panic("Copy Misc. Regs Not Implemented Yet\n"); @@ -67,9 +71,9 @@ void RegFile::serialize(std::ostream &os) { intRegFile.serialize(os); - //SERIALIZE_ARRAY(floatRegFile.q, NumFloatRegs); + //SERIALIZE_ARRAY(floatRegFile, NumFloatRegs); + //SERIALZE_ARRAY(miscRegFile); //SERIALIZE_SCALAR(miscRegs.fpcr); - //SERIALIZE_SCALAR(miscRegs.uniq); //SERIALIZE_SCALAR(miscRegs.lock_flag); //SERIALIZE_SCALAR(miscRegs.lock_addr); SERIALIZE_SCALAR(pc); @@ -82,9 +86,9 @@ void RegFile::unserialize(Checkpoint *cp, const std::string §ion) { intRegFile.unserialize(cp, section); - //UNSERIALIZE_ARRAY(floatRegFile.q, NumFloatRegs); + //UNSERIALIZE_ARRAY(floatRegFile); + //UNSERIALZE_ARRAY(miscRegFile); //UNSERIALIZE_SCALAR(miscRegs.fpcr); - //UNSERIALIZE_SCALAR(miscRegs.uniq); //UNSERIALIZE_SCALAR(miscRegs.lock_flag); //UNSERIALIZE_SCALAR(miscRegs.lock_addr); UNSERIALIZE_SCALAR(pc); diff --git a/src/arch/mips/isa_traits.hh b/src/arch/mips/isa_traits.hh index ff994bef9..fd484e315 100644 --- a/src/arch/mips/isa_traits.hh +++ b/src/arch/mips/isa_traits.hh @@ -32,149 +32,87 @@ #ifndef __ARCH_MIPS_ISA_TRAITS_HH__ #define __ARCH_MIPS_ISA_TRAITS_HH__ -#include "arch/mips/constants.hh" #include "arch/mips/types.hh" -#include "arch/mips/regfile/regfile.hh" -#include "arch/mips/faults.hh" -#include "arch/mips/utility.hh" -#include "base/misc.hh" -#include "config/full_system.hh" -#include "sim/byteswap.hh" #include "sim/host.hh" -#include "sim/faults.hh" - -#include <vector> - -class FastCPU; -class FullCPU; -class Checkpoint; -class ThreadContext; namespace LittleEndianGuest {}; #define TARGET_MIPS -class StaticInst; class StaticInstPtr; -class SyscallReturn { - public: - template <class T> - SyscallReturn(T v, bool s) - { - retval = (uint32_t)v; - success = s; - } - - template <class T> - SyscallReturn(T v) - { - success = (v >= 0); - retval = (uint32_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; -}; - namespace MipsISA { using namespace LittleEndianGuest; - static inline void setSyscallReturn(SyscallReturn return_value, RegFile *regs) - { - if (return_value.successful()) { - // no error - regs->setIntReg(SyscallSuccessReg, 0); - regs->setIntReg(ReturnValueReg1, return_value.value()); - } else { - // got an error, return details - regs->setIntReg(SyscallSuccessReg, (IntReg) -1); - regs->setIntReg(ReturnValueReg1, -return_value.value()); - } - } - StaticInstPtr decodeInst(ExtMachInst); - static inline ExtMachInst - makeExtMI(MachInst inst, const uint64_t &pc) { -#if FULL_SYSTEM - ExtMachInst ext_inst = inst; - if (pc && 0x1) - return ext_inst|=(static_cast<ExtMachInst>(pc & 0x1) << 32); - else - return ext_inst; -#else - return ExtMachInst(inst); -#endif - } - - /** - * Function to insure ISA semantics about 0 registers. - * @param tc The thread context. - */ - template <class TC> - void zeroRegisters(TC *tc); - - const Addr MaxAddr = (Addr)-1; - - void copyRegs(ThreadContext *src, ThreadContext *dest); - - // 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 - - 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; - } + const Addr PageShift = 13; + const Addr PageBytes = ULL(1) << PageShift; + const Addr PageMask = ~(PageBytes - 1); + const Addr PageOffset = PageBytes - 1; + + // return a no-op instruction... used for instruction fetch faults + const ExtMachInst NoopMachInst = 0x00000000; + + // Constants Related to the number of registers + const int NumIntArchRegs = 32; + const int NumIntSpecialRegs = 2; + const int NumFloatArchRegs = 32; + const int NumFloatSpecialRegs = 5; + const int NumControlRegs = 265; + const int NumInternalProcRegs = 0; + + const int NumIntRegs = NumIntArchRegs + NumIntSpecialRegs; //HI & LO Regs + const int NumFloatRegs = NumFloatArchRegs + NumFloatSpecialRegs;// + const int NumMiscRegs = NumControlRegs; + + const int TotalNumRegs = NumIntRegs + NumFloatRegs + + NumMiscRegs + 0/*NumInternalProcRegs*/; + + const int TotalDataRegs = NumIntRegs + NumFloatRegs; + + // Static instruction parameters + const int MaxInstSrcRegs = 3; + const int MaxInstDestRegs = 2; + + // semantically meaningful register indices + const int ZeroReg = 0; + const int AssemblerReg = 1; + const int ReturnValueReg = 2; + const int ReturnValueReg1 = 2; + const int ReturnValueReg2 = 3; + const int ArgumentReg0 = 4; + const int ArgumentReg1 = 5; + const int ArgumentReg2 = 6; + const int ArgumentReg3 = 7; + const int KernelReg0 = 26; + const int KernelReg1 = 27; + const int GlobalPointerReg = 28; + const int StackPointerReg = 29; + const int FramePointerReg = 30; + const int ReturnAddressReg = 31; + + const int SyscallNumReg = ReturnValueReg1; + const int SyscallPseudoReturnReg = ReturnValueReg1; + const int SyscallSuccessReg = ArgumentReg3; + + const int LogVMPageSize = 13; // 8K bytes + const int VMPageSize = (1 << LogVMPageSize); + + const int BranchPredAddrShiftAmt = 2; // instructions are 4-byte aligned + + const int MachineBytes = 4; + const int WordBytes = 4; + const int HalfwordBytes = 2; + const int ByteBytes = 1; + + // These help enumerate all the registers for dependence tracking. + const int FP_Base_DepTag = 34; + const int Ctrl_Base_DepTag = 257; + + const int ANNOTE_NONE = 0; + const uint32_t ITOUCH_ANNOTE = 0xffffffff; }; diff --git a/src/arch/mips/linux/linux.cc b/src/arch/mips/linux/linux.cc index 26e3dd479..90404af53 100644 --- a/src/arch/mips/linux/linux.cc +++ b/src/arch/mips/linux/linux.cc @@ -30,6 +30,8 @@ #include "arch/mips/linux/linux.hh" +#include <fcntl.h> + // open(2) flags translation table OpenFlagTransTable MipsLinux::openFlagTable[] = { #ifdef _MSC_VER diff --git a/src/arch/mips/process.hh b/src/arch/mips/process.hh index b0ef20399..400591599 100644 --- a/src/arch/mips/process.hh +++ b/src/arch/mips/process.hh @@ -50,6 +50,7 @@ class MipsLiveProcess : public LiveProcess std::vector<std::string> &envp); void startup(); + }; diff --git a/src/arch/mips/regfile.hh b/src/arch/mips/regfile.hh new file mode 100644 index 000000000..4b2f1ac35 --- /dev/null +++ b/src/arch/mips/regfile.hh @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2006 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Korey Sewell + */ + +#ifndef __ARCH_MIPS_REGFILE_HH__ +#define __ARCH_MIPS_REGFILE_HH__ + +#include "arch/mips/regfile/regfile.hh" + +#endif diff --git a/src/arch/mips/regfile/float_regfile.hh b/src/arch/mips/regfile/float_regfile.hh index 61efbb416..ce5f1fdde 100644 --- a/src/arch/mips/regfile/float_regfile.hh +++ b/src/arch/mips/regfile/float_regfile.hh @@ -26,24 +26,61 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef __ARCH_MIPS_FLOAT_REGFILE_HH__ -#define __ARCH_MIPS_FLOAT_REGFILE_HH__ +#ifndef __ARCH_MIPS_REGFILE_FLOAT_REGFILE_HH__ +#define __ARCH_MIPS_REGFILE_FLOAT_REGFILE_HH__ #include "arch/mips/types.hh" -#include "arch/mips/constants.hh" +#include "arch/mips/isa_traits.hh" #include "base/misc.hh" #include "base/bitfield.hh" -#include "config/full_system.hh" -#include "sim/byteswap.hh" #include "sim/faults.hh" -#include "sim/host.hh" + +#include <string> class Checkpoint; -class ExecContext; -class Regfile; namespace MipsISA { + static inline std::string getFloatRegName(RegIndex) + { + return ""; + } + + const uint32_t MIPS32_QNAN = 0x7fbfffff; + const uint64_t MIPS64_QNAN = ULL(0x7fbfffffffffffff); + + enum FPControlRegNums { + FIR = NumFloatArchRegs, + FCCR, + FEXR, + FENR, + FCSR + }; + + enum FCSRBits { + Inexact = 1, + Underflow, + Overflow, + DivideByZero, + Invalid, + Unimplemented + }; + + enum FCSRFields { + Flag_Field = 1, + Enable_Field = 6, + Cause_Field = 11 + }; + + const int SingleWidth = 32; + const int SingleBytes = SingleWidth / 4; + + const int DoubleWidth = 64; + const int DoubleBytes = DoubleWidth / 4; + + const int QuadWidth = 128; + const int QuadBytes = QuadWidth / 4; + class FloatRegFile { protected: @@ -102,7 +139,6 @@ namespace MipsISA Fault setReg(int floatReg, const FloatRegVal &val, int width) { - using namespace std; switch(width) { case SingleWidth: @@ -131,7 +167,6 @@ namespace MipsISA Fault setRegBits(int floatReg, const FloatRegBits &val, int width) { - using namespace std; switch(width) { diff --git a/src/arch/mips/regfile/int_regfile.hh b/src/arch/mips/regfile/int_regfile.hh index 5add1b7be..a45a17a85 100644 --- a/src/arch/mips/regfile/int_regfile.hh +++ b/src/arch/mips/regfile/int_regfile.hh @@ -28,20 +28,29 @@ * Authors: Korey Sewell */ -#ifndef __ARCH_MIPS_INT_REGFILE_HH__ -#define __ARCH_MIPS_INT_REGFILE_HH__ +#ifndef __ARCH_MIPS_REGFILE_INT_REGFILE_HH__ +#define __ARCH_MIPS_REGFILE_INT_REGFILE_HH__ #include "arch/mips/types.hh" -#include "arch/mips/constants.hh" +#include "arch/mips/isa_traits.hh" #include "base/misc.hh" #include "sim/faults.hh" class Checkpoint; class ThreadContext; -class Regfile; namespace MipsISA { + static inline std::string getIntRegName(RegIndex) + { + return ""; + } + + enum MiscIntRegNums { + HI = NumIntArchRegs, + LO + }; + class IntRegFile { protected: diff --git a/src/arch/mips/regfile/misc_regfile.hh b/src/arch/mips/regfile/misc_regfile.hh index 87961f97e..a4527a203 100644 --- a/src/arch/mips/regfile/misc_regfile.hh +++ b/src/arch/mips/regfile/misc_regfile.hh @@ -28,29 +28,191 @@ * Authors: Korey Sewell */ -#ifndef __ARCH_MIPS_MISC_REGFILE_HH__ -#define __ARCH_MIPS_MISC_REGFILE_HH__ +#ifndef __ARCH_MIPS_REGFILE_MISC_REGFILE_HH__ +#define __ARCH_MIPS_REGFILE_MISC_REGFILE_HH__ #include "arch/mips/types.hh" -#include "arch/mips/constants.hh" #include "sim/faults.hh" -class Checkpoint; class ThreadContext; -class Regfile; namespace MipsISA { + static inline std::string getMiscRegName(RegIndex) + { + return ""; + } + + //Coprocessor 0 Register Names + enum MiscRegTags { + //Reference MIPS32 Arch. for Programmers, Vol. III, Ch.8 + //(Register Number-Register Select) Summary of Register + //------------------------------------------------------ + Index = 0, //Bank 0: 0 - 3 + MVPControl, + MVPConf0, + MVPConf1, + + Random = 8, //Bank 1: 8 - 15 + VPEControl, + VPEConf0, + VPEConf1, + YQMask, + VPESchedule, + VPEScheFBack, + VPEOpt, + + EntryLo0 = 16, //Bank 2: 16 - 23 + TCStatus, + TCBind, + TCRestart, + TCHalt, + TCContext, + TCSchedule, + TCScheFBack, + + EntryLo1 = 24, // Bank 3: 24 + + Context = 32, // Bank 4: 32 - 33 + ContextConfig, + + //PageMask = 40, //Bank 5: 40 - 41 + PageGrain = 41, + + Wired = 48, //Bank 6: 48 - 55 + SRSConf0, + SRSConf1, + SRSConf2, + SRSConf3, + SRSConf4, + + HWRena = 56, //Bank 7: 56 + + BadVAddr = 63, //Bank 8: 63 + + Count = 64, //Bank 9: 64 + + EntryHi = 72, //Bank 10:72 - 79 + + Compare = 80, //Bank 10:80 - 87 + + Status = 88, //Bank 12:88 - 96 + IntCtl = 89, + SRSCtl = 90, + SRSMap = 91, + + Cause = 97, //97-104 + + EPC = 105, //105-112 + + PRId = 113, //113-120, + EBase = 114, + + 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 + }; + class MiscRegFile { protected: uint64_t fpcr; // floating point condition codes + // FPCR is not used in MIPS. Condition + // codes are kept as part of the FloatRegFile + bool lock_flag; // lock flag for LL/SC + // use LL reg. in the future + Addr lock_addr; // lock address for LL/SC + // use LLAddr reg. in the future MiscReg miscRegFile[NumMiscRegs]; public: + void clear() + { + fpcr = 0; + lock_flag = 0; + lock_addr = 0; + } + void copyMiscRegs(ThreadContext *tc); MiscReg readReg(int misc_reg) diff --git a/src/arch/mips/regfile/regfile.hh b/src/arch/mips/regfile/regfile.hh index a68120299..3a18c681b 100644 --- a/src/arch/mips/regfile/regfile.hh +++ b/src/arch/mips/regfile/regfile.hh @@ -28,11 +28,10 @@ * Authors: Korey Sewell */ -#ifndef __ARCH_MIPS_REGFILE_HH__ -#define __ARCH_MIPS_REGFILE_HH__ +#ifndef __ARCH_MIPS_REGFILE_REGFILE_HH__ +#define __ARCH_MIPS_REGFILE_REGFILE_HH__ #include "arch/mips/types.hh" -#include "arch/mips/constants.hh" #include "arch/mips/regfile/int_regfile.hh" #include "arch/mips/regfile/float_regfile.hh" #include "arch/mips/regfile/misc_regfile.hh" @@ -171,10 +170,7 @@ namespace MipsISA void serialize(std::ostream &os); void unserialize(Checkpoint *cp, const std::string §ion); - typedef int ContextParam; - typedef int ContextVal; - - void changeContext(ContextParam param, ContextVal val) + void changeContext(RegContextParam param, RegContextVal val) { } }; diff --git a/src/arch/mips/syscallreturn.hh b/src/arch/mips/syscallreturn.hh new file mode 100644 index 000000000..ef1093caf --- /dev/null +++ b/src/arch/mips/syscallreturn.hh @@ -0,0 +1,84 @@ +/* + * 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. + * + * Authors: Gabe Black + * Korey Sewell + */ + +#ifndef __ARCH_MIPS_SYSCALLRETURN_HH__ +#define __ARCH_MIPS_SYSCALLRETURN_HH__ + +class SyscallReturn { + public: + template <class T> + SyscallReturn(T v, bool s) + { + retval = (uint32_t)v; + success = s; + } + + template <class T> + SyscallReturn(T v) + { + success = (v >= 0); + retval = (uint32_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; +}; + +namespace MipsISA +{ + static inline void setSyscallReturn(SyscallReturn return_value, RegFile *regs) + { + if (return_value.successful()) { + // no error + regs->setIntReg(SyscallSuccessReg, 0); + regs->setIntReg(ReturnValueReg1, return_value.value()); + } else { + // got an error, return details + regs->setIntReg(SyscallSuccessReg, (IntReg) -1); + regs->setIntReg(ReturnValueReg1, -return_value.value()); + } + } +} + +#endif diff --git a/src/arch/mips/types.hh b/src/arch/mips/types.hh index 6330044d9..d4fa296fd 100644 --- a/src/arch/mips/types.hh +++ b/src/arch/mips/types.hh @@ -58,6 +58,9 @@ namespace MipsISA MiscReg ctrlreg; } AnyReg; + typedef int RegContextParam; + typedef int RegContextVal; + //used in FP convert & round function enum ConvertType{ SINGLE_TO_DOUBLE, diff --git a/src/arch/mips/utility.cc b/src/arch/mips/utility.cc index e7455fdbf..9ac4bb6d8 100644 --- a/src/arch/mips/utility.cc +++ b/src/arch/mips/utility.cc @@ -28,15 +28,12 @@ * Authors: Korey Sewell */ -#include "arch/mips/isa_traits.hh" +#include "arch/mips/regfile.hh" #include "arch/mips/utility.hh" -#include "config/full_system.hh" -#include "cpu/static_inst.hh" -#include "sim/serialize.hh" +#include "base/misc.hh" #include "base/bitfield.hh" using namespace MipsISA; -using namespace std; uint64_t MipsISA::fpConvert(ConvertType cvt_type, double fp_val) diff --git a/src/arch/mips/utility.hh b/src/arch/mips/utility.hh index c5c69ddcd..ae2fe1aea 100644 --- a/src/arch/mips/utility.hh +++ b/src/arch/mips/utility.hh @@ -33,10 +33,14 @@ #define __ARCH_MIPS_UTILITY_HH__ #include "arch/mips/types.hh" -#include "arch/mips/constants.hh" #include "base/misc.hh" +#include "config/full_system.hh" +//XXX This is needed for size_t. We should use something other than size_t +//#include "kern/linux/linux.hh" #include "sim/host.hh" +class ThreadContext; + namespace MipsISA { //Floating Point Utility Functions @@ -51,6 +55,48 @@ namespace MipsISA { bool isNan(void *val_ptr, int size); bool isQnan(void *val_ptr, int size); bool isSnan(void *val_ptr, int size); + + /** + * Function to insure ISA semantics about 0 registers. + * @param tc The thread context. + */ + template <class TC> + void zeroRegisters(TC *tc); + + void copyRegs(ThreadContext *src, ThreadContext *dest); + + // 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; + } + + static inline ExtMachInst + makeExtMI(MachInst inst, const uint64_t &pc) { +#if FULL_SYSTEM + ExtMachInst ext_inst = inst; + if (pc && 0x1) + return ext_inst|=(static_cast<ExtMachInst>(pc & 0x1) << 32); + else + return ext_inst; +#else + return ExtMachInst(inst); +#endif + } }; diff --git a/src/arch/sparc/SConscript b/src/arch/sparc/SConscript index e7a8278db..66f2b57e0 100644 --- a/src/arch/sparc/SConscript +++ b/src/arch/sparc/SConscript @@ -45,22 +45,25 @@ Import('env') # Base sources used by all configurations. base_sources = Split(''' faults.cc - isa_traits.cc + floatregfile.cc + intregfile.cc + miscregfile.cc + regfile.cc ''') # Full-system sources full_system_sources = Split(''' - vtophys.cc ua2005.cc + vtophys.cc ''') # Syscall emulation (non-full-system) sources syscall_emulation_sources = Split(''' linux/linux.cc linux/process.cc - solaris/solaris.cc - solaris/process.cc process.cc + solaris/process.cc + solaris/solaris.cc ''') sources = base_sources diff --git a/src/arch/sparc/floatregfile.cc b/src/arch/sparc/floatregfile.cc new file mode 100644 index 000000000..3cacbb278 --- /dev/null +++ b/src/arch/sparc/floatregfile.cc @@ -0,0 +1,174 @@ +/* + * 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. + * + * Authors: Gabe Black + * Ali Saidi + */ + +#include "arch/sparc/floatregfile.hh" +#include "base/trace.hh" +#include "sim/byteswap.hh" +#include "sim/serialize.hh" + +using namespace SparcISA; +using namespace std; + +class Checkpoint; + +string SparcISA::getFloatRegName(RegIndex index) +{ + static std::string floatRegName[NumFloatRegs] = + {"f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", + "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15", + "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23", + "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31", + "f32", "f33", "f34", "f35", "f36", "f37", "f38", "f39", + "f40", "f41", "f42", "f43", "f44", "f45", "f46", "f47", + "f48", "f49", "f50", "f51", "f52", "f53", "f54", "f55", + "f56", "f57", "f58", "f59", "f60", "f61", "f62", "f63"}; + return floatRegName[index]; +} + +void FloatRegFile::clear() +{ + bzero(regSpace, sizeof(regSpace)); +} + +FloatReg FloatRegFile::readReg(int floatReg, int width) +{ + //In each of these cases, we have to copy the value into a temporary + //variable. This is because we may otherwise try to access an + //unaligned portion of memory. + switch(width) + { + case SingleWidth: + float32_t result32; + memcpy(&result32, regSpace + 4 * floatReg, sizeof(result32)); + return htog(result32); + case DoubleWidth: + float64_t result64; + memcpy(&result64, regSpace + 4 * floatReg, sizeof(result64)); + return htog(result64); + case QuadWidth: + float128_t result128; + memcpy(&result128, regSpace + 4 * floatReg, sizeof(result128)); + return htog(result128); + default: + panic("Attempted to read a %d bit floating point register!", width); + } +} + +FloatRegBits FloatRegFile::readRegBits(int floatReg, int width) +{ + //In each of these cases, we have to copy the value into a temporary + //variable. This is because we may otherwise try to access an + //unaligned portion of memory. + switch(width) + { + case SingleWidth: + uint32_t result32; + memcpy(&result32, regSpace + 4 * floatReg, sizeof(result32)); + return htog(result32); + case DoubleWidth: + uint64_t result64; + memcpy(&result64, regSpace + 4 * floatReg, sizeof(result64)); + return htog(result64); + case QuadWidth: + uint64_t result128; + memcpy(&result128, regSpace + 4 * floatReg, sizeof(result128)); + return htog(result128); + default: + panic("Attempted to read a %d bit floating point register!", width); + } +} + +Fault FloatRegFile::setReg(int floatReg, const FloatReg &val, int width) +{ + //In each of these cases, we have to copy the value into a temporary + //variable. This is because we may otherwise try to access an + //unaligned portion of memory. + + uint32_t result32; + uint64_t result64; + DPRINTF(Sparc, "Setting floating point register %d\n", floatReg); + switch(width) + { + case SingleWidth: + result32 = gtoh((uint32_t)val); + memcpy(regSpace + 4 * floatReg, &result32, sizeof(result32)); + break; + case DoubleWidth: + result64 = gtoh((uint64_t)val); + memcpy(regSpace + 4 * floatReg, &result64, sizeof(result64)); + break; + case QuadWidth: + panic("Quad width FP not implemented."); + break; + default: + panic("Attempted to read a %d bit floating point register!", width); + } + return NoFault; +} + +Fault FloatRegFile::setRegBits(int floatReg, const FloatRegBits &val, int width) +{ + //In each of these cases, we have to copy the value into a temporary + //variable. This is because we may otherwise try to access an + //unaligned portion of memory. + uint32_t result32; + uint64_t result64; + switch(width) + { + case SingleWidth: + result32 = gtoh((uint32_t)val); + memcpy(regSpace + 4 * floatReg, &result32, sizeof(result32)); + break; + case DoubleWidth: + result64 = gtoh((uint64_t)val); + memcpy(regSpace + 4 * floatReg, &result64, sizeof(result64)); + break; + case QuadWidth: + panic("Quad width FP not implemented."); + break; + default: + panic("Attempted to read a %d bit floating point register!", width); + } + return NoFault; +} + +void FloatRegFile::serialize(std::ostream &os) +{ + SERIALIZE_ARRAY((unsigned char *)regSpace, + SingleWidth / 8 * NumFloatRegs); +} + +void FloatRegFile::unserialize(Checkpoint *cp, const std::string §ion) +{ + UNSERIALIZE_ARRAY((unsigned char *)regSpace, + SingleWidth / 8 * NumFloatRegs); +} + diff --git a/src/arch/sparc/floatregfile.hh b/src/arch/sparc/floatregfile.hh new file mode 100644 index 000000000..9d760c9ff --- /dev/null +++ b/src/arch/sparc/floatregfile.hh @@ -0,0 +1,83 @@ +/* + * 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. + * + * Authors: Gabe Black + * Ali Saidi + */ + +#ifndef __ARCH_SPARC_FLOATREGFILE_HH__ +#define __ARCH_SPARC_FLOATREGFILE_HH__ + +#include "arch/sparc/faults.hh" +#include "arch/sparc/isa_traits.hh" +#include "arch/sparc/types.hh" + +#include <string> + +namespace SparcISA +{ + std::string getFloatRegName(RegIndex); + + typedef float float32_t; + typedef double float64_t; + //FIXME long double refers to a 10 byte float, rather than a + //16 byte float as required. This data type may have to be emulated. + typedef double float128_t; + + class FloatRegFile + { + public: + static const int SingleWidth = 32; + static const int DoubleWidth = 64; + static const int QuadWidth = 128; + + protected: + + //Since the floating point registers overlap each other, + //A generic storage space is used. The float to be returned is + //pulled from the appropriate section of this region. + char regSpace[(SingleWidth / 8) * NumFloatRegs]; + + public: + + void clear(); + + FloatReg readReg(int floatReg, int width); + + FloatRegBits readRegBits(int floatReg, int width); + + Fault setReg(int floatReg, const FloatReg &val, int width); + + Fault setRegBits(int floatReg, const FloatRegBits &val, int width); + + void serialize(std::ostream &os); + + void unserialize(Checkpoint *cp, const std::string §ion); + }; +} + +#endif diff --git a/src/arch/sparc/intregfile.cc b/src/arch/sparc/intregfile.cc new file mode 100644 index 000000000..0cc0a886a --- /dev/null +++ b/src/arch/sparc/intregfile.cc @@ -0,0 +1,133 @@ +/* + * 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. + * + * Authors: Gabe Black + * Ali Saidi + */ + +#include "arch/sparc/intregfile.hh" +#include "base/trace.hh" +#include "sim/serialize.hh" + +using namespace SparcISA; +using namespace std; + +class Checkpoint; + +string SparcISA::getIntRegName(RegIndex index) +{ + static std::string intRegName[NumIntRegs] = + {"g0", "g1", "g2", "g3", "g4", "g5", "g6", "g7", + "o0", "o1", "o2", "o3", "o4", "o5", "o6", "o7", + "l0", "l1", "l2", "l3", "l4", "l5", "l6", "l7", + "i0", "i1", "i2", "i3", "i4", "i5", "i6", "i7"}; + return intRegName[index]; +} + +int IntRegFile::flattenIndex(int reg) +{ + int flatIndex = offset[reg >> FrameOffsetBits] + | (reg & FrameOffsetMask); + DPRINTF(Sparc, "Flattened index %d into %d.\n", reg, flatIndex); + return flatIndex; +} + +void IntRegFile::clear() +{ + int x; + for (x = 0; x < MaxGL; x++) + memset(regGlobals[x], 0, sizeof(regGlobals[x])); + for(int x = 0; x < 2 * NWindows; x++) + bzero(regSegments[x], sizeof(regSegments[x])); +} + +IntRegFile::IntRegFile() +{ + offset[Globals] = 0; + regView[Globals] = regGlobals[0]; + setCWP(0); + clear(); +} + +IntReg IntRegFile::readReg(int intReg) +{ + IntReg val = + regView[intReg >> FrameOffsetBits][intReg & FrameOffsetMask]; + DPRINTF(Sparc, "Read register %d = 0x%x\n", intReg, val); + return val; +} + +Fault IntRegFile::setReg(int intReg, const IntReg &val) +{ + if(intReg) + DPRINTF(Sparc, "Wrote register %d = 0x%x\n", intReg, val); + regView[intReg >> FrameOffsetBits][intReg & FrameOffsetMask] = val; + return NoFault; +} + +//This doesn't effect the actual CWP register. +//It's purpose is to adjust the view of the register file +//to what it would be if CWP = cwp. +void IntRegFile::setCWP(int cwp) +{ + int index = ((NWindows - cwp) % NWindows) * 2; + offset[Outputs] = FrameOffset + (index * RegsPerFrame); + offset[Locals] = FrameOffset + ((index+1) * RegsPerFrame); + offset[Inputs] = FrameOffset + + (((index+2) % (NWindows * 2)) * RegsPerFrame); + regView[Outputs] = regSegments[index]; + regView[Locals] = regSegments[index+1]; + regView[Inputs] = regSegments[(index+2) % (NWindows * 2)]; + + DPRINTF(Sparc, "Changed the CWP value to %d\n", cwp); +} + +void IntRegFile::setGlobals(int gl) +{ + DPRINTF(Sparc, "Now using %d globals", gl); + + regView[Globals] = regGlobals[gl]; + offset[Globals] = RegGlobalOffset + gl * RegsPerFrame; +} + +void IntRegFile::serialize(std::ostream &os) +{ + unsigned int x; + for(x = 0; x < MaxGL; x++) + SERIALIZE_ARRAY(regGlobals[x], RegsPerFrame); + for(x = 0; x < 2 * NWindows; x++) + SERIALIZE_ARRAY(regSegments[x], RegsPerFrame); +} + +void IntRegFile::unserialize(Checkpoint *cp, const std::string §ion) +{ + unsigned int x; + for(x = 0; x < MaxGL; x++) + UNSERIALIZE_ARRAY(regGlobals[x], RegsPerFrame); + for(unsigned int x = 0; x < 2 * NWindows; x++) + UNSERIALIZE_ARRAY(regSegments[x], RegsPerFrame); +} diff --git a/src/arch/sparc/intregfile.hh b/src/arch/sparc/intregfile.hh new file mode 100644 index 000000000..d305c753b --- /dev/null +++ b/src/arch/sparc/intregfile.hh @@ -0,0 +1,103 @@ +/* + * 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. + * + * Authors: Gabe Black + * Ali Saidi + */ + +#ifndef __ARCH_SPARC_INTREGFILE_HH__ +#define __ARCH_SPARC_INTREGFILE_HH__ + +#include "arch/sparc/faults.hh" +#include "arch/sparc/isa_traits.hh" +#include "arch/sparc/types.hh" + +#include <string> + +namespace SparcISA +{ + class RegFile; + + //This function translates integer register file indices into names + std::string getIntRegName(RegIndex); + + class IntRegFile + { + private: + friend class RegFile; + protected: + static const int FrameOffsetBits = 3; + static const int FrameNumBits = 2; + + static const int RegsPerFrame = 1 << FrameOffsetBits; + static const int FrameNumMask = + (FrameNumBits == sizeof(int)) ? + (unsigned int)(-1) : + (1 << FrameNumBits) - 1; + static const int FrameOffsetMask = + (FrameOffsetBits == sizeof(int)) ? + (unsigned int)(-1) : + (1 << FrameOffsetBits) - 1; + + IntReg regGlobals[MaxGL][RegsPerFrame]; + IntReg regSegments[2 * NWindows][RegsPerFrame]; + + enum regFrame {Globals, Outputs, Locals, Inputs, NumFrames}; + + IntReg * regView[NumFrames]; + + static const int RegGlobalOffset = 0; + static const int FrameOffset = MaxGL * RegsPerFrame; + int offset[NumFrames]; + + public: + + int flattenIndex(int reg); + + void clear(); + + IntRegFile(); + + IntReg readReg(int intReg); + + Fault setReg(int intReg, const IntReg &val); + + void serialize(std::ostream &os); + + void unserialize(Checkpoint *cp, const std::string §ion); + + protected: + //This doesn't effect the actual CWP register. + //It's purpose is to adjust the view of the register file + //to what it would be if CWP = cwp. + void setCWP(int cwp); + + void setGlobals(int gl); + }; +} + +#endif diff --git a/src/arch/sparc/isa/base.isa b/src/arch/sparc/isa/base.isa index 02f7cf61a..b518265aa 100644 --- a/src/arch/sparc/isa/base.isa +++ b/src/arch/sparc/isa/base.isa @@ -86,6 +86,11 @@ output header {{ const SymbolTable *symtab) const; void printReg(std::ostream &os, int reg) const; + void printSrcReg(std::ostream &os, int reg) const; + void printDestReg(std::ostream &os, int reg) const; + + void printRegArray(std::ostream &os, + const RegIndex indexArray[], int num) const; }; bool passesCondition(uint32_t codes, uint32_t condition); @@ -150,6 +155,33 @@ output decoder {{ ccprintf(os, "\t%s ", mnemonic); } + void SparcStaticInst::printRegArray(std::ostream &os, + const RegIndex indexArray[], int num) const + { + if(num <= 0) + return; + printReg(os, indexArray[0]); + for(int x = 1; x < num; x++) + { + os << ", "; + printReg(os, indexArray[x]); + } + } + + void + SparcStaticInst::printSrcReg(std::ostream &os, int reg) const + { + if(_numSrcRegs > reg) + printReg(os, _srcRegIdx[reg]); + } + + void + SparcStaticInst::printDestReg(std::ostream &os, int reg) const + { + if(_numDestRegs > reg) + printReg(os, _destRegIdx[reg]); + } + void SparcStaticInst::printReg(std::ostream &os, int reg) const { diff --git a/src/arch/sparc/isa/decoder.isa b/src/arch/sparc/isa/decoder.isa index fa8832920..0c2729833 100644 --- a/src/arch/sparc/isa/decoder.isa +++ b/src/arch/sparc/isa/decoder.isa @@ -39,30 +39,30 @@ decode OP default Unknown::unknown() { //Throw an illegal instruction acception 0x0: Trap::illtrap({{fault = new IllegalInstruction;}}); - 0x1: decode BPCC + format BranchN { - format Branch19 + 0x1: decode BPCC { - 0x0: bpcci({{ + 0x0: bpcci(19, {{ if(passesCondition(Ccr<3:0>, COND2)) NNPC = xc->readPC() + disp; else handle_annul }}); - 0x2: bpccx({{ + 0x2: bpccx(19, {{ if(passesCondition(Ccr<7:4>, COND2)) NNPC = xc->readPC() + disp; else handle_annul }}); } + 0x2: bicc(22, {{ + if(passesCondition(Ccr<3:0>, COND2)) + NNPC = xc->readPC() + disp; + else + handle_annul + }}); } - 0x2: Branch22::bicc({{ - if(passesCondition(Ccr<3:0>, COND2)) - NNPC = xc->readPC() + disp; - else - handle_annul - }}); 0x3: decode RCOND2 { format BranchSplit @@ -110,22 +110,22 @@ decode OP default Unknown::unknown() 0x5: Trap::fbpfcc({{fault = new FpDisabled;}}); 0x6: Trap::fbfcc({{fault = new FpDisabled;}}); } - 0x1: Branch30::call({{ + 0x1: BranchN::call(30, {{ R15 = xc->readPC(); NNPC = R15 + disp; }}); 0x2: decode OP3 { format IntOp { 0x00: add({{Rd = Rs1.sdw + Rs2_or_imm13;}}); - 0x01: and({{Rd = Rs1.udw & Rs2_or_imm13;}}); - 0x02: or({{Rd = Rs1.udw | Rs2_or_imm13;}}); - 0x03: xor({{Rd = Rs1.udw ^ Rs2_or_imm13;}}); + 0x01: and({{Rd = Rs1.sdw & Rs2_or_imm13;}}); + 0x02: or({{Rd = Rs1.sdw | Rs2_or_imm13;}}); + 0x03: xor({{Rd = Rs1.sdw ^ Rs2_or_imm13;}}); 0x04: sub({{Rd = Rs1.sdw - Rs2_or_imm13;}}); - 0x05: andn({{Rd = Rs1.udw & ~Rs2_or_imm13;}}); - 0x06: orn({{Rd = Rs1.udw | ~Rs2_or_imm13;}}); - 0x07: xnor({{Rd = ~(Rs1.udw ^ Rs2_or_imm13);}}); + 0x05: andn({{Rd = Rs1.sdw & ~Rs2_or_imm13;}}); + 0x06: orn({{Rd = Rs1.sdw | ~Rs2_or_imm13;}}); + 0x07: xnor({{Rd = ~(Rs1.sdw ^ Rs2_or_imm13);}}); 0x08: addc({{Rd = Rs1.sdw + Rs2_or_imm13 + Ccr<0:0>;}}); - 0x09: mulx({{Rd = Rs1 * Rs2_or_imm13;}}); + 0x09: mulx({{Rd = Rs1.sdw * Rs2_or_imm13;}}); 0x0A: umul({{ Rd = Rs1.udw<31:0> * Rs2_or_imm13<31:0>; Y = Rd<63:32>; @@ -134,7 +134,7 @@ decode OP default Unknown::unknown() Rd.sdw = Rs1.sdw<31:0> * Rs2_or_imm13<31:0>; Y = Rd.sdw; }}); - 0x0C: subc({{Rd.sdw = Rs1.sdw + (~Rs2_or_imm13) + 1 + Ccr<0:0>}}); + 0x0C: subc({{Rd.sdw = Rs1.sdw + (~Rs2_or_imm13) + 1 - Ccr<0:0>}}); 0x0D: udivx({{ if(Rs2_or_imm13 == 0) fault = new DivisionByZero; else Rd.udw = Rs1.udw / Rs2_or_imm13; @@ -208,7 +208,7 @@ decode OP default Unknown::unknown() 0x1C: subccc({{ int64_t resTemp, val2 = Rs2_or_imm13; int64_t carryin = Ccr<0:0>; - Rd = resTemp = Rs1 + ~(val2 + carryin) + 1;}}, + Rd = resTemp = Rs1 + ~val2 + 1 - carryin;}}, {{(~((Rs1<31:0> + (~(val2 + carryin))<31:0> + 1))<32:>)}}, {{Rs1<31:> != val2<31:> && Rs1<31:> != resTemp<31:>}}, {{(~((Rs1<63:1> + (~(val2 + carryin))<63:1>) + (Rs1<0:> + (~(val2+carryin))<0:> + 1)<63:1>))<63:>}}, @@ -272,8 +272,9 @@ decode OP default Unknown::unknown() ); 0x22: taddcctv({{ int64_t resTemp, val2 = Rs2_or_imm13; - Rd = resTemp = Rs1 + val2; - int32_t overflow = Rs1<1:0> || val2<1:0> || (Rs1<31:> == val2<31:> && val2<31:> != resTemp<31:>); + Rd = Rs1 + val2; + int32_t overflow = Rs1<1:0> || val2<1:0> || + (Rs1<31:> == val2<31:> && val2<31:> != Rd<31:>); if(overflow) fault = new TagOverflow;}}, {{((Rs1 & 0xFFFFFFFF + val2 & 0xFFFFFFFF) >> 31)}}, {{overflow}}, @@ -322,15 +323,21 @@ decode OP default Unknown::unknown() 0x1: srax({{Rd = Rs1.sdw >> (I ? SHCNT64 : Rs2<5:0>);}}); } // XXX might want a format rdipr thing here - 0x28: rdasr({{ + 0x28: decode RS1 { + 0xF: decode I { + 0x0: Nop::stbar({{/*stuff*/}}); + 0x1: Nop::membar({{/*stuff*/}}); + } + default: rdasr({{ Rd = xc->readMiscRegWithEffect(RS1 + AsrStart, fault); - }}); - 0x29: rdhpr({{ + }}); + } + 0x29: HPriv::rdhpr({{ // XXX Need to protect with format that traps non-priv/priv // access Rd = xc->readMiscRegWithEffect(RS1 + HprStart, fault); }}); - 0x2A: rdpr({{ + 0x2A: Priv::rdpr({{ // XXX Need to protect with format that traps non-priv // access Rd = xc->readMiscRegWithEffect(RS1 + PrStart, fault); @@ -397,18 +404,233 @@ decode OP default Unknown::unknown() 0x0: BasicOperate::saved({{/*Boogy Boogy*/}}); 0x1: BasicOperate::restored({{/*Boogy Boogy*/}}); } - 0x32: wrpr({{ + 0x32: Priv::wrpr({{ // XXX Need to protect with format that traps non-priv // access - xc->setMiscRegWithEffect(RD + PrStart, Rs1 ^ Rs2_or_imm13); + fault = xc->setMiscRegWithEffect(RD + PrStart, Rs1 ^ Rs2_or_imm13); }}); - 0x33: wrhpr({{ + 0x33: HPriv::wrhpr({{ // XXX Need to protect with format that traps non-priv/priv // access - xc->setMiscRegWithEffect(RD + HprStart, Rs1 ^ Rs2_or_imm13); + fault = xc->setMiscRegWithEffect(RD + HprStart, Rs1 ^ Rs2_or_imm13); }}); - 0x34: Trap::fpop1({{fault = new FpDisabled;}}); + 0x34: decode OPF{ + format BasicOperate{ + 0x01: fmovs({{ + Frd.sf = Frs2.sf; + //fsr.ftt = fsr.cexc = 0 + Fsr &= ~(7 << 14); + Fsr &= ~(0x1F); + }}); + 0x02: fmovd({{ + Frd.df = Frs2.df; + //fsr.ftt = fsr.cexc = 0 + Fsr &= ~(7 << 14); + Fsr &= ~(0x1F); + }}); + 0x03: Trap::fmovq({{fault = new FpDisabled;}}); + 0x05: fnegs({{ + //XXX might want to explicitly flip the sign bit + //So cases with Nan and +/-0 don't do weird things + Frd.sf = -Frs2.sf; + //fsr.ftt = fsr.cexc = 0 + Fsr &= ~(7 << 14); + Fsr &= ~(0x1F); + }}); + 0x06: fnegd({{ + //XXX might want to explicitly flip the sign bit + //So cases with Nan and +/-0 don't do weird things + Frd.df = -Frs2.df; + //fsr.ftt = fsr.cexc = 0 + Fsr &= ~(7 << 14); + Fsr &= ~(0x1F); + }}); + 0x07: Trap::fnegq({{fault = new FpDisabled;}}); + 0x09: fabss({{ + //XXX this instruction should be tested individually + //Clear the sign bit + Frd.sf = (float)(~(1 << 31) & ((uint32_t)Frs2.sf)); + //fsr.ftt = fsr.cexc = 0 + Fsr &= ~(7 << 14); + Fsr &= ~(0x1F); + }}); + 0x0A: fabsd({{ + //XXX this instruction should be tested individually + //Clear the sign bit + Frd.df = (float)(~((uint64_t)1 << 63) & ((uint64_t)Frs2.df)); + //fsr.ftt = fsr.cexc = 0 + Fsr &= ~(7 << 14); + Fsr &= ~(0x1F); + }}); + 0x0B: Trap::fabsq({{fault = new FpDisabled;}}); + 0x29: fsqrts({{Frd.sf = sqrt(Frs2.sf);}}); + 0x2A: fsqrtd({{Frd.df = sqrt(Frs2.df);}}); + 0x2B: Trap::fsqrtq({{fault = new FpDisabled;}}); + 0x41: fadds({{Frd.sf = Frs1.sf + Frs2.sf;}}); + 0x42: faddd({{Frd.df = Frs1.df + Frs2.df;}}); + 0x43: Trap::faddq({{fault = new FpDisabled;}}); + 0x45: fsubs({{Frd.sf = Frs1.sf - Frs2.sf;}}); + 0x46: fsubd({{Frd.df = Frs1.df - Frs2.df;}}); + 0x47: Trap::fsubq({{fault = new FpDisabled;}}); + 0x49: fmuls({{Frd.sf = Frs1.sf * Frs2.sf;}}); + 0x4A: fmuld({{Frd.df = Frs1.df * Frs2.df;}}); + 0x4B: Trap::fmulq({{fault = new FpDisabled;}}); + 0x4D: fdivs({{Frd.sf = Frs1.sf / Frs2.sf;}}); + 0x4E: fdivd({{Frd.df = Frs1.df / Frs2.df;}}); + 0x4F: Trap::fdivq({{fault = new FpDisabled;}}); + 0x69: fsmuld({{Frd.df = Frs1.sf * Frs2.sf;}}); + 0x6E: Trap::fdmulq({{fault = new FpDisabled;}}); + 0x81: fstox({{ + Frd.df = (double)static_cast<int64_t>(Frs2.sf); + }}); + 0x82: fdtox({{ + Frd.df = (double)static_cast<int64_t>(Frs2.df); + }}); + 0x83: Trap::fqtox({{fault = new FpDisabled;}}); + 0x84: fxtos({{ + Frd.sf = static_cast<float>((int64_t)Frs2.df); + }}); + 0x88: fxtod({{ + Frd.df = static_cast<double>((int64_t)Frs2.df); + }}); + 0x8C: Trap::fxtoq({{fault = new FpDisabled;}}); + 0xC4: fitos({{ + Frd.sf = static_cast<float>((int32_t)Frs2.sf); + }}); + 0xC6: fdtos({{Frd.sf = Frs2.df;}}); + 0xC7: Trap::fqtos({{fault = new FpDisabled;}}); + 0xC8: fitod({{ + Frd.df = static_cast<double>((int32_t)Frs2.sf); + }}); + 0xC9: fstod({{Frd.df = Frs2.sf;}}); + 0xCB: Trap::fqtod({{fault = new FpDisabled;}}); + 0xCC: Trap::fitoq({{fault = new FpDisabled;}}); + 0xCD: Trap::fstoq({{fault = new FpDisabled;}}); + 0xCE: Trap::fdtoq({{fault = new FpDisabled;}}); + 0xD1: fstoi({{ + Frd.sf = (float)static_cast<int32_t>(Frs2.sf); + }}); + 0xD2: fdtoi({{ + Frd.sf = (float)static_cast<int32_t>(Frs2.df); + }}); + 0xD3: Trap::fqtoi({{fault = new FpDisabled;}}); + default: Trap::fpop1({{fault = new FpDisabled;}}); + } + } 0x35: Trap::fpop2({{fault = new FpDisabled;}}); + //This used to be just impdep1, but now it's a whole bunch + //of instructions + 0x36: decode OPF{ + 0x00: Trap::edge8({{fault = new IllegalInstruction;}}); + 0x01: Trap::edge8n({{fault = new IllegalInstruction;}}); + 0x02: Trap::edge8l({{fault = new IllegalInstruction;}}); + 0x03: Trap::edge8ln({{fault = new IllegalInstruction;}}); + 0x04: Trap::edge16({{fault = new IllegalInstruction;}}); + 0x05: Trap::edge16n({{fault = new IllegalInstruction;}}); + 0x06: Trap::edge16l({{fault = new IllegalInstruction;}}); + 0x07: Trap::edge16ln({{fault = new IllegalInstruction;}}); + 0x08: Trap::edge32({{fault = new IllegalInstruction;}}); + 0x09: Trap::edge32n({{fault = new IllegalInstruction;}}); + 0x0A: Trap::edge32l({{fault = new IllegalInstruction;}}); + 0x0B: Trap::edge32ln({{fault = new IllegalInstruction;}}); + 0x10: Trap::array8({{fault = new IllegalInstruction;}}); + 0x12: Trap::array16({{fault = new IllegalInstruction;}}); + 0x14: Trap::array32({{fault = new IllegalInstruction;}}); + 0x18: BasicOperate::alignaddress({{ + uint64_t sum = Rs1 + Rs2; + Frd = sum & ~7; + Gsr = (Gsr & ~7) | (sum & 7); + }}); + 0x19: Trap::bmask({{fault = new IllegalInstruction;}}); + 0x1A: BasicOperate::alignaddresslittle({{ + uint64_t sum = Rs1 + Rs2; + Frd = sum & ~7; + Gsr = (Gsr & ~7) | ((~sum + 1) & 7); + }}); + 0x20: Trap::fcmple16({{fault = new IllegalInstruction;}}); + 0x22: Trap::fcmpne16({{fault = new IllegalInstruction;}}); + 0x24: Trap::fcmple32({{fault = new IllegalInstruction;}}); + 0x26: Trap::fcmpne32({{fault = new IllegalInstruction;}}); + 0x28: Trap::fcmpgt16({{fault = new IllegalInstruction;}}); + 0x2A: Trap::fcmpeq16({{fault = new IllegalInstruction;}}); + 0x2C: Trap::fcmpgt32({{fault = new IllegalInstruction;}}); + 0x2E: Trap::fcmpeq32({{fault = new IllegalInstruction;}}); + 0x31: Trap::fmul8x16({{fault = new IllegalInstruction;}}); + 0x33: Trap::fmul8x16au({{fault = new IllegalInstruction;}}); + 0x35: Trap::fmul8x16al({{fault = new IllegalInstruction;}}); + 0x36: Trap::fmul8sux16({{fault = new IllegalInstruction;}}); + 0x37: Trap::fmul8ulx16({{fault = new IllegalInstruction;}}); + 0x38: Trap::fmuld8sux16({{fault = new IllegalInstruction;}}); + 0x39: Trap::fmuld8ulx16({{fault = new IllegalInstruction;}}); + 0x3A: Trap::fpack32({{fault = new IllegalInstruction;}}); + 0x3B: Trap::fpack16({{fault = new IllegalInstruction;}}); + 0x3D: Trap::fpackfix({{fault = new IllegalInstruction;}}); + 0x3E: Trap::pdist({{fault = new IllegalInstruction;}}); + 0x48: BasicOperate::faligndata({{ + uint64_t msbX = (uint64_t)Frs1; + uint64_t lsbX = (uint64_t)Frs2; + uint64_t msbShift = Gsr<2:0> * 8; + uint64_t lsbShift = (8 - Gsr<2:0>) * 8; + uint64_t msbMask = ((uint64_t)(-1)) << msbShift; + uint64_t lsbMask = ((uint64_t)(-1)) << lsbShift; + Frd = ((msbX << msbShift) & msbMask) | + ((lsbX << lsbShift) & lsbMask); + }}); + 0x4B: Trap::fpmerge({{fault = new IllegalInstruction;}}); + 0x4C: Trap::bshuffle({{fault = new IllegalInstruction;}}); + 0x4D: Trap::fexpand({{fault = new IllegalInstruction;}}); + 0x50: Trap::fpadd16({{fault = new IllegalInstruction;}}); + 0x51: Trap::fpadd16s({{fault = new IllegalInstruction;}}); + 0x52: Trap::fpadd32({{fault = new IllegalInstruction;}}); + 0x53: Trap::fpadd32s({{fault = new IllegalInstruction;}}); + 0x54: Trap::fpsub16({{fault = new IllegalInstruction;}}); + 0x55: Trap::fpsub16s({{fault = new IllegalInstruction;}}); + 0x56: Trap::fpsub32({{fault = new IllegalInstruction;}}); + 0x57: Trap::fpsub32s({{fault = new IllegalInstruction;}}); + 0x60: BasicOperate::fzero({{Frd.df = 0;}}); + 0x61: BasicOperate::fzeros({{Frd.sf = 0;}}); + 0x62: Trap::fnor({{fault = new IllegalInstruction;}}); + 0x63: Trap::fnors({{fault = new IllegalInstruction;}}); + 0x64: Trap::fandnot2({{fault = new IllegalInstruction;}}); + 0x65: Trap::fandnot2s({{fault = new IllegalInstruction;}}); + 0x66: BasicOperate::fnot2({{ + Frd.df = (double)(~((uint64_t)Frs2.df)); + }}); + 0x67: BasicOperate::fnot2s({{ + Frd.sf = (float)(~((uint32_t)Frs2.sf)); + }}); + 0x68: Trap::fandnot1({{fault = new IllegalInstruction;}}); + 0x69: Trap::fandnot1s({{fault = new IllegalInstruction;}}); + 0x6A: BasicOperate::fnot1({{ + Frd.df = (double)(~((uint64_t)Frs1.df)); + }}); + 0x6B: BasicOperate::fnot1s({{ + Frd.sf = (float)(~((uint32_t)Frs1.sf)); + }}); + 0x6C: Trap::fxor({{fault = new IllegalInstruction;}}); + 0x6D: Trap::fxors({{fault = new IllegalInstruction;}}); + 0x6E: Trap::fnand({{fault = new IllegalInstruction;}}); + 0x6F: Trap::fnands({{fault = new IllegalInstruction;}}); + 0x70: Trap::fand({{fault = new IllegalInstruction;}}); + 0x71: Trap::fands({{fault = new IllegalInstruction;}}); + 0x72: Trap::fxnor({{fault = new IllegalInstruction;}}); + 0x73: Trap::fxnors({{fault = new IllegalInstruction;}}); + 0x74: BasicOperate::fsrc1({{Frd.df = Frs1.df;}}); + 0x75: BasicOperate::fsrc1s({{Frd.sf = Frs1.sf;}}); + 0x76: Trap::fornot2({{fault = new IllegalInstruction;}}); + 0x77: Trap::fornot2s({{fault = new IllegalInstruction;}}); + 0x78: BasicOperate::fsrc2({{Frd.df = Frs2.df;}}); + 0x79: BasicOperate::fsrc2s({{Frd.sf = Frs2.sf;}}); + 0x7A: Trap::fornot1({{fault = new IllegalInstruction;}}); + 0x7B: Trap::fornot1s({{fault = new IllegalInstruction;}}); + 0x7C: Trap::for({{fault = new IllegalInstruction;}}); + 0x7D: Trap::fors({{fault = new IllegalInstruction;}}); + 0x7E: Trap::fone({{fault = new IllegalInstruction;}}); + 0x7F: Trap::fones({{fault = new IllegalInstruction;}}); + 0x80: Trap::shutdown({{fault = new IllegalInstruction;}}); + 0x81: Trap::siam({{fault = new IllegalInstruction;}}); + } + 0x37: Trap::impdep2({{fault = new IllegalInstruction;}}); 0x38: Branch::jmpl({{ Addr target = Rs1 + Rs2_or_imm13; if(target & 0x3) @@ -549,7 +771,7 @@ decode OP default Unknown::unknown() NNPC = Tnpc + 4; Tl = Tl - 1; }}); - 0x1: BasicOperate::retry({{ + 0x1: Priv::retry({{ if(Tl == 0) return new IllegalInstruction; Cwp = Tstate<4:0>; @@ -630,27 +852,28 @@ decode OP default Unknown::unknown() Mem = temp; }}, {{32}}); format Trap { - 0x20: ldf({{fault = new FpDisabled;}}); + 0x20: Load::ldf({{Frd.sf = ((float)Mem);}}, {{32}}); 0x21: decode X { 0x0: Load::ldfsr({{Fsr = Mem<31:0> | Fsr<63:32>;}}, {{32}}); 0x1: Load::ldxfsr({{Fsr = Mem;}}, {{64}}); } 0x22: ldqf({{fault = new FpDisabled;}}); - 0x23: lddf({{fault = new FpDisabled;}}); - 0x24: stf({{fault = new FpDisabled;}}); + 0x23: Load::lddf({{Frd.df = ((double)Mem);}}, {{64}}); + 0x24: Store::stf({{Mem = ((int32_t)Frd.sf);}}, {{32}}); 0x25: decode X { 0x0: Store::stfsr({{Mem = Fsr<31:0>;}}, {{32}}); 0x1: Store::stxfsr({{Mem = Fsr;}}, {{64}}); } 0x26: stqf({{fault = new FpDisabled;}}); - 0x27: stdf({{fault = new FpDisabled;}}); + 0x27: Store::stdf({{Mem = ((int64_t)Frd.df);}}, {{64}}); 0x2D: Nop::prefetch({{ }}); - 0x30: ldfa({{return new FpDisabled;}}); + 0x30: Load::ldfa({{Frd.sf = ((float)Mem);}}, {{32}}); 0x32: ldqfa({{fault = new FpDisabled;}}); - 0x33: lddfa({{fault = new FpDisabled;}}); - 0x34: stfa({{fault = new FpDisabled;}}); - 0x35: stqfa({{fault = new FpDisabled;}}); - 0x36: stdfa({{fault = new FpDisabled;}}); + 0x33: Load::lddfa({{Frd.df = ((double)Mem);}}, {{64}}); + 0x34: Store::stfa({{Mem = ((int32_t)Frd.sf);}}, {{32}}); + 0x36: stqfa({{fault = new FpDisabled;}}); + //XXX need to work in the ASI thing + 0x37: Store::stdfa({{Mem = ((uint64_t)Frd.df);}}, {{64}}); 0x3C: Cas::casa({{ uint64_t val = Mem.uw; if(Rs2.uw == val) diff --git a/src/arch/sparc/isa/formats/basic.isa b/src/arch/sparc/isa/formats/basic.isa index 60432cb6b..0a47a7ffe 100644 --- a/src/arch/sparc/isa/formats/basic.isa +++ b/src/arch/sparc/isa/formats/basic.isa @@ -63,7 +63,6 @@ def template BasicExecute {{ { Fault fault = NoFault; - %(fp_enable_check)s; %(op_decl)s; %(op_rd)s; %(code)s; @@ -81,11 +80,6 @@ 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 BasicOperate(code, *flags) {{ iop = InstObjParams(name, Name, 'SparcStaticInst', diff --git a/src/arch/sparc/isa/formats/branch.isa b/src/arch/sparc/isa/formats/branch.isa index 7d46ce739..8a3f05173 100644 --- a/src/arch/sparc/isa/formats/branch.isa +++ b/src/arch/sparc/isa/formats/branch.isa @@ -69,47 +69,18 @@ output header {{ }; /** - * Base class for branches with 19 bit displacements. + * Base class for branches with n bit displacements. */ - class Branch19 : public BranchDisp + template<int bits> + class BranchNBits : public BranchDisp { protected: // Constructor - Branch19(const char *mnem, MachInst _machInst, + BranchNBits(const char *mnem, MachInst _machInst, OpClass __opClass) : BranchDisp(mnem, _machInst, __opClass) { - disp = sign_ext(DISP19 << 2, 21); - } - }; - - /** - * Base class for branches with 22 bit displacements. - */ - class Branch22 : public BranchDisp - { - protected: - // Constructor - Branch22(const char *mnem, MachInst _machInst, - OpClass __opClass) : - BranchDisp(mnem, _machInst, __opClass) - { - disp = sign_ext(DISP22 << 2, 24); - } - }; - - /** - * Base class for branches with 30 bit displacements. - */ - class Branch30 : public BranchDisp - { - protected: - // Constructor - Branch30(const char *mnem, MachInst _machInst, - OpClass __opClass) : - BranchDisp(mnem, _machInst, __opClass) - { - disp = sign_ext(DISP30 << 2, 32); + disp = sign_ext(_machInst << 2, bits + 2); } }; @@ -149,29 +120,23 @@ output header {{ }}; output decoder {{ + + template class BranchNBits<19>; + + template class BranchNBits<22>; + + template class BranchNBits<30>; + std::string Branch::generateDisassembly(Addr pc, const SymbolTable *symtab) const { std::stringstream response; printMnemonic(response, mnemonic); - - if (_numSrcRegs > 0) - { - printReg(response, _srcRegIdx[0]); - for(int x = 1; x < _numSrcRegs; x++) - { + printRegArray(response, _srcRegIdx, _numSrcRegs); + if(_numDestRegs && _numSrcRegs) response << ", "; - printReg(response, _srcRegIdx[x]); - } - } - - if (_numDestRegs > 0) - { - if(_numSrcRegs > 0) - response << ", "; - printReg(response, _destRegIdx[0]); - } + printDestReg(response, 0); return response.str(); } @@ -182,27 +147,13 @@ output decoder {{ std::stringstream response; printMnemonic(response, mnemonic); - - if (_numSrcRegs > 0) - { - printReg(response, _srcRegIdx[0]); - for(int x = 1; x < _numSrcRegs; x++) - { - response << ", "; - printReg(response, _srcRegIdx[x]); - } - } - + printRegArray(response, _srcRegIdx, _numSrcRegs); if(_numSrcRegs > 0) response << ", "; - ccprintf(response, "0x%x", imm); - if (_numDestRegs > 0) - { response << ", "; - printReg(response, _destRegIdx[0]); - } + printDestReg(response, 0); return response.str(); } @@ -292,32 +243,10 @@ def format Branch(code, *opt_flags) {{ }}; // Primary format for branch instructions: -def format Branch19(code, *opt_flags) {{ - code = re.sub(r'handle_annul', handle_annul, code) - codeBlk = CodeBlock(code) - iop = InstObjParams(name, Name, 'Branch19', codeBlk, opt_flags) - header_output = BasicDeclare.subst(iop) - decoder_output = BasicConstructor.subst(iop) - exec_output = BranchExecute.subst(iop) - decode_block = BasicDecode.subst(iop) -}}; - -// Primary format for branch instructions: -def format Branch22(code, *opt_flags) {{ - code = re.sub(r'handle_annul', handle_annul, code) - codeBlk = CodeBlock(code) - iop = InstObjParams(name, Name, 'Branch22', codeBlk, opt_flags) - header_output = BasicDeclare.subst(iop) - decoder_output = BasicConstructor.subst(iop) - exec_output = BranchExecute.subst(iop) - decode_block = BasicDecode.subst(iop) -}}; - -// Primary format for branch instructions: -def format Branch30(code, *opt_flags) {{ +def format BranchN(bits, code, *opt_flags) {{ code = re.sub(r'handle_annul', handle_annul, code) codeBlk = CodeBlock(code) - iop = InstObjParams(name, Name, 'Branch30', codeBlk, opt_flags) + iop = InstObjParams(name, Name, "BranchNBits<%d>" % bits, codeBlk, opt_flags) header_output = BasicDeclare.subst(iop) decoder_output = BasicConstructor.subst(iop) exec_output = BranchExecute.subst(iop) diff --git a/src/arch/sparc/isa/formats/integerop.isa b/src/arch/sparc/isa/formats/integerop.isa index 1894ce541..27616216e 100644 --- a/src/arch/sparc/isa/formats/integerop.isa +++ b/src/arch/sparc/isa/formats/integerop.isa @@ -132,7 +132,7 @@ output header {{ OpClass __opClass) : IntOpImm(mnem, _machInst, __opClass) { - imm = (IMM22 << 10) & 0xFFFFFC00; + imm = (IMM22 & 0x3FFFFF) << 10; } std::string generateDisassembly(Addr pc, @@ -157,12 +157,9 @@ output decoder {{ if(!strcmp(mnemonic, "or") && _srcRegIdx[0] == 0) { printMnemonic(os, "mov"); - if(_numSrcRegs > 0) - printReg(os, _srcRegIdx[1]); + printSrcReg(os, 1); ccprintf(os, ", "); - if(_numDestRegs > 0) - printReg(os, _destRegIdx[0]); - + printDestReg(os, 0); return true; } return false; @@ -173,32 +170,24 @@ output decoder {{ { if(!strcmp(mnemonic, "or")) { - if(_srcRegIdx[0] == 0) + if(_numSrcRegs > 0 && _srcRegIdx[0] == 0) { if(imm == 0) - { printMnemonic(os, "clr"); - if(_numDestRegs > 0) - printReg(os, _destRegIdx[0]); - return true; - } else { printMnemonic(os, "mov"); - ccprintf(os, ", 0x%x, ", imm); - if(_numDestRegs > 0) - printReg(os, _destRegIdx[0]); - return true; + ccprintf(os, " 0x%x, ", imm); } + printDestReg(os, 0); + return true; } else if(imm == 0) { printMnemonic(os, "mov"); - if(_numSrcRegs > 0) - printReg(os, _srcRegIdx[0]); + printSrcReg(os, 0); ccprintf(os, ", "); - if(_numDestRegs > 0) - printReg(os, _destRegIdx[0]); + printDestReg(os, 0); return true; } } @@ -210,25 +199,13 @@ output decoder {{ { std::stringstream response; - if(!printPseudoOps(response, pc, symtab)) - { - printMnemonic(response, mnemonic); - if (_numSrcRegs > 0) - { - printReg(response, _srcRegIdx[0]); - for(int x = 1; x < _numSrcRegs; x++) - { - response << ", "; - printReg(response, _srcRegIdx[x]); - } - } - if (_numDestRegs > 0) - { - if(_numSrcRegs > 0) - response << ", "; - printReg(response, _destRegIdx[0]); - } - } + if(printPseudoOps(response, pc, symtab)) + return response.str(); + printMnemonic(response, mnemonic); + printRegArray(response, _srcRegIdx, _numSrcRegs); + if(_numDestRegs && _numSrcRegs) + response << ", "; + printDestReg(response, 0); return response.str(); } @@ -237,27 +214,16 @@ output decoder {{ { std::stringstream response; - if(!printPseudoOps(response, pc, symtab)) - { - printMnemonic(response, mnemonic); - if (_numSrcRegs > 0) - { - printReg(response, _srcRegIdx[0]); - for(int x = 1; x < _numSrcRegs - 1; x++) - { - response << ", "; - printReg(response, _srcRegIdx[x]); - } - } - if(_numSrcRegs > 0) - response << ", "; - ccprintf(response, "0x%x", imm); - if (_numDestRegs > 0) - { - response << ", "; - printReg(response, _destRegIdx[0]); - } - } + if(printPseudoOps(response, pc, symtab)) + return response.str(); + printMnemonic(response, mnemonic); + printRegArray(response, _srcRegIdx, _numSrcRegs); + if(_numSrcRegs > 0) + response << ", "; + ccprintf(response, "0x%x", imm); + if(_numDestRegs > 0) + response << ", "; + printDestReg(response, 0); return response.str(); } @@ -267,10 +233,8 @@ output decoder {{ std::stringstream response; printMnemonic(response, mnemonic); - if(_numSrcRegs > 0) - response << ", "; ccprintf(response, "%%hi(0x%x), ", imm); - printReg(response, _destRegIdx[0]); + printDestReg(response, 0); return response.str(); } }}; @@ -316,38 +280,29 @@ let {{ return (header_output, decoder_output, exec_output, decode_block) calcCcCode = ''' - uint8_t tmp_ccriccc; - uint8_t tmp_ccriccv; - uint8_t tmp_ccriccz; - uint8_t tmp_ccriccn; - uint8_t tmp_ccrxccc; - uint8_t tmp_ccrxccv; - uint8_t tmp_ccrxccz; - uint8_t tmp_ccrxccn; - - tmp_ccriccn = (Rd >> 31) & 1; - tmp_ccriccz = ((Rd & 0xFFFFFFFF) == 0); - tmp_ccrxccn = (Rd >> 63) & 1; - tmp_ccrxccz = (Rd == 0); - tmp_ccriccv = %(ivValue)s & 1; - tmp_ccriccc = %(icValue)s & 1; - tmp_ccrxccv = %(xvValue)s & 1; - tmp_ccrxccc = %(xcValue)s & 1; - - Ccr = tmp_ccriccc | tmp_ccriccv << 1 | - tmp_ccriccz << 2 | tmp_ccriccn << 3| - tmp_ccrxccc << 4 | tmp_ccrxccv << 5| - tmp_ccrxccz << 6| tmp_ccrxccn << 7; - - - DPRINTF(Sparc, "in = %%d\\n", (uint16_t)tmp_ccriccn); - DPRINTF(Sparc, "iz = %%d\\n", (uint16_t)tmp_ccriccz); - DPRINTF(Sparc, "xn = %%d\\n", (uint16_t)tmp_ccrxccn); - DPRINTF(Sparc, "xz = %%d\\n", (uint16_t)tmp_ccrxccz); - DPRINTF(Sparc, "iv = %%d\\n", (uint16_t)tmp_ccriccv); - DPRINTF(Sparc, "ic = %%d\\n", (uint16_t)tmp_ccriccc); - DPRINTF(Sparc, "xv = %%d\\n", (uint16_t)tmp_ccrxccv); - DPRINTF(Sparc, "xc = %%d\\n", (uint16_t)tmp_ccrxccc); + uint16_t _ic, _iv, _iz, _in, _xc, _xv, _xz, _xn; + + _in = (Rd >> 31) & 1; + _iz = ((Rd & 0xFFFFFFFF) == 0); + _xn = (Rd >> 63) & 1; + _xz = (Rd == 0); + _iv = %(ivValue)s & 1; + _ic = %(icValue)s & 1; + _xv = %(xvValue)s & 1; + _xc = %(xcValue)s & 1; + + Ccr = _ic << 0 | _iv << 1 | _iz << 2 | _in << 3 | + _xc << 4 | _xv << 5 | _xz << 6 | _xn << 7; + + + DPRINTF(Sparc, "in = %%d\\n", _in); + DPRINTF(Sparc, "iz = %%d\\n", _iz); + DPRINTF(Sparc, "xn = %%d\\n", _xn); + DPRINTF(Sparc, "xz = %%d\\n", _xz); + DPRINTF(Sparc, "iv = %%d\\n", _iv); + DPRINTF(Sparc, "ic = %%d\\n", _ic); + DPRINTF(Sparc, "xv = %%d\\n", _xv); + DPRINTF(Sparc, "xc = %%d\\n", _xc); ''' }}; diff --git a/src/arch/sparc/isa/formats/priv.isa b/src/arch/sparc/isa/formats/priv.isa index 7df59d736..d7ee01519 100644 --- a/src/arch/sparc/isa/formats/priv.isa +++ b/src/arch/sparc/isa/formats/priv.isa @@ -72,7 +72,11 @@ output decoder {{ std::string Priv::generateDisassembly(Addr pc, const SymbolTable *symtab) const { - return "Privileged Instruction"; + std::stringstream response; + + printMnemonic(response, mnemonic); + + return response.str(); } }}; @@ -87,9 +91,10 @@ def template PrivExecute {{ if(%(check)s) return new PrivilegedAction; + Fault fault = NoFault; %(code)s; %(op_wb)s; - return NoFault; + return fault; } }}; @@ -116,10 +121,17 @@ let {{ // Primary format for integer operate instructions: def format Priv(code, *opt_flags) {{ - checkCode = "((xc->readMiscReg(PrStart + MISCREG_PSTATE))<2:2>)" + checkCode = '''((xc->readMiscReg(PrStart + MISCREG_PSTATE))<2:2>) || + ((xc->readMiscReg(HprStart + MISCREG_HPSTATE))<2:2>)''' (header_output, decoder_output, exec_output, decode_block) = doPrivFormat(code, - checkCode, name, Name, opt_flags) + checkCode, name, Name, opt_flags + ('IprAccessOp',)) }}; +def format HPriv(code, *opt_flags) {{ + checkCode = "((xc->readMiscReg(HprStart + MISCREG_HPSTATE))<2:2>)" + (header_output, decoder_output, + exec_output, decode_block) = doPrivFormat(code, + checkCode, name, Name, opt_flags + ('IprAccessOp',)) +}}; diff --git a/src/arch/sparc/isa/includes.isa b/src/arch/sparc/isa/includes.isa index 40afb3722..3783051c4 100644 --- a/src/arch/sparc/isa/includes.isa +++ b/src/arch/sparc/isa/includes.isa @@ -36,7 +36,6 @@ output header {{ #include <sstream> #include <iostream> -#include <iomanip> #include "cpu/static_inst.hh" #include "arch/sparc/faults.hh" @@ -50,7 +49,6 @@ output decoder {{ #include "base/loader/symtab.hh" #include "cpu/thread_context.hh" // for Jump::branchTarget() -#include <math.h> #if defined(linux) #include <fenv.h> #endif @@ -59,14 +57,10 @@ using namespace SparcISA; }}; output exec {{ -#include <math.h> #if defined(linux) #include <fenv.h> #endif -#ifdef FULL_SYSTEM -//#include "sim/pseudo_inst.hh" -#endif #include "cpu/base.hh" #include "cpu/exetrace.hh" #include "sim/sim_exit.hh" diff --git a/src/arch/sparc/isa/operands.isa b/src/arch/sparc/isa/operands.isa index 9e5c783e8..605816083 100644 --- a/src/arch/sparc/isa/operands.isa +++ b/src/arch/sparc/isa/operands.isa @@ -51,12 +51,12 @@ def operands {{ 'RdHigh': ('IntReg', 'udw', 'RD | 1', 'IsInteger', 3), 'Rs1': ('IntReg', 'udw', 'RS1', 'IsInteger', 4), 'Rs2': ('IntReg', 'udw', 'RS2', 'IsInteger', 5), - #'Fa': ('FloatReg', 'df', 'FA', 'IsFloating', 1), - #'Fb': ('FloatReg', 'df', 'FB', 'IsFloating', 2), - #'Fc': ('FloatReg', 'df', 'FC', 'IsFloating', 3), - 'Mem': ('Mem', 'udw', None, ('IsMemRef', 'IsLoad', 'IsStore'), 4), - 'NPC': ('NPC', 'udw', None, ( None, None, 'IsControl' ), 4), - 'NNPC': ('NNPC', 'udw', None, (None, None, 'IsControl' ), 4), + 'Frd': ('FloatReg', 'df', 'RD', 'IsFloating', 10), + 'Frs1': ('FloatReg', 'df', 'RS1', 'IsFloating', 11), + 'Frs2': ('FloatReg', 'df', 'RS2', 'IsFloating', 12), + 'Mem': ('Mem', 'udw', None, ('IsMemRef', 'IsLoad', 'IsStore'), 20), + 'NPC': ('NPC', 'udw', None, ( None, None, 'IsControl' ), 31), + 'NNPC': ('NNPC', 'udw', None, (None, None, 'IsControl' ), 32), #'Runiq': ('ControlReg', 'uq', 'Uniq', None, 1), #'FPCR': ('ControlReg', 'uq', 'Fpcr', None, 1), 'R0': ('IntReg', 'udw', '0', None, 6), @@ -65,24 +65,25 @@ def operands {{ 'R16': ('IntReg', 'udw', '16', None, 9), # Control registers - 'Y': ('ControlReg', 'udw', 'MISCREG_Y', None, 12), - 'Ccr': ('ControlReg', 'udw', 'MISCREG_CCR', None, 17), - 'Asi': ('ControlReg', 'udw', 'MISCREG_ASI', None, 26), + 'Y': ('ControlReg', 'udw', 'MISCREG_Y', None, 40), + 'Ccr': ('ControlReg', 'udw', 'MISCREG_CCR', None, 41), + 'Asi': ('ControlReg', 'udw', 'MISCREG_ASI', None, 42), - 'Tpc': ('ControlReg', 'udw', 'MISCREG_TPC', None, 28), - 'Tnpc': ('ControlReg', 'udw', 'MISCREG_TNPC', None, 28), - 'Tstate': ('ControlReg', 'udw', 'MISCREG_TSTATE', None, 28), - 'Pstate': ('ControlReg', 'udw', 'MISCREG_PSTATE', None, 1), - 'Tl': ('ControlReg', 'udw', 'MISCREG_TL', None, 27), + 'Tpc': ('ControlReg', 'udw', 'MISCREG_TPC', None, 43), + 'Tnpc': ('ControlReg', 'udw', 'MISCREG_TNPC', None, 44), + 'Tstate': ('ControlReg', 'udw', 'MISCREG_TSTATE', None, 45), + 'Pstate': ('ControlReg', 'udw', 'MISCREG_PSTATE', None, 46), + 'Tl': ('ControlReg', 'udw', 'MISCREG_TL', None, 47), - 'Cwp': ('ControlReg', 'udw', 'MISCREG_CWP', None, 15), - 'Cansave': ('ControlReg', 'udw', 'MISCREG_CANSAVE', None, 34), - 'Canrestore': ('ControlReg', 'udw', 'MISCREG_CANRESTORE', None, 35), - 'Cleanwin': ('ControlReg', 'udw', 'MISCREG_CLEANWIN', None, 37), - 'Otherwin': ('ControlReg', 'udw', 'MISCREG_OTHERWIN', None, 36), - 'Wstate': ('ControlReg', 'udw', 'MISCREG_WSTATE', None, 38), - 'Gl': ('ControlReg', 'udw', 'MISCREG_GL', None, 12), + 'Cwp': ('ControlReg', 'udw', 'MISCREG_CWP', None, 48), + 'Cansave': ('ControlReg', 'udw', 'MISCREG_CANSAVE', None, 49), + 'Canrestore': ('ControlReg', 'udw', 'MISCREG_CANRESTORE', None, 50), + 'Cleanwin': ('ControlReg', 'udw', 'MISCREG_CLEANWIN', None, 51), + 'Otherwin': ('ControlReg', 'udw', 'MISCREG_OTHERWIN', None, 52), + 'Wstate': ('ControlReg', 'udw', 'MISCREG_WSTATE', None, 53), + 'Gl': ('ControlReg', 'udw', 'MISCREG_GL', None, 54), - 'Fsr': ('ControlReg', 'udw', 'MISCREG_FSR', None, 47) + 'Fsr': ('ControlReg', 'udw', 'MISCREG_FSR', None, 55), + 'Gsr': ('ControlReg', 'udw', 'MISCREG_GSR', None, 56) }}; diff --git a/src/arch/sparc/isa_traits.hh b/src/arch/sparc/isa_traits.hh index 346f7b730..7f830eb28 100644 --- a/src/arch/sparc/isa_traits.hh +++ b/src/arch/sparc/isa_traits.hh @@ -25,13 +25,13 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * Authors: Korey Sewell - * Gabe Black + * Authors: Gabe Black */ #ifndef __ARCH_SPARC_ISA_TRAITS_HH__ #define __ARCH_SPARC_ISA_TRAITS_HH__ +#include "arch/sparc/types.hh" #include "base/misc.hh" #include "config/full_system.hh" #include "sim/host.hh" @@ -46,70 +46,45 @@ class StaticInstPtr; namespace BigEndianGuest {} -#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 #include "arch/sparc/isa_fullsys_traits.hh" #endif namespace SparcISA { + class RegFile; + + //This makes sure the big endian versions of certain functions are used. + using namespace BigEndianGuest; + + //TODO this needs to be a SPARC Noop + // Alpha UNOP (ldq_u r31,0(r0)) + const MachInst NoopMachInst = 0x2ffe0000; + + const int NumIntRegs = 32; + const int NumFloatRegs = 64; + const int NumMiscRegs = 40; // 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 = 96, + // 32..95 are the FP regs 0..31, i.e. use (reg + FP_Base_DepTag) + FP_Base_DepTag = NumIntRegs, + Ctrl_Base_DepTag = NumIntRegs + NumFloatRegs, //XXX These are here solely to get compilation and won't work Fpcr_DepTag = 0, Uniq_DepTag = 0 }; - //This makes sure the big endian versions of certain functions are used. - using namespace BigEndianGuest; - typedef uint32_t MachInst; - typedef uint64_t ExtMachInst; + // MAXTL - maximum trap level + const int MaxPTL = 2; + const int MaxTL = 6; + const int MaxGL = 3; + const int MaxPGL = 2; - const int NumIntRegs = 32; - const int NumFloatRegs = 64; - const int NumMiscRegs = 32; + // NWINDOWS - number of register windows, can be 3 to 32 + const int NWindows = 32; // semantically meaningful register indices const int ZeroReg = 0; // architecturally meaningful @@ -131,14 +106,6 @@ namespace SparcISA const int MaxInstSrcRegs = 8; const int MaxInstDestRegs = 9; - typedef uint64_t IntReg; - - // control register file contents - typedef uint64_t MiscReg; - - typedef double FloatReg; - typedef uint64_t FloatRegBits; - //8K. This value is implmentation specific; and should probably //be somewhere else. const int LogVMPageSize = 13; @@ -165,29 +132,4 @@ namespace SparcISA extern const MachInst NoopMachInst; } -#include "arch/sparc/regfile.hh" - -namespace SparcISA -{ - -#if !FULL_SYSTEM - static inline void setSyscallReturn(SyscallReturn return_value, - RegFile *regs) - { - // check for error condition. SPARC syscall convention is to - // indicate success/failure in reg the carry bit of the ccr - // and put the return value itself in the standard return value reg (). - if (return_value.successful()) { - // no error, clear XCC.C - regs->setMiscReg(MISCREG_CCR, regs->readMiscReg(MISCREG_CCR) & 0xEF); - regs->setIntReg(ReturnValueReg, return_value.value()); - } else { - // got an error, set XCC.C - regs->setMiscReg(MISCREG_CCR, regs->readMiscReg(MISCREG_CCR) | 0x10); - regs->setIntReg(ReturnValueReg, return_value.value()); - } - } -#endif -}; - #endif // __ARCH_SPARC_ISA_TRAITS_HH__ diff --git a/src/arch/sparc/linux/linux.cc b/src/arch/sparc/linux/linux.cc index ae6ffbc2a..1211d5f65 100644 --- a/src/arch/sparc/linux/linux.cc +++ b/src/arch/sparc/linux/linux.cc @@ -29,6 +29,7 @@ */ #include "arch/sparc/linux/linux.hh" +#include <fcntl.h> // open(2) flags translation table OpenFlagTransTable SparcLinux::openFlagTable[] = { diff --git a/src/arch/sparc/linux/process.cc b/src/arch/sparc/linux/process.cc index e27255e67..8c2de8ca3 100644 --- a/src/arch/sparc/linux/process.cc +++ b/src/arch/sparc/linux/process.cc @@ -199,7 +199,7 @@ SyscallDesc SparcLinuxProcess::syscallDescs[] = { /* 99 */ SyscallDesc("accept", unimplementedFunc), /* 100 */ SyscallDesc("getpriority", unimplementedFunc), /* 101 */ SyscallDesc("rt_sigreturn", unimplementedFunc), - /* 102 */ SyscallDesc("rt_sigaction", unimplementedFunc), + /* 102 */ SyscallDesc("rt_sigaction", ignoreFunc), /* 103 */ SyscallDesc("rt_sigprocmask", unimplementedFunc), /* 104 */ SyscallDesc("rt_sigpending", unimplementedFunc), /* 105 */ SyscallDesc("rt_sigtimedwait", unimplementedFunc), @@ -295,7 +295,7 @@ SyscallDesc SparcLinuxProcess::syscallDescs[] = { /* 195 */ SyscallDesc("epoll_wait", unimplementedFunc), /* 196 */ SyscallDesc("ioprio_set", unimplementedFunc), /* 197 */ SyscallDesc("getppid", getppidFunc), - /* 198 */ SyscallDesc("sigaction", unimplementedFunc), + /* 198 */ SyscallDesc("sigaction", ignoreFunc), /* 199 */ SyscallDesc("sgetmask", unimplementedFunc), /* 200 */ SyscallDesc("ssetmask", unimplementedFunc), /* 201 */ SyscallDesc("sigsuspend", unimplementedFunc), diff --git a/src/arch/sparc/linux/process.hh b/src/arch/sparc/linux/process.hh index f4819ba84..4af8f0f75 100644 --- a/src/arch/sparc/linux/process.hh +++ b/src/arch/sparc/linux/process.hh @@ -32,6 +32,7 @@ #define __SPARC_LINUX_PROCESS_HH__ #include "arch/sparc/linux/linux.hh" +#include "arch/sparc/syscallreturn.hh" #include "arch/sparc/process.hh" #include "sim/process.hh" diff --git a/src/arch/sparc/miscregfile.cc b/src/arch/sparc/miscregfile.cc new file mode 100644 index 000000000..8041e45c0 --- /dev/null +++ b/src/arch/sparc/miscregfile.cc @@ -0,0 +1,540 @@ +/* + * 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. + * + * Authors: Gabe Black + * Ali Saidi + */ + +#include "arch/sparc/miscregfile.hh" +#include "base/trace.hh" +#include "cpu/base.hh" +#include "cpu/thread_context.hh" + +using namespace SparcISA; +using namespace std; + +class Checkpoint; + +//These functions map register indices to names +string SparcISA::getMiscRegName(RegIndex index) +{ + static::string miscRegName[NumMiscRegs] = + {"y", "ccr", "asi", "tick", "pc", "fprs", "pcr", "pic", + "gsr", "softint_set", "softint_clr", "softint", "tick_cmpr", + "stick", "stick_cmpr", + "tpc", "tnpc", "tstate", "tt", "privtick", "tba", "pstate", "tl", + "pil", "cwp", "cansave", "canrestore", "cleanwin", "otherwin", + "wstate", "gl", + "hpstate", "htstate", "hintp", "htba", "hver", "strand_sts_reg", + "hstick_cmpr", + "fsr"}; + return miscRegName[index]; +} + +#if FULL_SYSTEM + +//XXX These need an implementation someplace +/** Fullsystem only register version of ReadRegWithEffect() */ +MiscReg MiscRegFile::readFSRegWithEffect(int miscReg, Fault &fault, ThreadContext *tc); +/** Fullsystem only register version of SetRegWithEffect() */ +Fault MiscRegFile::setFSRegWithEffect(int miscReg, const MiscReg &val, + ThreadContext * tc); +#endif + +void MiscRegFile::reset() +{ + pstateFields.pef = 0; //No FPU + //pstateFields.pef = 1; //FPU +#if FULL_SYSTEM + //For SPARC, when a system is first started, there is a power + //on reset Trap which sets the processor into the following state. + //Bits that aren't set aren't defined on startup. + tl = MaxTL; + gl = MaxGL; + + tickFields.counter = 0; //The TICK register is unreadable bya + tickFields.npt = 1; //The TICK register is unreadable by by !priv + + softint = 0; // Clear all the soft interrupt bits + tick_cmprFields.int_dis = 1; // disable timer compare interrupts + tick_cmprFields.tick_cmpr = 0; // Reset to 0 for pretty printing + stickFields.npt = 1; //The TICK register is unreadable by by !priv + stick_cmprFields.int_dis = 1; // disable timer compare interrupts + stick_cmprFields.tick_cmpr = 0; // Reset to 0 for pretty printing + + + tt[tl] = power_on_reset; + pstate = 0; // fields 0 but pef + pstateFields.pef = 1; + + hpstate = 0; + hpstateFields.red = 1; + hpstateFields.hpriv = 1; + hpstateFields.tlz = 0; // this is a guess + hintp = 0; // no interrupts pending + hstick_cmprFields.int_dis = 1; // disable timer compare interrupts + hstick_cmprFields.tick_cmpr = 0; // Reset to 0 for pretty printing +#else +/* //This sets up the initial state of the processor for usermode processes + pstateFields.priv = 0; //Process runs in user mode + pstateFields.ie = 1; //Interrupts are enabled + fsrFields.rd = 0; //Round to nearest + fsrFields.tem = 0; //Floating point traps not enabled + fsrFields.ns = 0; //Non standard mode off + fsrFields.qne = 0; //Floating point queue is empty + fsrFields.aexc = 0; //No accrued exceptions + fsrFields.cexc = 0; //No current exceptions + + //Register window management registers + otherwin = 0; //No windows contain info from other programs + canrestore = 0; //There are no windows to pop + cansave = MaxTL - 2; //All windows are available to save into + cleanwin = MaxTL;*/ +#endif +} + +MiscReg MiscRegFile::readReg(int miscReg) +{ + switch (miscReg) { + case MISCREG_Y: + return y; + case MISCREG_CCR: + return ccr; + case MISCREG_ASI: + return asi; + case MISCREG_FPRS: + return fprs; + case MISCREG_TICK: + return tick; + case MISCREG_PCR: + case MISCREG_PIC: + panic("ASR number %d not implemented\n", miscReg - AsrStart); + case MISCREG_GSR: + return gsr; + case MISCREG_SOFTINT: + return softint; + case MISCREG_TICK_CMPR: + return tick_cmpr; + case MISCREG_STICK: + return stick; + case MISCREG_STICK_CMPR: + return stick_cmpr; + + /** Privilged Registers */ + case MISCREG_TPC: + return tpc[tl-1]; + case MISCREG_TNPC: + return tnpc[tl-1]; + case MISCREG_TSTATE: + return tstate[tl-1]; + case MISCREG_TT: + return tt[tl-1]; + case MISCREG_PRIVTICK: + panic("Priviliged access to tick registers not implemented\n"); + case MISCREG_TBA: + return tba; + case MISCREG_PSTATE: + return pstate; + case MISCREG_TL: + return tl; + case MISCREG_PIL: + return pil; + case MISCREG_CWP: + return cwp; + case MISCREG_CANSAVE: + return cansave; + case MISCREG_CANRESTORE: + return canrestore; + case MISCREG_CLEANWIN: + return cleanwin; + case MISCREG_OTHERWIN: + return otherwin; + case MISCREG_WSTATE: + return wstate; + case MISCREG_GL: + return gl; + + /** Hyper privileged registers */ + case MISCREG_HPSTATE: + return hpstate; + case MISCREG_HTSTATE: + return htstate[tl-1]; + case MISCREG_HINTP: + panic("HINTP not implemented\n"); + case MISCREG_HTBA: + return htba; + case MISCREG_HVER: + return NWindows | MaxTL << 8 | MaxGL << 16; + case MISCREG_STRAND_STS_REG: + return strandStatusReg; + case MISCREG_HSTICK_CMPR: + return hstick_cmpr; + + /** Floating Point Status Register */ + case MISCREG_FSR: + return fsr; + default: + panic("Miscellaneous register %d not implemented\n", miscReg); + } +} + +MiscReg MiscRegFile::readRegWithEffect(int miscReg, + Fault &fault, ThreadContext * tc) +{ + fault = NoFault; + switch (miscReg) { + case MISCREG_Y: + case MISCREG_CCR: + case MISCREG_ASI: + return readReg(miscReg); + + case MISCREG_TICK: + case MISCREG_PRIVTICK: + // Check for reading privilege + if (tickFields.npt && !isNonPriv()) { + fault = new PrivilegedAction; + return 0; + } + return tc->getCpuPtr()->curCycle() - tickFields.counter | + tickFields.npt << 63; + case MISCREG_PC: + return tc->readPC(); + case MISCREG_FPRS: + fault = new UnimpFault("FPU not implemented\n"); + return 0; + case MISCREG_PCR: + fault = new UnimpFault("Performance Instrumentation not impl\n"); + return 0; + case MISCREG_PIC: + fault = new UnimpFault("Performance Instrumentation not impl\n"); + return 0; + case MISCREG_GSR: + return readReg(miscReg); + + /** Privilged Registers */ + case MISCREG_TPC: + case MISCREG_TNPC: + case MISCREG_TSTATE: + case MISCREG_TT: + if (tl == 0) { + fault = new IllegalInstruction; + return 0; + } // NOTE THE FALL THROUGH! + case MISCREG_PSTATE: + case MISCREG_TL: + return readReg(miscReg); + + case MISCREG_TBA: + return readReg(miscReg) & ULL(~0x7FFF); + + case MISCREG_PIL: + + case MISCREG_CWP: + case MISCREG_CANSAVE: + case MISCREG_CANRESTORE: + case MISCREG_CLEANWIN: + case MISCREG_OTHERWIN: + case MISCREG_WSTATE: + case MISCREG_GL: + return readReg(miscReg); + + /** Floating Point Status Register */ + case MISCREG_FSR: + panic("Floating Point not implemented\n"); + default: +#if FULL_SYSTEM + return readFSRegWithEffect(miscReg, fault, tc); +#else + fault = new IllegalInstruction; + return 0; +#endif + } +} + +Fault MiscRegFile::setReg(int miscReg, const MiscReg &val) +{ + switch (miscReg) { + case MISCREG_Y: + y = val; + return NoFault; + case MISCREG_CCR: + ccr = val; + return NoFault; + case MISCREG_ASI: + asi = val; + return NoFault; + case MISCREG_FPRS: + fprs = val; + return NoFault; + case MISCREG_TICK: + tick = val; + return NoFault; + case MISCREG_PCR: + case MISCREG_PIC: + panic("ASR number %d not implemented\n", miscReg - AsrStart); + case MISCREG_GSR: + gsr = val; + case MISCREG_SOFTINT: + softint = val; + return NoFault; + case MISCREG_TICK_CMPR: + tick_cmpr = val; + return NoFault; + case MISCREG_STICK: + stick = val; + return NoFault; + case MISCREG_STICK_CMPR: + stick_cmpr = val; + return NoFault; + + /** Privilged Registers */ + case MISCREG_TPC: + tpc[tl-1] = val; + return NoFault; + case MISCREG_TNPC: + tnpc[tl-1] = val; + return NoFault; + case MISCREG_TSTATE: + tstate[tl-1] = val; + return NoFault; + case MISCREG_TT: + tt[tl-1] = val; + return NoFault; + case MISCREG_PRIVTICK: + panic("Priviliged access to tick regesiters not implemented\n"); + case MISCREG_TBA: + tba = val; + return NoFault; + case MISCREG_PSTATE: + pstate = val; + return NoFault; + case MISCREG_TL: + tl = val; + return NoFault; + case MISCREG_PIL: + pil = val; + return NoFault; + case MISCREG_CWP: + cwp = val; + return NoFault; + case MISCREG_CANSAVE: + cansave = val; + return NoFault; + case MISCREG_CANRESTORE: + canrestore = val; + return NoFault; + case MISCREG_CLEANWIN: + cleanwin = val; + return NoFault; + case MISCREG_OTHERWIN: + otherwin = val; + return NoFault; + case MISCREG_WSTATE: + wstate = val; + return NoFault; + case MISCREG_GL: + gl = val; + return NoFault; + + /** Hyper privileged registers */ + case MISCREG_HPSTATE: + hpstate = val; + return NoFault; + case MISCREG_HTSTATE: + htstate[tl-1] = val; + return NoFault; + case MISCREG_HINTP: + panic("HINTP not implemented\n"); + case MISCREG_HTBA: + htba = val; + return NoFault; + case MISCREG_STRAND_STS_REG: + strandStatusReg = val; + return NoFault; + case MISCREG_HSTICK_CMPR: + hstick_cmpr = val; + return NoFault; + + /** Floating Point Status Register */ + case MISCREG_FSR: + fsr = val; + return NoFault; + default: + panic("Miscellaneous register %d not implemented\n", miscReg); + } +} + +Fault MiscRegFile::setRegWithEffect(int miscReg, + const MiscReg &val, ThreadContext * tc) +{ + const uint64_t Bit64 = (1ULL << 63); + switch (miscReg) { + case MISCREG_Y: + case MISCREG_CCR: + case MISCREG_ASI: + setReg(miscReg, val); + return NoFault; + case MISCREG_PRIVTICK: + case MISCREG_TICK: + if (isNonPriv()) + return new PrivilegedOpcode; + if (isPriv()) + return new PrivilegedAction; + tickFields.counter = tc->getCpuPtr()->curCycle() - val & ~Bit64; + tickFields.npt = val & Bit64 ? 1 : 0; + return NoFault; + case MISCREG_PC: + return new IllegalInstruction; + case MISCREG_FPRS: + return new UnimpFault("FPU not implemented\n"); + case MISCREG_PCR: + return new UnimpFault("Performance Instrumentation not impl\n"); + case MISCREG_PIC: + return new UnimpFault("Performance Instrumentation not impl\n"); + case MISCREG_GSR: + return setReg(miscReg, val); + + /** Privilged Registers */ + case MISCREG_TPC: + case MISCREG_TNPC: + case MISCREG_TSTATE: + case MISCREG_TT: + if (tl == 0) + return new IllegalInstruction; + setReg(miscReg, val); + return NoFault; + + case MISCREG_TBA: + // clear lower 7 bits on writes. + setReg(miscReg, val & ULL(~0x7FFF)); + return NoFault; + + case MISCREG_PSTATE: + setReg(miscReg, val); + return NoFault; + + case MISCREG_TL: + if (isHyperPriv() && val > MaxTL) + setReg(miscReg, MaxTL); + else if (isPriv() && !isHyperPriv() && val > MaxPTL) + setReg(miscReg, MaxPTL); + else + setReg(miscReg, val); + return NoFault; + + case MISCREG_CWP: + tc->changeRegFileContext(CONTEXT_CWP, val); + case MISCREG_CANSAVE: + case MISCREG_CANRESTORE: + case MISCREG_CLEANWIN: + case MISCREG_OTHERWIN: + case MISCREG_WSTATE: + setReg(miscReg, val); + return NoFault; + + case MISCREG_GL: + int newval; + if (isHyperPriv() && val > MaxGL) + newval = MaxGL; + else if (isPriv() && !isHyperPriv() && val > MaxPGL) + newval = MaxPGL; + else + newval = val; + tc->changeRegFileContext(CONTEXT_GLOBALS, newval); + setReg(miscReg, newval); + return NoFault; + + /** Floating Point Status Register */ + case MISCREG_FSR: + panic("Floating Point not implemented\n"); + default: +#if FULL_SYSTEM + setFSRegWithEffect(miscReg, val, tc); +#else + return new IllegalInstruction; +#endif + } +} + +void MiscRegFile::serialize(std::ostream & os) +{ + SERIALIZE_SCALAR(pstate); + SERIALIZE_SCALAR(tba); + SERIALIZE_SCALAR(y); + SERIALIZE_SCALAR(pil); + SERIALIZE_SCALAR(gl); + SERIALIZE_SCALAR(cwp); + SERIALIZE_ARRAY(tt, MaxTL); + SERIALIZE_SCALAR(ccr); + SERIALIZE_SCALAR(asi); + SERIALIZE_SCALAR(tl); + SERIALIZE_ARRAY(tpc, MaxTL); + SERIALIZE_ARRAY(tnpc, MaxTL); + SERIALIZE_ARRAY(tstate, MaxTL); + SERIALIZE_SCALAR(tick); + SERIALIZE_SCALAR(cansave); + SERIALIZE_SCALAR(canrestore); + SERIALIZE_SCALAR(otherwin); + SERIALIZE_SCALAR(cleanwin); + SERIALIZE_SCALAR(wstate); + SERIALIZE_SCALAR(fsr); + SERIALIZE_SCALAR(fprs); + SERIALIZE_SCALAR(hpstate); + SERIALIZE_ARRAY(htstate, MaxTL); + SERIALIZE_SCALAR(htba); + SERIALIZE_SCALAR(hstick_cmpr); +} + +void MiscRegFile::unserialize(Checkpoint * cp, const std::string & section) +{ + UNSERIALIZE_SCALAR(pstate); + UNSERIALIZE_SCALAR(tba); + UNSERIALIZE_SCALAR(y); + UNSERIALIZE_SCALAR(pil); + UNSERIALIZE_SCALAR(gl); + UNSERIALIZE_SCALAR(cwp); + UNSERIALIZE_ARRAY(tt, MaxTL); + UNSERIALIZE_SCALAR(ccr); + UNSERIALIZE_SCALAR(asi); + UNSERIALIZE_SCALAR(tl); + UNSERIALIZE_ARRAY(tpc, MaxTL); + UNSERIALIZE_ARRAY(tnpc, MaxTL); + UNSERIALIZE_ARRAY(tstate, MaxTL); + UNSERIALIZE_SCALAR(tick); + UNSERIALIZE_SCALAR(cansave); + UNSERIALIZE_SCALAR(canrestore); + UNSERIALIZE_SCALAR(otherwin); + UNSERIALIZE_SCALAR(cleanwin); + UNSERIALIZE_SCALAR(wstate); + UNSERIALIZE_SCALAR(fsr); + UNSERIALIZE_SCALAR(fprs); + UNSERIALIZE_SCALAR(hpstate); + UNSERIALIZE_ARRAY(htstate, MaxTL); + UNSERIALIZE_SCALAR(htba); + UNSERIALIZE_SCALAR(hstick_cmpr); +} + diff --git a/src/arch/sparc/miscregfile.hh b/src/arch/sparc/miscregfile.hh new file mode 100644 index 000000000..be143311f --- /dev/null +++ b/src/arch/sparc/miscregfile.hh @@ -0,0 +1,410 @@ +/* + * 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. + * + * Authors: Gabe Black + * Ali Saidi + */ + +#ifndef __ARCH_SPARC_MISCREGFILE_HH__ +#define __ARCH_SPARC_MISCREGFILE_HH__ + +#include "arch/sparc/faults.hh" +#include "arch/sparc/isa_traits.hh" +#include "arch/sparc/types.hh" + +#include <string> + +namespace SparcISA +{ + + //These functions map register indices to names + std::string getMiscRegName(RegIndex); + + const int AsrStart = 0; + const int PrStart = 32; + const int HprStart = 64; + const int MiscStart = 96; + + enum MiscRegIndex + { + /** Ancillary State Registers */ + MISCREG_Y = AsrStart + 0, + MISCREG_CCR = AsrStart + 2, + MISCREG_ASI = AsrStart + 3, + MISCREG_TICK = AsrStart + 4, + MISCREG_PC = AsrStart + 5, + MISCREG_FPRS = AsrStart + 6, + MISCREG_PCR = AsrStart + 16, + MISCREG_PIC = AsrStart + 17, + MISCREG_GSR = AsrStart + 19, + MISCREG_SOFTINT_SET = AsrStart + 20, + MISCREG_SOFTINT_CLR = AsrStart + 21, + MISCREG_SOFTINT = AsrStart + 22, + MISCREG_TICK_CMPR = AsrStart + 23, + MISCREG_STICK = AsrStart + 24, + MISCREG_STICK_CMPR = AsrStart + 25, + + /** Privilged Registers */ + MISCREG_TPC = PrStart + 0, + MISCREG_TNPC = PrStart + 1, + MISCREG_TSTATE = PrStart + 2, + MISCREG_TT = PrStart + 3, + MISCREG_PRIVTICK = PrStart + 4, + MISCREG_TBA = PrStart + 5, + MISCREG_PSTATE = PrStart + 6, + MISCREG_TL = PrStart + 7, + MISCREG_PIL = PrStart + 8, + MISCREG_CWP = PrStart + 9, + MISCREG_CANSAVE = PrStart + 10, + MISCREG_CANRESTORE = PrStart + 11, + MISCREG_CLEANWIN = PrStart + 12, + MISCREG_OTHERWIN = PrStart + 13, + MISCREG_WSTATE = PrStart + 14, + MISCREG_GL = PrStart + 16, + + /** Hyper privileged registers */ + MISCREG_HPSTATE = HprStart + 0, + MISCREG_HTSTATE = HprStart + 1, + MISCREG_HINTP = HprStart + 3, + MISCREG_HTBA = HprStart + 5, + MISCREG_HVER = HprStart + 6, + MISCREG_STRAND_STS_REG = HprStart + 16, + MISCREG_HSTICK_CMPR = HprStart + 31, + + /** Floating Point Status Register */ + MISCREG_FSR = MiscStart + 0 + + }; + + // The control registers, broken out into fields + class MiscRegFile + { + private: + + /* ASR Registers */ + union { + uint64_t y; // Y (used in obsolete multiplication) + struct { + uint64_t value:32; // The actual value stored in y + uint64_t :32; // reserved bits + } yFields; + }; + union { + uint8_t ccr; // Condition Code Register + struct { + union { + uint8_t icc:4; // 32-bit condition codes + struct { + uint8_t c:1; // Carry + uint8_t v:1; // Overflow + uint8_t z:1; // Zero + uint8_t n:1; // Negative + } iccFields; + }; + union { + uint8_t xcc:4; // 64-bit condition codes + struct { + uint8_t c:1; // Carry + uint8_t v:1; // Overflow + uint8_t z:1; // Zero + uint8_t n:1; // Negative + } xccFields; + }; + } ccrFields; + }; + uint8_t asi; // Address Space Identifier + union { + uint64_t tick; // Hardware clock-tick counter + struct { + int64_t counter:63; // Clock-tick count + uint64_t npt:1; // Non-priveleged trap + } tickFields; + }; + union { + uint8_t fprs; // Floating-Point Register State + struct { + uint8_t dl:1; // Dirty lower + uint8_t du:1; // Dirty upper + uint8_t fef:1; // FPRS enable floating-Point + } fprsFields; + }; + union { + uint64_t gsr; //General Status Register + struct { + uint64_t mask:32; + uint64_t :4; + uint64_t im:1; + uint64_t irnd:2; + uint64_t :17; + uint64_t scale:5; + uint64_t align:3; + } gsrFields; + }; + union { + uint64_t softint; + struct { + uint64_t tm:1; + uint64_t int_level:14; + uint64_t sm:1; + } softintFields; + }; + union { + uint64_t tick_cmpr; // Hardware tick compare registers + struct { + uint64_t tick_cmpr:63; // Clock-tick count + uint64_t int_dis:1; // Non-priveleged trap + } tick_cmprFields; + }; + union { + uint64_t stick; // Hardware clock-tick counter + struct { + int64_t :63; // Not used, storage in SparcSystem + uint64_t npt:1; // Non-priveleged trap + } stickFields; + }; + union { + uint64_t stick_cmpr; // Hardware tick compare registers + struct { + uint64_t tick_cmpr:63; // Clock-tick count + uint64_t int_dis:1; // Non-priveleged trap + } stick_cmprFields; + }; + + + /* Privileged Registers */ + uint64_t tpc[MaxTL]; // Trap Program Counter (value from + // previous trap level) + uint64_t tnpc[MaxTL]; // Trap Next Program Counter (value from + // previous trap level) + union { + uint64_t tstate[MaxTL]; // Trap State + struct { + //Values are from previous trap level + uint64_t cwp:5; // Current Window Pointer + uint64_t :3; // Reserved bits + uint64_t pstate:13; // Process State + uint64_t :3; // Reserved bits + uint64_t asi:8; // Address Space Identifier + uint64_t ccr:8; // Condition Code Register + uint64_t gl:8; // Global level + } tstateFields[MaxTL]; + }; + uint16_t tt[MaxTL]; // Trap Type (Type of trap which occured + // on the previous level) + uint64_t tba; // Trap Base Address + + union { + uint16_t pstate; // Process State Register + struct { + uint16_t :1; // reserved + uint16_t ie:1; // Interrupt enable + uint16_t priv:1; // Privelege mode + uint16_t am:1; // Address mask + uint16_t pef:1; // PSTATE enable floating-point + uint16_t :1; // reserved2 + uint16_t mm:2; // Memory Model + uint16_t tle:1; // Trap little-endian + uint16_t cle:1; // Current little-endian + } pstateFields; + }; + uint8_t tl; // Trap Level + uint8_t pil; // Process Interrupt Register + uint8_t cwp; // Current Window Pointer + uint8_t cansave; // Savable windows + uint8_t canrestore; // Restorable windows + uint8_t cleanwin; // Clean windows + uint8_t otherwin; // Other windows + union { + uint8_t wstate; // Window State + struct { + uint8_t normal:3; // Bits TT<4:2> are set to on a normal + // register window trap + uint8_t other:3; // Bits TT<4:2> are set to on an "otherwin" + // register window trap + } wstateFields; + }; + uint8_t gl; // Global level register + + + /** Hyperprivileged Registers */ + union { + uint64_t hpstate; // Hyperprivileged State Register + struct { + uint8_t tlz: 1; + uint8_t :1; + uint8_t hpriv:1; + uint8_t :2; + uint8_t red:1; + uint8_t :4; + uint8_t ibe:1; + uint8_t id:1; + } hpstateFields; + }; + + uint64_t htstate[MaxTL]; // Hyperprivileged Trap State Register + uint64_t hintp; + uint64_t htba; // Hyperprivileged Trap Base Address register + union { + uint64_t hstick_cmpr; // Hardware tick compare registers + struct { + uint64_t tick_cmpr:63; // Clock-tick count + uint64_t int_dis:1; // Non-priveleged trap + } hstick_cmprFields; + }; + + uint64_t strandStatusReg; // Per strand status register + + + /** Floating point misc registers. */ + union { + uint64_t fsr; // Floating-Point State Register + struct { + union { + uint64_t cexc:5; // Current excpetion + struct { + uint64_t nxc:1; // Inexact + uint64_t dzc:1; // Divide by zero + uint64_t ufc:1; // Underflow + uint64_t ofc:1; // Overflow + uint64_t nvc:1; // Invalid operand + } cexcFields; + }; + union { + uint64_t aexc:5; // Accrued exception + struct { + uint64_t nxc:1; // Inexact + uint64_t dzc:1; // Divide by zero + uint64_t ufc:1; // Underflow + uint64_t ofc:1; // Overflow + uint64_t nvc:1; // Invalid operand + } aexcFields; + }; + uint64_t fcc0:2; // Floating-Point condtion codes + uint64_t :1; // Reserved bits + uint64_t qne:1; // Deferred trap queue not empty + // with no queue, it should read 0 + uint64_t ftt:3; // Floating-Point trap type + uint64_t ver:3; // Version (of the FPU) + uint64_t :2; // Reserved bits + uint64_t ns:1; // Nonstandard floating point + union { + uint64_t tem:5; // Trap Enable Mask + struct { + uint64_t nxm:1; // Inexact + uint64_t dzm:1; // Divide by zero + uint64_t ufm:1; // Underflow + uint64_t ofm:1; // Overflow + uint64_t nvm:1; // Invalid operand + } temFields; + }; + uint64_t :2; // Reserved bits + uint64_t rd:2; // Rounding direction + uint64_t fcc1:2; // Floating-Point condition codes + uint64_t fcc2:2; // Floating-Point condition codes + uint64_t fcc3:2; // Floating-Point condition codes + uint64_t :26; // Reserved bits + } fsrFields; + }; + + // These need to check the int_dis field and if 0 then + // set appropriate bit in softint and checkinterrutps on the cpu +#if FULL_SYSTEM + /** Process a tick compare event and generate an interrupt on the cpu if + * appropriate. */ + void processTickCompare(ThreadContext *tc); + void processSTickCompare(ThreadContext *tc); + void processHSTickCompare(ThreadContext *tc); + + typedef CpuEventWrapper<MiscRegFile, + &MiscRegFile::processTickCompare> TickCompareEvent; + TickCompareEvent *tickCompare; + + typedef CpuEventWrapper<MiscRegFile, + &MiscRegFile::processSTickCompare> STickCompareEvent; + STickCompareEvent *sTickCompare; + + typedef CpuEventWrapper<MiscRegFile, + &MiscRegFile::processHSTickCompare> HSTickCompareEvent; + HSTickCompareEvent *hSTickCompare; + + /** Fullsystem only register version of ReadRegWithEffect() */ + MiscReg readFSRegWithEffect(int miscReg, Fault &fault, ThreadContext *tc); + /** Fullsystem only register version of SetRegWithEffect() */ + Fault setFSRegWithEffect(int miscReg, const MiscReg &val, + ThreadContext * tc); +#endif + public: + + void reset(); + + MiscRegFile() + { + reset(); + } + + /** read a value out of an either an SE or FS IPR. No checking is done + * about SE vs. FS as this is mostly used to copy the regfile. Thus more + * register are copied that are necessary for FS. However this prevents + * a bunch of ifdefs and is rarely called so is not performance + * criticial. */ + MiscReg readReg(int miscReg); + + /** Read a value from an IPR. Only the SE iprs are here and the rest + * are are readFSRegWithEffect (which is called by readRegWithEffect()). + * Checking is done for permission based on state bits in the miscreg + * file. */ + MiscReg readRegWithEffect(int miscReg, Fault &fault, ThreadContext *tc); + + /** write a value into an either an SE or FS IPR. No checking is done + * about SE vs. FS as this is mostly used to copy the regfile. Thus more + * register are copied that are necessary for FS. However this prevents + * a bunch of ifdefs and is rarely called so is not performance + * criticial.*/ + Fault setReg(int miscReg, const MiscReg &val); + + /** Write a value into an IPR. Only the SE iprs are here and the rest + * are are setFSRegWithEffect (which is called by setRegWithEffect()). + * Checking is done for permission based on state bits in the miscreg + * file. */ + Fault setRegWithEffect(int miscReg, + const MiscReg &val, ThreadContext * tc); + + void serialize(std::ostream & os); + + void unserialize(Checkpoint * cp, const std::string & section); + + void copyMiscRegs(ThreadContext * tc); + + protected: + + bool isHyperPriv() { return hpstateFields.hpriv; } + bool isPriv() { return hpstateFields.hpriv || pstateFields.priv; } + bool isNonPriv() { return !isPriv(); } + }; +} + +#endif diff --git a/src/arch/sparc/process.cc b/src/arch/sparc/process.cc index 75f01e038..70c7e719f 100644 --- a/src/arch/sparc/process.cc +++ b/src/arch/sparc/process.cc @@ -32,6 +32,7 @@ #include "arch/sparc/isa_traits.hh" #include "arch/sparc/process.hh" #include "base/loader/object_file.hh" +#include "base/loader/elf_object.hh" #include "base/misc.hh" #include "cpu/thread_context.hh" #include "mem/page_table.hh" @@ -129,7 +130,8 @@ SparcLiveProcess::argsInit(int intSize, int pageSize) SPARC_AT_UID = 11, SPARC_AT_EUID = 12, SPARC_AT_GID = 13, - SPARC_AT_EGID = 14 + SPARC_AT_EGID = 14, + SPARC_AT_SECURE = 23 }; enum hardwareCaps @@ -153,31 +155,42 @@ SparcLiveProcess::argsInit(int intSize, int pageSize) M5_HWCAP_SPARC_V9 | M5_HWCAP_SPARC_ULTRA3; - //Setup the auxilliary vectors. These will already have - //endian conversion. - auxv.push_back(buildAuxVect(SPARC_AT_EGID, 100)); - auxv.push_back(buildAuxVect(SPARC_AT_GID, 100)); - auxv.push_back(buildAuxVect(SPARC_AT_EUID, 100)); - auxv.push_back(buildAuxVect(SPARC_AT_UID, 100)); - //This would work, but the entry point is a protected member - //auxv.push_back(buildAuxVect(SPARC_AT_ENTRY, objFile->entry)); - auxv.push_back(buildAuxVect(SPARC_AT_FLAGS, 0)); - //This is the address of the elf "interpreter", which I don't - //think we currently set up. It should be set to 0 (I think) - //auxv.push_back(buildAuxVect(SPARC_AT_BASE, 0)); - //This is the number of headers which were in the original elf - //file. This information isn't avaibale by this point. - //auxv.push_back(buildAuxVect(SPARC_AT_PHNUM, 3)); - //This is the size of a program header entry. This isn't easy - //to compute here. - //auxv.push_back(buildAuxVect(SPARC_AT_PHENT, blah)); - //This is should be set to load_addr (whatever that is) + - //e_phoff. I think it's a pointer to the program headers. - //auxv.push_back(buildAuxVect(SPARC_AT_PHDR, blah)); - //This should be easy to get right, but I won't set it for now - //auxv.push_back(buildAuxVect(SPARC_AT_CLKTCK, blah)); - auxv.push_back(buildAuxVect(SPARC_AT_PAGESZ, SparcISA::VMPageSize)); - auxv.push_back(buildAuxVect(SPARC_AT_HWCAP, hwcap)); + + //Setup the auxilliary vectors. These will already have endian conversion. + //Auxilliary vectors are loaded only for elf formatted executables. + ElfObject * elfObject = dynamic_cast<ElfObject *>(objFile); + if(elfObject) + { + //Bits which describe the system hardware capabilities + auxv.push_back(buildAuxVect(SPARC_AT_HWCAP, hwcap)); + //The system page size + auxv.push_back(buildAuxVect(SPARC_AT_PAGESZ, SparcISA::VMPageSize)); + //Defined to be 100 in the kernel source. + //Frequency at which times() increments + auxv.push_back(buildAuxVect(SPARC_AT_CLKTCK, 100)); + // For statically linked executables, this is the virtual address of the + // program header tables if they appear in the executable image + auxv.push_back(buildAuxVect(SPARC_AT_PHDR, elfObject->programHeaderTable())); + // This is the size of a program header entry from the elf file. + auxv.push_back(buildAuxVect(SPARC_AT_PHENT, elfObject->programHeaderSize())); + // This is the number of program headers from the original elf file. + auxv.push_back(buildAuxVect(SPARC_AT_PHNUM, elfObject->programHeaderCount())); + //This is the address of the elf "interpreter", It should be set + //to 0 for regular executables. It should be something else + //(not sure what) for dynamic libraries. + auxv.push_back(buildAuxVect(SPARC_AT_BASE, 0)); + //This is hardwired to 0 in the elf loading code in the kernel + auxv.push_back(buildAuxVect(SPARC_AT_FLAGS, 0)); + //The entry point to the program + auxv.push_back(buildAuxVect(SPARC_AT_ENTRY, objFile->entryPoint())); + //Different user and group IDs + auxv.push_back(buildAuxVect(SPARC_AT_UID, 100)); + auxv.push_back(buildAuxVect(SPARC_AT_EUID, 100)); + auxv.push_back(buildAuxVect(SPARC_AT_GID, 100)); + auxv.push_back(buildAuxVect(SPARC_AT_EGID, 100)); + //Whether to enable "secure mode" in the executable + auxv.push_back(buildAuxVect(SPARC_AT_SECURE, 0)); + } //Figure out how big the initial stack needs to be diff --git a/src/arch/sparc/regfile.cc b/src/arch/sparc/regfile.cc new file mode 100644 index 000000000..747426781 --- /dev/null +++ b/src/arch/sparc/regfile.cc @@ -0,0 +1,279 @@ +/* + * 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. + * + * Authors: Gabe Black + * Ali Saidi + */ + +#include "arch/sparc/regfile.hh" +#include "cpu/thread_context.hh" + +class Checkpoint; + +using namespace SparcISA; +using namespace std; + +//RegFile class methods +Addr RegFile::readPC() +{ + return pc; +} + +void RegFile::setPC(Addr val) +{ + pc = val; +} + +Addr RegFile::readNextPC() +{ + return npc; +} + +void RegFile::setNextPC(Addr val) +{ + npc = val; +} + +Addr RegFile::readNextNPC() +{ + return nnpc; +} + +void RegFile::setNextNPC(Addr val) +{ + nnpc = val; +} + +void RegFile::clear() +{ + intRegFile.clear(); + floatRegFile.clear(); +} + +MiscReg RegFile::readMiscReg(int miscReg) +{ + return miscRegFile.readReg(miscReg); +} + +MiscReg RegFile::readMiscRegWithEffect(int miscReg, + Fault &fault, ThreadContext *tc) +{ + return miscRegFile.readRegWithEffect(miscReg, fault, tc); +} + +Fault RegFile::setMiscReg(int miscReg, const MiscReg &val) +{ + return miscRegFile.setReg(miscReg, val); +} + +Fault RegFile::setMiscRegWithEffect(int miscReg, const MiscReg &val, + ThreadContext * tc) +{ + return miscRegFile.setRegWithEffect(miscReg, val, tc); +} + +FloatReg RegFile::readFloatReg(int floatReg, int width) +{ + return floatRegFile.readReg(floatReg, width); +} + +FloatReg RegFile::readFloatReg(int floatReg) +{ + //Use the "natural" width of a single float + return floatRegFile.readReg(floatReg, FloatRegFile::SingleWidth); +} + +FloatRegBits RegFile::readFloatRegBits(int floatReg, int width) +{ + return floatRegFile.readRegBits(floatReg, width); +} + +FloatRegBits RegFile::readFloatRegBits(int floatReg) +{ + //Use the "natural" width of a single float + return floatRegFile.readRegBits(floatReg, + FloatRegFile::SingleWidth); +} + +Fault RegFile::setFloatReg(int floatReg, const FloatReg &val, int width) +{ + return floatRegFile.setReg(floatReg, val, width); +} + +Fault RegFile::setFloatReg(int floatReg, const FloatReg &val) +{ + //Use the "natural" width of a single float + return setFloatReg(floatReg, val, FloatRegFile::SingleWidth); +} + +Fault RegFile::setFloatRegBits(int floatReg, const FloatRegBits &val, int width) +{ + return floatRegFile.setRegBits(floatReg, val, width); +} + +Fault RegFile::setFloatRegBits(int floatReg, const FloatRegBits &val) +{ + //Use the "natural" width of a single float + return floatRegFile.setRegBits(floatReg, val, + FloatRegFile::SingleWidth); +} + +IntReg RegFile::readIntReg(int intReg) +{ + return intRegFile.readReg(intReg); +} + +Fault RegFile::setIntReg(int intReg, const IntReg &val) +{ + return intRegFile.setReg(intReg, val); +} + +void RegFile::serialize(std::ostream &os) +{ + intRegFile.serialize(os); + floatRegFile.serialize(os); + miscRegFile.serialize(os); + SERIALIZE_SCALAR(pc); + SERIALIZE_SCALAR(npc); +} + +void RegFile::unserialize(Checkpoint *cp, const std::string §ion) +{ + intRegFile.unserialize(cp, section); + floatRegFile.unserialize(cp, section); + miscRegFile.unserialize(cp, section); + UNSERIALIZE_SCALAR(pc); + UNSERIALIZE_SCALAR(npc); +} + +void RegFile::changeContext(RegContextParam param, RegContextVal val) +{ + switch(param) + { + case CONTEXT_CWP: + intRegFile.setCWP(val); + break; + case CONTEXT_GLOBALS: + intRegFile.setGlobals(val); + break; + default: + panic("Tried to set illegal context parameter in the SPARC regfile.\n"); + } +} + +int SparcISA::InterruptLevel(uint64_t softint) +{ + if (softint & 0x10000 || softint & 0x1) + return 14; + + int level = 14; + while (level >= 0 && !(1 << (level + 1) & softint)) + level--; + if (1 << (level + 1) & softint) + return level; + return 0; +} + +void SparcISA::copyMiscRegs(ThreadContext *src, ThreadContext *dest) +{ + + uint8_t tl = src->readMiscReg(MISCREG_TL); + + // Read all the trap level dependent registers and save them off + for(int i = 1; i <= MaxTL; i++) + { + src->setMiscReg(MISCREG_TL, i); + dest->setMiscReg(MISCREG_TL, i); + + dest->setMiscReg(MISCREG_TT, src->readMiscReg(MISCREG_TT)); + dest->setMiscReg(MISCREG_TPC, src->readMiscReg(MISCREG_TPC)); + dest->setMiscReg(MISCREG_TNPC, src->readMiscReg(MISCREG_TNPC)); + dest->setMiscReg(MISCREG_TSTATE, src->readMiscReg(MISCREG_TSTATE)); + } + + // Save off the traplevel + dest->setMiscReg(MISCREG_TL, tl); + src->setMiscReg(MISCREG_TL, tl); + + + // ASRs + dest->setMiscReg(MISCREG_Y, src->readMiscReg(MISCREG_Y)); + dest->setMiscReg(MISCREG_CCR, src->readMiscReg(MISCREG_CCR)); + dest->setMiscReg(MISCREG_ASI, src->readMiscReg(MISCREG_ASI)); + dest->setMiscReg(MISCREG_TICK, src->readMiscReg(MISCREG_TICK)); + dest->setMiscReg(MISCREG_FPRS, src->readMiscReg(MISCREG_FPRS)); + dest->setMiscReg(MISCREG_SOFTINT, src->readMiscReg(MISCREG_SOFTINT)); + dest->setMiscReg(MISCREG_TICK_CMPR, src->readMiscReg(MISCREG_TICK_CMPR)); + dest->setMiscReg(MISCREG_STICK, src->readMiscReg(MISCREG_STICK)); + dest->setMiscReg(MISCREG_STICK_CMPR, src->readMiscReg(MISCREG_STICK_CMPR)); + + // Priv Registers + dest->setMiscReg(MISCREG_TICK, src->readMiscReg(MISCREG_TICK)); + dest->setMiscReg(MISCREG_TBA, src->readMiscReg(MISCREG_TBA)); + dest->setMiscReg(MISCREG_PSTATE, src->readMiscReg(MISCREG_PSTATE)); + dest->setMiscReg(MISCREG_PIL, src->readMiscReg(MISCREG_PIL)); + dest->setMiscReg(MISCREG_CWP, src->readMiscReg(MISCREG_CWP)); + dest->setMiscReg(MISCREG_CANSAVE, src->readMiscReg(MISCREG_CANSAVE)); + dest->setMiscReg(MISCREG_CANRESTORE, src->readMiscReg(MISCREG_CANRESTORE)); + dest->setMiscReg(MISCREG_OTHERWIN, src->readMiscReg(MISCREG_OTHERWIN)); + dest->setMiscReg(MISCREG_CLEANWIN, src->readMiscReg(MISCREG_CLEANWIN)); + dest->setMiscReg(MISCREG_WSTATE, src->readMiscReg(MISCREG_WSTATE)); + dest->setMiscReg(MISCREG_GL, src->readMiscReg(MISCREG_GL)); + + // Hyperprivilged registers + dest->setMiscReg(MISCREG_HPSTATE, src->readMiscReg(MISCREG_HPSTATE)); + dest->setMiscReg(MISCREG_HINTP, src->readMiscReg(MISCREG_HINTP)); + dest->setMiscReg(MISCREG_HTBA, src->readMiscReg(MISCREG_HTBA)); + dest->setMiscReg(MISCREG_STRAND_STS_REG, + src->readMiscReg(MISCREG_STRAND_STS_REG)); + dest->setMiscReg(MISCREG_HSTICK_CMPR, + src->readMiscReg(MISCREG_HSTICK_CMPR)); + + // FSR + dest->setMiscReg(MISCREG_FSR, src->readMiscReg(MISCREG_FSR)); +} + +void SparcISA::copyRegs(ThreadContext *src, ThreadContext *dest) +{ + // First loop through the integer registers. + for (int i = 0; i < TheISA::NumIntRegs; ++i) { + dest->setIntReg(i, src->readIntReg(i)); + } + + // Then loop through the floating point registers. + for (int i = 0; i < TheISA::NumFloatRegs; ++i) { + dest->setFloatRegBits(i, src->readFloatRegBits(i)); + } + + // Copy misc. registers + copyMiscRegs(src, dest); + + // Lastly copy PC/NPC + dest->setPC(src->readPC()); + dest->setNextPC(src->readNextPC()); + dest->setNextNPC(src->readNextNPC()); +} diff --git a/src/arch/sparc/regfile.hh b/src/arch/sparc/regfile.hh index cbeb3c7b9..500fbbba4 100644 --- a/src/arch/sparc/regfile.hh +++ b/src/arch/sparc/regfile.hh @@ -32,833 +32,84 @@ #ifndef __ARCH_SPARC_REGFILE_HH__ #define __ARCH_SPARC_REGFILE_HH__ -#include "arch/sparc/exceptions.hh" #include "arch/sparc/faults.hh" -#include "base/trace.hh" -#include "sim/byteswap.hh" -#include "cpu/cpuevent.hh" +#include "arch/sparc/floatregfile.hh" +#include "arch/sparc/intregfile.hh" +#include "arch/sparc/isa_traits.hh" +#include "arch/sparc/miscregfile.hh" +#include "arch/sparc/types.hh" #include "sim/host.hh" +#include <string> + class Checkpoint; namespace SparcISA { - - typedef uint8_t RegIndex; - - // MAXTL - maximum trap level - const int MaxPTL = 2; - const int MaxTL = 6; - const int MaxGL = 3; - const int MaxPGL = 2; - - // NWINDOWS - number of register windows, can be 3 to 32 - const int NWindows = 32; - - - const int AsrStart = 0; - const int PrStart = 32; - const int HprStart = 64; - const int MiscStart = 96; - - const uint64_t Bit64 = (1ULL << 63); - - class IntRegFile + class RegFile { protected: - static const int FrameOffsetBits = 3; - static const int FrameNumBits = 2; - - static const int RegsPerFrame = 1 << FrameOffsetBits; - static const int FrameNumMask = - (FrameNumBits == sizeof(int)) ? - (unsigned int)(-1) : - (1 << FrameNumBits) - 1; - static const int FrameOffsetMask = - (FrameOffsetBits == sizeof(int)) ? - (unsigned int)(-1) : - (1 << FrameOffsetBits) - 1; - - IntReg regGlobals[MaxGL][RegsPerFrame]; - IntReg regSegments[2 * NWindows][RegsPerFrame]; - - enum regFrame {Globals, Outputs, Locals, Inputs, NumFrames}; - - IntReg * regView[NumFrames]; - - static const int RegGlobalOffset = 0; - static const int FrameOffset = MaxGL * RegsPerFrame; - int offset[NumFrames]; + Addr pc; // Program Counter + Addr npc; // Next Program Counter + Addr nnpc; public: + Addr readPC(); + void setPC(Addr val); - int flattenIndex(int reg) - { - int flatIndex = offset[reg >> FrameOffsetBits] - | (reg & FrameOffsetMask); - DPRINTF(Sparc, "Flattened index %d into %d.\n", reg, flatIndex); - return flatIndex; - } - - void clear() - { - int x; - for (x = 0; x < MaxGL; x++) - memset(regGlobals[x], 0, sizeof(regGlobals[x])); - for(int x = 0; x < 2 * NWindows; x++) - bzero(regSegments[x], sizeof(regSegments[x])); - } - - IntRegFile() - { - offset[Globals] = 0; - regView[Globals] = regGlobals[0]; - setCWP(0); - clear(); - } - - IntReg readReg(int intReg) - { - IntReg val = - regView[intReg >> FrameOffsetBits][intReg & FrameOffsetMask]; - DPRINTF(Sparc, "Read register %d = 0x%x\n", intReg, val); - return val; - } - - Fault setReg(int intReg, const IntReg &val) - { - if(intReg) - DPRINTF(Sparc, "Wrote register %d = 0x%x\n", intReg, val); - regView[intReg >> FrameOffsetBits][intReg & FrameOffsetMask] = val; - return NoFault; - } - - //This doesn't effect the actual CWP register. - //It's purpose is to adjust the view of the register file - //to what it would be if CWP = cwp. - void setCWP(int cwp) - { - int index = ((NWindows - cwp) % NWindows) * 2; - offset[Outputs] = FrameOffset + (index * RegsPerFrame); - offset[Locals] = FrameOffset + ((index+1) * RegsPerFrame); - offset[Inputs] = FrameOffset + - (((index+2) % (NWindows * 2)) * RegsPerFrame); - regView[Outputs] = regSegments[index]; - regView[Locals] = regSegments[index+1]; - regView[Inputs] = regSegments[(index+2) % (NWindows * 2)]; - - DPRINTF(Sparc, "Changed the CWP value to %d\n", cwp); - } - - void setGlobals(int gl) - { - - DPRINTF(Sparc, "Now using %d globals", gl); - - regView[Globals] = regGlobals[gl]; - offset[Globals] = RegGlobalOffset + gl * RegsPerFrame; - } - - void serialize(std::ostream &os); - - void unserialize(Checkpoint *cp, const std::string §ion); - }; - - typedef float float32_t; - typedef double float64_t; - //FIXME long double refers to a 10 byte float, rather than a - //16 byte float as required. This data type may have to be emulated. - typedef double float128_t; + Addr readNextPC(); + void setNextPC(Addr val); - class FloatRegFile - { - public: - static const int SingleWidth = 32; - static const int DoubleWidth = 64; - static const int QuadWidth = 128; + Addr readNextNPC(); + void setNextNPC(Addr val); protected: - - //Since the floating point registers overlap each other, - //A generic storage space is used. The float to be returned is - //pulled from the appropriate section of this region. - char regSpace[SingleWidth / 8 * NumFloatRegs]; + IntRegFile intRegFile; // integer register file + FloatRegFile floatRegFile; // floating point register file + MiscRegFile miscRegFile; // control register file public: - void clear() - { - bzero(regSpace, sizeof(regSpace)); - } - - FloatReg readReg(int floatReg, int width) - { - //In each of these cases, we have to copy the value into a temporary - //variable. This is because we may otherwise try to access an - //unaligned portion of memory. - switch(width) - { - case SingleWidth: - float32_t result32; - memcpy(&result32, regSpace + 4 * floatReg, width); - return htog(result32); - case DoubleWidth: - float64_t result64; - memcpy(&result64, regSpace + 4 * floatReg, width); - return htog(result64); - case QuadWidth: - float128_t result128; - memcpy(&result128, regSpace + 4 * floatReg, width); - return htog(result128); - default: - panic("Attempted to read a %d bit floating point register!", width); - } - } - - FloatRegBits readRegBits(int floatReg, int width) - { - //In each of these cases, we have to copy the value into a temporary - //variable. This is because we may otherwise try to access an - //unaligned portion of memory. - switch(width) - { - case SingleWidth: - uint32_t result32; - memcpy(&result32, regSpace + 4 * floatReg, width); - return htog(result32); - case DoubleWidth: - uint64_t result64; - memcpy(&result64, regSpace + 4 * floatReg, width); - return htog(result64); - case QuadWidth: - uint64_t result128; - memcpy(&result128, regSpace + 4 * floatReg, width); - return htog(result128); - default: - panic("Attempted to read a %d bit floating point register!", width); - } - } - - Fault setReg(int floatReg, const FloatReg &val, int width) - { - //In each of these cases, we have to copy the value into a temporary - //variable. This is because we may otherwise try to access an - //unaligned portion of memory. - - uint32_t result32; - uint64_t result64; - switch(width) - { - case SingleWidth: - result32 = gtoh((uint32_t)val); - memcpy(regSpace + 4 * floatReg, &result32, width); - break; - case DoubleWidth: - result64 = gtoh((uint64_t)val); - memcpy(regSpace + 4 * floatReg, &result64, width); - break; - case QuadWidth: - panic("Quad width FP not implemented."); - break; - default: - panic("Attempted to read a %d bit floating point register!", width); - } - return NoFault; - } - - Fault setRegBits(int floatReg, const FloatRegBits &val, int width) - { - //In each of these cases, we have to copy the value into a temporary - //variable. This is because we may otherwise try to access an - //unaligned portion of memory. - uint32_t result32; - uint64_t result64; - switch(width) - { - case SingleWidth: - result32 = gtoh((uint32_t)val); - memcpy(regSpace + 4 * floatReg, &result32, width); - break; - case DoubleWidth: - result64 = gtoh((uint64_t)val); - memcpy(regSpace + 4 * floatReg, &result64, width); - break; - case QuadWidth: - panic("Quad width FP not implemented."); - break; - default: - panic("Attempted to read a %d bit floating point register!", width); - } - return NoFault; - } + void clear(); - void serialize(std::ostream &os); + int FlattenIntIndex(int reg); - void unserialize(Checkpoint *cp, const std::string §ion); - }; + MiscReg readMiscReg(int miscReg); - enum MiscRegIndex - { - /** Ancillary State Registers */ - MISCREG_Y = AsrStart + 0, - MISCREG_CCR = AsrStart + 2, - MISCREG_ASI = AsrStart + 3, - MISCREG_TICK = AsrStart + 4, - MISCREG_PC = AsrStart + 5, - MISCREG_FPRS = AsrStart + 6, - MISCREG_PCR = AsrStart + 16, - MISCREG_PIC = AsrStart + 17, - MISCREG_GSR = AsrStart + 19, - MISCREG_SOFTINT_SET = AsrStart + 20, - MISCREG_SOFTINT_CLR = AsrStart + 21, - MISCREG_SOFTINT = AsrStart + 22, - MISCREG_TICK_CMPR = AsrStart + 23, - MISCREG_STICK = AsrStart + 24, - MISCREG_STICK_CMPR = AsrStart + 25, - - /** Privilged Registers */ - MISCREG_TPC = PrStart + 0, - MISCREG_TNPC = PrStart + 1, - MISCREG_TSTATE = PrStart + 2, - MISCREG_TT = PrStart + 3, - MISCREG_PRIVTICK = PrStart + 4, - MISCREG_TBA = PrStart + 5, - MISCREG_PSTATE = PrStart + 6, - MISCREG_TL = PrStart + 7, - MISCREG_PIL = PrStart + 8, - MISCREG_CWP = PrStart + 9, - MISCREG_CANSAVE = PrStart + 10, - MISCREG_CANRESTORE = PrStart + 11, - MISCREG_CLEANWIN = PrStart + 12, - MISCREG_OTHERWIN = PrStart + 13, - MISCREG_WSTATE = PrStart + 14, - MISCREG_GL = PrStart + 16, - - /** Hyper privileged registers */ - MISCREG_HPSTATE = HprStart + 0, - MISCREG_HTSTATE = HprStart + 1, - MISCREG_HINTP = HprStart + 3, - MISCREG_HTBA = HprStart + 5, - MISCREG_HVER = HprStart + 6, - MISCREG_STRAND_STS_REG = HprStart + 16, - MISCREG_HSTICK_CMPR = HprStart + 31, - - /** Floating Point Status Register */ - MISCREG_FSR = MiscStart + 0 + MiscReg readMiscRegWithEffect(int miscReg, + Fault &fault, ThreadContext *tc); - }; + Fault setMiscReg(int miscReg, const MiscReg &val); - // The control registers, broken out into fields - class MiscRegFile - { - private: - - /* ASR Registers */ - union { - uint64_t y; // Y (used in obsolete multiplication) - struct { - uint64_t value:32; // The actual value stored in y - uint64_t :32; // reserved bits - } yFields; - }; - union { - uint8_t ccr; // Condition Code Register - struct { - union { - uint8_t icc:4; // 32-bit condition codes - struct { - uint8_t c:1; // Carry - uint8_t v:1; // Overflow - uint8_t z:1; // Zero - uint8_t n:1; // Negative - } iccFields; - }; - union { - uint8_t xcc:4; // 64-bit condition codes - struct { - uint8_t c:1; // Carry - uint8_t v:1; // Overflow - uint8_t z:1; // Zero - uint8_t n:1; // Negative - } xccFields; - }; - } ccrFields; - }; - uint8_t asi; // Address Space Identifier - union { - uint64_t tick; // Hardware clock-tick counter - struct { - int64_t counter:63; // Clock-tick count - uint64_t npt:1; // Non-priveleged trap - } tickFields; - }; - union { - uint8_t fprs; // Floating-Point Register State - struct { - uint8_t dl:1; // Dirty lower - uint8_t du:1; // Dirty upper - uint8_t fef:1; // FPRS enable floating-Point - } fprsFields; - }; - union { - uint64_t softint; - struct { - uint64_t tm:1; - uint64_t int_level:14; - uint64_t sm:1; - } softintFields; - }; - union { - uint64_t tick_cmpr; // Hardware tick compare registers - struct { - uint64_t tick_cmpr:63; // Clock-tick count - uint64_t int_dis:1; // Non-priveleged trap - } tick_cmprFields; - }; - union { - uint64_t stick; // Hardware clock-tick counter - struct { - int64_t :63; // Not used, storage in SparcSystem - uint64_t npt:1; // Non-priveleged trap - } stickFields; - }; - union { - uint64_t stick_cmpr; // Hardware tick compare registers - struct { - uint64_t tick_cmpr:63; // Clock-tick count - uint64_t int_dis:1; // Non-priveleged trap - } stick_cmprFields; - }; - - - /* Privileged Registers */ - uint64_t tpc[MaxTL]; // Trap Program Counter (value from - // previous trap level) - uint64_t tnpc[MaxTL]; // Trap Next Program Counter (value from - // previous trap level) - union { - uint64_t tstate[MaxTL]; // Trap State - struct { - //Values are from previous trap level - uint64_t cwp:5; // Current Window Pointer - uint64_t :3; // Reserved bits - uint64_t pstate:13; // Process State - uint64_t :3; // Reserved bits - uint64_t asi:8; // Address Space Identifier - uint64_t ccr:8; // Condition Code Register - uint64_t gl:8; // Global level - } tstateFields[MaxTL]; - }; - uint16_t tt[MaxTL]; // Trap Type (Type of trap which occured - // on the previous level) - uint64_t tba; // Trap Base Address - - union { - uint16_t pstate; // Process State Register - struct { - uint16_t :1; // reserved - uint16_t ie:1; // Interrupt enable - uint16_t priv:1; // Privelege mode - uint16_t am:1; // Address mask - uint16_t pef:1; // PSTATE enable floating-point - uint16_t :1; // reserved2 - uint16_t mm:2; // Memory Model - uint16_t tle:1; // Trap little-endian - uint16_t cle:1; // Current little-endian - } pstateFields; - }; - uint8_t tl; // Trap Level - uint8_t pil; // Process Interrupt Register - uint8_t cwp; // Current Window Pointer - uint8_t cansave; // Savable windows - uint8_t canrestore; // Restorable windows - uint8_t cleanwin; // Clean windows - uint8_t otherwin; // Other windows - union { - uint8_t wstate; // Window State - struct { - uint8_t normal:3; // Bits TT<4:2> are set to on a normal - // register window trap - uint8_t other:3; // Bits TT<4:2> are set to on an "otherwin" - // register window trap - } wstateFields; - }; - uint8_t gl; // Global level register - - - /** Hyperprivileged Registers */ - union { - uint64_t hpstate; // Hyperprivileged State Register - struct { - uint8_t tlz: 1; - uint8_t :1; - uint8_t hpriv:1; - uint8_t :2; - uint8_t red:1; - uint8_t :4; - uint8_t ibe:1; - uint8_t id:1; - } hpstateFields; - }; - - uint64_t htstate[MaxTL]; // Hyperprivileged Trap State Register - uint64_t hintp; - uint64_t htba; // Hyperprivileged Trap Base Address register - union { - uint64_t hstick_cmpr; // Hardware tick compare registers - struct { - uint64_t tick_cmpr:63; // Clock-tick count - uint64_t int_dis:1; // Non-priveleged trap - } hstick_cmprFields; - }; - - uint64_t strandStatusReg; // Per strand status register - - - /** Floating point misc registers. */ - union { - uint64_t fsr; // Floating-Point State Register - struct { - union { - uint64_t cexc:5; // Current excpetion - struct { - uint64_t nxc:1; // Inexact - uint64_t dzc:1; // Divide by zero - uint64_t ufc:1; // Underflow - uint64_t ofc:1; // Overflow - uint64_t nvc:1; // Invalid operand - } cexcFields; - }; - union { - uint64_t aexc:5; // Accrued exception - struct { - uint64_t nxc:1; // Inexact - uint64_t dzc:1; // Divide by zero - uint64_t ufc:1; // Underflow - uint64_t ofc:1; // Overflow - uint64_t nvc:1; // Invalid operand - } aexcFields; - }; - uint64_t fcc0:2; // Floating-Point condtion codes - uint64_t :1; // Reserved bits - uint64_t qne:1; // Deferred trap queue not empty - // with no queue, it should read 0 - uint64_t ftt:3; // Floating-Point trap type - uint64_t ver:3; // Version (of the FPU) - uint64_t :2; // Reserved bits - uint64_t ns:1; // Nonstandard floating point - union { - uint64_t tem:5; // Trap Enable Mask - struct { - uint64_t nxm:1; // Inexact - uint64_t dzm:1; // Divide by zero - uint64_t ufm:1; // Underflow - uint64_t ofm:1; // Overflow - uint64_t nvm:1; // Invalid operand - } temFields; - }; - uint64_t :2; // Reserved bits - uint64_t rd:2; // Rounding direction - uint64_t fcc1:2; // Floating-Point condition codes - uint64_t fcc2:2; // Floating-Point condition codes - uint64_t fcc3:2; // Floating-Point condition codes - uint64_t :26; // Reserved bits - } fsrFields; - }; - - // These need to check the int_dis field and if 0 then - // set appropriate bit in softint and checkinterrutps on the cpu -#if FULL_SYSTEM - /** Process a tick compare event and generate an interrupt on the cpu if - * appropriate. */ - void processTickCompare(ThreadContext *tc); - void processSTickCompare(ThreadContext *tc); - void processHSTickCompare(ThreadContext *tc); - - typedef CpuEventWrapper<MiscRegFile, - &MiscRegFile::processTickCompare> TickCompareEvent; - TickCompareEvent *tickCompare; - - typedef CpuEventWrapper<MiscRegFile, - &MiscRegFile::processSTickCompare> STickCompareEvent; - STickCompareEvent *sTickCompare; - - typedef CpuEventWrapper<MiscRegFile, - &MiscRegFile::processHSTickCompare> HSTickCompareEvent; - HSTickCompareEvent *hSTickCompare; - - /** Fullsystem only register version of ReadRegWithEffect() */ - MiscReg readFSRegWithEffect(int miscReg, Fault &fault, ThreadContext *tc); - /** Fullsystem only register version of SetRegWithEffect() */ - Fault setFSRegWithEffect(int miscReg, const MiscReg &val, + Fault setMiscRegWithEffect(int miscReg, const MiscReg &val, ThreadContext * tc); -#endif - public: - void reset() - { - pstateFields.pef = 0; //No FPU - //pstateFields.pef = 1; //FPU -#if FULL_SYSTEM - //For SPARC, when a system is first started, there is a power - //on reset Trap which sets the processor into the following state. - //Bits that aren't set aren't defined on startup. - tl = MaxTL; - gl = MaxGL; - - tickFields.counter = 0; //The TICK register is unreadable bya - tickFields.npt = 1; //The TICK register is unreadable by by !priv - - softint = 0; // Clear all the soft interrupt bits - tick_cmprFields.int_dis = 1; // disable timer compare interrupts - tick_cmprFields.tick_cmpr = 0; // Reset to 0 for pretty printing - stickFields.npt = 1; //The TICK register is unreadable by by !priv - stick_cmprFields.int_dis = 1; // disable timer compare interrupts - stick_cmprFields.tick_cmpr = 0; // Reset to 0 for pretty printing - - - tt[tl] = power_on_reset; - pstate = 0; // fields 0 but pef - pstateFields.pef = 1; - - hpstate = 0; - hpstateFields.red = 1; - hpstateFields.hpriv = 1; - hpstateFields.tlz = 0; // this is a guess - - hintp = 0; // no interrupts pending - hstick_cmprFields.int_dis = 1; // disable timer compare interrupts - hstick_cmprFields.tick_cmpr = 0; // Reset to 0 for pretty printing - -#else -/* //This sets up the initial state of the processor for usermode processes - pstateFields.priv = 0; //Process runs in user mode - pstateFields.ie = 1; //Interrupts are enabled - fsrFields.rd = 0; //Round to nearest - fsrFields.tem = 0; //Floating point traps not enabled - fsrFields.ns = 0; //Non standard mode off - fsrFields.qne = 0; //Floating point queue is empty - fsrFields.aexc = 0; //No accrued exceptions - fsrFields.cexc = 0; //No current exceptions - - //Register window management registers - otherwin = 0; //No windows contain info from other programs - canrestore = 0; //There are no windows to pop - cansave = MaxTL - 2; //All windows are available to save into - cleanwin = MaxTL;*/ -#endif - } - - MiscRegFile() - { - reset(); - } - - /** read a value out of an either an SE or FS IPR. No checking is done - * about SE vs. FS as this is mostly used to copy the regfile. Thus more - * register are copied that are necessary for FS. However this prevents - * a bunch of ifdefs and is rarely called so is not performance - * criticial. */ - MiscReg readReg(int miscReg); - - /** Read a value from an IPR. Only the SE iprs are here and the rest - * are are readFSRegWithEffect (which is called by readRegWithEffect()). - * Checking is done for permission based on state bits in the miscreg - * file. */ - MiscReg readRegWithEffect(int miscReg, Fault &fault, ThreadContext *tc); - - /** write a value into an either an SE or FS IPR. No checking is done - * about SE vs. FS as this is mostly used to copy the regfile. Thus more - * register are copied that are necessary for FS. However this prevents - * a bunch of ifdefs and is rarely called so is not performance - * criticial.*/ - Fault setReg(int miscReg, const MiscReg &val); - - /** Write a value into an IPR. Only the SE iprs are here and the rest - * are are setFSRegWithEffect (which is called by setRegWithEffect()). - * Checking is done for permission based on state bits in the miscreg - * file. */ - Fault setRegWithEffect(int miscReg, - const MiscReg &val, ThreadContext * tc); - - void serialize(std::ostream & os); - - void unserialize(Checkpoint * cp, const std::string & section); - - void copyMiscRegs(ThreadContext * tc); - - bool isHyperPriv() { return hpstateFields.hpriv; } - bool isPriv() { return hpstateFields.hpriv || pstateFields.priv; } - bool isNonPriv() { return !isPriv(); } - }; + FloatReg readFloatReg(int floatReg, int width); - typedef union - { - IntReg intreg; - FloatReg fpreg; - MiscReg ctrlreg; - } AnyReg; + FloatReg readFloatReg(int floatReg); - class RegFile - { - protected: - Addr pc; // Program Counter - Addr npc; // Next Program Counter - Addr nnpc; - - public: - Addr readPC() - { - return pc; - } - - void setPC(Addr val) - { - pc = val; - } - - Addr readNextPC() - { - return npc; - } - - void setNextPC(Addr val) - { - npc = val; - } - - Addr readNextNPC() - { - return nnpc; - } - - void setNextNPC(Addr val) - { - nnpc = val; - } - - protected: - IntRegFile intRegFile; // integer register file - FloatRegFile floatRegFile; // floating point register file - MiscRegFile miscRegFile; // control register file + FloatRegBits readFloatRegBits(int floatReg, int width); - public: + FloatRegBits readFloatRegBits(int floatReg); - void clear() - { - intRegFile.clear(); - floatRegFile.clear(); - } + Fault setFloatReg(int floatReg, const FloatReg &val, int width); - int FlattenIntIndex(int reg) - { - return intRegFile.flattenIndex(reg); - } + Fault setFloatReg(int floatReg, const FloatReg &val); - MiscReg readMiscReg(int miscReg) - { - return miscRegFile.readReg(miscReg); - } + Fault setFloatRegBits(int floatReg, const FloatRegBits &val, int width); - MiscReg readMiscRegWithEffect(int miscReg, - Fault &fault, ThreadContext *tc) - { - return miscRegFile.readRegWithEffect(miscReg, fault, tc); - } + Fault setFloatRegBits(int floatReg, const FloatRegBits &val); - Fault setMiscReg(int miscReg, const MiscReg &val) - { - return miscRegFile.setReg(miscReg, val); - } + IntReg readIntReg(int intReg); - Fault setMiscRegWithEffect(int miscReg, const MiscReg &val, - ThreadContext * tc) - { - return miscRegFile.setRegWithEffect(miscReg, val, tc); - } - - FloatReg readFloatReg(int floatReg, int width) - { - return floatRegFile.readReg(floatReg, width); - } - - FloatReg readFloatReg(int floatReg) - { - //Use the "natural" width of a single float - return floatRegFile.readReg(floatReg, FloatRegFile::SingleWidth); - } - - FloatRegBits readFloatRegBits(int floatReg, int width) - { - return floatRegFile.readRegBits(floatReg, width); - } - - FloatRegBits readFloatRegBits(int floatReg) - { - //Use the "natural" width of a single float - return floatRegFile.readRegBits(floatReg, - FloatRegFile::SingleWidth); - } - - Fault setFloatReg(int floatReg, const FloatReg &val, int width) - { - return floatRegFile.setReg(floatReg, val, width); - } - - Fault setFloatReg(int floatReg, const FloatReg &val) - { - //Use the "natural" width of a single float - return setFloatReg(floatReg, val, FloatRegFile::SingleWidth); - } - - Fault setFloatRegBits(int floatReg, const FloatRegBits &val, int width) - { - return floatRegFile.setRegBits(floatReg, val, width); - } - - Fault setFloatRegBits(int floatReg, const FloatRegBits &val) - { - //Use the "natural" width of a single float - return floatRegFile.setRegBits(floatReg, val, - FloatRegFile::SingleWidth); - } - - IntReg readIntReg(int intReg) - { - return intRegFile.readReg(intReg); - } - - Fault setIntReg(int intReg, const IntReg &val) - { - return intRegFile.setReg(intReg, val); - } + Fault setIntReg(int intReg, const IntReg &val); void serialize(std::ostream &os); void unserialize(Checkpoint *cp, const std::string §ion); public: - enum ContextParam - { - CONTEXT_CWP, - CONTEXT_GLOBALS - }; - typedef int ContextVal; - - void changeContext(ContextParam param, ContextVal val) - { - switch(param) - { - case CONTEXT_CWP: - intRegFile.setCWP(val); - break; - case CONTEXT_GLOBALS: - intRegFile.setGlobals(val); - break; - default: - panic("Tried to set illegal context parameter in the SPARC regfile.\n"); - } - } + void changeContext(RegContextParam param, RegContextVal val); }; void copyRegs(ThreadContext *src, ThreadContext *dest); diff --git a/src/arch/sparc/solaris/solaris.cc b/src/arch/sparc/solaris/solaris.cc index c588925b0..c53caa72a 100644 --- a/src/arch/sparc/solaris/solaris.cc +++ b/src/arch/sparc/solaris/solaris.cc @@ -30,6 +30,8 @@ #include "arch/sparc/solaris/solaris.hh" +#include <fcntl.h> + // open(2) flags translation table OpenFlagTransTable SparcSolaris::openFlagTable[] = { #ifdef _MSC_VER diff --git a/src/arch/sparc/stacktrace.hh b/src/arch/sparc/stacktrace.hh index d12aee211..54d3d17be 100644 --- a/src/arch/sparc/stacktrace.hh +++ b/src/arch/sparc/stacktrace.hh @@ -28,8 +28,8 @@ * Authors: Nathan Binkert */ -#ifndef __ARCH_ALPHA_STACKTRACE_HH__ -#define __ARCH_ALPHA_STACKTRACE_HH__ +#ifndef __ARCH_SPARC_STACKTRACE_HH__ +#define __ARCH_SPARC_STACKTRACE_HH__ #include "base/trace.hh" #include "cpu/static_inst.hh" @@ -118,4 +118,4 @@ StackTrace::trace(ThreadContext *tc, StaticInstPtr inst) return true; } -#endif // __ARCH_ALPHA_STACKTRACE_HH__ +#endif // __ARCH_SPARC_STACKTRACE_HH__ diff --git a/src/arch/sparc/syscallreturn.hh b/src/arch/sparc/syscallreturn.hh new file mode 100644 index 000000000..d850f4b65 --- /dev/null +++ b/src/arch/sparc/syscallreturn.hh @@ -0,0 +1,92 @@ +/* + * 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. + * + * Authors: Gabe Black + */ + +#ifndef __ARCH_SPARC_SYSCALLRETURN_HH__ +#define __ARCH_SPARC_SYSCALLRETURN_HH__ + +#include <inttypes.h> + +#include "arch/sparc/regfile.hh" + +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; +}; + +namespace SparcISA +{ + static inline void setSyscallReturn(SyscallReturn return_value, + RegFile *regs) + { + // check for error condition. SPARC syscall convention is to + // indicate success/failure in reg the carry bit of the ccr + // and put the return value itself in the standard return value reg (). + if (return_value.successful()) { + // no error, clear XCC.C + regs->setMiscReg(MISCREG_CCR, regs->readMiscReg(MISCREG_CCR) & 0xEF); + regs->setIntReg(ReturnValueReg, return_value.value()); + } else { + // got an error, set XCC.C + regs->setMiscReg(MISCREG_CCR, regs->readMiscReg(MISCREG_CCR) | 0x10); + regs->setIntReg(ReturnValueReg, return_value.value()); + } + } +}; + +#endif diff --git a/src/arch/sparc/system.cc b/src/arch/sparc/system.cc index e197e7918..63cbbe057 100644 --- a/src/arch/sparc/system.cc +++ b/src/arch/sparc/system.cc @@ -141,6 +141,7 @@ SparcSystem::unserialize(Checkpoint *cp, const std::string §ion) BEGIN_DECLARE_SIM_OBJECT_PARAMS(SparcSystem) SimObjectParam<PhysicalMemory *> physmem; + SimpleEnumParam<System::MemoryMode> mem_mode; Param<std::string> kernel; Param<std::string> reset_bin; @@ -161,6 +162,8 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(SparcSystem) INIT_PARAM(boot_cpu_frequency, "Frequency of the boot CPU"), INIT_PARAM(physmem, "phsyical memory"), + INIT_ENUM_PARAM(mem_mode, "Memory Mode, (1=atomic, 2=timing)", + System::MemoryModeStrings), INIT_PARAM(kernel, "file that contains the kernel code"), INIT_PARAM(reset_bin, "file that contains the reset code"), INIT_PARAM(hypervisor_bin, "file that contains the hypervisor code"), @@ -183,6 +186,7 @@ CREATE_SIM_OBJECT(SparcSystem) p->name = getInstanceName(); p->boot_cpu_frequency = boot_cpu_frequency; p->physmem = physmem; + p->mem_mode = mem_mode; p->kernel_path = kernel; p->reset_bin = reset_bin; p->hypervisor_bin = hypervisor_bin; diff --git a/src/arch/sparc/types.hh b/src/arch/sparc/types.hh new file mode 100644 index 000000000..88fb24153 --- /dev/null +++ b/src/arch/sparc/types.hh @@ -0,0 +1,63 @@ +/* + * 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. + * + * Authors: Gabe Black + */ + +#ifndef __ARCH_SPARC_TYPES_HH__ +#define __ARCH_SPARC_TYPES_HH__ + +#include <inttypes.h> + +namespace SparcISA +{ + typedef uint32_t MachInst; + typedef uint64_t ExtMachInst; + + typedef uint64_t IntReg; + typedef uint64_t MiscReg; + typedef double FloatReg; + typedef uint64_t FloatRegBits; + typedef union + { + IntReg intReg; + FloatReg fpreg; + MiscReg ctrlreg; + } AnyReg; + + enum RegContextParam + { + CONTEXT_CWP, + CONTEXT_GLOBALS + }; + + typedef int RegContextVal; + + typedef uint8_t RegIndex; +} + +#endif diff --git a/src/arch/sparc/ua2005.cc b/src/arch/sparc/ua2005.cc index b89d48663..6493ddfd5 100644 --- a/src/arch/sparc/ua2005.cc +++ b/src/arch/sparc/ua2005.cc @@ -37,7 +37,7 @@ SparcISA::MiscRegFile::setFSRegWithEffect(int miscReg, const MiscReg &val, int64_t time; SparcSystem *sys; switch (miscReg) { - /** Full system only ASRs */ + /* Full system only ASRs */ case MISCREG_SOFTINT: if (isNonPriv()) return new PrivilegedOpcode; @@ -94,7 +94,7 @@ SparcISA::MiscRegFile::setFSRegWithEffect(int miscReg, const MiscReg &val, sTickCompare.schedule(time * Clock::Int::ns); return NoFault; - /** Fullsystem only Priv registers. */ + /* Fullsystem only Priv registers. */ case MISCREG_PIL: if (FULL_SYSTEM) { setReg(miscReg, val); @@ -104,7 +104,7 @@ SparcISA::MiscRegFile::setFSRegWithEffect(int miscReg, const MiscReg &val, } else panic("PIL not implemented for syscall emulation\n"); - /** Hyper privileged registers */ + /* Hyper privileged registers */ case MISCREG_HPSTATE: case MISCREG_HINTP: setReg(miscReg, val); @@ -147,7 +147,7 @@ MiscRegFile::readFSRegWithEffect(int miscReg, Fault &fault, ThreadContext * tc) { switch (miscReg) { - /** Privileged registers. */ + /* Privileged registers. */ case MISCREG_SOFTINT: if (isNonPriv()) { fault = new PrivilegedOpcode; @@ -177,7 +177,7 @@ MiscRegFile::readFSRegWithEffect(int miscReg, Fault &fault, ThreadContext * tc) return readReg(miscReg); - /** Hyper privileged registers */ + /* Hyper privileged registers */ case MISCREG_HPSTATE: case MISCREG_HINTP: return readReg(miscReg); |