fix smul and sdiv to sign extend, and handle overflow/underflow corretly
Only allow writing/reading of 32 bits of Y Only allow writing/reading 32 bits of pc when pstate.am Put any loaded data on the first half of a micro-op in uReg0 so it can't overwrite the register we are using for address calculation only erase a entry from the lookup table if it's valid Put in a temporary check to make sure that lookup table and tlb array stay in sync if we are interrupted in the middle of a mico-op, reset the micropc/nexpc so we start on the first part of it when we come back src/arch/sparc/isa/decoder.isa: fix smul and sdiv to sign extend, and handle overflow/underflow corretly Only allow writing/reading of 32 bits of Y Only allow writing/reading 32 bits of pc when pstate.am Put any loaded data on the first half of a micro-op in uReg0 so it can't overwrite the register we are using for address calculation src/arch/sparc/isa/formats/mem/blockmem.isa: Put any loaded data on the first half of a micro-op in uReg0 so it can't overwrite the register we are using for address calculation src/arch/sparc/isa/includes.isa: Use limits for 32bit underflow/overflow detection src/arch/sparc/tlb.cc: only erase a entry from the lookup table if it's valid Put in a temporary check to make sure that lookup table and tlb array stay in sync src/arch/sparc/tlb_map.hh: add a print function to dump the tlb lookup table src/cpu/simple/base.cc: if we are interrupted in the middle of a mico-op, reset the micropc/nexpc so we start on the first part of it when we come back --HG-- extra : convert_revision : 50a23837fd888393a5c2aa35cbd1abeebb7f55d4
This commit is contained in:
parent
4301e4cd08
commit
8561c8366c
6 changed files with 58 additions and 37 deletions
|
@ -186,7 +186,7 @@ decode OP default Unknown::unknown()
|
||||||
Y = Rd<63:32>;
|
Y = Rd<63:32>;
|
||||||
}});
|
}});
|
||||||
0x0B: smul({{
|
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>;
|
Y = Rd.sdw<63:32>;
|
||||||
}});
|
}});
|
||||||
0x0C: subc({{Rd.sdw = Rs1.sdw + (~Rs2_or_imm13) + 1 - Ccr<0:0>}});
|
0x0C: subc({{Rd.sdw = Rs1.sdw + (~Rs2_or_imm13) + 1 - Ccr<0:0>}});
|
||||||
|
@ -209,10 +209,10 @@ decode OP default Unknown::unknown()
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Rd.udw = ((int64_t)((Y << 32) | Rs1.sdw<31:0>)) / Rs2_or_imm13.sdw;
|
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;
|
Rd.udw = 0x7FFFFFFF;
|
||||||
else if(Rd.udw<63:> && Rd.udw<62:31> != 0xFFFFFFFF)
|
else if((int64_t)Rd.udw <= std::numeric_limits<int32_t>::min())
|
||||||
Rd.udw = 0xFFFFFFFF80000000ULL;
|
Rd.udw = ULL(0xFFFFFFFF80000000);
|
||||||
}
|
}
|
||||||
}});
|
}});
|
||||||
}
|
}
|
||||||
|
@ -257,7 +257,7 @@ decode OP default Unknown::unknown()
|
||||||
{{0}},{{0}},{{0}},{{0}});
|
{{0}},{{0}},{{0}},{{0}});
|
||||||
0x1B: smulcc({{
|
0x1B: smulcc({{
|
||||||
int64_t resTemp;
|
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>;}},
|
Y = resTemp<63:32>;}},
|
||||||
{{0}},{{0}},{{0}},{{0}});
|
{{0}},{{0}},{{0}},{{0}});
|
||||||
0x1C: subccc({{
|
0x1C: subccc({{
|
||||||
|
@ -296,10 +296,10 @@ decode OP default Unknown::unknown()
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Rd = (int64_t)((Y << 32) | Rs1.sdw<31:0>) / val2;
|
Rd = (int64_t)((Y << 32) | Rs1.sdw<31:0>) / val2;
|
||||||
overflow = (Rd<63:31> != 0);
|
overflow = ((int64_t)Rd >= std::numeric_limits<int32_t>::max());
|
||||||
underflow = (Rd<63:> && Rd<62:31> != 0xFFFFFFFF);
|
underflow = ((int64_t)Rd <= std::numeric_limits<int32_t>::min());
|
||||||
if(overflow) Rd = 0x7FFFFFFF;
|
if(overflow) Rd = 0x7FFFFFFF;
|
||||||
else if(underflow) Rd = 0xFFFFFFFF80000000ULL;
|
else if(underflow) Rd = ULL(0xFFFFFFFF80000000);
|
||||||
} }},
|
} }},
|
||||||
{{0}},
|
{{0}},
|
||||||
{{overflow || underflow}},
|
{{overflow || underflow}},
|
||||||
|
@ -376,7 +376,7 @@ decode OP default Unknown::unknown()
|
||||||
0x1: srax({{Rd = Rs1.sdw >> (I ? SHCNT64 : Rs2<5:0>);}});
|
0x1: srax({{Rd = Rs1.sdw >> (I ? SHCNT64 : Rs2<5:0>);}});
|
||||||
}
|
}
|
||||||
0x28: decode RS1 {
|
0x28: decode RS1 {
|
||||||
0x00: NoPriv::rdy({{Rd = Y;}});
|
0x00: NoPriv::rdy({{Rd = Y<31:0>;}});
|
||||||
//1 should cause an illegal instruction exception
|
//1 should cause an illegal instruction exception
|
||||||
0x02: NoPriv::rdccr({{Rd = Ccr;}});
|
0x02: NoPriv::rdccr({{Rd = Ccr;}});
|
||||||
0x03: NoPriv::rdasi({{Rd = Asi;}});
|
0x03: NoPriv::rdasi({{Rd = Asi;}});
|
||||||
|
@ -526,7 +526,7 @@ decode OP default Unknown::unknown()
|
||||||
0x7: movrge({{Rd = (Rs1.sdw >= 0) ? Rs2_or_imm10 : Rd;}});
|
0x7: movrge({{Rd = (Rs1.sdw >= 0) ? Rs2_or_imm10 : Rd;}});
|
||||||
}
|
}
|
||||||
0x30: decode 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
|
//0x01 should cause an illegal instruction exception
|
||||||
0x02: NoPriv::wrccr({{Ccr = Rs1 ^ Rs2_or_imm13;}});
|
0x02: NoPriv::wrccr({{Ccr = Rs1 ^ Rs2_or_imm13;}});
|
||||||
0x03: NoPriv::wrasi({{Asi = Rs1 ^ Rs2_or_imm13;}});
|
0x03: NoPriv::wrasi({{Asi = Rs1 ^ Rs2_or_imm13;}});
|
||||||
|
@ -882,7 +882,7 @@ decode OP default Unknown::unknown()
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (Pstate<3:>)
|
if (Pstate<3:>)
|
||||||
(Rd = xc->readPC())<31:0>;
|
Rd = (xc->readPC())<31:0>;
|
||||||
else
|
else
|
||||||
Rd = xc->readPC();
|
Rd = xc->readPC();
|
||||||
NNPC = target;
|
NNPC = target;
|
||||||
|
@ -1058,13 +1058,14 @@ decode OP default Unknown::unknown()
|
||||||
0x0B: ldx({{Rd = (int64_t)Mem.sdw;}});
|
0x0B: ldx({{Rd = (int64_t)Mem.sdw;}});
|
||||||
}
|
}
|
||||||
0x0D: LoadStore::ldstub(
|
0x0D: LoadStore::ldstub(
|
||||||
{{Rd = Mem.ub;}},
|
{{uReg0 = Mem.ub;}},
|
||||||
{{Mem.ub = 0xFF;}});
|
{{Rd.ub = uReg0;
|
||||||
|
Mem.ub = 0xFF;}});
|
||||||
0x0E: Store::stx({{Mem.udw = Rd}});
|
0x0E: Store::stx({{Mem.udw = Rd}});
|
||||||
0x0F: LoadStore::swap(
|
0x0F: LoadStore::swap(
|
||||||
{{uReg0 = Rd.uw;
|
{{ uReg0 = Mem.uw}},
|
||||||
Rd.uw = Mem.uw;}},
|
{{ Mem.uw = Rd.uw;
|
||||||
{{Mem.uw = uReg0;}});
|
Rd.uw = uReg0;}});
|
||||||
format LoadAlt {
|
format LoadAlt {
|
||||||
0x10: lduwa({{Rd = Mem.uw;}}, {{EXT_ASI}});
|
0x10: lduwa({{Rd = Mem.uw;}}, {{EXT_ASI}});
|
||||||
0x11: lduba({{Rd = Mem.ub;}}, {{EXT_ASI}});
|
0x11: lduba({{Rd = Mem.ub;}}, {{EXT_ASI}});
|
||||||
|
@ -1072,34 +1073,34 @@ decode OP default Unknown::unknown()
|
||||||
0x13: decode EXT_ASI {
|
0x13: decode EXT_ASI {
|
||||||
//ASI_LDTD_AIUP
|
//ASI_LDTD_AIUP
|
||||||
0x22: TwinLoad::ldtx_aiup(
|
0x22: TwinLoad::ldtx_aiup(
|
||||||
{{RdTwin.udw = Mem.udw}}, {{EXT_ASI}});
|
{{RdTwin.udw = Mem.udw;}}, {{EXT_ASI}});
|
||||||
//ASI_LDTD_AIUS
|
//ASI_LDTD_AIUS
|
||||||
0x23: TwinLoad::ldtx_aius(
|
0x23: TwinLoad::ldtx_aius(
|
||||||
{{RdTwin.udw = Mem.udw}}, {{EXT_ASI}});
|
{{RdTwin.udw = Mem.udw;}}, {{EXT_ASI}});
|
||||||
//ASI_QUAD_LDD
|
//ASI_QUAD_LDD
|
||||||
0x24: TwinLoad::ldtx_quad_ldd(
|
0x24: TwinLoad::ldtx_quad_ldd(
|
||||||
{{RdTwin.udw = Mem.udw}}, {{EXT_ASI}});
|
{{RdTwin.udw = Mem.udw;}}, {{EXT_ASI}});
|
||||||
//ASI_LDTX_REAL
|
//ASI_LDTX_REAL
|
||||||
0x26: TwinLoad::ldtx_real(
|
0x26: TwinLoad::ldtx_real(
|
||||||
{{RdTwin.udw = Mem.udw}}, {{EXT_ASI}});
|
{{RdTwin.udw = Mem.udw;}}, {{EXT_ASI}});
|
||||||
//ASI_LDTX_N
|
//ASI_LDTX_N
|
||||||
0x27: TwinLoad::ldtx_n(
|
0x27: TwinLoad::ldtx_n(
|
||||||
{{RdTwin.udw = Mem.udw}}, {{EXT_ASI}});
|
{{RdTwin.udw = Mem.udw;}}, {{EXT_ASI}});
|
||||||
//ASI_LDTX_L
|
//ASI_LDTX_L
|
||||||
0x2C: TwinLoad::ldtx_l(
|
0x2C: TwinLoad::ldtx_l(
|
||||||
{{RdTwin.udw = Mem.udw}}, {{EXT_ASI}});
|
{{RdTwin.udw = Mem.udw;}}, {{EXT_ASI}});
|
||||||
//ASI_LDTX_REAL_L
|
//ASI_LDTX_REAL_L
|
||||||
0x2E: TwinLoad::ldtx_real_l(
|
0x2E: TwinLoad::ldtx_real_l(
|
||||||
{{RdTwin.udw = Mem.udw}}, {{EXT_ASI}});
|
{{RdTwin.udw = Mem.udw;}}, {{EXT_ASI}});
|
||||||
//ASI_LDTX_N_L
|
//ASI_LDTX_N_L
|
||||||
0x2F: TwinLoad::ldtx_n_l(
|
0x2F: TwinLoad::ldtx_n_l(
|
||||||
{{RdTwin.udw = Mem.udw}}, {{EXT_ASI}});
|
{{RdTwin.udw = Mem.udw;}}, {{EXT_ASI}});
|
||||||
//ASI_LDTX_P
|
//ASI_LDTX_P
|
||||||
0xE2: TwinLoad::ldtx_p(
|
0xE2: TwinLoad::ldtx_p(
|
||||||
{{RdTwin.udw = Mem.udw}}, {{EXT_ASI}});
|
{{RdTwin.udw = Mem.udw;}}, {{EXT_ASI}});
|
||||||
//ASI_LDTX_S
|
//ASI_LDTX_S
|
||||||
0xE3: TwinLoad::ldtx_s(
|
0xE3: TwinLoad::ldtx_s(
|
||||||
{{RdTwin.udw = Mem.udw}}, {{EXT_ASI}});
|
{{RdTwin.udw = Mem.udw;}}, {{EXT_ASI}});
|
||||||
default: ldtwa({{
|
default: ldtwa({{
|
||||||
uint64_t val = Mem.udw;
|
uint64_t val = Mem.udw;
|
||||||
RdLow = val<31:0>;
|
RdLow = val<31:0>;
|
||||||
|
@ -1120,13 +1121,14 @@ decode OP default Unknown::unknown()
|
||||||
0x1B: ldxa({{Rd = (int64_t)Mem.sdw;}}, {{EXT_ASI}});
|
0x1B: ldxa({{Rd = (int64_t)Mem.sdw;}}, {{EXT_ASI}});
|
||||||
}
|
}
|
||||||
0x1D: LoadStoreAlt::ldstuba(
|
0x1D: LoadStoreAlt::ldstuba(
|
||||||
{{Rd = Mem.ub;}},
|
{{uReg0 = Mem.ub;}},
|
||||||
{{Mem.ub = 0xFF}}, {{EXT_ASI}});
|
{{Rd.ub = uReg0;
|
||||||
|
Mem.ub = 0xFF;}}, {{EXT_ASI}});
|
||||||
0x1E: StoreAlt::stxa({{Mem.udw = Rd}}, {{EXT_ASI}});
|
0x1E: StoreAlt::stxa({{Mem.udw = Rd}}, {{EXT_ASI}});
|
||||||
0x1F: LoadStoreAlt::swapa(
|
0x1F: LoadStoreAlt::swapa(
|
||||||
{{uReg0 = Rd.uw;
|
{{ uReg0 = Mem.uw}},
|
||||||
Rd.uw = Mem.uw;}},
|
{{ Mem.uw = Rd.uw;
|
||||||
{{Mem.uw = uReg0;}}, {{EXT_ASI}});
|
Rd.uw = uReg0;}}, {{EXT_ASI}});
|
||||||
format Trap {
|
format Trap {
|
||||||
0x20: Load::ldf({{Frd.uw = Mem.uw;}});
|
0x20: Load::ldf({{Frd.uw = Mem.uw;}});
|
||||||
0x21: decode X {
|
0x21: decode X {
|
||||||
|
|
|
@ -476,7 +476,6 @@ let {{
|
||||||
faultCode = ''
|
faultCode = ''
|
||||||
return (header_output, decoder_output, exec_output, decode_block)
|
return (header_output, decoder_output, exec_output, decode_block)
|
||||||
|
|
||||||
|
|
||||||
def doTwinLoadFormat(code, faultCode, name, Name, asi, opt_flags):
|
def doTwinLoadFormat(code, faultCode, name, Name, asi, opt_flags):
|
||||||
addrCalcReg = 'EA = Rs1 + Rs2 + offset;'
|
addrCalcReg = 'EA = Rs1 + Rs2 + offset;'
|
||||||
addrCalcImm = 'EA = Rs1 + imm + offset;'
|
addrCalcImm = 'EA = Rs1 + imm + offset;'
|
||||||
|
@ -492,10 +491,11 @@ let {{
|
||||||
pcedCode = ''
|
pcedCode = ''
|
||||||
if (microPc == 1):
|
if (microPc == 1):
|
||||||
flag_code = "flags[IsLastMicroOp] = true;"
|
flag_code = "flags[IsLastMicroOp] = true;"
|
||||||
pcedCode = matcher.sub("RdHigh", code)
|
pcedCode = "RdLow = uReg0;\n"
|
||||||
|
pcedCode += matcher.sub("RdHigh", code)
|
||||||
else:
|
else:
|
||||||
flag_code = "flags[IsDelayedCommit] = true; flags[IsFirstMicroOp] = true;"
|
flag_code = "flags[IsDelayedCommit] = true; flags[IsFirstMicroOp] = true;"
|
||||||
pcedCode = matcher.sub("RdLow", code)
|
pcedCode = matcher.sub("uReg0", code)
|
||||||
iop = InstObjParams(name, Name, 'TwinMem', pcedCode,
|
iop = InstObjParams(name, Name, 'TwinMem', pcedCode,
|
||||||
opt_flags, {"ea_code": addrCalcReg,
|
opt_flags, {"ea_code": addrCalcReg,
|
||||||
"fault_check": faultCode, "micro_pc": microPc,
|
"fault_check": faultCode, "micro_pc": microPc,
|
||||||
|
|
|
@ -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.
|
// All rights reserved.
|
||||||
//
|
//
|
||||||
// Redistribution and use in source and binary forms, with or without
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
@ -63,6 +63,7 @@ output exec {{
|
||||||
#if defined(linux)
|
#if defined(linux)
|
||||||
#include <fenv.h>
|
#include <fenv.h>
|
||||||
#endif
|
#endif
|
||||||
|
#include <limits>
|
||||||
|
|
||||||
#include "arch/sparc/asi.hh"
|
#include "arch/sparc/asi.hh"
|
||||||
#include "cpu/base.hh"
|
#include "cpu/base.hh"
|
||||||
|
|
|
@ -170,7 +170,7 @@ insertAllLocked:
|
||||||
freeList.remove(new_entry);
|
freeList.remove(new_entry);
|
||||||
if (new_entry->valid && new_entry->used)
|
if (new_entry->valid && new_entry->used)
|
||||||
usedEntries--;
|
usedEntries--;
|
||||||
|
if (new_entry->valid)
|
||||||
lookupTable.erase(new_entry->range);
|
lookupTable.erase(new_entry->range);
|
||||||
|
|
||||||
|
|
||||||
|
@ -582,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",
|
DPRINTF(TLB, "TLB: DTB Request to translate va=%#x size=%d asi=%#x\n",
|
||||||
vaddr, size, asi);
|
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)
|
if (asi == ASI_IMPLICIT)
|
||||||
implicit = true;
|
implicit = true;
|
||||||
|
|
||||||
|
|
|
@ -135,6 +135,19 @@ class TlbMap
|
||||||
{
|
{
|
||||||
return tree.empty();
|
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++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -439,6 +439,8 @@ BaseSimpleCPU::advancePC(Fault fault)
|
||||||
if (fault != NoFault) {
|
if (fault != NoFault) {
|
||||||
curMacroStaticInst = StaticInst::nullStaticInstPtr;
|
curMacroStaticInst = StaticInst::nullStaticInstPtr;
|
||||||
fault->invoke(tc);
|
fault->invoke(tc);
|
||||||
|
thread->setMicroPC(0);
|
||||||
|
thread->setNextMicroPC(1);
|
||||||
} else {
|
} else {
|
||||||
//If we're at the last micro op for this instruction
|
//If we're at the last micro op for this instruction
|
||||||
if (curStaticInst->isLastMicroOp()) {
|
if (curStaticInst->isLastMicroOp()) {
|
||||||
|
|
Loading…
Reference in a new issue