Files
gem5/src/arch/sparc/isa/decoder.isa
Ali Saidi 58f69391ca implement ipi stufff for SPARC
src/arch/alpha/utility.hh:
src/arch/mips/utility.hh:
src/arch/sparc/utility.hh:
src/arch/x86/utility.hh:
    add hook for system to startup the cpu or not... in the case of FS sparc, only the first cpu would get spunup.. the rest sit in an idle state until they get an ipi
src/arch/sparc/isa/decoder.isa:
    handle writable bits of strandstatus register in miscregfile
src/arch/sparc/miscregfile.hh:
    some constants for the strand status register
src/arch/sparc/ua2005.cc:
    properly implement the strand status register
src/dev/sparc/iob.cc:
    implement ipi generation properly
src/sim/system.cc:
    call into the ISA to start the CPU (or not)

--HG--
extra : convert_revision : 0003b2032337d8a031a9fc044da726dbb2a9e36f
2007-03-09 16:56:39 -05:00

1489 lines
64 KiB
Plaintext

// 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
// modification, are permitted provided that the following conditions are
// met: redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer;
// redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution;
// neither the name of the copyright holders nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Authors: Ali Saidi
// Gabe Black
// Steve Reinhardt
////////////////////////////////////////////////////////////////////
//
// The actual decoder specification
//
decode OP default Unknown::unknown()
{
0x0: decode OP2
{
//Throw an illegal instruction acception
0x0: Trap::illtrap({{fault = new IllegalInstruction;}});
format BranchN
{
//bpcc
0x1: decode COND2
{
//Branch Always
0x8: decode A
{
0x0: bpa(19, {{
NNPC = xc->readPC() + disp;
}});
0x1: bpa(19, {{
NPC = xc->readPC() + disp;
NNPC = NPC + 4;
}}, ',a');
}
//Branch Never
0x0: decode A
{
0x0: bpn(19, {{
NNPC = NNPC;//Don't do anything
}});
0x1: bpn(19, {{
NNPC = NPC + 8;
NPC = NPC + 4;
}}, ',a');
}
default: decode BPCC
{
0x0: bpcci(19, {{
if(passesCondition(Ccr<3:0>, COND2))
NNPC = xc->readPC() + disp;
else
handle_annul
}});
0x2: bpccx(19, {{
if(passesCondition(Ccr<7:4>, COND2))
NNPC = xc->readPC() + disp;
else
handle_annul
}});
}
}
//bicc
0x2: decode COND2
{
//Branch Always
0x8: decode A
{
0x0: ba(22, {{
NNPC = xc->readPC() + disp;
}});
0x1: ba(22, {{
NPC = xc->readPC() + disp;
NNPC = NPC + 4;
}}, ',a');
}
//Branch Never
0x0: decode A
{
0x0: bn(22, {{
NNPC = NNPC;//Don't do anything
}});
0x1: bn(22, {{
NNPC = NPC + 8;
NPC = NPC + 4;
}}, ',a');
}
default: bicc(22, {{
if(passesCondition(Ccr<3:0>, COND2))
NNPC = xc->readPC() + disp;
else
handle_annul
}});
}
}
0x3: decode RCOND2
{
format BranchSplit
{
0x1: bpreq({{
if(Rs1.sdw == 0)
NNPC = xc->readPC() + disp;
else
handle_annul
}});
0x2: bprle({{
if(Rs1.sdw <= 0)
NNPC = xc->readPC() + disp;
else
handle_annul
}});
0x3: bprl({{
if(Rs1.sdw < 0)
NNPC = xc->readPC() + disp;
else
handle_annul
}});
0x5: bprne({{
if(Rs1.sdw != 0)
NNPC = xc->readPC() + disp;
else
handle_annul
}});
0x6: bprg({{
if(Rs1.sdw > 0)
NNPC = xc->readPC() + disp;
else
handle_annul
}});
0x7: bprge({{
if(Rs1.sdw >= 0)
NNPC = xc->readPC() + disp;
else
handle_annul
}});
}
}
//SETHI (or NOP if rd == 0 and imm == 0)
0x4: SetHi::sethi({{Rd.udw = imm;}});
//fbpfcc
0x5: decode COND2 {
format BranchN {
//Branch Always
0x8: decode A
{
0x0: fbpa(22, {{
NNPC = xc->readPC() + disp;
}});
0x1: fbpa(22, {{
NPC = xc->readPC() + disp;
NNPC = NPC + 4;
}}, ',a');
}
//Branch Never
0x0: decode A
{
0x0: fbpn(22, {{
NNPC = NNPC;//Don't do anything
}});
0x1: fbpn(22, {{
NNPC = NPC + 8;
NPC = NPC + 4;
}}, ',a');
}
default: decode BPCC {
0x0: fbpcc0(22, {{
if(passesFpCondition(Fsr<11:10>, COND2))
NNPC = xc->readPC() + disp;
else
handle_annul
}});
0x1: fbpcc1(22, {{
if(passesFpCondition(Fsr<33:32>, COND2))
NNPC = xc->readPC() + disp;
else
handle_annul
}});
0x2: fbpcc2(22, {{
if(passesFpCondition(Fsr<35:34>, COND2))
NNPC = xc->readPC() + disp;
else
handle_annul
}});
0x3: fbpcc3(22, {{
if(passesFpCondition(Fsr<37:36>, COND2))
NNPC = xc->readPC() + disp;
else
handle_annul
}});
}
}
}
//fbfcc
0x6: decode COND2 {
format BranchN {
//Branch Always
0x8: decode A
{
0x0: fba(22, {{
NNPC = xc->readPC() + disp;
}});
0x1: fba(22, {{
NPC = xc->readPC() + disp;
NNPC = NPC + 4;
}}, ',a');
}
//Branch Never
0x0: decode A
{
0x0: fbn(22, {{
NNPC = NNPC;//Don't do anything
}});
0x1: fbn(22, {{
NNPC = NPC + 8;
NPC = NPC + 4;
}}, ',a');
}
default: fbfcc(22, {{
if(passesFpCondition(Fsr<11:10>, COND2))
NNPC = xc->readPC() + disp;
else
handle_annul
}});
}
}
}
0x1: BranchN::call(30, {{
if (Pstate<3:>)
R15 = (xc->readPC())<31:0>;
else
R15 = xc->readPC();
NNPC = R15 + disp;
}});
0x2: decode OP3 {
format IntOp {
0x00: add({{Rd = Rs1.sdw + Rs2_or_imm13;}});
0x01: and({{Rd = Rs1.sdw & Rs2_or_imm13;}});
0x02: or({{Rd = Rs1.sdw | Rs2_or_imm13;}});
0x03: xor({{Rd = Rs1.sdw ^ Rs2_or_imm13;}});
0x04: sub({{Rd = Rs1.sdw - Rs2_or_imm13;}});
0x05: andn({{Rd = Rs1.sdw & ~Rs2_or_imm13;}});
0x06: orn({{Rd = Rs1.sdw | ~Rs2_or_imm13;}});
0x07: xnor({{Rd = ~(Rs1.sdw ^ Rs2_or_imm13);}});
0x08: addc({{Rd = Rs1.sdw + Rs2_or_imm13 + Ccr<0:0>;}});
0x09: mulx({{Rd = Rs1.sdw * Rs2_or_imm13;}});
0x0A: umul({{
Rd = Rs1.udw<31:0> * Rs2_or_imm13<31:0>;
Y = Rd<63:32>;
}});
0x0B: smul({{
Rd.sdw = sext<32>(Rs1.sdw<31:0>) * sext<32>(Rs2_or_imm13<31:0>);
Y = Rd.sdw<63:32>;
}});
0x0C: subc({{Rd.sdw = Rs1.sdw + (~Rs2_or_imm13) + 1 - Ccr<0:0>}});
0x0D: udivx({{
if(Rs2_or_imm13 == 0) fault = new DivisionByZero;
else Rd.udw = Rs1.udw / Rs2_or_imm13;
}});
0x0E: udiv({{
if(Rs2_or_imm13 == 0) fault = new DivisionByZero;
else
{
Rd.udw = ((Y << 32) | Rs1.udw<31:0>) / Rs2_or_imm13;
if(Rd.udw >> 32 != 0)
Rd.udw = 0xFFFFFFFF;
}
}});
0x0F: sdiv({{
if(Rs2_or_imm13.sdw == 0)
fault = new DivisionByZero;
else
{
Rd.udw = ((int64_t)((Y << 32) | Rs1.sdw<31:0>)) / Rs2_or_imm13.sdw;
if((int64_t)Rd.udw >= std::numeric_limits<int32_t>::max())
Rd.udw = 0x7FFFFFFF;
else if((int64_t)Rd.udw <= std::numeric_limits<int32_t>::min())
Rd.udw = ULL(0xFFFFFFFF80000000);
}
}});
}
format IntOpCc {
0x10: addcc({{
int64_t resTemp, val2 = Rs2_or_imm13;
Rd = resTemp = Rs1 + val2;}},
{{(Rs1<31:0> + val2<31:0>)<32:>}},
{{Rs1<31:> == val2<31:> && val2<31:> != resTemp<31:>}},
{{(Rs1<63:1> + val2<63:1> + (Rs1 & val2)<0:>)<63:>}},
{{Rs1<63:> == val2<63:> && val2<63:> != resTemp<63:>}}
);
0x11: IntOpCcRes::andcc({{Rd = Rs1 & Rs2_or_imm13;}});
0x12: IntOpCcRes::orcc({{Rd = Rs1 | Rs2_or_imm13;}});
0x13: IntOpCcRes::xorcc({{Rd = Rs1 ^ Rs2_or_imm13;}});
0x14: subcc({{
int64_t val2 = Rs2_or_imm13;
Rd = Rs1 - val2;}},
{{(~(Rs1<31:0> + (~val2)<31:0> + 1))<32:>}},
{{(Rs1<31:> != val2<31:>) && (Rs1<31:> != Rd<31:>)}},
{{(~(Rs1<63:1> + (~val2)<63:1> +
(Rs1 | ~val2)<0:>))<63:>}},
{{Rs1<63:> != val2<63:> && Rs1<63:> != Rd<63:>}}
);
0x15: IntOpCcRes::andncc({{Rd = Rs1 & ~Rs2_or_imm13;}});
0x16: IntOpCcRes::orncc({{Rd = Rs1 | ~Rs2_or_imm13;}});
0x17: IntOpCcRes::xnorcc({{Rd = ~(Rs1 ^ Rs2_or_imm13);}});
0x18: addccc({{
int64_t resTemp, val2 = Rs2_or_imm13;
int64_t carryin = Ccr<0:0>;
Rd = resTemp = Rs1 + val2 + carryin;}},
{{(Rs1<31:0> + val2<31:0> + carryin)<32:>}},
{{Rs1<31:> == val2<31:> && val2<31:> != resTemp<31:>}},
{{((Rs1 & val2) | (~resTemp & (Rs1 | val2)))<63:>}},
{{Rs1<63:> == val2<63:> && val2<63:> != resTemp<63:>}}
);
0x1A: IntOpCcRes::umulcc({{
uint64_t resTemp;
Rd = resTemp = Rs1.udw<31:0> * Rs2_or_imm13.udw<31:0>;
Y = resTemp<63:32>;}});
0x1B: IntOpCcRes::smulcc({{
int64_t resTemp;
Rd = resTemp = sext<32>(Rs1.sdw<31:0>) * sext<32>(Rs2_or_imm13<31:0>);
Y = resTemp<63:32>;}});
0x1C: subccc({{
int64_t resTemp, val2 = Rs2_or_imm13;
int64_t carryin = Ccr<0:0>;
Rd = resTemp = Rs1 + ~val2 + 1 - carryin;}},
{{((~Rs1 & val2) | (resTemp & (~Rs1 | val2)))<31:>}},
{{Rs1<31:> != val2<31:> && Rs1<31:> != resTemp<31:>}},
{{((~Rs1 & val2) | (resTemp & (~Rs1 | val2)))<63:>}},
{{Rs1<63:> != val2<63:> && Rs1<63:> != resTemp<63:>}}
);
0x1D: IntOpCcRes::udivxcc({{
if(Rs2_or_imm13.udw == 0) fault = new DivisionByZero;
else Rd = Rs1.udw / Rs2_or_imm13.udw;}});
0x1E: udivcc({{
uint32_t resTemp, val2 = Rs2_or_imm13.udw;
int32_t overflow = 0;
if(val2 == 0) fault = new DivisionByZero;
else
{
resTemp = (uint64_t)((Y << 32) | Rs1.udw<31:0>) / val2;
overflow = (resTemp<63:32> != 0);
if(overflow) Rd = resTemp = 0xFFFFFFFF;
else Rd = resTemp;
} }},
{{0}},
{{overflow}},
{{0}},
{{0}}
);
0x1F: sdivcc({{
int64_t val2 = Rs2_or_imm13.sdw<31:0>;
bool overflow = false, underflow = false;
if(val2 == 0) fault = new DivisionByZero;
else
{
Rd = (int64_t)((Y << 32) | Rs1.sdw<31:0>) / val2;
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 = ULL(0xFFFFFFFF80000000);
} }},
{{0}},
{{overflow || underflow}},
{{0}},
{{0}}
);
0x20: taddcc({{
int64_t resTemp, val2 = Rs2_or_imm13;
Rd = resTemp = Rs1 + val2;
int32_t overflow = Rs1<1:0> || val2<1:0> || (Rs1<31:> == val2<31:> && val2<31:> != resTemp<31:>);}},
{{((Rs1<31:0> + val2<31:0>)<32:0>)}},
{{overflow}},
{{((Rs1 >> 1) + (val2 >> 1) + (Rs1 & val2 & 0x1))<63:>}},
{{Rs1<63:> == val2<63:> && val2<63:> != resTemp<63:>}}
);
0x21: tsubcc({{
int64_t resTemp, val2 = Rs2_or_imm13;
Rd = resTemp = Rs1 + val2;
int32_t overflow = Rs1<1:0> || val2<1:0> || (Rs1<31:> == val2<31:> && val2<31:> != resTemp<31:>);}},
{{(Rs1<31:0> + val2<31:0>)<32:0>}},
{{overflow}},
{{((Rs1 >> 1) + (val2 >> 1) + (Rs1 & val2 & 0x1))<63:>}},
{{Rs1<63:> == val2<63:> && val2<63:> != resTemp<63:>}}
);
0x22: taddcctv({{
int64_t val2 = Rs2_or_imm13;
Rd = Rs1 + val2;
int32_t overflow = Rs1<1:0> || val2<1:0> ||
(Rs1<31:> == val2<31:> && val2<31:> != Rd<31:>);
if(overflow) fault = new TagOverflow;}},
{{((Rs1<31:0> + val2<31:0>)<32:0>)}},
{{overflow}},
{{((Rs1 >> 1) + (val2 >> 1) + (Rs1 & val2 & 0x1))<63:>}},
{{Rs1<63:> == val2<63:> && val2<63:> != Rd<63:>}}
);
0x23: tsubcctv({{
int64_t resTemp, val2 = Rs2_or_imm13;
Rd = resTemp = Rs1 + val2;
int32_t overflow = Rs1<1:0> || val2<1:0> || (Rs1<31:> == val2<31:> && val2<31:> != resTemp<31:>);
if(overflow) fault = new TagOverflow;}},
{{((Rs1<31:0> + val2<31:0>)<32:0>)}},
{{overflow}},
{{((Rs1 >> 1) + (val2 >> 1) + (Rs1 & val2 & 0x1))<63:>}},
{{Rs1<63:> == val2<63:> && val2<63:> != resTemp<63:>}}
);
0x24: mulscc({{
int64_t resTemp, multiplicand = Rs2_or_imm13;
int32_t multiplier = Rs1<31:0>;
int32_t savedLSB = Rs1<0:>;
multiplier = multiplier<31:1> |
((Ccr<3:3> ^ Ccr<1:1>) << 32);
if(!Y<0:>)
multiplicand = 0;
Rd = resTemp = multiplicand + multiplier;
Y = Y<31:1> | (savedLSB << 31);}},
{{((multiplicand<31:0> + multiplier<31:0>)<32:0>)}},
{{multiplicand<31:> == multiplier<31:> && multiplier<31:> != resTemp<31:>}},
{{((multiplicand >> 1) + (multiplier >> 1) + (multiplicand & multiplier & 0x1))<63:>}},
{{multiplicand<63:> == multiplier<63:> && multiplier<63:> != resTemp<63:>}}
);
}
format IntOp
{
0x25: decode X {
0x0: sll({{Rd = Rs1 << (I ? SHCNT32 : Rs2<4:0>);}});
0x1: sllx({{Rd = Rs1 << (I ? SHCNT64 : Rs2<5:0>);}});
}
0x26: decode X {
0x0: srl({{Rd = Rs1.uw >> (I ? SHCNT32 : Rs2<4:0>);}});
0x1: srlx({{Rd = Rs1.udw >> (I ? SHCNT64 : Rs2<5:0>);}});
}
0x27: decode X {
0x0: sra({{Rd = Rs1.sw >> (I ? SHCNT32 : Rs2<4:0>);}});
0x1: srax({{Rd = Rs1.sdw >> (I ? SHCNT64 : Rs2<5:0>);}});
}
0x28: decode RS1 {
0x00: NoPriv::rdy({{Rd = Y<31:0>;}});
//1 should cause an illegal instruction exception
0x02: NoPriv::rdccr({{Rd = Ccr;}});
0x03: NoPriv::rdasi({{Rd = Asi;}});
0x04: PrivCheck::rdtick({{Rd = Tick;}}, {{Tick<63:>}});
0x05: NoPriv::rdpc({{
if(Pstate<3:>)
Rd = (xc->readPC())<31:0>;
else
Rd = xc->readPC();}});
0x06: NoPriv::rdfprs({{
//Wait for all fpops to finish.
Rd = Fprs;
}});
//7-14 should cause an illegal instruction exception
0x0F: decode I {
0x0: Nop::stbar({{/*stuff*/}}, IsWriteBarrier, MemWriteOp);
0x1: Nop::membar({{/*stuff*/}}, IsMemBarrier, MemReadOp);
}
0x10: Priv::rdpcr({{Rd = Pcr;}});
0x11: PrivCheck::rdpic({{Rd = Pic;}}, {{Pcr<0:>}});
//0x12 should cause an illegal instruction exception
0x13: NoPriv::rdgsr({{
fault = checkFpEnableFault(xc);
if (fault)
return fault;
Rd = Gsr;
}});
//0x14-0x15 should cause an illegal instruction exception
0x16: Priv::rdsoftint({{Rd = Softint;}});
0x17: Priv::rdtick_cmpr({{Rd = TickCmpr;}});
0x18: PrivCheck::rdstick({{Rd = Stick}}, {{Stick<63:>}});
0x19: Priv::rdstick_cmpr({{Rd = StickCmpr;}});
0x1A: Priv::rdstrand_sts_reg({{
if(Pstate<2:> && !Hpstate<2:>)
Rd = StrandStsReg<0:>;
else
Rd = StrandStsReg;
}});
//0x1A is supposed to be reserved, but it reads the strand
//status register.
//0x1B-0x1F should cause an illegal instruction exception
}
0x29: decode RS1 {
0x00: HPriv::rdhprhpstate({{Rd = Hpstate;}});
0x01: HPriv::rdhprhtstate({{
if(Tl == 0)
return new IllegalInstruction;
Rd = Htstate;
}});
//0x02 should cause an illegal instruction exception
0x03: HPriv::rdhprhintp({{Rd = Hintp;}});
//0x04 should cause an illegal instruction exception
0x05: HPriv::rdhprhtba({{Rd = Htba;}});
0x06: HPriv::rdhprhver({{Rd = Hver;}});
//0x07-0x1E should cause an illegal instruction exception
0x1F: HPriv::rdhprhstick_cmpr({{Rd = HstickCmpr;}});
}
0x2A: decode RS1 {
0x00: Priv::rdprtpc({{
if(Tl == 0)
return new IllegalInstruction;
Rd = Tpc;
}});
0x01: Priv::rdprtnpc({{
if(Tl == 0)
return new IllegalInstruction;
Rd = Tnpc;
}});
0x02: Priv::rdprtstate({{
if(Tl == 0)
return new IllegalInstruction;
Rd = Tstate;
}});
0x03: Priv::rdprtt({{
if(Tl == 0)
return new IllegalInstruction;
Rd = Tt;
}});
0x04: Priv::rdprtick({{Rd = Tick;}});
0x05: Priv::rdprtba({{Rd = Tba;}});
0x06: Priv::rdprpstate({{Rd = Pstate;}});
0x07: Priv::rdprtl({{Rd = Tl;}});
0x08: Priv::rdprpil({{Rd = Pil;}});
0x09: Priv::rdprcwp({{Rd = Cwp;}});
0x0A: Priv::rdprcansave({{Rd = Cansave;}});
0x0B: Priv::rdprcanrestore({{Rd = Canrestore;}});
0x0C: Priv::rdprcleanwin({{Rd = Cleanwin;}});
0x0D: Priv::rdprotherwin({{Rd = Otherwin;}});
0x0E: Priv::rdprwstate({{Rd = Wstate;}});
//0x0F should cause an illegal instruction exception
0x10: Priv::rdprgl({{Rd = Gl;}});
//0x11-0x1F should cause an illegal instruction exception
}
0x2B: BasicOperate::flushw({{
if(NWindows - 2 - Cansave != 0)
{
if(Otherwin)
fault = new SpillNOther(4*Wstate<5:3>);
else
fault = new SpillNNormal(4*Wstate<2:0>);
}
}});
0x2C: decode MOVCC3
{
0x0: Trap::movccfcc({{fault = new FpDisabled;}});
0x1: decode CC
{
0x0: movcci({{
if(passesCondition(Ccr<3:0>, COND4))
Rd = Rs2_or_imm11;
else
Rd = Rd;
}});
0x2: movccx({{
if(passesCondition(Ccr<7:4>, COND4))
Rd = Rs2_or_imm11;
else
Rd = Rd;
}});
}
}
0x2D: sdivx({{
if(Rs2_or_imm13.sdw == 0) fault = new DivisionByZero;
else Rd.sdw = Rs1.sdw / Rs2_or_imm13.sdw;
}});
0x2E: Trap::popc({{fault = new IllegalInstruction;}});
0x2F: decode RCOND3
{
0x1: movreq({{Rd = (Rs1.sdw == 0) ? Rs2_or_imm10 : Rd;}});
0x2: movrle({{Rd = (Rs1.sdw <= 0) ? Rs2_or_imm10 : Rd;}});
0x3: movrl({{Rd = (Rs1.sdw < 0) ? Rs2_or_imm10 : Rd;}});
0x5: movrne({{Rd = (Rs1.sdw != 0) ? Rs2_or_imm10 : Rd;}});
0x6: movrg({{Rd = (Rs1.sdw > 0) ? Rs2_or_imm10 : Rd;}});
0x7: movrge({{Rd = (Rs1.sdw >= 0) ? Rs2_or_imm10 : Rd;}});
}
0x30: decode RD {
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;}});
//0x04-0x05 should cause an illegal instruction exception
0x06: NoPriv::wrfprs({{Fprs = Rs1 ^ Rs2_or_imm13;}});
//0x07-0x0E should cause an illegal instruction exception
0x0F: Trap::softreset({{fault = new SoftwareInitiatedReset;}});
0x10: Priv::wrpcr({{Pcr = Rs1 ^ Rs2_or_imm13;}});
0x11: PrivCheck::wrpic({{Pic = Rs1 ^ Rs2_or_imm13;}}, {{Pcr<0:>}});
//0x12 should cause an illegal instruction exception
0x13: NoPriv::wrgsr({{
if(Fprs<2:> == 0 || Pstate<4:> == 0)
return new FpDisabled;
Gsr = Rs1 ^ Rs2_or_imm13;
}});
0x14: Priv::wrsoftint_set({{SoftintSet = Rs1 ^ Rs2_or_imm13;}});
0x15: Priv::wrsoftint_clr({{SoftintClr = Rs1 ^ Rs2_or_imm13;}});
0x16: Priv::wrsoftint({{Softint = Rs1 ^ Rs2_or_imm13;}});
0x17: Priv::wrtick_cmpr({{TickCmpr = Rs1 ^ Rs2_or_imm13;}});
0x18: NoPriv::wrstick({{
if(!Hpstate<2:>)
return new IllegalInstruction;
Stick = Rs1 ^ Rs2_or_imm13;
}});
0x19: Priv::wrstick_cmpr({{StickCmpr = Rs1 ^ Rs2_or_imm13;}});
0x1A: Priv::wrstrand_sts_reg({{
StrandStsReg = Rs1 ^ Rs2_or_imm13;
}});
//0x1A is supposed to be reserved, but it writes the strand
//status register.
//0x1B-0x1F should cause an illegal instruction exception
}
0x31: decode FCN {
0x0: Priv::saved({{
assert(Cansave < NWindows - 2);
assert(Otherwin || Canrestore);
Cansave = Cansave + 1;
if(Otherwin == 0)
Canrestore = Canrestore - 1;
else
Otherwin = Otherwin - 1;
}});
0x1: Priv::restored({{
assert(Cansave || Otherwin);
assert(Canrestore < NWindows - 2);
Canrestore = Canrestore + 1;
if(Otherwin == 0)
Cansave = Cansave - 1;
else
Otherwin = Otherwin - 1;
if(Cleanwin < NWindows - 1)
Cleanwin = Cleanwin + 1;
}});
}
0x32: decode RD {
0x00: Priv::wrprtpc({{
if(Tl == 0)
return new IllegalInstruction;
else
Tpc = Rs1 ^ Rs2_or_imm13;
}});
0x01: Priv::wrprtnpc({{
if(Tl == 0)
return new IllegalInstruction;
else
Tnpc = Rs1 ^ Rs2_or_imm13;
}});
0x02: Priv::wrprtstate({{
if(Tl == 0)
return new IllegalInstruction;
else
Tstate = Rs1 ^ Rs2_or_imm13;
}});
0x03: Priv::wrprtt({{
if(Tl == 0)
return new IllegalInstruction;
else
Tt = Rs1 ^ Rs2_or_imm13;
}});
0x04: HPriv::wrprtick({{Tick = Rs1 ^ Rs2_or_imm13;}});
0x05: Priv::wrprtba({{Tba = Rs1 ^ Rs2_or_imm13;}});
0x06: Priv::wrprpstate({{Pstate = Rs1 ^ Rs2_or_imm13;}});
0x07: Priv::wrprtl({{
if(Pstate<2:> && !Hpstate<2:>)
Tl = std::min<uint64_t>(Rs1 ^ Rs2_or_imm13, MaxPTL);
else
Tl = std::min<uint64_t>(Rs1 ^ Rs2_or_imm13, MaxTL);
}});
0x08: Priv::wrprpil({{Pil = Rs1 ^ Rs2_or_imm13;}});
0x09: Priv::wrprcwp({{Cwp = Rs1 ^ Rs2_or_imm13;}});
0x0A: Priv::wrprcansave({{Cansave = Rs1 ^ Rs2_or_imm13;}});
0x0B: Priv::wrprcanrestore({{Canrestore = Rs1 ^ Rs2_or_imm13;}});
0x0C: Priv::wrprcleanwin({{Cleanwin = Rs1 ^ Rs2_or_imm13;}});
0x0D: Priv::wrprotherwin({{Otherwin = Rs1 ^ Rs2_or_imm13;}});
0x0E: Priv::wrprwstate({{Wstate = Rs1 ^ Rs2_or_imm13;}});
//0x0F should cause an illegal instruction exception
0x10: Priv::wrprgl({{
if(Pstate<2:> && !Hpstate<2:>)
Gl = std::min<uint64_t>(Rs1 ^ Rs2_or_imm13, MaxPGL);
else
Gl = std::min<uint64_t>(Rs1 ^ Rs2_or_imm13, MaxGL);
}});
//0x11-0x1F should cause an illegal instruction exception
}
0x33: decode RD {
0x00: HPriv::wrhprhpstate({{Hpstate = Rs1 ^ Rs2_or_imm13;}});
0x01: HPriv::wrhprhtstate({{
if(Tl == 0)
return new IllegalInstruction;
Htstate = Rs1 ^ Rs2_or_imm13;
}});
//0x02 should cause an illegal instruction exception
0x03: HPriv::wrhprhintp({{Hintp = Rs1 ^ Rs2_or_imm13;}});
//0x04 should cause an illegal instruction exception
0x05: HPriv::wrhprhtba({{Htba = Rs1 ^ Rs2_or_imm13;}});
//0x06-0x01D should cause an illegal instruction exception
0x1F: HPriv::wrhprhstick_cmpr({{HstickCmpr = Rs1 ^ Rs2_or_imm13;}});
}
0x34: decode OPF{
format FpBasic{
0x01: fmovs({{
Frds.uw = Frs2s.uw;
//fsr.ftt = fsr.cexc = 0
Fsr &= ~(7 << 14);
Fsr &= ~(0x1F);
}});
0x02: fmovd({{
Frd.udw = Frs2.udw;
//fsr.ftt = fsr.cexc = 0
Fsr &= ~(7 << 14);
Fsr &= ~(0x1F);
}});
0x03: FpUnimpl::fmovq();
0x05: fnegs({{
Frds.uw = Frs2s.uw ^ (1UL << 31);
//fsr.ftt = fsr.cexc = 0
Fsr &= ~(7 << 14);
Fsr &= ~(0x1F);
}});
0x06: fnegd({{
Frd.udw = Frs2.udw ^ (1ULL << 63);
//fsr.ftt = fsr.cexc = 0
Fsr &= ~(7 << 14);
Fsr &= ~(0x1F);
}});
0x07: FpUnimpl::fnegq();
0x09: fabss({{
Frds.uw = ((1UL << 31) - 1) & Frs2s.uw;
//fsr.ftt = fsr.cexc = 0
Fsr &= ~(7 << 14);
Fsr &= ~(0x1F);
}});
0x0A: fabsd({{
Frd.udw = ((1ULL << 63) - 1) & Frs2.udw;
//fsr.ftt = fsr.cexc = 0
Fsr &= ~(7 << 14);
Fsr &= ~(0x1F);
}});
0x0B: FpUnimpl::fabsq();
0x29: fsqrts({{Frds.sf = std::sqrt(Frs2s.sf);}});
0x2A: fsqrtd({{Frd.df = std::sqrt(Frs2.df);}});
0x2B: FpUnimpl::fsqrtq();
0x41: fadds({{Frds.sf = Frs1s.sf + Frs2s.sf;}});
0x42: faddd({{Frd.df = Frs1.df + Frs2.df;}});
0x43: FpUnimpl::faddq();
0x45: fsubs({{Frds.sf = Frs1s.sf - Frs2s.sf;}});
0x46: fsubd({{Frd.df = Frs1.df - Frs2.df; }});
0x47: FpUnimpl::fsubq();
0x49: fmuls({{Frds.sf = Frs1s.sf * Frs2s.sf;}});
0x4A: fmuld({{Frd.df = Frs1.df * Frs2.df;}});
0x4B: FpUnimpl::fmulq();
0x4D: fdivs({{Frds.sf = Frs1s.sf / Frs2s.sf;}});
0x4E: fdivd({{Frd.df = Frs1.df / Frs2.df;}});
0x4F: FpUnimpl::fdivq();
0x69: fsmuld({{Frd.df = Frs1s.sf * Frs2s.sf;}});
0x6E: FpUnimpl::fdmulq();
0x81: fstox({{
Frd.sdw = static_cast<int64_t>(Frs2s.sf);
}});
0x82: fdtox({{
Frd.sdw = static_cast<int64_t>(Frs2.df);
}});
0x83: FpUnimpl::fqtox();
0x84: fxtos({{
Frds.sf = static_cast<float>(Frs2.sdw);
}});
0x88: fxtod({{
Frd.df = static_cast<double>(Frs2.sdw);
}});
0x8C: FpUnimpl::fxtoq();
0xC4: fitos({{
Frds.sf = static_cast<float>(Frs2s.sw);
}});
0xC6: fdtos({{Frds.sf = Frs2.df;}});
0xC7: FpUnimpl::fqtos();
0xC8: fitod({{
Frd.df = static_cast<double>(Frs2s.sw);
}});
0xC9: fstod({{Frd.df = Frs2s.sf;}});
0xCB: FpUnimpl::fqtod();
0xCC: FpUnimpl::fitoq();
0xCD: FpUnimpl::fstoq();
0xCE: FpUnimpl::fdtoq();
0xD1: fstoi({{
Frds.sw = static_cast<int32_t>(Frs2s.sf);
float t = Frds.sw;
if (t != Frs2s.sf)
Fsr = insertBits(Fsr, 4,0, 0x01);
}});
0xD2: fdtoi({{
Frds.sw = static_cast<int32_t>(Frs2.df);
double t = Frds.sw;
if (t != Frs2.df)
Fsr = insertBits(Fsr, 4,0, 0x01);
}});
0xD3: FpUnimpl::fqtoi();
default: FailUnimpl::fpop1();
}
}
0x35: decode OPF{
format FpBasic{
0x51: fcmps({{
uint8_t fcc;
if(isnan(Frs1s) || isnan(Frs2s))
fcc = 3;
else if(Frs1s < Frs2s)
fcc = 1;
else if(Frs1s > Frs2s)
fcc = 2;
else
fcc = 0;
uint8_t firstbit = 10;
if(FCMPCC)
firstbit = FCMPCC * 2 + 30;
Fsr = insertBits(Fsr, firstbit +1, firstbit, fcc);
}});
0x52: fcmpd({{
uint8_t fcc;
if(isnan(Frs1) || isnan(Frs2))
fcc = 3;
else if(Frs1 < Frs2)
fcc = 1;
else if(Frs1 > Frs2)
fcc = 2;
else
fcc = 0;
uint8_t firstbit = 10;
if(FCMPCC)
firstbit = FCMPCC * 2 + 30;
Fsr = insertBits(Fsr, firstbit +1, firstbit, fcc);
}});
0x53: FpUnimpl::fcmpq();
0x55: fcmpes({{
uint8_t fcc = 0;
if(isnan(Frs1s) || isnan(Frs2s))
fault = new FpExceptionIEEE754;
if(Frs1s < Frs2s)
fcc = 1;
else if(Frs1s > Frs2s)
fcc = 2;
uint8_t firstbit = 10;
if(FCMPCC)
firstbit = FCMPCC * 2 + 30;
Fsr = insertBits(Fsr, firstbit +1, firstbit, fcc);
}});
0x56: fcmped({{
uint8_t fcc = 0;
if(isnan(Frs1) || isnan(Frs2))
fault = new FpExceptionIEEE754;
if(Frs1 < Frs2)
fcc = 1;
else if(Frs1 > Frs2)
fcc = 2;
uint8_t firstbit = 10;
if(FCMPCC)
firstbit = FCMPCC * 2 + 30;
Fsr = insertBits(Fsr, firstbit +1, firstbit, fcc);
}});
0x57: FpUnimpl::fcmpeq();
default: FailUnimpl::fpop2();
}
}
//This used to be just impdep1, but now it's a whole bunch
//of instructions
0x36: decode OPF{
0x00: FailUnimpl::edge8();
0x01: FailUnimpl::edge8n();
0x02: FailUnimpl::edge8l();
0x03: FailUnimpl::edge8ln();
0x04: FailUnimpl::edge16();
0x05: FailUnimpl::edge16n();
0x06: FailUnimpl::edge16l();
0x07: FailUnimpl::edge16ln();
0x08: FailUnimpl::edge32();
0x09: FailUnimpl::edge32n();
0x0A: FailUnimpl::edge32l();
0x0B: FailUnimpl::edge32ln();
0x10: FailUnimpl::array8();
0x12: FailUnimpl::array16();
0x14: FailUnimpl::array32();
0x18: BasicOperate::alignaddr({{
uint64_t sum = Rs1 + Rs2;
Rd = sum & ~7;
Gsr = (Gsr & ~7) | (sum & 7);
}});
0x19: FailUnimpl::bmask();
0x1A: BasicOperate::alignaddresslittle({{
uint64_t sum = Rs1 + Rs2;
Rd = sum & ~7;
Gsr = (Gsr & ~7) | ((~sum + 1) & 7);
}});
0x20: FailUnimpl::fcmple16();
0x22: FailUnimpl::fcmpne16();
0x24: FailUnimpl::fcmple32();
0x26: FailUnimpl::fcmpne32();
0x28: FailUnimpl::fcmpgt16();
0x2A: FailUnimpl::fcmpeq16();
0x2C: FailUnimpl::fcmpgt32();
0x2E: FailUnimpl::fcmpeq32();
0x31: FailUnimpl::fmul8x16();
0x33: FailUnimpl::fmul8x16au();
0x35: FailUnimpl::fmul8x16al();
0x36: FailUnimpl::fmul8sux16();
0x37: FailUnimpl::fmul8ulx16();
0x38: FailUnimpl::fmuld8sux16();
0x39: FailUnimpl::fmuld8ulx16();
0x3A: Trap::fpack32({{fault = new IllegalInstruction;}});
0x3B: Trap::fpack16({{fault = new IllegalInstruction;}});
0x3D: Trap::fpackfix({{fault = new IllegalInstruction;}});
0x3E: Trap::pdist({{fault = new IllegalInstruction;}});
0x48: BasicOperate::faligndata({{
uint64_t msbX = Frs1.udw;
uint64_t lsbX = Frs2.udw;
//Some special cases need to be split out, first
//because they're the most likely to be used, and
//second because otherwise, we end up shifting by
//greater than the width of the type being shifted,
//namely 64, which produces undefined results according
//to the C standard.
switch(Gsr<2:0>)
{
case 0:
Frd.udw = msbX;
break;
case 8:
Frd.udw = lsbX;
break;
default:
uint64_t msbShift = Gsr<2:0> * 8;
uint64_t lsbShift = (8 - Gsr<2:0>) * 8;
uint64_t msbMask = ((uint64_t)(-1)) >> msbShift;
uint64_t lsbMask = ((uint64_t)(-1)) << lsbShift;
Frd.udw = ((msbX & msbMask) << msbShift) |
((lsbX & lsbMask) >> lsbShift);
}
}});
0x4B: Trap::fpmerge({{fault = new IllegalInstruction;}});
0x4C: FailUnimpl::bshuffle();
0x4D: FailUnimpl::fexpand();
0x50: FailUnimpl::fpadd16();
0x51: FailUnimpl::fpadd16s();
0x52: FailUnimpl::fpadd32();
0x53: FailUnimpl::fpadd32s();
0x54: FailUnimpl::fpsub16();
0x55: FailUnimpl::fpsub16s();
0x56: FailUnimpl::fpsub32();
0x57: FailUnimpl::fpsub32s();
0x60: FpBasic::fzero({{Frd.df = 0;}});
0x61: FpBasic::fzeros({{Frds.sf = 0;}});
0x62: FailUnimpl::fnor();
0x63: FailUnimpl::fnors();
0x64: FailUnimpl::fandnot2();
0x65: FailUnimpl::fandnot2s();
0x66: FpBasic::fnot2({{
Frd.df = (double)(~((uint64_t)Frs2.df));
}});
0x67: FpBasic::fnot2s({{
Frds.sf = (float)(~((uint32_t)Frs2s.sf));
}});
0x68: FailUnimpl::fandnot1();
0x69: FailUnimpl::fandnot1s();
0x6A: FpBasic::fnot1({{
Frd.df = (double)(~((uint64_t)Frs1.df));
}});
0x6B: FpBasic::fnot1s({{
Frds.sf = (float)(~((uint32_t)Frs1s.sf));
}});
0x6C: FailUnimpl::fxor();
0x6D: FailUnimpl::fxors();
0x6E: FailUnimpl::fnand();
0x6F: FailUnimpl::fnands();
0x70: FailUnimpl::fand();
0x71: FailUnimpl::fands();
0x72: FailUnimpl::fxnor();
0x73: FailUnimpl::fxnors();
0x74: FpBasic::fsrc1({{Frd.udw = Frs1.udw;}});
0x75: FpBasic::fsrc1s({{Frds.uw = Frs1s.uw;}});
0x76: FailUnimpl::fornot2();
0x77: FailUnimpl::fornot2s();
0x78: FpBasic::fsrc2({{Frd.udw = Frs2.udw;}});
0x79: FpBasic::fsrc2s({{Frds.uw = Frs2s.uw;}});
0x7A: FailUnimpl::fornot1();
0x7B: FailUnimpl::fornot1s();
0x7C: FailUnimpl::for();
0x7D: FailUnimpl::fors();
0x7E: FpBasic::fone({{Frd.udw = std::numeric_limits<uint64_t>::max();}});
0x7F: FpBasic::fones({{Frds.uw = std::numeric_limits<uint32_t>::max();}});
0x80: Trap::shutdown({{fault = new IllegalInstruction;}});
0x81: FailUnimpl::siam();
}
// M5 special opcodes use the reserved IMPDEP2A opcode space
0x37: decode M5FUNC {
#if FULL_SYSTEM
format BasicOperate {
// we have 7 bits of space here to play with...
0x21: m5exit({{PseudoInst::m5exit(xc->tcBase(), O0);
}}, No_OpClass, IsNonSpeculative);
0x50: m5readfile({{
O0 = PseudoInst::readfile(xc->tcBase(), O0, O1, O2);
}}, IsNonSpeculative);
0x51: m5break({{PseudoInst::debugbreak(xc->tcBase());
}}, IsNonSpeculative);
0x54: m5panic({{
panic("M5 panic instruction called at pc=%#x.", xc->readPC());
}}, No_OpClass, IsNonSpeculative);
}
#endif
default: Trap::impdep2({{fault = new IllegalInstruction;}});
}
0x38: Branch::jmpl({{
Addr target = Rs1 + Rs2_or_imm13;
if(target & 0x3)
fault = new MemAddressNotAligned;
else
{
if (Pstate<3:>)
Rd = (xc->readPC())<31:0>;
else
Rd = xc->readPC();
NNPC = target;
}
}});
0x39: Branch::return({{
Addr target = Rs1 + Rs2_or_imm13;
if(fault == NoFault)
{
//Check for fills which are higher priority than alignment
//faults.
if(Canrestore == 0)
{
if(Otherwin)
fault = new FillNOther(4*Wstate<5:3>);
else
fault = new FillNNormal(4*Wstate<2:0>);
}
//Check for alignment faults
else if(target & 0x3)
fault = new MemAddressNotAligned;
else
{
NNPC = target;
Cwp = (Cwp - 1 + NWindows) % NWindows;
Cansave = Cansave + 1;
Canrestore = Canrestore - 1;
}
}
}});
0x3A: decode CC
{
0x0: Trap::tcci({{
if(passesCondition(Ccr<3:0>, COND2))
{
int lTrapNum = I ? (Rs1 + SW_TRAP) : (Rs1 + Rs2);
DPRINTF(Sparc, "The trap number is %d\n", lTrapNum);
fault = new TrapInstruction(lTrapNum);
}
}}, IsSerializeAfter, IsNonSpeculative);
0x2: Trap::tccx({{
if(passesCondition(Ccr<7:4>, COND2))
{
int lTrapNum = I ? (Rs1 + SW_TRAP) : (Rs1 + Rs2);
DPRINTF(Sparc, "The trap number is %d\n", lTrapNum);
fault = new TrapInstruction(lTrapNum);
}
}}, IsSerializeAfter, IsNonSpeculative);
}
0x3B: Nop::flush({{/*Instruction memory flush*/}}, IsWriteBarrier,
MemWriteOp);
0x3C: save({{
if(Cansave == 0)
{
if(Otherwin)
fault = new SpillNOther(4*Wstate<5:3>);
else
fault = new SpillNNormal(4*Wstate<2:0>);
}
else if(Cleanwin - Canrestore == 0)
{
fault = new CleanWindow;
}
else
{
Cwp = (Cwp + 1) % NWindows;
Rd_next = Rs1 + Rs2_or_imm13;
Cansave = Cansave - 1;
Canrestore = Canrestore + 1;
}
}});
0x3D: restore({{
if(Canrestore == 0)
{
if(Otherwin)
fault = new FillNOther(4*Wstate<5:3>);
else
fault = new FillNNormal(4*Wstate<2:0>);
}
else
{
Cwp = (Cwp - 1 + NWindows) % NWindows;
Rd_prev = Rs1 + Rs2_or_imm13;
Cansave = Cansave + 1;
Canrestore = Canrestore - 1;
}
}});
0x3E: decode FCN {
0x0: Priv::done({{
if(Tl == 0)
return new IllegalInstruction;
Cwp = Tstate<4:0>;
Pstate = Tstate<20:8>;
Asi = Tstate<31:24>;
Ccr = Tstate<39:32>;
Gl = Tstate<42:40>;
Hpstate = Htstate;
NPC = Tnpc;
NNPC = Tnpc + 4;
Tl = Tl - 1;
}});
0x1: Priv::retry({{
if(Tl == 0)
return new IllegalInstruction;
Cwp = Tstate<4:0>;
Pstate = Tstate<20:8>;
Asi = Tstate<31:24>;
Ccr = Tstate<39:32>;
Gl = Tstate<42:40>;
Hpstate = Htstate;
NPC = Tpc;
NNPC = Tnpc;
Tl = Tl - 1;
}});
}
}
}
0x3: decode OP3 {
format Load {
0x00: lduw({{Rd = Mem.uw;}});
0x01: ldub({{Rd = Mem.ub;}});
0x02: lduh({{Rd = Mem.uhw;}});
0x03: ldtw({{
RdLow = (Mem.tuw).a;
RdHigh = (Mem.tuw).b;
}});
}
format Store {
0x04: stw({{Mem.uw = Rd.sw;}});
0x05: stb({{Mem.ub = Rd.sb;}});
0x06: sth({{Mem.uhw = Rd.shw;}});
0x07: sttw({{Mem.udw = RdLow<31:0> | (RdHigh<31:0> << 32);}});
}
format Load {
0x08: ldsw({{Rd = (int32_t)Mem.sw;}});
0x09: ldsb({{Rd = (int8_t)Mem.sb;}});
0x0A: ldsh({{Rd = (int16_t)Mem.shw;}});
0x0B: ldx({{Rd = (int64_t)Mem.sdw;}});
}
0x0D: Swap::ldstub({{Mem.ub = 0xFF;}},
{{
uint8_t tmp = mem_data;
Rd.ub = tmp;
}}, MEM_SWAP);
0x0E: Store::stx({{Mem.udw = Rd}});
0x0F: Swap::swap({{Mem.uw = Rd.uw}},
{{
uint32_t tmp = mem_data;
Rd.uw = tmp;
}}, MEM_SWAP);
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(
{{RdLow.udw = (Mem.tudw).a;
RdHigh.udw = (Mem.tudw).b;}}, {{EXT_ASI}});
//ASI_LDTD_AIUS
0x23: TwinLoad::ldtx_aius(
{{RdLow.udw = (Mem.tudw).a;
RdHigh.udw = (Mem.tudw).b;}}, {{EXT_ASI}});
//ASI_QUAD_LDD
0x24: TwinLoad::ldtx_quad_ldd(
{{RdLow.udw = (Mem.tudw).a;
RdHigh.udw = (Mem.tudw).b;}}, {{EXT_ASI}});
//ASI_LDTX_REAL
0x26: TwinLoad::ldtx_real(
{{RdLow.udw = (Mem.tudw).a;
RdHigh.udw = (Mem.tudw).b;}}, {{EXT_ASI}});
//ASI_LDTX_N
0x27: TwinLoad::ldtx_n(
{{RdLow.udw = (Mem.tudw).a;
RdHigh.udw = (Mem.tudw).b;}}, {{EXT_ASI}});
//ASI_LDTX_AIUP_L
0x2A: TwinLoad::ldtx_aiup_l(
{{RdLow.udw = (Mem.tudw).a;
RdHigh.udw = (Mem.tudw).b;}}, {{EXT_ASI}});
//ASI_LDTX_AIUS_L
0x2B: TwinLoad::ldtx_aius_l(
{{RdLow.udw = (Mem.tudw).a;
RdHigh.udw = (Mem.tudw).b;}}, {{EXT_ASI}});
//ASI_LDTX_L
0x2C: TwinLoad::ldtx_l(
{{RdLow.udw = (Mem.tudw).a;
RdHigh.udw = (Mem.tudw).b;}}, {{EXT_ASI}});
//ASI_LDTX_REAL_L
0x2E: TwinLoad::ldtx_real_l(
{{RdLow.udw = (Mem.tudw).a;
RdHigh.udw = (Mem.tudw).b;}}, {{EXT_ASI}});
//ASI_LDTX_N_L
0x2F: TwinLoad::ldtx_n_l(
{{RdLow.udw = (Mem.tudw).a;
RdHigh.udw = (Mem.tudw).b;}}, {{EXT_ASI}});
//ASI_LDTX_P
0xE2: TwinLoad::ldtx_p(
{{RdLow.udw = (Mem.tudw).a;
RdHigh.udw = (Mem.tudw).b;}}, {{EXT_ASI}});
//ASI_LDTX_S
0xE3: TwinLoad::ldtx_s(
{{RdLow.udw = (Mem.tudw).a;
RdHigh.udw = (Mem.tudw).b;}}, {{EXT_ASI}});
//ASI_LDTX_PL
0xEA: TwinLoad::ldtx_pl(
{{RdLow.udw = (Mem.tudw).a;
RdHigh.udw = (Mem.tudw).b;}}, {{EXT_ASI}});
//ASI_LDTX_SL
0xEB: TwinLoad::ldtx_sl(
{{RdLow.udw = (Mem.tudw).a;
RdHigh.udw = (Mem.tudw).b;}}, {{EXT_ASI}});
default: ldtwa({{
RdLow = (Mem.tuw).a;
RdHigh = (Mem.tuw).b;
}}, {{EXT_ASI}});
}
}
format StoreAlt {
0x14: stwa({{Mem.uw = Rd;}}, {{EXT_ASI}});
0x15: stba({{Mem.ub = Rd;}}, {{EXT_ASI}});
0x16: stha({{Mem.uhw = Rd;}}, {{EXT_ASI}});
0x17: sttwa({{Mem.udw = RdLow<31:0> | RdHigh<31:0> << 32;}}, {{EXT_ASI}});
}
format LoadAlt {
0x18: ldswa({{Rd = (int32_t)Mem.sw;}}, {{EXT_ASI}});
0x19: ldsba({{Rd = (int8_t)Mem.sb;}}, {{EXT_ASI}});
0x1A: ldsha({{Rd = (int16_t)Mem.shw;}}, {{EXT_ASI}});
0x1B: ldxa({{Rd = (int64_t)Mem.sdw;}}, {{EXT_ASI}});
}
0x1D: SwapAlt::ldstuba({{Mem.ub = 0xFF;}},
{{
uint8_t tmp = mem_data;
Rd.ub = tmp;
}}, {{EXT_ASI}}, MEM_SWAP);
0x1E: StoreAlt::stxa({{Mem.udw = Rd}}, {{EXT_ASI}});
0x1F: SwapAlt::swapa({{Mem.uw = Rd.uw}},
{{
uint32_t tmp = mem_data;
Rd.uw = tmp;
}}, {{EXT_ASI}}, MEM_SWAP);
format Trap {
0x20: Load::ldf({{Frds.uw = Mem.uw;}});
0x21: decode RD {
0x0: Load::ldfsr({{fault = checkFpEnableFault(xc);
if (fault)
return fault;
Fsr = Mem.uw | Fsr<63:32>;}});
0x1: Load::ldxfsr({{fault = checkFpEnableFault(xc);
if (fault)
return fault;
Fsr = Mem.udw;}});
default: FailUnimpl::ldfsrOther();
}
0x22: ldqf({{fault = new FpDisabled;}});
0x23: Load::lddf({{Frd.udw = Mem.udw;}});
0x24: Store::stf({{Mem.uw = Frds.uw;}});
0x25: decode RD {
0x0: Store::stfsr({{fault = checkFpEnableFault(xc);
if (fault)
return fault;
Mem.uw = Fsr<31:0>;
Fsr = insertBits(Fsr,16,14,0);}});
0x1: Store::stxfsr({{fault = checkFpEnableFault(xc);
if (fault)
return fault;
Mem.udw = Fsr;
Fsr = insertBits(Fsr,16,14,0);}});
default: FailUnimpl::stfsrOther();
}
0x26: stqf({{fault = new FpDisabled;}});
0x27: Store::stdf({{Mem.udw = Frd.udw;}});
0x2D: Nop::prefetch({{ }});
0x30: LoadAlt::ldfa({{Frds.uw = Mem.uw;}}, {{EXT_ASI}});
0x32: ldqfa({{fault = new FpDisabled;}});
format LoadAlt {
0x33: decode EXT_ASI {
//ASI_NUCLEUS
0x04: FailUnimpl::lddfa_n();
//ASI_NUCLEUS_LITTLE
0x0C: FailUnimpl::lddfa_nl();
//ASI_AS_IF_USER_PRIMARY
0x10: FailUnimpl::lddfa_aiup();
//ASI_AS_IF_USER_PRIMARY_LITTLE
0x18: FailUnimpl::lddfa_aiupl();
//ASI_AS_IF_USER_SECONDARY
0x11: FailUnimpl::lddfa_aius();
//ASI_AS_IF_USER_SECONDARY_LITTLE
0x19: FailUnimpl::lddfa_aiusl();
//ASI_REAL
0x14: FailUnimpl::lddfa_real();
//ASI_REAL_LITTLE
0x1C: FailUnimpl::lddfa_real_l();
//ASI_REAL_IO
0x15: FailUnimpl::lddfa_real_io();
//ASI_REAL_IO_LITTLE
0x1D: FailUnimpl::lddfa_real_io_l();
//ASI_PRIMARY
0x80: FailUnimpl::lddfa_p();
//ASI_PRIMARY_LITTLE
0x88: FailUnimpl::lddfa_pl();
//ASI_SECONDARY
0x81: FailUnimpl::lddfa_s();
//ASI_SECONDARY_LITTLE
0x89: FailUnimpl::lddfa_sl();
//ASI_PRIMARY_NO_FAULT
0x82: FailUnimpl::lddfa_pnf();
//ASI_PRIMARY_NO_FAULT_LITTLE
0x8A: FailUnimpl::lddfa_pnfl();
//ASI_SECONDARY_NO_FAULT
0x83: FailUnimpl::lddfa_snf();
//ASI_SECONDARY_NO_FAULT_LITTLE
0x8B: FailUnimpl::lddfa_snfl();
format BlockLoad {
// LDBLOCKF
//ASI_BLOCK_AS_IF_USER_PRIMARY
0x16: FailUnimpl::ldblockf_aiup();
//ASI_BLOCK_AS_IF_USER_SECONDARY
0x17: FailUnimpl::ldblockf_aius();
//ASI_BLOCK_AS_IF_USER_PRIMARY_LITTLE
0x1E: FailUnimpl::ldblockf_aiupl();
//ASI_BLOCK_AS_IF_USER_SECONDARY_LITTLE
0x1F: FailUnimpl::ldblockf_aiusl();
//ASI_BLOCK_PRIMARY
0xF0: ldblockf_p({{Frd_N.udw = Mem.udw;}}, {{EXT_ASI}});
//ASI_BLOCK_SECONDARY
0xF1: FailUnimpl::ldblockf_s();
//ASI_BLOCK_PRIMARY_LITTLE
0xF8: FailUnimpl::ldblockf_pl();
//ASI_BLOCK_SECONDARY_LITTLE
0xF9: FailUnimpl::ldblockf_sl();
}
//LDSHORTF
//ASI_FL8_PRIMARY
0xD0: FailUnimpl::ldshortf_8p();
//ASI_FL8_SECONDARY
0xD1: FailUnimpl::ldshortf_8s();
//ASI_FL8_PRIMARY_LITTLE
0xD8: FailUnimpl::ldshortf_8pl();
//ASI_FL8_SECONDARY_LITTLE
0xD9: FailUnimpl::ldshortf_8sl();
//ASI_FL16_PRIMARY
0xD2: FailUnimpl::ldshortf_16p();
//ASI_FL16_SECONDARY
0xD3: FailUnimpl::ldshortf_16s();
//ASI_FL16_PRIMARY_LITTLE
0xDA: FailUnimpl::ldshortf_16pl();
//ASI_FL16_SECONDARY_LITTLE
0xDB: FailUnimpl::ldshortf_16sl();
//Not an ASI which is legal with lddfa
default: Trap::lddfa_bad_asi(
{{fault = new DataAccessException;}});
}
}
0x34: Store::stfa({{Mem.uw = Frds.uw;}});
0x36: stqfa({{fault = new FpDisabled;}});
format StoreAlt {
0x37: decode EXT_ASI {
//ASI_NUCLEUS
0x04: FailUnimpl::stdfa_n();
//ASI_NUCLEUS_LITTLE
0x0C: FailUnimpl::stdfa_nl();
//ASI_AS_IF_USER_PRIMARY
0x10: FailUnimpl::stdfa_aiup();
//ASI_AS_IF_USER_PRIMARY_LITTLE
0x18: FailUnimpl::stdfa_aiupl();
//ASI_AS_IF_USER_SECONDARY
0x11: FailUnimpl::stdfa_aius();
//ASI_AS_IF_USER_SECONDARY_LITTLE
0x19: FailUnimpl::stdfa_aiusl();
//ASI_REAL
0x14: FailUnimpl::stdfa_real();
//ASI_REAL_LITTLE
0x1C: FailUnimpl::stdfa_real_l();
//ASI_REAL_IO
0x15: FailUnimpl::stdfa_real_io();
//ASI_REAL_IO_LITTLE
0x1D: FailUnimpl::stdfa_real_io_l();
//ASI_PRIMARY
0x80: FailUnimpl::stdfa_p();
//ASI_PRIMARY_LITTLE
0x88: FailUnimpl::stdfa_pl();
//ASI_SECONDARY
0x81: FailUnimpl::stdfa_s();
//ASI_SECONDARY_LITTLE
0x89: FailUnimpl::stdfa_sl();
//ASI_PRIMARY_NO_FAULT
0x82: FailUnimpl::stdfa_pnf();
//ASI_PRIMARY_NO_FAULT_LITTLE
0x8A: FailUnimpl::stdfa_pnfl();
//ASI_SECONDARY_NO_FAULT
0x83: FailUnimpl::stdfa_snf();
//ASI_SECONDARY_NO_FAULT_LITTLE
0x8B: FailUnimpl::stdfa_snfl();
format BlockStore {
// STBLOCKF
//ASI_BLOCK_AS_IF_USER_PRIMARY
0x16: FailUnimpl::stblockf_aiup();
//ASI_BLOCK_AS_IF_USER_SECONDARY
0x17: FailUnimpl::stblockf_aius();
//ASI_BLOCK_AS_IF_USER_PRIMARY_LITTLE
0x1E: FailUnimpl::stblockf_aiupl();
//ASI_BLOCK_AS_IF_USER_SECONDARY_LITTLE
0x1F: FailUnimpl::stblockf_aiusl();
//ASI_BLOCK_PRIMARY
0xF0: stblockf_p({{Mem.udw = Frd_N.udw;}}, {{EXT_ASI}});
//ASI_BLOCK_SECONDARY
0xF1: FailUnimpl::stblockf_s();
//ASI_BLOCK_PRIMARY_LITTLE
0xF8: FailUnimpl::stblockf_pl();
//ASI_BLOCK_SECONDARY_LITTLE
0xF9: FailUnimpl::stblockf_sl();
}
//STSHORTF
//ASI_FL8_PRIMARY
0xD0: FailUnimpl::stshortf_8p();
//ASI_FL8_SECONDARY
0xD1: FailUnimpl::stshortf_8s();
//ASI_FL8_PRIMARY_LITTLE
0xD8: FailUnimpl::stshortf_8pl();
//ASI_FL8_SECONDARY_LITTLE
0xD9: FailUnimpl::stshortf_8sl();
//ASI_FL16_PRIMARY
0xD2: FailUnimpl::stshortf_16p();
//ASI_FL16_SECONDARY
0xD3: FailUnimpl::stshortf_16s();
//ASI_FL16_PRIMARY_LITTLE
0xDA: FailUnimpl::stshortf_16pl();
//ASI_FL16_SECONDARY_LITTLE
0xDB: FailUnimpl::stshortf_16sl();
//Not an ASI which is legal with lddfa
default: Trap::stdfa_bad_asi(
{{fault = new DataAccessException;}});
}
}
0x3C: CasAlt::casa({{
mem_data = htog(Rs2.uw);
Mem.uw = Rd.uw;}},
{{
uint32_t tmp = mem_data;
Rd.uw = tmp;
}}, {{EXT_ASI}}, MEM_SWAP_COND);
0x3D: Nop::prefetcha({{ }});
0x3E: CasAlt::casxa({{mem_data = gtoh(Rs2);
Mem.udw = Rd.udw; }},
{{ Rd.udw = mem_data; }}, {{EXT_ASI}}, MEM_SWAP_COND);
}
}
}