arch-power: Add MSR and associated dependencies
This adds the definition of the Machine State Register (MSR) in preparation for multi-mode support. The MSR has bits that define the state of the processor. This defines all the bitfields and sets the ones that are typically used for userspace environments. In preparation for multi-mode support, the SF and LE bits are used by instructions to check if the simulation is running in 64-bit mode and if memory accesses are to be performed in little endian byte order respectively. This introduces changes in areas such as target address computation for branch instructions, carry and overflow computation for arithmetic instructions, etc. Change-Id: If9ac69415ca85b0c873bd8579e7d1bd2219eac62 Signed-off-by: Sandipan Das <sandipan@linux.ibm.com> Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/40943 Reviewed-by: Boris Shingarov <shingarov@labware.com> Maintainer: Boris Shingarov <shingarov@labware.com> Tested-by: kokoro <noreply+kokoro@google.com>
This commit is contained in:
committed by
Boris Shingarov
parent
0e8238d717
commit
be3a57e68a
@@ -27,6 +27,8 @@
|
||||
*/
|
||||
|
||||
#include "arch/power/insts/branch.hh"
|
||||
#include "arch/power/regs/int.hh"
|
||||
#include "arch/power/regs/misc.hh"
|
||||
|
||||
#include "base/loader/symtab.hh"
|
||||
#include "cpu/thread_context.hh"
|
||||
@@ -54,12 +56,17 @@ PCDependentDisassembly::disassemble(
|
||||
|
||||
|
||||
PowerISA::PCState
|
||||
BranchOp::branchTarget(const PowerISA::PCState &pc) const
|
||||
BranchOp::branchTarget(ThreadContext *tc) const
|
||||
{
|
||||
Msr msr = tc->readIntReg(INTREG_MSR);
|
||||
Addr addr;
|
||||
|
||||
if (aa)
|
||||
return li;
|
||||
addr = li;
|
||||
else
|
||||
return pc.pc() + li;
|
||||
addr = tc->pcState().pc() + li;
|
||||
|
||||
return msr.sf ? addr : addr & UINT32_MAX;
|
||||
}
|
||||
|
||||
|
||||
@@ -97,13 +104,17 @@ BranchOp::generateDisassembly(
|
||||
|
||||
|
||||
PowerISA::PCState
|
||||
BranchDispCondOp::branchTarget(const PowerISA::PCState &pc) const
|
||||
BranchDispCondOp::branchTarget(ThreadContext *tc) const
|
||||
{
|
||||
if (aa) {
|
||||
return bd;
|
||||
} else {
|
||||
return pc.pc() + bd;
|
||||
}
|
||||
Msr msr = tc->readIntReg(INTREG_MSR);
|
||||
Addr addr;
|
||||
|
||||
if (aa)
|
||||
addr = bd;
|
||||
else
|
||||
addr = tc->pcState().pc() + bd;
|
||||
|
||||
return msr.sf ? addr : addr & UINT32_MAX;
|
||||
}
|
||||
|
||||
|
||||
@@ -146,8 +157,9 @@ BranchDispCondOp::generateDisassembly(
|
||||
PowerISA::PCState
|
||||
BranchRegCondOp::branchTarget(ThreadContext *tc) const
|
||||
{
|
||||
Addr addr = tc->readIntReg(srcRegIdx(_numSrcRegs - 1).index());
|
||||
return addr & -4ULL;
|
||||
Msr msr = tc->readIntReg(INTREG_MSR);
|
||||
Addr addr = tc->readIntReg(srcRegIdx(_numSrcRegs - 1).index()) & -4ULL;
|
||||
return msr.sf ? addr : addr & UINT32_MAX;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -87,7 +87,7 @@ class BranchOp : public PCDependentDisassembly
|
||||
{
|
||||
}
|
||||
|
||||
PowerISA::PCState branchTarget(const PowerISA::PCState &pc) const override;
|
||||
PowerISA::PCState branchTarget(ThreadContext *tc) const override;
|
||||
|
||||
/// Explicitly import the otherwise hidden branchTarget
|
||||
using StaticInst::branchTarget;
|
||||
@@ -158,7 +158,7 @@ class BranchDispCondOp : public BranchCondOp
|
||||
{
|
||||
}
|
||||
|
||||
PowerISA::PCState branchTarget(const PowerISA::PCState &pc) const override;
|
||||
PowerISA::PCState branchTarget(ThreadContext *tc) const override;
|
||||
|
||||
/// Explicitly import the otherwise hidden branchTarget
|
||||
using StaticInst::branchTarget;
|
||||
|
||||
@@ -87,11 +87,11 @@ let {{
|
||||
|
||||
# Check the condition register (CR) allows the branch to be taken.
|
||||
def GetCondCode(br_code):
|
||||
cond_code = 'if (condOk(CR)) {\n'
|
||||
cond_code = 'Msr msr = MSR;\n'
|
||||
cond_code += 'if (condOk(CR)) {\n'
|
||||
cond_code += ' ' + br_code + '\n'
|
||||
cond_code += '} else {\n'
|
||||
cond_code += ' NIA = NIA;\n'
|
||||
cond_code += '}\n'
|
||||
cond_code += 'NIA = msr.sf ? NIA : NIA & UINT32_MAX;\n'
|
||||
return cond_code
|
||||
|
||||
# Check the condition register (CR) and count register (CTR) allow the
|
||||
@@ -99,11 +99,11 @@ def GetCondCode(br_code):
|
||||
# register too. This takes place in ctrOk within BranchCondOp classes.
|
||||
def GetCtrCondCode(br_code):
|
||||
cond_code = 'uint64_t ctr = CTR;\n'
|
||||
cond_code += 'Msr msr = MSR;\n'
|
||||
cond_code += 'if (ctrOk(ctr) && condOk(CR)) {\n'
|
||||
cond_code += ' ' + br_code + '\n'
|
||||
cond_code += '} else {\n'
|
||||
cond_code += ' NIA = NIA;\n'
|
||||
cond_code += '}\n'
|
||||
cond_code += 'NIA = msr.sf ? NIA : NIA & UINT32_MAX;\n'
|
||||
cond_code += 'CTR = ctr;\n'
|
||||
return cond_code
|
||||
|
||||
|
||||
@@ -38,38 +38,60 @@ readXERCode = 'GEM5_VAR_USED Xer xer = XER;'
|
||||
setXERCode = 'XER = xer;'
|
||||
|
||||
computeCR0Code = '''
|
||||
PowerISA::Cr cr = CR;
|
||||
cr.cr0 = makeCRFieldSigned(%(result)s, 0, xer.so);
|
||||
{
|
||||
Cr cr = CR;
|
||||
Msr msr = MSR;
|
||||
cr.cr0 = msr.sf ?
|
||||
makeCRFieldSigned((int64_t)%(result)s, 0, xer.so) :
|
||||
makeCRFieldSigned((int32_t)%(result)s, 0, xer.so);
|
||||
CR = cr;
|
||||
}
|
||||
'''
|
||||
|
||||
computeCACode = '''
|
||||
if (findCarry(64, %(result)s, %(inputa)s, %(inputb)s)) {
|
||||
xer.ca = 1;
|
||||
} else {
|
||||
xer.ca = 0;
|
||||
}
|
||||
|
||||
{
|
||||
Msr msr = MSR;
|
||||
if (findCarry(32, %(result)s, %(inputa)s, %(inputb)s)) {
|
||||
xer.ca = 1;
|
||||
xer.ca32 = 1;
|
||||
} else {
|
||||
xer.ca = 0;
|
||||
xer.ca32 = 0;
|
||||
}
|
||||
|
||||
if (msr.sf) {
|
||||
if (findCarry(64, %(result)s, %(inputa)s, %(inputb)s)) {
|
||||
xer.ca = 1;
|
||||
} else {
|
||||
xer.ca = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
'''
|
||||
|
||||
computeOVCode = '''
|
||||
if (findOverflow(64, %(result)s, %(inputa)s, %(inputb)s)) {
|
||||
xer.ov = 1;
|
||||
xer.so = 1;
|
||||
} else {
|
||||
xer.ov = 0;
|
||||
}
|
||||
|
||||
{
|
||||
Msr msr = MSR;
|
||||
if (findOverflow(32, %(result)s, %(inputa)s, %(inputb)s)) {
|
||||
xer.ov = 1;
|
||||
xer.ov32 = 1;
|
||||
} else {
|
||||
xer.ov = 0;
|
||||
xer.ov32 = 0;
|
||||
}
|
||||
|
||||
if (msr.sf) {
|
||||
if (findOverflow(64, %(result)s, %(inputa)s, %(inputb)s)) {
|
||||
xer.ov = 1;
|
||||
} else {
|
||||
xer.ov = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (xer.ov) {
|
||||
xer.so = 1;
|
||||
}
|
||||
}
|
||||
'''
|
||||
|
||||
setCACode = '''
|
||||
|
||||
@@ -68,13 +68,16 @@ def template LoadExecute {{
|
||||
{
|
||||
Addr EA;
|
||||
Fault fault = NoFault;
|
||||
Msr msr = xc->tcBase()->readIntReg(INTREG_MSR);
|
||||
|
||||
%(op_decl)s;
|
||||
%(op_rd)s;
|
||||
%(ea_code)s;
|
||||
|
||||
if (fault == NoFault) {
|
||||
fault = readMemAtomicBE(xc, traceData, EA, Mem, memAccessFlags);
|
||||
fault = msr.le ?
|
||||
readMemAtomicLE(xc, traceData, EA, Mem, memAccessFlags) :
|
||||
readMemAtomicBE(xc, traceData, EA, Mem, memAccessFlags);
|
||||
%(memacc_code)s;
|
||||
}
|
||||
|
||||
@@ -114,13 +117,17 @@ def template LoadCompleteAcc {{
|
||||
{
|
||||
GEM5_VAR_USED Addr EA;
|
||||
Fault fault = NoFault;
|
||||
Msr msr = xc->tcBase()->readIntReg(INTREG_MSR);
|
||||
|
||||
%(op_decl)s;
|
||||
%(op_rd)s;
|
||||
|
||||
EA = pkt->req->getVaddr();
|
||||
|
||||
getMemBE(pkt, Mem, traceData);
|
||||
if (msr.le)
|
||||
getMemLE(pkt, Mem, traceData);
|
||||
else
|
||||
getMemBE(pkt, Mem, traceData);
|
||||
|
||||
if (fault == NoFault) {
|
||||
%(memacc_code)s;
|
||||
@@ -141,6 +148,7 @@ def template StoreExecute {{
|
||||
{
|
||||
Addr EA;
|
||||
Fault fault = NoFault;
|
||||
Msr msr = xc->tcBase()->readIntReg(INTREG_MSR);
|
||||
|
||||
%(op_decl)s;
|
||||
%(op_rd)s;
|
||||
@@ -151,8 +159,11 @@ def template StoreExecute {{
|
||||
}
|
||||
|
||||
if (fault == NoFault) {
|
||||
fault = writeMemAtomicBE(xc, traceData, Mem, EA, memAccessFlags,
|
||||
NULL);
|
||||
fault = msr.le ?
|
||||
writeMemAtomicLE(xc, traceData, Mem, EA, memAccessFlags,
|
||||
NULL) :
|
||||
writeMemAtomicBE(xc, traceData, Mem, EA, memAccessFlags,
|
||||
NULL);
|
||||
}
|
||||
|
||||
if (fault == NoFault) {
|
||||
@@ -170,6 +181,7 @@ def template StoreInitiateAcc {{
|
||||
{
|
||||
Addr EA;
|
||||
Fault fault = NoFault;
|
||||
Msr msr = xc->tcBase()->readIntReg(INTREG_MSR);
|
||||
|
||||
%(op_decl)s;
|
||||
%(op_rd)s;
|
||||
@@ -180,8 +192,11 @@ def template StoreInitiateAcc {{
|
||||
}
|
||||
|
||||
if (fault == NoFault) {
|
||||
fault = writeMemTimingBE(xc, traceData, Mem, EA, memAccessFlags,
|
||||
NULL);
|
||||
fault = msr.le ?
|
||||
writeMemTimingLE(xc, traceData, Mem, EA, memAccessFlags,
|
||||
NULL) :
|
||||
writeMemTimingBE(xc, traceData, Mem, EA, memAccessFlags,
|
||||
NULL);
|
||||
}
|
||||
|
||||
// Need to write back any potential address register update
|
||||
|
||||
@@ -67,6 +67,7 @@ def operands {{
|
||||
'CTR': ('IntReg', 'ud', 'INTREG_CTR', 'IsInteger', 9),
|
||||
'TAR': ('IntReg', 'ud', 'INTREG_TAR', 'IsInteger', 9),
|
||||
'XER': ('IntReg', 'uw', 'INTREG_XER', 'IsInteger', 9),
|
||||
'MSR': ('IntReg', 'ud', 'INTREG_MSR', 'IsInteger', 9),
|
||||
|
||||
# Setting as IntReg so things are stored as an integer, not double
|
||||
'FPSCR': ('IntReg', 'uw', 'INTREG_FPSCR', 'IsFloating', 9),
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
|
||||
#include "arch/power/page_size.hh"
|
||||
#include "arch/power/regs/int.hh"
|
||||
#include "arch/power/regs/misc.hh"
|
||||
#include "arch/power/types.hh"
|
||||
#include "base/loader/elf_object.hh"
|
||||
#include "base/loader/object_file.hh"
|
||||
@@ -279,6 +280,19 @@ PowerProcess::argsInit(int pageSize)
|
||||
//Set the stack pointer register
|
||||
tc->setIntReg(StackPointerReg, stack_min);
|
||||
|
||||
//Set the machine status for a typical userspace
|
||||
Msr msr = 0;
|
||||
msr.sf = (intSize == 8);
|
||||
msr.hv = 1;
|
||||
msr.ee = 1;
|
||||
msr.pr = 1;
|
||||
msr.me = 1;
|
||||
msr.ir = 1;
|
||||
msr.dr = 1;
|
||||
msr.ri = 1;
|
||||
msr.le = (byteOrder == ByteOrder::little);
|
||||
tc->setIntReg(INTREG_MSR, msr);
|
||||
|
||||
tc->pcState(getStartPC());
|
||||
|
||||
//Align the "stack_min" to a page boundary.
|
||||
|
||||
@@ -38,9 +38,9 @@ namespace PowerISA
|
||||
// Constants Related to the number of registers
|
||||
const int NumIntArchRegs = 32;
|
||||
|
||||
// CR, XER, LR, CTR, TAR, FPSCR, RSV, RSV-LEN, RSV-ADDR
|
||||
// CR, XER, LR, CTR, TAR, FPSCR, MSR, RSV, RSV-LEN, RSV-ADDR
|
||||
// and zero register, which doesn't actually exist but needs a number
|
||||
const int NumIntSpecialRegs = 10;
|
||||
const int NumIntSpecialRegs = 11;
|
||||
|
||||
const int NumIntRegs = NumIntArchRegs + NumIntSpecialRegs;
|
||||
|
||||
@@ -62,6 +62,7 @@ enum MiscIntRegNums
|
||||
INTREG_CTR,
|
||||
INTREG_TAR,
|
||||
INTREG_FPSCR,
|
||||
INTREG_MSR,
|
||||
INTREG_RSV,
|
||||
INTREG_RSV_LEN,
|
||||
INTREG_RSV_ADDR
|
||||
|
||||
@@ -99,6 +99,27 @@ BitUnion32(Fpscr)
|
||||
Bitfield<2,1> rn;
|
||||
EndBitUnion(Fpscr)
|
||||
|
||||
BitUnion64(Msr)
|
||||
Bitfield<63> sf;
|
||||
Bitfield<60> hv;
|
||||
Bitfield<34, 33> ts;
|
||||
Bitfield<32> tm;
|
||||
Bitfield<25> vec;
|
||||
Bitfield<23> vsx;
|
||||
Bitfield<15> ee;
|
||||
Bitfield<14> pr;
|
||||
Bitfield<13> fp;
|
||||
Bitfield<12> me;
|
||||
Bitfield<11> fe0;
|
||||
Bitfield<10, 9> te;
|
||||
Bitfield<8> fe1;
|
||||
Bitfield<5> ir;
|
||||
Bitfield<4> dr;
|
||||
Bitfield<2> pmm;
|
||||
Bitfield<1> ri;
|
||||
Bitfield<0> le;
|
||||
EndBitUnion(Msr)
|
||||
|
||||
} // namespace PowerISA
|
||||
} // namespace gem5
|
||||
|
||||
|
||||
Reference in New Issue
Block a user