Files
gem5/src/arch/sparc/isa/decoder.isa
Gabe Black 695414217f sparc: Pull most of the Nop format out of the ISA description.
The Nop format mostly just made instructions that inherited from the
Nop base class but with different mnemonics, so there doesn't need
to be very much dynamic content.

Change-Id: I1cf5e25ca8372f9b71f56d49756879c7545c9f6c
Reviewed-on: https://gem5-review.googlesource.com/5462
Reviewed-by: Gabe Black <gabeblack@google.com>
Maintainer: Gabe Black <gabeblack@google.com>
2017-11-22 00:22:16 +00:00

1450 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 = std::make_shared<IllegalInstruction>();}});
format BranchN
{
// bpcc
0x1: decode COND2
{
// Branch Always
0x8: bpa(19, annul_code={{
NPC = PC + disp;
NNPC = PC + disp + 4;
}});
// Branch Never
0x0: bpn(19, {{;}},
annul_code={{
NNPC = NPC + 8;
NPC = NPC + 4;
}});
default: decode BPCC
{
0x0: bpcci(19, test={{passesCondition(Ccr<3:0>, COND2)}});
0x2: bpccx(19, test={{passesCondition(Ccr<7:4>, COND2)}});
}
}
// bicc
0x2: decode COND2
{
// Branch Always
0x8: ba(22, annul_code={{
NPC = PC + disp;
NNPC = PC + disp + 4;
}});
// Branch Never
0x0: bn(22, {{;}},
annul_code={{
NNPC = NPC + 8;
NPC = NPC + 4;
}});
default: bicc(22, test={{passesCondition(Ccr<3:0>, COND2)}});
}
}
0x3: decode RCOND2
{
format BranchSplit
{
0x1: bpreq(test={{Rs1_sdw == 0}});
0x2: bprle(test={{Rs1_sdw <= 0}});
0x3: bprl(test={{Rs1_sdw < 0}});
0x5: bprne(test={{Rs1_sdw != 0}});
0x6: bprg(test={{Rs1_sdw > 0}});
0x7: bprge(test={{Rs1_sdw >= 0}});
}
}
// SETHI (or NOP if rd == 0 and imm == 0)
0x4: SetHi::sethi({{Rd_udw = imm;}});
// fbpfcc
0x5: decode COND2 {
format BranchN {
// Branch Always
0x8: fbpa(22, annul_code={{
NPC = PC + disp;
NNPC = PC + disp + 4;
}});
// Branch Never
0x0: fbpn(22, {{;}},
annul_code={{
NNPC = NPC + 8;
NPC = NPC + 4;
}});
default: decode BPCC {
0x0: fbpfcc0(19, test=
{{passesFpCondition(Fsr<11:10>, COND2)}});
0x1: fbpfcc1(19, test=
{{passesFpCondition(Fsr<33:32>, COND2)}});
0x2: fbpfcc2(19, test=
{{passesFpCondition(Fsr<35:34>, COND2)}});
0x3: fbpfcc3(19, test=
{{passesFpCondition(Fsr<37:36>, COND2)}});
}
}
}
// fbfcc
0x6: decode COND2 {
format BranchN {
// Branch Always
0x8: fba(22, annul_code={{
NPC = PC + disp;
NNPC = PC + disp + 4;
}});
// Branch Never
0x0: fbn(22, {{;}},
annul_code={{
NNPC = NPC + 8;
NPC = NPC + 4;
}});
default: fbfcc(22, test=
{{passesFpCondition(Fsr<11:10>, COND2)}});
}
}
}
0x1: BranchN::call(30, {{
IntReg midVal;
R15 = midVal = (Pstate.am ? (PC)<31:0> : PC);
NNPC = midVal + disp;
}},None, None, IsIndirectControl, IsCall);
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 = std::make_shared<DivisionByZero>();
else
Rd_udw = Rs1_udw / Rs2_or_imm13;
}});
0x0E: udiv({{
if (Rs2_or_imm13 == 0) {
fault = std::make_shared<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 = std::make_shared<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 res, op1 = Rs1, op2 = Rs2_or_imm13;
Rd = res = op1 + op2;
}});
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 res, op1 = Rs1, op2 = Rs2_or_imm13;
Rd = res = op1 - op2;
}}, sub=True);
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 res, op1 = Rs1, op2 = Rs2_or_imm13;
Rd = res = op1 + op2 + Ccr<0:>;
}});
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 res, op1 = Rs1, op2 = Rs2_or_imm13;
Rd = res = op1 - op2 - Ccr<0:>;
}}, sub=True);
0x1D: IntOpCcRes::udivxcc({{
if (Rs2_or_imm13_udw == 0)
fault = std::make_shared<DivisionByZero>();
else
Rd = Rs1_udw / Rs2_or_imm13_udw;}});
0x1E: IntOpCcRes::udivcc({{
uint64_t resTemp;
uint32_t val2 = Rs2_or_imm13_udw;
int32_t overflow = 0;
if (val2 == 0) {
fault = std::make_shared<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;
}
}}, iv={{overflow}});
0x1F: IntOpCcRes::sdivcc({{
int64_t val2 = Rs2_or_imm13_sdw<31:0>;
bool overflow = false, underflow = false;
if (val2 == 0) {
fault = std::make_shared<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);
}
}}, iv={{overflow || underflow}});
0x20: taddcc({{
int64_t res, op1 = Rs1, op2 = Rs2_or_imm13;
Rd = res = Rs1 + op2;
}}, iv={{
(op1 & mask(2)) || (op2 & mask(2)) ||
findOverflow(32, res, op1, op2)
}});
0x21: tsubcc({{
int64_t res, op1 = Rs1, op2 = Rs2_or_imm13;
Rd = res = Rs1 - op2;
}}, iv={{
(op1 & mask(2)) || (op2 & mask(2)) ||
findOverflow(32, res, op1, ~op2)
}}, sub=True);
0x22: taddcctv({{
int64_t res, op1 = Rs1, op2 = Rs2_or_imm13;
Rd = res = op1 + op2;
bool overflow = (op1 & mask(2)) || (op2 & mask(2)) ||
findOverflow(32, res, op1, op2);
if (overflow)
fault = std::make_shared<TagOverflow>();
}}, iv={{overflow}});
0x23: tsubcctv({{
int64_t res, op1 = Rs1, op2 = Rs2_or_imm13;
Rd = res = op1 - op2;
bool overflow = (op1 & mask(2)) || (op2 & mask(2)) ||
findOverflow(32, res, op1, ~op2);
if (overflow)
fault = std::make_shared<TagOverflow>();
}}, iv={{overflow}}, sub=True);
0x24: mulscc({{
int32_t savedLSB = Rs1<0:>;
// Step 1
int64_t multiplicand = Rs2_or_imm13;
// Step 2
int32_t partialP = Rs1<31:1> |
((Ccr<3:3> ^ Ccr<1:1>) << 31);
// Step 3
int32_t added = Y<0:> ? multiplicand : 0;
int64_t res, op1 = partialP, op2 = added;
Rd = res = partialP + added;
// Steps 4 & 5
Y = Y<31:1> | (savedLSB << 31);
}});
}
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: Priv::rdtick({{Rd = Tick;}}, {{Tick<63:>}});
0x05: NoPriv::rdpc({{
if (Pstate.am)
Rd = (PC)<31:0>;
else
Rd = PC;
}});
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(IsWriteBarrier, MemWriteOp);
0x1: Nop::membar(IsMemBarrier, MemReadOp);
}
0x10: Priv::rdpcr({{Rd = Pcr;}});
0x11: Priv::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: Priv::rdstick({{Rd = Stick}}, {{Stick<63:>}});
0x19: Priv::rdstick_cmpr({{Rd = StickCmpr;}});
0x1A: Priv::rdstrand_sts_reg({{
if (Pstate.am && !Hpstate.hpriv)
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({{Rd = Htstate;}}, check_tl=true);
// 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({{Rd = Tpc;}}, check_tl=true);
0x01: Priv::rdprtnpc({{Rd = Tnpc;}}, check_tl=true);
0x02: Priv::rdprtstate({{Rd = Tstate;}}, check_tl=true);
0x03: Priv::rdprtt({{Rd = Tt;}}, check_tl=true);
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 = std::make_shared<SpillNOther>(4*Wstate<5:3>);
else
fault = std::make_shared<SpillNNormal>(4*Wstate<2:0>);
}
}});
0x2C: decode MOVCC3
{
0x0: decode CC
{
0x0: movccfcc0({{
if (passesCondition(Fsr<11:10>, COND4))
Rd = Rs2_or_imm11;
else
Rd = Rd;
}});
0x1: movccfcc1({{
if (passesCondition(Fsr<33:32>, COND4))
Rd = Rs2_or_imm11;
else
Rd = Rd;
}});
0x2: movccfcc2({{
if (passesCondition(Fsr<35:34>, COND4))
Rd = Rs2_or_imm11;
else
Rd = Rd;
}});
0x3: movccfcc3({{
if (passesCondition(Fsr<37:36>, COND4))
Rd = Rs2_or_imm11;
else
Rd = Rd;
}});
}
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 = std::make_shared<DivisionByZero>();
else
Rd_sdw = Rs1_sdw / Rs2_or_imm13_sdw;
}});
0x2E: Trap::popc({{fault = std::make_shared<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;}},
IsSquashAfter);
// 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 = std::make_shared<SoftwareInitiatedReset>();}});
0x10: Priv::wrpcr({{Pcr = Rs1 ^ Rs2_or_imm13;}});
0x11: Priv::wrpic({{Pic = Rs1 ^ Rs2_or_imm13;}}, {{Pcr<0:>}});
// 0x12 should cause an illegal instruction exception
0x13: NoPriv::wrgsr({{
if (Fprs<2:> == 0 || Pstate.pef == 0)
return std::make_shared<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.hpriv)
return std::make_shared<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(
{{Tpc = Rs1 ^ Rs2_or_imm13;}}, check_tl=true);
0x01: Priv::wrprtnpc(
{{Tnpc = Rs1 ^ Rs2_or_imm13;}}, check_tl=true);
0x02: Priv::wrprtstate(
{{Tstate = Rs1 ^ Rs2_or_imm13;}}, check_tl=true);
0x03: Priv::wrprtt(
{{Tt = Rs1 ^ Rs2_or_imm13;}}, check_tl=true);
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.priv && !Hpstate.hpriv)
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.priv && !Hpstate.hpriv)
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(
{{Htstate = Rs1 ^ Rs2_or_imm13;}}, check_tl=true);
// 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;}});
0x02: fmovd({{Frd_udw = Frs2_udw;}});
0x03: FpUnimpl::fmovq();
0x05: fnegs({{Frds_uw = Frs2s_uw ^ (1UL << 31);}});
0x06: fnegd({{Frd_udw = Frs2_udw ^ (1ULL << 63);}});
0x07: FpUnimpl::fnegq();
0x09: fabss({{Frds_uw = ((1UL << 31) - 1) & Frs2s_uw;}});
0x0A: fabsd({{Frd_udw = ((1ULL << 63) - 1) & Frs2_udw;}});
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{
0x01: fmovs_fcc0({{
if (passesFpCondition(Fsr<11:10>, COND4))
Frds = Frs2s;
else
Frds = Frds;
}});
0x02: fmovd_fcc0({{
if (passesFpCondition(Fsr<11:10>, COND4))
Frd = Frs2;
else
Frd = Frd;
}});
0x03: FpUnimpl::fmovq_fcc0();
0x25: fmovrsz({{
if (Rs1 == 0)
Frds = Frs2s;
else
Frds = Frds;
}});
0x26: fmovrdz({{
if (Rs1 == 0)
Frd = Frs2;
else
Frd = Frd;
}});
0x27: FpUnimpl::fmovrqz();
0x41: fmovs_fcc1({{
if (passesFpCondition(Fsr<33:32>, COND4))
Frds = Frs2s;
else
Frds = Frds;
}});
0x42: fmovd_fcc1({{
if (passesFpCondition(Fsr<33:32>, COND4))
Frd = Frs2;
else
Frd = Frd;
}});
0x43: FpUnimpl::fmovq_fcc1();
0x45: fmovrslez({{
if ((int64_t)Rs1 <= 0)
Frds = Frs2s;
else
Frds = Frds;
}});
0x46: fmovrdlez({{
if ((int64_t)Rs1 <= 0)
Frd = Frs2;
else
Frd = Frd;
}});
0x47: FpUnimpl::fmovrqlez();
0x51: fcmps({{
uint8_t fcc;
if (std::isnan(Frs1s) || std::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 (std::isnan(Frs1) || std::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 (std::isnan(Frs1s) || std::isnan(Frs2s))
fault = std::make_shared<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 (std::isnan(Frs1) || std::isnan(Frs2))
fault = std::make_shared<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();
0x65: fmovrslz({{
if ((int64_t)Rs1 < 0)
Frds = Frs2s;
else
Frds = Frds;
}});
0x66: fmovrdlz({{
if ((int64_t)Rs1 < 0)
Frd = Frs2;
else
Frd = Frd;
}});
0x67: FpUnimpl::fmovrqlz();
0x81: fmovs_fcc2({{
if (passesFpCondition(Fsr<35:34>, COND4))
Frds = Frs2s;
else
Frds = Frds;
}});
0x82: fmovd_fcc2({{
if (passesFpCondition(Fsr<35:34>, COND4))
Frd = Frs2;
else
Frd = Frd;
}});
0x83: FpUnimpl::fmovq_fcc2();
0xA5: fmovrsnz({{
if (Rs1 != 0)
Frds = Frs2s;
else
Frds = Frds;
}});
0xA6: fmovrdnz({{
if (Rs1 != 0)
Frd = Frs2;
else
Frd = Frd;
}});
0xA7: FpUnimpl::fmovrqnz();
0xC1: fmovs_fcc3({{
if (passesFpCondition(Fsr<37:36>, COND4))
Frds = Frs2s;
else
Frds = Frds;
}});
0xC2: fmovd_fcc3({{
if (passesFpCondition(Fsr<37:36>, COND4))
Frd = Frs2;
else
Frd = Frd;
}});
0xC3: FpUnimpl::fmovq_fcc3();
0xC5: fmovrsgz({{
if ((int64_t)Rs1 > 0)
Frds = Frs2s;
else
Frds = Frds;
}});
0xC6: fmovrdgz({{
if ((int64_t)Rs1 > 0)
Frd = Frs2;
else
Frd = Frd;
}});
0xC7: FpUnimpl::fmovrqgz();
0xE5: fmovrsgez({{
if ((int64_t)Rs1 >= 0)
Frds = Frs2s;
else
Frds = Frds;
}});
0xE6: fmovrdgez({{
if ((int64_t)Rs1 >= 0)
Frd = Frs2;
else
Frd = Frd;
}});
0xE7: FpUnimpl::fmovrqgez();
0x101: fmovs_icc({{
if (passesCondition(Ccr<3:0>, COND4))
Frds = Frs2s;
else
Frds = Frds;
}});
0x102: fmovd_icc({{
if (passesCondition(Ccr<3:0>, COND4))
Frd = Frs2;
else
Frd = Frd;
}});
0x103: FpUnimpl::fmovq_icc();
0x181: fmovs_xcc({{
if (passesCondition(Ccr<7:4>, COND4))
Frds = Frs2s;
else
Frds = Frds;
}});
0x182: fmovd_xcc({{
if (passesCondition(Ccr<7:4>, COND4))
Frd = Frs2;
else
Frd = Frd;
}});
0x183: FpUnimpl::fmovq_xcc();
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 = std::make_shared<IllegalInstruction>();}});
0x3B: Trap::fpack16({{fault = std::make_shared<IllegalInstruction>();}});
0x3D: Trap::fpackfix({{fault = std::make_shared<IllegalInstruction>();}});
0x3E: Trap::pdist({{fault = std::make_shared<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 = std::make_shared<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 = std::make_shared<IllegalInstruction>();}});
0x81: FailUnimpl::siam();
}
// M5 special opcodes use the reserved IMPDEP2A opcode space
0x37: decode M5FUNC {
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.", PC);
}}, No_OpClass, IsNonSpeculative);
}
default: Trap::impdep2({{fault = std::make_shared<IllegalInstruction>();}});
}
0x38: Branch::jmpl({{
Addr target = Rs1 + Rs2_or_imm13;
if (target & 0x3) {
fault = std::make_shared<MemAddressNotAligned>();
} else {
if (Pstate.am)
Rd = (PC)<31:0>;
else
Rd = PC;
NNPC = target;
}
}}, IsUncondControl, IsIndirectControl);
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 = std::make_shared<FillNOther>(4*Wstate<5:3>);
else
fault = std::make_shared<FillNNormal>(4*Wstate<2:0>);
} else if (target & 0x3) { // Check for alignment faults
fault = std::make_shared<MemAddressNotAligned>();
} else {
NNPC = target;
Cwp = (Cwp - 1 + NWindows) % NWindows;
Cansave = Cansave + 1;
Canrestore = Canrestore - 1;
}
}
}}, IsUncondControl, IsIndirectControl, IsReturn);
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 = std::make_shared<TrapInstruction>(lTrapNum);
}
}}, IsSerializeAfter, IsNonSpeculative, IsSyscall);
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 = std::make_shared<TrapInstruction>(lTrapNum);
}
}}, IsSerializeAfter, IsNonSpeculative, IsSyscall);
}
0x3B: Nop::flush(IsWriteBarrier, MemWriteOp);
0x3C: save({{
if (Cansave == 0) {
if (Otherwin)
fault = std::make_shared<SpillNOther>(4*Wstate<5:3>);
else
fault = std::make_shared<SpillNNormal>(4*Wstate<2:0>);
} else if (Cleanwin - Canrestore == 0) {
fault = std::make_shared<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 = std::make_shared<FillNOther>(4*Wstate<5:3>);
else
fault = std::make_shared<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({{
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;
}}, check_tl=true);
0x1: Priv::retry({{
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;
}}, check_tl=true);
}
}
}
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({{
// This temporary needs to be here so that the parser
// will correctly identify this instruction as a store.
// It's probably either the parenthesis or referencing
// the member variable that throws confuses it.
Twin32_t temp;
temp.a = RdLow<31:0>;
temp.b = RdHigh<31:0>;
Mem_tuw = temp;
}});
}
format Load {
0x08: ldsw({{Rd = Mem_sw;}});
0x09: ldsb({{Rd = Mem_sb;}});
0x0A: ldsh({{Rd = Mem_shw;}});
0x0B: ldx({{Rd = 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;}});
0x11: lduba({{Rd = Mem_ub;}});
0x12: lduha({{Rd = Mem_uhw;}});
0x13: decode EXT_ASI {
// ASI_LDTD_AIUP
0x22: TwinLoad::ldtx_aiup(
{{RdLow_udw = (Mem_tudw).a;
RdHigh_udw = (Mem_tudw).b;}});
// ASI_LDTD_AIUS
0x23: TwinLoad::ldtx_aius(
{{RdLow_udw = (Mem_tudw).a;
RdHigh_udw = (Mem_tudw).b;}});
// ASI_QUAD_LDD
0x24: TwinLoad::ldtx_quad_ldd(
{{RdLow_udw = (Mem_tudw).a;
RdHigh_udw = (Mem_tudw).b;}});
// ASI_LDTX_REAL
0x26: TwinLoad::ldtx_real(
{{RdLow_udw = (Mem_tudw).a;
RdHigh_udw = (Mem_tudw).b;}});
// ASI_LDTX_N
0x27: TwinLoad::ldtx_n(
{{RdLow_udw = (Mem_tudw).a;
RdHigh_udw = (Mem_tudw).b;}});
// ASI_LDTX_AIUP_L
0x2A: TwinLoad::ldtx_aiup_l(
{{RdLow_udw = (Mem_tudw).a;
RdHigh_udw = (Mem_tudw).b;}});
// ASI_LDTX_AIUS_L
0x2B: TwinLoad::ldtx_aius_l(
{{RdLow_udw = (Mem_tudw).a;
RdHigh_udw = (Mem_tudw).b;}});
// ASI_LDTX_L
0x2C: TwinLoad::ldtx_l(
{{RdLow_udw = (Mem_tudw).a;
RdHigh_udw = (Mem_tudw).b;}});
// ASI_LDTX_REAL_L
0x2E: TwinLoad::ldtx_real_l(
{{RdLow_udw = (Mem_tudw).a;
RdHigh_udw = (Mem_tudw).b;}});
// ASI_LDTX_N_L
0x2F: TwinLoad::ldtx_n_l(
{{RdLow_udw = (Mem_tudw).a;
RdHigh_udw = (Mem_tudw).b;}});
// ASI_LDTX_P
0xE2: TwinLoad::ldtx_p(
{{RdLow_udw = (Mem_tudw).a;
RdHigh_udw = (Mem_tudw).b;}});
// ASI_LDTX_S
0xE3: TwinLoad::ldtx_s(
{{RdLow_udw = (Mem_tudw).a;
RdHigh_udw = (Mem_tudw).b;}});
// ASI_LDTX_PL
0xEA: TwinLoad::ldtx_pl(
{{RdLow_udw = (Mem_tudw).a;
RdHigh_udw = (Mem_tudw).b;}});
// ASI_LDTX_SL
0xEB: TwinLoad::ldtx_sl(
{{RdLow_udw = (Mem_tudw).a;
RdHigh_udw = (Mem_tudw).b;}});
default: ldtwa({{
RdLow = (Mem_tuw).a;
RdHigh = (Mem_tuw).b;}});
}
}
format StoreAlt {
0x14: stwa({{Mem_uw = Rd;}});
0x15: stba({{Mem_ub = Rd;}});
0x16: stha({{Mem_uhw = Rd;}});
0x17: sttwa({{
// This temporary needs to be here so that the parser
// will correctly identify this instruction as a store.
// It's probably either the parenthesis or referencing
// the member variable that throws confuses it.
Twin32_t temp;
temp.a = RdLow<31:0>;
temp.b = RdHigh<31:0>;
Mem_tuw = temp;
}});
}
format LoadAlt {
0x18: ldswa({{Rd = Mem_sw;}});
0x19: ldsba({{Rd = Mem_sb;}});
0x1A: ldsha({{Rd = Mem_shw;}});
0x1B: ldxa({{Rd = Mem_sdw;}});
}
0x1D: SwapAlt::ldstuba({{Mem_ub = 0xFF;}},
{{
uint8_t tmp = mem_data;
Rd_ub = tmp;
}}, MEM_SWAP);
0x1E: StoreAlt::stxa({{Mem_udw = Rd}});
0x1F: SwapAlt::swapa({{Mem_uw = Rd_uw}},
{{
uint32_t tmp = mem_data;
Rd_uw = tmp;
}}, 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 = std::make_shared<FpDisabled>();}});
0x23: Load::lddf({{Frd_udw = Mem_udw;}});
0x24: Store::stf({{Mem_uw = Frds_uw;}});
0x25: decode RD {
0x0: StoreFsr::stfsr({{fault = checkFpEnableFault(xc);
if (fault)
return fault;
Mem_uw = Fsr<31:0>;}});
0x1: StoreFsr::stxfsr({{fault = checkFpEnableFault(xc);
if (fault)
return fault;
Mem_udw = Fsr;}});
default: FailUnimpl::stfsrOther();
}
0x26: stqf({{fault = std::make_shared<FpDisabled>();}});
0x27: Store::stdf({{Mem_udw = Frd_udw;}});
0x2D: Nop::prefetch();
0x30: LoadAlt::ldfa({{Frds_uw = Mem_uw;}});
0x32: ldqfa({{fault = std::make_shared<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;}});
// 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 = std::make_shared<DataAccessException>();}});
}
}
0x34: Store::stfa({{Mem_uw = Frds_uw;}});
0x36: stqfa({{fault = std::make_shared<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;}});
// 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 = std::make_shared<DataAccessException>();}});
}
}
0x3C: CasAlt::casa({{
mem_data = htog(Rs2_uw);
Mem_uw = Rd_uw;}},
{{
uint32_t tmp = mem_data;
Rd_uw = tmp;
}}, MEM_SWAP_COND);
0x3D: Nop::prefetcha();
0x3E: CasAlt::casxa({{mem_data = gtoh(Rs2);
Mem_udw = Rd_udw; }},
{{ Rd_udw = mem_data; }}, MEM_SWAP_COND);
}
}
}