| // -*- 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. |
| |
| //////////////////////////////////////////////////////////////////// |
| // |
| // 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_sd * Rb_sd; Rt = prod >> 32; }}); |
| 11: mulhwu({{ uint64_t prod = Ra_ud * Rb_ud; Rt = prod >> 32; }}); |
| 235: mullw({{ int64_t prod = Ra_sd * Rb_sd; Rt = prod; }}); |
| 747: mullwo({{ |
| int64_t src1 = Ra_sd; |
| 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+7, n) == bits(Rb, n+7, n)) { |
| val = insertBits(val, n+7, n, 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; |
| Mem = Rs; |
| if (Rsv) { |
| if (RsvLen == 4) { |
| if (RsvAddr == EA) { |
| 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({{ NIA = (uint32_t)(CIA + disp); }}); |
| } |
| |
| // Conditionally branch to fixed address based on CR and CTR. |
| format BranchNonPCRelCondCtr { |
| 1: bca({{ NIA = targetAddr; }}); |
| } |
| } |
| |
| 18: decode AA { |
| |
| // Unconditionally branch relative to PC. |
| format BranchPCRel { |
| 0: b({{ NIA = (uint32_t)(CIA + disp); }}); |
| } |
| |
| // Unconditionally branch to fixed address. |
| format BranchNonPCRel { |
| 1: ba({{ NIA = targetAddr; }}); |
| } |
| } |
| |
| 19: decode XO_XO { |
| |
| // Conditionally branch to address in LR based on CR and CTR. |
| format BranchLrCondCtr { |
| 16: bclr({{ NIA = LR & 0xfffffffc; }}); |
| } |
| |
| // Conditionally branch to address in CTR based on CR. |
| format BranchCtrCond { |
| 528: bcctr({{ NIA = 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({{ return std::make_shared<SESyscallFault>(); }}); |
| |
| 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_ud = Fb_ud; |
| Ft_ud = insertBits(Ft_ud, 63, 0); }}); |
| 136: fnabs({{ |
| Ft_ud = Fb_ud; |
| Ft_ud = insertBits(Ft_ud, 63, 1); }}); |
| 40: fneg({{ Ft = -Fb; }}); |
| 8: fcpsgn({{ |
| Ft_ud = Fb_ud; |
| Ft_ud = insertBits(Ft_ud, 63, Fa_ud<63:63>); |
| }}); |
| 583: mffs({{ Ft_ud = FPSCR; }}); |
| 134: mtfsfi({{ |
| FPSCR = insertCRField(FPSCR, BF + (8 * (1 - W_FIELD)), |
| U_FIELD); |
| }}); |
| 711: mtfsf({{ |
| if (L_FIELD == 1) { FPSCR = Fb_ud; } |
| else { |
| for (int i = 0; i < 8; ++i) { |
| if (bits(FLM, i) == 1) { |
| int k = 4 * (i + (8 * (1 - W_FIELD))); |
| FPSCR = insertBits(FPSCR, k + 3, k, |
| bits(Fb_ud, k + 3, k)); |
| } |
| } |
| } |
| }}); |
| 70: mtfsb0({{ FPSCR = insertBits(FPSCR, 31 - BT, 0); }}); |
| 38: mtfsb1({{ FPSCR = insertBits(FPSCR, 31 - BT, 1); }}); |
| } |
| } |
| } |
| } |