summaryrefslogtreecommitdiff
path: root/src/arch
diff options
context:
space:
mode:
Diffstat (limited to 'src/arch')
-rw-r--r--src/arch/alpha/predecoder.hh6
-rw-r--r--src/arch/arm/insts/branch.hh1
-rw-r--r--src/arch/arm/insts/macromem.cc86
-rw-r--r--src/arch/arm/insts/macromem.hh21
-rw-r--r--src/arch/arm/insts/mem.hh8
-rw-r--r--src/arch/arm/intregs.hh2
-rw-r--r--src/arch/arm/isa.cc10
-rw-r--r--src/arch/arm/isa/formats/fp.isa2
-rw-r--r--src/arch/arm/isa/insts/branch.isa35
-rw-r--r--src/arch/arm/isa/insts/ldr.isa25
-rw-r--r--src/arch/arm/isa/insts/m5ops.isa6
-rw-r--r--src/arch/arm/isa/insts/macromem.isa84
-rw-r--r--src/arch/arm/isa/insts/mem.isa25
-rw-r--r--src/arch/arm/isa/insts/misc.isa20
-rw-r--r--src/arch/arm/isa/insts/str.isa14
-rw-r--r--src/arch/arm/isa/operands.isa6
-rw-r--r--src/arch/arm/isa/templates/branch.isa37
-rw-r--r--src/arch/arm/isa/templates/macromem.isa35
-rw-r--r--src/arch/arm/isa/templates/mem.isa24
-rw-r--r--src/arch/arm/isa/templates/pred.isa32
-rw-r--r--src/arch/arm/linux/process.cc34
-rw-r--r--src/arch/arm/linux/system.cc24
-rw-r--r--src/arch/arm/linux/system.hh13
-rw-r--r--src/arch/arm/miscregs.hh17
-rw-r--r--src/arch/arm/predecoder.hh13
-rw-r--r--src/arch/arm/types.hh13
-rw-r--r--src/arch/mips/predecoder.hh6
-rw-r--r--src/arch/power/predecoder.hh6
-rw-r--r--src/arch/sparc/predecoder.hh7
-rw-r--r--src/arch/x86/predecoder.hh6
30 files changed, 484 insertions, 134 deletions
diff --git a/src/arch/alpha/predecoder.hh b/src/arch/alpha/predecoder.hh
index a8788051f..2f8c4c2ef 100644
--- a/src/arch/alpha/predecoder.hh
+++ b/src/arch/alpha/predecoder.hh
@@ -76,6 +76,12 @@ class Predecoder
emiIsReady = false;
}
+ void
+ reset(const ExtMachInst &old_emi)
+ {
+ reset();
+ }
+
// Use this to give data to the predecoder. This should be used
// when there is control flow.
void
diff --git a/src/arch/arm/insts/branch.hh b/src/arch/arm/insts/branch.hh
index fbdd10d68..0e33a9214 100644
--- a/src/arch/arm/insts/branch.hh
+++ b/src/arch/arm/insts/branch.hh
@@ -57,6 +57,7 @@ class BranchImm : public PredOp
int32_t _imm) :
PredOp(mnem, _machInst, __opClass), imm(_imm)
{}
+
};
// Conditionally Branch to a target computed with an immediate
diff --git a/src/arch/arm/insts/macromem.cc b/src/arch/arm/insts/macromem.cc
index 2a45cf2e6..8a82bd319 100644
--- a/src/arch/arm/insts/macromem.cc
+++ b/src/arch/arm/insts/macromem.cc
@@ -58,8 +58,13 @@ MacroMemOp::MacroMemOp(const char *mnem, ExtMachInst machInst,
{
uint32_t regs = reglist;
uint32_t ones = number_of_ones(reglist);
- // Remember that writeback adds a uop
- numMicroops = ones + (writeback ? 1 : 0) + 1;
+ // Remember that writeback adds a uop or two and the temp register adds one
+ numMicroops = ones + (writeback ? (load ? 2 : 1) : 0) + 1;
+
+ // It's technically legal to do a lot of nothing
+ if (!ones)
+ numMicroops = 1;
+
microOps = new StaticInstPtr[numMicroops];
uint32_t addr = 0;
@@ -70,28 +75,13 @@ MacroMemOp::MacroMemOp(const char *mnem, ExtMachInst machInst,
addr += 4;
StaticInstPtr *uop = microOps;
- StaticInstPtr wbUop;
- if (writeback) {
- if (up) {
- wbUop = new MicroAddiUop(machInst, rn, rn, ones * 4);
- } else {
- wbUop = new MicroSubiUop(machInst, rn, rn, ones * 4);
- }
- }
// Add 0 to Rn and stick it in ureg0.
// This is equivalent to a move.
*uop = new MicroAddiUop(machInst, INTREG_UREG0, rn, 0);
- // Write back at the start for loads. This covers the ldm exception return
- // case where the base needs to be written in the old mode. Stores may need
- // the original value of the base, but they don't change mode and can
- // write back at the end like before.
- if (load && writeback) {
- *++uop = wbUop;
- }
-
unsigned reg = 0;
+ unsigned regIdx = 0;
bool force_user = user & !bits(reglist, 15);
bool exception_ret = user & bits(reglist, 15);
@@ -101,19 +91,28 @@ MacroMemOp::MacroMemOp(const char *mnem, ExtMachInst machInst,
reg++;
replaceBits(regs, reg, 0);
- unsigned regIdx = reg;
+ regIdx = reg;
if (force_user) {
regIdx = intRegInMode(MODE_USER, regIdx);
}
if (load) {
- if (reg == INTREG_PC && exception_ret) {
- // This must be the exception return form of ldm.
- *++uop = new MicroLdrRetUop(machInst, regIdx,
- INTREG_UREG0, up, addr);
+ if (writeback && i == ones - 1) {
+ // If it's a writeback and this is the last register
+ // do the load into a temporary register which we'll move
+ // into the final one later
+ *++uop = new MicroLdrUop(machInst, INTREG_UREG1, INTREG_UREG0,
+ up, addr);
} else {
- *++uop = new MicroLdrUop(machInst, regIdx,
- INTREG_UREG0, up, addr);
+ // Otherwise just do it normally
+ if (reg == INTREG_PC && exception_ret) {
+ // This must be the exception return form of ldm.
+ *++uop = new MicroLdrRetUop(machInst, regIdx,
+ INTREG_UREG0, up, addr);
+ } else {
+ *++uop = new MicroLdrUop(machInst, regIdx,
+ INTREG_UREG0, up, addr);
+ }
}
} else {
*++uop = new MicroStrUop(machInst, regIdx, INTREG_UREG0, up, addr);
@@ -125,8 +124,32 @@ MacroMemOp::MacroMemOp(const char *mnem, ExtMachInst machInst,
addr -= 4;
}
- if (!load && writeback) {
- *++uop = wbUop;
+ if (writeback && ones) {
+ // put the register update after we're done all loading
+ if (up)
+ *++uop = new MicroAddiUop(machInst, rn, rn, ones * 4);
+ else
+ *++uop = new MicroSubiUop(machInst, rn, rn, ones * 4);
+
+ // If this was a load move the last temporary value into place
+ // this way we can't take an exception after we update the base
+ // register.
+ if (load && reg == INTREG_PC && exception_ret) {
+ *++uop = new MicroUopRegMovRet(machInst, 0, INTREG_UREG1);
+ warn("creating instruction with exception return at curTick:%d\n",
+ curTick());
+ } else if (load) {
+ *++uop = new MicroUopRegMov(machInst, regIdx, INTREG_UREG1);
+ if (reg == INTREG_PC) {
+ (*uop)->setFlag(StaticInstBase::IsControl);
+ (*uop)->setFlag(StaticInstBase::IsCondControl);
+ (*uop)->setFlag(StaticInstBase::IsIndirectControl);
+ // This is created as a RAS POP
+ if (rn == INTREG_SP)
+ (*uop)->setFlag(StaticInstBase::IsReturn);
+
+ }
+ }
}
(*uop)->setLastMicroop();
@@ -896,6 +919,15 @@ MicroIntImmOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
}
std::string
+MicroSetPCCPSR::generateDisassembly(Addr pc, const SymbolTable *symtab) const
+{
+ std::stringstream ss;
+ printMnemonic(ss);
+ ss << "[PC,CPSR]";
+ return ss.str();
+}
+
+std::string
MicroIntMov::generateDisassembly(Addr pc, const SymbolTable *symtab) const
{
std::stringstream ss;
diff --git a/src/arch/arm/insts/macromem.hh b/src/arch/arm/insts/macromem.hh
index 1a2db8b9a..4933a1e7c 100644
--- a/src/arch/arm/insts/macromem.hh
+++ b/src/arch/arm/insts/macromem.hh
@@ -134,6 +134,27 @@ class MicroNeonMixLaneOp : public MicroNeonMixOp
{
}
};
+
+/**
+ * Microops of the form
+ * PC = IntRegA
+ * CPSR = IntRegB
+ */
+class MicroSetPCCPSR : public MicroOp
+{
+ protected:
+ IntRegIndex ura, urb, urc;
+
+ MicroSetPCCPSR(const char *mnem, ExtMachInst machInst, OpClass __opClass,
+ IntRegIndex _ura, IntRegIndex _urb, IntRegIndex _urc)
+ : MicroOp(mnem, machInst, __opClass),
+ ura(_ura), urb(_urb), urc(_urc)
+ {
+ }
+
+ std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
+};
+
/**
* Microops of the form IntRegA = IntRegB
*/
diff --git a/src/arch/arm/insts/mem.hh b/src/arch/arm/insts/mem.hh
index a4fc62603..324d86fed 100644
--- a/src/arch/arm/insts/mem.hh
+++ b/src/arch/arm/insts/mem.hh
@@ -97,14 +97,18 @@ class RfeOp : public MightBeMicro
IntRegIndex base;
AddrMode mode;
bool wb;
- static const unsigned numMicroops = 2;
+ IntRegIndex ura, urb, urc;
+ static const unsigned numMicroops = 3;
StaticInstPtr *uops;
RfeOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass,
IntRegIndex _base, AddrMode _mode, bool _wb)
: MightBeMicro(mnem, _machInst, __opClass),
- base(_base), mode(_mode), wb(_wb), uops(NULL)
+ base(_base), mode(_mode), wb(_wb),
+ ura(INTREG_UREG0), urb(INTREG_UREG1),
+ urc(INTREG_UREG2),
+ uops(NULL)
{}
virtual
diff --git a/src/arch/arm/intregs.hh b/src/arch/arm/intregs.hh
index 4b2cc560d..2cbed6c59 100644
--- a/src/arch/arm/intregs.hh
+++ b/src/arch/arm/intregs.hh
@@ -110,6 +110,8 @@ enum IntRegIndex
INTREG_ZERO, // Dummy zero reg since there has to be one.
INTREG_UREG0,
+ INTREG_UREG1,
+ INTREG_UREG2,
INTREG_CONDCODES,
INTREG_FPCONDCODES,
diff --git a/src/arch/arm/isa.cc b/src/arch/arm/isa.cc
index 4bdbe77ce..d720becba 100644
--- a/src/arch/arm/isa.cc
+++ b/src/arch/arm/isa.cc
@@ -143,6 +143,16 @@ ISA::clear()
miscRegs[MISCREG_CPACR] = 0;
miscRegs[MISCREG_FPSID] = 0x410430A0;
+
+ // See section B4.1.84 of ARM ARM
+ // All values are latest for ARMv7-A profile
+ miscRegs[MISCREG_ID_ISAR0] = 0x01101111;
+ miscRegs[MISCREG_ID_ISAR1] = 0x02112111;
+ miscRegs[MISCREG_ID_ISAR2] = 0x21232141;
+ miscRegs[MISCREG_ID_ISAR3] = 0x01112131;
+ miscRegs[MISCREG_ID_ISAR4] = 0x10010142;
+ miscRegs[MISCREG_ID_ISAR5] = 0x00000000;
+
//XXX We need to initialize the rest of the state.
}
diff --git a/src/arch/arm/isa/formats/fp.isa b/src/arch/arm/isa/formats/fp.isa
index 3a0cad1c5..2267ee34f 100644
--- a/src/arch/arm/isa/formats/fp.isa
+++ b/src/arch/arm/isa/formats/fp.isa
@@ -143,7 +143,7 @@ let {{
bits(machInst, 22) << 4);
const uint32_t type = bits(machInst, 11, 8);
uint32_t size = 0;
- uint32_t align = 0;
+ uint32_t align = TLB::MustBeOne;
unsigned inc = 1;
unsigned regs = 1;
unsigned lane = 0;
diff --git a/src/arch/arm/isa/insts/branch.isa b/src/arch/arm/isa/insts/branch.isa
index d8ea2118e..84b9bb720 100644
--- a/src/arch/arm/isa/insts/branch.isa
+++ b/src/arch/arm/isa/insts/branch.isa
@@ -48,6 +48,8 @@ let {{
bCode = '''
NPC = (uint32_t)(PC + imm);
'''
+ br_tgt_code = '''pcs.instNPC(branchPC.instPC() + imm);'''
+ instFlags = ["IsDirectControl"]
if (link):
bCode += '''
if (Thumb)
@@ -55,12 +57,15 @@ let {{
else
LR = PC - 4;
'''
+ instFlags += ["IsCall"]
+
bIop = InstObjParams(mnem, mnem.capitalize(), "BranchImmCond",
- {"code": bCode,
- "predicate_test": predicateTest})
+ {"code": bCode, "predicate_test": predicateTest,
+ "brTgtCode" : br_tgt_code}, instFlags)
header_output += BranchImmCondDeclare.subst(bIop)
- decoder_output += BranchImmCondConstructor.subst(bIop)
+ decoder_output += BranchImmCondConstructor.subst(bIop) + \
+ BranchTarget.subst(bIop)
exec_output += PredOpExecute.subst(bIop)
# BX, BLX
@@ -81,15 +86,22 @@ let {{
# Since we're switching ISAs, the target ISA will be the opposite
# of the current ISA. Thumb is whether the target is ARM.
newPC = '(Thumb ? (roundDown(PC, 4) + imm) : (PC + imm))'
+ br_tgt_code = '''
+ pcs.instNPC((branchPC.thumb() ? (roundDown(branchPC.instPC(),4) + imm) :
+ (branchPC.instPC() + imm)));
+ '''
base = "BranchImmCond"
declare = BranchImmCondDeclare
constructor = BranchImmCondConstructor
+ instFlags = ["IsDirectControl"]
else:
Name += "Reg"
newPC = 'Op1'
+ br_tgt_code = ''
base = "BranchRegCond"
declare = BranchRegCondDeclare
constructor = BranchRegCondConstructor
+ instFlags = ["IsIndirectControl"]
if link and imm:
linkStr = '''
// The immediate version of the blx thumb instruction
@@ -100,6 +112,7 @@ let {{
else
LR = PC - 4;
'''
+ instFlags += ["IsCall"]
elif link:
linkStr = '''
if (Thumb)
@@ -107,14 +120,18 @@ let {{
else
LR = PC - 4;
'''
+ instFlags += ["IsCall"]
else:
linkStr = ""
+ instFlags += ["IsReturn"]
if imm and link: #blx with imm
branchStr = '''
NextThumb = !Thumb;
NPC = %(newPC)s;
'''
+ br_tgt_code = '''pcs.nextThumb(!branchPC.thumb());\n''' + \
+ br_tgt_code
else:
branchStr = "IWNPC = %(newPC)s;"
branchStr = branchStr % { "newPC" : newPC }
@@ -123,11 +140,13 @@ let {{
"newPC": newPC,
"branch": branchStr}
blxIop = InstObjParams(mnem, Name, base,
- {"code": code,
- "predicate_test": predicateTest})
+ {"code": code, "brTgtCode" : br_tgt_code,
+ "predicate_test": predicateTest}, instFlags)
header_output += declare.subst(blxIop)
decoder_output += constructor.subst(blxIop)
exec_output += PredOpExecute.subst(blxIop)
+ if imm:
+ decoder_output += BranchTarget.subst(blxIop)
#Ignore BXJ for now
@@ -136,7 +155,8 @@ let {{
code = 'NPC = (uint32_t)(PC + imm);\n'
predTest = "Op1 %(test)s 0" % {"test": test}
iop = InstObjParams(mnem, mnem.capitalize(), "BranchImmReg",
- {"code": code, "predicate_test": predTest})
+ {"code": code, "predicate_test": predTest},
+ ["IsIndirectControl"])
header_output += BranchImmRegDeclare.subst(iop)
decoder_output += BranchImmRegConstructor.subst(iop)
exec_output += PredOpExecute.subst(iop)
@@ -164,7 +184,8 @@ let {{
iop = InstObjParams(mnem, mnem.capitalize(), "BranchRegReg",
{'ea_code': eaCode,
'memacc_code': accCode,
- 'predicate_test': predicateTest})
+ 'predicate_test': predicateTest},
+ ["IsIndirectControl"])
header_output += BranchTableDeclare.subst(iop)
decoder_output += BranchRegRegConstructor.subst(iop)
exec_output += LoadExecute.subst(iop) + \
diff --git a/src/arch/arm/isa/insts/ldr.isa b/src/arch/arm/isa/insts/ldr.isa
index c60a91a50..2e45f2875 100644
--- a/src/arch/arm/isa/insts/ldr.isa
+++ b/src/arch/arm/isa/insts/ldr.isa
@@ -67,7 +67,7 @@ let {{
self.memFlags = ["ArmISA::TLB::MustBeOne"]
self.codeBlobs = {"postacc_code" : ""}
- def emitHelper(self, base = 'Memory', wbDecl = None, instFlags = []):
+ def emitHelper(self, base = 'Memory', wbDecl = None, instFlags = [], pcDecl = None):
global header_output, decoder_output, exec_output
@@ -76,7 +76,8 @@ let {{
(newHeader,
newDecoder,
newExec) = self.fillTemplates(self.name, self.Name, codeBlobs,
- self.memFlags, instFlags, base, wbDecl)
+ self.memFlags, instFlags, base,
+ wbDecl, pcDecl)
header_output += newHeader
decoder_output += newDecoder
@@ -104,26 +105,18 @@ let {{
wbDiff = 8
accCode = '''
CPSR cpsr = Cpsr;
- SCTLR sctlr = Sctlr;
- // Use the version of NPC that gets set before NextThumb
- pNPC = cSwap<uint32_t>(Mem.ud, cpsr.e);
- uint32_t tempSpsr = cSwap<uint32_t>(Mem.ud >> 32, cpsr.e);
- uint32_t newCpsr =
- cpsrWriteByInstr(cpsr | CondCodes, tempSpsr,
- 0xF, true, sctlr.nmfi);
- Cpsr = ~CondCodesMask & newCpsr;
- NextThumb = ((CPSR)newCpsr).t;
- NextJazelle = ((CPSR)newCpsr).j;
- ForcedItState = ((((CPSR)tempSpsr).it2 << 2) & 0xFC)
- | (((CPSR)tempSpsr).it1 & 0x3);
- CondCodes = CondCodesMask & newCpsr;
+ URc = cpsr | CondCodes;
+ URa = cSwap<uint32_t>(Mem.ud, cpsr.e);
+ URb = cSwap<uint32_t>(Mem.ud >> 32, cpsr.e);
'''
self.codeBlobs["memacc_code"] = accCode
wbDecl = None
+ pcDecl = "MicroUopSetPCCPSR(machInst, INTREG_UREG0, INTREG_UREG1, INTREG_UREG2);"
+
if self.writeback:
wbDecl = "MicroAddiUop(machInst, base, base, %d);" % wbDiff
- self.emitHelper('RfeOp', wbDecl, ["IsSerializeAfter", "IsNonSpeculative"])
+ self.emitHelper('RfeOp', wbDecl, ["IsSerializeAfter", "IsNonSpeculative"], pcDecl)
class LoadImmInst(LoadInst):
def __init__(self, *args, **kargs):
diff --git a/src/arch/arm/isa/insts/m5ops.isa b/src/arch/arm/isa/insts/m5ops.isa
index da3609bbc..8521cbc97 100644
--- a/src/arch/arm/isa/insts/m5ops.isa
+++ b/src/arch/arm/isa/insts/m5ops.isa
@@ -66,7 +66,7 @@ let {{
["IsNonSpeculative", "IsQuiesce"])
header_output += BasicDeclare.subst(quiesceIop)
decoder_output += BasicConstructor.subst(quiesceIop)
- exec_output += PredOpExecute.subst(quiesceIop)
+ exec_output += QuiescePredOpExecute.subst(quiesceIop)
quiesceNsCode = '''
#if FULL_SYSTEM
@@ -80,7 +80,7 @@ let {{
["IsNonSpeculative", "IsQuiesce"])
header_output += BasicDeclare.subst(quiesceNsIop)
decoder_output += BasicConstructor.subst(quiesceNsIop)
- exec_output += PredOpExecute.subst(quiesceNsIop)
+ exec_output += QuiescePredOpExecute.subst(quiesceNsIop)
quiesceCyclesCode = '''
#if FULL_SYSTEM
@@ -94,7 +94,7 @@ let {{
["IsNonSpeculative", "IsQuiesce", "IsUnverifiable"])
header_output += BasicDeclare.subst(quiesceCyclesIop)
decoder_output += BasicConstructor.subst(quiesceCyclesIop)
- exec_output += PredOpExecute.subst(quiesceCyclesIop)
+ exec_output += QuiescePredOpExecute.subst(quiesceCyclesIop)
quiesceTimeCode = '''
#if FULL_SYSTEM
diff --git a/src/arch/arm/isa/insts/macromem.isa b/src/arch/arm/isa/insts/macromem.isa
index 33d57a60b..15879e0e3 100644
--- a/src/arch/arm/isa/insts/macromem.isa
+++ b/src/arch/arm/isa/insts/macromem.isa
@@ -51,7 +51,7 @@ let {{
microLdrUopIop = InstObjParams('ldr_uop', 'MicroLdrUop',
'MicroMemOp',
{'memacc_code': microLdrUopCode,
- 'ea_code': 'EA = Rb + (up ? imm : -imm);',
+ 'ea_code': 'EA = URb + (up ? imm : -imm);',
'predicate_test': predicateTest},
['IsMicroop'])
@@ -60,7 +60,7 @@ let {{
'MicroMemOp',
{'memacc_code': microLdrFpUopCode,
'ea_code': vfpEnabledCheckCode +
- 'EA = Rb + (up ? imm : -imm);',
+ 'EA = URb + (up ? imm : -imm);',
'predicate_test': predicateTest},
['IsMicroop'])
@@ -69,7 +69,7 @@ let {{
'MicroMemOp',
{'memacc_code': microLdrFpUopCode,
'ea_code': vfpEnabledCheckCode + '''
- EA = Rb + (up ? imm : -imm) +
+ EA = URb + (up ? imm : -imm) +
(((CPSR)Cpsr).e ? 4 : 0);
''',
'predicate_test': predicateTest},
@@ -80,37 +80,40 @@ let {{
'MicroMemOp',
{'memacc_code': microLdrFpUopCode,
'ea_code': vfpEnabledCheckCode + '''
- EA = Rb + (up ? imm : -imm) -
+ EA = URb + (up ? imm : -imm) -
(((CPSR)Cpsr).e ? 4 : 0);
''',
'predicate_test': predicateTest},
['IsMicroop'])
- microLdrRetUopCode = '''
+ microRetUopCode = '''
CPSR cpsr = Cpsr;
SCTLR sctlr = Sctlr;
uint32_t newCpsr =
cpsrWriteByInstr(cpsr | CondCodes, Spsr, 0xF, true, sctlr.nmfi);
Cpsr = ~CondCodesMask & newCpsr;
CondCodes = CondCodesMask & newCpsr;
- IWNPC = cSwap(Mem.uw, cpsr.e) | ((Spsr & 0x20) ? 1 : 0);
+ IWNPC = cSwap(%s, cpsr.e) | ((Spsr & 0x20) ? 1 : 0);
ForcedItState = ((((CPSR)Spsr).it2 << 2) & 0xFC)
| (((CPSR)Spsr).it1 & 0x3);
'''
+
microLdrRetUopIop = InstObjParams('ldr_ret_uop', 'MicroLdrRetUop',
'MicroMemOp',
- {'memacc_code': microLdrRetUopCode,
+ {'memacc_code':
+ microRetUopCode % 'Mem.uw',
'ea_code':
- 'EA = Rb + (up ? imm : -imm);',
+ 'EA = URb + (up ? imm : -imm);',
'predicate_test': condPredicateTest},
- ['IsMicroop','IsNonSpeculative','IsSerializeAfter'])
+ ['IsMicroop','IsNonSpeculative',
+ 'IsSerializeAfter'])
- microStrUopCode = "Mem = cSwap(Ra.uw, ((CPSR)Cpsr).e);"
+ microStrUopCode = "Mem = cSwap(URa.uw, ((CPSR)Cpsr).e);"
microStrUopIop = InstObjParams('str_uop', 'MicroStrUop',
'MicroMemOp',
{'memacc_code': microStrUopCode,
'postacc_code': "",
- 'ea_code': 'EA = Rb + (up ? imm : -imm);',
+ 'ea_code': 'EA = URb + (up ? imm : -imm);',
'predicate_test': predicateTest},
['IsMicroop'])
@@ -120,7 +123,7 @@ let {{
{'memacc_code': microStrFpUopCode,
'postacc_code': "",
'ea_code': vfpEnabledCheckCode +
- 'EA = Rb + (up ? imm : -imm);',
+ 'EA = URb + (up ? imm : -imm);',
'predicate_test': predicateTest},
['IsMicroop'])
@@ -130,7 +133,7 @@ let {{
{'memacc_code': microStrFpUopCode,
'postacc_code': "",
'ea_code': vfpEnabledCheckCode + '''
- EA = Rb + (up ? imm : -imm) +
+ EA = URb + (up ? imm : -imm) +
(((CPSR)Cpsr).e ? 4 : 0);
''',
'predicate_test': predicateTest},
@@ -142,7 +145,7 @@ let {{
{'memacc_code': microStrFpUopCode,
'postacc_code': "",
'ea_code': vfpEnabledCheckCode + '''
- EA = Rb + (up ? imm : -imm) -
+ EA = URb + (up ? imm : -imm) -
(((CPSR)Cpsr).e ? 4 : 0);
''',
'predicate_test': predicateTest},
@@ -170,7 +173,7 @@ let {{
let {{
exec_output = header_output = ''
- eaCode = 'EA = Ra + imm;'
+ eaCode = 'EA = URa + imm;'
for size in (1, 2, 3, 4, 6, 8, 12, 16):
# Set up the memory access.
@@ -572,14 +575,14 @@ let {{
let {{
microAddiUopIop = InstObjParams('addi_uop', 'MicroAddiUop',
'MicroIntImmOp',
- {'code': 'Ra = Rb + imm;',
+ {'code': 'URa = URb + imm;',
'predicate_test': predicateTest},
['IsMicroop'])
microAddUopIop = InstObjParams('add_uop', 'MicroAddUop',
'MicroIntRegOp',
{'code':
- '''Ra = Rb + shift_rm_imm(Rc, shiftAmt,
+ '''URa = URb + shift_rm_imm(URc, shiftAmt,
shiftType,
CondCodes<29:>);
''',
@@ -588,14 +591,14 @@ let {{
microSubiUopIop = InstObjParams('subi_uop', 'MicroSubiUop',
'MicroIntImmOp',
- {'code': 'Ra = Rb - imm;',
+ {'code': 'URa = URb - imm;',
'predicate_test': predicateTest},
['IsMicroop'])
microSubUopIop = InstObjParams('sub_uop', 'MicroSubUop',
'MicroIntRegOp',
{'code':
- '''Ra = Rb - shift_rm_imm(Rc, shiftAmt,
+ '''URa = URb - shift_rm_imm(URc, shiftAmt,
shiftType,
CondCodes<29:>);
''',
@@ -604,27 +607,62 @@ let {{
microUopRegMovIop = InstObjParams('uopReg_uop', 'MicroUopRegMov',
'MicroIntMov',
- {'code': 'IWRa = Rb;',
+ {'code': 'IWRa = URb;',
'predicate_test': predicateTest},
['IsMicroop'])
+ microUopRegMovRetIop = InstObjParams('movret_uop', 'MicroUopRegMovRet',
+ 'MicroIntMov',
+ {'code': microRetUopCode % 'URb',
+ 'predicate_test': predicateTest},
+ ['IsMicroop', 'IsNonSpeculative',
+ 'IsSerializeAfter'])
+
+ setPCCPSRDecl = '''
+ CPSR cpsrOrCondCodes = URc;
+ SCTLR sctlr = Sctlr;
+ pNPC = URa;
+ uint32_t newCpsr =
+ cpsrWriteByInstr(cpsrOrCondCodes, URb,
+ 0xF, true, sctlr.nmfi);
+ Cpsr = ~CondCodesMask & newCpsr;
+ NextThumb = ((CPSR)newCpsr).t;
+ NextJazelle = ((CPSR)newCpsr).j;
+ ForcedItState = ((((CPSR)URb).it2 << 2) & 0xFC)
+ | (((CPSR)URb).it1 & 0x3);
+ CondCodes = CondCodesMask & newCpsr;
+ '''
+
+ microUopSetPCCPSRIop = InstObjParams('uopSet_uop', 'MicroUopSetPCCPSR',
+ 'MicroSetPCCPSR',
+ {'code': setPCCPSRDecl,
+ 'predicate_test': predicateTest},
+ ['IsMicroop'])
+
header_output = MicroIntImmDeclare.subst(microAddiUopIop) + \
MicroIntImmDeclare.subst(microSubiUopIop) + \
MicroIntRegDeclare.subst(microAddUopIop) + \
MicroIntRegDeclare.subst(microSubUopIop) + \
- MicroIntMovDeclare.subst(microUopRegMovIop)
+ MicroIntMovDeclare.subst(microUopRegMovIop) + \
+ MicroIntMovDeclare.subst(microUopRegMovRetIop) + \
+ MicroSetPCCPSRDeclare.subst(microUopSetPCCPSRIop)
decoder_output = MicroIntImmConstructor.subst(microAddiUopIop) + \
MicroIntImmConstructor.subst(microSubiUopIop) + \
MicroIntRegConstructor.subst(microAddUopIop) + \
MicroIntRegConstructor.subst(microSubUopIop) + \
- MicroIntMovConstructor.subst(microUopRegMovIop)
+ MicroIntMovConstructor.subst(microUopRegMovIop) + \
+ MicroIntMovConstructor.subst(microUopRegMovRetIop) + \
+ MicroSetPCCPSRConstructor.subst(microUopSetPCCPSRIop)
exec_output = PredOpExecute.subst(microAddiUopIop) + \
PredOpExecute.subst(microSubiUopIop) + \
PredOpExecute.subst(microAddUopIop) + \
PredOpExecute.subst(microSubUopIop) + \
- PredOpExecute.subst(microUopRegMovIop)
+ PredOpExecute.subst(microUopRegMovIop) + \
+ PredOpExecute.subst(microUopRegMovRetIop) + \
+ PredOpExecute.subst(microUopSetPCCPSRIop)
+
}};
let {{
diff --git a/src/arch/arm/isa/insts/mem.isa b/src/arch/arm/isa/insts/mem.isa
index 507f8cd4b..d0c0f0710 100644
--- a/src/arch/arm/isa/insts/mem.isa
+++ b/src/arch/arm/isa/insts/mem.isa
@@ -48,7 +48,7 @@ let {{
self.constructTemplate = eval(self.decConstBase + 'Constructor')
def fillTemplates(self, name, Name, codeBlobs, memFlags, instFlags,
- base = 'Memory', wbDecl = None):
+ base = 'Memory', wbDecl = None, pcDecl = None):
# Make sure flags are in lists (convert to lists if not).
memFlags = makeList(memFlags)
instFlags = makeList(instFlags)
@@ -65,12 +65,26 @@ let {{
macroName = Name
instFlagsCopy = list(instFlags)
codeBlobsCopy = dict(codeBlobs)
- if wbDecl is not None:
+
+ use_uops = 0
+ if wbDecl is not None or pcDecl is not None:
instFlagsCopy.append('IsMicroop')
Name = Name + 'Acc'
+ use_uops = 1
+
+ use_wb = 0
+ use_pc = 0
+ if wbDecl is not None:
+ use_wb = 1
+ if pcDecl is not None:
+ use_pc = 1
+
codeBlobsCopy['acc_name'] = Name
codeBlobsCopy['wb_decl'] = wbDecl
+ codeBlobsCopy['pc_decl'] = pcDecl
codeBlobsCopy['use_uops'] = 0
+ codeBlobsCopy['use_wb'] = 0
+ codeBlobsCopy['use_pc'] = 0
iop = InstObjParams(name, Name, base,
codeBlobsCopy, instFlagsCopy)
@@ -81,11 +95,14 @@ let {{
self.initiateAccTemplate.subst(iop) + \
self.completeAccTemplate.subst(iop)
- if wbDecl is not None:
+ if wbDecl is not None or pcDecl is not None:
iop = InstObjParams(name, macroName, base,
{ "wb_decl" : wbDecl,
+ "pc_decl" : pcDecl,
"acc_name" : Name,
- "use_uops" : 1 },
+ "use_uops" : use_uops,
+ "use_pc" : use_pc,
+ "use_wb" : use_wb },
['IsMacroop'])
header_output += self.declareTemplate.subst(iop)
decoder_output += self.constructTemplate.subst(iop)
diff --git a/src/arch/arm/isa/insts/misc.isa b/src/arch/arm/isa/insts/misc.isa
index be51d927d..cf5c7b47a 100644
--- a/src/arch/arm/isa/insts/misc.isa
+++ b/src/arch/arm/isa/insts/misc.isa
@@ -491,10 +491,13 @@ let {{
wfeCode = '''
#if FULL_SYSTEM
- if (SevMailbox)
+ if (SevMailbox) {
SevMailbox = 0;
- else
+ PseudoInst::quiesceSkip(xc->tcBase());
+ }
+ else {
PseudoInst::quiesce(xc->tcBase());
+ }
#endif
'''
wfeIop = InstObjParams("wfe", "WfeInst", "PredOp", \
@@ -502,7 +505,7 @@ let {{
["IsNonSpeculative", "IsQuiesce", "IsSerializeAfter"])
header_output += BasicDeclare.subst(wfeIop)
decoder_output += BasicConstructor.subst(wfeIop)
- exec_output += PredOpExecute.subst(wfeIop)
+ exec_output += QuiescePredOpExecute.subst(wfeIop)
wfiCode = '''
#if FULL_SYSTEM
@@ -511,22 +514,25 @@ let {{
'''
wfiIop = InstObjParams("wfi", "WfiInst", "PredOp", \
{ "code" : wfiCode, "predicate_test" : predicateTest },
- ["IsNonSpeculative", "IsQuiesce"])
+ ["IsNonSpeculative", "IsQuiesce", "IsSerializeAfter"])
header_output += BasicDeclare.subst(wfiIop)
decoder_output += BasicConstructor.subst(wfiIop)
- exec_output += PredOpExecute.subst(wfiIop)
+ exec_output += QuiescePredOpExecute.subst(wfiIop)
sevCode = '''
// Need a way for O3 to not scoreboard these accesses as pipe flushes.
+ SevMailbox = 1;
System *sys = xc->tcBase()->getSystemPtr();
for (int x = 0; x < sys->numContexts(); x++) {
ThreadContext *oc = sys->getThreadContext(x);
- oc->setMiscReg(MISCREG_SEV_MAILBOX, 1);
+ if (oc != xc->tcBase()) {
+ oc->setMiscReg(MISCREG_SEV_MAILBOX, 1);
+ }
}
'''
sevIop = InstObjParams("sev", "SevInst", "PredOp", \
{ "code" : sevCode, "predicate_test" : predicateTest },
- ["IsNonSpeculative", "IsQuiesce", "IsSerializeAfter"])
+ ["IsNonSpeculative", "IsSquashAfter"])
header_output += BasicDeclare.subst(sevIop)
decoder_output += BasicConstructor.subst(sevIop)
exec_output += PredOpExecute.subst(sevIop)
diff --git a/src/arch/arm/isa/insts/str.isa b/src/arch/arm/isa/insts/str.isa
index f661961f7..e5d47c28f 100644
--- a/src/arch/arm/isa/insts/str.isa
+++ b/src/arch/arm/isa/insts/str.isa
@@ -222,7 +222,6 @@ let {{
decConstBase = 'StoreExImm'
basePrefix = 'MemoryExImm'
nameFunc = staticmethod(storeImmClassName)
- instFlags = ['IsStoreConditional']
def __init__(self, *args, **kargs):
super(StoreImmEx, self).__init__(*args, **kargs)
@@ -302,7 +301,6 @@ let {{
decConstBase = 'StoreExDImm'
basePrefix = 'MemoryExDImm'
nameFunc = staticmethod(storeDoubleImmClassName)
- instFlags = ['IsStoreConditional']
def __init__(self, *args, **kargs):
super(StoreDoubleImmEx, self).__init__(*args, **kargs)
@@ -370,10 +368,14 @@ let {{
buildDoubleStores("strd")
- StoreImmEx("strex", False, True, False, size=4, flavor="exclusive").emit()
- StoreImmEx("strexh", False, True, False, size=2, flavor="exclusive").emit()
- StoreImmEx("strexb", False, True, False, size=1, flavor="exclusive").emit()
- StoreDoubleImmEx("strexd", False, True, False, flavor="exclusive").emit()
+ StoreImmEx("strex", False, True, False, size=4, flavor="exclusive",
+ instFlags = ['IsStoreConditional']).emit()
+ StoreImmEx("strexh", False, True, False, size=2, flavor="exclusive",
+ instFlags = ['IsStoreConditional']).emit()
+ StoreImmEx("strexb", False, True, False, size=1, flavor="exclusive",
+ instFlags = ['IsStoreConditional']).emit()
+ StoreDoubleImmEx("strexd", False, True, False, flavor="exclusive",
+ instFlags = ['IsStoreConditional']).emit()
StoreImm("vstr", False, True, False, size=4, flavor="fp").emit()
StoreImm("vstr", False, False, False, size=4, flavor="fp").emit()
diff --git a/src/arch/arm/isa/operands.isa b/src/arch/arm/isa/operands.isa
index f403f9372..7b014acd0 100644
--- a/src/arch/arm/isa/operands.isa
+++ b/src/arch/arm/isa/operands.isa
@@ -228,11 +228,11 @@ def operands {{
'SevMailbox': cntrlRegNC('MISCREG_SEV_MAILBOX'),
#Register fields for microops
- 'Ra' : intReg('ura'),
+ 'URa' : intReg('ura'),
'IWRa' : intRegIWPC('ura'),
'Fa' : floatReg('ura'),
- 'Rb' : intReg('urb'),
- 'Rc' : intReg('urc'),
+ 'URb' : intReg('urb'),
+ 'URc' : intReg('urc'),
#Memory Operand
'Mem': ('Mem', 'uw', None, ('IsMemRef', 'IsLoad', 'IsStore'), srtNormal),
diff --git a/src/arch/arm/isa/templates/branch.isa b/src/arch/arm/isa/templates/branch.isa
index d1f581f51..6abf76963 100644
--- a/src/arch/arm/isa/templates/branch.isa
+++ b/src/arch/arm/isa/templates/branch.isa
@@ -57,7 +57,11 @@ def template BranchImmConstructor {{
for (int x = 0; x < _numDestRegs; x++) {
_srcRegIdx[_numSrcRegs++] = _destRegIdx[x];
}
+ flags[IsCondControl] = true;
+ } else {
+ flags[IsUncondControl] = true;
}
+
}
}};
@@ -69,6 +73,7 @@ class %(class_name)s : public %(base_class)s
%(class_name)s(ExtMachInst machInst, int32_t _imm,
ConditionCode _condCode);
%(BasicExecDeclare)s
+ ArmISA::PCState branchTarget(const ArmISA::PCState &branchPC) const;
};
}};
@@ -84,6 +89,9 @@ def template BranchImmCondConstructor {{
for (int x = 0; x < _numDestRegs; x++) {
_srcRegIdx[_numSrcRegs++] = _destRegIdx[x];
}
+ flags[IsCondControl] = true;
+ } else {
+ flags[IsUncondControl] = true;
}
}
}};
@@ -108,6 +116,9 @@ def template BranchRegConstructor {{
for (int x = 0; x < _numDestRegs; x++) {
_srcRegIdx[_numSrcRegs++] = _destRegIdx[x];
}
+ flags[IsCondControl] = true;
+ } else {
+ flags[IsUncondControl] = true;
}
}
}};
@@ -135,6 +146,9 @@ def template BranchRegCondConstructor {{
for (int x = 0; x < _numDestRegs; x++) {
_srcRegIdx[_numSrcRegs++] = _destRegIdx[x];
}
+ flags[IsCondControl] = true;
+ } else {
+ flags[IsUncondControl] = true;
}
}
}};
@@ -176,6 +190,9 @@ def template BranchRegRegConstructor {{
for (int x = 0; x < _numDestRegs; x++) {
_srcRegIdx[_numSrcRegs++] = _destRegIdx[x];
}
+ flags[IsCondControl] = true;
+ } else {
+ flags[IsUncondControl] = true;
}
}
}};
@@ -202,6 +219,26 @@ def template BranchImmRegConstructor {{
for (int x = 0; x < _numDestRegs; x++) {
_srcRegIdx[_numSrcRegs++] = _destRegIdx[x];
}
+ flags[IsCondControl] = true;
+ } else {
+ flags[IsUncondControl] = true;
}
}
}};
+
+def template BranchTarget {{
+
+ ArmISA::PCState
+ %(class_name)s::branchTarget(const ArmISA::PCState &branchPC) const
+ {
+ %(op_decl)s;
+ %(op_rd)s;
+
+ ArmISA::PCState pcs = branchPC;
+ %(brTgtCode)s
+ pcs.advance();
+ return pcs;
+ }
+}};
+
+
diff --git a/src/arch/arm/isa/templates/macromem.isa b/src/arch/arm/isa/templates/macromem.isa
index b7ca7fa48..a7f7f0da8 100644
--- a/src/arch/arm/isa/templates/macromem.isa
+++ b/src/arch/arm/isa/templates/macromem.isa
@@ -109,6 +109,41 @@ def template MicroNeonMemDeclare {{
////////////////////////////////////////////////////////////////////
//
+// PC = Integer(ura)
+// CPSR = Integer(urb)
+//
+
+def template MicroSetPCCPSRDeclare {{
+ class %(class_name)s : public %(base_class)s
+ {
+ public:
+ %(class_name)s(ExtMachInst machInst,
+ IntRegIndex _ura,
+ IntRegIndex _urb,
+ IntRegIndex _urc);
+ %(BasicExecDeclare)s
+ };
+}};
+
+def template MicroSetPCCPSRConstructor {{
+ %(class_name)s::%(class_name)s(ExtMachInst machInst,
+ IntRegIndex _ura,
+ IntRegIndex _urb,
+ IntRegIndex _urc)
+ : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s,
+ _ura, _urb, _urc)
+ {
+ %(constructor)s;
+ if (!(condCode == COND_AL || condCode == COND_UC)) {
+ for (int x = 0; x < _numDestRegs; x++) {
+ _srcRegIdx[_numSrcRegs++] = _destRegIdx[x];
+ }
+ }
+ }
+}};
+
+////////////////////////////////////////////////////////////////////
+//
// Integer = Integer op Integer microops
//
diff --git a/src/arch/arm/isa/templates/mem.isa b/src/arch/arm/isa/templates/mem.isa
index 3d073b322..dcfd47ace 100644
--- a/src/arch/arm/isa/templates/mem.isa
+++ b/src/arch/arm/isa/templates/mem.isa
@@ -917,9 +917,9 @@ def template CompleteAccDeclare {{
def template RfeConstructor {{
inline %(class_name)s::%(class_name)s(ExtMachInst machInst,
- uint32_t _base, int _mode, bool _wb)
- : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s,
- (IntRegIndex)_base, (AddrMode)_mode, _wb)
+ uint32_t _base, int _mode, bool _wb)
+ : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s,
+ (IntRegIndex)_base, (AddrMode)_mode, _wb)
{
%(constructor)s;
if (!(condCode == COND_AL || condCode == COND_UC)) {
@@ -928,12 +928,18 @@ def template RfeConstructor {{
}
}
#if %(use_uops)d
- assert(numMicroops >= 2);
- uops = new StaticInstPtr[numMicroops];
- uops[0] = new %(acc_name)s(machInst, _base, _mode, _wb);
- uops[0]->setDelayedCommit();
- uops[1] = new %(wb_decl)s;
- uops[1]->setLastMicroop();
+ uops = new StaticInstPtr[1 + %(use_wb)d + %(use_pc)d];
+ int uopIdx = 0;
+ uops[uopIdx] = new %(acc_name)s(machInst, _base, _mode, _wb);
+ uops[uopIdx]->setDelayedCommit();
+#if %(use_wb)d
+ uops[++uopIdx] = new %(wb_decl)s;
+ uops[uopIdx]->setDelayedCommit();
+#endif
+#if %(use_pc)d
+ uops[++uopIdx] = new %(pc_decl)s;
+#endif
+ uops[uopIdx]->setLastMicroop();
#endif
}
}};
diff --git a/src/arch/arm/isa/templates/pred.isa b/src/arch/arm/isa/templates/pred.isa
index c9e7b1803..2a4bd9dab 100644
--- a/src/arch/arm/isa/templates/pred.isa
+++ b/src/arch/arm/isa/templates/pred.isa
@@ -170,6 +170,38 @@ def template PredOpExecute {{
}
}};
+def template QuiescePredOpExecute {{
+ Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, Trace::InstRecord *traceData) const
+ {
+ Fault fault = NoFault;
+ uint64_t resTemp = 0;
+ resTemp = resTemp;
+ %(op_decl)s;
+ %(op_rd)s;
+
+ if (%(predicate_test)s)
+ {
+ %(code)s;
+ if (fault == NoFault)
+ {
+ %(op_wb)s;
+ }
+ } else {
+ xc->setPredicate(false);
+#if FULL_SYSTEM
+ PseudoInst::quiesceSkip(xc->tcBase());
+#endif
+ }
+
+ if (fault == NoFault && machInst.itstateMask != 0&&
+ (!isMicroop() || isLastMicroop())) {
+ xc->setMiscReg(MISCREG_ITSTATE, machInst.newItstate);
+ }
+
+ return fault;
+ }
+}};
+
def template DataDecode {{
if (machInst.opcode4 == 0) {
if (machInst.sField == 0)
diff --git a/src/arch/arm/linux/process.cc b/src/arch/arm/linux/process.cc
index e3455d211..fc48ec12d 100644
--- a/src/arch/arm/linux/process.cc
+++ b/src/arch/arm/linux/process.cc
@@ -197,7 +197,7 @@ SyscallDesc ArmLinuxProcess::syscallDescs[] = {
/* 117 */ SyscallDesc("ipc", unimplementedFunc),
/* 118 */ SyscallDesc("fsync", unimplementedFunc),
/* 119 */ SyscallDesc("sigreturn", unimplementedFunc),
- /* 120 */ SyscallDesc("clone", unimplementedFunc),
+ /* 120 */ SyscallDesc("clone", cloneFunc),
/* 121 */ SyscallDesc("setdomainname", unimplementedFunc),
/* 122 */ SyscallDesc("uname", unameFunc),
/* 123 */ SyscallDesc("unused#123", unimplementedFunc),
@@ -239,7 +239,7 @@ SyscallDesc ArmLinuxProcess::syscallDescs[] = {
/* 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),
+ /* 162 */ SyscallDesc("nanosleep", ignoreWarnOnceFunc),
/* 163 */ SyscallDesc("mremap", mremapFunc<ArmLinux>), // ARM-specific
/* 164 */ SyscallDesc("setresuid", unimplementedFunc),
/* 165 */ SyscallDesc("getresuid", unimplementedFunc),
@@ -251,8 +251,8 @@ SyscallDesc ArmLinuxProcess::syscallDescs[] = {
/* 171 */ SyscallDesc("getresgid", unimplementedFunc),
/* 172 */ SyscallDesc("prctl", unimplementedFunc),
/* 173 */ SyscallDesc("rt_sigreturn", unimplementedFunc),
- /* 174 */ SyscallDesc("rt_sigaction", ignoreFunc),
- /* 175 */ SyscallDesc("rt_sigprocmask", unimplementedFunc),
+ /* 174 */ SyscallDesc("rt_sigaction", ignoreWarnOnceFunc),
+ /* 175 */ SyscallDesc("rt_sigprocmask", ignoreWarnOnceFunc),
/* 176 */ SyscallDesc("rt_sigpending", unimplementedFunc),
/* 177 */ SyscallDesc("rt_sigtimedwait", unimplementedFunc),
/* 178 */ SyscallDesc("rt_sigqueueinfo", ignoreFunc),
@@ -317,7 +317,7 @@ SyscallDesc ArmLinuxProcess::syscallDescs[] = {
/* 237 */ SyscallDesc("fremovexattr", unimplementedFunc),
/* 238 */ SyscallDesc("tkill", unimplementedFunc),
/* 239 */ SyscallDesc("sendfile64", unimplementedFunc),
- /* 240 */ SyscallDesc("futex", unimplementedFunc),
+ /* 240 */ SyscallDesc("futex", ignoreWarnOnceFunc),
/* 241 */ SyscallDesc("sched_setaffinity", unimplementedFunc),
/* 242 */ SyscallDesc("sched_getaffinity", unimplementedFunc),
/* 243 */ SyscallDesc("io_setup", unimplementedFunc),
@@ -456,6 +456,7 @@ setTLSFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
tc->getMemPort()->writeBlob(ArmLinuxProcess::commPage + 0x0ff0,
(uint8_t *)&tlsPtr, sizeof(tlsPtr));
+ tc->setMiscReg(MISCREG_TPIDRURO,tlsPtr);
return 0;
}
@@ -508,7 +509,7 @@ ArmLinuxProcess::startup()
ThreadContext *tc = system->getThreadContext(contextIds[0]);
uint8_t swiNeg1[] = {
- 0xff, 0xff, 0xff, 0xef //swi -1
+ 0xff, 0xff, 0xff, 0xef // swi -1
};
// Fill this page with swi -1 so we'll no if we land in it somewhere.
@@ -521,7 +522,8 @@ ArmLinuxProcess::startup()
// @todo Add a barrrier in this code
uint8_t memory_barrier[] =
{
- 0x0e, 0xf0, 0xa0, 0xe1 //usr_ret lr
+ 0x5f, 0xf0, 0x7f, 0xf5, // dmb
+ 0x0e, 0xf0, 0xa0, 0xe1 // return
};
tc->getMemPort()->writeBlob(commPage + 0x0fa0, memory_barrier,
sizeof(memory_barrier));
@@ -531,18 +533,22 @@ ArmLinuxProcess::startup()
// @todo replace this with ldrex/strex and dmb
uint8_t cmpxchg[] =
{
- 0x00, 0x30, 0x92, 0xe5, //ldr r3, [r2]
- 0x00, 0x30, 0x53, 0xe0, //subs r3, r3, r0
- 0x00, 0x10, 0x82, 0x05, //streq r1, [r2]
- 0x03, 0x00, 0xa0, 0xe1, //mov r0, r3
- 0x0e, 0xf0, 0xa0, 0xe1 //usr_ret lr
+ 0x9f, 0x3f, 0x92, 0xe1, // ldrex r3, [r2]
+ 0x00, 0x30, 0x53, 0xe0, // subs r3, r3, r0
+ 0x91, 0x3f, 0x82, 0x01, // strexeq r3, r1, [r2]
+ 0x01, 0x00, 0x33, 0x03, // teqeq r3, #1
+ 0xfa, 0xff, 0xff, 0x0a, // beq 1b
+ 0x00, 0x00, 0x73, 0xe2, // rsbs r0, r3, #0
+ 0x5f, 0xf0, 0x7f, 0xf5, // dmb
+ 0x0e, 0xf0, 0xa0, 0xe1 // return
};
tc->getMemPort()->writeBlob(commPage + 0x0fc0, cmpxchg, sizeof(cmpxchg));
uint8_t get_tls[] =
{
- 0x08, 0x00, 0x9f, 0xe5, //ldr r0, [pc, #(16 - 8)]
- 0x0e, 0xf0, 0xa0, 0xe1 //usr_ret lr
+ // read user read-only thread id register
+ 0x70, 0x0f, 0x1d, 0xee, // mrc p15, 0, r0, c13, c0, 3
+ 0x0e, 0xf0, 0xa0, 0xe1 // return
};
tc->getMemPort()->writeBlob(commPage + 0x0fe0, get_tls, sizeof(get_tls));
}
diff --git a/src/arch/arm/linux/system.cc b/src/arch/arm/linux/system.cc
index 38024c058..7aff2b6ef 100644
--- a/src/arch/arm/linux/system.cc
+++ b/src/arch/arm/linux/system.cc
@@ -47,9 +47,11 @@
#include "base/loader/object_file.hh"
#include "base/loader/symtab.hh"
#include "cpu/thread_context.hh"
+#include "kern/linux/events.hh"
#include "mem/physical.hh"
using namespace ArmISA;
+using namespace Linux;
LinuxArmSystem::LinuxArmSystem(Params *p)
: ArmSystem(p)
@@ -96,6 +98,24 @@ LinuxArmSystem::LinuxArmSystem(Params *p)
if (!kernelPanicEvent)
panic("could not find kernel symbol \'panic\'");
#endif
+
+ // With ARM udelay() is #defined to __udelay
+ Addr addr = 0;
+ if (kernelSymtab->findAddress("__udelay", addr)) {
+ uDelaySkipEvent = new UDelayEvent(&pcEventQueue, "__udelay",
+ fixFuncEventAddr(addr), 1000, 0);
+ } else {
+ panic("couldn't find kernel symbol \'udelay\'");
+ }
+
+ // constant arguments to udelay() have some precomputation done ahead of
+ // time. Constant comes from code.
+ if (kernelSymtab->findAddress("__const_udelay", addr)) {
+ constUDelaySkipEvent = new UDelayEvent(&pcEventQueue, "__const_udelay",
+ fixFuncEventAddr(addr), 1000, 107374);
+ } else {
+ panic("couldn't find kernel symbol \'udelay\'");
+ }
}
void
@@ -115,6 +135,10 @@ LinuxArmSystem::initState()
LinuxArmSystem::~LinuxArmSystem()
{
+ if (uDelaySkipEvent)
+ delete uDelaySkipEvent;
+ if (constUDelaySkipEvent)
+ delete constUDelaySkipEvent;
}
LinuxArmSystem *
diff --git a/src/arch/arm/linux/system.hh b/src/arch/arm/linux/system.hh
index 4e5ebcd73..2ef65fea2 100644
--- a/src/arch/arm/linux/system.hh
+++ b/src/arch/arm/linux/system.hh
@@ -74,6 +74,19 @@ class LinuxArmSystem : public ArmSystem
/** Event to halt the simulator if the kernel calls panic() */
BreakPCEvent *kernelPanicEvent;
#endif
+ /**
+ * PC based event to skip udelay(<time>) calls and quiesce the
+ * processor for the appropriate amount of time. This is not functionally
+ * required but does speed up simulation.
+ */
+ Linux::UDelayEvent *uDelaySkipEvent;
+
+ /** Another PC based skip event for const_udelay(). Similar to the udelay
+ * skip, but this function precomputes the first multiply that is done
+ * in the generic case since the parameter is known at compile time.
+ * Thus we need to do some division to get back to us.
+ */
+ Linux::UDelayEvent *constUDelaySkipEvent;
};
#endif // __ARCH_ARM_LINUX_SYSTEM_HH__
diff --git a/src/arch/arm/miscregs.hh b/src/arch/arm/miscregs.hh
index 90b4fd999..47495a4e7 100644
--- a/src/arch/arm/miscregs.hh
+++ b/src/arch/arm/miscregs.hh
@@ -165,6 +165,12 @@ namespace ArmISA
MISCREG_PMUSERENR,
MISCREG_PMINTENSET,
MISCREG_PMINTENCLR,
+ MISCREG_ID_ISAR0,
+ MISCREG_ID_ISAR1,
+ MISCREG_ID_ISAR2,
+ MISCREG_ID_ISAR3,
+ MISCREG_ID_ISAR4,
+ MISCREG_ID_ISAR5,
MISCREG_CP15_UNIMP_START,
MISCREG_TCMTR = MISCREG_CP15_UNIMP_START,
MISCREG_ID_PFR1,
@@ -173,12 +179,6 @@ namespace ArmISA
MISCREG_ID_MMFR1,
MISCREG_ID_MMFR2,
MISCREG_ID_MMFR3,
- MISCREG_ID_ISAR0,
- MISCREG_ID_ISAR1,
- MISCREG_ID_ISAR2,
- MISCREG_ID_ISAR3,
- MISCREG_ID_ISAR4,
- MISCREG_ID_ISAR5,
MISCREG_AIDR,
MISCREG_ADFSR,
MISCREG_AIFSR,
@@ -233,13 +233,12 @@ namespace ArmISA
"pmswinc", "pmselr", "pmceid0",
"pmceid1", "pmc_other", "pmxevcntr",
"pmuserenr", "pmintenset", "pmintenclr",
+ "id_isar0", "id_isar1", "id_isar2", "id_isar3", "id_isar4", "id_isar5",
// Unimplemented below
"tcmtr",
"id_pfr1", "id_dfr0", "id_afr0",
"id_mmfr1", "id_mmfr2", "id_mmfr3",
- "id_isar0", "id_isar1", "id_isar2", "id_isar3", "id_isar4", "id_isar5",
- "aidr",
- "adfsr", "aifsr",
+ "aidr", "adfsr", "aifsr",
"dcimvac", "dcisw", "mccsw",
"dccmvau",
"nsacr",
diff --git a/src/arch/arm/predecoder.hh b/src/arch/arm/predecoder.hh
index a99e38ce7..08e1676c0 100644
--- a/src/arch/arm/predecoder.hh
+++ b/src/arch/arm/predecoder.hh
@@ -83,6 +83,12 @@ namespace ArmISA
predAddrValid = false;
}
+ void reset(const ExtMachInst &old_emi)
+ {
+ reset();
+ itstate = old_emi.newItstate;
+ }
+
Predecoder(ThreadContext * _tc) :
tc(_tc), data(0)
{
@@ -122,17 +128,17 @@ namespace ArmISA
outOfBytes = true;
}
- bool needMoreBytes()
+ bool needMoreBytes() const
{
return outOfBytes;
}
- bool extMachInstReady()
+ bool extMachInstReady() const
{
return emiReady;
}
- int getInstSize()
+ int getInstSize() const
{
return (!emi.thumb || emi.bigThumb) ? 4 : 2;
}
@@ -145,6 +151,7 @@ namespace ArmISA
pc.npc(pc.pc() + getInstSize());
predAddrValid = true;
predAddr = pc.pc() + getInstSize();
+ pc.size(getInstSize());
emi = 0;
emiReady = false;
return thisEmi;
diff --git a/src/arch/arm/types.hh b/src/arch/arm/types.hh
index e6865e280..b4ef07d8a 100644
--- a/src/arch/arm/types.hh
+++ b/src/arch/arm/types.hh
@@ -203,6 +203,7 @@ namespace ArmISA
uint8_t flags;
uint8_t nextFlags;
uint8_t forcedItStateValue;
+ uint8_t _size;
bool forcedItStateValid;
public:
PCState() : flags(0), nextFlags(0), forcedItStateValue(0), forcedItStateValid(false)
@@ -248,6 +249,16 @@ namespace ArmISA
nextFlags &= ~ThumbBit;
}
+ void size(uint8_t s) { _size = s; }
+ uint8_t size() const { return _size; }
+
+ bool
+ branching() const
+ {
+ return ((this->pc() + this->size()) != this->npc());
+ }
+
+
bool
jazelle() const
{
@@ -392,6 +403,7 @@ namespace ArmISA
{
Base::serialize(os);
SERIALIZE_SCALAR(flags);
+ SERIALIZE_SCALAR(_size);
SERIALIZE_SCALAR(nextFlags);
SERIALIZE_SCALAR(forcedItStateValue);
SERIALIZE_SCALAR(forcedItStateValid);
@@ -402,6 +414,7 @@ namespace ArmISA
{
Base::unserialize(cp, section);
UNSERIALIZE_SCALAR(flags);
+ UNSERIALIZE_SCALAR(_size);
UNSERIALIZE_SCALAR(nextFlags);
UNSERIALIZE_SCALAR(forcedItStateValue);
UNSERIALIZE_SCALAR(forcedItStateValid);
diff --git a/src/arch/mips/predecoder.hh b/src/arch/mips/predecoder.hh
index 4220b768c..110493cc5 100644
--- a/src/arch/mips/predecoder.hh
+++ b/src/arch/mips/predecoder.hh
@@ -75,6 +75,12 @@ class Predecoder
emiIsReady = false;
}
+ void
+ reset(const ExtMachInst &old_emi)
+ {
+ reset();
+ }
+
//Use this to give data to the predecoder. This should be used
//when there is control flow.
void
diff --git a/src/arch/power/predecoder.hh b/src/arch/power/predecoder.hh
index 8b1089095..c10bc51bf 100644
--- a/src/arch/power/predecoder.hh
+++ b/src/arch/power/predecoder.hh
@@ -82,6 +82,12 @@ class Predecoder
emiIsReady = false;
}
+ void
+ reset(const ExtMachInst &old_emi)
+ {
+ reset();
+ }
+
// Use this to give data to the predecoder. This should be used
// when there is control flow.
void
diff --git a/src/arch/sparc/predecoder.hh b/src/arch/sparc/predecoder.hh
index 670c547d0..082adeb72 100644
--- a/src/arch/sparc/predecoder.hh
+++ b/src/arch/sparc/predecoder.hh
@@ -68,12 +68,19 @@ class Predecoder
}
void process() {}
+
void
reset()
{
emiIsReady = false;
}
+ void
+ reset(const ExtMachInst &old_emi)
+ {
+ reset();
+ }
+
// Use this to give data to the predecoder. This should be used
// when there is control flow.
void
diff --git a/src/arch/x86/predecoder.hh b/src/arch/x86/predecoder.hh
index 5c67e28e1..790453b98 100644
--- a/src/arch/x86/predecoder.hh
+++ b/src/arch/x86/predecoder.hh
@@ -174,6 +174,12 @@ namespace X86ISA
state = ResetState;
}
+ void
+ reset(const ExtMachInst &old_emi)
+ {
+ reset();
+ }
+
ThreadContext * getTC()
{
return tc;