summaryrefslogtreecommitdiff
path: root/src/arch/sparc
diff options
context:
space:
mode:
Diffstat (limited to 'src/arch/sparc')
-rw-r--r--src/arch/sparc/asi.cc27
-rw-r--r--src/arch/sparc/faults.cc73
-rw-r--r--src/arch/sparc/isa/decoder.isa96
-rw-r--r--src/arch/sparc/isa/formats/mem/blockmem.isa6
-rw-r--r--src/arch/sparc/isa/includes.isa3
-rw-r--r--src/arch/sparc/regfile.cc6
-rw-r--r--src/arch/sparc/tlb.cc102
-rw-r--r--src/arch/sparc/tlb_map.hh13
-rw-r--r--src/arch/sparc/ua2005.cc2
9 files changed, 173 insertions, 155 deletions
diff --git a/src/arch/sparc/asi.cc b/src/arch/sparc/asi.cc
index a9a778ff6..3d553955f 100644
--- a/src/arch/sparc/asi.cc
+++ b/src/arch/sparc/asi.cc
@@ -179,26 +179,23 @@ namespace SparcISA
(asi == ASI_LDTX_PL) ||
(asi == ASI_LDTX_SL) ||
(asi == ASI_BLK_PL) ||
- (asi == ASI_BLK_SL);
+ (asi == ASI_BLK_SL) ||
+ (asi == ASI_LTX_L);
}
bool AsiIsTwin(ASI asi)
{
return
- (asi == ASI_QUAD_LDD) ||
- (asi == ASI_LDTX_AIUP) ||
- (asi == ASI_LDTX_AIUS) ||
- (asi == ASI_LDTX_REAL) ||
- (asi == ASI_LDTX_N) ||
- (asi == ASI_LDTX_AIUP_L) ||
- (asi == ASI_LDTX_AIUS_L) ||
- (asi == ASI_LDTX_REAL_L) ||
- (asi == ASI_LDTX_NL) ||
- (asi == ASI_LDTX_P) ||
- (asi == ASI_LDTX_S) ||
- (asi == ASI_LDTX_PL) ||
- (asi == ASI_LDTX_SL) ||
- (asi == ASI_LTX_L);
+ (asi >= ASI_LDTX_AIUP &&
+ asi <= ASI_LDTX_N &&
+ asi != ASI_QUEUE) ||
+ (asi >= ASI_LDTX_AIUP_L &&
+ asi <= ASI_LDTX_NL &&
+ asi != 0x2D) ||
+ asi == ASI_LDTX_P ||
+ asi == ASI_LDTX_S ||
+ asi == ASI_LDTX_PL ||
+ asi == ASI_LDTX_SL;
}
bool AsiIsPartialStore(ASI asi)
diff --git a/src/arch/sparc/faults.cc b/src/arch/sparc/faults.cc
index a74eebafa..825ff40f6 100644
--- a/src/arch/sparc/faults.cc
+++ b/src/arch/sparc/faults.cc
@@ -312,6 +312,11 @@ void doREDFault(ThreadContext *tc, TrapType tt)
TL++;
+ if (bits(PSTATE, 3,3)) {
+ PC &= mask(32);
+ NPC &= mask(32);
+ }
+
//set TSTATE.gl to gl
replaceBits(TSTATE, 42, 40, GL);
//set TSTATE.ccr to ccr
@@ -340,22 +345,8 @@ void doREDFault(ThreadContext *tc, TrapType tt)
//Update GL
tc->setMiscRegWithEffect(MISCREG_GL, min<int>(GL+1, MaxGL));
- //set PSTATE.mm to 00
- //set PSTATE.pef to 1
- PSTATE |= (1 << 4);
- //set PSTATE.am to 0
- PSTATE &= ~(1 << 3);
-/* //set PSTATE.priv to 0
- PSTATE &= ~(1 << 2);*/
- //set PSTATE.ie to 0
- //PSTATE.priv is set to 1 here. The manual says it should be 0, but
- //Legion sets it to 1.
- PSTATE |= (1 << 2);
- //set PSTATE.cle to 0
- PSTATE &= ~(1 << 9);
- //PSTATE.tle is unchanged
- //XXX Where is the tct bit?
- //set PSTATE.tct to 0
+ PSTATE = mbits(PSTATE, 2, 2); // just save the priv bit
+ PSTATE |= (1 << 4); //set PSTATE.pef to 1
tc->setMiscReg(MISCREG_PSTATE, PSTATE);
//set HPSTATE.red to 1
@@ -404,6 +395,11 @@ void doNormalFault(ThreadContext *tc, TrapType tt, bool gotoHpriv)
MiscReg PC = tc->readPC();
MiscReg NPC = tc->readNextPC();
+ if (bits(PSTATE, 3,3)) {
+ PC &= mask(32);
+ NPC &= mask(32);
+ }
+
//Increment the trap level
TL++;
tc->setMiscReg(MISCREG_TL, TL);
@@ -442,46 +438,27 @@ void doNormalFault(ThreadContext *tc, TrapType tt, bool gotoHpriv)
tc->setMiscRegWithEffect(MISCREG_GL, min<int>(GL+1, MaxGL));
//PSTATE.mm is unchanged
- //PSTATE.pef = whether or not an fpu is present
- //XXX We'll say there's one present, even though there aren't
- //implementations for a decent number of the instructions
- PSTATE |= (1 << 4);
- //PSTATE.am = 0
- PSTATE &= ~(1 << 3);
- if (!gotoHpriv)
- {
- //PSTATE.priv = 1
- PSTATE |= (1 << 2);
- //PSTATE.cle = PSTATE.tle
- replaceBits(PSTATE, 9, 9, PSTATE >> 8);
- }
- else
- {
- //PSTATE.priv = 0
- //PSTATE.priv is set to 1 here. The manual says it should be 0, but
- //Legion sets it to 1.
- PSTATE |= (1 << 2);
- //PSTATE.cle = 0
- PSTATE &= ~(1 << 9);
- }
- //PSTATE.ie = 0
- PSTATE &= ~(1 << 1);
+ PSTATE |= (1 << 4); //PSTATE.pef = whether or not an fpu is present
+ PSTATE &= ~(1 << 3); //PSTATE.am = 0
+ PSTATE &= ~(1 << 1); //PSTATE.ie = 0
//PSTATE.tle is unchanged
//PSTATE.tct = 0
- //XXX Where exactly is this field?
- tc->setMiscReg(MISCREG_PSTATE, PSTATE);
if (gotoHpriv)
{
- //HPSTATE.red = 0
- HPSTATE &= ~(1 << 5);
- //HPSTATE.hpriv = 1
- HPSTATE |= (1 << 2);
- //HPSTATE.ibe = 0
- HPSTATE &= ~(1 << 10);
+ PSTATE &= ~(1 << 9); // PSTATE.cle = 0
+ //The manual says PSTATE.priv should be 0, but Legion leaves it alone
+ HPSTATE &= ~(1 << 5); //HPSTATE.red = 0
+ HPSTATE |= (1 << 2); //HPSTATE.hpriv = 1
+ HPSTATE &= ~(1 << 10); //HPSTATE.ibe = 0
//HPSTATE.tlz is unchanged
tc->setMiscReg(MISCREG_HPSTATE, HPSTATE);
+ } else { // we are going to priv
+ PSTATE |= (1 << 2); //PSTATE.priv = 1
+ replaceBits(PSTATE, 9, 9, PSTATE >> 8); //PSTATE.cle = PSTATE.tle
}
+ tc->setMiscReg(MISCREG_PSTATE, PSTATE);
+
bool changedCWP = true;
if (tt == 0x24)
diff --git a/src/arch/sparc/isa/decoder.isa b/src/arch/sparc/isa/decoder.isa
index bd1a44342..425ebc9d0 100644
--- a/src/arch/sparc/isa/decoder.isa
+++ b/src/arch/sparc/isa/decoder.isa
@@ -163,7 +163,10 @@ decode OP default Unknown::unknown()
0x6: Trap::fbfcc({{fault = new FpDisabled;}});
}
0x1: BranchN::call(30, {{
- R15 = xc->readPC();
+ if (Pstate<3:>)
+ R15 = (xc->readPC())<31:0>;
+ else
+ R15 = xc->readPC();
NNPC = R15 + disp;
}});
0x2: decode OP3 {
@@ -183,7 +186,7 @@ decode OP default Unknown::unknown()
Y = Rd<63:32>;
}});
0x0B: smul({{
- Rd.sdw = Rs1.sdw<31:0> * Rs2_or_imm13<31:0>;
+ Rd.sdw = sext<32>(Rs1.sdw) * sext<32>(Rs2_or_imm13);
Y = Rd.sdw<63:32>;
}});
0x0C: subc({{Rd.sdw = Rs1.sdw + (~Rs2_or_imm13) + 1 - Ccr<0:0>}});
@@ -206,10 +209,10 @@ decode OP default Unknown::unknown()
else
{
Rd.udw = ((int64_t)((Y << 32) | Rs1.sdw<31:0>)) / Rs2_or_imm13.sdw;
- if(Rd.udw<63:31> != 0)
+ if((int64_t)Rd.udw >= std::numeric_limits<int32_t>::max())
Rd.udw = 0x7FFFFFFF;
- else if(Rd.udw<63:> && Rd.udw<62:31> != 0xFFFFFFFF)
- Rd.udw = 0xFFFFFFFF80000000ULL;
+ else if((int64_t)Rd.udw <= std::numeric_limits<int32_t>::min())
+ Rd.udw = ULL(0xFFFFFFFF80000000);
}
}});
}
@@ -254,7 +257,7 @@ decode OP default Unknown::unknown()
{{0}},{{0}},{{0}},{{0}});
0x1B: smulcc({{
int64_t resTemp;
- Rd = resTemp = Rs1.sdw<31:0> * Rs2_or_imm13.sdw<31:0>;
+ Rd = resTemp = sext<32>(Rs1.sdw) * sext<32>(Rs2_or_imm13);
Y = resTemp<63:32>;}},
{{0}},{{0}},{{0}},{{0}});
0x1C: subccc({{
@@ -293,10 +296,10 @@ decode OP default Unknown::unknown()
else
{
Rd = (int64_t)((Y << 32) | Rs1.sdw<31:0>) / val2;
- overflow = (Rd<63:31> != 0);
- underflow = (Rd<63:> && Rd<62:31> != 0xFFFFFFFF);
+ overflow = ((int64_t)Rd >= std::numeric_limits<int32_t>::max());
+ underflow = ((int64_t)Rd <= std::numeric_limits<int32_t>::min());
if(overflow) Rd = 0x7FFFFFFF;
- else if(underflow) Rd = 0xFFFFFFFF80000000ULL;
+ else if(underflow) Rd = ULL(0xFFFFFFFF80000000);
} }},
{{0}},
{{overflow || underflow}},
@@ -373,7 +376,7 @@ decode OP default Unknown::unknown()
0x1: srax({{Rd = Rs1.sdw >> (I ? SHCNT64 : Rs2<5:0>);}});
}
0x28: decode RS1 {
- 0x00: NoPriv::rdy({{Rd = Y;}});
+ 0x00: NoPriv::rdy({{Rd = Y<31:0>;}});
//1 should cause an illegal instruction exception
0x02: NoPriv::rdccr({{Rd = Ccr;}});
0x03: NoPriv::rdasi({{Rd = Asi;}});
@@ -468,12 +471,12 @@ decode OP default Unknown::unknown()
//0x11-0x1F should cause an illegal instruction exception
}
0x2B: BasicOperate::flushw({{
- if(NWindows - 2 - Cansave == 0)
+ if(NWindows - 2 - Cansave != 0)
{
if(Otherwin)
- fault = new SpillNOther(Wstate<5:3>);
+ fault = new SpillNOther(4*Wstate<5:3>);
else
- fault = new SpillNNormal(Wstate<2:0>);
+ fault = new SpillNNormal(4*Wstate<2:0>);
}
}});
0x2C: decode MOVCC3
@@ -523,7 +526,7 @@ decode OP default Unknown::unknown()
0x7: movrge({{Rd = (Rs1.sdw >= 0) ? Rs2_or_imm10 : Rd;}});
}
0x30: decode RD {
- 0x00: NoPriv::wry({{Y = Rs1 ^ Rs2_or_imm13;}});
+ 0x00: NoPriv::wry({{Y = (Rs1 ^ Rs2_or_imm13)<31:0>;}});
//0x01 should cause an illegal instruction exception
0x02: NoPriv::wrccr({{Ccr = Rs1 ^ Rs2_or_imm13;}});
0x03: NoPriv::wrasi({{Asi = Rs1 ^ Rs2_or_imm13;}});
@@ -578,6 +581,9 @@ decode OP default Unknown::unknown()
Cansave = Cansave - 1;
else
Otherwin = Otherwin - 1;
+
+ if(Cleanwin < NWindows - 1)
+ Cleanwin = Cleanwin + 1;
}});
}
0x32: decode RD {
@@ -875,7 +881,10 @@ decode OP default Unknown::unknown()
fault = new MemAddressNotAligned;
else
{
- Rd = xc->readPC();
+ if (Pstate<3:>)
+ Rd = (xc->readPC())<31:0>;
+ else
+ Rd = xc->readPC();
NNPC = target;
}
}});
@@ -893,9 +902,9 @@ decode OP default Unknown::unknown()
if(Canrestore == 0)
{
if(Otherwin)
- fault = new FillNOther(Wstate<5:3>);
+ fault = new FillNOther(4*Wstate<5:3>);
else
- fault = new FillNNormal(Wstate<2:0>);
+ fault = new FillNNormal(4*Wstate<2:0>);
}
else
{
@@ -949,9 +958,9 @@ decode OP default Unknown::unknown()
if(Cansave == 0)
{
if(Otherwin)
- fault = new SpillNOther(Wstate<5:3>);
+ fault = new SpillNOther(4*Wstate<5:3>);
else
- fault = new SpillNNormal(Wstate<2:0>);
+ fault = new SpillNNormal(4*Wstate<2:0>);
//Cwp = (Cwp + 2) % NWindows;
}
else if(Cleanwin - Canrestore == 0)
@@ -975,9 +984,9 @@ decode OP default Unknown::unknown()
if(Canrestore == 0)
{
if(Otherwin)
- fault = new FillNOther(Wstate<5:3>);
+ fault = new FillNOther(4*Wstate<5:3>);
else
- fault = new FillNNormal(Wstate<2:0>);
+ fault = new FillNNormal(4*Wstate<2:0>);
}
else
{
@@ -1049,39 +1058,49 @@ decode OP default Unknown::unknown()
0x0B: ldx({{Rd = (int64_t)Mem.sdw;}});
}
0x0D: LoadStore::ldstub(
- {{Rd = Mem.ub;}},
- {{Mem.ub = 0xFF;}});
+ {{uReg0 = Mem.ub;}},
+ {{Rd.ub = uReg0;
+ Mem.ub = 0xFF;}});
0x0E: Store::stx({{Mem.udw = Rd}});
0x0F: LoadStore::swap(
- {{uReg0 = Rd.uw;
- Rd.uw = Mem.uw;}},
- {{Mem.uw = uReg0;}});
+ {{ uReg0 = Mem.uw}},
+ {{ Mem.uw = Rd.uw;
+ Rd.uw = uReg0;}});
format LoadAlt {
0x10: lduwa({{Rd = Mem.uw;}}, {{EXT_ASI}});
0x11: lduba({{Rd = Mem.ub;}}, {{EXT_ASI}});
0x12: lduha({{Rd = Mem.uhw;}}, {{EXT_ASI}});
0x13: decode EXT_ASI {
+ //ASI_LDTD_AIUP
+ 0x22: TwinLoad::ldtx_aiup(
+ {{RdTwin.udw = Mem.udw;}}, {{EXT_ASI}});
+ //ASI_LDTD_AIUS
+ 0x23: TwinLoad::ldtx_aius(
+ {{RdTwin.udw = Mem.udw;}}, {{EXT_ASI}});
//ASI_QUAD_LDD
0x24: TwinLoad::ldtx_quad_ldd(
- {{RdTwin.udw = Mem.udw}}, {{EXT_ASI}});
+ {{RdTwin.udw = Mem.udw;}}, {{EXT_ASI}});
//ASI_LDTX_REAL
0x26: TwinLoad::ldtx_real(
- {{RdTwin.udw = Mem.udw}}, {{EXT_ASI}});
+ {{RdTwin.udw = Mem.udw;}}, {{EXT_ASI}});
//ASI_LDTX_N
0x27: TwinLoad::ldtx_n(
- {{RdTwin.udw = Mem.udw}}, {{EXT_ASI}});
+ {{RdTwin.udw = Mem.udw;}}, {{EXT_ASI}});
//ASI_LDTX_L
0x2C: TwinLoad::ldtx_l(
- {{RdTwin.udw = Mem.udw}}, {{EXT_ASI}});
+ {{RdTwin.udw = Mem.udw;}}, {{EXT_ASI}});
//ASI_LDTX_REAL_L
0x2E: TwinLoad::ldtx_real_l(
- {{RdTwin.udw = Mem.udw}}, {{EXT_ASI}});
+ {{RdTwin.udw = Mem.udw;}}, {{EXT_ASI}});
//ASI_LDTX_N_L
0x2F: TwinLoad::ldtx_n_l(
- {{RdTwin.udw = Mem.udw}}, {{EXT_ASI}});
+ {{RdTwin.udw = Mem.udw;}}, {{EXT_ASI}});
//ASI_LDTX_P
0xE2: TwinLoad::ldtx_p(
- {{RdTwin.udw = Mem.udw}}, {{EXT_ASI}});
+ {{RdTwin.udw = Mem.udw;}}, {{EXT_ASI}});
+ //ASI_LDTX_S
+ 0xE3: TwinLoad::ldtx_s(
+ {{RdTwin.udw = Mem.udw;}}, {{EXT_ASI}});
default: ldtwa({{
uint64_t val = Mem.udw;
RdLow = val<31:0>;
@@ -1102,13 +1121,14 @@ decode OP default Unknown::unknown()
0x1B: ldxa({{Rd = (int64_t)Mem.sdw;}}, {{EXT_ASI}});
}
0x1D: LoadStoreAlt::ldstuba(
- {{Rd = Mem.ub;}},
- {{Mem.ub = 0xFF}}, {{EXT_ASI}});
+ {{uReg0 = Mem.ub;}},
+ {{Rd.ub = uReg0;
+ Mem.ub = 0xFF;}}, {{EXT_ASI}});
0x1E: StoreAlt::stxa({{Mem.udw = Rd}}, {{EXT_ASI}});
0x1F: LoadStoreAlt::swapa(
- {{uReg0 = Rd.uw;
- Rd.uw = Mem.uw;}},
- {{Mem.uw = uReg0;}}, {{EXT_ASI}});
+ {{ uReg0 = Mem.uw}},
+ {{ Mem.uw = Rd.uw;
+ Rd.uw = uReg0;}}, {{EXT_ASI}});
format Trap {
0x20: Load::ldf({{Frd.uw = Mem.uw;}});
0x21: decode X {
diff --git a/src/arch/sparc/isa/formats/mem/blockmem.isa b/src/arch/sparc/isa/formats/mem/blockmem.isa
index 32421a75f..c36fede2e 100644
--- a/src/arch/sparc/isa/formats/mem/blockmem.isa
+++ b/src/arch/sparc/isa/formats/mem/blockmem.isa
@@ -476,7 +476,6 @@ let {{
faultCode = ''
return (header_output, decoder_output, exec_output, decode_block)
-
def doTwinLoadFormat(code, faultCode, name, Name, asi, opt_flags):
addrCalcReg = 'EA = Rs1 + Rs2 + offset;'
addrCalcImm = 'EA = Rs1 + imm + offset;'
@@ -492,10 +491,11 @@ let {{
pcedCode = ''
if (microPc == 1):
flag_code = "flags[IsLastMicroOp] = true;"
- pcedCode = matcher.sub("RdHigh", code)
+ pcedCode = "RdLow = uReg0;\n"
+ pcedCode += matcher.sub("RdHigh", code)
else:
flag_code = "flags[IsDelayedCommit] = true; flags[IsFirstMicroOp] = true;"
- pcedCode = matcher.sub("RdLow", code)
+ pcedCode = matcher.sub("uReg0", code)
iop = InstObjParams(name, Name, 'TwinMem', pcedCode,
opt_flags, {"ea_code": addrCalcReg,
"fault_check": faultCode, "micro_pc": microPc,
diff --git a/src/arch/sparc/isa/includes.isa b/src/arch/sparc/isa/includes.isa
index 624afb693..0c112d481 100644
--- a/src/arch/sparc/isa/includes.isa
+++ b/src/arch/sparc/isa/includes.isa
@@ -1,4 +1,4 @@
-// Copyright (c) 2006 The Regents of The University of Michigan
+// Copyright (c) 2006-2007 The Regents of The University of Michigan
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
@@ -63,6 +63,7 @@ output exec {{
#if defined(linux)
#include <fenv.h>
#endif
+#include <limits>
#include "arch/sparc/asi.hh"
#include "cpu/base.hh"
diff --git a/src/arch/sparc/regfile.cc b/src/arch/sparc/regfile.cc
index 5d8ac6a17..b36133544 100644
--- a/src/arch/sparc/regfile.cc
+++ b/src/arch/sparc/regfile.cc
@@ -189,10 +189,10 @@ int SparcISA::InterruptLevel(uint64_t softint)
if (softint & 0x10000 || softint & 0x1)
return 14;
- int level = 14;
- while (level >= 0 && !(1 << (level + 1) & softint))
+ int level = 15;
+ while (level > 0 && !(1 << level & softint))
level--;
- if (1 << (level + 1) & softint)
+ if (1 << level & softint)
return level;
return 0;
}
diff --git a/src/arch/sparc/tlb.cc b/src/arch/sparc/tlb.cc
index 612345300..bf57c894f 100644
--- a/src/arch/sparc/tlb.cc
+++ b/src/arch/sparc/tlb.cc
@@ -85,6 +85,7 @@ TLB::insert(Addr va, int partition_id, int context_id, bool real,
int x;
cacheValid = false;
+ va &= ~(PTE.size()-1);
/* tr.va = va;
tr.size = PTE.size() - 1;
tr.contextId = context_id;
@@ -169,8 +170,8 @@ insertAllLocked:
freeList.remove(new_entry);
if (new_entry->valid && new_entry->used)
usedEntries--;
-
- lookupTable.erase(new_entry->range);
+ if (new_entry->valid)
+ lookupTable.erase(new_entry->range);
DPRINTF(TLB, "Using entry: %#X\n", new_entry);
@@ -414,6 +415,9 @@ TLB::writeSfsr(ThreadContext *tc, int reg, bool write, ContextType ct,
void
TLB::writeTagAccess(ThreadContext *tc, int reg, Addr va, int context)
{
+ DPRINTF(TLB, "TLB: Writing Tag Access: va: %#X ctx: %#X value: %#X\n",
+ va, context, mbits(va, 63,13) | mbits(context,12,0));
+
tc->setMiscRegWithEffect(reg, mbits(va, 63,13) | mbits(context,12,0));
}
@@ -536,8 +540,7 @@ ITB::translate(RequestPtr &req, ThreadContext *tc)
}
if (e == NULL || !e->valid) {
- tc->setMiscReg(MISCREG_MMU_ITLB_TAG_ACCESS,
- vaddr & ~BytesInPageMask | context);
+ writeTagAccess(tc, vaddr, context);
if (real)
return new InstructionRealTranslationMiss;
else
@@ -546,6 +549,7 @@ ITB::translate(RequestPtr &req, ThreadContext *tc)
// were not priviledged accesing priv page
if (!priv && e->pte.priv()) {
+ writeTagAccess(tc, vaddr, context);
writeSfsr(tc, false, ct, false, PrivViolation, asi);
return new InstructionAccessException;
}
@@ -578,6 +582,9 @@ DTB::translate(RequestPtr &req, ThreadContext *tc, bool write)
DPRINTF(TLB, "TLB: DTB Request to translate va=%#x size=%d asi=%#x\n",
vaddr, size, asi);
+ if (lookupTable.size() != 64 - freeList.size())
+ panic("Lookup table size: %d tlb size: %d\n", lookupTable.size(),
+ freeList.size());
if (asi == ASI_IMPLICIT)
implicit = true;
@@ -589,13 +596,15 @@ DTB::translate(RequestPtr &req, ThreadContext *tc, bool write)
// Be fast if we can!
if (cacheValid && cacheState == tlbdata) {
if (cacheEntry[0] && cacheAsi[0] == asi && cacheEntry[0]->range.va < vaddr + size &&
- cacheEntry[0]->range.va + cacheEntry[0]->range.size > vaddr) {
+ cacheEntry[0]->range.va + cacheEntry[0]->range.size > vaddr &&
+ (!write || cacheEntry[0]->pte.writable())) {
req->setPaddr(cacheEntry[0]->pte.paddr() & ~(cacheEntry[0]->pte.size()-1) |
vaddr & cacheEntry[0]->pte.size()-1 );
return NoFault;
}
if (cacheEntry[1] && cacheAsi[1] == asi && cacheEntry[1]->range.va < vaddr + size &&
- cacheEntry[1]->range.va + cacheEntry[1]->range.size > vaddr) {
+ cacheEntry[1]->range.va + cacheEntry[1]->range.size > vaddr &&
+ (!write || cacheEntry[1]->pte.writable())) {
req->setPaddr(cacheEntry[1]->pte.paddr() & ~(cacheEntry[1]->pte.size()-1) |
vaddr & cacheEntry[1]->pte.size()-1 );
return NoFault;
@@ -610,7 +619,7 @@ DTB::translate(RequestPtr &req, ThreadContext *tc, bool write)
int part_id = bits(tlbdata,15,8);
int tl = bits(tlbdata,18,16);
int pri_context = bits(tlbdata,47,32);
- int sec_context = bits(tlbdata,47,32);
+ int sec_context = bits(tlbdata,63,48);
bool real = false;
ContextType ct = Primary;
@@ -631,48 +640,42 @@ DTB::translate(RequestPtr &req, ThreadContext *tc, bool write)
ct = Primary;
context = pri_context;
}
- } else if (!hpriv && !red) {
- if (tl > 0 || AsiIsNucleus(asi)) {
- ct = Nucleus;
- context = 0;
- } else if (AsiIsSecondary(asi)) {
- ct = Secondary;
- context = sec_context;
- } else {
- context = pri_context;
- ct = Primary; //???
- }
-
+ } else {
// We need to check for priv level/asi priv
- if (!priv && !AsiIsUnPriv(asi)) {
+ if (!priv && !hpriv && !AsiIsUnPriv(asi)) {
// It appears that context should be Nucleus in these cases?
writeSfr(tc, vaddr, write, Nucleus, false, IllegalAsi, asi);
return new PrivilegedAction;
}
- if (priv && AsiIsHPriv(asi)) {
+
+ if (!hpriv && AsiIsHPriv(asi)) {
writeSfr(tc, vaddr, write, Nucleus, false, IllegalAsi, asi);
return new DataAccessException;
}
- }
- if (asi == ASI_P || asi == ASI_LDTX_P) {
- ct = Primary;
- context = pri_context;
- goto continueDtbFlow;
+ if (AsiIsPrimary(asi)) {
+ context = pri_context;
+ ct = Primary;
+ } else if (AsiIsSecondary(asi)) {
+ context = sec_context;
+ ct = Secondary;
+ } else if (AsiIsNucleus(asi)) {
+ ct = Nucleus;
+ context = 0;
+ } else { // ????
+ ct = Primary;
+ context = pri_context;
+ }
}
- if (!implicit) {
+ if (!implicit && asi != ASI_P && asi != ASI_S) {
if (AsiIsLittle(asi))
panic("Little Endian ASIs not supported\n");
if (AsiIsBlock(asi))
panic("Block ASIs not supported\n");
if (AsiIsNoFault(asi))
panic("No Fault ASIs not supported\n");
- if (!write && (asi == ASI_QUAD_LDD || asi == ASI_LDTX_REAL))
- goto continueDtbFlow;
- if (AsiIsTwin(asi))
- panic("Twin ASIs not supported\n");
if (AsiIsPartialStore(asi))
panic("Partial Store ASIs not supported\n");
if (AsiIsInterrupt(asi))
@@ -687,11 +690,11 @@ DTB::translate(RequestPtr &req, ThreadContext *tc, bool write)
if (AsiIsSparcError(asi))
goto handleSparcErrorRegAccess;
- if (!AsiIsReal(asi) && !AsiIsNucleus(asi))
+ if (!AsiIsReal(asi) && !AsiIsNucleus(asi) && !AsiIsAsIfUser(asi) &&
+ !AsiIsTwin(asi))
panic("Accessing ASI %#X. Should we?\n", asi);
}
-continueDtbFlow:
// If the asi is unaligned trap
if (vaddr & size-1) {
writeSfr(tc, vaddr, false, ct, false, OtherFault, asi);
@@ -707,7 +710,7 @@ continueDtbFlow:
}
- if ((!lsu_dm && !hpriv) || AsiIsReal(asi)) {
+ if ((!lsu_dm && !hpriv && !red) || AsiIsReal(asi)) {
real = true;
context = 0;
};
@@ -720,8 +723,7 @@ continueDtbFlow:
e = lookup(vaddr, part_id, real, context);
if (e == NULL || !e->valid) {
- tc->setMiscReg(MISCREG_MMU_DTLB_TAG_ACCESS,
- vaddr & ~BytesInPageMask | context);
+ writeTagAccess(tc, vaddr, context);
DPRINTF(TLB, "TLB: DTB Failed to find matching TLB entry\n");
if (real)
return new DataRealTranslationMiss;
@@ -730,26 +732,34 @@ continueDtbFlow:
}
+ if (!priv && e->pte.priv()) {
+ writeTagAccess(tc, vaddr, context);
+ writeSfr(tc, vaddr, write, ct, e->pte.sideffect(), PrivViolation, asi);
+ return new DataAccessException;
+ }
if (write && !e->pte.writable()) {
+ writeTagAccess(tc, vaddr, context);
writeSfr(tc, vaddr, write, ct, e->pte.sideffect(), OtherFault, asi);
return new FastDataAccessProtection;
}
if (e->pte.nofault() && !AsiIsNoFault(asi)) {
+ writeTagAccess(tc, vaddr, context);
writeSfr(tc, vaddr, write, ct, e->pte.sideffect(), LoadFromNfo, asi);
return new DataAccessException;
}
- if (e->pte.sideffect())
- req->setFlags(req->getFlags() | UNCACHEABLE);
-
-
- if (!priv && e->pte.priv()) {
- writeSfr(tc, vaddr, write, ct, e->pte.sideffect(), PrivViolation, asi);
+ if (e->pte.sideffect() && AsiIsNoFault(asi)) {
+ writeTagAccess(tc, vaddr, context);
+ writeSfr(tc, vaddr, write, ct, e->pte.sideffect(), SideEffect, asi);
return new DataAccessException;
}
+
+ if (e->pte.sideffect())
+ req->setFlags(req->getFlags() | UNCACHEABLE);
+
// cache translation date for next translation
cacheState = tlbdata;
if (!cacheValid) {
@@ -893,7 +903,7 @@ DTB::doMmuRegRead(ThreadContext *tc, Packet *pkt)
break;
case ASI_SPARC_ERROR_STATUS_REG:
warn("returning 0 for SPARC ERROR regsiter read\n");
- pkt->set(0);
+ pkt->set((uint64_t)0);
break;
case ASI_HYP_SCRATCHPAD:
case ASI_SCRATCHPAD:
@@ -963,7 +973,7 @@ DTB::doMmuRegRead(ThreadContext *tc, Packet *pkt)
data = mbits(tsbtemp,63,13);
if (bits(tsbtemp,12,12))
data |= ULL(1) << (13+bits(tsbtemp,3,0));
- data |= temp >> (9 + bits(cnftemp,2,0) * 3) &
+ data |= temp >> (9 + bits(cnftemp,10,8) * 3) &
mbits((uint64_t)-1ll,12+bits(tsbtemp,3,0), 4);
pkt->set(data);
break;
@@ -993,7 +1003,7 @@ DTB::doMmuRegRead(ThreadContext *tc, Packet *pkt)
data = mbits(tsbtemp,63,13);
if (bits(tsbtemp,12,12))
data |= ULL(1) << (13+bits(tsbtemp,3,0));
- data |= temp >> (9 + bits(cnftemp,2,0) * 3) &
+ data |= temp >> (9 + bits(cnftemp,10,8) * 3) &
mbits((uint64_t)-1ll,12+bits(tsbtemp,3,0), 4);
pkt->set(data);
break;
@@ -1112,6 +1122,7 @@ DTB::doMmuRegWrite(ThreadContext *tc, Packet *pkt)
tc->setMiscRegWithEffect(MISCREG_MMU_ITLB_SFSR, data);
break;
case 0x30:
+ sext<59>(bits(data, 59,0));
tc->setMiscRegWithEffect(MISCREG_MMU_ITLB_TAG_ACCESS, data);
break;
default:
@@ -1186,6 +1197,7 @@ DTB::doMmuRegWrite(ThreadContext *tc, Packet *pkt)
tc->setMiscRegWithEffect(MISCREG_MMU_DTLB_SFSR, data);
break;
case 0x30:
+ sext<59>(bits(data, 59,0));
tc->setMiscRegWithEffect(MISCREG_MMU_DTLB_TAG_ACCESS, data);
break;
case 0x80:
diff --git a/src/arch/sparc/tlb_map.hh b/src/arch/sparc/tlb_map.hh
index 688daf5b9..8285db939 100644
--- a/src/arch/sparc/tlb_map.hh
+++ b/src/arch/sparc/tlb_map.hh
@@ -135,6 +135,19 @@ class TlbMap
{
return tree.empty();
}
+
+ void print()
+ {
+ iterator i;
+ i = tree.begin();
+ while (i != tree.end()) {
+ std::cout << std::hex << i->first.va << " " << i->first.size << " " <<
+ i->first.contextId << " " << i->first.partitionId << " " <<
+ i->first.real << " " << i->second << std::endl;
+ i++;
+ }
+ }
+
};
};
diff --git a/src/arch/sparc/ua2005.cc b/src/arch/sparc/ua2005.cc
index b583da8b0..ecb63bb9a 100644
--- a/src/arch/sparc/ua2005.cc
+++ b/src/arch/sparc/ua2005.cc
@@ -43,8 +43,6 @@ MiscRegFile::setFSRegWithEffect(int miscReg, const MiscReg &val,
/* Full system only ASRs */
case MISCREG_SOFTINT:
setReg(miscReg, val);;
- if (val != 0x10000 && val != 0)
- warn("Writing to softint not really supported, writing: %#x\n", val);
break;
case MISCREG_SOFTINT_CLR: