diff options
author | Stephen Hines <hines@cs.fsu.edu> | 2009-04-05 18:53:15 -0700 |
---|---|---|
committer | Stephen Hines <hines@cs.fsu.edu> | 2009-04-05 18:53:15 -0700 |
commit | 7a7c4c5fca83a8d47c7e71c9c080a882ebe204a9 (patch) | |
tree | 727269d84fb4ba0e7db6e1c7ffdeb3e114b71773 /src/arch | |
parent | 65332ef3a9df48f7ff11b417b0ffc4a171824931 (diff) | |
download | gem5-7a7c4c5fca83a8d47c7e71c9c080a882ebe204a9.tar.xz |
arm: add ARM support to M5
Diffstat (limited to 'src/arch')
51 files changed, 8822 insertions, 0 deletions
diff --git a/src/arch/arm/ArmTLB.py b/src/arch/arm/ArmTLB.py new file mode 100644 index 000000000..21253edef --- /dev/null +++ b/src/arch/arm/ArmTLB.py @@ -0,0 +1,58 @@ +# -*- mode:python -*- + +# Copyright (c) 2007-2008 The Florida State University +# 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: Stephen Hines + +from m5.SimObject import SimObject +from m5.params import * + +class ArmTLB(SimObject): + abstract = True + type = 'ArmTLB' + cxx_namespace = 'ArmISA' + cxx_class = 'TLB' + size = Param.Int("TLB size") + +class ArmDTB(ArmTLB): + type = 'ArmDTB' + cxx_namespace = 'ArmISA' + cxx_class = 'DTB' + size = 64 + +class ArmITB(ArmTLB): + type = 'ArmITB' + cxx_namespace = 'ArmISA' + cxx_class = 'ITB' + size = 64 + +class ArmUTB(ArmTLB): + type = 'ArmUTB' + cxx_namespace = 'ArmISA' + cxx_class = 'UTB' + size = 64 + diff --git a/src/arch/arm/SConscript b/src/arch/arm/SConscript new file mode 100644 index 000000000..d56373225 --- /dev/null +++ b/src/arch/arm/SConscript @@ -0,0 +1,61 @@ +# -*- mode:python -*- + +# Copyright (c) 2007-2008 The Florida State University +# 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: Stephen Hines + +Import('*') + +if env['TARGET_ISA'] == 'arm': +# Workaround for bug in SCons version > 0.97d20071212 +# Scons bug id: 2006 M5 Bug id: 308 + Dir('isa/formats') + Source('faults.cc') + Source('pagetable.cc') + Source('regfile/regfile.cc') + Source('tlb.cc') + Source('utility.cc') + Source('vtophys.cc') + + SimObject('ArmTLB.py') + TraceFlag('Arm') + + if env['FULL_SYSTEM']: + #Insert Full-System Files Here + pass + else: + Source('process.cc') + Source('linux/linux.cc') + Source('linux/process.cc') + + # Add in files generated by the ISA description. + isa_desc_files = env.ISADesc('isa/main.isa') + # Only non-header files need to be compiled. + for f in isa_desc_files: + if not f.path.endswith('.hh'): + Source(f) + diff --git a/src/arch/arm/SConsopts b/src/arch/arm/SConsopts new file mode 100644 index 000000000..fd9516929 --- /dev/null +++ b/src/arch/arm/SConsopts @@ -0,0 +1,33 @@ +# -*- mode:python -*- + +# Copyright (c) 2007-2008 The Florida State University +# 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: Stephen Hines + +Import('*') + +all_isa_list.append('arm') diff --git a/src/arch/arm/faults.cc b/src/arch/arm/faults.cc new file mode 100644 index 000000000..b79c09174 --- /dev/null +++ b/src/arch/arm/faults.cc @@ -0,0 +1,515 @@ +/* + * Copyright (c) 2003-2005 The Regents of The University of Michigan + * Copyright (c) 2007-2008 The Florida State University + * 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 + * Stephen Hines + */ + +#include "arch/arm/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" +#endif + +namespace ArmISA +{ + +FaultName MachineCheckFault::_name = "Machine Check"; +FaultVect MachineCheckFault::_vect = 0x0401; +FaultStat MachineCheckFault::_count; + +FaultName AlignmentFault::_name = "Alignment"; +FaultVect AlignmentFault::_vect = 0x0301; +FaultStat AlignmentFault::_count; + +FaultName ResetFault::_name = "Reset Fault"; +#if FULL_SYSTEM +FaultVect ResetFault::_vect = 0xBFC00000; +#else +FaultVect ResetFault::_vect = 0x001; +#endif +FaultStat ResetFault::_count; + +FaultName AddressErrorFault::_name = "Address Error"; +FaultVect AddressErrorFault::_vect = 0x0180; +FaultStat AddressErrorFault::_count; + +FaultName StoreAddressErrorFault::_name = "Store Address Error"; +FaultVect StoreAddressErrorFault::_vect = 0x0180; +FaultStat StoreAddressErrorFault::_count; + + +FaultName SystemCallFault::_name = "Syscall"; +FaultVect SystemCallFault::_vect = 0x0180; +FaultStat SystemCallFault::_count; + +FaultName CoprocessorUnusableFault::_name = "Coprocessor Unusable Fault"; +FaultVect CoprocessorUnusableFault::_vect = 0x180; +FaultStat CoprocessorUnusableFault::_count; + +FaultName ReservedInstructionFault::_name = "Reserved Instruction Fault"; +FaultVect ReservedInstructionFault::_vect = 0x0180; +FaultStat ReservedInstructionFault::_count; + +FaultName ThreadFault::_name = "Thread Fault"; +FaultVect ThreadFault::_vect = 0x00F1; +FaultStat ThreadFault::_count; + + +FaultName ArithmeticFault::_name = "Arithmetic Overflow Exception"; +FaultVect ArithmeticFault::_vect = 0x180; +FaultStat ArithmeticFault::_count; + +FaultName UnimplementedOpcodeFault::_name = "opdec"; +FaultVect UnimplementedOpcodeFault::_vect = 0x0481; +FaultStat UnimplementedOpcodeFault::_count; + +FaultName InterruptFault::_name = "interrupt"; +FaultVect InterruptFault::_vect = 0x0180; +FaultStat InterruptFault::_count; + +FaultName TrapFault::_name = "Trap"; +FaultVect TrapFault::_vect = 0x0180; +FaultStat TrapFault::_count; + +FaultName BreakpointFault::_name = "Breakpoint"; +FaultVect BreakpointFault::_vect = 0x0180; +FaultStat BreakpointFault::_count; + + +FaultName ItbInvalidFault::_name = "Invalid TLB Entry Exception (I-Fetch/LW)"; +FaultVect ItbInvalidFault::_vect = 0x0180; +FaultStat ItbInvalidFault::_count; + +FaultName ItbPageFault::_name = "itbmiss"; +FaultVect ItbPageFault::_vect = 0x0181; +FaultStat ItbPageFault::_count; + +FaultName ItbMissFault::_name = "itbmiss"; +FaultVect ItbMissFault::_vect = 0x0181; +FaultStat ItbMissFault::_count; + +FaultName ItbAcvFault::_name = "iaccvio"; +FaultVect ItbAcvFault::_vect = 0x0081; +FaultStat ItbAcvFault::_count; + +FaultName ItbRefillFault::_name = "TLB Refill Exception (I-Fetch/LW)"; +FaultVect ItbRefillFault::_vect = 0x0180; +FaultStat ItbRefillFault::_count; + +FaultName NDtbMissFault::_name = "dtb_miss_single"; +FaultVect NDtbMissFault::_vect = 0x0201; +FaultStat NDtbMissFault::_count; + +FaultName PDtbMissFault::_name = "dtb_miss_double"; +FaultVect PDtbMissFault::_vect = 0x0281; +FaultStat PDtbMissFault::_count; + +FaultName DtbPageFault::_name = "dfault"; +FaultVect DtbPageFault::_vect = 0x0381; +FaultStat DtbPageFault::_count; + +FaultName DtbAcvFault::_name = "dfault"; +FaultVect DtbAcvFault::_vect = 0x0381; +FaultStat DtbAcvFault::_count; + +FaultName DtbInvalidFault::_name = "Invalid TLB Entry Exception (Store)"; +FaultVect DtbInvalidFault::_vect = 0x0180; +FaultStat DtbInvalidFault::_count; + +FaultName DtbRefillFault::_name = "TLB Refill Exception (Store)"; +FaultVect DtbRefillFault::_vect = 0x0180; +FaultStat DtbRefillFault::_count; + +FaultName TLBModifiedFault::_name = "TLB Modified Exception"; +FaultVect TLBModifiedFault::_vect = 0x0180; +FaultStat TLBModifiedFault::_count; + +FaultName FloatEnableFault::_name = "float_enable_fault"; +FaultVect FloatEnableFault::_vect = 0x0581; +FaultStat FloatEnableFault::_count; + +FaultName IntegerOverflowFault::_name = "Integer Overflow Fault"; +FaultVect IntegerOverflowFault::_vect = 0x0501; +FaultStat IntegerOverflowFault::_count; + +FaultName DspStateDisabledFault::_name = "DSP Disabled Fault"; +FaultVect DspStateDisabledFault::_vect = 0x001a; +FaultStat DspStateDisabledFault::_count; + +#if FULL_SYSTEM +void ArmFault::setHandlerPC(Addr HandlerBase, ThreadContext *tc) +{ + tc->setPC(HandlerBase); + tc->setNextPC(HandlerBase+sizeof(MachInst)); + tc->setNextNPC(HandlerBase+2*sizeof(MachInst)); +} + +void ArmFault::setExceptionState(ThreadContext *tc,uint8_t ExcCode) +{ + // modify SRS Ctl - Save CSS, put ESS into CSS + MiscReg stat = tc->readMiscReg(ArmISA::Status); + if(bits(stat,Status_EXL) != 1 && bits(stat,Status_BEV) != 1) + { + // SRS Ctl is modified only if Status_EXL and Status_BEV are not set + MiscReg srs = tc->readMiscReg(ArmISA::SRSCtl); + uint8_t CSS,ESS; + CSS = bits(srs,SRSCtl_CSS_HI,SRSCtl_CSS_LO); + ESS = bits(srs,SRSCtl_ESS_HI,SRSCtl_ESS_LO); + // Move CSS to PSS + replaceBits(srs,SRSCtl_PSS_HI,SRSCtl_PSS_LO,CSS); + // Move ESS to CSS + replaceBits(srs,SRSCtl_CSS_HI,SRSCtl_CSS_LO,ESS); + tc->setMiscRegNoEffect(ArmISA::SRSCtl,srs); + //tc->setShadowSet(ESS); + } + + // set EXL bit (don't care if it is already set!) + replaceBits(stat,Status_EXL_HI,Status_EXL_LO,1); + tc->setMiscRegNoEffect(ArmISA::Status,stat); + + // write EPC + // warn("Set EPC to %x\n",tc->readPC()); + // CHECK ME or FIXME or FIX ME or POSSIBLE HACK + // Check to see if the exception occurred in the branch delay slot + DPRINTF(Arm,"PC: %x, NextPC: %x, NNPC: %x\n",tc->readPC(),tc->readNextPC(),tc->readNextNPC()); + int C_BD=0; + if(tc->readPC() + sizeof(MachInst) != tc->readNextPC()){ + tc->setMiscRegNoEffect(ArmISA::EPC,tc->readPC()-sizeof(MachInst)); + // In the branch delay slot? set CAUSE_31 + C_BD = 1; + } else { + tc->setMiscRegNoEffect(ArmISA::EPC,tc->readPC()); + // In the branch delay slot? reset CAUSE_31 + C_BD = 0; + } + + // Set Cause_EXCCODE field + MiscReg cause = tc->readMiscReg(ArmISA::Cause); + replaceBits(cause,Cause_EXCCODE_HI,Cause_EXCCODE_LO,ExcCode); + replaceBits(cause,Cause_BD_HI,Cause_BD_LO,C_BD); + replaceBits(cause,Cause_CE_HI,Cause_CE_LO,0); + tc->setMiscRegNoEffect(ArmISA::Cause,cause); + +} + +void ArithmeticFault::invoke(ThreadContext *tc) +{ + DPRINTF(Arm,"%s encountered.\n", name()); + setExceptionState(tc,0xC); + + // Set new PC + Addr HandlerBase; + MiscReg stat = tc->readMiscReg(ArmISA::Status); + // Here, the handler is dependent on BEV, which is not modified by setExceptionState() + if(bits(stat,Status_BEV)==0){ // See MIPS ARM Vol 3, Revision 2, Page 38 + HandlerBase= vect() + tc->readMiscReg(ArmISA::EBase); + }else{ + HandlerBase = 0xBFC00200; + } + setHandlerPC(HandlerBase,tc); + // warn("Exception Handler At: %x \n",HandlerBase); +} + +void StoreAddressErrorFault::invoke(ThreadContext *tc) +{ + DPRINTF(Arm,"%s encountered.\n", name()); + setExceptionState(tc,0x5); + tc->setMiscRegNoEffect(ArmISA::BadVAddr,BadVAddr); + + // Set new PC + Addr HandlerBase; + HandlerBase= vect() + tc->readMiscReg(ArmISA::EBase); // Offset 0x180 - General Exception Vector + setHandlerPC(HandlerBase,tc); + // warn("Exception Handler At: %x \n",HandlerBase); + // warn("Exception Handler At: %x , EPC set to %x\n",HandlerBase,tc->readMiscReg(ArmISA::EPC)); + +} + +void TrapFault::invoke(ThreadContext *tc) +{ + DPRINTF(Arm,"%s encountered.\n", name()); + // warn("%s encountered.\n", name()); + setExceptionState(tc,0xD); + + // Set new PC + Addr HandlerBase; + HandlerBase= vect() + tc->readMiscReg(ArmISA::EBase); // Offset 0x180 - General Exception Vector + setHandlerPC(HandlerBase,tc); + // warn("Exception Handler At: %x \n",HandlerBase); + // warn("Exception Handler At: %x , EPC set to %x\n",HandlerBase,tc->readMiscReg(ArmISA::EPC)); +} + +void BreakpointFault::invoke(ThreadContext *tc) +{ + setExceptionState(tc,0x9); + + // Set new PC + Addr HandlerBase; + HandlerBase= vect() + tc->readMiscReg(ArmISA::EBase); // Offset 0x180 - General Exception Vector + setHandlerPC(HandlerBase,tc); + // warn("Exception Handler At: %x \n",HandlerBase); + // warn("Exception Handler At: %x , EPC set to %x\n",HandlerBase,tc->readMiscReg(ArmISA::EPC)); + +} + +void DtbInvalidFault::invoke(ThreadContext *tc) +{ + DPRINTF(Arm,"%s encountered.\n", name()); + // warn("%s encountered.\n", name()); + tc->setMiscRegNoEffect(ArmISA::BadVAddr,BadVAddr); + MiscReg eh = tc->readMiscReg(ArmISA::EntryHi); + replaceBits(eh,EntryHi_ASID_HI,EntryHi_ASID_LO,EntryHi_Asid); + replaceBits(eh,EntryHi_VPN2_HI,EntryHi_VPN2_LO,EntryHi_VPN2); + replaceBits(eh,EntryHi_VPN2X_HI,EntryHi_VPN2X_LO,EntryHi_VPN2X); + tc->setMiscRegNoEffect(ArmISA::EntryHi,eh); + MiscReg ctxt = tc->readMiscReg(ArmISA::Context); + replaceBits(ctxt,Context_BadVPN2_HI,Context_BadVPN2_LO,Context_BadVPN2); + tc->setMiscRegNoEffect(ArmISA::Context,ctxt); + setExceptionState(tc,0x3); + + + // Set new PC + Addr HandlerBase; + HandlerBase= vect() + tc->readMiscReg(ArmISA::EBase); // Offset 0x180 - General Exception Vector + setHandlerPC(HandlerBase,tc); + // warn("Exception Handler At: %x , EPC set to %x\n",HandlerBase,tc->readMiscReg(ArmISA::EPC)); +} + +void AddressErrorFault::invoke(ThreadContext *tc) +{ + DPRINTF(Arm,"%s encountered.\n", name()); + setExceptionState(tc,0x4); + tc->setMiscRegNoEffect(ArmISA::BadVAddr,BadVAddr); + + // Set new PC + Addr HandlerBase; + HandlerBase= vect() + tc->readMiscReg(ArmISA::EBase); // Offset 0x180 - General Exception Vector + setHandlerPC(HandlerBase,tc); +} + +void ItbInvalidFault::invoke(ThreadContext *tc) +{ + DPRINTF(Arm,"%s encountered.\n", name()); + setExceptionState(tc,0x2); + tc->setMiscRegNoEffect(ArmISA::BadVAddr,BadVAddr); + MiscReg eh = tc->readMiscReg(ArmISA::EntryHi); + replaceBits(eh,EntryHi_ASID_HI,EntryHi_ASID_LO,EntryHi_Asid); + replaceBits(eh,EntryHi_VPN2_HI,EntryHi_VPN2_LO,EntryHi_VPN2); + replaceBits(eh,EntryHi_VPN2X_HI,EntryHi_VPN2X_LO,EntryHi_VPN2X); + tc->setMiscRegNoEffect(ArmISA::EntryHi,eh); + MiscReg ctxt = tc->readMiscReg(ArmISA::Context); + replaceBits(ctxt,Context_BadVPN2_HI,Context_BadVPN2_LO,Context_BadVPN2); + tc->setMiscRegNoEffect(ArmISA::Context,ctxt); + + + // Set new PC + Addr HandlerBase; + HandlerBase= vect() + tc->readMiscReg(ArmISA::EBase); // Offset 0x180 - General Exception Vector + setHandlerPC(HandlerBase,tc); + DPRINTF(Arm,"Exception Handler At: %x , EPC set to %x\n",HandlerBase,tc->readMiscReg(ArmISA::EPC)); +} + +void ItbRefillFault::invoke(ThreadContext *tc) +{ + DPRINTF(Arm,"%s encountered (%x).\n", name(),BadVAddr); + Addr HandlerBase; + tc->setMiscRegNoEffect(ArmISA::BadVAddr,BadVAddr); + MiscReg eh = tc->readMiscReg(ArmISA::EntryHi); + replaceBits(eh,EntryHi_ASID_HI,EntryHi_ASID_LO,EntryHi_Asid); + replaceBits(eh,EntryHi_VPN2_HI,EntryHi_VPN2_LO,EntryHi_VPN2); + replaceBits(eh,EntryHi_VPN2X_HI,EntryHi_VPN2X_LO,EntryHi_VPN2X); + tc->setMiscRegNoEffect(ArmISA::EntryHi,eh); + MiscReg ctxt = tc->readMiscReg(ArmISA::Context); + replaceBits(ctxt,Context_BadVPN2_HI,Context_BadVPN2_LO,Context_BadVPN2); + tc->setMiscRegNoEffect(ArmISA::Context,ctxt); + + MiscReg stat = tc->readMiscReg(ArmISA::Status); + // Since handler depends on EXL bit, must check EXL bit before setting it!! + if(bits(stat,Status_EXL)==1){ // See MIPS ARM Vol 3, Revision 2, Page 38 + HandlerBase= vect() + tc->readMiscReg(ArmISA::EBase); // Offset 0x180 - General Exception Vector + }else{ + HandlerBase = tc->readMiscReg(ArmISA::EBase); // Offset 0x000 + } + + setExceptionState(tc,0x2); + setHandlerPC(HandlerBase,tc); +} + +void DtbRefillFault::invoke(ThreadContext *tc) +{ + // Set new PC + DPRINTF(Arm,"%s encountered.\n", name()); + Addr HandlerBase; + tc->setMiscRegNoEffect(ArmISA::BadVAddr,BadVAddr); + MiscReg eh = tc->readMiscReg(ArmISA::EntryHi); + replaceBits(eh,EntryHi_ASID_HI,EntryHi_ASID_LO,EntryHi_Asid); + replaceBits(eh,EntryHi_VPN2_HI,EntryHi_VPN2_LO,EntryHi_VPN2); + replaceBits(eh,EntryHi_VPN2X_HI,EntryHi_VPN2X_LO,EntryHi_VPN2X); + tc->setMiscRegNoEffect(ArmISA::EntryHi,eh); + MiscReg ctxt = tc->readMiscReg(ArmISA::Context); + replaceBits(ctxt,Context_BadVPN2_HI,Context_BadVPN2_LO,Context_BadVPN2); + tc->setMiscRegNoEffect(ArmISA::Context,ctxt); + + MiscReg stat = tc->readMiscReg(ArmISA::Status); + // Since handler depends on EXL bit, must check EXL bit before setting it!! + if(bits(stat,Status_EXL)==1){ // See MIPS ARM Vol 3, Revision 2, Page 38 + HandlerBase= vect() + tc->readMiscReg(ArmISA::EBase); // Offset 0x180 - General Exception Vector + }else{ + HandlerBase = tc->readMiscReg(ArmISA::EBase); // Offset 0x000 + } + + + setExceptionState(tc,0x3); + + setHandlerPC(HandlerBase,tc); +} + +void TLBModifiedFault::invoke(ThreadContext *tc) +{ + DPRINTF(Arm,"%s encountered.\n", name()); + tc->setMiscRegNoEffect(ArmISA::BadVAddr,BadVAddr); + MiscReg eh = tc->readMiscReg(ArmISA::EntryHi); + replaceBits(eh,EntryHi_ASID_HI,EntryHi_ASID_LO,EntryHi_Asid); + replaceBits(eh,EntryHi_VPN2_HI,EntryHi_VPN2_LO,EntryHi_VPN2); + replaceBits(eh,EntryHi_VPN2X_HI,EntryHi_VPN2X_LO,EntryHi_VPN2X); + tc->setMiscRegNoEffect(ArmISA::EntryHi,eh); + MiscReg ctxt = tc->readMiscReg(ArmISA::Context); + replaceBits(ctxt,Context_BadVPN2_HI,Context_BadVPN2_LO,Context_BadVPN2); + tc->setMiscRegNoEffect(ArmISA::Context,ctxt); + + // Set new PC + Addr HandlerBase; + HandlerBase= vect() + tc->readMiscReg(ArmISA::EBase); // Offset 0x180 - General Exception Vector + setExceptionState(tc,0x1); + setHandlerPC(HandlerBase,tc); + // warn("Exception Handler At: %x , EPC set to %x\n",HandlerBase,tc->readMiscReg(ArmISA::EPC)); + +} + +void SystemCallFault::invoke(ThreadContext *tc) +{ + DPRINTF(Arm,"%s encountered.\n", name()); + setExceptionState(tc,0x8); + + // Set new PC + Addr HandlerBase; + HandlerBase= vect() + tc->readMiscReg(ArmISA::EBase); // Offset 0x180 - General Exception Vector + setHandlerPC(HandlerBase,tc); + // warn("Exception Handler At: %x \n",HandlerBase); + // warn("Exception Handler At: %x , EPC set to %x\n",HandlerBase,tc->readMiscReg(ArmISA::EPC)); + +} + +void InterruptFault::invoke(ThreadContext *tc) +{ +#if FULL_SYSTEM + DPRINTF(Arm,"%s encountered.\n", name()); + //RegFile *Reg = tc->getRegFilePtr(); // Get pointer to the register fil + setExceptionState(tc,0x0A); + Addr HandlerBase; + + + uint8_t IV = bits(tc->readMiscRegNoEffect(ArmISA::Cause),Cause_IV); + if (IV)// Offset 200 for release 2 + HandlerBase= 0x20 + vect() + tc->readMiscRegNoEffect(ArmISA::EBase); + else//Ofset at 180 for release 1 + HandlerBase= vect() + tc->readMiscRegNoEffect(ArmISA::EBase); + + setHandlerPC(HandlerBase,tc); +#endif +} + +#endif // FULL_SYSTEM + +void ResetFault::invoke(ThreadContext *tc) +{ +#if FULL_SYSTEM + DPRINTF(Arm,"%s encountered.\n", name()); + /* All reset activity must be invoked from here */ + tc->setPC(vect()); + tc->setNextPC(vect()+sizeof(MachInst)); + tc->setNextNPC(vect()+sizeof(MachInst)+sizeof(MachInst)); + DPRINTF(Arm,"(%x) - ResetFault::invoke : PC set to %x",(unsigned)tc,(unsigned)tc->readPC()); +#endif + + // Set Coprocessor 1 (Floating Point) To Usable + //tc->setMiscReg(ArmISA::Status, ArmISA::Status | 0x20000000); +} + +void ReservedInstructionFault::invoke(ThreadContext *tc) +{ +#if FULL_SYSTEM + DPRINTF(Arm,"%s encountered.\n", name()); + //RegFile *Reg = tc->getRegFilePtr(); // Get pointer to the register fil + setExceptionState(tc,0x0A); + Addr HandlerBase; + HandlerBase= vect() + tc->readMiscRegNoEffect(ArmISA::EBase); // Offset 0x180 - General Exception Vector + setHandlerPC(HandlerBase,tc); +#else + panic("%s encountered.\n", name()); +#endif +} + +void ThreadFault::invoke(ThreadContext *tc) +{ + DPRINTF(Arm,"%s encountered.\n", name()); + panic("%s encountered.\n", name()); +} + +void DspStateDisabledFault::invoke(ThreadContext *tc) +{ + DPRINTF(Arm,"%s encountered.\n", name()); + panic("%s encountered.\n", name()); +} + +void CoprocessorUnusableFault::invoke(ThreadContext *tc) +{ +#if FULL_SYSTEM + DPRINTF(Arm,"%s encountered.\n", name()); + setExceptionState(tc,0xb); + /* The ID of the coprocessor causing the exception is stored in CoprocessorUnusableFault::coProcID */ + MiscReg cause = tc->readMiscReg(ArmISA::Cause); + replaceBits(cause,Cause_CE_HI,Cause_CE_LO,coProcID); + tc->setMiscRegNoEffect(ArmISA::Cause,cause); + + Addr HandlerBase; + HandlerBase= vect() + tc->readMiscReg(ArmISA::EBase); // Offset 0x180 - General Exception Vector + setHandlerPC(HandlerBase,tc); + + // warn("Status: %x, Cause: %x\n",tc->readMiscReg(ArmISA::Status),tc->readMiscReg(ArmISA::Cause)); +#else + warn("%s (CP%d) encountered.\n", name(), coProcID); +#endif +} + +} // namespace ArmISA + diff --git a/src/arch/arm/faults.hh b/src/arch/arm/faults.hh new file mode 100644 index 000000000..28ecd7591 --- /dev/null +++ b/src/arch/arm/faults.hh @@ -0,0 +1,574 @@ +/* + * Copyright (c) 2003-2005 The Regents of The University of Michigan + * Copyright (c) 2007-2008 The Florida State University + * 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 + * Stephen Hines + */ + +#ifndef __ARM_FAULTS_HH__ +#define __ARM_FAULTS_HH__ + +#include "sim/faults.hh" + +// The design of the "name" and "vect" functions is in sim/faults.hh + +namespace ArmISA +{ +typedef const Addr FaultVect; + +class ArmFault : public FaultBase +{ + protected: + virtual bool skipFaultingInstruction() {return false;} + virtual bool setRestartAddress() {return true;} + public: + Addr BadVAddr; + Addr EntryHi_Asid; + Addr EntryHi_VPN2; + Addr EntryHi_VPN2X; + Addr Context_BadVPN2; +#if FULL_SYSTEM + void invoke(ThreadContext * tc) {}; + void setExceptionState(ThreadContext *,uint8_t); + void setHandlerPC(Addr,ThreadContext *); +#endif + virtual FaultVect vect() = 0; + virtual FaultStat & countStat() = 0; +}; + +class MachineCheckFault : public ArmFault +{ + private: + static FaultName _name; + static FaultVect _vect; + static FaultStat _count; + public: + FaultName name() const {return _name;} + FaultVect vect() {return _vect;} + FaultStat & countStat() {return _count;} + bool isMachineCheckFault() {return true;} +}; + +class NonMaskableInterrupt : public ArmFault +{ + private: + static FaultName _name; + static FaultVect _vect; + static FaultStat _count; + public: + FaultName name() const {return _name;} + FaultVect vect() {return _vect;} + FaultStat & countStat() {return _count;} + bool isNonMaskableInterrupt() {return true;} +}; + +class AlignmentFault : public ArmFault +{ + private: + static FaultName _name; + static FaultVect _vect; + static FaultStat _count; + public: + FaultName name() const {return _name;} + FaultVect vect() {return _vect;} + FaultStat & countStat() {return _count;} + bool isAlignmentFault() {return true;} +}; + +class AddressErrorFault : public ArmFault +{ + private: + static FaultName _name; + static FaultVect _vect; + static FaultStat _count; + public: + FaultName name() const {return _name;} + FaultVect vect() {return _vect;} + FaultStat & countStat() {return _count;} +#if FULL_SYSTEM + void invoke(ThreadContext * tc); +#endif + +}; +class StoreAddressErrorFault : public ArmFault +{ + private: + static FaultName _name; + static FaultVect _vect; + static FaultStat _count; + public: + FaultName name() const {return _name;} + FaultVect vect() {return _vect;} + FaultStat & countStat() {return _count;} +#if FULL_SYSTEM + void invoke(ThreadContext * tc); +#endif + +}; +class UnimplementedOpcodeFault : public ArmFault +{ + private: + static FaultName _name; + static FaultVect _vect; + static FaultStat _count; + public: + FaultName name() const {return _name;} + FaultVect vect() {return _vect;} + FaultStat & countStat() {return _count;} +}; + + +class TLBRefillIFetchFault : public ArmFault +{ + private: + Addr vaddr; + static FaultName _name; + static FaultVect _vect; + static FaultStat _count; + public: + FaultName name() const {return _name;} + FaultVect vect() {return _vect;} + FaultStat & countStat() {return _count;} + void invoke(ThreadContext * tc); +}; +class TLBInvalidIFetchFault : public ArmFault +{ + private: + Addr vaddr; + static FaultName _name; + static FaultVect _vect; + static FaultStat _count; + public: + FaultName name() const {return _name;} + FaultVect vect() {return _vect;} + FaultStat & countStat() {return _count;} + void invoke(ThreadContext * tc); +}; + +class NDtbMissFault : public ArmFault +{ + private: + static FaultName _name; + static FaultVect _vect; + static FaultStat _count; + public: + FaultName name() const {return _name;} + FaultVect vect() {return _vect;} + FaultStat & countStat() {return _count;} +}; + +class PDtbMissFault : public ArmFault +{ + private: + static FaultName _name; + static FaultVect _vect; + static FaultStat _count; + public: + FaultName name() const {return _name;} + FaultVect vect() {return _vect;} + FaultStat & countStat() {return _count;} +}; + +class DtbPageFault : public ArmFault +{ + private: + static FaultName _name; + static FaultVect _vect; + static FaultStat _count; + public: + FaultName name() const {return _name;} + FaultVect vect() {return _vect;} + FaultStat & countStat() {return _count;} +}; + +class DtbAcvFault : public ArmFault +{ + private: + static FaultName _name; + static FaultVect _vect; + static FaultStat _count; + public: + FaultName name() const {return _name;} + FaultVect vect() {return _vect;} + FaultStat & countStat() {return _count;} +}; + +class CacheErrorFault : public ArmFault +{ + private: + Addr vaddr; + static FaultName _name; + static FaultVect _vect; + static FaultStat _count; + public: + FaultName name() const {return _name;} + FaultVect vect() {return _vect;} + FaultStat & countStat() {return _count;} + void invoke(ThreadContext * tc); +}; + + + + +static inline Fault genMachineCheckFault() +{ + return new MachineCheckFault; +} + +static inline Fault genAlignmentFault() +{ + return new AlignmentFault; +} + +class ResetFault : public ArmFault +{ + private: + static FaultName _name; + static FaultVect _vect; + static FaultStat _count; + public: + FaultName name() const {return _name;} + FaultVect vect() {return _vect;} + FaultStat & countStat() {return _count;} + void invoke(ThreadContext * tc); + +}; +class SystemCallFault : public ArmFault +{ + private: + static FaultName _name; + static FaultVect _vect; + static FaultStat _count; + public: + FaultName name() const {return _name;} + FaultVect vect() {return _vect;} + FaultStat & countStat() {return _count;} + void invoke(ThreadContext * tc); +}; + +class SoftResetFault : public ArmFault +{ + private: + static FaultName _name; + static FaultVect _vect; + static FaultStat _count; + public: + FaultName name() const {return _name;} + FaultVect vect() {return _vect;} + FaultStat & countStat() {return _count;} + void invoke(ThreadContext * tc); +}; +class DebugSingleStep : public ArmFault +{ + private: + static FaultName _name; + static FaultVect _vect; + static FaultStat _count; + public: + FaultName name() const {return _name;} + FaultVect vect() {return _vect;} + FaultStat & countStat() {return _count;} + void invoke(ThreadContext * tc); +}; +class DebugInterrupt : public ArmFault +{ + private: + static FaultName _name; + static FaultVect _vect; + static FaultStat _count; + public: + FaultName name() const {return _name;} + FaultVect vect() {return _vect;} + FaultStat & countStat() {return _count;} + void invoke(ThreadContext * tc); +}; + +class CoprocessorUnusableFault : public ArmFault +{ + private: + static FaultName _name; + static FaultVect _vect; + static FaultStat _count; + int coProcID; + public: + FaultName name() const {return _name;} + FaultVect vect() {return _vect;} + FaultStat & countStat() {return _count;} + void invoke(ThreadContext * tc); + CoprocessorUnusableFault(int _procid){ coProcID = _procid;} +}; + +class ReservedInstructionFault : public ArmFault +{ + private: + static FaultName _name; + static FaultVect _vect; + static FaultStat _count; + public: + FaultName name() const {return _name;} + FaultVect vect() {return _vect;} + FaultStat & countStat() {return _count;} + void invoke(ThreadContext * tc); +}; + +class ThreadFault : public ArmFault +{ + private: + static FaultName _name; + static FaultVect _vect; + static FaultStat _count; + public: + FaultName name() const {return _name;} + FaultVect vect() {return _vect;} + FaultStat & countStat() {return _count;} + void invoke(ThreadContext * tc); +}; + + +class ArithmeticFault : public ArmFault +{ + protected: + bool skipFaultingInstruction() {return true;} + private: + static FaultName _name; + static FaultVect _vect; + static FaultStat _count; + public: + FaultName name() const {return _name;} + FaultVect vect() {return _vect;} + FaultStat & countStat() {return _count;} +#if FULL_SYSTEM + void invoke(ThreadContext * tc); +#endif +}; + +class InterruptFault : public ArmFault +{ + protected: + bool setRestartAddress() {return false;} + private: + static FaultName _name; + static FaultVect _vect; + static FaultStat _count; + public: + FaultName name() const {return _name;} + FaultVect vect() {return _vect;} + FaultStat & countStat() {return _count;} + +#if FULL_SYSTEM + void invoke(ThreadContext * tc); +#endif + + //void invoke(ThreadContext * tc); +}; + +class TrapFault : public ArmFault +{ + private: + static FaultName _name; + static FaultVect _vect; + static FaultStat _count; + public: + FaultName name() const {return _name;} + FaultVect vect() {return _vect;} + FaultStat & countStat() {return _count;} +#if FULL_SYSTEM + void invoke(ThreadContext * tc); +#endif +}; + +class BreakpointFault : public ArmFault +{ + private: + static FaultName _name; + static FaultVect _vect; + static FaultStat _count; + public: + FaultName name() const {return _name;} + FaultVect vect() {return _vect;} + FaultStat & countStat() {return _count;} +#if FULL_SYSTEM + void invoke(ThreadContext * tc); +#endif +}; + +class ItbRefillFault : public ArmFault +{ + private: + static FaultName _name; + static FaultVect _vect; + static FaultStat _count; + public: + FaultName name() const {return _name;} + FaultVect vect() {return _vect;} + FaultStat & countStat() {return _count;} +#if FULL_SYSTEM + void invoke(ThreadContext * tc); +#endif +}; +class DtbRefillFault : public ArmFault +{ + private: + static FaultName _name; + static FaultVect _vect; + static FaultStat _count; + public: + FaultName name() const {return _name;} + FaultVect vect() {return _vect;} + FaultStat & countStat() {return _count;} +#if FULL_SYSTEM + void invoke(ThreadContext * tc); +#endif +}; + +class ItbPageFault : public ArmFault +{ + private: + static FaultName _name; + static FaultVect _vect; + static FaultStat _count; + public: + FaultName name() const {return _name;} + FaultVect vect() {return _vect;} + FaultStat & countStat() {return _count;} +#if FULL_SYSTEM + void invoke(ThreadContext * tc); +#endif +}; + +class ItbInvalidFault : public ArmFault +{ + private: + static FaultName _name; + static FaultVect _vect; + static FaultStat _count; + public: + FaultName name() const {return _name;} + FaultVect vect() {return _vect;} + FaultStat & countStat() {return _count;} +#if FULL_SYSTEM + void invoke(ThreadContext * tc); +#endif + +}; +class TLBModifiedFault : public ArmFault +{ + private: + static FaultName _name; + static FaultVect _vect; + static FaultStat _count; + public: + FaultName name() const {return _name;} + FaultVect vect() {return _vect;} + FaultStat & countStat() {return _count;} +#if FULL_SYSTEM + void invoke(ThreadContext * tc); +#endif + +}; + +class DtbInvalidFault : public ArmFault +{ + private: + static FaultName _name; + static FaultVect _vect; + static FaultStat _count; + public: + FaultName name() const {return _name;} + FaultVect vect() {return _vect;} + FaultStat & countStat() {return _count;} +#if FULL_SYSTEM + void invoke(ThreadContext * tc); +#endif + +}; + +class FloatEnableFault : public ArmFault +{ + private: + static FaultName _name; + static FaultVect _vect; + static FaultStat _count; + public: + FaultName name() const {return _name;} + FaultVect vect() {return _vect;} + FaultStat & countStat() {return _count;} +}; + +class ItbMissFault : public ArmFault +{ + private: + static FaultName _name; + static FaultVect _vect; + static FaultStat _count; + public: + FaultName name() const {return _name;} + FaultVect vect() {return _vect;} + FaultStat & countStat() {return _count;} +}; + +class ItbAcvFault : public ArmFault +{ + private: + static FaultName _name; + static FaultVect _vect; + static FaultStat _count; + public: + FaultName name() const {return _name;} + FaultVect vect() {return _vect;} + FaultStat & countStat() {return _count;} +}; + +class IntegerOverflowFault : public ArmFault +{ + private: + static FaultName _name; + static FaultVect _vect; + static FaultStat _count; + public: + FaultName name() const {return _name;} + FaultVect vect() {return _vect;} + FaultStat & countStat() {return _count;} +}; + +class DspStateDisabledFault : public ArmFault +{ + private: + static FaultName _name; + static FaultVect _vect; + static FaultStat _count; + public: + FaultName name() const {return _name;} + FaultVect vect() {return _vect;} + FaultStat & countStat() {return _count;} + void invoke(ThreadContext * tc); +}; + +} // ArmISA namespace + +#endif // __ARM_FAULTS_HH__ diff --git a/src/arch/arm/isa/base.isa b/src/arch/arm/isa/base.isa new file mode 100644 index 000000000..d492bd3cd --- /dev/null +++ b/src/arch/arm/isa/base.isa @@ -0,0 +1,87 @@ +// -*- mode:c++ -*- + +// Copyright (c) 2007-2008 The Florida State University +// 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: Stephen Hines + +//////////////////////////////////////////////////////////////////// +// +// Base class for ARM instructions, and some support functions +// + +//Outputs to decoder.hh +output header {{ + + using namespace ArmISA; + + /** + * Base class for all MIPS static instructions. + */ + class ArmStaticInst : public StaticInst + { + protected: + + // Constructor + ArmStaticInst(const char *mnem, MachInst _machInst, OpClass __opClass) + : StaticInst(mnem, _machInst, __opClass) + { + } + + /// Print a register name for disassembly given the unique + /// dependence tag number (FP or int). + void printReg(std::ostream &os, int reg) const; + + std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; + }; + +}}; + +//Ouputs to decoder.cc +output decoder {{ + + void ArmStaticInst::printReg(std::ostream &os, int reg) const + { + if (reg < FP_Base_DepTag) { + ccprintf(os, "r%d", reg); + } + else { + ccprintf(os, "f%d", reg - FP_Base_DepTag); + } + } + + std::string ArmStaticInst::generateDisassembly(Addr pc, + const SymbolTable *symtab) const + { + std::stringstream ss; + + ccprintf(ss, "%-10s ", mnemonic); + + return ss.str(); + } + +}}; + diff --git a/src/arch/arm/isa/bitfields.isa b/src/arch/arm/isa/bitfields.isa new file mode 100644 index 000000000..bcb2869b7 --- /dev/null +++ b/src/arch/arm/isa/bitfields.isa @@ -0,0 +1,170 @@ +// -*- mode:c++ -*- + +// Copyright (c) 2007-2008 The Florida State University +// 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: Stephen Hines + +//////////////////////////////////////////////////////////////////// +// +// Bitfield definitions. +// + +// Opcode fields +def bitfield OPCODE <27:25>; +def bitfield OPCODE_27_25 <27:25>; +def bitfield OPCODE_24_21 <24:21>; +def bitfield OPCODE_24_23 <24:23>; +def bitfield OPCODE_24 <24:24>; +def bitfield OPCODE_23_20 <23:20>; +def bitfield OPCODE_23_21 <23:21>; +def bitfield OPCODE_23 <23:23>; +def bitfield OPCODE_22_8 <22: 8>; +def bitfield OPCODE_22_21 <22:21>; +def bitfield OPCODE_22 <22:22>; +def bitfield OPCODE_21_20 <21:20>; +def bitfield OPCODE_20 <20:20>; +def bitfield OPCODE_19_18 <19:18>; +def bitfield OPCODE_19 <19:19>; +def bitfield OPCODE_15_12 <15:12>; +def bitfield OPCODE_15 <15:15>; +def bitfield OPCODE_9 < 9: 9>; +def bitfield OPCODE_7_4 < 7: 4>; +def bitfield OPCODE_7_5 < 7: 5>; +def bitfield OPCODE_7_6 < 7: 6>; +def bitfield OPCODE_7 < 7: 7>; +def bitfield OPCODE_6_5 < 6: 5>; +def bitfield OPCODE_6 < 6: 6>; +def bitfield OPCODE_5 < 5: 5>; +def bitfield OPCODE_4 < 4: 4>; + +// Other +def bitfield COND_CODE <31:28>; +def bitfield S_FIELD <20:20>; +def bitfield RN <19:16>; +def bitfield RD <15:12>; +def bitfield SHIFT_SIZE <11: 7>; +def bitfield SHIFT < 6: 5>; +def bitfield RM < 3: 0>; + +def bitfield RE <20:16>; + +def bitfield RS <11: 8>; + +def bitfield RDUP <19:16>; +def bitfield RNDN <15:12>; + +def bitfield RDHI <15:12>; +def bitfield RDLO <11: 8>; + +def bitfield U_FIELD <23:23>; + +def bitfield PUSWL <24:20>; +def bitfield PREPOST <24:24>; +def bitfield UP <23:23>; +def bitfield PSRUSER <22:22>; +def bitfield WRITEBACK <21:21>; +def bitfield LOADOP <20:20>; + +def bitfield PUBWL <24:20>; +def bitfield PUIWL <24:20>; +def bitfield BYTEACCESS <22:22>; + +def bitfield LUAS <23:20>; + +def bitfield IMM < 7: 0>; +def bitfield IMMED_7_4 < 7: 4>; +def bitfield IMMED_3_0 < 3: 0>; + +def bitfield F_MSR <19:19>; +def bitfield S_MSR <18:18>; +def bitfield X_MSR <17:17>; +def bitfield C_MSR <16:16>; + +def bitfield Y_6 < 6: 6>; +def bitfield X_5 < 5: 5>; + +def bitfield IMMED_15_4 <15: 4>; + +def bitfield W_FIELD <21:21>; + +def bitfield ROTATE <11: 8>; +def bitfield IMMED_7_0 < 7: 0>; + +def bitfield T_FIELD <21:21>; +def bitfield IMMED_11_0 <11: 0>; + +def bitfield IMMED_20_16 <20:16>; +def bitfield IMMED_19_16 <19:16>; + +def bitfield IMMED_HI_11_8 <11: 8>; +def bitfield IMMED_LO_3_0 < 3: 0>; + +def bitfield ROT <11:10>; + +def bitfield R_FIELD < 5: 5>; + +def bitfield CARET <22:22>; +def bitfield REGLIST <15: 0>; + +def bitfield OFFSET <23: 0>; +def bitfield COPRO <11: 8>; +def bitfield OP1_7_4 < 7: 4>; +def bitfield CM < 3: 0>; + +def bitfield L_FIELD <22:22>; +def bitfield CD <15:12>; +def bitfield OPTION < 7: 0>; + +def bitfield OP1_23_20 <23:20>; +def bitfield CN <19:16>; +def bitfield OP2_7_5 < 7: 5>; + +def bitfield OP1_23_21 <23:21>; + +def bitfield IMMED_23_0 <23: 0>; +def bitfield M_FIELD <17:17>; +def bitfield A_FIELD < 8: 8>; +def bitfield I_FIELD < 7: 7>; +def bitfield F_FIELD < 6: 6>; +def bitfield MODE < 4: 0>; + +def bitfield A_BLX <24:24>; + +def bitfield CPNUM <11: 8>; +// Note that FP Regs are only 3 bits +def bitfield FN <18:16>; +def bitfield FD <14:12>; +def bitfield FPREGIMM < 3: 3>; +// We can just use 3:0 for FM since the hard-wired FP regs are handled in +// float_regfile.hh +def bitfield FM < 3: 0>; +def bitfield FPIMM < 2: 0>; +def bitfield PUNWL <24:20>; + +// M5 instructions +def bitfield M5FUNC <7:0>; + diff --git a/src/arch/arm/isa/copyright.txt b/src/arch/arm/isa/copyright.txt new file mode 100644 index 000000000..5a5c487dd --- /dev/null +++ b/src/arch/arm/isa/copyright.txt @@ -0,0 +1,28 @@ +// Copyright (c) 2007, 2008 +// The Florida State University +// All Rights Reserved +// +// This code is part of the M5 simulator. +// +// Permission is granted to use, copy, create derivative works and +// redistribute this software and such derivative works for any +// purpose, so long as the copyright notice above, this grant of +// permission, and the disclaimer below appear in all copies made; and +// so long as the name of The Florida State University is not used in +// any advertising or publicity pertaining to the use or distribution +// of this software without specific, written prior authorization. +// +// THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION FROM THE +// FLORIDA STATE UNIVERSITY AS TO ITS FITNESS FOR ANY PURPOSE, AND +// WITHOUT WARRANTY BY THE FLORIDA STATE UNIVERSITY OF ANY KIND, EITHER +// EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED +// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE. THE REGENTS OF THE FLORIDA STATE UNIVERSITY SHALL NOT BE +// LIABLE FOR ANY DAMAGES, INCLUDING DIRECT, SPECIAL, INDIRECT, +// INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM +// ARISING OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN +// IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGES. +// +// Authors: Stephen R. Hines - modified for use in ARM version + diff --git a/src/arch/arm/isa/decoder.isa b/src/arch/arm/isa/decoder.isa new file mode 100644 index 000000000..459c9788e --- /dev/null +++ b/src/arch/arm/isa/decoder.isa @@ -0,0 +1,845 @@ +// -*- mode:c++ -*- + +// Copyright (c) 2007-2008 The Florida State University +// 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: Stephen Hines + +//////////////////////////////////////////////////////////////////// +// +// The actual ARM ISA decoder +// -------------------------- +// The following instructions are specified in the ARM ISA +// Specification. Decoding closely follows the style specified +// in the ARM ISA specification document starting with Table B.1 or 3-1 +// +// +decode COND_CODE default Unknown::unknown() { + 0xf: decode COND_CODE { + 0x0: decode OPCODE_27_25 { + // Just a simple trick to allow us to specify our new uops here + 0x0: PredImmOp::addi_uop({{ Raddr = Rn + rotated_imm; }}, + 'IsMicroop'); + 0x1: PredImmOp::subi_uop({{ Raddr = Rn - rotated_imm; }}, + 'IsMicroop'); + 0x2: ArmLoadMemory::ldr_uop({{ Rd = Mem; }}, + {{ EA = Raddr + disp; }}, + inst_flags = [IsMicroop]); + 0x3: ArmStoreMemory::str_uop({{ Mem = Rd; }}, + {{ EA = Raddr + disp; }}, + inst_flags = [IsMicroop]); + 0x4: PredImmOp::addi_rd_uop({{ Rd = Rn + rotated_imm; }}, + 'IsMicroop'); + 0x5: PredImmOp::subi_rd_uop({{ Rd = Rn - rotated_imm; }}, + 'IsMicroop'); + } + 0x1: decode OPCODE_27_25 { + 0x0: PredIntOp::mvtd_uop({{ Fd.ud = ((uint64_t) Rhi << 32)|Rlo; }}, + 'IsMicroop'); + 0x1: PredIntOp::mvfd_uop({{ Rhi = (Fd.ud >> 32) & 0xffffffff; + Rlo = Fd.ud & 0xffffffff; }}, + 'IsMicroop'); + 0x2: ArmLoadMemory::ldhi_uop({{ Rhi = Mem; }}, + {{ EA = Rn + disp; }}, + inst_flags = [IsMicroop]); + 0x3: ArmLoadMemory::ldlo_uop({{ Rlo = Mem; }}, + {{ EA = Rn + disp; }}, + inst_flags = [IsMicroop]); + 0x4: ArmStoreMemory::sthi_uop({{ Mem = Rhi; }}, + {{ EA = Rn + disp; }}, + inst_flags = [IsMicroop]); + 0x5: ArmStoreMemory::stlo_uop({{ Mem = Rlo; }}, + {{ EA = Rn + disp; }}, + inst_flags = [IsMicroop]); + } + default: Unknown::unknown(); // TODO: Ignore other NV space for now + } + format BasicOp{ + default: decode OPCODE_27_25 { + 0x0: decode OPCODE_4 { + 0: decode S_FIELD { + 0: decode OPCODE_24_21 { + format PredIntOp { + 0x0: and({{ Rd = Rn & Rm_Imm; }}); + 0x1: eor({{ Rd = Rn ^ Rm_Imm; }}); + 0x2: sub({{ Rd = Rn - Rm_Imm; }}); + 0x3: rsb({{ Rd = Rm_Imm - Rn; }}); + 0x4: add({{ Rd = Rn + Rm_Imm; }}); + 0x5: adc({{ Rd = Rn + Rm_Imm + Cpsr<29:>; }}); + 0x6: sbc({{ Rd = Rn - Rm_Imm + Cpsr<29:> - 1; }}); + 0x7: rsc({{ Rd = Rm_Imm - Rn + Cpsr<29:> - 1; }}); + //0x8:mrs_cpsr -- TODO + //0x9:msr_cpsr -- TODO + //0xa:mrs_spsr -- TODO + //0xb:msr_spsr -- TODO + 0xc: orr({{ Rd = Rn | Rm_Imm; }}); + 0xd: mov({{ Rd = Rm_Imm; }}); + 0xe: bic({{ Rd = Rn & ~Rm_Imm; }}); + 0xf: mvn({{ Rd = ~Rm_Imm; }}); + } + } + 1: decode OPCODE_24_21 { + format PredIntOpCc { + 0x0: ands({{ + uint32_t resTemp; + Rd = resTemp = Rn & Rm_Imm; + }}, + {{ shift_carry_imm(Rm, shift_size, shift, Cpsr<29:>) }}, + {{ Cpsr<28:> }}); + 0x1: eors({{ + uint32_t resTemp; + Rd = resTemp = Rn ^ Rm_Imm; + }}, + {{ shift_carry_imm(Rm, shift_size, shift, Cpsr<29:>) }}, + {{ Cpsr<28:> }}); + 0x2: subs({{ + uint32_t resTemp, + val2 = Rm_Imm; + Rd = resTemp = Rn - val2; + }}, + {{ arm_sub_carry(resTemp, Rn, val2) }}, + {{ arm_sub_overflow(resTemp, Rn, val2) }}); + 0x3: rsbs({{ + uint32_t resTemp, + val2 = Rm_Imm; + Rd = resTemp = val2 - Rn; + }}, + {{ arm_sub_carry(resTemp, val2, Rn) }}, + {{ arm_sub_overflow(resTemp, val2, Rn) }}); + 0x4: adds({{ + uint32_t resTemp, + val2 = Rm_Imm; + Rd = resTemp = Rn + val2; + }}, + {{ arm_add_carry(resTemp, Rn, val2) }}, + {{ arm_add_overflow(resTemp, Rn, val2) }}); + 0x5: adcs({{ + uint32_t resTemp, + val2 = Rm_Imm; + Rd = resTemp = Rn + val2 + Cpsr<29:>; + }}, + {{ arm_add_carry(resTemp, Rn, val2) }}, + {{ arm_add_overflow(resTemp, Rn, val2) }}); + 0x6: sbcs({{ + uint32_t resTemp, + val2 = Rm_Imm; + Rd = resTemp = Rn - val2 + Cpsr<29:> - 1; + }}, + {{ arm_sub_carry(resTemp, Rn, val2) }}, + {{ arm_sub_overflow(resTemp, Rn, val2) }}); + 0x7: rscs({{ + uint32_t resTemp, + val2 = Rm_Imm; + Rd = resTemp = val2 - Rn + Cpsr<29:> - 1; + }}, + {{ arm_sub_carry(resTemp, val2, Rn) }}, + {{ arm_sub_overflow(resTemp, val2, Rn) }}); + 0x8: tst({{ + uint32_t resTemp; + resTemp = Rn & Rm_Imm; + }}, + {{ shift_carry_imm(Rm, shift_size, shift, Cpsr<29:>) }}, + {{ Cpsr<28:> }}); + 0x9: teq({{ + uint32_t resTemp; + resTemp = Rn ^ Rm_Imm; + }}, + {{ shift_carry_imm(Rm, shift_size, shift, Cpsr<29:>) }}, + {{ Cpsr<28:> }}); + 0xa: cmp({{ + uint32_t resTemp, + val2 = Rm_Imm; + resTemp = Rn - val2; + }}, + {{ arm_sub_carry(resTemp, Rn, val2) }}, + {{ arm_sub_overflow(resTemp, Rn, val2) }}); + 0xb: cmn({{ + uint32_t resTemp, + val2 = Rm_Imm; + resTemp = Rn + val2; + }}, + {{ arm_add_carry(resTemp, Rn, val2) }}, + {{ arm_add_overflow(resTemp, Rn, val2) }}); + 0xc: orrs({{ + uint32_t resTemp, + val2 = Rm_Imm; + Rd = resTemp = Rn | val2; + }}, + {{ shift_carry_imm(Rm, shift_size, shift, Cpsr<29:>) }}, + {{ Cpsr<28:> }}); + 0xd: movs({{ + uint32_t resTemp; + Rd = resTemp = Rm_Imm; + }}, + {{ shift_carry_imm(Rm, shift_size, shift, Cpsr<29:>) }}, + {{ Cpsr<28:> }}); + 0xe: bics({{ + uint32_t resTemp; + Rd = resTemp = Rn & ~Rm_Imm; + }}, + {{ shift_carry_imm(Rm, shift_size, shift, Cpsr<29:>) }}, + {{ Cpsr<28:> }}); + 0xf: mvns({{ + uint32_t resTemp; + Rd = resTemp = ~Rm_Imm; + }}, + {{ shift_carry_imm(Rm, shift_size, shift, Cpsr<29:>) }}, + {{ Cpsr<28:> }}); + } + } + } + 1: decode OPCODE_7 { + 0: decode S_FIELD { + 0: decode OPCODE_24_21 { + format PredIntOp { + 0x0: and_rs({{ Rd = Rn & Rm_Rs; }}); + 0x1: eor_rs({{ Rd = Rn ^ Rm_Rs; }}); + 0x2: sub_rs({{ Rd = Rn - Rm_Rs; }}); + 0x3: rsb_rs({{ Rd = Rm_Rs - Rn; }}); + 0x4: add_rs({{ Rd = Rn + Rm_Rs; }}); + 0x5: adc_rs({{ Rd = Rn + Rm_Rs + Cpsr<29:>; }}); + 0x6: sbc_rs({{ Rd = Rn - Rm_Rs + Cpsr<29:> - 1; }}); + 0x7: rsc_rs({{ Rd = Rm_Rs - Rn + Cpsr<29:> - 1; }}); + 0xc: orr_rs({{ Rd = Rn | Rm_Rs; }}); + 0xd: mov_rs({{ Rd = Rm_Rs; }}); + 0xe: bic_rs({{ Rd = Rn & ~Rm_Rs; }}); + 0xf: mvn_rs({{ Rd = ~Rm_Rs; }}); + default: decode OPCODE_7_4 { + 0x1: decode OPCODE_24_21 { + 0x9: BranchExchange::bx({{ }}); + 0xb: PredOp::clz({{ + if (Rm == 0) + Rd = 32; + else + { + int i; + for (i = 0; i < 32; i++) + { + if (Rm & (1<<(31-i))) + break; + } + Rd = i; + } + }}); + } + 0x3: decode OPCODE_24_21 { + 0x9: BranchExchange::blx({{ LR = NPC; }}); + } + } + } + } + 1: decode OPCODE_24_21 { + format PredIntOpCc { + 0x0: ands_rs({{ + uint32_t resTemp; + Rd = resTemp = Rn & Rm_Rs; + }}, + {{ shift_carry_rs(Rm, Rs, shift, Cpsr<29:>) }}, + {{ Cpsr<28:> }}); + 0x1: eors_rs({{ + uint32_t resTemp; + Rd = resTemp = Rn ^ Rm_Rs; + }}, + {{ shift_carry_rs(Rm, Rs, shift, Cpsr<29:>) }}, + {{ Cpsr<28:> }}); + 0x2: subs_rs({{ + uint32_t resTemp, + val2 = Rm_Rs; + Rd = resTemp = Rn - val2; + }}, + {{ arm_sub_carry(resTemp, Rn, val2) }}, + {{ arm_sub_overflow(resTemp, Rn, val2) }}); + 0x3: rsbs_rs({{ + uint32_t resTemp, + val2 = Rm_Rs; + Rd = resTemp = val2 - Rn; + }}, + {{ arm_sub_carry(resTemp, val2, Rn) }}, + {{ arm_sub_overflow(resTemp, val2, Rn) }}); + 0x4: adds_rs({{ + uint32_t resTemp, + val2 = Rm_Rs; + Rd = resTemp = Rn + val2; + }}, + {{ arm_add_carry(resTemp, Rn, val2) }}, + {{ arm_add_overflow(resTemp, Rn, val2) }}); + 0x5: adcs_rs({{ + uint32_t resTemp, + val2 = Rm_Rs; + Rd = resTemp = Rn + val2 + Cpsr<29:>; + }}, + {{ arm_add_carry(resTemp, Rn, val2) }}, + {{ arm_add_overflow(resTemp, Rn, val2) }}); + 0x6: sbcs_rs({{ + uint32_t resTemp, + val2 = Rm_Rs; + Rd = resTemp = Rn - val2 + Cpsr<29:> - 1; + }}, + {{ arm_sub_carry(resTemp, Rn, val2) }}, + {{ arm_sub_overflow(resTemp, Rn, val2) }}); + 0x7: rscs_rs({{ + uint32_t resTemp, + val2 = Rm_Rs; + Rd = resTemp = val2 - Rn + Cpsr<29:> - 1; + }}, + {{ arm_sub_carry(resTemp, val2, Rn) }}, + {{ arm_sub_overflow(resTemp, val2, Rn) }}); + 0x8: tst_rs({{ + uint32_t resTemp; + resTemp = Rn & Rm_Rs; + }}, + {{ shift_carry_rs(Rm, Rs, shift, Cpsr<29:>) }}, + {{ Cpsr<28:> }}); + 0x9: teq_rs({{ + uint32_t resTemp; + resTemp = Rn ^ Rm_Rs; + }}, + {{ shift_carry_rs(Rm, Rs, shift, Cpsr<29:>) }}, + {{ Cpsr<28:> }}); + 0xa: cmp_rs({{ + uint32_t resTemp, + val2 = Rm_Rs; + resTemp = Rn - val2; + }}, + {{ arm_sub_carry(resTemp, Rn, val2) }}, + {{ arm_sub_overflow(resTemp, Rn, val2) }}); + 0xb: cmn_rs({{ + uint32_t resTemp, + val2 = Rm_Rs; + resTemp = Rn + val2; + }}, + {{ arm_add_carry(resTemp, Rn, val2) }}, + {{ arm_add_overflow(resTemp, Rn, val2) }}); + 0xc: orrs_rs({{ + uint32_t resTemp, + val2 = Rm_Rs; + Rd = resTemp = Rn | val2; + }}, + {{ shift_carry_rs(Rm, Rs, shift, Cpsr<29:>) }}, + {{ Cpsr<28:> }}); + 0xd: movs_rs({{ + uint32_t resTemp; + Rd = resTemp = Rm_Rs; + }}, + {{ shift_carry_rs(Rm, Rs, shift, Cpsr<29:>) }}, + {{ Cpsr<28:> }}); + 0xe: bics_rs({{ + uint32_t resTemp; + Rd = resTemp = Rn & ~Rm_Rs; + }}, + {{ shift_carry_rs(Rm, Rs, shift, Cpsr<29:>) }}, + {{ Cpsr<28:> }}); + 0xf: mvns_rs({{ + uint32_t resTemp; + Rd = resTemp = ~Rm_Rs; + }}, + {{ shift_carry_rs(Rm, Rs, shift, Cpsr<29:>) }}, + {{ Cpsr<28:> }}); + } + } + } + 1: decode OPCODE_6_5 { + 0x0: decode OPCODE_24 { + 0: decode LUAS { + format PredIntOp { + 0x0: mul({{ Rn = Rm * Rs; }}); + 0x1: PredIntOpCc::muls({{ + uint32_t resTemp; + Rn = resTemp = Rm * Rs; + }}, + {{ Cpsr<29:> }}, + {{ Cpsr<28:> }}); + 0x2: mla_a({{ Rn = Rm * Rs + Rd; }}); + 0x8: umull_l({{ + uint64_t resTemp; + resTemp = ((uint64_t)Rm)*((uint64_t)Rs); + Rd = (uint32_t)(resTemp & 0xffffffff); + Rn = (uint32_t)(resTemp >> 32); + }}); + 0xa: umlal_lu({{ + uint64_t resTemp; + resTemp = ((uint64_t)Rm)*((uint64_t)Rs); + resTemp += ((uint64_t)Rn << 32)+((uint64_t)Rd); + Rd = (uint32_t)(resTemp & 0xffffffff); + Rn = (uint32_t)(resTemp >> 32); + }}); + 0xc: smull_lu({{ + int64_t resTemp; + resTemp = ((int64_t)Rm)*((int64_t)Rs); + Rd = (int32_t)(resTemp & 0xffffffff); + Rn = (int32_t)(resTemp >> 32); + }}); + } + } + } + 0x1: decode PUIWL { + 0x04,0x0c: ArmStoreMemory::strh_i({{ Mem.uh = Rd.uh; + Rn = Rn + hilo; }}, + {{ EA = Rn; }}); + 0x05,0x0d: ArmLoadMemory::ldrh_il({{ Rd.uh = Mem.uh; + Rn = Rn + hilo; }}, + {{ EA = Rn; }}); + 0x10,0x18: ArmStoreMemory::strh_p({{ Mem.uh = Rd.uh; }}, + {{ EA = Rn + Rm; }}); + 0x11,0x19: ArmLoadMemory::ldrh_pl({{ Rd.uh = Mem.uh; }}, + {{ EA = Rn + Rm; }}); + 0x12,0x1a: ArmStoreMemory::strh_pw({{ Mem.uh = Rd.uh; + Rn = Rn + Rm; }}, + {{ EA = Rn + Rm; }}); + 0x13,0x1b: ArmLoadMemory::ldrh_pwl({{ Rd.uh = Mem.uh; + Rn = Rn + Rm; }}, + {{ EA = Rn + Rm; }}); + 0x14,0x1c: ArmStoreMemory::strh_pi({{ Mem.uh = Rd.uh; }}, + {{ EA = Rn + hilo; }}); + 0x15,0x1d: ArmLoadMemory::ldrh_pil({{ Rd.uh = Mem.uh; }}, + {{ EA = Rn + hilo; }}); + 0x16,0x1e: ArmStoreMemory::strh_piw({{ Mem.uh = Rd.uh; + Rn = Rn + hilo; }}, + {{ EA = Rn + hilo; }}); + 0x17,0x1f: ArmLoadMemory::ldrh_piwl({{ Rd.uh = Mem.uh; + Rn = Rn + hilo; }}, + {{ EA = Rn + hilo; }}); + } + 0x2: decode PUIWL { + format ArmLoadMemory { + 0x11,0x19: ldrsb_pl({{ Rd.sb = Mem.sb; }}, + {{ EA = Rn + Rm; }}); + 0x13,0x1b: ldrsb_pwl({{ Rd.sb = Mem.sb; + Rn = Rn + Rm; }}, + {{ EA = Rn + Rm; }}); + 0x15,0x1d: ldrsb_pil({{ Rd.sb = Mem.sb; }}, + {{ EA = Rn + hilo; }}); + 0x17,0x1f: ldrsb_piwl({{ Rd.sb = Mem.sb; + Rn = Rn + hilo; }}, + {{ EA = Rn + hilo; }}); + } + } + 0x3: decode PUIWL { + format ArmLoadMemory { + 0x11,0x19: ldrsh_pl({{ Rd.sh = Mem.sh; }}, + {{ EA = Rn + Rm; }}); + 0x13,0x1b: ldrsh_pwl({{ Rd.sh = Mem.sh; + Rn = Rn + Rm; }}, + {{ EA = Rn + Rm; }}); + 0x15,0x1d: ldrsh_pil({{ Rd.sh = Mem.sh; }}, + {{ EA = Rn + hilo; }}); + 0x17,0x1f: ldrsh_piwl({{ Rd.sh = Mem.sh; + Rn = Rn + hilo; }}, + {{ EA = Rn + hilo; }}); + } + } + } + } + } + 0x1: decode S_FIELD { + 0: decode OPCODE_24_21 { + format PredImmOp { + 0x0: andi({{ Rd = Rn & rotated_imm; }}); + 0x1: eori({{ Rd = Rn ^ rotated_imm; }}); + 0x2: subi({{ Rd = Rn - rotated_imm; }}); + 0x3: rsbi({{ Rd = rotated_imm - Rn; }}); + 0x4: addi({{ Rd = Rn + rotated_imm; }}); + 0x5: adci({{ Rd = Rn + rotated_imm + Cpsr<29:>; }}); + 0x6: sbci({{ Rd = Rn - rotated_imm + Cpsr<29:> - 1; }}); + 0x7: rsci({{ Rd = rotated_imm - Rn + Cpsr<29:> - 1; }}); + 0xc: orri({{ Rd = Rn | rotated_imm; }}); + 0xd: decode RN { + 0: movi({{ Rd = rotated_imm; }}); + } + 0xe: bici({{ Rd = Rn & ~rotated_imm; }}); + 0xf: decode RN { + 0: mvni({{ Rd = ~rotated_imm; }}); + } + } + } + 1: decode OPCODE_24_21 { + format PredImmOpCc { + 0x0: andsi({{ + uint32_t resTemp; + Rd = resTemp = Rn & rotated_imm; + }}, + {{ (rotate ? rotated_carry:Cpsr<29:>) }}, + {{ Cpsr<28:> }}); + 0x1: eorsi({{ + uint32_t resTemp; + Rd = resTemp = Rn ^ rotated_imm; + }}, + {{ (rotate ? rotated_carry:Cpsr<29:>) }}, + {{ Cpsr<28:> }}); + 0x2: subsi({{ + uint32_t resTemp; + Rd = resTemp = Rn - rotated_imm; + }}, + {{ arm_sub_carry(resTemp, Rn, rotated_imm) }}, + {{ arm_sub_overflow(resTemp, Rn, rotated_imm) }}); + 0x3: rsbsi({{ + uint32_t resTemp; + Rd = resTemp = rotated_imm - Rn; + }}, + {{ arm_sub_carry(resTemp, rotated_imm, Rn) }}, + {{ arm_sub_overflow(resTemp, rotated_imm, Rn) }}); + 0x4: addsi({{ + uint32_t resTemp; + Rd = resTemp = Rn + rotated_imm; + }}, + {{ arm_add_carry(resTemp, Rn, rotated_imm) }}, + {{ arm_add_overflow(resTemp, Rn, rotated_imm) }}); + 0x5: adcsi({{ + uint32_t resTemp; + Rd = resTemp = Rn + rotated_imm + Cpsr<29:>; + }}, + {{ arm_add_carry(resTemp, Rn, rotated_imm) }}, + {{ arm_add_overflow(resTemp, Rn, rotated_imm) }}); + 0x6: sbcsi({{ + uint32_t resTemp; + Rd = resTemp = Rn -rotated_imm + Cpsr<29:> - 1; + }}, + {{ arm_sub_carry(resTemp, Rn, rotated_imm) }}, + {{ arm_sub_overflow(resTemp, Rn, rotated_imm) }}); + 0x7: rscsi({{ + uint32_t resTemp; + Rd = resTemp = rotated_imm - Rn + Cpsr<29:> - 1; + }}, + {{ arm_sub_carry(resTemp, rotated_imm, Rn) }}, + {{ arm_sub_overflow(resTemp, rotated_imm, Rn) }}); + 0x8: tsti({{ + uint32_t resTemp; + resTemp = Rn & rotated_imm; + }}, + {{ (rotate ? rotated_carry:Cpsr<29:>) }}, + {{ Cpsr<28:> }}); + 0x9: teqi({{ + uint32_t resTemp; + resTemp = Rn ^ rotated_imm; + }}, + {{ (rotate ? rotated_carry:Cpsr<29:>) }}, + {{ Cpsr<28:> }}); + 0xa: cmpi({{ + uint32_t resTemp; + resTemp = Rn - rotated_imm; + }}, + {{ arm_sub_carry(resTemp, Rn, rotated_imm) }}, + {{ arm_sub_overflow(resTemp, Rn, rotated_imm) }}); + 0xb: cmni({{ + uint32_t resTemp; + resTemp = Rn + rotated_imm; + }}, + {{ arm_add_carry(resTemp, Rn, rotated_imm) }}, + {{ arm_add_overflow(resTemp, Rn, rotated_imm) }}); + 0xc: orrsi({{ + uint32_t resTemp; + Rd = resTemp = Rn | rotated_imm; + }}, + {{ (rotate ? rotated_carry:Cpsr<29:>) }}, + {{ Cpsr<28:> }}); + 0xd: movsi({{ + uint32_t resTemp; + Rd = resTemp = rotated_imm; + }}, + {{ (rotate ? rotated_carry:Cpsr<29:>) }}, + {{ Cpsr<28:> }}); + 0xe: bicsi({{ + uint32_t resTemp; + Rd = resTemp = Rn & ~rotated_imm; + }}, + {{ (rotate ? rotated_carry:Cpsr<29:>) }}, + {{ Cpsr<28:> }}); + 0xf: mvnsi({{ + uint32_t resTemp; + Rd = resTemp = ~rotated_imm; + }}, + {{ (rotate ? rotated_carry:Cpsr<29:>) }}, + {{ Cpsr<28:> }}); + } + } + } + 0x2: decode PUBWL { + // CAREFUL: + // Can always do EA + disp, since we negate disp using the UP flag + // Post-indexed variants + 0x00,0x08: ArmStoreMemory::str_({{ Mem = Rd; + Rn = Rn + disp; }}, + {{ EA = Rn; }}); + 0x01,0x09: ArmLoadMemory::ldr_l({{ Rd = Mem; + Rn = Rn + disp; }}, + {{ EA = Rn; }}); + 0x04,0x0c: ArmStoreMemory::strb_b({{ Mem.ub = Rd.ub; + Rn = Rn + disp; }}, + {{ EA = Rn; }}); + 0x05,0x0d: ArmLoadMemory::ldrb_bl({{ Rd.ub = Mem.ub; + Rn = Rn + disp; }}, + {{ EA = Rn; }}); + // Pre-indexed variants + 0x10,0x18: ArmStoreMemory::str_p({{ Mem = Rd; }}); + 0x11,0x19: ArmLoadMemory::ldr_pl({{ Rd = Mem; }}); + 0x12,0x1a: ArmStoreMemory::str_pw({{ Mem = Rd; + Rn = Rn + disp; }}); + 0x13,0x1b: ArmLoadMemory::ldr_pwl({{ Rd = Mem; + Rn = Rn + disp; }}); + 0x14,0x1c: ArmStoreMemory::strb_pb({{ Mem.ub = Rd.ub; }}); + 0x15,0x1d: ArmLoadMemory::ldrb_pbl({{ Rd.ub = Mem.ub; }}); + 0x16,0x1e: ArmStoreMemory::strb_pbw({{ Mem.ub = Rd.ub; + Rn = Rn + disp; }}); + 0x17,0x1f: ArmLoadMemory::ldrb_pbwl({{ Rd.ub = Mem.ub; + Rn = Rn + disp; }}); + } + 0x3: decode OPCODE_4 { + 0: decode PUBWL { + 0x00,0x08: ArmStoreMemory::strr_({{ + Mem = Rd; + Rn = Rn + Rm_Imm; }}, + {{ EA = Rn; }}); + 0x01,0x09: ArmLoadMemory::ldrr_l({{ + Rd = Mem; + Rn = Rn + Rm_Imm; }}, + {{ EA = Rn; }}); + 0x04,0x0c: ArmStoreMemory::strr_b({{ + Mem.ub = Rd.ub; + Rn = Rn + Rm_Imm; }}, + {{ EA = Rn; }}); + 0x05,0x0d: ArmLoadMemory::ldrr_bl({{ + Rd.ub = Mem.ub; + Rn = Rn + Rm_Imm; }}, + {{ EA = Rn; }}); + 0x10,0x18: ArmStoreMemory::strr_p({{ + Mem = Rd; }}, + {{ EA = Rn + Rm_Imm; }}); + 0x11,0x19: ArmLoadMemory::ldrr_pl({{ + Rd = Mem; }}, + {{ EA = Rn + Rm_Imm; }}); + 0x12,0x1a: ArmStoreMemory::strr_pw({{ + Mem = Rd; + Rn = Rn + Rm_Imm; }}, + {{ EA = Rn + Rm_Imm; }}); + 0x13,0x1b: ArmLoadMemory::ldrr_pwl({{ + Rd = Mem; + Rn = Rn + Rm_Imm; }}, + {{ EA = Rn + Rm_Imm; }}); + 0x14,0x1c: ArmStoreMemory::strr_pb({{ + Mem.ub = Rd.ub; }}, + {{ EA = Rn + Rm_Imm; }}); + 0x15,0x1d: ArmLoadMemory::ldrr_pbl({{ + Rd.ub = Mem.ub; }}, + {{ EA = Rn + Rm_Imm; }}); + 0x16,0x1e: ArmStoreMemory::strr_pbw({{ + Mem.ub = Rd.ub; + Rn = Rn + Rm_Imm; }}, + {{ EA = Rn + Rm_Imm; }}); + 0x17,0x1f: ArmLoadMemory::ldrr_pbwl({{ + Rd.ub = Mem.ub; + Rn = Rn + Rm_Imm; }}, + {{ EA = Rn + Rm_Imm; }}); + } + } + 0x4: decode PUSWL { + // Right now we only handle cases when S (PSRUSER) is not set + default: ArmMacroStore::ldmstm({{ }}); + } + 0x5: decode OPCODE_24 { + // Branch (and Link) Instructions + 0: Branch::b({{ }}); + 1: Branch::bl({{ LR = NPC; }}); + } + 0x6: decode CPNUM { + 0x1: decode PUNWL { + 0x02,0x0a: decode OPCODE_15 { + 0: ArmStoreMemory::stfs_({{ Mem.sf = Fd.sf; + Rn = Rn + disp8; }}, + {{ EA = Rn; }}); + 1: ArmMacroFPAOp::stfd_({{ }}); + } + 0x03,0x0b: decode OPCODE_15 { + 0: ArmLoadMemory::ldfs_({{ Fd.sf = Mem.sf; + Rn = Rn + disp8; }}, + {{ EA = Rn; }}); + 1: ArmMacroFPAOp::ldfd_({{ }}); + } + 0x06,0x0e: decode OPCODE_15 { + 0: ArmMacroFPAOp::stfe_nw({{ }}); + } + 0x07,0x0f: decode OPCODE_15 { + 0: ArmMacroFPAOp::ldfe_nw({{ }}); + } + 0x10,0x18: decode OPCODE_15 { + 0: ArmStoreMemory::stfs_p({{ Mem.sf = Fd.sf; }}, + {{ EA = Rn + disp8; }}); + 1: ArmMacroFPAOp::stfd_p({{ }}); + } + 0x11,0x19: decode OPCODE_15 { + 0: ArmLoadMemory::ldfs_p({{ Fd.sf = Mem.sf; }}, + {{ EA = Rn + disp8; }}); + 1: ArmMacroFPAOp::ldfd_p({{ }}); + } + 0x12,0x1a: decode OPCODE_15 { + 0: ArmStoreMemory::stfs_pw({{ Mem.sf = Fd.sf; + Rn = Rn + disp8; }}, + {{ EA = Rn + disp8; }}); + 1: ArmMacroFPAOp::stfd_pw({{ }}); + } + 0x13,0x1b: decode OPCODE_15 { + 0: ArmLoadMemory::ldfs_pw({{ Fd.sf = Mem.sf; + Rn = Rn + disp8; }}, + {{ EA = Rn + disp8; }}); + 1: ArmMacroFPAOp::ldfd_pw({{ }}); + } + 0x14,0x1c: decode OPCODE_15 { + 0: ArmMacroFPAOp::stfe_pn({{ }}); + } + 0x15,0x1d: decode OPCODE_15 { + 0: ArmMacroFPAOp::ldfe_pn({{ }}); + } + 0x16,0x1e: decode OPCODE_15 { + 0: ArmMacroFPAOp::stfe_pnw({{ }}); + } + 0x17,0x1f: decode OPCODE_15 { + 0: ArmMacroFPAOp::ldfe_pnw({{ }}); + } + } + 0x2: decode PUNWL { + // could really just decode as a single instruction + 0x00,0x04,0x08,0x0c: ArmMacroFMOp::sfm_({{ }}); + 0x01,0x05,0x09,0x0d: ArmMacroFMOp::lfm_({{ }}); + 0x02,0x06,0x0a,0x0e: ArmMacroFMOp::sfm_w({{ }}); + 0x03,0x07,0x0b,0x0f: ArmMacroFMOp::lfm_w({{ }}); + 0x10,0x14,0x18,0x1c: ArmMacroFMOp::sfm_p({{ }}); + 0x11,0x15,0x19,0x1d: ArmMacroFMOp::lfm_p({{ }}); + 0x12,0x16,0x1a,0x1e: ArmMacroFMOp::sfm_pw({{ }}); + 0x13,0x17,0x1b,0x1f: ArmMacroFMOp::lfm_pw({{ }}); + } + } + 0x7: decode OPCODE_24 { + 0: decode CPNUM { + // Coprocessor Instructions + 0x1: decode OPCODE_4 { + format FloatOp { + // Basic FPA Instructions + 0: decode OPCODE_23_20 { + 0x0: decode OPCODE_15 { + 0: adf({{ Fd.sf = Fn.sf + Fm.sf; }}); + 1: mvf({{ Fd.sf = Fm.sf; }}); + } + 0x1: decode OPCODE_15 { + 0: muf({{ Fd.sf = Fn.sf * Fm.sf; }}); + 1: mnf({{ Fd.sf = -Fm.sf; }}); + } + 0x2: decode OPCODE_15 { + 0: suf({{ Fd.sf = Fn.sf - Fm.sf; }}); + 1: abs({{ Fd.sf = fabs(Fm.sf); }}); + } + 0x3: decode OPCODE_15 { + 0: rsf({{ Fd.sf = Fm.sf - Fn.sf; }}); + 1: rnd({{ Fd.sf = rint(Fm.sf); }}); + } + 0x4: decode OPCODE_15 { + 0: dvf({{ Fd.sf = Fn.sf / Fm.sf; }}); + 1: sqt({{ Fd.sf = sqrt(Fm.sf); }}); + } + 0x5: decode OPCODE_15 { + 0: rdf({{ Fd.sf = Fm.sf / Fn.sf; }}); + 1: log({{ Fd.sf = log10(Fm.sf); }}); + } + 0x6: decode OPCODE_15 { + 0: pow({{ Fd.sf = pow(Fm.sf, Fn.sf); }}); + 1: lgn({{ Fd.sf = log(Fm.sf); }}); + } + 0x7: decode OPCODE_15 { + 0: rpw({{ Fd.sf = pow(Fn.sf, Fm.sf); }}); + 1: exp({{ Fd.sf = exp(Fm.sf); }}); + } + 0x8: decode OPCODE_15 { + 0: rmf({{ Fd.sf = drem(Fn.sf, Fm.sf); }}); + 1: sin({{ Fd.sf = sin(Fm.sf); }}); + } + 0x9: decode OPCODE_15 { + 0: fml({{ Fd.sf = Fn.sf * Fm.sf; }}); + 1: cos({{ Fd.sf = cos(Fm.sf); }}); + } + 0xa: decode OPCODE_15 { + 0: fdv({{ Fd.sf = Fn.sf / Fm.sf; }}); + 1: tan({{ Fd.sf = tan(Fm.sf); }}); + } + 0xb: decode OPCODE_15 { + 0: frd({{ Fd.sf = Fm.sf / Fn.sf; }}); + 1: asn({{ Fd.sf = asin(Fm.sf); }}); + } + 0xc: decode OPCODE_15 { + 0: pol({{ Fd.sf = atan2(Fn.sf, Fm.sf); }}); + 1: acs({{ Fd.sf = acos(Fm.sf); }}); + } + 0xd: decode OPCODE_15 { + 1: atn({{ Fd.sf = atan(Fm.sf); }}); + } + 0xe: decode OPCODE_15 { + // Unnormalised Round + 1: FailUnimpl::urd(); + } + 0xf: decode OPCODE_15 { + // Normalise + 1: FailUnimpl::nrm(); + } + } + 1: decode OPCODE_15_12 { + 0xf: decode OPCODE_23_21 { + format FloatCmp { + 0x4: cmf({{ Fn.df }}, {{ Fm.df }}); + 0x5: cnf({{ Fn.df }}, {{ -Fm.df }}); + 0x6: cmfe({{ Fn.df }}, {{ Fm.df}}); + 0x7: cnfe({{ Fn.df }}, {{ -Fm.df}}); + } + } + default: decode OPCODE_23_20 { + 0x0: decode OPCODE_7 { + 0: flts({{ Fn.sf = (float) Rd.sw; }}); + 1: fltd({{ Fn.df = (double) Rd.sw; }}); + } + 0x1: decode OPCODE_7 { + 0: fixs({{ Rd = (uint32_t) Fm.sf; }}); + 1: fixd({{ Rd = (uint32_t) Fm.df; }}); + } + 0x2: wfs({{ Fpsr = Rd; }}); + 0x3: rfs({{ Rd = Fpsr; }}); + 0x4: FailUnimpl::wfc(); + 0x5: FailUnimpl::rfc(); + } + } + } + } + } + format PredOp { + // ARM System Call (SoftWare Interrupt) + 1: swi({{ if (arm_predicate(xc->readMiscReg(ArmISA::CPSR), + condCode)) + { + //xc->syscall(R7); + xc->syscall(IMMED_23_0); + } + }}); + } + } + } + } +} + diff --git a/src/arch/arm/isa/formats/basic.isa b/src/arch/arm/isa/formats/basic.isa new file mode 100644 index 000000000..d154b987c --- /dev/null +++ b/src/arch/arm/isa/formats/basic.isa @@ -0,0 +1,103 @@ +// -*- mode:c++ -*- + +// Copyright (c) 2007-2008 The Florida State University +// 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: Stephen Hines + +// Declarations for execute() methods. +def template BasicExecDeclare {{ + Fault execute(%(CPU_exec_context)s *, Trace::InstRecord *) const; +}}; + +// Basic instruction class declaration template. +def template BasicDeclare {{ + /** + * Static instruction class for "%(mnemonic)s". + */ + class %(class_name)s : public %(base_class)s + { + public: + /// Constructor. + %(class_name)s(MachInst machInst); + %(BasicExecDeclare)s + }; +}}; + +// Basic instruction class constructor template. +def template BasicConstructor {{ + inline %(class_name)s::%(class_name)s(MachInst machInst) : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s) + { + %(constructor)s; + } +}}; + + +// Basic instruction class execute method template. +def template BasicExecute {{ + Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, Trace::InstRecord *traceData) const + { + Fault fault = NoFault; + + %(fp_enable_check)s; + %(op_decl)s; + %(op_rd)s; + %(code)s; + + if (fault == NoFault) + { + %(op_wb)s; + } + return fault; + } +}}; + +// Basic decode template. +def template BasicDecode {{ + return new %(class_name)s(machInst); +}}; + +// Basic decode template, passing mnemonic in as string arg to constructor. +def template BasicDecodeWithMnemonic {{ + return new %(class_name)s("%(mnemonic)s", machInst); +}}; + +// Definitions of execute methods that panic. +def template BasicExecPanic {{ +Fault execute(%(CPU_exec_context)s *, Trace::InstRecord *) const +{ + panic("Execute method called when it shouldn't!"); +} +}}; + +// The most basic instruction format... +def format BasicOp(code, *flags) {{ + iop = InstObjParams(name, Name, 'ArmStaticInst', code, flags) + header_output = BasicDeclare.subst(iop) + decoder_output = BasicConstructor.subst(iop) + decode_block = BasicDecode.subst(iop) + exec_output = BasicExecute.subst(iop) +}}; diff --git a/src/arch/arm/isa/formats/branch.isa b/src/arch/arm/isa/formats/branch.isa new file mode 100644 index 000000000..40aa4a952 --- /dev/null +++ b/src/arch/arm/isa/formats/branch.isa @@ -0,0 +1,307 @@ +// -*- mode:c++ -*- + +// Copyright (c) 2007-2008 The Florida State University +// 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: Stephen Hines + +//////////////////////////////////////////////////////////////////// +// +// Control transfer instructions +// + +output header {{ + +#include <iostream> + + /** + * Base class for instructions whose disassembly is not purely a + * function of the machine instruction (i.e., it depends on the + * PC). This class overrides the disassemble() method to check + * the PC and symbol table values before re-using a cached + * disassembly string. This is necessary for branches and jumps, + * where the disassembly string includes the target address (which + * may depend on the PC and/or symbol table). + */ + class PCDependentDisassembly : public PredOp + { + protected: + /// Cached program counter from last disassembly + mutable Addr cachedPC; + + /// Cached symbol table pointer from last disassembly + mutable const SymbolTable *cachedSymtab; + + /// Constructor + PCDependentDisassembly(const char *mnem, MachInst _machInst, + OpClass __opClass) + : PredOp(mnem, _machInst, __opClass), + cachedPC(0), cachedSymtab(0) + { + } + + const std::string & + disassemble(Addr pc, const SymbolTable *symtab) const; + }; + + /** + * Base class for branches (PC-relative control transfers), + * conditional or unconditional. + */ + class Branch : public PCDependentDisassembly + { + protected: + /// target address (signed) Displacement . + int32_t disp; + + /// Constructor. + Branch(const char *mnem, MachInst _machInst, OpClass __opClass) + : PCDependentDisassembly(mnem, _machInst, __opClass), + disp(OFFSET << 2) + { + //If Bit 26 is 1 then Sign Extend + if ( (disp & 0x02000000) > 0 ) { + disp |= 0xFC000000; + } + } + + Addr branchTarget(Addr branchPC) const; + + std::string + generateDisassembly(Addr pc, const SymbolTable *symtab) const; + }; + + /** + * Base class for branch and exchange instructions on the ARM + */ + class BranchExchange : public PredOp + { + protected: + /// Constructor + BranchExchange(const char *mnem, MachInst _machInst, + OpClass __opClass) + : PredOp(mnem, _machInst, __opClass) + { + } + + std::string + generateDisassembly(Addr pc, const SymbolTable *symtab) const; + }; + + + /** + * Base class for jumps (register-indirect control transfers). In + * the Arm ISA, these are always unconditional. + */ + class Jump : public PCDependentDisassembly + { + protected: + + /// Displacement to target address (signed). + int32_t disp; + + uint32_t target; + + public: + /// Constructor + Jump(const char *mnem, MachInst _machInst, OpClass __opClass) + : PCDependentDisassembly(mnem, _machInst, __opClass), + disp(OFFSET << 2) + { + } + + Addr branchTarget(ThreadContext *tc) const; + + std::string + generateDisassembly(Addr pc, const SymbolTable *symtab) const; + }; +}}; + +output decoder {{ + Addr + Branch::branchTarget(Addr branchPC) const + { + return branchPC + 8 + disp; + } + + Addr + Jump::branchTarget(ThreadContext *tc) const + { + Addr NPC = tc->readPC() + 8; + uint64_t Rb = tc->readIntReg(_srcRegIdx[0]); + return (Rb & ~3) | (NPC & 1); + } + + const std::string & + PCDependentDisassembly::disassemble(Addr pc, + const SymbolTable *symtab) const + { + if (!cachedDisassembly || + pc != cachedPC || symtab != cachedSymtab) + { + if (cachedDisassembly) + delete cachedDisassembly; + + cachedDisassembly = + new std::string(generateDisassembly(pc, symtab)); + cachedPC = pc; + cachedSymtab = symtab; + } + + return *cachedDisassembly; + } + + std::string + Branch::generateDisassembly(Addr pc, const SymbolTable *symtab) const + { + std::stringstream ss; + + ccprintf(ss, "%-10s ", mnemonic); + + Addr target = pc + 8 + disp; + + std::string str; + if (symtab && symtab->findSymbol(target, str)) + ss << str; + else + ccprintf(ss, "0x%x", target); + + return ss.str(); + } + + std::string + BranchExchange::generateDisassembly(Addr pc, const SymbolTable *symtab) const + { + std::stringstream ss; + + ccprintf(ss, "%-10s ", mnemonic); + + if (_numSrcRegs > 0) { + printReg(ss, _srcRegIdx[0]); + } + + return ss.str(); + } + + std::string + Jump::generateDisassembly(Addr pc, const SymbolTable *symtab) const + { + std::stringstream ss; + + ccprintf(ss, "%-10s ", mnemonic); + + return ss.str(); + } +}}; + +def format Branch(code,*opt_flags) {{ + + #Build Instruction Flags + #Use Link & Likely Flags to Add Link/Condition Code + inst_flags = ('IsDirectControl', ) + for x in opt_flags: + if x == 'Link': + code += 'LR = NPC;\n' + else: + inst_flags += (x, ) + + #Take into account uncond. branch instruction + if 'cond == 1' in code: + inst_flags += ('IsUnCondControl', ) + else: + inst_flags += ('IsCondControl', ) + + icode = 'if (arm_predicate(xc->readMiscReg(ArmISA::CPSR), condCode)) {\n' + icode += code + icode += ' NPC = NPC + 4 + disp;\n' + icode += '} else {\n' + icode += ' NPC = NPC;\n' + icode += '};\n' + + code = icode + + iop = InstObjParams(name, Name, 'Branch', code, inst_flags) + header_output = BasicDeclare.subst(iop) + decoder_output = BasicConstructor.subst(iop) + decode_block = BasicDecode.subst(iop) + exec_output = BasicExecute.subst(iop) +}}; + +def format BranchExchange(code,*opt_flags) {{ + #Build Instruction Flags + #Use Link & Likely Flags to Add Link/Condition Code + inst_flags = ('IsIndirectControl', ) + for x in opt_flags: + if x == 'Link': + code += 'LR = NPC;\n' + else: + inst_flags += (x, ) + + #Take into account uncond. branch instruction + if 'cond == 1' in code: + inst_flags += ('IsUnCondControl', ) + else: + inst_flags += ('IsCondControl', ) + + #Condition code + + icode = 'if (arm_predicate(xc->readMiscReg(ArmISA::CPSR), condCode)) {\n' + icode += code + icode += ' NPC = Rm & 0xfffffffe; // Masks off bottom bit\n' + icode += '} else {\n' + icode += ' NPC = NPC;\n' + icode += '};\n' + + code = icode + + iop = InstObjParams(name, Name, 'BranchExchange', code, inst_flags) + header_output = BasicDeclare.subst(iop) + decoder_output = BasicConstructor.subst(iop) + decode_block = BasicDecode.subst(iop) + exec_output = BasicExecute.subst(iop) +}}; + +def format Jump(code, *opt_flags) {{ + #Build Instruction Flags + #Use Link Flag to Add Link Code + inst_flags = ('IsIndirectControl', 'IsUncondControl') + for x in opt_flags: + if x == 'Link': + code = 'LR = NPC;\n' + code + elif x == 'ClearHazards': + code += '/* Code Needed to Clear Execute & Inst Hazards */\n' + else: + inst_flags += (x, ) + + iop = InstObjParams(name, Name, 'Jump', code, inst_flags) + header_output = BasicDeclare.subst(iop) + decoder_output = BasicConstructor.subst(iop) + decode_block = BasicDecode.subst(iop) + exec_output = BasicExecute.subst(iop) + #exec_output = PredOpExecute.subst(iop) +}}; + + diff --git a/src/arch/arm/isa/formats/formats.isa b/src/arch/arm/isa/formats/formats.isa new file mode 100644 index 000000000..5f6faa741 --- /dev/null +++ b/src/arch/arm/isa/formats/formats.isa @@ -0,0 +1,57 @@ +// -*- mode:c++ -*- + +// Copyright (c) 2007-2008 The Florida State University +// 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: Stephen Hines + +//Templates from this format are used later +//Include the basic format +##include "basic.isa" + +//Include support for predicated instructions +##include "pred.isa" + +//Include utility functions +##include "util.isa" + +//Include the float formats +##include "fp.isa" + +//Include the mem format +##include "mem.isa" + +//Include the macro-mem format +##include "macromem.isa" + +//Include the branch format +##include "branch.isa" + +//Include the unimplemented format +##include "unimp.isa" + +//Include the unknown format +##include "unknown.isa" diff --git a/src/arch/arm/isa/formats/fp.isa b/src/arch/arm/isa/formats/fp.isa new file mode 100644 index 000000000..682c76079 --- /dev/null +++ b/src/arch/arm/isa/formats/fp.isa @@ -0,0 +1,150 @@ +// -*- mode:c++ -*- + +// Copyright (c) 2007-2008 The Florida State University +// 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: Stephen Hines + +//////////////////////////////////////////////////////////////////// +// +// Floating Point operate instructions +// + +output header {{ + + /** + * Base class for FP operations. + */ + class FPAOp : public PredOp + { + protected: + + /// Constructor + FPAOp(const char *mnem, MachInst _machInst, OpClass __opClass) : PredOp(mnem, _machInst, __opClass) + { + } + + //std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; + }; + +}}; + +output exec {{ +}}; + +def template FPAExecute {{ + Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, Trace::InstRecord *traceData) const + { + Fault fault = NoFault; + + %(fp_enable_check)s; + + %(op_decl)s; + %(op_rd)s; + + %(code)s; + + if (arm_predicate(xc->readMiscReg(ArmISA::CPSR), condCode) && + fault == NoFault) + { + %(op_wb)s; + } + + return fault; + } +}}; + +def template FloatDoubleDecode {{ + { + ArmStaticInst *i = NULL; + switch (OPCODE_19 << 1 | OPCODE_7) + { + case 0: + i = (ArmStaticInst *)new %(class_name)sS(machInst); + break; + case 1: + i = (ArmStaticInst *)new %(class_name)sD(machInst); + break; + case 2: + case 3: + default: + panic("Cannot decode float/double nature of the instruction"); + } + return i; + } +}}; + +// Primary format for float point operate instructions: +def format FloatOp(code, *flags) {{ + orig_code = code + + cblk = code + iop = InstObjParams(name, Name, 'FPAOp', cblk, flags) + header_output = BasicDeclare.subst(iop) + decoder_output = BasicConstructor.subst(iop) + exec_output = FPAExecute.subst(iop) + + sng_cblk = code + sng_iop = InstObjParams(name, Name+'S', 'FPAOp', sng_cblk, flags) + header_output += BasicDeclare.subst(sng_iop) + decoder_output += BasicConstructor.subst(sng_iop) + exec_output += FPAExecute.subst(sng_iop) + + dbl_code = re.sub(r'\.sf', '.df', orig_code) + + dbl_cblk = dbl_code + dbl_iop = InstObjParams(name, Name+'D', 'FPAOp', dbl_cblk, flags) + header_output += BasicDeclare.subst(dbl_iop) + decoder_output += BasicConstructor.subst(dbl_iop) + exec_output += FPAExecute.subst(dbl_iop) + + decode_block = FloatDoubleDecode.subst(iop) +}}; + +let {{ + calcFPCcCode = ''' + uint16_t _in, _iz, _ic, _iv; + + _in = %(fReg1)s < %(fReg2)s; + _iz = %(fReg1)s == %(fReg2)s; + _ic = %(fReg1)s >= %(fReg2)s; + _iv = (isnan(%(fReg1)s) || isnan(%(fReg2)s)) & 1; + + Cpsr = _in << 31 | _iz << 30 | _ic << 29 | _iv << 28 | + (Cpsr & 0x0FFFFFFF); + ''' +}}; + +def format FloatCmp(fReg1, fReg2, *flags) {{ + code = calcFPCcCode % vars() + iop = InstObjParams(name, Name, 'FPAOp', code, flags) + header_output = BasicDeclare.subst(iop) + decoder_output = BasicConstructor.subst(iop) + decode_block = BasicDecode.subst(iop) + exec_output = FPAExecute.subst(iop) +}}; + + diff --git a/src/arch/arm/isa/formats/macromem.isa b/src/arch/arm/isa/formats/macromem.isa new file mode 100644 index 000000000..bc055d74e --- /dev/null +++ b/src/arch/arm/isa/formats/macromem.isa @@ -0,0 +1,389 @@ +// -*- mode:c++ -*- + +// Copyright (c) 2007-2008 The Florida State University +// 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: Stephen Hines + +//////////////////////////////////////////////////////////////////// +// +// Macro Memory-format instructions +// + +output header {{ + + /** + * Arm Macro Memory operations like LDM/STM + */ + class ArmMacroMemoryOp : public PredMacroOp + { + protected: + /// Memory request flags. See mem_req_base.hh. + unsigned memAccessFlags; + /// Pointer to EAComp object. + const StaticInstPtr eaCompPtr; + /// Pointer to MemAcc object. + const StaticInstPtr memAccPtr; + + uint32_t reglist; + uint32_t ones; + uint32_t puswl, + prepost, + up, + psruser, + writeback, + loadop; + + ArmMacroMemoryOp(const char *mnem, MachInst _machInst, OpClass __opClass, + StaticInstPtr _eaCompPtr = nullStaticInstPtr, + StaticInstPtr _memAccPtr = nullStaticInstPtr) + : PredMacroOp(mnem, _machInst, __opClass), + memAccessFlags(0), eaCompPtr(_eaCompPtr), memAccPtr(_memAccPtr), + reglist(REGLIST), ones(0), puswl(PUSWL), prepost(PREPOST), up(UP), + psruser(PSRUSER), writeback(WRITEBACK), loadop(LOADOP) + { + ones = number_of_ones(reglist); + numMicroops = ones + writeback + 1; + // Remember that writeback adds a uop + microOps = new StaticInstPtr[numMicroops]; + } + }; + + /** + * Arm Macro FPA operations to fix ldfd and stfd instructions + */ + class ArmMacroFPAOp : public PredMacroOp + { + protected: + uint32_t puswl, + prepost, + up, + psruser, + writeback, + loadop; + int32_t disp8; + + ArmMacroFPAOp(const char *mnem, MachInst _machInst, OpClass __opClass) + : PredMacroOp(mnem, _machInst, __opClass), + puswl(PUSWL), prepost(PREPOST), up(UP), + psruser(PSRUSER), writeback(WRITEBACK), loadop(LOADOP), + disp8(IMMED_7_0 << 2) + { + numMicroops = 3 + writeback; + microOps = new StaticInstPtr[numMicroops]; + } + }; + + /** + * Arm Macro FM operations to fix lfm and sfm + */ + class ArmMacroFMOp : public PredMacroOp + { + protected: + uint32_t punwl, + prepost, + up, + n1bit, + writeback, + loadop, + n0bit, + count; + int32_t disp8; + + ArmMacroFMOp(const char *mnem, MachInst _machInst, OpClass __opClass) + : PredMacroOp(mnem, _machInst, __opClass), + punwl(PUNWL), prepost(PREPOST), up(UP), + n1bit(OPCODE_22), writeback(WRITEBACK), loadop(LOADOP), + n0bit(OPCODE_15), disp8(IMMED_7_0 << 2) + { + // Transfer 1-4 registers based on n1 and n0 bits (with 00 repr. 4) + count = (n1bit << 1) | n0bit; + if (count == 0) + count = 4; + numMicroops = (3*count) + writeback; + microOps = new StaticInstPtr[numMicroops]; + } + }; + + +}}; + + +output decoder {{ +}}; + +def template MacroStoreDeclare {{ + /** + * Static instructions class for a store multiple instruction + */ + class %(class_name)s : public %(base_class)s + { + public: + // Constructor + %(class_name)s(MachInst machInst); + %(BasicExecDeclare)s + }; +}}; + +def template MacroStoreConstructor {{ + inline %(class_name)s::%(class_name)s(MachInst machInst) + : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s) + { + %(constructor)s; + uint32_t regs_to_handle = reglist; + uint32_t j = 0, + start_addr = 0, + end_addr = 0; + + switch (puswl) + { + case 0x01: // L ldmda_l + start_addr = (ones << 2) - 4; + end_addr = 0; + break; + case 0x03: // WL ldmda_wl + start_addr = (ones << 2) - 4; + end_addr = 0; + break; + case 0x08: // U stmia_u + start_addr = 0; + end_addr = (ones << 2) - 4; + break; + case 0x09: // U L ldmia_ul + start_addr = 0; + end_addr = (ones << 2) - 4; + break; + case 0x0b: // U WL ldmia + start_addr = 0; + end_addr = (ones << 2) - 4; + break; + case 0x11: // P L ldmdb + start_addr = (ones << 2); // U-bit is already 0 for subtract + end_addr = 4; // negative 4 + break; + case 0x12: // P W stmdb + start_addr = (ones << 2); // U-bit is already 0 for subtract + end_addr = 4; // negative 4 + break; + case 0x18: // PU stmib + start_addr = 4; + end_addr = (ones << 2) + 4; + break; + case 0x19: // PU L ldmib + start_addr = 4; + end_addr = (ones << 2) + 4; + break; + default: + panic("Unhandled Load/Store Multiple Instruction"); + break; + } + + //TODO - Add addi_uop/subi_uop here to create starting addresses + //Just using addi with 0 offset makes a "copy" of Rn for our use + uint32_t newMachInst = 0; + newMachInst = machInst & 0xffff0000; + microOps[0] = new Addi_uop(newMachInst); + + for (int i = 1; i < ones+1; i++) + { + // Get next available bit for transfer + while (! ( regs_to_handle & (1<<j))) + j++; + regs_to_handle &= ~(1<<j); + + microOps[i] = gen_ldrstr_uop(machInst, loadop, j, start_addr); + + if (up) + start_addr += 4; + else + start_addr -= 4; + } + + /* TODO: Take a look at how these 2 values should meet together + if (start_addr != (end_addr - 4)) + { + fprintf(stderr, "start_addr: %d\n", start_addr); + fprintf(stderr, "end_addr: %d\n", end_addr); + panic("start_addr does not meet end_addr"); + } + */ + + if (writeback) + { + uint32_t newMachInst = machInst & 0xf0000000; + uint32_t rn = (machInst >> 16) & 0x0f; + // 3322 2222 2222 1111 1111 11 + // 1098 7654 3210 9876 5432 1098 7654 3210 + // COND 0010 0100 [RN] [RD] 0000 [ IMM ] + // sub rn, rn, imm + newMachInst |= 0x02400000; + newMachInst |= ((rn << 16) | (rn << 12)); + newMachInst |= (ones << 2); + if (up) + { + microOps[numMicroops-1] = new Addi_rd_uop(newMachInst); + } + else + { + microOps[numMicroops-1] = new Subi_rd_uop(newMachInst); + } + } + microOps[numMicroops-1]->setLastMicroop(); + } + +}}; + +def template MacroStoreExecute {{ + Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, Trace::InstRecord *traceData) const + { + Fault fault = NoFault; + + %(fp_enable_check)s; + %(op_decl)s; + %(op_rd)s; + %(code)s; + if (fault == NoFault) + { + %(op_wb)s; + } + + return fault; + } +}}; + +def template MacroFPAConstructor {{ + inline %(class_name)s::%(class_name)s(MachInst machInst) + : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s) + { + %(constructor)s; + + uint32_t start_addr = 0; + + if (prepost) + start_addr = disp8; + else + start_addr = 0; + + emit_ldfstf_uops(microOps, 0, machInst, loadop, up, start_addr); + + if (writeback) + { + uint32_t newMachInst = machInst & 0xf0000000; + uint32_t rn = (machInst >> 16) & 0x0f; + // 3322 2222 2222 1111 1111 11 + // 1098 7654 3210 9876 5432 1098 7654 3210 + // COND 0010 0100 [RN] [RD] 0000 [ IMM ] + // sub rn, rn, imm + newMachInst |= 0x02400000; + newMachInst |= ((rn << 16) | (rn << 12)); + if (up) + { + newMachInst |= disp8; + microOps[numMicroops-1] = new Addi_rd_uop(newMachInst); + } + else + { + newMachInst |= disp8; + microOps[numMicroops-1] = new Subi_rd_uop(newMachInst); + } + } + microOps[numMicroops-1]->setLastMicroop(); + } + +}}; + + +def template MacroFMConstructor {{ + inline %(class_name)s::%(class_name)s(MachInst machInst) + : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s) + { + %(constructor)s; + + uint32_t start_addr = 0; + + if (prepost) + start_addr = disp8; + else + start_addr = 0; + + for (int i = 0; i < count; i++) + { + emit_ldfstf_uops(microOps, 3*i, machInst, loadop, up, start_addr); + } + + if (writeback) + { + uint32_t newMachInst = machInst & 0xf0000000; + uint32_t rn = (machInst >> 16) & 0x0f; + // 3322 2222 2222 1111 1111 11 + // 1098 7654 3210 9876 5432 1098 7654 3210 + // COND 0010 0100 [RN] [RD] 0000 [ IMM ] + // sub rn, rn, imm + newMachInst |= 0x02400000; + newMachInst |= ((rn << 16) | (rn << 12)); + if (up) + { + newMachInst |= disp8; + microOps[numMicroops-1] = new Addi_rd_uop(newMachInst); + } + else + { + newMachInst |= disp8; + microOps[numMicroops-1] = new Subi_rd_uop(newMachInst); + } + } + microOps[numMicroops-1]->setLastMicroop(); + } + +}}; + + +def format ArmMacroStore(code, mem_flags = [], inst_flag = [], *opt_flags) {{ + iop = InstObjParams(name, Name, 'ArmMacroMemoryOp', code, opt_flags) + header_output = MacroStoreDeclare.subst(iop) + decoder_output = MacroStoreConstructor.subst(iop) + decode_block = BasicDecode.subst(iop) + exec_output = MacroStoreExecute.subst(iop) +}}; + +def format ArmMacroFPAOp(code, mem_flags = [], inst_flag = [], *opt_flags) {{ + iop = InstObjParams(name, Name, 'ArmMacroFPAOp', code, opt_flags) + header_output = BasicDeclare.subst(iop) + decoder_output = MacroFPAConstructor.subst(iop) + decode_block = BasicDecode.subst(iop) + exec_output = PredOpExecute.subst(iop) +}}; + +def format ArmMacroFMOp(code, mem_flags = [], inst_flag = [], *opt_flags) {{ + iop = InstObjParams(name, Name, 'ArmMacroFMOp', code, opt_flags) + header_output = BasicDeclare.subst(iop) + decoder_output = MacroFMConstructor.subst(iop) + decode_block = BasicDecode.subst(iop) + exec_output = PredOpExecute.subst(iop) +}}; + + + diff --git a/src/arch/arm/isa/formats/mem.isa b/src/arch/arm/isa/formats/mem.isa new file mode 100644 index 000000000..0c736f947 --- /dev/null +++ b/src/arch/arm/isa/formats/mem.isa @@ -0,0 +1,593 @@ +// -*- mode:c++ -*- + +// Copyright (c) 2007-2008 The Florida State University +// 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: Stephen Hines + +//////////////////////////////////////////////////////////////////// +// +// Memory-format instructions +// + +output header {{ + /** + * Base class for general Arm memory-format instructions. + */ + class Memory : public PredOp + { + protected: + + /// Memory request flags. See mem_req_base.hh. + unsigned memAccessFlags; + /// Pointer to EAComp object. + const StaticInstPtr eaCompPtr; + /// Pointer to MemAcc object. + const StaticInstPtr memAccPtr; + + /// Displacement for EA calculation (signed). + int32_t disp; + int32_t disp8; + int32_t up; + int32_t hilo, + shift_size, + shift; + + /// Constructor + Memory(const char *mnem, MachInst _machInst, OpClass __opClass, + StaticInstPtr _eaCompPtr = nullStaticInstPtr, + StaticInstPtr _memAccPtr = nullStaticInstPtr) + : PredOp(mnem, _machInst, __opClass), + memAccessFlags(0), eaCompPtr(_eaCompPtr), memAccPtr(_memAccPtr), + disp(IMMED_11_0), disp8(IMMED_7_0 << 2), up(UP), + hilo((IMMED_HI_11_8 << 4) | IMMED_LO_3_0), + shift_size(SHIFT_SIZE), shift(SHIFT) + { + // When Up is not set, then we must subtract by the displacement + if (!up) + { + disp = -disp; + disp8 = -disp8; + hilo = -hilo; + } + } + + std::string + generateDisassembly(Addr pc, const SymbolTable *symtab) const; + + public: + + const StaticInstPtr &eaCompInst() const { return eaCompPtr; } + const StaticInstPtr &memAccInst() const { return memAccPtr; } + }; + + /** + * Base class for a few miscellaneous memory-format insts + * that don't interpret the disp field + */ + class MemoryNoDisp : public Memory + { + protected: + /// Constructor + MemoryNoDisp(const char *mnem, ExtMachInst _machInst, OpClass __opClass, + StaticInstPtr _eaCompPtr = nullStaticInstPtr, + StaticInstPtr _memAccPtr = nullStaticInstPtr) + : Memory(mnem, _machInst, __opClass, _eaCompPtr, _memAccPtr) + { + } + + std::string + generateDisassembly(Addr pc, const SymbolTable *symtab) const; + }; +}}; + + +output decoder {{ + std::string + Memory::generateDisassembly(Addr pc, const SymbolTable *symtab) const + { + return csprintf("%-10s", mnemonic); + } + + std::string + MemoryNoDisp::generateDisassembly(Addr pc, const SymbolTable *symtab) const + { + return csprintf("%-10s", mnemonic); + } +}}; + +def template LoadStoreDeclare {{ + /** + * Static instruction class for "%(mnemonic)s". + */ + class %(class_name)s : public %(base_class)s + { + protected: + + /** + * "Fake" effective address computation class for "%(mnemonic)s". + */ + class EAComp : public %(base_class)s + { + public: + /// Constructor + EAComp(MachInst machInst); + + %(BasicExecDeclare)s + }; + + /** + * "Fake" memory access instruction class for "%(mnemonic)s". + */ + class MemAcc : public %(base_class)s + { + public: + /// Constructor + MemAcc(MachInst machInst); + + %(BasicExecDeclare)s + }; + + public: + + /// Constructor. + %(class_name)s(MachInst machInst); + + %(BasicExecDeclare)s + + %(InitiateAccDeclare)s + + %(CompleteAccDeclare)s + }; +}}; + + +def template InitiateAccDeclare {{ + Fault initiateAcc(%(CPU_exec_context)s *, Trace::InstRecord *) const; +}}; + + +def template CompleteAccDeclare {{ + Fault completeAcc(PacketPtr, %(CPU_exec_context)s *, Trace::InstRecord *) const; +}}; + + +def template EACompConstructor {{ + inline %(class_name)s::EAComp::EAComp(MachInst machInst) + : %(base_class)s("%(mnemonic)s (EAComp)", machInst, IntAluOp) + { + %(constructor)s; + } +}}; + + +def template MemAccConstructor {{ + inline %(class_name)s::MemAcc::MemAcc(MachInst machInst) + : %(base_class)s("%(mnemonic)s (MemAcc)", machInst, %(op_class)s) + { + %(constructor)s; + } +}}; + + +def template LoadStoreConstructor {{ + inline %(class_name)s::%(class_name)s(MachInst machInst) + : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s, + new EAComp(machInst), new MemAcc(machInst)) + { + %(constructor)s; + } +}}; + + +def template EACompExecute {{ + Fault + %(class_name)s::EAComp::execute(%(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + Addr EA; + Fault fault = NoFault; + + %(fp_enable_check)s; + %(op_decl)s; + %(op_rd)s; + %(ea_code)s; + + if (arm_predicate(xc->readMiscReg(ArmISA::CPSR), condCode)) + { + if (fault == NoFault) { + %(op_wb)s; + xc->setEA(EA); + } + } + + return fault; + } +}}; + +def template LoadMemAccExecute {{ + Fault + %(class_name)s::MemAcc::execute(%(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + Addr EA; + Fault fault = NoFault; + + %(fp_enable_check)s; + %(op_decl)s; + %(op_rd)s; + EA = xc->getEA(); + + if (arm_predicate(xc->readMiscReg(ArmISA::CPSR), condCode)) + { + if (fault == NoFault) { + fault = xc->read(EA, (uint%(mem_acc_size)d_t&)Mem, memAccessFlags); + %(memacc_code)s; + } + + if (fault == NoFault) { + %(op_wb)s; + } + } + + return fault; + } +}}; + + +def template LoadExecute {{ + Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + Addr EA; + Fault fault = NoFault; + + %(fp_enable_check)s; + %(op_decl)s; + %(op_rd)s; + %(ea_code)s; + + if (arm_predicate(xc->readMiscReg(ArmISA::CPSR), condCode)) + { + if (fault == NoFault) { + fault = xc->read(EA, (uint%(mem_acc_size)d_t&)Mem, memAccessFlags); + %(memacc_code)s; + } + + if (fault == NoFault) { + %(op_wb)s; + } + } + + return fault; + } +}}; + + +def template LoadInitiateAcc {{ + Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + Addr EA; + Fault fault = NoFault; + + %(fp_enable_check)s; + %(op_src_decl)s; + %(op_rd)s; + %(ea_code)s; + + if (arm_predicate(xc->readMiscReg(ArmISA::CPSR), condCode)) + { + if (fault == NoFault) { + fault = xc->read(EA, (uint%(mem_acc_size)d_t &)Mem, memAccessFlags); + } + } + + return fault; + } +}}; + + +def template LoadCompleteAcc {{ + Fault %(class_name)s::completeAcc(PacketPtr pkt, + %(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + Fault fault = NoFault; + + %(fp_enable_check)s; + %(op_decl)s; + %(op_rd)s; + + if (arm_predicate(xc->readMiscReg(ArmISA::CPSR), condCode)) + { + // ARM instructions will not have a pkt if the predicate is false + Mem = pkt->get<typeof(Mem)>(); + + if (fault == NoFault) { + %(memacc_code)s; + } + + if (fault == NoFault) { + %(op_wb)s; + } + } + + return fault; + } +}}; + + +def template StoreMemAccExecute {{ + Fault + %(class_name)s::MemAcc::execute(%(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + Addr EA; + Fault fault = NoFault; + + %(fp_enable_check)s; + %(op_decl)s; + %(op_rd)s; + + if (arm_predicate(xc->readMiscReg(ArmISA::CPSR), condCode)) + { + EA = xc->getEA(); + + if (fault == NoFault) { + %(postacc_code)s; + } + + if (fault == NoFault) { + fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA, + memAccessFlags, NULL); + if (traceData) { traceData->setData(Mem); } + } + + if (fault == NoFault) { + %(postacc_code)s; + } + + if (fault == NoFault) { + %(op_wb)s; + } + } + + return fault; + } +}}; + + +def template StoreExecute {{ + Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + Addr EA; + Fault fault = NoFault; + + %(fp_enable_check)s; + %(op_decl)s; + %(op_rd)s; + %(ea_code)s; + + if (arm_predicate(xc->readMiscReg(ArmISA::CPSR), condCode)) + { + if (fault == NoFault) { + %(memacc_code)s; + } + + if (fault == NoFault) { + fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA, + memAccessFlags, NULL); + if (traceData) { traceData->setData(Mem); } + } + + if (fault == NoFault) { + %(postacc_code)s; + } + + if (fault == NoFault) { + %(op_wb)s; + } + } + + return fault; + } +}}; + +def template StoreInitiateAcc {{ + Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + Addr EA; + Fault fault = NoFault; + + %(fp_enable_check)s; + %(op_decl)s; + %(op_rd)s; + %(ea_code)s; + + if (arm_predicate(xc->readMiscReg(ArmISA::CPSR), condCode)) + { + if (fault == NoFault) { + %(memacc_code)s; + } + + if (fault == NoFault) { + fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA, + memAccessFlags, NULL); + if (traceData) { traceData->setData(Mem); } + } + + // Need to write back any potential address register update + if (fault == NoFault) { + %(op_wb)s; + } + } + + return fault; + } +}}; + + +def template StoreCompleteAcc {{ + Fault %(class_name)s::completeAcc(PacketPtr pkt, + %(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + Fault fault = NoFault; + + %(fp_enable_check)s; + %(op_dest_decl)s; + + if (arm_predicate(xc->readMiscReg(ArmISA::CPSR), condCode)) + { + if (fault == NoFault) { + %(postacc_code)s; + } + + if (fault == NoFault) { + %(op_wb)s; + } + } + + return fault; + } +}}; + +def template StoreCondCompleteAcc {{ + Fault %(class_name)s::completeAcc(PacketPtr pkt, + %(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + Fault fault = NoFault; + + %(fp_enable_check)s; + %(op_dest_decl)s; + + if (arm_predicate(xc->readMiscReg(ArmISA::CPSR), condCode)) + { + if (fault == NoFault) { + %(postacc_code)s; + } + + if (fault == NoFault) { + %(op_wb)s; + } + } + + return fault; + } +}}; + + +def template MiscMemAccExecute {{ + Fault %(class_name)s::MemAcc::execute(%(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + Addr EA; + Fault fault = NoFault; + + %(fp_enable_check)s; + %(op_decl)s; + %(op_rd)s; + + if (arm_predicate(xc->readMiscReg(ArmISA::CPSR), condCode)) + { + EA = xc->getEA(); + + if (fault == NoFault) { + %(memacc_code)s; + } + } + + return NoFault; + } +}}; + +def template MiscExecute {{ + Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + Addr EA; + Fault fault = NoFault; + + %(fp_enable_check)s; + %(op_decl)s; + %(op_rd)s; + %(ea_code)s; + + if (arm_predicate(xc->readMiscReg(ArmISA::CPSR), condCode)) + { + if (fault == NoFault) { + %(memacc_code)s; + } + } + + return NoFault; + } +}}; + +def template MiscInitiateAcc {{ + Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + panic("Misc instruction does not support split access method!"); + return NoFault; + } +}}; + + +def template MiscCompleteAcc {{ + Fault %(class_name)s::completeAcc(PacketPtr pkt, + %(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + panic("Misc instruction does not support split access method!"); + + return NoFault; + } +}}; + +def format ArmLoadMemory(memacc_code, ea_code = {{ EA = Rn + disp; }}, + mem_flags = [], inst_flags = []) {{ + ea_code = ArmGenericCodeSubs(ea_code) + memacc_code = ArmGenericCodeSubs(memacc_code) + (header_output, decoder_output, decode_block, exec_output) = \ + LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, + decode_template = BasicDecode, + exec_template_base = 'Load') +}}; + +def format ArmStoreMemory(memacc_code, ea_code = {{ EA = Rn + disp; }}, + mem_flags = [], inst_flags = []) {{ + ea_code = ArmGenericCodeSubs(ea_code) + memacc_code = ArmGenericCodeSubs(memacc_code) + (header_output, decoder_output, decode_block, exec_output) = \ + LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, + exec_template_base = 'Store') +}}; + diff --git a/src/arch/arm/isa/formats/pred.isa b/src/arch/arm/isa/formats/pred.isa new file mode 100644 index 000000000..1e9dba07e --- /dev/null +++ b/src/arch/arm/isa/formats/pred.isa @@ -0,0 +1,402 @@ +// -*- mode:c++ -*- + +// Copyright (c) 2007-2008 The Florida State University +// 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: Stephen Hines + +//////////////////////////////////////////////////////////////////// +// +// Predicated Instruction Execution +// + +output header {{ +#include <iostream> + + enum ArmPredicateBits { + COND_EQ = 0, + COND_NE, // 1 + COND_CS, // 2 + COND_CC, // 3 + COND_MI, // 4 + COND_PL, // 5 + COND_VS, // 6 + COND_VC, // 7 + COND_HI, // 8 + COND_LS, // 9 + COND_GE, // 10 + COND_LT, // 11 + COND_GT, // 12 + COND_LE, // 13 + COND_AL, // 14 + COND_NV // 15 + }; + + inline uint32_t + rotate_imm(uint32_t immValue, uint32_t rotateValue) + { + return ((immValue >> (int)(rotateValue & 31)) | + (immValue << (32 - (int)(rotateValue & 31)))); + } + + inline uint32_t nSet(uint32_t cpsr) { return cpsr & (1<<31); } + inline uint32_t zSet(uint32_t cpsr) { return cpsr & (1<<30); } + inline uint32_t cSet(uint32_t cpsr) { return cpsr & (1<<29); } + inline uint32_t vSet(uint32_t cpsr) { return cpsr & (1<<28); } + + inline bool arm_predicate(uint32_t cpsr, uint32_t predBits) + { + + enum ArmPredicateBits armPredBits = (enum ArmPredicateBits) predBits; + uint32_t result = 0; + switch (armPredBits) + { + case COND_EQ: + result = zSet(cpsr); break; + case COND_NE: + result = !zSet(cpsr); break; + case COND_CS: + result = cSet(cpsr); break; + case COND_CC: + result = !cSet(cpsr); break; + case COND_MI: + result = nSet(cpsr); break; + case COND_PL: + result = !nSet(cpsr); break; + case COND_VS: + result = vSet(cpsr); break; + case COND_VC: + result = !vSet(cpsr); break; + case COND_HI: + result = cSet(cpsr) && !zSet(cpsr); break; + case COND_LS: + result = !cSet(cpsr) || zSet(cpsr); break; + case COND_GE: + result = (!nSet(cpsr) && !vSet(cpsr)) || (nSet(cpsr) && vSet(cpsr)); break; + case COND_LT: + result = (nSet(cpsr) && !vSet(cpsr)) || (!nSet(cpsr) && vSet(cpsr)); break; + case COND_GT: + result = (!nSet(cpsr) && !vSet(cpsr) && !zSet(cpsr)) || (nSet(cpsr) && vSet(cpsr) && !zSet(cpsr)); break; + case COND_LE: + result = (nSet(cpsr) && !vSet(cpsr)) || (!nSet(cpsr) && vSet(cpsr)) || zSet(cpsr); break; + case COND_AL: result = 1; break; + case COND_NV: result = 0; break; + default: + fprintf(stderr, "Unhandled predicate condition: %d\n", armPredBits); + exit(1); + } + if (result) + return true; + else + return false; + } + + + /** + * Base class for predicated integer operations. + */ + class PredOp : public ArmStaticInst + { + protected: + + uint32_t condCode; + + /// Constructor + PredOp(const char *mnem, MachInst _machInst, OpClass __opClass) : + ArmStaticInst(mnem, _machInst, __opClass), + condCode(COND_CODE) + { + } + + std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; + }; + + /** + * Base class for predicated immediate operations. + */ + class PredImmOp : public PredOp + { + protected: + + uint32_t imm; + uint32_t rotate; + uint32_t rotated_imm; + uint32_t rotated_carry; + + /// Constructor + PredImmOp(const char *mnem, MachInst _machInst, OpClass __opClass) : + PredOp(mnem, _machInst, __opClass), + imm(IMM), rotate(ROTATE << 1), rotated_imm(0), + rotated_carry(0) + { + rotated_imm = rotate_imm(imm, rotate); + if (rotate != 0) + rotated_carry = (rotated_imm >> 31) & 1; + } + + std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; + }; + + /** + * Base class for predicated integer operations. + */ + class PredIntOp : public PredOp + { + protected: + + uint32_t shift_size; + uint32_t shift; + + /// Constructor + PredIntOp(const char *mnem, MachInst _machInst, OpClass __opClass) : + PredOp(mnem, _machInst, __opClass), + shift_size(SHIFT_SIZE), shift(SHIFT) + { + } + + std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; + }; + + /** + * Base class for predicated macro-operations. + */ + class PredMacroOp : public PredOp + { + protected: + + uint32_t numMicroops; + StaticInstPtr * microOps; + + /// Constructor + PredMacroOp(const char *mnem, MachInst _machInst, OpClass __opClass) : + PredOp(mnem, _machInst, __opClass), + numMicroops(0) + { + // We rely on the subclasses of this object to handle the + // initialization of the micro-operations, since they are + // all of variable length + flags[IsMacroop] = true; + } + + ~PredMacroOp() + { + if (numMicroops) + delete [] microOps; + } + + StaticInstPtr fetchMicroop(MicroPC microPC) + { + assert(microPC < numMicroops); + return microOps[microPC]; + } + + %(BasicExecPanic)s + + std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; + }; + + /** + * Base class for predicated micro-operations. + */ + class PredMicroop : public PredOp + { + /// Constructor + PredMicroop(const char *mnem, MachInst _machInst, OpClass __opClass) : + PredOp(mnem, _machInst, __opClass) + { + flags[IsMicroop] = true; + } + }; + +}}; + +def template PredOpExecute {{ + Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, Trace::InstRecord *traceData) const + { + Fault fault = NoFault; + + %(fp_enable_check)s; + %(op_decl)s; + %(op_rd)s; + %(code)s; + + if (arm_predicate(xc->readMiscReg(ArmISA::CPSR), condCode)) + { + if (fault == NoFault) + { + %(op_wb)s; + } + } + else + return NoFault; + // Predicated false instructions should not return faults + + return fault; + } +}}; + +//Outputs to decoder.cc +output decoder {{ + std::string PredOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const + { + std::stringstream ss; + + ccprintf(ss, "%-10s ", mnemonic); + + if (_numDestRegs > 0) { + printReg(ss, _destRegIdx[0]); + } + + ss << ", "; + + if (_numSrcRegs > 0) { + printReg(ss, _srcRegIdx[0]); + ss << ", "; + } + + return ss.str(); + } + + std::string PredImmOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const + { + std::stringstream ss; + + ccprintf(ss, "%-10s ", mnemonic); + + if (_numDestRegs > 0) { + printReg(ss, _destRegIdx[0]); + } + + ss << ", "; + + if (_numSrcRegs > 0) { + printReg(ss, _srcRegIdx[0]); + ss << ", "; + } + + return ss.str(); + } + + std::string PredIntOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const + { + std::stringstream ss; + + ccprintf(ss, "%-10s ", mnemonic); + + if (_numDestRegs > 0) { + printReg(ss, _destRegIdx[0]); + } + + ss << ", "; + + if (_numSrcRegs > 0) { + printReg(ss, _srcRegIdx[0]); + ss << ", "; + } + + return ss.str(); + } + + std::string PredMacroOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const + { + std::stringstream ss; + + ccprintf(ss, "%-10s ", mnemonic); + + return ss.str(); + } + +}}; + +let {{ + + calcCcCode = ''' + uint16_t _ic, _iv, _iz, _in; + + _in = (resTemp >> 31) & 1; + _iz = (resTemp == 0); + _iv = %(ivValue)s & 1; + _ic = %(icValue)s & 1; + + Cpsr = _in << 31 | _iz << 30 | _ic << 29 | _iv << 28 | + (Cpsr & 0x0FFFFFFF); + + DPRINTF(Arm, "in = %%d\\n", _in); + DPRINTF(Arm, "iz = %%d\\n", _iz); + DPRINTF(Arm, "ic = %%d\\n", _ic); + DPRINTF(Arm, "iv = %%d\\n", _iv); + ''' + +}}; + +def format PredOp(code, *opt_flags) {{ + iop = InstObjParams(name, Name, 'PredOp', code, opt_flags) + header_output = BasicDeclare.subst(iop) + decoder_output = BasicConstructor.subst(iop) + decode_block = BasicDecode.subst(iop) + exec_output = PredOpExecute.subst(iop) +}}; + +def format PredImmOp(code, *opt_flags) {{ + iop = InstObjParams(name, Name, 'PredImmOp', code, opt_flags) + header_output = BasicDeclare.subst(iop) + decoder_output = BasicConstructor.subst(iop) + decode_block = BasicDecode.subst(iop) + exec_output = PredOpExecute.subst(iop) +}}; + +def format PredImmOpCc(code, icValue, ivValue, *opt_flags) {{ + ccCode = calcCcCode % vars() + code += ccCode; + iop = InstObjParams(name, Name, 'PredImmOp', + {"code": code, "cc_code": ccCode}, opt_flags) + header_output = BasicDeclare.subst(iop) + decoder_output = BasicConstructor.subst(iop) + decode_block = BasicDecode.subst(iop) + exec_output = PredOpExecute.subst(iop) +}}; + +def format PredIntOp(code, *opt_flags) {{ + new_code = ArmGenericCodeSubs(code) + iop = InstObjParams(name, Name, 'PredIntOp', new_code, opt_flags) + header_output = BasicDeclare.subst(iop) + decoder_output = BasicConstructor.subst(iop) + decode_block = BasicDecode.subst(iop) + exec_output = PredOpExecute.subst(iop) +}}; + +def format PredIntOpCc(code, icValue, ivValue, *opt_flags) {{ + ccCode = calcCcCode % vars() + code += ccCode; + new_code = ArmGenericCodeSubs(code) + iop = InstObjParams(name, Name, 'PredIntOp', + {"code": new_code, "cc_code": ccCode }, opt_flags) + header_output = BasicDeclare.subst(iop) + decoder_output = BasicConstructor.subst(iop) + decode_block = BasicDecode.subst(iop) + exec_output = PredOpExecute.subst(iop) +}}; + diff --git a/src/arch/arm/isa/formats/unimp.isa b/src/arch/arm/isa/formats/unimp.isa new file mode 100644 index 000000000..c82bb41c6 --- /dev/null +++ b/src/arch/arm/isa/formats/unimp.isa @@ -0,0 +1,144 @@ +// -*- mode:c++ -*- + +// Copyright (c) 2007-2008 The Florida State University +// 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: Stephen Hines + +//////////////////////////////////////////////////////////////////// +// +// Unimplemented instructions +// + +output header {{ + /** + * Static instruction class for unimplemented instructions that + * cause simulator termination. Note that these are recognized + * (legal) instructions that the simulator does not support; the + * 'Unknown' class is used for unrecognized/illegal instructions. + * This is a leaf class. + */ + class FailUnimplemented : public ArmStaticInst + { + public: + /// Constructor + FailUnimplemented(const char *_mnemonic, MachInst _machInst) + : ArmStaticInst(_mnemonic, _machInst, No_OpClass) + { + // don't call execute() (which panics) if we're on a + // speculative path + flags[IsNonSpeculative] = true; + } + + %(BasicExecDeclare)s + + std::string + generateDisassembly(Addr pc, const SymbolTable *symtab) const; + }; + + /** + * Base class for unimplemented instructions that cause a warning + * to be printed (but do not terminate simulation). This + * implementation is a little screwy in that it will print a + * warning for each instance of a particular unimplemented machine + * instruction, not just for each unimplemented opcode. Should + * probably make the 'warned' flag a static member of the derived + * class. + */ + class WarnUnimplemented : public ArmStaticInst + { + private: + /// Have we warned on this instruction yet? + mutable bool warned; + + public: + /// Constructor + WarnUnimplemented(const char *_mnemonic, MachInst _machInst) + : ArmStaticInst(_mnemonic, _machInst, No_OpClass), warned(false) + { + // don't call execute() (which panics) if we're on a + // speculative path + flags[IsNonSpeculative] = true; + } + + %(BasicExecDeclare)s + + std::string + generateDisassembly(Addr pc, const SymbolTable *symtab) const; + }; +}}; + +output decoder {{ + std::string + FailUnimplemented::generateDisassembly(Addr pc, + const SymbolTable *symtab) const + { + return csprintf("%-10s (unimplemented)", mnemonic); + } + + std::string + WarnUnimplemented::generateDisassembly(Addr pc, + const SymbolTable *symtab) const + { + return csprintf("%-10s (unimplemented)", mnemonic); + } +}}; + +output exec {{ + Fault + FailUnimplemented::execute(%(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + panic("attempt to execute unimplemented instruction '%s' " + "(inst 0x%08x, opcode 0x%x, binary:%s)", mnemonic, machInst, OPCODE, + inst2string(machInst)); + return new UnimplementedOpcodeFault; + } + + Fault + WarnUnimplemented::execute(%(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + if (!warned) { + warn("\tinstruction '%s' unimplemented\n", mnemonic); + warned = true; + } + + return NoFault; + } +}}; + + +def format FailUnimpl() {{ + iop = InstObjParams(name, 'FailUnimplemented') + decode_block = BasicDecodeWithMnemonic.subst(iop) +}}; + +def format WarnUnimpl() {{ + iop = InstObjParams(name, 'WarnUnimplemented') + decode_block = BasicDecodeWithMnemonic.subst(iop) +}}; + diff --git a/src/arch/arm/isa/formats/unknown.isa b/src/arch/arm/isa/formats/unknown.isa new file mode 100644 index 000000000..3d13ef616 --- /dev/null +++ b/src/arch/arm/isa/formats/unknown.isa @@ -0,0 +1,84 @@ +// -*- mode:c++ -*- + +// Copyright (c) 2007-2008 The Florida State University +// 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: Stephen Hines + +//////////////////////////////////////////////////////////////////// +// +// Unknown instructions +// + +output header {{ + /** + * Static instruction class for unknown (illegal) instructions. + * These cause simulator termination if they are executed in a + * non-speculative mode. This is a leaf class. + */ + class Unknown : public ArmStaticInst + { + public: + /// Constructor + Unknown(MachInst _machInst) + : ArmStaticInst("unknown", _machInst, No_OpClass) + { + // don't call execute() (which panics) if we're on a + // speculative path + flags[IsNonSpeculative] = true; + } + + %(BasicExecDeclare)s + + std::string + generateDisassembly(Addr pc, const SymbolTable *symtab) const; + }; +}}; + +output decoder {{ + std::string + Unknown::generateDisassembly(Addr pc, const SymbolTable *symtab) const + { + return csprintf("%-10s (inst 0x%x, opcode 0x%x, binary:%s)", + "unknown", machInst, OPCODE, inst2string(machInst)); + } +}}; + +output exec {{ + Fault + Unknown::execute(%(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + panic("attempt to execute unknown instruction " + "(inst 0x%08x, opcode 0x%x, binary: %s)", machInst, OPCODE, inst2string(machInst)); + return new UnimplementedOpcodeFault; + } +}}; + +def format Unknown() {{ + decode_block = 'return new Unknown(machInst);\n' +}}; + diff --git a/src/arch/arm/isa/formats/util.isa b/src/arch/arm/isa/formats/util.isa new file mode 100644 index 000000000..ee6339c02 --- /dev/null +++ b/src/arch/arm/isa/formats/util.isa @@ -0,0 +1,217 @@ +// -*- mode:c++ -*- + +// Copyright (c) 2007-2008 The Florida State University +// 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: Stephen Hines + +let {{ + +# Generic substitutions for Arm instructions +def ArmGenericCodeSubs(code): + # Substitute in the shifted portion of operations + new_code = re.sub(r'Rm_Imm', 'shift_rm_imm(Rm, shift_size, shift, Cpsr<29:>)', code) + new_code = re.sub(r'Rm_Rs', 'shift_rm_rs(Rm, Rs, shift, Cpsr<29:>)', new_code) + new_code = re.sub(r'^', 'Cpsr = Cpsr;', new_code) + return new_code + +def LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, + postacc_code = '', base_class = 'Memory', + decode_template = BasicDecode, exec_template_base = ''): + # Make sure flags are in lists (convert to lists if not). + mem_flags = makeList(mem_flags) + inst_flags = makeList(inst_flags) + + # add hook to get effective addresses into execution trace output. + ea_code += '\nif (traceData) { traceData->setAddr(EA); }\n' + + # Some CPU models execute the memory operation as an atomic unit, + # while others want to separate them into an effective address + # computation and a memory access operation. As a result, we need + # to generate three StaticInst objects. Note that the latter two + # are nested inside the larger "atomic" one. + + # Generate InstObjParams for each of the three objects. Note that + # they differ only in the set of code objects contained (which in + # turn affects the object's overall operand list). + iop = InstObjParams(name, Name, base_class, + { 'ea_code':ea_code, 'memacc_code':memacc_code, 'postacc_code':postacc_code }, + inst_flags) + ea_iop = InstObjParams(name, Name, base_class, + { 'ea_code':ea_code }, + inst_flags) + memacc_iop = InstObjParams(name, Name, base_class, + { 'memacc_code':memacc_code, 'postacc_code':postacc_code }, + inst_flags) + + if mem_flags: + s = '\n\tmemAccessFlags = ' + string.join(mem_flags, '|') + ';' + iop.constructor += s + memacc_iop.constructor += s + + # select templates + + # The InitiateAcc template is the same for StoreCond templates as the + # corresponding Store template.. + StoreCondInitiateAcc = StoreInitiateAcc + + memAccExecTemplate = eval(exec_template_base + 'MemAccExecute') + fullExecTemplate = eval(exec_template_base + 'Execute') + initiateAccTemplate = eval(exec_template_base + 'InitiateAcc') + completeAccTemplate = eval(exec_template_base + 'CompleteAcc') + + # (header_output, decoder_output, decode_block, exec_output) + return (LoadStoreDeclare.subst(iop), + EACompConstructor.subst(ea_iop) + + MemAccConstructor.subst(memacc_iop) + + LoadStoreConstructor.subst(iop), + decode_template.subst(iop), + EACompExecute.subst(ea_iop) + + memAccExecTemplate.subst(memacc_iop) + + fullExecTemplate.subst(iop) + + initiateAccTemplate.subst(iop) + + completeAccTemplate.subst(iop)) +}}; + + +output header {{ + std::string inst2string(MachInst machInst); + StaticInstPtr gen_ldrstr_uop(uint32_t baseinst, int loadop, uint32_t rd, int32_t disp); + int emit_ldfstf_uops(StaticInstPtr* microOps, int index, uint32_t baseinst, int loadop, int up, int32_t disp); +}}; + +output decoder {{ + + std::string inst2string(MachInst machInst) + { + std::string str = ""; + uint32_t mask = 0x80000000; + + for(int i=0; i < 32; i++) { + if ((machInst & mask) == 0) { + str += "0"; + } else { + str += "1"; + } + + mask = mask >> 1; + } + + return str; + } + + // Generate the bit pattern for an Ldr_uop or Str_uop; + StaticInstPtr + gen_ldrstr_uop(uint32_t baseinst, int loadop, uint32_t rd, int32_t disp) + { + StaticInstPtr newInst; + uint32_t newMachInst = baseinst & 0xffff0000; + newMachInst |= (rd << 12); + newMachInst |= disp; + if (loadop) + newInst = new Ldr_uop(newMachInst); + else + newInst = new Str_uop(newMachInst); + return newInst; + } + + // Emits uops for a double fp move + int + emit_ldfstf_uops(StaticInstPtr* microOps, int index, uint32_t baseinst, int loadop, int up, int32_t disp) + { + StaticInstPtr newInst; + uint32_t newMachInst; + + if (loadop) + { + newMachInst = baseinst & 0xfffff000; + newMachInst |= (disp & 0x0fff); + newInst = new Ldlo_uop(newMachInst); + microOps[index++] = newInst; + + newMachInst = baseinst & 0xfffff000; + if (up) + newMachInst |= ((disp + 4) & 0x0fff); + else + newMachInst |= ((disp - 4) & 0x0fff); + newInst = new Ldhi_uop(newMachInst); + microOps[index++] = newInst; + + newMachInst = baseinst & 0xf000f000; + newInst = new Mvtd_uop(newMachInst); + microOps[index++] = newInst; + } + else + { + newMachInst = baseinst & 0xf000f000; + newInst = new Mvfd_uop(newMachInst); + microOps[index++] = newInst; + + newMachInst = baseinst & 0xfffff000; + newMachInst |= (disp & 0x0fff); + newInst = new Stlo_uop(newMachInst); + microOps[index++] = newInst; + + newMachInst = baseinst & 0xfffff000; + if (up) + newMachInst |= ((disp + 4) & 0x0fff); + else + newMachInst |= ((disp - 4) & 0x0fff); + newInst = new Sthi_uop(newMachInst); + microOps[index++] = newInst; + } + return 3; + } + +}}; + +output exec {{ + + using namespace ArmISA; + + /// CLEAR ALL CPU INST/EXE HAZARDS + inline void + clear_exe_inst_hazards() + { + //CODE HERE + } + +#if FULL_SYSTEM + inline Fault checkFpEnableFault(%(CPU_exec_context)s *xc) + { + return NoFault; + } +#else + inline Fault checkFpEnableFault(%(CPU_exec_context)s *xc) + { + return NoFault; + } +#endif + + +}}; + + diff --git a/src/arch/arm/isa/includes.isa b/src/arch/arm/isa/includes.isa new file mode 100644 index 000000000..6205a8f81 --- /dev/null +++ b/src/arch/arm/isa/includes.isa @@ -0,0 +1,82 @@ +// -*- mode:c++ -*- + +// Copyright (c) 2007-2008 The Florida State University +// 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: Stephen Hines + +//////////////////////////////////////////////////////////////////// +// +// Output include file directives. +// + +output header {{ +#include <sstream> +#include <iostream> +#include <iomanip> + +#include "arch/arm/isa_traits.hh" +#include "cpu/static_inst.hh" +#include "mem/packet.hh" +}}; + +output decoder {{ +#include <cmath> +#if defined(linux) +#include <fenv.h> +#endif + +#include "arch/arm/faults.hh" +#include "arch/arm/isa_traits.hh" +#include "arch/arm/utility.hh" +#include "base/cprintf.hh" +#include "base/loader/symtab.hh" +#include "cpu/thread_context.hh" + +using namespace ArmISA; +using std::isnan; +}}; + +output exec {{ +#include "arch/arm/faults.hh" +#include "arch/arm/isa_traits.hh" +#include "arch/arm/utility.hh" + +#include <cmath> +#if defined(linux) +#include <fenv.h> +#endif + +#include "cpu/base.hh" +#include "cpu/exetrace.hh" +#include "mem/packet.hh" +#include "mem/packet_access.hh" +#include "sim/sim_exit.hh" + +using namespace ArmISA; +using std::isnan; +}}; + diff --git a/src/arch/arm/isa/main.isa b/src/arch/arm/isa/main.isa new file mode 100644 index 000000000..aeb8b69d0 --- /dev/null +++ b/src/arch/arm/isa/main.isa @@ -0,0 +1,63 @@ +// -*- mode:c++ -*- + +// Copyright (c) 2007-2008 The Florida State University +// 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: Stephen Hines + +//////////////////////////////////////////////////////////////////// +// +// ARM ISA description file. +// +//////////////////////////////////////////////////////////////////// + +//Include the C++ include directives +##include "includes.isa" + +//////////////////////////////////////////////////////////////////// +// +// Namespace statement. Everything below this line will be in the +// ArmISAInst namespace. +// +namespace ArmISA; + +//Include the utility functions +##include "util.isa" + +//Include the bitfield definitions +##include "bitfields.isa" + +//Include the operand_types and operand definitions +##include "operands.isa" + +//Include the base class for Arm instructions, and some support code +##include "base.isa" + +//Include the definitions for the instruction formats +##include "formats/formats.isa" + +//Include the decoder definition +##include "decoder.isa" diff --git a/src/arch/arm/isa/operands.isa b/src/arch/arm/isa/operands.isa new file mode 100644 index 000000000..b2c4f8420 --- /dev/null +++ b/src/arch/arm/isa/operands.isa @@ -0,0 +1,72 @@ +// -*- mode:c++ -*- + +// Copyright (c) 2007-2008 The Florida State University +// 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: Stephen Hines + +def operand_types {{ + 'sb' : ('signed int', 8), + 'ub' : ('unsigned int', 8), + 'sh' : ('signed int', 16), + 'uh' : ('unsigned int', 16), + 'sw' : ('signed int', 32), + 'uw' : ('unsigned int', 32), + 'ud' : ('unsigned int', 64), + 'sf' : ('float', 32), + 'df' : ('float', 64) +}}; + +def operands {{ + #General Purpose Integer Reg Operands + 'Rd': ('IntReg', 'uw', 'RD', 'IsInteger', 1), + 'Rm': ('IntReg', 'uw', 'RM', 'IsInteger', 2), + 'Rs': ('IntReg', 'uw', 'RS', 'IsInteger', 3), + 'Rn': ('IntReg', 'uw', 'RN', 'IsInteger', 4), + 'Re': ('IntReg', 'uw', 'RE', 'IsInteger', 5), + + 'Raddr': ('IntReg', 'uw', '17', 'IsInteger', 5), + 'R0': ('IntReg', 'uw', '0', 'IsInteger', 5), + 'R7': ('IntReg', 'uw', '7', 'IsInteger', 5), + 'Rhi': ('IntReg', 'uw', '18', 'IsInteger', 5), + 'Rlo': ('IntReg', 'uw', '19', 'IsInteger', 6), + 'LR': ('IntReg', 'uw', '14', 'IsInteger', 6), + 'Ignore': ('IntReg', 'uw', '16', 'IsInteger', 99), + + #General Purpose Floating Point Reg Operands + 'Fd': ('FloatReg', 'df', 'FD', 'IsFloating', 1), + 'Fn': ('FloatReg', 'df', 'FN', 'IsFloating', 2), + 'Fm': ('FloatReg', 'df', 'FM', 'IsFloating', 3), + + #Memory Operand + 'Mem': ('Mem', 'uw', None, ('IsMemRef', 'IsLoad', 'IsStore'), 8), + + 'Cpsr': ('ControlReg', 'uw', 'CPSR', 'IsInteger', 7), + 'Fpsr': ('ControlReg', 'uw', 'FPSR', 'IsInteger', 7), + 'NPC': ('NPC', 'uw', None, (None, None, 'IsControl'), 9), + 'NNPC': ('NNPC', 'uw', None, (None, None, 'IsControl'), 9), + +}}; diff --git a/src/arch/arm/isa/util.isa b/src/arch/arm/isa/util.isa new file mode 100644 index 000000000..4fe0d732c --- /dev/null +++ b/src/arch/arm/isa/util.isa @@ -0,0 +1,282 @@ +// -*- mode:c++ -*- + +// Copyright (c) 2007-2008 The Florida State University +// 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: Stephen Hines + +//////////////////////////////////////////////////////////////////// +// +// Utility functions for execute methods +// +// +output header {{ + + // Shift types for ARM instructions + enum ArmShiftType { + LSL = 0, + LSR, + ASR, + ROR + }; + + enum ArmShiftMode { + }; + + inline uint32_t number_of_ones(int32_t val) + { + uint32_t ones = 0; + for (int i = 0; i < 32; i++ ) + { + if ( val & (1<<i) ) + ones++; + } + return ones; + } + +}}; + +output exec {{ + + static int32_t arm_NEG(int32_t val) { return (val >> 31); } + static int32_t arm_POS(int32_t val) { return ((~val) >> 31); } + + // Shift Rm by an immediate value + inline int32_t + shift_rm_imm(uint32_t base, uint32_t shamt, uint32_t type, uint32_t cfval) + { + enum ArmShiftType shiftType; + shiftType = (enum ArmShiftType) type; + + switch (shiftType) + { + case LSL: + return (base << shamt); + case LSR: + if (shamt == 0) + return (0); + else + return (base >> shamt); + case ASR: + if (shamt == 0) + return ((uint32_t) ((int32_t) base >> 31L)); + else + return ((uint32_t) (((int32_t) base) >> shamt)); + case ROR: + //shamt = shamt & 0x1f; + if (shamt == 0) + return (cfval << 31) | (base >> 1); // RRX + else + return (base << (32 - shamt)) | (base >> shamt); + default: + fprintf(stderr, "Unhandled shift type\n"); + exit(1); + break; + } + return 0; + } + + // Shift Rm by Rs + inline int32_t + shift_rm_rs(uint32_t base, uint32_t shamt, uint32_t type, uint32_t cfval) + { + enum ArmShiftType shiftType; + shiftType = (enum ArmShiftType) type; + + switch (shiftType) + { + case LSL: + if (shamt == 0) + return (base); + else if (shamt >= 32) + return (0); + else + return (base << shamt); + case LSR: + if (shamt == 0) + return (base); + else if (shamt >= 32) + return (0); + else + return (base >> shamt); + case ASR: + if (shamt == 0) + return base; + else if (shamt >= 32) + return ((uint32_t) ((int32_t) base >> 31L)); + else + return ((uint32_t) (((int32_t) base) >> (int) shamt)); + case ROR: + shamt = shamt & 0x1f; + if (shamt == 0) + return (base); + else + return ((base << (32 - shamt)) | (base >> shamt)); + default: + fprintf(stderr, "Unhandled shift type\n"); + exit(1); + break; + } + return 0; + } + + + // Generate C for a shift by immediate + inline int32_t + shift_carry_imm(uint32_t base, uint32_t shamt, uint32_t type, + uint32_t cfval) + { + enum ArmShiftType shiftType; + shiftType = (enum ArmShiftType) type; + + switch (shiftType) + { + case LSL: + return (base >> (32 - shamt)) & 1; + case LSR: + if (shamt == 0) + return (base >> 31) & 1; + else + return (base >> (shamt - 1)) & 1; + case ASR: + if (shamt == 0) + return (base >> 31L); + else + return ((uint32_t) (((int32_t) base) >> (shamt - 1))) & 1; + case ROR: + shamt = shamt & 0x1f; + if (shamt == 0) + return (base & 1); // RRX + else + return (base >> (shamt - 1)) & 1; + default: + fprintf(stderr, "Unhandled shift type\n"); + exit(1); + break; + + } + return 0; + } + + + // Generate C for a shift by Rs + inline int32_t + shift_carry_rs(uint32_t base, uint32_t shamt, uint32_t type, uint32_t cfval) + { + enum ArmShiftType shiftType; + shiftType = (enum ArmShiftType) type; + + switch (shiftType) + { + case LSL: + if (shamt == 0) + return (!!cfval); + else if (shamt == 32) + return (base & 1); + else if (shamt > 32) + return (0); + else + return ((base >> (32 - shamt)) & 1); + case LSR: + if (shamt == 0) + return (!!cfval); + else if (shamt == 32) + return (base >> 31); + else if (shamt > 32) + return (0); + else + return ((base >> (shamt - 1)) & 1); + case ASR: + if (shamt == 0) + return (!!cfval); + else if (shamt >= 32) + return (base >> 31L); + else + return (((uint32_t) (((int32_t) base) >> (shamt - 1))) & 1); + case ROR: + if (shamt == 0) + return (!!cfval); + shamt = shamt & 0x1f; + if (shamt == 0) + return (base >> 31); // RRX + else + return ((base >> (shamt - 1)) & 1); + default: + fprintf(stderr, "Unhandled shift type\n"); + exit(1); + break; + + } + return 0; + } + + + // Generate the appropriate carry bit for an addition operation + inline int32_t + arm_add_carry(int32_t result, int32_t lhs, int32_t rhs) + { + if ((lhs | rhs) >> 30) + return ((arm_NEG(lhs) && arm_NEG(rhs)) || + (arm_NEG(lhs) && arm_POS(result)) || + (arm_NEG(rhs) && arm_POS(result))); + else + return 0; + } + + // Generate the appropriate carry bit for a subtraction operation + inline int32_t + arm_sub_carry(int32_t result, int32_t lhs, int32_t rhs) + { + if ((lhs >= rhs) || ((rhs | lhs) >> 31)) + return ((arm_NEG(lhs) && arm_POS(rhs)) || + (arm_NEG(lhs) && arm_POS(result)) || + (arm_POS(rhs) && arm_POS(result))); + else + return 0; + } + + inline int32_t + arm_add_overflow(int32_t result, int32_t lhs, int32_t rhs) + { + if ((lhs | rhs) >> 30) + return ((arm_NEG(lhs) && arm_NEG(rhs) && arm_POS(result)) || + (arm_POS(lhs) && arm_POS(rhs) && arm_NEG(result))); + else + return 0; + } + + inline int32_t + arm_sub_overflow(int32_t result, int32_t lhs, int32_t rhs) + { + if ((lhs >= rhs) || ((rhs | lhs) >> 31)) + return ((arm_NEG(lhs) && arm_POS(rhs) && arm_POS(result)) || + (arm_POS(lhs) && arm_NEG(rhs) && arm_NEG(result))); + else + return 0; + } + +}}; + diff --git a/src/arch/arm/isa_traits.hh b/src/arch/arm/isa_traits.hh new file mode 100644 index 000000000..253114ad1 --- /dev/null +++ b/src/arch/arm/isa_traits.hh @@ -0,0 +1,158 @@ +/* + * Copyright (c) 2003-2005 The Regents of The University of Michigan + * Copyright (c) 2007-2008 The Florida State University + * 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 + * Stephen Hines + */ + +#ifndef __ARCH_ARM_ISA_TRAITS_HH__ +#define __ARCH_ARM_ISA_TRAITS_HH__ + +#include "arch/arm/types.hh" +#include "sim/host.hh" + +namespace LittleEndianGuest {}; + +#define TARGET_ARM + +class StaticInstPtr; + +namespace ArmISA +{ + using namespace LittleEndianGuest; + + StaticInstPtr decodeInst(ExtMachInst); + + // ARM DOES NOT have a delay slot + #define ISA_HAS_DELAY_SLOT 0 + + const Addr PageShift = 12; + const Addr PageBytes = ULL(1) << PageShift; + const Addr Page_Mask = ~(PageBytes - 1); + const Addr PageOffset = PageBytes - 1; + + + //////////////////////////////////////////////////////////////////////// + // + // Translation stuff + // + + const Addr PteShift = 3; + const Addr NPtePageShift = PageShift - PteShift; + const Addr NPtePage = ULL(1) << NPtePageShift; + const Addr PteMask = NPtePage - 1; + + //// All 'Mapped' segments go through the TLB + //// All other segments are translated by dropping the MSB, to give + //// the corresponding physical address + // User Segment - Mapped + const Addr USegBase = ULL(0x0); + const Addr USegEnd = ULL(0x7FFFFFFF); + + // Kernel Segment 0 - Unmapped + const Addr KSeg0End = ULL(0x9FFFFFFF); + const Addr KSeg0Base = ULL(0x80000000); + const Addr KSeg0Mask = ULL(0x1FFFFFFF); + + // For loading... XXX This maybe could be USegEnd?? --ali + const Addr LoadAddrMask = ULL(0xffffffffff); + + const unsigned VABits = 32; + const unsigned PABits = 32; // Is this correct? + const Addr VAddrImplMask = (ULL(1) << VABits) - 1; + const Addr VAddrUnImplMask = ~VAddrImplMask; + inline Addr VAddrImpl(Addr a) { return a & VAddrImplMask; } + inline Addr VAddrVPN(Addr a) { return a >> ArmISA::PageShift; } + inline Addr VAddrOffset(Addr a) { return a & ArmISA::PageOffset; } + + const Addr PAddrImplMask = (ULL(1) << PABits) - 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 = 16; + const int NumIntSpecialRegs = 19; + const int NumFloatArchRegs = 16; + const int NumFloatSpecialRegs = 5; + const int NumControlRegs = 7; + const int NumInternalProcRegs = 0; + + const int NumIntRegs = NumIntArchRegs + NumIntSpecialRegs; + const int NumFloatRegs = NumFloatArchRegs + NumFloatSpecialRegs; + const int NumMiscRegs = NumControlRegs; + + const int TotalNumRegs = NumIntRegs + NumFloatRegs + NumMiscRegs; + + const int TotalDataRegs = NumIntRegs + NumFloatRegs; + + // Static instruction parameters + const int MaxInstSrcRegs = 5; + const int MaxInstDestRegs = 3; + + // semantically meaningful register indices + const int ReturnValueReg = 0; + const int ReturnValueReg1 = 1; + const int ReturnValueReg2 = 2; + const int ArgumentReg0 = 0; + const int ArgumentReg1 = 1; + const int ArgumentReg2 = 2; + const int ArgumentReg3 = 3; + const int FramePointerReg = 11; + const int StackPointerReg = 13; + const int ReturnAddressReg = 14; + const int PCReg = 15; + + const int ZeroReg = NumIntArchRegs; + const int AddrReg = ZeroReg + 1; // Used to generate address for uops + + const int ArgumentReg[] = {0, 1, 2, 3}; + const int NumArgumentRegs = sizeof(ArgumentReg)/ sizeof(const int); + + const int SyscallNumReg = ReturnValueReg; + const int SyscallPseudoReturnReg = ReturnValueReg; + const int SyscallSuccessReg = ReturnValueReg; + + const int LogVMPageSize = 12; // 4K 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 = NumIntRegs; + const int Ctrl_Base_DepTag = FP_Base_DepTag + NumFloatRegs; +}; + +using namespace ArmISA; + +#endif // __ARCH_ARM_ISA_TRAITS_HH__ diff --git a/src/arch/arm/linux/linux.cc b/src/arch/arm/linux/linux.cc new file mode 100644 index 000000000..a4c782403 --- /dev/null +++ b/src/arch/arm/linux/linux.cc @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2003-2005 The Regents of The University of Michigan + * Copyright (c) 2007-2008 The Florida State University + * 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: Stephen Hines + */ + +#include "arch/arm/linux/linux.hh" + +#include <fcntl.h> + +// open(2) flags translation table +OpenFlagTransTable ArmLinux::openFlagTable[] = { +#ifdef _MSC_VER + { ArmLinux::TGT_O_RDONLY, _O_RDONLY }, + { ArmLinux::TGT_O_WRONLY, _O_WRONLY }, + { ArmLinux::TGT_O_RDWR, _O_RDWR }, + { ArmLinux::TGT_O_APPEND, _O_APPEND }, + { ArmLinux::TGT_O_CREAT, _O_CREAT }, + { ArmLinux::TGT_O_TRUNC, _O_TRUNC }, + { ArmLinux::TGT_O_EXCL, _O_EXCL }, +#ifdef _O_NONBLOCK + { ArmLinux::TGT_O_NONBLOCK, _O_NONBLOCK }, +#endif +#ifdef _O_NOCTTY + { ArmLinux::TGT_O_NOCTTY, _O_NOCTTY }, +#endif +#ifdef _O_SYNC + { ArmLinux::TGT_O_SYNC, _O_SYNC }, +#endif +#else /* !_MSC_VER */ + { ArmLinux::TGT_O_RDONLY, O_RDONLY }, + { ArmLinux::TGT_O_WRONLY, O_WRONLY }, + { ArmLinux::TGT_O_RDWR, O_RDWR }, + { ArmLinux::TGT_O_APPEND, O_APPEND }, + { ArmLinux::TGT_O_CREAT, O_CREAT }, + { ArmLinux::TGT_O_TRUNC, O_TRUNC }, + { ArmLinux::TGT_O_EXCL, O_EXCL }, + { ArmLinux::TGT_O_NONBLOCK, O_NONBLOCK }, + { ArmLinux::TGT_O_NOCTTY, O_NOCTTY }, +#ifdef O_SYNC + { ArmLinux::TGT_O_SYNC, O_SYNC }, +#endif +#endif /* _MSC_VER */ +}; + +const int ArmLinux::NUM_OPEN_FLAGS = + (sizeof(ArmLinux::openFlagTable)/sizeof(ArmLinux::openFlagTable[0])); + diff --git a/src/arch/arm/linux/linux.hh b/src/arch/arm/linux/linux.hh new file mode 100644 index 000000000..e0545761d --- /dev/null +++ b/src/arch/arm/linux/linux.hh @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2003-2005 The Regents of The University of Michigan + * Copyright (c) 2007-2008 The Florida State University + * 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: Stephen Hines + */ + +#ifndef __ARCH_ARM_LINUX_LINUX_HH__ +#define __ARCH_ARM_LINUX_LINUX_HH__ + +#include "kern/linux/linux.hh" + +class ArmLinux : public Linux +{ + public: + + /// This table maps the target open() flags to the corresponding + /// host open() flags. + static OpenFlagTransTable openFlagTable[]; + + /// Number of entries in openFlagTable[]. + static const int NUM_OPEN_FLAGS; + + //@{ + /// open(2) flag values. + static const int TGT_O_RDONLY = 0x00000000; //!< O_RDONLY + static const int TGT_O_WRONLY = 0x00000001; //!< O_WRONLY + static const int TGT_O_RDWR = 0x00000002; //!< O_RDWR + static const int TGT_O_CREAT = 0x00000100; //!< O_CREAT + static const int TGT_O_EXCL = 0x00000200; //!< O_EXCL + static const int TGT_O_NOCTTY = 0x00000400; //!< O_NOCTTY + static const int TGT_O_TRUNC = 0x00001000; //!< O_TRUNC + static const int TGT_O_APPEND = 0x00002000; //!< O_APPEND + static const int TGT_O_NONBLOCK = 0x00004000; //!< O_NONBLOCK + static const int TGT_O_SYNC = 0x00010000; //!< O_SYNC + static const int TGT_FASYNC = 0x00020000; //!< FASYNC + static const int TGT_O_DIRECT = 0x00040000; //!< O_DIRECT + static const int TGT_O_LARGEFILE = 0x00100000; //!< O_LARGEFILE + static const int TGT_O_DIRECTORY = 0x00200000; //!< O_DIRECTORY + static const int TGT_O_NOFOLLOW = 0x00400000; //!< O_NOFOLLOW + static const int TGT_O_NOATIME = 0x01000000; //!< O_NOATIME + //@} + + /// For mmap(). + static const unsigned TGT_MAP_ANONYMOUS = 0x800; + + //@{ + /// For getsysinfo(). + static const unsigned GSI_PLATFORM_NAME = 103; //!< platform name as string + static const unsigned GSI_CPU_INFO = 59; //!< CPU information + static const unsigned GSI_PROC_TYPE = 60; //!< get proc_type + static const unsigned GSI_MAX_CPU = 30; //!< max # cpu's on this machine + static const unsigned GSI_CPUS_IN_BOX = 55; //!< number of CPUs in system + static const unsigned GSI_PHYSMEM = 19; //!< Physical memory in KB + static const unsigned GSI_CLK_TCK = 42; //!< clock freq in Hz + //@} + + //@{ + /// For getrusage(). + static const int TGT_RUSAGE_SELF = 0; + static const int TGT_RUSAGE_CHILDREN = -1; + static const int TGT_RUSAGE_BOTH = -2; + //@} + + //@{ + /// For setsysinfo(). + static const unsigned SSI_IEEE_FP_CONTROL = 14; //!< ieee_set_fp_control() + //@} + + //@{ + /// ioctl() command codes. + static const unsigned TIOCGETP_ = 0x40067408; + static const unsigned TIOCSETP_ = 0x80067409; + static const unsigned TIOCSETN_ = 0x8006740a; + static const unsigned TIOCSETC_ = 0x80067411; + static const unsigned TIOCGETC_ = 0x40067412; + static const unsigned FIONREAD_ = 0x4004667f; + static const unsigned TIOCISATTY_ = 0x2000745e; + static const unsigned TIOCGETS_ = 0x402c7413; + static const unsigned TIOCGETA_ = 0x40127417; + //@} + + /// For table(). + static const int TBL_SYSINFO = 12; + + /// Resource enumeration for getrlimit(). + enum rlimit_resources { + TGT_RLIMIT_CPU = 0, + TGT_RLIMIT_FSIZE = 1, + TGT_RLIMIT_DATA = 2, + TGT_RLIMIT_STACK = 3, + TGT_RLIMIT_CORE = 4, + TGT_RLIMIT_NOFILE = 5, + TGT_RLIMIT_AS = 6, + TGT_RLIMIT_RSS = 7, + TGT_RLIMIT_VMEM = 7, + TGT_RLIMIT_NPROC = 8, + TGT_RLIMIT_MEMLOCK = 9, + TGT_RLIMIT_LOCKS = 10 + }; + +}; + +#endif diff --git a/src/arch/arm/linux/process.cc b/src/arch/arm/linux/process.cc new file mode 100644 index 000000000..6d3153063 --- /dev/null +++ b/src/arch/arm/linux/process.cc @@ -0,0 +1,434 @@ +/* + * Copyright (c) 2003-2005 The Regents of The University of Michigan + * Copyright (c) 2007-2008 The Florida State University + * 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 + * Stephen Hines + */ + +#include "arch/arm/linux/linux.hh" +#include "arch/arm/linux/process.hh" +#include "arch/arm/isa_traits.hh" + +#include "base/trace.hh" +#include "cpu/thread_context.hh" +#include "kern/linux/linux.hh" + +#include "sim/process.hh" +#include "sim/syscall_emul.hh" + +using namespace std; +using namespace ArmISA; + +/// Target uname() handler. +static SyscallReturn +unameFunc(SyscallDesc *desc, int callnum, LiveProcess *process, + ThreadContext *tc) +{ + TypedBufferArg<Linux::utsname> name(tc->getSyscallArg(0)); + + strcpy(name->sysname, "Linux"); + strcpy(name->nodename, "m5.eecs.umich.edu"); + strcpy(name->release, "2.4.20"); + strcpy(name->version, "#1 Mon Aug 18 11:32:15 EDT 2003"); + strcpy(name->machine, "arm"); + + name.copyOut(tc->getMemPort()); + return 0; +} + +SyscallDesc ArmLinuxProcess::syscallDescs[] = { + /* 0 */ SyscallDesc("syscall", unimplementedFunc), + /* 1 */ SyscallDesc("exit", exitFunc), + /* 2 */ SyscallDesc("fork", unimplementedFunc), + /* 3 */ SyscallDesc("read", readFunc), + /* 4 */ SyscallDesc("write", writeFunc), + /* 5 */ SyscallDesc("open", openFunc<ArmLinux>), + /* 6 */ SyscallDesc("close", closeFunc), + /* 7 */ SyscallDesc("waitpid", unimplementedFunc), //??? + /* 8 */ SyscallDesc("creat", unimplementedFunc), + /* 9 */ SyscallDesc("link", unimplementedFunc), + /* 10 */ SyscallDesc("unlink", unlinkFunc), + /* 11 */ SyscallDesc("execve", unimplementedFunc), + /* 12 */ SyscallDesc("chdir", unimplementedFunc), + /* 13 */ SyscallDesc("time", unimplementedFunc), + /* 14 */ SyscallDesc("mknod", unimplementedFunc), + /* 15 */ SyscallDesc("chmod", chmodFunc<ArmLinux>), + /* 16 */ SyscallDesc("lchown", chownFunc), + /* 17 */ SyscallDesc("break", obreakFunc), //??? + /* 18 */ SyscallDesc("unused#18", unimplementedFunc), //??? + /* 19 */ SyscallDesc("lseek", lseekFunc), + /* 20 */ SyscallDesc("getpid", getpidFunc), + /* 21 */ SyscallDesc("mount", unimplementedFunc), + /* 22 */ SyscallDesc("umount", unimplementedFunc), + /* 23 */ SyscallDesc("setuid", setuidFunc), + /* 24 */ SyscallDesc("getuid", getuidFunc), + /* 25 */ SyscallDesc("stime", unimplementedFunc), + /* 26 */ SyscallDesc("ptrace", unimplementedFunc), + /* 27 */ SyscallDesc("alarm", unimplementedFunc), + /* 28 */ SyscallDesc("unused#28", unimplementedFunc), + /* 29 */ SyscallDesc("pause", unimplementedFunc), + /* 30 */ SyscallDesc("utime", unimplementedFunc), + /* 31 */ SyscallDesc("stty", unimplementedFunc), + /* 32 */ SyscallDesc("gtty", unimplementedFunc), + /* 33 */ SyscallDesc("access", unimplementedFunc), + /* 34 */ SyscallDesc("nice", unimplementedFunc), + /* 35 */ SyscallDesc("ftime", unimplementedFunc), + /* 36 */ SyscallDesc("sync", unimplementedFunc), + /* 37 */ SyscallDesc("kill", ignoreFunc), + /* 38 */ SyscallDesc("rename", unimplementedFunc), + /* 39 */ SyscallDesc("mkdir", unimplementedFunc), + /* 40 */ SyscallDesc("rmdir", unimplementedFunc), + /* 41 */ SyscallDesc("dup", unimplementedFunc), + /* 42 */ SyscallDesc("pipe", unimplementedFunc), + /* 43 */ SyscallDesc("times", unimplementedFunc), + /* 44 */ SyscallDesc("prof", unimplementedFunc), + /* 45 */ SyscallDesc("brk", obreakFunc), + /* 46 */ SyscallDesc("setgid", unimplementedFunc), + /* 47 */ SyscallDesc("getgid", getgidFunc), + /* 48 */ SyscallDesc("signal", ignoreFunc), + /* 49 */ SyscallDesc("geteuid", geteuidFunc), + /* 50 */ SyscallDesc("getegid", getegidFunc), + /* 51 */ SyscallDesc("acct", unimplementedFunc), + /* 52 */ SyscallDesc("umount2", unimplementedFunc), + /* 53 */ SyscallDesc("lock", unimplementedFunc), + /* 54 */ SyscallDesc("ioctl", ioctlFunc<ArmLinux>), + /* 55 */ SyscallDesc("fcntl", fcntlFunc), + /* 56 */ SyscallDesc("mpx", unimplementedFunc), + /* 57 */ SyscallDesc("setpgid", unimplementedFunc), + /* 58 */ SyscallDesc("ulimit", unimplementedFunc), + /* 59 */ SyscallDesc("unused#59", unimplementedFunc), + /* 60 */ SyscallDesc("umask", unimplementedFunc), + /* 61 */ SyscallDesc("chroot", unimplementedFunc), + /* 62 */ SyscallDesc("ustat", unimplementedFunc), + /* 63 */ SyscallDesc("dup2", unimplementedFunc), + /* 64 */ SyscallDesc("getppid", getpagesizeFunc), + /* 65 */ SyscallDesc("getpgrp", unimplementedFunc), + /* 66 */ SyscallDesc("setsid", unimplementedFunc), + /* 67 */ SyscallDesc("sigaction",unimplementedFunc), + /* 68 */ SyscallDesc("sgetmask", unimplementedFunc), + /* 69 */ SyscallDesc("ssetmask", unimplementedFunc), + /* 70 */ SyscallDesc("setreuid", unimplementedFunc), + /* 71 */ SyscallDesc("setregid", unimplementedFunc), + /* 72 */ SyscallDesc("sigsuspend", unimplementedFunc), + /* 73 */ SyscallDesc("sigpending", unimplementedFunc), + /* 74 */ SyscallDesc("sethostname", ignoreFunc), + /* 75 */ SyscallDesc("setrlimit", unimplementedFunc), + /* 76 */ SyscallDesc("getrlimit", unimplementedFunc), + /* 77 */ SyscallDesc("getrusage", unimplementedFunc), + /* 78 */ SyscallDesc("gettimeofday", unimplementedFunc), + /* 79 */ SyscallDesc("settimeofday", unimplementedFunc), + /* 80 */ SyscallDesc("getgroups", unimplementedFunc), + /* 81 */ SyscallDesc("setgroups", unimplementedFunc), + /* 82 */ SyscallDesc("reserved#82", unimplementedFunc), + /* 83 */ SyscallDesc("symlink", unimplementedFunc), + /* 84 */ SyscallDesc("unused#84", unimplementedFunc), + /* 85 */ SyscallDesc("readlink", unimplementedFunc), + /* 86 */ SyscallDesc("uselib", unimplementedFunc), + /* 87 */ SyscallDesc("swapon", gethostnameFunc), + /* 88 */ SyscallDesc("reboot", unimplementedFunc), + /* 89 */ SyscallDesc("readdir", unimplementedFunc), + /* 90 */ SyscallDesc("mmap", mmapFunc<ArmLinux>), + /* 91 */ SyscallDesc("munmap",munmapFunc), + /* 92 */ SyscallDesc("truncate", truncateFunc), + /* 93 */ SyscallDesc("ftruncate", ftruncateFunc), + /* 94 */ SyscallDesc("fchmod", unimplementedFunc), + /* 95 */ SyscallDesc("fchown", unimplementedFunc), + /* 96 */ SyscallDesc("getpriority", unimplementedFunc), + /* 97 */ SyscallDesc("setpriority", unimplementedFunc), + /* 98 */ SyscallDesc("profil", unimplementedFunc), + /* 99 */ SyscallDesc("statfs", unimplementedFunc), + /* 100 */ SyscallDesc("fstatfs", unimplementedFunc), + /* 101 */ SyscallDesc("ioperm", unimplementedFunc), + /* 102 */ SyscallDesc("socketcall", unimplementedFunc), + /* 103 */ SyscallDesc("syslog", unimplementedFunc), + /* 104 */ SyscallDesc("setitimer", unimplementedFunc), + /* 105 */ SyscallDesc("getitimer", unimplementedFunc), + /* 106 */ SyscallDesc("stat", statFunc<ArmLinux>), + /* 107 */ SyscallDesc("lstat", unimplementedFunc), + /* 108 */ SyscallDesc("fstat", fstatFunc<ArmLinux>), + /* 109 */ SyscallDesc("unused#109", unimplementedFunc), + /* 110 */ SyscallDesc("iopl", unimplementedFunc), + /* 111 */ SyscallDesc("vhangup", unimplementedFunc), + /* 112 */ SyscallDesc("idle", ignoreFunc), + /* 113 */ SyscallDesc("vm86", unimplementedFunc), + /* 114 */ SyscallDesc("wait4", unimplementedFunc), + /* 115 */ SyscallDesc("swapoff", unimplementedFunc), + /* 116 */ SyscallDesc("sysinfo", unimplementedFunc), + /* 117 */ SyscallDesc("ipc", unimplementedFunc), + /* 118 */ SyscallDesc("fsync", unimplementedFunc), + /* 119 */ SyscallDesc("sigreturn", unimplementedFunc), + /* 120 */ SyscallDesc("clone", unimplementedFunc), + /* 121 */ SyscallDesc("setdomainname", unimplementedFunc), + /* 122 */ SyscallDesc("uname", unameFunc), + /* 123 */ SyscallDesc("modify_ldt", unimplementedFunc), + /* 124 */ SyscallDesc("adjtimex", unimplementedFunc), + /* 125 */ SyscallDesc("mprotect", ignoreFunc), + /* 126 */ SyscallDesc("sigprocmask", unimplementedFunc), + /* 127 */ SyscallDesc("create_module", unimplementedFunc), + /* 128 */ SyscallDesc("init_module", unimplementedFunc), + /* 129 */ SyscallDesc("delete_module", unimplementedFunc), + /* 130 */ SyscallDesc("get_kernel_syms", unimplementedFunc), + /* 131 */ SyscallDesc("quotactl", unimplementedFunc), + /* 132 */ SyscallDesc("getpgid", unimplementedFunc), + /* 133 */ SyscallDesc("fchdir", unimplementedFunc), + /* 134 */ SyscallDesc("bdflush", unimplementedFunc), + /* 135 */ SyscallDesc("sysfs", unimplementedFunc), + /* 136 */ SyscallDesc("personality", unimplementedFunc), + /* 137 */ SyscallDesc("afs_syscall", unimplementedFunc), + /* 138 */ SyscallDesc("setfsuid", unimplementedFunc), + /* 139 */ SyscallDesc("setfsgid", unimplementedFunc), + /* 140 */ SyscallDesc("llseek", unimplementedFunc), + /* 141 */ SyscallDesc("getdents", unimplementedFunc), + /* 142 */ SyscallDesc("newselect", unimplementedFunc), + /* 143 */ SyscallDesc("flock", unimplementedFunc), + /* 144 */ SyscallDesc("msync", unimplementedFunc), + /* 145 */ SyscallDesc("readv", unimplementedFunc), + /* 146 */ SyscallDesc("writev", writevFunc<ArmLinux>), + /* 147 */ SyscallDesc("getsid", unimplementedFunc), + /* 148 */ SyscallDesc("fdatasync", unimplementedFunc), + /* 149 */ SyscallDesc("sysctl", unimplementedFunc), + /* 150 */ SyscallDesc("mlock", unimplementedFunc), + /* 151 */ SyscallDesc("munlock", unimplementedFunc), + /* 152 */ SyscallDesc("mlockall", unimplementedFunc), + /* 153 */ SyscallDesc("munlockall", unimplementedFunc), + /* 154 */ SyscallDesc("sched_setparam", unimplementedFunc), + /* 155 */ SyscallDesc("sched_getparam", unimplementedFunc), + /* 156 */ SyscallDesc("sched_setscheduler", unimplementedFunc), + /* 157 */ SyscallDesc("sched_getscheduler", unimplementedFunc), + /* 158 */ SyscallDesc("sched_yield", unimplementedFunc), + /* 159 */ SyscallDesc("sched_get_priority_max", unimplementedFunc), + /* 160 */ SyscallDesc("sched_get_priority_min", unimplementedFunc), + /* 161 */ SyscallDesc("sched_rr_get_interval", unimplementedFunc), + /* 162 */ SyscallDesc("nanosleep", unimplementedFunc), + /* 163 */ SyscallDesc("mremap", unimplementedFunc), // ARM-specific + /* 164 */ SyscallDesc("setresuid", unimplementedFunc), + /* 165 */ SyscallDesc("getresuid", unimplementedFunc), + /* 166 */ SyscallDesc("vm862", unimplementedFunc), + /* 167 */ SyscallDesc("query_module", unimplementedFunc), + /* 168 */ SyscallDesc("poll", unimplementedFunc), + /* 169 */ SyscallDesc("nfsservctl", unimplementedFunc), + /* 170 */ SyscallDesc("setresgid", unimplementedFunc), + /* 171 */ SyscallDesc("getresgid", unimplementedFunc), + /* 172 */ SyscallDesc("prctl", unimplementedFunc), + /* 173 */ SyscallDesc("rt_sigreturn", unimplementedFunc), + /* 174 */ SyscallDesc("rt_sigaction", unimplementedFunc), + /* 175 */ SyscallDesc("rt_sigprocmask", unimplementedFunc), + /* 176 */ SyscallDesc("rt_sigpending", unimplementedFunc), + /* 177 */ SyscallDesc("rt_sigtimedwait", unimplementedFunc), + /* 178 */ SyscallDesc("rt_sigqueueinfo", ignoreFunc), + /* 179 */ SyscallDesc("rt_sigsuspend", unimplementedFunc), + /* 180 */ SyscallDesc("pread64", unimplementedFunc), + /* 181 */ SyscallDesc("pwrite64", unimplementedFunc), + /* 182 */ SyscallDesc("chown", unimplementedFunc), + /* 183 */ SyscallDesc("getcwd", unimplementedFunc), + /* 184 */ SyscallDesc("capget", unimplementedFunc), + /* 185 */ SyscallDesc("capset", unimplementedFunc), + /* 186 */ SyscallDesc("sigaltstack", unimplementedFunc), + /* 187 */ SyscallDesc("sendfile", unimplementedFunc), + /* 188 */ SyscallDesc("getpmsg", unimplementedFunc), + /* 189 */ SyscallDesc("putpmsg", unimplementedFunc), + /* 190 */ SyscallDesc("vfork", unimplementedFunc), + /* 191 */ SyscallDesc("getrlimit", unimplementedFunc), + /* 192 */ SyscallDesc("mmap2", unimplementedFunc), + /* 193 */ SyscallDesc("truncate64", unimplementedFunc), + /* 194 */ SyscallDesc("ftruncate64", unimplementedFunc), + /* 195 */ SyscallDesc("stat64", unimplementedFunc), + /* 196 */ SyscallDesc("lstat64", lstat64Func<ArmLinux>), + /* 197 */ SyscallDesc("fstat64", fstatFunc<ArmLinux>), + /* 198 */ SyscallDesc("lchown", unimplementedFunc), + /* 199 */ SyscallDesc("getuid", getuidFunc), + /* 200 */ SyscallDesc("getgid", getgidFunc), + /* 201 */ SyscallDesc("geteuid", geteuidFunc), + /* 202 */ SyscallDesc("getegid", getegidFunc), + /* 203 */ SyscallDesc("setreuid", unimplementedFunc), + /* 204 */ SyscallDesc("setregid", unimplementedFunc), + /* 205 */ SyscallDesc("getgroups", unimplementedFunc), + /* 206 */ SyscallDesc("setgroups", unimplementedFunc), + /* 207 */ SyscallDesc("fchown", unimplementedFunc), + /* 208 */ SyscallDesc("setresuid", unimplementedFunc), + /* 209 */ SyscallDesc("getresuid", unimplementedFunc), + /* 210 */ SyscallDesc("setresgid", unimplementedFunc), + /* 211 */ SyscallDesc("getresgid", unimplementedFunc), + /* 212 */ SyscallDesc("chown", unimplementedFunc), + /* 213 */ SyscallDesc("setuid", unimplementedFunc), + /* 214 */ SyscallDesc("setgid", unimplementedFunc), + /* 215 */ SyscallDesc("setfsuid", unimplementedFunc), + /* 216 */ SyscallDesc("setfsgid", unimplementedFunc), + /* 217 */ SyscallDesc("getdents64", unimplementedFunc), + /* 218 */ SyscallDesc("pivot_root", unimplementedFunc), + /* 219 */ SyscallDesc("mincore", unimplementedFunc), + /* 220 */ SyscallDesc("madvise", unimplementedFunc), + /* 221 */ SyscallDesc("fcntl64", fcntl64Func), + /* 222 */ SyscallDesc("tux", unimplementedFunc), + /* 223 */ SyscallDesc("unknown#223", unimplementedFunc), + /* 224 */ SyscallDesc("gettid", unimplementedFunc), + /* 225 */ SyscallDesc("readahead", unimplementedFunc), + /* 226 */ SyscallDesc("setxattr", unimplementedFunc), + /* 227 */ SyscallDesc("lsetxattr", unimplementedFunc), + /* 228 */ SyscallDesc("fsetxattr", unimplementedFunc), + /* 229 */ SyscallDesc("getxattr", unimplementedFunc), + /* 230 */ SyscallDesc("lgetxattr", unimplementedFunc), + /* 231 */ SyscallDesc("fgetxattr", unimplementedFunc), + /* 232 */ SyscallDesc("listxattr", unimplementedFunc), + /* 233 */ SyscallDesc("llistxattr", unimplementedFunc), + /* 234 */ SyscallDesc("flistxattr", unimplementedFunc), + /* 235 */ SyscallDesc("removexattr", unimplementedFunc), + /* 236 */ SyscallDesc("lremovexattr", unimplementedFunc), + /* 237 */ SyscallDesc("fremovexattr", unimplementedFunc), + /* 238 */ SyscallDesc("tkill", unimplementedFunc), + /* 239 */ SyscallDesc("sendfile64", unimplementedFunc), + /* 240 */ SyscallDesc("futex", unimplementedFunc), + /* 241 */ SyscallDesc("sched_setaffinity", unimplementedFunc), + /* 242 */ SyscallDesc("sched_getaffinity", unimplementedFunc), + /* 243 */ SyscallDesc("io_setup", unimplementedFunc), + /* 244 */ SyscallDesc("io_destory", unimplementedFunc), + /* 245 */ SyscallDesc("io_getevents", unimplementedFunc), + /* 246 */ SyscallDesc("io_submit", unimplementedFunc), + /* 247 */ SyscallDesc("io_cancel", unimplementedFunc), + /* 248 */ SyscallDesc("exit_group", exitFunc), + /* 249 */ SyscallDesc("lookup_dcookie", unimplementedFunc), + /* 250 */ SyscallDesc("epoll_create", unimplementedFunc), + /* 251 */ SyscallDesc("epoll_ctl", unimplementedFunc), + /* 252 */ SyscallDesc("epoll_wait", unimplementedFunc), + /* 253 */ SyscallDesc("remap_file_pages", unimplementedFunc), + /* 254 */ SyscallDesc("set_thread_area", unimplementedFunc), + /* 255 */ SyscallDesc("get_thread_area", unimplementedFunc), + /* 256 */ SyscallDesc("set_tid_address", unimplementedFunc), + /* 257 */ SyscallDesc("timer_create", unimplementedFunc), + /* 258 */ SyscallDesc("timer_settime", unimplementedFunc), + /* 259 */ SyscallDesc("timer_gettime", unimplementedFunc), + /* 260 */ SyscallDesc("timer_getoverrun", unimplementedFunc), + /* 261 */ SyscallDesc("timer_delete", unimplementedFunc), + /* 262 */ SyscallDesc("clock_settime", unimplementedFunc), + /* 263 */ SyscallDesc("clock_gettime", unimplementedFunc), + /* 264 */ SyscallDesc("clock_getres", unimplementedFunc), + /* 265 */ SyscallDesc("clock_nanosleep", unimplementedFunc), + /* 266 */ SyscallDesc("statfs64", unimplementedFunc), + /* 267 */ SyscallDesc("fstatfs64", unimplementedFunc), + /* 268 */ SyscallDesc("tgkill", unimplementedFunc), + /* 269 */ SyscallDesc("utimes", unimplementedFunc), + /* 270 */ SyscallDesc("arm_fadvise64_64", unimplementedFunc), + /* 271 */ SyscallDesc("pciconfig_iobase", unimplementedFunc), + /* 272 */ SyscallDesc("pciconfig_read", unimplementedFunc), + /* 273 */ SyscallDesc("pciconfig_write", unimplementedFunc), + /* 274 */ SyscallDesc("mq_open", unimplementedFunc), + /* 275 */ SyscallDesc("mq_unlink", unimplementedFunc), + /* 276 */ SyscallDesc("mq_timedsend", unimplementedFunc), + /* 277 */ SyscallDesc("mq_timedreceive", unimplementedFunc), + /* 278 */ SyscallDesc("mq_notify", unimplementedFunc), + /* 279 */ SyscallDesc("mq_getsetattr", unimplementedFunc), + /* 280 */ SyscallDesc("waitid", unimplementedFunc), + /* 281 */ SyscallDesc("socket", unimplementedFunc), + /* 282 */ SyscallDesc("bind", unimplementedFunc), + /* 283 */ SyscallDesc("connect", unimplementedFunc), + /* 284 */ SyscallDesc("listen", unimplementedFunc), + /* 285 */ SyscallDesc("accept", unimplementedFunc), + /* 286 */ SyscallDesc("getsockname", unimplementedFunc), + /* 287 */ SyscallDesc("getpeername", unimplementedFunc), + /* 288 */ SyscallDesc("socketpair", unimplementedFunc), + /* 289 */ SyscallDesc("send", unimplementedFunc), + /* 290 */ SyscallDesc("sendto", unimplementedFunc), + /* 291 */ SyscallDesc("recv", unimplementedFunc), + /* 292 */ SyscallDesc("recvfrom", unimplementedFunc), + /* 293 */ SyscallDesc("shutdown", unimplementedFunc), + /* 294 */ SyscallDesc("setsockopt", unimplementedFunc), + /* 295 */ SyscallDesc("getsockopt", unimplementedFunc), + /* 296 */ SyscallDesc("sendmsg", unimplementedFunc), + /* 297 */ SyscallDesc("rcvmsg", unimplementedFunc), + /* 298 */ SyscallDesc("semop", unimplementedFunc), + /* 299 */ SyscallDesc("semget", unimplementedFunc), + /* 300 */ SyscallDesc("semctl", unimplementedFunc), + /* 301 */ SyscallDesc("msgsend", unimplementedFunc), + /* 302 */ SyscallDesc("msgrcv", unimplementedFunc), + /* 303 */ SyscallDesc("msgget", unimplementedFunc), + /* 304 */ SyscallDesc("msgctl", unimplementedFunc), + /* 305 */ SyscallDesc("shmat", unimplementedFunc), + /* 306 */ SyscallDesc("shmdt", unimplementedFunc), + /* 307 */ SyscallDesc("shmget", unimplementedFunc), + /* 308 */ SyscallDesc("shmctl", unimplementedFunc), + /* 309 */ SyscallDesc("add_key", unimplementedFunc), + /* 310 */ SyscallDesc("request_key", unimplementedFunc), + /* 311 */ SyscallDesc("keyctl", unimplementedFunc), + /* 312 */ SyscallDesc("semtimedop", unimplementedFunc), + /* 313 */ SyscallDesc("vserver", unimplementedFunc), + /* 314 */ SyscallDesc("ioprio_set", unimplementedFunc), + /* 315 */ SyscallDesc("ioprio_get", unimplementedFunc), + /* 316 */ SyscallDesc("inotify_init", unimplementedFunc), + /* 317 */ SyscallDesc("inotify_add_watch", unimplementedFunc), + /* 318 */ SyscallDesc("inotify_rm_watch", unimplementedFunc), + /* 319 */ SyscallDesc("mbind", unimplementedFunc), + /* 320 */ SyscallDesc("get_mempolicy", unimplementedFunc), + /* 321 */ SyscallDesc("set_mempolicy", unimplementedFunc), + /* 322 */ SyscallDesc("openat", unimplementedFunc), + /* 323 */ SyscallDesc("mkdirat", unimplementedFunc), + /* 324 */ SyscallDesc("mknodat", unimplementedFunc), + /* 325 */ SyscallDesc("fchownat", unimplementedFunc), + /* 326 */ SyscallDesc("futimesat", unimplementedFunc), + /* 327 */ SyscallDesc("fstatat64", unimplementedFunc), + /* 328 */ SyscallDesc("unlinkat", unimplementedFunc), + /* 329 */ SyscallDesc("renameat", unimplementedFunc), + /* 330 */ SyscallDesc("linkat", unimplementedFunc), + /* 331 */ SyscallDesc("symlinkat", unimplementedFunc), + /* 332 */ SyscallDesc("readlinkat", unimplementedFunc), + /* 333 */ SyscallDesc("fchmodat", unimplementedFunc), + /* 334 */ SyscallDesc("faccessat", unimplementedFunc), + /* 335 */ SyscallDesc("pselect6", unimplementedFunc), + /* 336 */ SyscallDesc("ppoll", unimplementedFunc), + /* 337 */ SyscallDesc("unshare", unimplementedFunc), + /* 338 */ SyscallDesc("set_robust_list", unimplementedFunc), + /* 339 */ SyscallDesc("get_robust_list", unimplementedFunc), + /* 340 */ SyscallDesc("splice", unimplementedFunc), + /* 341 */ SyscallDesc("arm_sync_file_range", unimplementedFunc), + /* 342 */ SyscallDesc("tee", unimplementedFunc), + /* 343 */ SyscallDesc("vmsplice", unimplementedFunc), + /* 344 */ SyscallDesc("move_pages", unimplementedFunc), + /* 345 */ SyscallDesc("getcpu", unimplementedFunc), + /* 346 */ SyscallDesc("epoll_pwait", unimplementedFunc), +}; + +ArmLinuxProcess::ArmLinuxProcess(LiveProcessParams * params, + ObjectFile *objFile) + : ArmLiveProcess(params, objFile), + Num_Syscall_Descs(sizeof(syscallDescs) / sizeof(SyscallDesc)) +{ } + +SyscallDesc* +ArmLinuxProcess::getDesc(int callnum) +{ + // Angel SWI syscalls are unsupported in this release + if (callnum == 0x123456) + panic("Attempt to execute an ANGEL_SWI system call (newlib-related)"); + else if ((callnum & 0x00f00000) == 0x00900000) + callnum &= 0x000fffff; + // Linux syscalls have to strip off the 0x00900000 + + if (callnum < 0 || callnum > Num_Syscall_Descs) + return NULL; + + return &syscallDescs[callnum]; +} diff --git a/src/arch/arm/linux/process.hh b/src/arch/arm/linux/process.hh new file mode 100644 index 000000000..524661b5b --- /dev/null +++ b/src/arch/arm/linux/process.hh @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2007-2008 The Florida State University + * 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: Stephen Hines + */ + +#ifndef __ARM_LINUX_PROCESS_HH__ +#define __ARM_LINUX_PROCESS_HH__ + +#include "arch/arm/process.hh" + + +/// A process with emulated Arm/Linux syscalls. +class ArmLinuxProcess : public ArmLiveProcess +{ + public: + ArmLinuxProcess(LiveProcessParams * params, ObjectFile *objFile); + + virtual SyscallDesc* getDesc(int callnum); + + /// The target system's hostname. + static const char *hostname; + + /// Array of syscall descriptors, indexed by call number. + static SyscallDesc syscallDescs[]; + + const int Num_Syscall_Descs; +}; + +#endif // __ARM_LINUX_PROCESS_HH__ diff --git a/src/arch/arm/locked_mem.hh b/src/arch/arm/locked_mem.hh new file mode 100644 index 000000000..41899273a --- /dev/null +++ b/src/arch/arm/locked_mem.hh @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2006 The Regents of The University of Michigan + * Copyright (c) 2007-2008 The Florida State University + * 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 + * Stephen Hines + */ + +#ifndef __ARCH_ARM_LOCKED_MEM_HH__ +#define __ARCH_ARM_LOCKED_MEM_HH__ + +/** + * @file + * + * ISA-specific helper functions for locked memory accesses. + */ + +#include "mem/request.hh" + + +namespace ArmISA +{ +template <class XC> +inline void +handleLockedRead(XC *xc, Request *req) +{ +} + + +template <class XC> +inline bool +handleLockedWrite(XC *xc, Request *req) +{ + return true; +} + + +} // namespace ArmISA + +#endif diff --git a/src/arch/arm/mmaped_ipr.hh b/src/arch/arm/mmaped_ipr.hh new file mode 100644 index 000000000..8483ef7a2 --- /dev/null +++ b/src/arch/arm/mmaped_ipr.hh @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2006 The Regents of The University of Michigan + * Copyright (c) 2007-2008 The Florida State University + * 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: Ali Saidi + * Stephen Hines + */ + +#ifndef __ARCH_ARM_MMAPED_IPR_HH__ +#define __ARCH_ARM_MMAPED_IPR_HH__ + +/** + * @file + * + * ISA-specific helper functions for memory mapped IPR accesses. + */ + +#include "base/misc.hh" +#include "mem/packet.hh" + +class ThreadContext; + +namespace ArmISA +{ +inline Tick +handleIprRead(ThreadContext *xc, Packet *pkt) +{ + panic("No implementation for handleIprRead in ARM\n"); +} + +inline Tick +handleIprWrite(ThreadContext *xc, Packet *pkt) +{ + panic("No implementation for handleIprWrite in ARM\n"); +} + + +} // namespace ArmISA + +#endif diff --git a/src/arch/arm/pagetable.cc b/src/arch/arm/pagetable.cc new file mode 100644 index 000000000..aebe7f00a --- /dev/null +++ b/src/arch/arm/pagetable.cc @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2002-2005 The Regents of The University of Michigan + * Copyright (c) 2007 MIPS Technologies, Inc. + * Copyright (c) 2007-2008 The Florida State University + * 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 + * Jaidev Patwardhan + * Stephen Hines + */ + +#include "arch/arm/pagetable.hh" +#include "sim/serialize.hh" + +namespace ArmISA +{ + void + PTE::serialize(std::ostream &os) + { + SERIALIZE_SCALAR(Mask); + SERIALIZE_SCALAR(VPN); + SERIALIZE_SCALAR(asid); + SERIALIZE_SCALAR(G); + SERIALIZE_SCALAR(PFN0); + SERIALIZE_SCALAR(D0); + SERIALIZE_SCALAR(V0); + SERIALIZE_SCALAR(C0); + SERIALIZE_SCALAR(PFN1); + SERIALIZE_SCALAR(D1); + SERIALIZE_SCALAR(V1); + SERIALIZE_SCALAR(C1); + SERIALIZE_SCALAR(AddrShiftAmount); + SERIALIZE_SCALAR(OffsetMask); + } + + void + PTE::unserialize(Checkpoint *cp, const std::string §ion) + { + UNSERIALIZE_SCALAR(Mask); + UNSERIALIZE_SCALAR(VPN); + UNSERIALIZE_SCALAR(asid); + UNSERIALIZE_SCALAR(G); + UNSERIALIZE_SCALAR(PFN0); + UNSERIALIZE_SCALAR(D0); + UNSERIALIZE_SCALAR(V0); + UNSERIALIZE_SCALAR(C0); + UNSERIALIZE_SCALAR(PFN1); + UNSERIALIZE_SCALAR(D1); + UNSERIALIZE_SCALAR(V1); + UNSERIALIZE_SCALAR(C1); + UNSERIALIZE_SCALAR(AddrShiftAmount); + UNSERIALIZE_SCALAR(OffsetMask); + } +} diff --git a/src/arch/arm/pagetable.hh b/src/arch/arm/pagetable.hh new file mode 100644 index 000000000..ad3464a63 --- /dev/null +++ b/src/arch/arm/pagetable.hh @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2002-2005 The Regents of The University of Michigan + * Copyright (c) 2007 MIPS Technologies, Inc. + * Copyright (c) 2007-2008 The Florida State University + * 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 + * Jaidev Patwardhan + * Stephen Hines + */ + +#ifndef __ARCH_ARM_PAGETABLE_H__ +#define __ARCH_ARM_PAGETABLE_H__ + +#include "arch/arm/isa_traits.hh" +#include "arch/arm/utility.hh" +#include "arch/arm/vtophys.hh" +#include "config/full_system.hh" + +namespace ArmISA { + + 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 & Page_Mask; } + Addr offset() const { return addr & PageOffset; } + + Addr level3() const + { return ArmISA::PteAddr(addr >> PageShift); } + Addr level2() const + { return ArmISA::PteAddr(addr >> (NPtePageShift + PageShift)); } + Addr level1() const + { return ArmISA::PteAddr(addr >> (2 * NPtePageShift + PageShift)); } + }; + + // ITB/DTB page table entry + struct PTE + { + Addr Mask; // What parts of the VAddr (from bits 28..11) should be used in translation (includes Mask and MaskX from PageMask) + Addr VPN; // Virtual Page Number (/2) (Includes VPN2 + VPN2X .. bits 31..11 from EntryHi) + uint8_t asid; // Address Space ID (8 bits) // Lower 8 bits of EntryHi + + bool G; // Global Bit - Obtained by an *AND* of EntryLo0 and EntryLo1 G bit + + /* Contents of Entry Lo0 */ + Addr PFN0; // Physical Frame Number - Even + bool D0; // Even entry Dirty Bit + bool V0; // Even entry Valid Bit + uint8_t C0; // Cache Coherency Bits - Even + + /* Contents of Entry Lo1 */ + Addr PFN1; // Physical Frame Number - Odd + bool D1; // Odd entry Dirty Bit + bool V1; // Odd entry Valid Bit + uint8_t C1; // Cache Coherency Bits (3 bits) + + /* The next few variables are put in as optimizations to reduce TLB lookup overheads */ + /* For a given Mask, what is the address shift amount, and what is the OffsetMask */ + int AddrShiftAmount; + int OffsetMask; + + bool Valid() { return (V0 | V1);}; + void serialize(std::ostream &os); + void unserialize(Checkpoint *cp, const std::string §ion); + }; + +}; +#endif // __ARCH_ARM_PAGETABLE_H__ + diff --git a/src/arch/arm/predecoder.hh b/src/arch/arm/predecoder.hh new file mode 100644 index 000000000..86d344b05 --- /dev/null +++ b/src/arch/arm/predecoder.hh @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2006 The Regents of The University of Michigan + * Copyright (c) 2007-2008 The Florida State University + * 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 + * Stephen Hines + */ + +#ifndef __ARCH_ARM_PREDECODER_HH__ +#define __ARCH_ARM_PREDECODER_HH__ + +#include "arch/arm/types.hh" +#include "base/misc.hh" +#include "sim/host.hh" + +class ThreadContext; + +namespace ArmISA +{ + class Predecoder + { + protected: + ThreadContext * tc; + //The extended machine instruction being generated + ExtMachInst emi; + + public: + Predecoder(ThreadContext * _tc) : tc(_tc) + {} + + ThreadContext * getTC() + { + return tc; + } + + void setTC(ThreadContext * _tc) + { + tc = _tc; + } + + void process() + {} + + void reset() + {} + + //Use this to give data to the predecoder. This should be used + //when there is control flow. + void moreBytes(Addr pc, Addr fetchPC, MachInst inst) + { + emi = inst; + } + + //Use this to give data to the predecoder. This should be used + //when instructions are executed in order. + void moreBytes(MachInst machInst) + { + moreBytes(0, 0, machInst); + } + + bool needMoreBytes() + { + return true; + } + + bool extMachInstReady() + { + return true; + } + + //This returns a constant reference to the ExtMachInst to avoid a copy + const ExtMachInst & getExtMachInst() + { + return emi; + } + }; +}; + +#endif // __ARCH_ARM_PREDECODER_HH__ diff --git a/src/arch/arm/process.cc b/src/arch/arm/process.cc new file mode 100644 index 000000000..00ba414ba --- /dev/null +++ b/src/arch/arm/process.cc @@ -0,0 +1,158 @@ +/* + * Copyright (c) 2007-2008 The Florida State University + * 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: Stephen Hines + */ + +#include "arch/arm/isa_traits.hh" +#include "arch/arm/process.hh" +#include "arch/arm/types.hh" +#include "base/loader/elf_object.hh" +#include "base/loader/object_file.hh" +#include "base/misc.hh" +#include "cpu/thread_context.hh" +#include "mem/page_table.hh" +#include "mem/translating_port.hh" +#include "sim/process_impl.hh" +#include "sim/system.hh" + +using namespace std; +using namespace ArmISA; + +ArmLiveProcess::ArmLiveProcess(LiveProcessParams * params, + ObjectFile *objFile) + : LiveProcess(params, objFile) +{ + stack_base = 0xc0000000L; + + // Set pointer for next thread stack. Reserve 8M for main stack. + next_thread_stack_base = stack_base - (8 * 1024 * 1024); + + // Set up break point (Top of Heap) + brk_point = objFile->dataBase() + objFile->dataSize() + objFile->bssSize(); + brk_point = roundUp(brk_point, VMPageSize); + + // Set up region for mmaps. For now, start at bottom of kuseg space. + mmap_start = mmap_end = 0x70000000L; +} + +void +ArmLiveProcess::startup() +{ + argsInit(MachineBytes, VMPageSize); +} + +void +ArmLiveProcess::copyStringArray32(std::vector<std::string> &strings, + Addr array_ptr, Addr data_ptr, + TranslatingPort* memPort) +{ + Addr data_ptr_swap; + for (int i = 0; i < strings.size(); ++i) { + data_ptr_swap = htog(data_ptr); + memPort->writeBlob(array_ptr, (uint8_t*)&data_ptr_swap, + sizeof(uint32_t)); + memPort->writeString(data_ptr, strings[i].c_str()); + array_ptr += sizeof(uint32_t); + data_ptr += strings[i].size() + 1; + } + // add NULL terminator + data_ptr = 0; + + memPort->writeBlob(array_ptr, (uint8_t*)&data_ptr, sizeof(uint32_t)); +} + +void +ArmLiveProcess::argsInit(int intSize, int pageSize) +{ + // Overloaded argsInit so that we can fine-tune for ARM architecture + Process::startup(); + + // load object file into target memory + objFile->loadSections(initVirtMem); + + // Calculate how much space we need for arg & env arrays. + int argv_array_size = intSize * (argv.size() + 1); + int envp_array_size = intSize * (envp.size() + 1); + int arg_data_size = 0; + for (int i = 0; i < argv.size(); ++i) { + arg_data_size += argv[i].size() + 1; + } + int env_data_size = 0; + for (int i = 0; i < envp.size(); ++i) { + env_data_size += envp[i].size() + 1; + } + + int space_needed = + argv_array_size + envp_array_size + arg_data_size + env_data_size; + if (space_needed < 16*1024) + space_needed = 16*1024; + + // set bottom of stack + stack_min = stack_base - space_needed; + // align it + stack_min = roundDown(stack_min, pageSize); + stack_size = stack_base - stack_min; + // map memory + pTable->allocate(stack_min, roundUp(stack_size, pageSize)); + + // map out initial stack contents + Addr argv_array_base = stack_min + intSize; // room for argc + Addr envp_array_base = argv_array_base + argv_array_size; + Addr arg_data_base = envp_array_base + envp_array_size; + Addr env_data_base = arg_data_base + arg_data_size; + + // write contents to stack + uint64_t argc = argv.size(); + if (intSize == 8) + argc = htog((uint64_t)argc); + else if (intSize == 4) + argc = htog((uint32_t)argc); + else + panic("Unknown int size"); + + initVirtMem->writeBlob(stack_min, (uint8_t*)&argc, intSize); + + copyStringArray32(argv, argv_array_base, arg_data_base, initVirtMem); + copyStringArray32(envp, envp_array_base, env_data_base, initVirtMem); + + /* + //uint8_t insns[] = {0xe5, 0x9f, 0x00, 0x08, 0xe1, 0xa0, 0xf0, 0x0e}; + uint8_t insns[] = {0x08, 0x00, 0x9f, 0xe5, 0x0e, 0xf0, 0xa0, 0xe1}; + + initVirtMem->writeBlob(0xffff0fe0, insns, 8); + */ + + threadContexts[0]->setIntReg(ArgumentReg1, argc); + threadContexts[0]->setIntReg(ArgumentReg2, argv_array_base); + threadContexts[0]->setIntReg(StackPointerReg, stack_min); + + Addr prog_entry = objFile->entryPoint(); + threadContexts[0]->setPC(prog_entry); + threadContexts[0]->setNextPC(prog_entry + sizeof(MachInst)); +} + diff --git a/src/arch/arm/process.hh b/src/arch/arm/process.hh new file mode 100644 index 000000000..b97f4b0d2 --- /dev/null +++ b/src/arch/arm/process.hh @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2007-2008 The Florida State University + * 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: Stephen Hines + */ + +#ifndef __ARM_PROCESS_HH__ +#define __ARM_PROCESS_HH__ + +#include <string> +#include <vector> +#include "sim/process.hh" + +class LiveProcess; +class ObjectFile; +class System; + +class ArmLiveProcess : public LiveProcess +{ + protected: + ArmLiveProcess(LiveProcessParams * params, ObjectFile *objFile); + + void startup(); + + void copyStringArray32(std::vector<std::string> &strings, + Addr array_ptr, Addr data_ptr, + TranslatingPort* memPort); + + public: + void argsInit(int intSize, int pageSize); + +}; + +#endif // __ARM_PROCESS_HH__ + diff --git a/src/arch/arm/regfile.hh b/src/arch/arm/regfile.hh new file mode 100644 index 000000000..91cc67be0 --- /dev/null +++ b/src/arch/arm/regfile.hh @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2007-2008 The Florida State University + * 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: Stephen Hines + */ + +#ifndef __ARCH_ARM_REGFILE_HH__ +#define __ARCH_ARM_REGFILE_HH__ + +#include "arch/arm/regfile/regfile.hh" + +#endif diff --git a/src/arch/arm/regfile/float_regfile.hh b/src/arch/arm/regfile/float_regfile.hh new file mode 100644 index 000000000..757f5f0df --- /dev/null +++ b/src/arch/arm/regfile/float_regfile.hh @@ -0,0 +1,181 @@ +/* + * Copyright (c) 2007-2008 The Florida State University + * 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: Stephen Hines + */ + +#ifndef __ARCH_ARM_REGFILE_FLOAT_REGFILE_HH__ +#define __ARCH_ARM_REGFILE_FLOAT_REGFILE_HH__ + +#include "arch/arm/types.hh" +#include "arch/arm/isa_traits.hh" +#include "base/misc.hh" +#include "base/bitfield.hh" +#include "sim/faults.hh" +#include "sim/serialize.hh" + +#include <string> + +class Checkpoint; + +namespace ArmISA +{ + static inline std::string getFloatRegName(RegIndex) + { + return ""; + } + + const uint32_t ARM32_QNAN = 0x7fbfffff; + const uint64_t ARM64_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: + union { + FloatRegBits qregs[NumFloatRegs]; + FloatRegVal regs[NumFloatRegs]; + }; + + public: + + void clear() + { + bzero(regs, sizeof(regs)); + regs[8] = 0.0; + regs[9] = 1.0; + regs[10] = 2.0; + regs[11] = 3.0; + regs[12] = 4.0; + regs[13] = 5.0; + regs[14] = 0.5; + regs[15] = 10.0; + } + + FloatRegVal readReg(int floatReg, int width) + { + return regs[floatReg]; + } + + FloatRegBits readRegBits(int floatReg, int width) + { + //return qregs[floatReg]; + switch(width) + { + case SingleWidth: + { + union { + float f; + uint32_t i; + } s; + s.f = (float) regs[floatReg]; + return s.i; + } + case DoubleWidth: + { + uint64_t tmp = (qregs[floatReg]<<32|qregs[floatReg]>>32); + return tmp; + } + default: + panic("Attempted to read a %d bit floating point " + "register!", width); + + } + } + + Fault setReg(int floatReg, const FloatRegVal &val, int width) + { + if (floatReg > 7) + panic("Writing to a hard-wired FP register"); + regs[floatReg] = val; + return NoFault; + } + + Fault setRegBits(int floatReg, const FloatRegBits &val, int width) + { + if (floatReg > 7) + panic("Writing to a hard-wired FP register"); + switch(width) + { + case DoubleWidth: + { + uint64_t tmp = (val << 32 | val >> 32); + qregs[floatReg] = tmp; + return NoFault; + } + case SingleWidth: + default: + panic("Attempted to write a %d bit floating point " + "register!", width); + } + } + + void serialize(std::ostream &os) + { + SERIALIZE_ARRAY(regs, NumFloatRegs); + } + + void unserialize(Checkpoint *cp, const std::string §ion) + { + UNSERIALIZE_ARRAY(regs, NumFloatRegs); + } + }; + +} // namespace ArmISA + +#endif diff --git a/src/arch/arm/regfile/int_regfile.hh b/src/arch/arm/regfile/int_regfile.hh new file mode 100644 index 000000000..938e68816 --- /dev/null +++ b/src/arch/arm/regfile/int_regfile.hh @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2007-2008 The Florida State University + * 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: Stephen Hines + */ + +#ifndef __ARCH_ARM_REGFILE_INT_REGFILE_HH__ +#define __ARCH_ARM_REGFILE_INT_REGFILE_HH__ + +#include "arch/arm/isa_traits.hh" +#include "arch/arm/types.hh" +#include "base/misc.hh" +#include "sim/faults.hh" +#include "sim/serialize.hh" + +class Checkpoint; +class ThreadContext; + +namespace ArmISA +{ + static inline std::string getIntRegName(RegIndex) + { + return ""; + } + + enum MiscIntRegNums { + zero_reg = NumIntArchRegs, + addr_reg, + + rhi, + rlo, + + r8_fiq, /* FIQ mode register bank */ + r9_fiq, + r10_fiq, + r11_fiq, + r12_fiq, + + r13_fiq, /* FIQ mode SP and LR */ + r14_fiq, + + r13_irq, /* IRQ mode SP and LR */ + r14_irq, + + r13_svc, /* SVC mode SP and LR */ + r14_svc, + + r13_undef, /* UNDEF mode SP and LR */ + r14_undef, + + r13_abt, /* ABT mode SP and LR */ + r14_abt + }; + + class IntRegFile + { + protected: + IntReg regs[NumIntRegs]; + + public: + IntReg readReg(int intReg) + { + return regs[intReg]; + } + + void clear() + { + bzero(regs, sizeof(regs)); + } + + Fault setReg(int intReg, const IntReg &val) + { + regs[intReg] = val; + return NoFault; + } + + void serialize(std::ostream &os) + { + SERIALIZE_ARRAY(regs, NumIntRegs); + } + + void unserialize(Checkpoint *cp, const std::string §ion) + { + UNSERIALIZE_ARRAY(regs, NumIntRegs); + } + }; + +} // namespace ArmISA + +#endif diff --git a/src/arch/arm/regfile/misc_regfile.hh b/src/arch/arm/regfile/misc_regfile.hh new file mode 100644 index 000000000..f8301bed2 --- /dev/null +++ b/src/arch/arm/regfile/misc_regfile.hh @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2007-2008 The Florida State University + * 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: Stephen Hines + */ + +#ifndef __ARCH_ARM_REGFILE_MISC_REGFILE_HH__ +#define __ARCH_ARM_REGFILE_MISC_REGFILE_HH__ + +#include "arch/arm/types.hh" +#include "sim/faults.hh" + +class ThreadContext; + +namespace ArmISA +{ + static inline std::string getMiscRegName(RegIndex) + { + return ""; + } + + //Coprocessor 0 Register Names + enum MiscRegTags { + // Status Registers for the ARM + // + // CPSR Layout + // 31302928 ... 7 6 5 4 3 2 1 0 + // N Z C V ... I F T { MODE } + CPSR = 0, + SPSR_FIQ, + SPSR_IRQ, + SPSR_SVC, + SPSR_UND, + SPSR_ABT, + FPSR + }; + + class MiscRegFile { + + protected: + MiscReg miscRegFile[NumMiscRegs]; + + public: + void clear() + { + // Unknown startup state in misc register file currently + } + + void copyMiscRegs(ThreadContext *tc); + + MiscReg readRegNoEffect(int misc_reg) + { + return miscRegFile[misc_reg]; + } + + MiscReg readReg(int misc_reg, ThreadContext *tc) + { + return miscRegFile[misc_reg]; + } + + void setRegNoEffect(int misc_reg, const MiscReg &val) + { + miscRegFile[misc_reg] = val; + } + + void setReg(int misc_reg, const MiscReg &val, + ThreadContext *tc) + { + miscRegFile[misc_reg] = val; + } + + friend class RegFile; + }; +} // namespace ArmISA + +#endif diff --git a/src/arch/arm/regfile/regfile.cc b/src/arch/arm/regfile/regfile.cc new file mode 100644 index 000000000..5de0b3076 --- /dev/null +++ b/src/arch/arm/regfile/regfile.cc @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2007-2008 The Florida State University + * 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: Stephen Hines + */ + +#include "arch/arm/regfile/regfile.hh" +#include "sim/serialize.hh" + +using namespace std; + +namespace ArmISA +{ + +void +copyRegs(ThreadContext *src, ThreadContext *dest) +{ + panic("Copy Regs Not Implemented Yet\n"); +} + +void +copyMiscRegs(ThreadContext *src, ThreadContext *dest) +{ + panic("Copy Misc. Regs Not Implemented Yet\n"); +} + +void +MiscRegFile::copyMiscRegs(ThreadContext *tc) +{ + panic("Copy Misc. Regs Not Implemented Yet\n"); +} + +void +RegFile::serialize(std::ostream &os) +{ + intRegFile.serialize(os); + //SERIALIZE_ARRAY(floatRegFile, NumFloatRegs); + //SERIALZE_ARRAY(miscRegFile); + //SERIALIZE_SCALAR(miscRegs.fpcr); + //SERIALIZE_SCALAR(miscRegs.lock_flag); + //SERIALIZE_SCALAR(miscRegs.lock_addr); + //SERIALIZE_SCALAR(pc); + SERIALIZE_SCALAR(npc); + SERIALIZE_SCALAR(nnpc); +} + +void +RegFile::unserialize(Checkpoint *cp, const std::string §ion) +{ + intRegFile.unserialize(cp, section); + //UNSERIALIZE_ARRAY(floatRegFile); + //UNSERIALZE_ARRAY(miscRegFile); + //UNSERIALIZE_SCALAR(miscRegs.fpcr); + //UNSERIALIZE_SCALAR(miscRegs.lock_flag); + //UNSERIALIZE_SCALAR(miscRegs.lock_addr); + //UNSERIALIZE_SCALAR(pc); + UNSERIALIZE_SCALAR(npc); + UNSERIALIZE_SCALAR(nnpc); + +} + +} // namespace ArmISA diff --git a/src/arch/arm/regfile/regfile.hh b/src/arch/arm/regfile/regfile.hh new file mode 100644 index 000000000..86799f18d --- /dev/null +++ b/src/arch/arm/regfile/regfile.hh @@ -0,0 +1,203 @@ +/* + * Copyright (c) 2007-2008 The Florida State University + * 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: Stephen Hines + */ + +#ifndef __ARCH_ARM_REGFILE_REGFILE_HH__ +#define __ARCH_ARM_REGFILE_REGFILE_HH__ + +#include "arch/arm/types.hh" +#include "arch/arm/regfile/int_regfile.hh" +#include "arch/arm/regfile/float_regfile.hh" +#include "arch/arm/regfile/misc_regfile.hh" +#include "sim/faults.hh" + +class Checkpoint; +class ThreadContext; + +namespace ArmISA +{ + class RegFile { + protected: + IntRegFile intRegFile; // (signed) integer register file + FloatRegFile floatRegFile; // floating point register file + MiscRegFile miscRegFile; // control register file + + public: + + void clear() + { + intRegFile.clear(); + floatRegFile.clear(); + miscRegFile.clear(); + } + + MiscReg readMiscRegNoEffect(int miscReg) + { + return miscRegFile.readRegNoEffect(miscReg); + } + + MiscReg readMiscReg(int miscReg, ThreadContext *tc) + { + return miscRegFile.readReg(miscReg, tc); + } + + void setMiscRegNoEffect(int miscReg, const MiscReg &val) + { + miscRegFile.setRegNoEffect(miscReg, val); + } + + void setMiscReg(int miscReg, const MiscReg &val, + ThreadContext * tc) + { + miscRegFile.setReg(miscReg, val, tc); + } + + FloatRegVal readFloatReg(int floatReg) + { + return floatRegFile.readReg(floatReg,SingleWidth); + } + + FloatRegVal readFloatReg(int floatReg, int width) + { + return floatRegFile.readReg(floatReg,width); + } + + FloatRegBits readFloatRegBits(int floatReg) + { + return floatRegFile.readRegBits(floatReg,SingleWidth); + } + + FloatRegBits readFloatRegBits(int floatReg, int width) + { + return floatRegFile.readRegBits(floatReg,width); + } + + void setFloatReg(int floatReg, const FloatRegVal &val) + { + floatRegFile.setReg(floatReg, val, SingleWidth); + } + + void setFloatReg(int floatReg, const FloatRegVal &val, int width) + { + floatRegFile.setReg(floatReg, val, width); + } + + void setFloatRegBits(int floatReg, const FloatRegBits &val) + { + floatRegFile.setRegBits(floatReg, val, SingleWidth); + } + + void setFloatRegBits(int floatReg, const FloatRegBits &val, int width) + { + floatRegFile.setRegBits(floatReg, val, width); + } + + IntReg readIntReg(int intReg) + { + // In the Arm, reading from the PC for a generic instruction yields + // the current PC + 8, due to previous pipeline implementations + if (intReg == PCReg) + return intRegFile.readReg(intReg) + 8; + //return pc + 8; + else + return intRegFile.readReg(intReg); + } + + void setIntReg(int intReg, const IntReg &val) + { + // Have to trap writes to PC so that they update NPC instead + if (intReg == PCReg) + setNextPC(val); + else + intRegFile.setReg(intReg, val); + } + protected: + + Addr pc; // program counter + Addr npc; // next-cycle program counter + Addr nnpc; // next-next-cycle program counter + + public: + Addr readPC() + { + return intRegFile.readReg(PCReg); + //return pc; + } + + void setPC(Addr val) + { + intRegFile.setReg(PCReg, val); + //pc = val; + } + + Addr readNextPC() + { + return npc; + } + + void setNextPC(Addr val) + { + npc = val; + } + + Addr readNextNPC() + { + return npc + sizeof(MachInst); + } + + void setNextNPC(Addr val) + { + //nnpc = val; + } + + void serialize(std::ostream &os); + void unserialize(Checkpoint *cp, const std::string §ion); + + void changeContext(RegContextParam param, RegContextVal val) + { + } + }; + + static inline int flattenIntIndex(ThreadContext * tc, int reg) + { + return reg; + } + + static inline int flattenFloatIndex(ThreadContext * tc, int reg) + { + return reg; + } + + void copyRegs(ThreadContext *src, ThreadContext *dest); + + void copyMiscRegs(ThreadContext *src, ThreadContext *dest); + +} // namespace ArmISA + +#endif diff --git a/src/arch/arm/remote_gdb.hh b/src/arch/arm/remote_gdb.hh new file mode 100644 index 000000000..ec8098c7a --- /dev/null +++ b/src/arch/arm/remote_gdb.hh @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2002-2005 The Regents of The University of Michigan + * Copyright (c) 2007-2008 The Florida State University + * 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 + * Stephen Hines + */ + +#ifndef __ARCH_ARM_REMOTE_GDB_HH__ +#define __ARCH_ARM_REMOTE_GDB_HH__ + +#include "base/remote_gdb.hh" + +namespace ArmISA +{ + class RemoteGDB : public BaseRemoteGDB + { + public: + //These needs to be written to suit ARM + + RemoteGDB(System *system, ThreadContext *context) + : BaseRemoteGDB(system, context, 1) + {} + + bool acc(Addr, size_t) + { panic("acc not implemented for ARM!"); } + + void getregs() + { panic("getregs not implemented for ARM!"); } + + void setregs() + { panic("setregs not implemented for ARM!"); } + + void clearSingleStep() + { panic("clearSingleStep not implemented for ARM!"); } + + void setSingleStep() + { panic("setSingleStep not implemented for ARM!"); } + }; +} + +#endif /* __ARCH_ARM_REMOTE_GDB_H__ */ diff --git a/src/arch/arm/stacktrace.hh b/src/arch/arm/stacktrace.hh new file mode 100644 index 000000000..3f9c91096 --- /dev/null +++ b/src/arch/arm/stacktrace.hh @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2005 The Regents of The University of Michigan + * Copyright (c) 2007-2008 The Florida State University + * 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: Ali Saidi + * Stephen Hines + */ + +#ifndef __ARCH_ARM_STACKTRACE_HH__ +#define __ARCH_ARM_STACKTRACE_HH__ + +#include "base/trace.hh" +#include "cpu/static_inst.hh" + +class ThreadContext; +class StackTrace; + +namespace ArmISA +{ + +class ProcessInfo +{ + private: + ThreadContext *tc; + + int thread_info_size; + int task_struct_size; + int task_off; + int pid_off; + int name_off; + + public: + ProcessInfo(ThreadContext *_tc); + + Addr task(Addr ksp) const; + int pid(Addr ksp) const; + std::string name(Addr ksp) const; +}; + +class StackTrace +{ + protected: + typedef TheISA::MachInst MachInst; + private: + ThreadContext *tc; + std::vector<Addr> stack; + + private: + bool isEntry(Addr addr); + bool decodePrologue(Addr sp, Addr callpc, Addr func, int &size, Addr &ra); + bool decodeSave(MachInst inst, int ®, int &disp); + bool decodeStack(MachInst inst, int &disp); + + void trace(ThreadContext *tc, bool is_call); + + public: + StackTrace(); + StackTrace(ThreadContext *tc, StaticInstPtr inst); + ~StackTrace(); + + void clear() + { + tc = 0; + stack.clear(); + } + + bool valid() const { return tc != NULL; } + bool trace(ThreadContext *tc, StaticInstPtr inst); + + public: + const std::vector<Addr> &getstack() const { return stack; } + + static const int user = 1; + static const int console = 2; + static const int unknown = 3; + +#if TRACING_ON + private: + void dump(); + + public: + void dprintf() { if (DTRACE(Stack)) dump(); } +#else + public: + void dprintf() {} +#endif +}; + +inline bool +StackTrace::trace(ThreadContext *tc, StaticInstPtr inst) +{ + if (!inst->isCall() && !inst->isReturn()) + return false; + + if (valid()) + clear(); + + trace(tc, !inst->isReturn()); + return true; +} + +} + +#endif // __ARCH_ARM_STACKTRACE_HH__ diff --git a/src/arch/arm/syscallreturn.hh b/src/arch/arm/syscallreturn.hh new file mode 100644 index 000000000..ad46c2232 --- /dev/null +++ b/src/arch/arm/syscallreturn.hh @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2003-2005 The Regents of The University of Michigan + * Copyright (c) 2007-2008 The Florida State University + * 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 + * Stephen Hines + */ + +#ifndef __ARCH_ARM_SYSCALLRETURN_HH__ +#define __ARCH_ARM_SYSCALLRETURN_HH__ + +#include "sim/syscallreturn.hh" +#include "cpu/thread_context.hh" + +namespace ArmISA +{ + static inline void setSyscallReturn(SyscallReturn return_value, + ThreadContext *tc) + { + if (return_value.successful()) { + // no error + //regs->setIntReg(SyscallSuccessReg, 0); + tc->setIntReg(ReturnValueReg, return_value.value()); + } else { + // got an error, return details + //regs->setIntReg(SyscallSuccessReg, (IntReg) -1); + tc->setIntReg(ReturnValueReg, return_value.value()); + } + } +} + +#endif diff --git a/src/arch/arm/tlb.cc b/src/arch/arm/tlb.cc new file mode 100644 index 000000000..d0cc57a1d --- /dev/null +++ b/src/arch/arm/tlb.cc @@ -0,0 +1,364 @@ +/* + * Copyright (c) 2001-2005 The Regents of The University of Michigan + * Copyright (c) 2007 MIPS Technologies, Inc. + * Copyright (c) 2007-2008 The Florida State University + * 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 + * Stephen Hines + */ + +#include <string> +#include <vector> + +#include "arch/arm/pagetable.hh" +#include "arch/arm/tlb.hh" +#include "arch/arm/faults.hh" +#include "arch/arm/utility.hh" +#include "base/inifile.hh" +#include "base/str.hh" +#include "base/trace.hh" +#include "cpu/thread_context.hh" +#include "sim/process.hh" +#include "mem/page_table.hh" +#include "params/ArmDTB.hh" +#include "params/ArmITB.hh" +#include "params/ArmTLB.hh" +#include "params/ArmUTB.hh" + + +using namespace std; +using namespace ArmISA; + +/////////////////////////////////////////////////////////////////////// +// +// ARM TLB +// + +#define MODE2MASK(X) (1 << (X)) + +TLB::TLB(const Params *p) + : BaseTLB(p), size(p->size), nlu(0) +{ + table = new ArmISA::PTE[size]; + memset(table, 0, sizeof(ArmISA::PTE[size])); + smallPages=0; +} + +TLB::~TLB() +{ + if (table) + delete [] table; +} + +// look up an entry in the TLB +ArmISA::PTE * +TLB::lookup(Addr vpn, uint8_t asn) const +{ + // assume not found... + ArmISA::PTE *retval = NULL; + PageTable::const_iterator i = lookupTable.find(vpn); + if (i != lookupTable.end()) { + while (i->first == vpn) { + int index = i->second; + ArmISA::PTE *pte = &table[index]; + + /* 1KB TLB Lookup code - from ARM ARM Volume III - Rev. 2.50 */ + Addr Mask = pte->Mask; + Addr InvMask = ~Mask; + Addr VPN = pte->VPN; + // warn("Valid: %d - %d\n",pte->V0,pte->V1); + if(((vpn & InvMask) == (VPN & InvMask)) && (pte->G || (asn == pte->asid))) + { // We have a VPN + ASID Match + retval = pte; + break; + } + ++i; + } + } + + DPRINTF(TLB, "lookup %#x, asn %#x -> %s ppn %#x\n", vpn, (int)asn, + retval ? "hit" : "miss", retval ? retval->PFN1 : 0); + return retval; +} + +ArmISA::PTE* TLB::getEntry(unsigned Index) const +{ + // Make sure that Index is valid + assert(Index<size); + return &table[Index]; +} + +int TLB::probeEntry(Addr vpn,uint8_t asn) const +{ + // assume not found... + ArmISA::PTE *retval = NULL; + int Ind=-1; + PageTable::const_iterator i = lookupTable.find(vpn); + if (i != lookupTable.end()) { + while (i->first == vpn) { + int index = i->second; + ArmISA::PTE *pte = &table[index]; + + /* 1KB TLB Lookup code - from ARM ARM Volume III - Rev. 2.50 */ + Addr Mask = pte->Mask; + Addr InvMask = ~Mask; + Addr VPN = pte->VPN; + if(((vpn & InvMask) == (VPN & InvMask)) && (pte->G || (asn == pte->asid))) + { // We have a VPN + ASID Match + retval = pte; + Ind = index; + break; + } + + ++i; + } + } + DPRINTF(Arm,"VPN: %x, asid: %d, Result of TLBP: %d\n",vpn,asn,Ind); + return Ind; +} +Fault inline +TLB::checkCacheability(RequestPtr &req) +{ + Addr VAddrUncacheable = 0xA0000000; + // In ARM, cacheability is controlled by certain bits of the virtual address + // or by the TLB entry + if((req->getVaddr() & VAddrUncacheable) == VAddrUncacheable) { + // mark request as uncacheable + req->setFlags(req->getFlags() | UNCACHEABLE); + } + return NoFault; +} +void TLB::insertAt(ArmISA::PTE &pte, unsigned Index, int _smallPages) +{ + smallPages=_smallPages; + if(Index > size){ + warn("Attempted to write at index (%d) beyond TLB size (%d)",Index,size); + } else { + // Update TLB + DPRINTF(TLB,"TLB[%d]: %x %x %x %x\n",Index,pte.Mask<<11,((pte.VPN << 11) | pte.asid),((pte.PFN0 <<6) | (pte.C0 << 3) | (pte.D0 << 2) | (pte.V0 <<1) | pte.G), + ((pte.PFN1 <<6) | (pte.C1 << 3) | (pte.D1 << 2) | (pte.V1 <<1) | pte.G)); + if(table[Index].V0 == true || table[Index].V1 == true){ // Previous entry is valid + PageTable::iterator i = lookupTable.find(table[Index].VPN); + lookupTable.erase(i); + } + table[Index]=pte; + // Update fast lookup table + lookupTable.insert(make_pair(table[Index].VPN, Index)); + // int TestIndex=probeEntry(pte.VPN,pte.asid); + // warn("Inserted at: %d, Found at: %d (%x)\n",Index,TestIndex,pte.Mask); + } + +} + +// insert a new TLB entry +void +TLB::insert(Addr addr, ArmISA::PTE &pte) +{ + fatal("TLB Insert not yet implemented\n"); +} + +void +TLB::flushAll() +{ + DPRINTF(TLB, "flushAll\n"); + memset(table, 0, sizeof(ArmISA::PTE[size])); + lookupTable.clear(); + nlu = 0; +} + +void +TLB::serialize(ostream &os) +{ + SERIALIZE_SCALAR(size); + SERIALIZE_SCALAR(nlu); + + for (int i = 0; i < size; i++) { + nameOut(os, csprintf("%s.PTE%d", name(), i)); + table[i].serialize(os); + } +} + +void +TLB::unserialize(Checkpoint *cp, const string §ion) +{ + UNSERIALIZE_SCALAR(size); + UNSERIALIZE_SCALAR(nlu); + + for (int i = 0; i < size; i++) { + table[i].unserialize(cp, csprintf("%s.PTE%d", section, i)); + if (table[i].V0 || table[i].V1) { + lookupTable.insert(make_pair(table[i].VPN, i)); + } + } +} + +void +TLB::regStats() +{ + read_hits + .name(name() + ".read_hits") + .desc("DTB read hits") + ; + + read_misses + .name(name() + ".read_misses") + .desc("DTB read misses") + ; + + + read_accesses + .name(name() + ".read_accesses") + .desc("DTB read accesses") + ; + + write_hits + .name(name() + ".write_hits") + .desc("DTB write hits") + ; + + write_misses + .name(name() + ".write_misses") + .desc("DTB write misses") + ; + + + write_accesses + .name(name() + ".write_accesses") + .desc("DTB write accesses") + ; + + hits + .name(name() + ".hits") + .desc("DTB hits") + ; + + misses + .name(name() + ".misses") + .desc("DTB misses") + ; + + invalids + .name(name() + ".invalids") + .desc("DTB access violations") + ; + + accesses + .name(name() + ".accesses") + .desc("DTB accesses") + ; + + hits = read_hits + write_hits; + misses = read_misses + write_misses; + accesses = read_accesses + write_accesses; +} + +Fault +ITB::translate(RequestPtr &req, ThreadContext *tc) +{ +#if !FULL_SYSTEM + Process * p = tc->getProcessPtr(); + + Fault fault = p->pTable->translate(req); + if(fault != NoFault) + return fault; + + return NoFault; +#else + fatal("ITB translate not yet implemented\n"); +#endif +} + +Fault +DTB::translate(RequestPtr &req, ThreadContext *tc, bool write) +{ +#if !FULL_SYSTEM + Process * p = tc->getProcessPtr(); + + Fault fault = p->pTable->translate(req); + if(fault != NoFault) + return fault; + + return NoFault; +#else + fatal("DTB translate not yet implemented\n"); +#endif +} + +/////////////////////////////////////////////////////////////////////// +// +// Arm ITB +// +ITB::ITB(const Params *p) + : TLB(p) +{} + + +/////////////////////////////////////////////////////////////////////// +// +// Arm DTB +// +DTB::DTB(const Params *p) + : TLB(p) +{} + +/////////////////////////////////////////////////////////////////////// +// +// Arm UTB +// +UTB::UTB(const Params *p) + : ITB(p), DTB(p) +{} + +ArmISA::PTE & +TLB::index(bool advance) +{ + ArmISA::PTE *pte = &table[nlu]; + + if (advance) + nextnlu(); + + return *pte; +} + +ArmISA::ITB * +ArmITBParams::create() +{ + return new ArmISA::ITB(this); +} + +ArmISA::DTB * +ArmDTBParams::create() +{ + return new ArmISA::DTB(this); +} + +ArmISA::UTB * +ArmUTBParams::create() +{ + return new ArmISA::UTB(this); +} diff --git a/src/arch/arm/tlb.hh b/src/arch/arm/tlb.hh new file mode 100644 index 000000000..59fe1a60d --- /dev/null +++ b/src/arch/arm/tlb.hh @@ -0,0 +1,164 @@ +/* + * Copyright (c) 2001-2005 The Regents of The University of Michigan + * Copyright (c) 2007 MIPS Technologies, Inc. + * Copyright (c) 2007-2008 The Florida State University + * 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 + * Stephen Hines + */ + +#ifndef __ARCH_ARM_TLB_HH__ +#define __ARCH_ARM_TLB_HH__ + +#include <map> + +#include "arch/arm/isa_traits.hh" +#include "arch/arm/utility.hh" +#include "arch/arm/vtophys.hh" +#include "arch/arm/pagetable.hh" +#include "base/statistics.hh" +#include "mem/request.hh" +#include "params/ArmDTB.hh" +#include "params/ArmITB.hh" +#include "sim/faults.hh" +#include "sim/tlb.hh" + +class ThreadContext; + +/* ARM does not distinguish between a DTLB and an ITLB -> unified TLB + However, to maintain compatibility with other architectures, we'll + simply create an ITLB and DTLB that will point to the real TLB */ +namespace ArmISA { + +// WARN: This particular TLB entry is not necessarily conformed to ARM ISA +struct TlbEntry +{ + Addr _pageStart; + TlbEntry() {} + TlbEntry(Addr asn, Addr vaddr, Addr paddr) : _pageStart(paddr) {} + + Addr pageStart() + { + return _pageStart; + } + + void serialize(std::ostream &os) + { + SERIALIZE_SCALAR(_pageStart); + } + + void unserialize(Checkpoint *cp, const std::string §ion) + { + UNSERIALIZE_SCALAR(_pageStart); + } + +}; + +class TLB : public BaseTLB +{ + protected: + typedef std::multimap<Addr, int> PageTable; + PageTable lookupTable; // Quick lookup into page table + + ArmISA::PTE *table; // the Page Table + int size; // TLB Size + int nlu; // not last used entry (for replacement) + + void nextnlu() { if (++nlu >= size) nlu = 0; } + ArmISA::PTE *lookup(Addr vpn, uint8_t asn) const; + + mutable Stats::Scalar<> read_hits; + mutable Stats::Scalar<> read_misses; + mutable Stats::Scalar<> read_acv; + mutable Stats::Scalar<> read_accesses; + mutable Stats::Scalar<> write_hits; + mutable Stats::Scalar<> write_misses; + mutable Stats::Scalar<> write_acv; + mutable Stats::Scalar<> write_accesses; + Stats::Formula hits; + Stats::Formula misses; + Stats::Formula invalids; + Stats::Formula accesses; + + public: + typedef ArmTLBParams Params; + TLB(const Params *p); + + int probeEntry(Addr vpn,uint8_t) const; + ArmISA::PTE *getEntry(unsigned) const; + virtual ~TLB(); + int smallPages; + int getsize() const { return size; } + + ArmISA::PTE &index(bool advance = true); + void insert(Addr vaddr, ArmISA::PTE &pte); + void insertAt(ArmISA::PTE &pte, unsigned Index, int _smallPages); + void flushAll(); + void demapPage(Addr vaddr, uint64_t asn) + { + panic("demapPage unimplemented.\n"); + } + + // static helper functions... really + static bool validVirtualAddress(Addr vaddr); + + static Fault checkCacheability(RequestPtr &req); + + // Checkpointing + void serialize(std::ostream &os); + void unserialize(Checkpoint *cp, const std::string §ion); + + void regStats(); +}; + +class ITB : public TLB { + public: + typedef ArmTLBParams Params; + ITB(const Params *p); + + Fault translate(RequestPtr &req, ThreadContext *tc); +}; + +class DTB : public TLB { + public: + typedef ArmTLBParams Params; + DTB(const Params *p); + + Fault translate(RequestPtr &req, ThreadContext *tc, bool write = false); +}; + +class UTB : public ITB, public DTB { + public: + typedef ArmTLBParams Params; + UTB(const Params *p); + +}; + +} + +#endif // __ARCH_ARM_TLB_HH__ diff --git a/src/arch/arm/types.hh b/src/arch/arm/types.hh new file mode 100644 index 000000000..0a8d5d696 --- /dev/null +++ b/src/arch/arm/types.hh @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2007-2008 The Florida State University + * 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: Stephen Hines + */ + +#ifndef __ARCH_ARM_TYPES_HH__ +#define __ARCH_ARM_TYPES_HH__ + +#include "sim/host.hh" + +namespace ArmISA +{ + typedef uint32_t MachInst; + typedef uint64_t ExtMachInst; + typedef uint8_t RegIndex; + + typedef uint64_t IntReg; + typedef uint64_t LargestRead; + // Need to use 64 bits to make sure that read requests get handled properly + + // floating point register file entry type + typedef uint32_t FloatReg32; + typedef uint64_t FloatReg64; + typedef uint64_t FloatRegBits; + + typedef double FloatRegVal; + typedef double FloatReg; + + // cop-0/cop-1 system control register + typedef uint64_t MiscReg; + + typedef union { + IntReg intreg; + FloatReg fpreg; + MiscReg ctrlreg; + } AnyReg; + + typedef int RegContextParam; + typedef int RegContextVal; + + //used in FP convert & round function + enum ConvertType{ + SINGLE_TO_DOUBLE, + SINGLE_TO_WORD, + SINGLE_TO_LONG, + + DOUBLE_TO_SINGLE, + DOUBLE_TO_WORD, + DOUBLE_TO_LONG, + + LONG_TO_SINGLE, + LONG_TO_DOUBLE, + LONG_TO_WORD, + LONG_TO_PS, + + WORD_TO_SINGLE, + WORD_TO_DOUBLE, + WORD_TO_LONG, + WORD_TO_PS, + + PL_TO_SINGLE, + PU_TO_SINGLE + }; + + //used in FP convert & round function + enum RoundMode{ + RND_ZERO, + RND_DOWN, + RND_UP, + RND_NEAREST + }; + + enum OperatingMode { + MODE_USER = 16, + MODE_FIQ = 17, + MODE_IRQ = 18, + MODE_SVC = 19, + MODE_ABORT = 23, + MODE_UNDEFINED = 27, + MODE_SYSTEM = 31 + }; + + struct CoreSpecific { + // Empty for now on the ARM + }; + +} // namespace ArmISA + +#endif diff --git a/src/arch/arm/utility.cc b/src/arch/arm/utility.cc new file mode 100644 index 000000000..83d741297 --- /dev/null +++ b/src/arch/arm/utility.cc @@ -0,0 +1,201 @@ +/* + * Copyright (c) 2003-2006 The Regents of The University of Michigan + * Copyright (c) 2007-2008 The Florida State University + * 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 + * Stephen Hines + */ + +#include "arch/arm/regfile.hh" +#include "arch/arm/utility.hh" +#include "base/misc.hh" +#include "base/bitfield.hh" + +using namespace ArmISA; + +uint64_t +ArmISA::fpConvert(ConvertType cvt_type, double fp_val) +{ + + switch (cvt_type) + { + case SINGLE_TO_DOUBLE: + { + double sdouble_val = fp_val; + void *sdouble_ptr = &sdouble_val; + uint64_t sdp_bits = *(uint64_t *) sdouble_ptr; + return sdp_bits; + } + + case SINGLE_TO_WORD: + { + int32_t sword_val = (int32_t) fp_val; + void *sword_ptr = &sword_val; + uint64_t sword_bits= *(uint32_t *) sword_ptr; + return sword_bits; + } + + case WORD_TO_SINGLE: + { + float wfloat_val = fp_val; + void *wfloat_ptr = &wfloat_val; + uint64_t wfloat_bits = *(uint32_t *) wfloat_ptr; + return wfloat_bits; + } + + case WORD_TO_DOUBLE: + { + double wdouble_val = fp_val; + void *wdouble_ptr = &wdouble_val; + uint64_t wdp_bits = *(uint64_t *) wdouble_ptr; + return wdp_bits; + } + + default: + panic("Invalid Floating Point Conversion Type (%d). See \"types.hh\" for List of Conversions\n",cvt_type); + return 0; + } +} + +double +ArmISA::roundFP(double val, int digits) +{ + double digit_offset = pow(10.0,digits); + val = val * digit_offset; + val = val + 0.5; + val = floor(val); + val = val / digit_offset; + return val; +} + +double +ArmISA::truncFP(double val) +{ + int trunc_val = (int) val; + return (double) trunc_val; +} + +bool +ArmISA::getCondCode(uint32_t fcsr, int cc_idx) +{ + int shift = (cc_idx == 0) ? 23 : cc_idx + 24; + bool cc_val = (fcsr >> shift) & 0x00000001; + return cc_val; +} + +uint32_t +ArmISA::genCCVector(uint32_t fcsr, int cc_num, uint32_t cc_val) +{ + int cc_idx = (cc_num == 0) ? 23 : cc_num + 24; + + fcsr = bits(fcsr, 31, cc_idx + 1) << (cc_idx + 1) | + cc_val << cc_idx | + bits(fcsr, cc_idx - 1, 0); + + return fcsr; +} + +uint32_t +ArmISA::genInvalidVector(uint32_t fcsr_bits) +{ + //Set FCSR invalid in "flag" field + int invalid_offset = Invalid + Flag_Field; + fcsr_bits = fcsr_bits | (1 << invalid_offset); + + //Set FCSR invalid in "cause" flag + int cause_offset = Invalid + Cause_Field; + fcsr_bits = fcsr_bits | (1 << cause_offset); + + return fcsr_bits; +} + +bool +ArmISA::isNan(void *val_ptr, int size) +{ + switch (size) + { + case 32: + { + uint32_t val_bits = *(uint32_t *) val_ptr; + return (bits(val_bits, 30, 23) == 0xFF); + } + + case 64: + { + uint64_t val_bits = *(uint64_t *) val_ptr; + return (bits(val_bits, 62, 52) == 0x7FF); + } + + default: + panic("Type unsupported. Size mismatch\n"); + } +} + + +bool +ArmISA::isQnan(void *val_ptr, int size) +{ + switch (size) + { + case 32: + { + uint32_t val_bits = *(uint32_t *) val_ptr; + return (bits(val_bits, 30, 22) == 0x1FE); + } + + case 64: + { + uint64_t val_bits = *(uint64_t *) val_ptr; + return (bits(val_bits, 62, 51) == 0xFFE); + } + + default: + panic("Type unsupported. Size mismatch\n"); + } +} + +bool +ArmISA::isSnan(void *val_ptr, int size) +{ + switch (size) + { + case 32: + { + uint32_t val_bits = *(uint32_t *) val_ptr; + return (bits(val_bits, 30, 22) == 0x1FF); + } + + case 64: + { + uint64_t val_bits = *(uint64_t *) val_ptr; + return (bits(val_bits, 62, 51) == 0xFFF); + } + + default: + panic("Type unsupported. Size mismatch\n"); + } +} diff --git a/src/arch/arm/utility.hh b/src/arch/arm/utility.hh new file mode 100644 index 000000000..fedf1fa05 --- /dev/null +++ b/src/arch/arm/utility.hh @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2003-2005 The Regents of The University of Michigan + * Copyright (c) 2007-2008 The Florida State University + * 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 + * Stephen Hines + */ + +#ifndef __ARCH_ARM_UTILITY_HH__ +#define __ARCH_ARM_UTILITY_HH__ + +#include "arch/arm/types.hh" +#include "base/misc.hh" +#include "config/full_system.hh" +#include "cpu/thread_context.hh" +#include "sim/host.hh" + +class ThreadContext; + +namespace ArmISA { + + //Floating Point Utility Functions + uint64_t fpConvert(ConvertType cvt_type, double fp_val); + double roundFP(double val, int digits); + double truncFP(double val); + + bool getCondCode(uint32_t fcsr, int cc); + uint32_t genCCVector(uint32_t fcsr, int num, uint32_t cc_val); + uint32_t genInvalidVector(uint32_t fcsr); + + 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); + + // 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 + static inline size_t fetchInstSize() { + return sizeof(MachInst); + } + + static inline MachInst makeRegisterCopy(int dest, int src) { + panic("makeRegisterCopy not implemented"); + return 0; + } + + inline void startupCPU(ThreadContext *tc, int cpuId) + { + tc->activate(0); + } +}; + + +#endif diff --git a/src/arch/arm/vtophys.cc b/src/arch/arm/vtophys.cc new file mode 100644 index 000000000..086c034c8 --- /dev/null +++ b/src/arch/arm/vtophys.cc @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2002-2005 The Regents of The University of Michigan + * Copyright (c) 2007-2008 The Florida State University + * 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: Ali Saidi + * Nathan Binkert + * Stephen Hines + */ + +#include <string> + +#include "arch/arm/vtophys.hh" +#include "base/chunk_generator.hh" +#include "base/trace.hh" +#include "cpu/thread_context.hh" +#include "mem/vport.hh" + +using namespace std; +using namespace ArmISA; + +Addr +ArmISA::vtophys(Addr vaddr) +{ + Addr paddr = 0; + if (ArmISA::IsUSeg(vaddr)) + DPRINTF(VtoPhys, "vtophys: invalid vaddr %#x", vaddr); + else if (ArmISA::IsKSeg0(vaddr)) + paddr = ArmISA::KSeg02Phys(vaddr); + else + panic("vtophys: ptbr is not set on virtual lookup for vaddr %#x", vaddr); + + DPRINTF(VtoPhys, "vtophys(%#x) -> %#x\n", vaddr, paddr); + + return paddr; +} + +Addr +ArmISA::vtophys(ThreadContext *tc, Addr addr) +{ + fatal("VTOPHYS: Unimplemented on ARM\n"); +} + diff --git a/src/arch/arm/vtophys.hh b/src/arch/arm/vtophys.hh new file mode 100644 index 000000000..edd21558f --- /dev/null +++ b/src/arch/arm/vtophys.hh @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2002-2005 The Regents of The University of Michigan + * Copyright (c) 2007-2008 The Florida State University + * 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: Ali Saidi + * Nathan Binkert + * Stephen Hines + */ + +#ifndef __ARCH_ARM_VTOPHYS_H__ +#define __ARCH_ARM_VTOPHYS_H__ + +#include "arch/arm/isa_traits.hh" +#include "arch/arm/utility.hh" + + +class ThreadContext; +class FunctionalPort; + +namespace ArmISA { + inline Addr PteAddr(Addr a) { return (a & PteMask) << PteShift; } + + // User Virtual + inline bool IsUSeg(Addr a) { return USegBase <= a && a <= USegEnd; } + + inline bool IsKSeg0(Addr a) { return KSeg0Base <= a && a <= KSeg0End; } + + inline Addr KSeg02Phys(Addr addr) { return addr & KSeg0Mask; } + + Addr vtophys(Addr vaddr); + Addr vtophys(ThreadContext *tc, Addr vaddr); +}; + +#endif // __ARCH_ARM_VTOPHYS_H__ + |