arm: use condition code registers for ARM ISA

Analogous to ee049bf (for x86).  Requires a bump of the checkpoint version
and corresponding upgrader code to move the condition code register values
to the new register file.
This commit is contained in:
Curtis Dunham 2014-04-29 16:05:02 -05:00
parent 035a82ee2c
commit 4a3f11149d
15 changed files with 184 additions and 87 deletions

85
src/arch/arm/ccregs.hh Normal file
View file

@ -0,0 +1,85 @@
/*
* Copyright (c) 2014 ARM Limited
* All rights reserved
*
* The license below extends only to copyright in the software and shall
* not be construed as granting a license to any other intellectual
* property including but not limited to intellectual property relating
* to a hardware implementation of the functionality of the software
* licensed hereunder. You may use the software subject to the license
* terms below provided that you ensure that this notice is replicated
* unmodified and in its entirety in all distributions of the software,
* modified or unmodified, in source code or in binary form.
*
* 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: Curtis Dunham
*/
#ifndef __ARCH_ARM_CCREGS_HH__
#define __ARCH_ARM_CCREGS_HH__
namespace ArmISA
{
enum ccRegIndex {
CCREG_NZ,
CCREG_C,
CCREG_V,
CCREG_GE,
CCREG_FP,
CCREG_ZERO,
NUM_CCREGS
};
const char * const ccRegName[NUM_CCREGS] = {
"nz",
"c",
"v",
"ge",
"fp",
"zero"
};
enum ConditionCode {
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_UC // 15
};
}
#endif // __ARCH_ARM_CCREGS_HH__

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2010, 2012-2013 ARM Limited
* Copyright (c) 2010, 2012-2014 ARM Limited
* All rights reserved
*
* The license below extends only to copyright in the software and shall
@ -466,10 +466,10 @@ ArmFault::invoke(ThreadContext *tc, StaticInstPtr inst)
SCTLR sctlr = tc->readMiscReg(MISCREG_SCTLR);
SCR scr = tc->readMiscReg(MISCREG_SCR);
CPSR saved_cpsr = tc->readMiscReg(MISCREG_CPSR);
saved_cpsr.nz = tc->readIntReg(INTREG_CONDCODES_NZ);
saved_cpsr.c = tc->readIntReg(INTREG_CONDCODES_C);
saved_cpsr.v = tc->readIntReg(INTREG_CONDCODES_V);
saved_cpsr.ge = tc->readIntReg(INTREG_CONDCODES_GE);
saved_cpsr.nz = tc->readCCReg(CCREG_NZ);
saved_cpsr.c = tc->readCCReg(CCREG_C);
saved_cpsr.v = tc->readCCReg(CCREG_V);
saved_cpsr.ge = tc->readCCReg(CCREG_GE);
Addr curPc M5_VAR_USED = tc->pcState().pc();
ITSTATE it = tc->pcState().itstate();
@ -615,9 +615,9 @@ ArmFault::invoke64(ThreadContext *tc, StaticInstPtr inst)
// Save process state into SPSR_ELx
CPSR cpsr = tc->readMiscReg(MISCREG_CPSR);
CPSR spsr = cpsr;
spsr.nz = tc->readIntReg(INTREG_CONDCODES_NZ);
spsr.c = tc->readIntReg(INTREG_CONDCODES_C);
spsr.v = tc->readIntReg(INTREG_CONDCODES_V);
spsr.nz = tc->readCCReg(CCREG_NZ);
spsr.c = tc->readCCReg(CCREG_C);
spsr.v = tc->readCCReg(CCREG_V);
if (from64) {
// Force some bitfields to 0
spsr.q = 0;
@ -628,7 +628,7 @@ ArmFault::invoke64(ThreadContext *tc, StaticInstPtr inst)
spsr.it2 = 0;
spsr.t = 0;
} else {
spsr.ge = tc->readIntReg(INTREG_CONDCODES_GE);
spsr.ge = tc->readCCReg(CCREG_GE);
ITSTATE it = tc->pcState().itstate();
spsr.it2 = it.top6;
spsr.it1 = it.bottom2;

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2010-2013 ARM Limited
* Copyright (c) 2010-2014 ARM Limited
* Copyright (c) 2013 Advanced Micro Devices, Inc.
* All rights reserved
*
@ -335,7 +335,8 @@ ArmStaticInst::printReg(std::ostream &os, int reg) const
ccprintf(os, "%s", ArmISA::miscRegName[rel_reg]);
break;
case CCRegClass:
panic("printReg: CCRegClass but ARM has no CC regs\n");
ccprintf(os, "cc_%s", ArmISA::ccRegName[rel_reg]);
break;
}
}

View file

@ -115,11 +115,6 @@ enum IntRegIndex
INTREG_UREG0,
INTREG_UREG1,
INTREG_UREG2,
INTREG_CONDCODES_NZ,
INTREG_CONDCODES_C,
INTREG_CONDCODES_V,
INTREG_CONDCODES_GE,
INTREG_FPCONDCODES,
INTREG_DUMMY, // Dummy reg used to throw away int reg results
INTREG_SP0,

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2010-2013 ARM Limited
* Copyright (c) 2010-2014 ARM Limited
* All rights reserved
*
* The license below extends only to copyright in the software and shall
@ -599,9 +599,9 @@ ISA::readMiscReg(int misc_reg, ThreadContext *tc)
case MISCREG_NZCV:
{
CPSR cpsr = 0;
cpsr.nz = tc->readIntReg(INTREG_CONDCODES_NZ);
cpsr.c = tc->readIntReg(INTREG_CONDCODES_C);
cpsr.v = tc->readIntReg(INTREG_CONDCODES_V);
cpsr.nz = tc->readCCReg(CCREG_NZ);
cpsr.c = tc->readCCReg(CCREG_C);
cpsr.v = tc->readCCReg(CCREG_V);
return cpsr;
}
case MISCREG_DAIF:
@ -1688,9 +1688,9 @@ ISA::setMiscReg(int misc_reg, const MiscReg &val, ThreadContext *tc)
{
CPSR cpsr = val;
tc->setIntReg(INTREG_CONDCODES_NZ, cpsr.nz);
tc->setIntReg(INTREG_CONDCODES_C, cpsr.c);
tc->setIntReg(INTREG_CONDCODES_V, cpsr.v);
tc->setCCReg(CCREG_NZ, cpsr.nz);
tc->setCCReg(CCREG_C, cpsr.c);
tc->setCCReg(CCREG_V, cpsr.v);
}
break;
case MISCREG_DAIF:

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2010, 2012-2013 ARM Limited
* Copyright (c) 2010, 2012-2014 ARM Limited
* All rights reserved
*
* The license below extends only to copyright in the software and shall
@ -268,19 +268,21 @@ namespace ArmISA
int
flattenFloatIndex(int reg) const
{
assert(reg >= 0);
return reg;
}
// dummy
int
flattenCCIndex(int reg) const
{
assert(reg >= 0);
return reg;
}
int
flattenMiscIndex(int reg) const
{
assert(reg >= 0);
int flat_idx = reg;
if (reg == MISCREG_SPSR) {

View file

@ -1,5 +1,5 @@
// -*- mode:c++ -*-
// Copyright (c) 2010-2013 ARM Limited
// Copyright (c) 2010-2014 ARM Limited
// All rights reserved
//
// The license below extends only to copyright in the software and shall
@ -151,8 +151,8 @@ let {{
return ('IntReg', 'uw', idx, 'IsInteger', srtNormal,
maybePCRead, maybeAIWPCWrite)
def intRegCC(idx):
return ('IntReg', 'uw', idx, None, srtNormal)
def ccReg(idx):
return ('CCReg', 'uw', idx, None, srtNormal)
def cntrlReg(idx, id = srtNormal, type = 'uw'):
return ('ControlReg', type, idx, None, id)
@ -221,31 +221,31 @@ def operands {{
'X2': intRegX64('2'),
'X3': intRegX64('3'),
#Pseudo integer condition code registers
'CondCodesNZ': intRegCC('INTREG_CONDCODES_NZ'),
'CondCodesC': intRegCC('INTREG_CONDCODES_C'),
'CondCodesV': intRegCC('INTREG_CONDCODES_V'),
'CondCodesGE': intRegCC('INTREG_CONDCODES_GE'),
'OptCondCodesNZ': intRegCC(
'''(condCode == COND_AL || condCode == COND_UC ||
condCode == COND_CC || condCode == COND_CS ||
condCode == COND_VS || condCode == COND_VC) ?
INTREG_ZERO : INTREG_CONDCODES_NZ'''),
'OptCondCodesC': intRegCC(
'''(condCode == COND_HI || condCode == COND_LS ||
# Condition code registers
'CondCodesNZ': ccReg('CCREG_NZ'),
'CondCodesC': ccReg('CCREG_C'),
'CondCodesV': ccReg('CCREG_V'),
'CondCodesGE': ccReg('CCREG_GE'),
'OptCondCodesNZ': ccReg(
'''((condCode == COND_AL || condCode == COND_UC ||
condCode == COND_CC || condCode == COND_CS ||
condCode == COND_VS || condCode == COND_VC) ?
CCREG_ZERO : CCREG_NZ)'''),
'OptCondCodesC': ccReg(
'''((condCode == COND_HI || condCode == COND_LS ||
condCode == COND_CS || condCode == COND_CC) ?
INTREG_CONDCODES_C : INTREG_ZERO'''),
'OptShiftRmCondCodesC': intRegCC(
'''(condCode == COND_HI || condCode == COND_LS ||
condCode == COND_CS || condCode == COND_CC ||
shiftType == ROR) ?
INTREG_CONDCODES_C : INTREG_ZERO'''),
'OptCondCodesV': intRegCC(
'''(condCode == COND_VS || condCode == COND_VC ||
condCode == COND_GE || condCode == COND_LT ||
condCode == COND_GT || condCode == COND_LE) ?
INTREG_CONDCODES_V : INTREG_ZERO'''),
'FpCondCodes': intRegCC('INTREG_FPCONDCODES'),
CCREG_C : CCREG_ZERO)'''),
'OptShiftRmCondCodesC': ccReg(
'''((condCode == COND_HI || condCode == COND_LS ||
condCode == COND_CS || condCode == COND_CC ||
shiftType == ROR) ?
CCREG_C : CCREG_ZERO)'''),
'OptCondCodesV': ccReg(
'''((condCode == COND_VS || condCode == COND_VC ||
condCode == COND_GE || condCode == COND_LT ||
condCode == COND_GT || condCode == COND_LE) ?
CCREG_V : CCREG_ZERO)'''),
'FpCondCodes': ccReg('CCREG_FP'),
#Abstracted floating point reg operands
'FpDest': floatReg('(dest + 0)'),

View file

@ -53,25 +53,6 @@ class ThreadContext;
namespace ArmISA
{
enum ConditionCode {
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_UC // 15
};
enum MiscRegIndex {
MISCREG_CPSR = 0, // 0
MISCREG_SPSR, // 1

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2010-2011 ARM Limited
* Copyright (c) 2010-2011, 2014 ARM Limited
* All rights reserved
*
* The license below extends only to copyright in the software and shall
@ -116,10 +116,10 @@ Trace::ArmNativeTrace::ThreadState::update(ThreadContext *tc)
//CPSR
CPSR cpsr = tc->readMiscReg(MISCREG_CPSR);
cpsr.nz = tc->readIntReg(INTREG_CONDCODES_NZ);
cpsr.c = tc->readIntReg(INTREG_CONDCODES_C);
cpsr.v = tc->readIntReg(INTREG_CONDCODES_V);
cpsr.ge = tc->readIntReg(INTREG_CONDCODES_GE);
cpsr.nz = tc->readCCReg(CCREG_NZ);
cpsr.c = tc->readCCReg(CCREG_C);
cpsr.v = tc->readCCReg(CCREG_V);
cpsr.ge = tc->readCCReg(CCREG_GE);
newState[STATE_CPSR] = cpsr;
changed[STATE_CPSR] = (newState[STATE_CPSR] != oldState[STATE_CPSR]);
@ -130,7 +130,7 @@ Trace::ArmNativeTrace::ThreadState::update(ThreadContext *tc)
tc->readFloatRegBits(i);
}
newState[STATE_FPSCR] = tc->readMiscRegNoEffect(MISCREG_FPSCR) |
tc->readIntReg(INTREG_FPCONDCODES);
tc->readCCReg(CCREG_FP);
}
void

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2010-2011 ARM Limited
* Copyright (c) 2010-2011, 2014 ARM Limited
* All rights reserved
*
* The license below extends only to copyright in the software and shall
@ -45,6 +45,7 @@
#include "arch/arm/generated/max_inst_regs.hh"
#include "arch/arm/intregs.hh"
#include "arch/arm/ccregs.hh"
#include "arch/arm/miscregs.hh"
namespace ArmISA {
@ -68,8 +69,8 @@ typedef float FloatReg;
// cop-0/cop-1 system control register
typedef uint64_t MiscReg;
// dummy typedef since we don't have CC regs
typedef uint8_t CCReg;
// condition code register; must be at least 32 bits for FpCondCodes
typedef uint64_t CCReg;
// Constants Related to the number of registers
const int NumIntArchRegs = NUM_ARCH_INTREGS;
@ -80,9 +81,11 @@ const int NumFloatSpecialRegs = 32;
const int NumIntRegs = NUM_INTREGS;
const int NumFloatRegs = NumFloatV8ArchRegs + NumFloatSpecialRegs;
const int NumCCRegs = 0;
const int NumCCRegs = NUM_CCREGS;
const int NumMiscRegs = NUM_MISCREGS;
#define ISA_HAS_CC_REGS
const int TotalNumRegs = NumIntRegs + NumFloatRegs + NumMiscRegs;
// semantically meaningful register indices
@ -109,12 +112,13 @@ const int SyscallSuccessReg = ReturnValueReg;
// These help enumerate all the registers for dependence tracking.
const int FP_Reg_Base = NumIntRegs * (MODE_MAXMODE + 1);
const int CC_Reg_Base = FP_Reg_Base + NumFloatRegs;
const int Misc_Reg_Base = CC_Reg_Base + NumCCRegs; // NumCCRegs == 0
const int Misc_Reg_Base = CC_Reg_Base + NumCCRegs;
const int Max_Reg_Index = Misc_Reg_Base + NumMiscRegs;
typedef union {
IntReg intreg;
FloatReg fpreg;
CCReg ccreg;
MiscReg ctrlreg;
} AnyReg;

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2009-2013 ARM Limited
* Copyright (c) 2009-2014 ARM Limited
* All rights reserved.
*
* The license below extends only to copyright in the software and shall
@ -152,8 +152,8 @@ copyRegs(ThreadContext *src, ThreadContext *dest)
for (int i = 0; i < NumFloatRegs; i++)
dest->setFloatRegFlat(i, src->readFloatRegFlat(i));
// Would need to add condition-code regs if implemented
assert(NumCCRegs == 0);
for (int i = 0; i < NumCCRegs; i++)
dest->setCCReg(i, src->readCCReg(i));
for (int i = 0; i < NumMiscRegs; i++)
dest->setMiscRegNoEffect(i, src->readMiscRegNoEffect(i));

View file

@ -116,7 +116,7 @@ class DerivO3CPU(BaseCPU):
"registers")
# most ISAs don't use condition-code regs, so default is 0
_defaultNumPhysCCRegs = 0
if buildEnv['TARGET_ISA'] == 'x86':
if buildEnv['TARGET_ISA'] in ('arm','x86'):
# For x86, each CC reg is used to hold only a subset of the
# flags, so we need 4-5 times the number of CC regs as
# physical integer regs to be sure we don't run out. In

View file

@ -273,6 +273,7 @@ class SimpleThread : public ThreadState
{
#ifdef ISA_HAS_CC_REGS
int flatIndex = isa->flattenCCIndex(reg_idx);
assert(0 <= flatIndex);
assert(flatIndex < TheISA::NumCCRegs);
uint64_t regVal(readCCRegFlat(flatIndex));
DPRINTF(CCRegs, "Reading CC reg %d (%d) as %#x.\n",

View file

@ -58,7 +58,7 @@ class EventQueue;
* SimObject shouldn't cause the version number to increase, only changes to
* existing objects such as serializing/unserializing more state, changing sizes
* of serialized arrays, etc. */
static const uint64_t gem5CheckpointVersion = 0x000000000000000c;
static const uint64_t gem5CheckpointVersion = 0x000000000000000d;
template <class T>
void paramOut(std::ostream &os, const std::string &name, const T &param);

View file

@ -574,6 +574,33 @@ def from_A(cpt):
def from_B(cpt):
cpt.set('Globals', 'numMainEventQueues', '1')
# Checkpoint version D uses condition code registers for the ARM
# architecture; previously the integer register file was used for these
# registers. To upgrade, we move those 5 integer registers to the ccRegs
# register file.
def from_C(cpt):
if cpt.get('root','isa') == 'arm':
for sec in cpt.sections():
import re
re_cpu_match = re.match('^(.*sys.*\.cpu[^.]*)\.xc\.(.+)$', sec)
# Search for all the execution contexts
if not re_cpu_match:
continue
items = []
for (item,value) in cpt.items(sec):
items.append(item)
if 'ccRegs' not in items:
intRegs = cpt.get(sec, 'intRegs').split()
ccRegs = intRegs[38:43]
del intRegs[38:43]
ccRegs.append('0') # CCREG_ZERO
cpt.set(sec, 'intRegs', ' '.join(intRegs))
cpt.set(sec, 'ccRegs', ' '.join(ccRegs))
migrations = []
migrations.append(from_0)
@ -588,6 +615,7 @@ migrations.append(from_8)
migrations.append(from_9)
migrations.append(from_A)
migrations.append(from_B)
migrations.append(from_C)
verbose_print = False