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:
Ali Saidi 2007-01-25 13:43:46 -05:00
parent 4301e4cd08
commit 8561c8366c
6 changed files with 58 additions and 37 deletions

View file

@ -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 {

View file

@ -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,

View file

@ -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"

View file

@ -170,8 +170,8 @@ 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);
DPRINTF(TLB, "Using entry: %#X\n", new_entry); DPRINTF(TLB, "Using entry: %#X\n", new_entry);
@ -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;

View file

@ -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++;
}
}
}; };
}; };

View file

@ -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()) {