summaryrefslogtreecommitdiff
path: root/src/arch/power/isa/decoder.isa
diff options
context:
space:
mode:
Diffstat (limited to 'src/arch/power/isa/decoder.isa')
-rw-r--r--src/arch/power/isa/decoder.isa593
1 files changed, 593 insertions, 0 deletions
diff --git a/src/arch/power/isa/decoder.isa b/src/arch/power/isa/decoder.isa
new file mode 100644
index 000000000..3252ff14a
--- /dev/null
+++ b/src/arch/power/isa/decoder.isa
@@ -0,0 +1,593 @@
+// -*- mode:c++ -*-
+
+// Copyright (c) 2009 The University of Edinburgh
+// 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: Timothy M. Jones
+
+////////////////////////////////////////////////////////////////////
+//
+// The actual Power ISA decoder
+// ------------------------------
+//
+// I've used the Power ISA Book I v2.06 for instruction formats,
+// opcode numbers, register names, etc.
+//
+decode OPCODE default Unknown::unknown() {
+
+ format IntImmOp {
+ 10: cmpli({{
+ Xer xer = XER;
+ uint32_t cr = makeCRField(Ra, (uint32_t)uimm, xer.so);
+ CR = insertCRField(CR, BF, cr);
+ }});
+ 11: cmpi({{
+ Xer xer = XER;
+ uint32_t cr = makeCRField(Ra.sw, (int32_t)imm, xer.so);
+ CR = insertCRField(CR, BF, cr);
+ }});
+ }
+
+ // Some instructions use bits 21 - 30, others 22 - 30. We have to use
+ // the larger size to account for all opcodes. For those that use the
+ // smaller value, the OE bit is bit 21. Therefore, we have two versions
+ // of each instruction: 1 with OE set, the other without. For an
+ // example see 'add' and 'addo'.
+ 31: decode XO_XO {
+
+ // These instructions can all be reduced to the form
+ // Rt = src1 + src2 [+ CA], therefore we just give src1 and src2
+ // (and, if necessary, CA) definitions and let the python script
+ // deal with setting things up correctly. We also give flags to
+ // say which control registers to set.
+ format IntSumOp {
+ 266: add({{ Ra }}, {{ Rb }});
+ 40: subf({{ ~Ra }}, {{ Rb }}, {{ 1 }});
+ 10: addc({{ Ra }}, {{ Rb }},
+ computeCA = true);
+ 8: subfc({{ ~Ra }}, {{ Rb }}, {{ 1 }},
+ true);
+ 104: neg({{ ~Ra }}, {{ 1 }});
+ 138: adde({{ Ra }}, {{ Rb }}, {{ xer.ca }},
+ true);
+ 234: addme({{ Ra }}, {{ (uint32_t)-1 }}, {{ xer.ca }},
+ true);
+ 136: subfe({{ ~Ra }}, {{ Rb }}, {{ xer.ca }},
+ true);
+ 232: subfme({{ ~Ra }}, {{ (uint32_t)-1 }}, {{ xer.ca }},
+ true);
+ 202: addze({{ Ra }}, {{ xer.ca }},
+ computeCA = true);
+ 200: subfze({{ ~Ra }}, {{ xer.ca }},
+ computeCA = true);
+ }
+
+ // Arithmetic instructions all use source registers Ra and Rb,
+ // with destination register Rt.
+ format IntArithOp {
+ 75: mulhw({{ int64_t prod = Ra.sq * Rb.sq; Rt = prod >> 32; }});
+ 11: mulhwu({{ uint64_t prod = Ra.uq * Rb.uq; Rt = prod >> 32; }});
+ 235: mullw({{ int64_t prod = Ra.sq * Rb.sq; Rt = prod; }});
+ 747: mullwo({{ int64_t src1 = Ra.sq; int64_t src2 = Rb; int64_t prod = src1 * src2; Rt = prod; }},
+ true);
+
+ 491: divw({{
+ int32_t src1 = Ra.sw;
+ int32_t src2 = Rb.sw;
+ if ((src1 != 0x80000000 || src2 != 0xffffffff)
+ && src2 != 0) {
+ Rt = src1 / src2;
+ } else {
+ Rt = 0;
+ }
+ }});
+
+ 1003: divwo({{
+ int32_t src1 = Ra.sw;
+ int32_t src2 = Rb.sw;
+ if ((src1 != 0x80000000 || src2 != 0xffffffff)
+ && src2 != 0) {
+ Rt = src1 / src2;
+ } else {
+ Rt = 0;
+ divSetOV = true;
+ }
+ }},
+ true);
+
+ 459: divwu({{
+ uint32_t src1 = Ra.sw;
+ uint32_t src2 = Rb.sw;
+ if (src2 != 0) {
+ Rt = src1 / src2;
+ } else {
+ Rt = 0;
+ }
+ }});
+
+ 971: divwuo({{
+ uint32_t src1 = Ra.sw;
+ uint32_t src2 = Rb.sw;
+ if (src2 != 0) {
+ Rt = src1 / src2;
+ } else {
+ Rt = 0;
+ divSetOV = true;
+ }
+ }},
+ true);
+ }
+
+ // Integer logic instructions use source registers Rs and Rb,
+ // with destination register Ra.
+ format IntLogicOp {
+ 28: and({{ Ra = Rs & Rb; }});
+ 316: xor({{ Ra = Rs ^ Rb; }});
+ 476: nand({{ Ra = ~(Rs & Rb); }});
+ 444: or({{ Ra = Rs | Rb; }});
+ 124: nor({{ Ra = ~(Rs | Rb); }});
+ 60: andc({{ Ra = Rs & ~Rb; }});
+ 954: extsb({{ Ra = sext<8>(Rs); }});
+ 284: eqv({{ Ra = ~(Rs ^ Rb); }});
+ 412: orc({{ Ra = Rs | ~Rb; }});
+ 922: extsh({{ Ra = sext<16>(Rs); }});
+ 26: cntlzw({{ Ra = Rs == 0 ? 32 : 31 - findMsbSet(Rs); }});
+ 508: cmpb({{
+ uint32_t val = 0;
+ for (int n = 0; n < 32; n += 8) {
+ if(bits(Rs, n, n+7) == bits(Rb, n, n+7)) {
+ val = insertBits(val, n, n+7, 0xff);
+ }
+ }
+ Ra = val;
+ }});
+
+ 24: slw({{
+ if (Rb & 0x20) {
+ Ra = 0;
+ } else {
+ Ra = Rs << (Rb & 0x1f);
+ }
+ }});
+
+ 536: srw({{
+ if (Rb & 0x20) {
+ Ra = 0;
+ } else {
+ Ra = Rs >> (Rb & 0x1f);
+ }
+ }});
+
+ 792: sraw({{
+ bool shiftSetCA = false;
+ int32_t s = Rs;
+ if (Rb == 0) {
+ Ra = Rs;
+ shiftSetCA = true;
+ } else if (Rb & 0x20) {
+ if (s < 0) {
+ Ra = (uint32_t)-1;
+ if (s & 0x7fffffff) {
+ shiftSetCA = true;
+ } else {
+ shiftSetCA = false;
+ }
+ } else {
+ Ra = 0;
+ shiftSetCA = false;
+ }
+ } else {
+ Ra = s >> (Rb & 0x1f);
+ if (s < 0 && (s << (32 - (Rb & 0x1f))) != 0) {
+ shiftSetCA = true;
+ } else {
+ shiftSetCA = false;
+ }
+ }
+ Xer xer1 = XER;
+ if (shiftSetCA) {
+ xer1.ca = 1;
+ } else {
+ xer1.ca = 0;
+ }
+ XER = xer1;
+ }});
+ }
+
+ // Integer logic instructions with a shift value.
+ format IntShiftOp {
+ 824: srawi({{
+ bool shiftSetCA = false;
+ if (sh == 0) {
+ Ra = Rs;
+ shiftSetCA = false;
+ } else {
+ int32_t s = Rs;
+ Ra = s >> sh;
+ if (s < 0 && (s << (32 - sh)) != 0) {
+ shiftSetCA = true;
+ } else {
+ shiftSetCA = false;
+ }
+ }
+ Xer xer1 = XER;
+ if (shiftSetCA) {
+ xer1.ca = 1;
+ } else {
+ xer1.ca = 0;
+ }
+ XER = xer1;
+ }});
+ }
+
+ // Generic integer format instructions.
+ format IntOp {
+ 0: cmp({{
+ Xer xer = XER;
+ uint32_t cr = makeCRField(Ra.sw, Rb.sw, xer.so);
+ CR = insertCRField(CR, BF, cr);
+ }});
+ 32: cmpl({{
+ Xer xer = XER;
+ uint32_t cr = makeCRField(Ra, Rb, xer.so);
+ CR = insertCRField(CR, BF, cr);
+ }});
+ 144: mtcrf({{
+ uint32_t mask = 0;
+ for (int i = 0; i < 8; ++i) {
+ if (((FXM >> i) & 0x1) == 0x1) {
+ mask |= 0xf << (4 * i);
+ }
+ }
+ CR = (Rs & mask) | (CR & ~mask);
+ }});
+ 19: mfcr({{ Rt = CR; }});
+ 339: decode SPR {
+ 0x20: mfxer({{ Rt = XER; }});
+ 0x100: mflr({{ Rt = LR; }});
+ 0x120: mfctr({{ Rt = CTR; }});
+ }
+ 467: decode SPR {
+ 0x20: mtxer({{ XER = Rs; }});
+ 0x100: mtlr({{ LR = Rs; }});
+ 0x120: mtctr({{ CTR = Rs; }});
+ }
+ }
+
+ // All loads with an index register. The non-update versions
+ // all use the value 0 if Ra == R0, not the value contained in
+ // R0. Others update Ra with the effective address. In all cases,
+ // Ra and Rb are source registers, Rt is the destintation.
+ format LoadIndexOp {
+ 87: lbzx({{ Rt = Mem.ub; }});
+ 279: lhzx({{ Rt = Mem.uh; }});
+ 343: lhax({{ Rt = Mem.sh; }});
+ 23: lwzx({{ Rt = Mem; }});
+ 341: lwax({{ Rt = Mem.sw; }});
+ 20: lwarx({{ Rt = Mem.sw; Rsv = 1; RsvLen = 4; RsvAddr = EA; }});
+ 535: lfsx({{ Ft.sf = Mem.sf; }});
+ 599: lfdx({{ Ft = Mem.df; }});
+ 855: lfiwax({{ Ft.uw = Mem; }});
+ }
+
+ format LoadIndexUpdateOp {
+ 119: lbzux({{ Rt = Mem.ub; }});
+ 311: lhzux({{ Rt = Mem.uh; }});
+ 375: lhaux({{ Rt = Mem.sh; }});
+ 55: lwzux({{ Rt = Mem; }});
+ 373: lwaux({{ Rt = Mem.sw; }});
+ 567: lfsux({{ Ft.sf = Mem.sf; }});
+ 631: lfdux({{ Ft = Mem.df; }});
+ }
+
+ format StoreIndexOp {
+ 215: stbx({{ Mem.ub = Rs.ub; }});
+ 407: sthx({{ Mem.uh = Rs.uh; }});
+ 151: stwx({{ Mem = Rs; }});
+ 150: stwcx({{
+ bool store_performed = false;
+ if (Rsv) {
+ if (RsvLen == 4) {
+ if (RsvAddr == EA) {
+ Mem = Rs;
+ store_performed = true;
+ }
+ }
+ }
+ Xer xer = XER;
+ Cr cr = CR;
+ cr.cr0 = ((store_performed ? 0x2 : 0x0) | xer.so);
+ CR = cr;
+ Rsv = 0;
+ }});
+ 663: stfsx({{ Mem.sf = Fs.sf; }});
+ 727: stfdx({{ Mem.df = Fs; }});
+ 983: stfiwx({{ Mem = Fs.uw; }});
+ }
+
+ format StoreIndexUpdateOp {
+ 247: stbux({{ Mem.ub = Rs.ub; }});
+ 439: sthux({{ Mem.uh = Rs.uh; }});
+ 183: stwux({{ Mem = Rs; }});
+ 695: stfsux({{ Mem.sf = Fs.sf; }});
+ 759: stfdux({{ Mem.df = Fs; }});
+ }
+
+ // These instructions all provide data cache hints
+ format MiscOp {
+ 278: dcbt({{ }});
+ 246: dcbtst({{ }});
+ 598: sync({{ }}, [ IsMemBarrier ]);
+ 854: eieio({{ }}, [ IsMemBarrier ]);
+ }
+ }
+
+ format IntImmArithCheckRaOp {
+ 14: addi({{ Rt = Ra + imm; }},
+ {{ Rt = imm }});
+ 15: addis({{ Rt = Ra + (imm << 16); }},
+ {{ Rt = imm << 16; }});
+ }
+
+ format IntImmArithOp {
+ 12: addic({{ uint32_t src = Ra; Rt = src + imm; }},
+ [computeCA]);
+ 13: addic_({{ uint32_t src = Ra; Rt = src + imm; }},
+ [computeCA, computeCR0]);
+ 8: subfic({{ int32_t src = ~Ra; Rt = src + imm + 1; }},
+ [computeCA]);
+ 7: mulli({{
+ int32_t src = Ra.sw;
+ int64_t prod = src * imm;
+ Rt = (uint32_t)prod;
+ }});
+ }
+
+ format IntImmLogicOp {
+ 24: ori({{ Ra = Rs | uimm; }});
+ 25: oris({{ Ra = Rs | (uimm << 16); }});
+ 26: xori({{ Ra = Rs ^ uimm; }});
+ 27: xoris({{ Ra = Rs ^ (uimm << 16); }});
+ 28: andi_({{ Ra = Rs & uimm; }},
+ true);
+ 29: andis_({{ Ra = Rs & (uimm << 16); }},
+ true);
+ }
+
+ 16: decode AA {
+
+ // Conditionally branch relative to PC based on CR and CTR.
+ format BranchPCRelCondCtr {
+ 0: bc({{ NPC = PC + disp; }});
+ }
+
+ // Conditionally branch to fixed address based on CR and CTR.
+ format BranchNonPCRelCondCtr {
+ 1: bca({{ NPC = targetAddr; }});
+ }
+ }
+
+ 18: decode AA {
+
+ // Unconditionally branch relative to PC.
+ format BranchPCRel {
+ 0: b({{ NPC = PC + disp; }});
+ }
+
+ // Unconditionally branch to fixed address.
+ format BranchNonPCRel {
+ 1: ba({{ NPC = targetAddr; }});
+ }
+ }
+
+ 19: decode XO_XO {
+
+ // Conditionally branch to address in LR based on CR and CTR.
+ format BranchLrCondCtr {
+ 16: bclr({{ NPC = LR & 0xfffffffc; }});
+ }
+
+ // Conditionally branch to address in CTR based on CR.
+ format BranchCtrCond {
+ 528: bcctr({{ NPC = CTR & 0xfffffffc; }});
+ }
+
+ // Condition register manipulation instructions.
+ format CondLogicOp {
+ 257: crand({{
+ uint32_t crBa = bits(CR, 31 - ba);
+ uint32_t crBb = bits(CR, 31 - bb);
+ CR = insertBits(CR, 31 - bt, crBa & crBb);
+ }});
+ 449: cror({{
+ uint32_t crBa = bits(CR, 31 - ba);
+ uint32_t crBb = bits(CR, 31 - bb);
+ CR = insertBits(CR, 31 - bt, crBa | crBb);
+ }});
+ 255: crnand({{
+ uint32_t crBa = bits(CR, 31 - ba);
+ uint32_t crBb = bits(CR, 31 - bb);
+ CR = insertBits(CR, 31 - bt, !(crBa & crBb));
+ }});
+ 193: crxor({{
+ uint32_t crBa = bits(CR, 31 - ba);
+ uint32_t crBb = bits(CR, 31 - bb);
+ CR = insertBits(CR, 31 - bt, crBa ^ crBb);
+ }});
+ 33: crnor({{
+ uint32_t crBa = bits(CR, 31 - ba);
+ uint32_t crBb = bits(CR, 31 - bb);
+ CR = insertBits(CR, 31 - bt, !(crBa | crBb));
+ }});
+ 289: creqv({{
+ uint32_t crBa = bits(CR, 31 - ba);
+ uint32_t crBb = bits(CR, 31 - bb);
+ CR = insertBits(CR, 31 - bt, crBa == crBb);
+ }});
+ 129: crandc({{
+ uint32_t crBa = bits(CR, 31 - ba);
+ uint32_t crBb = bits(CR, 31 - bb);
+ CR = insertBits(CR, 31 - bt, crBa & !crBb);
+ }});
+ 417: crorc({{
+ uint32_t crBa = bits(CR, 31 - ba);
+ uint32_t crBb = bits(CR, 31 - bb);
+ CR = insertBits(CR, 31 - bt, crBa | !crBb);
+ }});
+ }
+ format CondMoveOp {
+ 0: mcrf({{
+ uint32_t crBfa = bits(CR, 31 - bfa*4, 28 - bfa*4);
+ CR = insertBits(CR, 31 - bf*4, 28 - bf*4, crBfa);
+ }});
+ }
+ format MiscOp {
+ 150: isync({{ }}, [ IsSerializeAfter ]);
+ }
+ }
+
+ format IntRotateOp {
+ 21: rlwinm({{ Ra = rotateValue(Rs, sh) & fullMask; }});
+ 23: rlwnm({{ Ra = rotateValue(Rs, Rb) & fullMask; }});
+ 20: rlwimi({{ Ra = (rotateValue(Rs, sh) & fullMask) | (Ra & ~fullMask); }});
+ }
+
+ format LoadDispOp {
+ 34: lbz({{ Rt = Mem.ub; }});
+ 40: lhz({{ Rt = Mem.uh; }});
+ 42: lha({{ Rt = Mem.sh; }});
+ 32: lwz({{ Rt = Mem; }});
+ 58: lwa({{ Rt = Mem.sw; }},
+ {{ EA = Ra + (disp & 0xfffffffc); }},
+ {{ EA = disp & 0xfffffffc; }});
+ 48: lfs({{ Ft.sf = Mem.sf; }});
+ 50: lfd({{ Ft = Mem.df; }});
+ }
+
+ format LoadDispUpdateOp {
+ 35: lbzu({{ Rt = Mem.ub; }});
+ 41: lhzu({{ Rt = Mem.uh; }});
+ 43: lhau({{ Rt = Mem.sh; }});
+ 33: lwzu({{ Rt = Mem; }});
+ 49: lfsu({{ Ft.sf = Mem.sf; }});
+ 51: lfdu({{ Ft = Mem.df; }});
+ }
+
+ format StoreDispOp {
+ 38: stb({{ Mem.ub = Rs.ub; }});
+ 44: sth({{ Mem.uh = Rs.uh; }});
+ 36: stw({{ Mem = Rs; }});
+ 52: stfs({{ Mem.sf = Fs.sf; }});
+ 54: stfd({{ Mem.df = Fs; }});
+ }
+
+ format StoreDispUpdateOp {
+ 39: stbu({{ Mem.ub = Rs.ub; }});
+ 45: sthu({{ Mem.uh = Rs.uh; }});
+ 37: stwu({{ Mem = Rs; }});
+ 53: stfsu({{ Mem.sf = Fs.sf; }});
+ 55: stfdu({{ Mem.df = Fs; }});
+ }
+
+ 17: IntOp::sc({{ xc->syscall(R0); }},
+ [ IsSyscall, IsNonSpeculative, IsSerializeAfter ]);
+
+ format FloatArithOp {
+ 59: decode A_XO {
+ 21: fadds({{ Ft = Fa + Fb; }});
+ 20: fsubs({{ Ft = Fa - Fb; }});
+ 25: fmuls({{ Ft = Fa * Fc; }});
+ 18: fdivs({{ Ft = Fa / Fb; }});
+ 29: fmadds({{ Ft = (Fa * Fc) + Fb; }});
+ 28: fmsubs({{ Ft = (Fa * Fc) - Fb; }});
+ 31: fnmadds({{ Ft = -((Fa * Fc) + Fb); }});
+ 30: fnmsubs({{ Ft = -((Fa * Fc) - Fb); }});
+ }
+ }
+
+ 63: decode A_XO {
+ format FloatArithOp {
+ 21: fadd({{ Ft = Fa + Fb; }});
+ 20: fsub({{ Ft = Fa - Fb; }});
+ 25: fmul({{ Ft = Fa * Fc; }});
+ 18: fdiv({{ Ft = Fa / Fb; }});
+ 29: fmadd({{ Ft = (Fa * Fc) + Fb; }});
+ 28: fmsub({{ Ft = (Fa * Fc) - Fb; }});
+ 31: fnmadd({{ Ft = -((Fa * Fc) + Fb); }});
+ 30: fnmsub({{ Ft = -((Fa * Fc) - Fb); }});
+ }
+
+ default: decode XO_XO {
+ format FloatConvertOp {
+ 12: frsp({{ Ft.sf = Fb; }});
+ 15: fctiwz({{ Ft.sw = (int32_t)trunc(Fb); }});
+ }
+
+ format FloatOp {
+ 0: fcmpu({{
+ uint32_t c = makeCRField(Fa, Fb);
+ Fpscr fpscr = FPSCR;
+ fpscr.fprf.fpcc = c;
+ FPSCR = fpscr;
+ CR = insertCRField(CR, BF, c);
+ }});
+ }
+
+ format FloatRCCheckOp {
+ 72: fmr({{ Ft = Fb; }});
+ 264: fabs({{
+ Ft.uq = Fb.uq;
+ Ft.uq = insertBits(Ft.uq, 63, 0); }});
+ 136: fnabs({{
+ Ft.uq = Fb.uq;
+ Ft.uq = insertBits(Ft.uq, 63, 1); }});
+ 40: fneg({{ Ft = -Fb; }});
+ 8: fcpsgn({{
+ Ft.uq = Fb.uq;
+ Ft.uq = insertBits(Ft.uq, 63, Fa.uq<63:63>);
+ }});
+ 583: mffs({{ Ft.uq = FPSCR; }});
+ 134: mtfsfi({{
+ FPSCR = insertCRField(FPSCR, BF + (8 * (1 - W)), U_FIELD);
+ }});
+ 711: mtfsf({{
+ if (L == 1) { FPSCR = Fb.uq; }
+ else {
+ for (int i = 0; i < 8; ++i) {
+ if (bits(FLM, i) == 1) {
+ int k = 4 * (i + (8 * (1 - W)));
+ FPSCR = insertBits(FPSCR, k, k + 3,
+ bits(Fb.uq, k, k + 3));
+ }
+ }
+ }
+ }});
+ 70: mtfsb0({{ FPSCR = insertBits(FPSCR, 31 - BT, 0); }});
+ 38: mtfsb1({{ FPSCR = insertBits(FPSCR, 31 - BT, 1); }});
+ }
+ }
+ }
+}