// // Decoder.cpp // Clock Signal // // Created by Thomas Harte on 30/12/20. // Copyright © 2020 Thomas Harte. All rights reserved. // #include "Decoder.hpp" using namespace InstructionSet::PowerPC; namespace { template Instruction instruction(uint32_t opcode, bool is_supervisor = false) { // If validation isn't required, there's nothing to do here. if constexpr (!validate_reserved_bits) { return Instruction(operation, opcode, is_supervisor); } // Otherwise, validation depends on operation // (and, in principle, processor model). switch(operation) { case Operation::absx: case Operation::clcs: case Operation::nabsx: case Operation::addmex: case Operation::addzex: case Operation::bcctrx: case Operation::bclrx: case Operation::cntlzdx: case Operation::cntlzwx: case Operation::extsbx: case Operation::extshx: case Operation::extswx: case Operation::fmulx: case Operation::fmulsx: case Operation::negx: case Operation::subfmex: case Operation::subfzex: if(opcode & 0b000000'00000'00000'11111'0000000000'0) return Instruction(opcode); break; case Operation::cmp: case Operation::cmpl: if(opcode & 0b000000'00010'00000'00000'0000000000'1) return Instruction(opcode); break; case Operation::cmpi: case Operation::cmpli: if(opcode & 0b000000'00010'00000'00000'0000000000'0) return Instruction(opcode); break; case Operation::dcbf: case Operation::dcbi: case Operation::dcbst: case Operation::dcbt: case Operation::dcbtst: case Operation::dcbz: if(opcode & 0b000000'11111'00000'00000'0000000000'0) return Instruction(opcode); break; case Operation::crand: case Operation::crandc: case Operation::creqv: case Operation::crnand: case Operation::crnor: case Operation::cror: case Operation::crorc: case Operation::crxor: case Operation::eciwx: case Operation::ecowx: case Operation::lbzux: case Operation::lbzx: case Operation::ldarx: case Operation::ldux: case Operation::ldx: case Operation::lfdux: case Operation::lfdx: case Operation::lfsux: case Operation::lfsx: case Operation::lhaux: case Operation::lhax: case Operation::lhbrx: case Operation::lhzux: case Operation::lhzx: case Operation::lswi: case Operation::lswx: case Operation::lwarx: case Operation::lwaux: case Operation::lwax: case Operation::lwbrx: case Operation::lwzux: case Operation::lwzx: case Operation::mfspr: case Operation::mftb: case Operation::mtspr: case Operation::stbux: case Operation::stbx: case Operation::stdux: case Operation::stdx: case Operation::stfdux: case Operation::stfdx: case Operation::stfiwx: case Operation::stfsux: case Operation::stfsx: case Operation::sthbrx: case Operation::sthux: case Operation::sthx: case Operation::stswi: case Operation::stswx: case Operation::stwbrx: case Operation::stwux: case Operation::stwx: case Operation::td: case Operation::tw: if(opcode & 0b000000'00000'00000'00000'0000000000'1) return Instruction(opcode); break; case Operation::fabsx: case Operation::fcfidx: case Operation::fctidx: case Operation::fctidzx: case Operation::fctiwx: case Operation::fctiwzx: case Operation::fmrx: case Operation::fnabsx: case Operation::fnegx: case Operation::frspx: if(opcode & 0b000000'00000'11111'00000'0000000000'0) return Instruction(opcode); break; case Operation::faddx: case Operation::faddsx: case Operation::fdivx: case Operation::fdivsx: case Operation::fsubx: case Operation::fsubsx: if(opcode & 0b000000'00000'00000'00000'1111100000'0) return Instruction(opcode); break; case Operation::fcmpo: case Operation::fcmpu: if(opcode & 0b000000'00011'00000'00000'0000000000'1) return Instruction(opcode); break; case Operation::fresx: case Operation::frsqrtex: case Operation::fsqrtx: case Operation::fsqrtsx: if(opcode & 0b000000'00000'11111'00000'1111100000'1) return Instruction(opcode); break; case Operation::icbi: if(opcode & 0b000000'11111'00000'00000'0000000000'1) return Instruction(opcode); break; case Operation::eieio: case Operation::isync: case Operation::rfi: case Operation::slbia: case Operation::sync: case Operation::tlbia: case Operation::tlbsync: if(opcode & 0b000000'11111'11111'11111'0000000000'1) return Instruction(opcode); break; case Operation::mcrf: case Operation::mcrfs: if(opcode & 0b000000'00011'00011'11111'0000000000'1) return Instruction(opcode); break; case Operation::mcrxr: if(opcode & 0b000000'00011'11111'11111'0000000000'1) return Instruction(opcode); break; case Operation::mfcr: case Operation::mfmsr: case Operation::mtmsr: if(opcode & 0b000000'00000'11111'11111'0000000000'1) return Instruction(opcode); break; case Operation::mffsx: case Operation::mtfsb0x: case Operation::mtfsb1x: if(opcode & 0b000000'00000'11111'11111'0000000000'0) return Instruction(opcode); break; case Operation::mtfsfx: if(opcode & 0b000000'10000'00001'00000'0000000000'0) return Instruction(opcode); break; case Operation::mtfsfix: if(opcode & 0b000000'00011'11111'00001'0000000000'0) return Instruction(opcode); break; case Operation::mtsr: if(opcode & 0b000000'00000'10000'11111'0000000000'1) return Instruction(opcode); break; case Operation::mtsrin: case Operation::mfsrin: if(opcode & 0b000000'00000'11111'00000'0000000000'1) return Instruction(opcode); break; case Operation::mfsr: if(opcode & 0b000000'00000'10000'11111'0000000000'1) return Instruction(opcode); break; case Operation::mtcrf: if(opcode & 0b000000'00000'10000'00001'0000000000'1) return Instruction(opcode); break; case Operation::mulhdx: case Operation::mulhdux: case Operation::mulhwx: case Operation::mulhwux: if(opcode & 0b000000'00000'00000'00000'1000000000'0) return Instruction(opcode); break; case Operation::sc: if(opcode & 0b000000'11111'11111'11111'1111111110'1) return Instruction(opcode); break; case Operation::slbie: case Operation::tlbie: if(opcode & 0b000000'11111'11111'00000'0000000000'1) return Instruction(opcode); break; case Operation::stwcx_: if(!(opcode & 0b000000'00000'00000'00000'0000000000'1)) return Instruction(opcode); break; case Operation::divx: case Operation::divsx: case Operation::dozx: case Operation::dozi: case Operation::lscbxx: case Operation::maskgx: case Operation::maskirx: case Operation::mulx: case Operation::rlmix: case Operation::rribx: case Operation::slex: case Operation::sleqx: case Operation::sliqx: case Operation::slliqx: case Operation::sllqx: case Operation::slqx: case Operation::sraiqx: case Operation::sraqx: case Operation::srex: case Operation::sreqx: case Operation::sriqx: case Operation::srliqx: case Operation::srlqx: case Operation::srqx: case Operation::sreax: case Operation::addx: case Operation::addcx: case Operation::addex: case Operation::addi: case Operation::addic: case Operation::addic_: case Operation::addis: case Operation::andx: case Operation::andcx: case Operation::andi_: case Operation::andis_: case Operation::bx: case Operation::bcx: case Operation::divdx: case Operation::divdux: case Operation::divwx: case Operation::divwux: case Operation::eqvx: case Operation::fmaddx: case Operation::fmaddsx: case Operation::fmsubx: case Operation::fmsubsx: case Operation::fnmaddx: case Operation::fnmaddsx: case Operation::fnmsubx: case Operation::fnmsubsx: case Operation::fselx: case Operation::lbz: case Operation::lbzu: case Operation::lfd: case Operation::lfdu: case Operation::lfs: case Operation::lfsu: case Operation::lha: case Operation::lhau: case Operation::lhz: case Operation::lhzu: case Operation::lmw: case Operation::lwa: case Operation::lwz: case Operation::lwzu: case Operation::mulldx: case Operation::mulli: case Operation::mullwx: case Operation::nandx: case Operation::norx: case Operation::orx: case Operation::orcx: case Operation::ori: case Operation::oris: case Operation::rlwimix: case Operation::rlwinmx: case Operation::rlwnmx: case Operation::sldx: case Operation::slwx: case Operation::sradx: case Operation::sradix: case Operation::srawx: case Operation::srawix: case Operation::srdx: case Operation::srwx: case Operation::stb: case Operation::stbu: case Operation::std: case Operation::stdcx_: case Operation::stdu: case Operation::stfd: case Operation::stfdu: case Operation::stfs: case Operation::stfsu: case Operation::sth: case Operation::sthu: case Operation::stmw: case Operation::stw: case Operation::stwu: case Operation::subfx: case Operation::subfcx: case Operation::subfex: case Operation::subfic: case Operation::tdi: case Operation::twi: case Operation::xorx: case Operation::xori: case Operation::xoris: case Operation::ld: case Operation::ldu: case Operation::rldclx: case Operation::rldcrx: case Operation::rldicx: case Operation::rldiclx: case Operation::rldicrx: case Operation::rldimix: break; } return Instruction(operation, opcode, is_supervisor); } } template Instruction Decoder::decode(uint32_t opcode) { // Quick bluffer's guide to PowerPC instruction encoding: // // There is a six-bit field at the very top of the instruction. // Sometimes that fully identifies an instruction, but usually // it doesn't. // // There is an addition 9- or 10-bit field starting one bit above // least significant that disambiguates the rest. Strictly speaking // it's a 10-bit field, but the mnemonics for many instructions treat // it as a 9-bit field with a flag at the top. // // I've decided to hew directly to the mnemonics. // // Various opcodes in the 1995 documentation define reserved bits, // which are given the nominal value of 0. It does not give a formal // definition of a reserved bit. As a result this code does not // currently check the value of reserved bits. That may need to change // if/when I add support for extended instruction sets. #define Bind(mask, operation) case mask: return instruction(opcode); #define BindSupervisor(mask, operation) case mask: return instruction(opcode, true); #define BindConditional(condition, mask, operation) \ case mask: \ if(condition(model)) return instruction(opcode); \ return instruction(opcode); #define BindSupervisorConditional(condition, mask, operation) \ case mask: \ if(condition(model)) return instruction(opcode, true); \ return instruction(opcode); #define Six(x) (unsigned(x) << 26) #define SixTen(x, y) (Six(x) | ((y) << 1)) // First pass: weed out all those instructions identified entirely by the // top six bits. switch(opcode & Six(0b111111)) { default: break; BindConditional(is64bit, Six(0b000010), tdi); Bind(Six(0b000011), twi); Bind(Six(0b000111), mulli); Bind(Six(0b001000), subfic); Bind(Six(0b001100), addic); Bind(Six(0b001101), addic_); Bind(Six(0b001110), addi); Bind(Six(0b001111), addis); case Six(0b010000): { // This might be a bcx, but check for a valid bo field. switch((opcode >> 21) & 0x1f) { case 0: case 1: case 2: case 3: case 4: case 5: case 8: case 9: case 10: case 11: case 12: case 13: case 16: case 17: case 18: case 19: case 20: return instruction(opcode); default: return Instruction(opcode); } } break; Bind(Six(0b010010), bx); Bind(Six(0b010100), rlwimix); Bind(Six(0b010101), rlwinmx); Bind(Six(0b010111), rlwnmx); Bind(Six(0b011000), ori); Bind(Six(0b011001), oris); Bind(Six(0b011010), xori); Bind(Six(0b011011), xoris); Bind(Six(0b011100), andi_); Bind(Six(0b011101), andis_); Bind(Six(0b100000), lwz); Bind(Six(0b100001), lwzu); Bind(Six(0b100010), lbz); Bind(Six(0b100011), lbzu); Bind(Six(0b100100), stw); Bind(Six(0b100101), stwu); Bind(Six(0b100110), stb); Bind(Six(0b100111), stbu); Bind(Six(0b101000), lhz); Bind(Six(0b101001), lhzu); Bind(Six(0b101010), lha); Bind(Six(0b101011), lhau); Bind(Six(0b101100), sth); Bind(Six(0b101101), sthu); Bind(Six(0b101110), lmw); Bind(Six(0b101111), stmw); Bind(Six(0b110000), lfs); Bind(Six(0b110001), lfsu); Bind(Six(0b110010), lfd); Bind(Six(0b110011), lfdu); Bind(Six(0b110100), stfs); Bind(Six(0b110101), stfsu); Bind(Six(0b110110), stfd); Bind(Six(0b110111), stfdu); BindConditional(is601, Six(9), dozi); BindConditional(is601, Six(22), rlmix); Bind(Six(0b001010), cmpli); Bind(Six(0b001011), cmpi); } // Second pass: all those with a top six bits and a bottom nine or ten. switch(opcode & SixTen(0b111111, 0b1111111111)) { default: break; // 64-bit instructions. BindConditional(is64bit, SixTen(0b011111, 0b0000001001), mulhdux); BindConditional(is64bit, SixTen(0b011111, 0b1000001001), mulhdux); BindConditional(is64bit, SixTen(0b011111, 0b0000010101), ldx); BindConditional(is64bit, SixTen(0b011111, 0b0000011011), sldx); BindConditional(is64bit, SixTen(0b011111, 0b0000110101), ldux); BindConditional(is64bit, SixTen(0b011111, 0b0000111010), cntlzdx); BindConditional(is64bit, SixTen(0b011111, 0b0001000100), td); BindConditional(is64bit, SixTen(0b011111, 0b0001001001), mulhdx); BindConditional(is64bit, SixTen(0b011111, 0b1001001001), mulhdx); BindConditional(is64bit, SixTen(0b011111, 0b0001010100), ldarx); BindConditional(is64bit, SixTen(0b011111, 0b0010010101), stdx); BindConditional(is64bit, SixTen(0b011111, 0b0010110101), stdux); BindConditional(is64bit, SixTen(0b011111, 0b0011101001), mulldx); BindConditional(is64bit, SixTen(0b011111, 0b1011101001), mulldx); BindConditional(is64bit, SixTen(0b011111, 0b0101010101), lwax); BindConditional(is64bit, SixTen(0b011111, 0b0101110101), lwaux); BindConditional(is64bit, SixTen(0b011111, 0b1100111011), sradix); BindConditional(is64bit, SixTen(0b011111, 0b1100111010), sradix); BindConditional(is64bit, SixTen(0b011111, 0b0110110010), slbie); BindConditional(is64bit, SixTen(0b011111, 0b0111001001), divdux); BindConditional(is64bit, SixTen(0b011111, 0b1111001001), divdux); BindConditional(is64bit, SixTen(0b011111, 0b0111101001), divdx); BindConditional(is64bit, SixTen(0b011111, 0b1111101001), divdx); BindConditional(is64bit, SixTen(0b011111, 0b1000011011), srdx); BindConditional(is64bit, SixTen(0b011111, 0b1100011010), sradx); BindConditional(is64bit, SixTen(0b111111, 0b1111011010), extswx); // Power instructions; these are all taken from the MPC601 manual rather than // the PowerPC Programmer's Reference Guide, hence the decimal encoding of the // ten-bit field. BindConditional(is601, SixTen(0b011111, 360), absx); BindConditional(is601, SixTen(0b011111, 512 + 360), absx); BindConditional(is601, SixTen(0b011111, 531), clcs); BindConditional(is601, SixTen(0b011111, 331), divx); BindConditional(is601, SixTen(0b011111, 512 + 331), divx); BindConditional(is601, SixTen(0b011111, 363), divsx); BindConditional(is601, SixTen(0b011111, 512 + 363), divsx); BindConditional(is601, SixTen(0b011111, 264), dozx); BindConditional(is601, SixTen(0b011111, 512 + 264), dozx); BindConditional(is601, SixTen(0b011111, 277), lscbxx); BindConditional(is601, SixTen(0b011111, 29), maskgx); BindConditional(is601, SixTen(0b011111, 541), maskirx); BindConditional(is601, SixTen(0b011111, 107), mulx); BindConditional(is601, SixTen(0b011111, 512 + 107), mulx); BindConditional(is601, SixTen(0b011111, 488), nabsx); BindConditional(is601, SixTen(0b011111, 512 + 488), nabsx); BindConditional(is601, SixTen(0b011111, 537), rribx); BindConditional(is601, SixTen(0b011111, 153), slex); BindConditional(is601, SixTen(0b011111, 217), sleqx); BindConditional(is601, SixTen(0b011111, 184), sliqx); BindConditional(is601, SixTen(0b011111, 248), slliqx); BindConditional(is601, SixTen(0b011111, 216), sllqx); BindConditional(is601, SixTen(0b011111, 152), slqx); BindConditional(is601, SixTen(0b011111, 952), sraiqx); BindConditional(is601, SixTen(0b011111, 920), sraqx); BindConditional(is601, SixTen(0b011111, 665), srex); BindConditional(is601, SixTen(0b011111, 921), sreax); BindConditional(is601, SixTen(0b011111, 729), sreqx); BindConditional(is601, SixTen(0b011111, 696), sriqx); BindConditional(is601, SixTen(0b011111, 760), srliqx); BindConditional(is601, SixTen(0b011111, 728), srlqx); BindConditional(is601, SixTen(0b011111, 664), srqx); // 32-bit instructions. Bind(SixTen(0b010011, 0b0000000000), mcrf); Bind(SixTen(0b010011, 0b0000010000), bclrx); Bind(SixTen(0b010011, 0b0000100001), crnor); Bind(SixTen(0b010011, 0b0000110010), rfi); Bind(SixTen(0b010011, 0b0010000001), crandc); Bind(SixTen(0b010011, 0b0010010110), isync); Bind(SixTen(0b010011, 0b0011000001), crxor); Bind(SixTen(0b010011, 0b0011100001), crnand); Bind(SixTen(0b010011, 0b0100000001), crand); Bind(SixTen(0b010011, 0b0100100001), creqv); Bind(SixTen(0b010011, 0b0110100001), crorc); Bind(SixTen(0b010011, 0b0111000001), cror); Bind(SixTen(0b010011, 0b1000010000), bcctrx); Bind(SixTen(0b011111, 0b0000000000), cmp); Bind(SixTen(0b011111, 0b0000000100), tw); Bind(SixTen(0b011111, 0b0000001000), subfcx); Bind(SixTen(0b011111, 0b1000001000), subfcx); Bind(SixTen(0b011111, 0b0000001010), addcx); Bind(SixTen(0b011111, 0b1000001010), addcx); Bind(SixTen(0b011111, 0b0000001011), mulhwux); Bind(SixTen(0b011111, 0b1000001011), mulhwux); Bind(SixTen(0b011111, 0b0000010011), mfcr); Bind(SixTen(0b011111, 0b0000010100), lwarx); Bind(SixTen(0b011111, 0b0000010111), lwzx); Bind(SixTen(0b011111, 0b0000011000), slwx); Bind(SixTen(0b011111, 0b0000011010), cntlzwx); Bind(SixTen(0b011111, 0b0000011100), andx); Bind(SixTen(0b011111, 0b0000100000), cmpl); Bind(SixTen(0b011111, 0b0000101000), subfx); Bind(SixTen(0b011111, 0b1000101000), subfx); Bind(SixTen(0b011111, 0b0000110110), dcbst); Bind(SixTen(0b011111, 0b0000110111), lwzux); Bind(SixTen(0b011111, 0b0000111100), andcx); Bind(SixTen(0b011111, 0b0001001011), mulhwx); Bind(SixTen(0b011111, 0b1001001011), mulhwx); Bind(SixTen(0b011111, 0b0001010011), mfmsr); Bind(SixTen(0b011111, 0b0001010110), dcbf); Bind(SixTen(0b011111, 0b0001010111), lbzx); Bind(SixTen(0b011111, 0b0001101000), negx); Bind(SixTen(0b011111, 0b1001101000), negx); Bind(SixTen(0b011111, 0b0001110111), lbzux); Bind(SixTen(0b011111, 0b0001111100), norx); Bind(SixTen(0b011111, 0b0010001000), subfex); Bind(SixTen(0b011111, 0b1010001000), subfex); Bind(SixTen(0b011111, 0b0010001010), addex); Bind(SixTen(0b011111, 0b1010001010), addex); Bind(SixTen(0b011111, 0b0010010000), mtcrf); Bind(SixTen(0b011111, 0b0010010010), mtmsr); Bind(SixTen(0b011111, 0b0010010111), stwx); Bind(SixTen(0b011111, 0b0010110111), stwux); Bind(SixTen(0b011111, 0b0011001000), subfzex); Bind(SixTen(0b011111, 0b1011001000), subfzex); Bind(SixTen(0b011111, 0b0011001010), addzex); Bind(SixTen(0b011111, 0b1011001010), addzex); Bind(SixTen(0b011111, 0b0011010111), stbx); Bind(SixTen(0b011111, 0b0011101000), subfmex); Bind(SixTen(0b011111, 0b1011101000), subfmex); Bind(SixTen(0b011111, 0b0011101010), addmex); Bind(SixTen(0b011111, 0b1011101010), addmex); Bind(SixTen(0b011111, 0b0011101011), mullwx); Bind(SixTen(0b011111, 0b1011101011), mullwx); Bind(SixTen(0b011111, 0b0011110110), dcbtst); Bind(SixTen(0b011111, 0b0011110111), stbux); Bind(SixTen(0b011111, 0b0100001010), addx); Bind(SixTen(0b011111, 0b1100001010), addx); Bind(SixTen(0b011111, 0b0100010110), dcbt); Bind(SixTen(0b011111, 0b0100010111), lhzx); Bind(SixTen(0b011111, 0b0100011100), eqvx); Bind(SixTen(0b011111, 0b0100110110), eciwx); Bind(SixTen(0b011111, 0b0100110111), lhzux); Bind(SixTen(0b011111, 0b0100111100), xorx); Bind(SixTen(0b011111, 0b0101010111), lhax); Bind(SixTen(0b011111, 0b0101110011), mftb); Bind(SixTen(0b011111, 0b0101110111), lhaux); Bind(SixTen(0b011111, 0b0110010111), sthx); Bind(SixTen(0b011111, 0b0110011100), orcx); Bind(SixTen(0b011111, 0b0110110110), ecowx); Bind(SixTen(0b011111, 0b0110110111), sthux); Bind(SixTen(0b011111, 0b0110111100), orx); Bind(SixTen(0b011111, 0b0111001011), divwux); Bind(SixTen(0b011111, 0b1111001011), divwux); Bind(SixTen(0b011111, 0b0111010110), dcbi); Bind(SixTen(0b011111, 0b0111011100), nandx); Bind(SixTen(0b011111, 0b0111101011), divwx); Bind(SixTen(0b011111, 0b1111101011), divwx); Bind(SixTen(0b011111, 0b1000000000), mcrxr); Bind(SixTen(0b011111, 0b1000010101), lswx); Bind(SixTen(0b011111, 0b1000010110), lwbrx); Bind(SixTen(0b011111, 0b1000010111), lfsx); Bind(SixTen(0b011111, 0b1000011000), srwx); Bind(SixTen(0b011111, 0b1000110111), lfsux); Bind(SixTen(0b011111, 0b1001010101), lswi); Bind(SixTen(0b011111, 0b1001010110), sync); Bind(SixTen(0b011111, 0b1001010111), lfdx); Bind(SixTen(0b011111, 0b1001110111), lfdux); Bind(SixTen(0b011111, 0b1010010101), stswx); Bind(SixTen(0b011111, 0b1010010110), stwbrx); Bind(SixTen(0b011111, 0b1010010111), stfsx); Bind(SixTen(0b011111, 0b1010110111), stfsux); Bind(SixTen(0b011111, 0b1011010101), stswi); Bind(SixTen(0b011111, 0b1011010111), stfdx); Bind(SixTen(0b011111, 0b1011110111), stfdux); Bind(SixTen(0b011111, 0b1100010110), lhbrx); Bind(SixTen(0b011111, 0b1100011000), srawx); Bind(SixTen(0b011111, 0b1100111000), srawix); Bind(SixTen(0b011111, 0b1101010110), eieio); Bind(SixTen(0b011111, 0b1110010110), sthbrx); Bind(SixTen(0b011111, 0b1110011010), extshx); Bind(SixTen(0b011111, 0b1110111010), extsbx); Bind(SixTen(0b011111, 0b1111010110), icbi); Bind(SixTen(0b011111, 0b1111010111), stfiwx); Bind(SixTen(0b011111, 0b1111110110), dcbz); Bind(SixTen(0b111111, 0b0000000000), fcmpu); Bind(SixTen(0b111111, 0b0000001100), frspx); Bind(SixTen(0b111111, 0b0000001110), fctiwx); Bind(SixTen(0b111111, 0b0000001111), fctiwzx); Bind(SixTen(0b111111, 0b0000100000), fcmpo); Bind(SixTen(0b111111, 0b0000100110), mtfsb1x); Bind(SixTen(0b111111, 0b0000101000), fnegx); Bind(SixTen(0b111111, 0b0001000000), mcrfs); Bind(SixTen(0b111111, 0b0001000110), mtfsb0x); Bind(SixTen(0b111111, 0b0001001000), fmrx); Bind(SixTen(0b111111, 0b0010000110), mtfsfix); Bind(SixTen(0b111111, 0b0010001000), fnabsx); Bind(SixTen(0b111111, 0b0100001000), fabsx); Bind(SixTen(0b111111, 0b1001000111), mffsx); Bind(SixTen(0b111111, 0b1011000111), mtfsfx); Bind(SixTen(0b111111, 0b1100101110), fctidx); Bind(SixTen(0b111111, 0b1100101111), fctidzx); Bind(SixTen(0b111111, 0b1101001110), fcfidx); Bind(SixTen(0b011111, 0b0101010011), mfspr); // Flagged as "supervisor and user"? Bind(SixTen(0b011111, 0b0111010011), mtspr); // Flagged as "supervisor and user"? BindSupervisorConditional(is32bit, SixTen(0b011111, 0b0011010010), mtsr); BindSupervisorConditional(is32bit, SixTen(0b011111, 0b0011110010), mtsrin); BindSupervisorConditional(is32bit, SixTen(0b011111, 0b1001010011), mfsr); BindSupervisorConditional(is32bit, SixTen(0b011111, 0b1010010011), mfsrin); BindSupervisorConditional(is64bit, SixTen(0b011111, 0b0111110010), slbia); // optional // The following are all optional; should I record that? BindSupervisor(SixTen(0b011111, 0b0100110010), tlbie); BindSupervisor(SixTen(0b011111, 0b0101110010), tlbia); BindSupervisor(SixTen(0b011111, 0b1000110110), tlbsync); } // Third pass: like six-ten except that the top five of the final ten // are reserved (i.e. ignored here). switch(opcode & SixTen(0b111111, 0b11111)) { default: break; Bind(SixTen(0b111011, 0b10010), fdivsx); Bind(SixTen(0b111011, 0b10100), fsubsx); Bind(SixTen(0b111011, 0b10101), faddsx); Bind(SixTen(0b111011, 0b11001), fmulsx); Bind(SixTen(0b111011, 0b11100), fmsubsx); Bind(SixTen(0b111011, 0b11101), fmaddsx); Bind(SixTen(0b111011, 0b11110), fnmsubsx); Bind(SixTen(0b111011, 0b11111), fnmaddsx); Bind(SixTen(0b111111, 0b10010), fdivx); Bind(SixTen(0b111111, 0b10100), fsubx); Bind(SixTen(0b111111, 0b10101), faddx); Bind(SixTen(0b111111, 0b11001), fmulx); Bind(SixTen(0b111111, 0b11100), fmsubx); Bind(SixTen(0b111111, 0b11101), fmaddx); Bind(SixTen(0b111111, 0b11110), fnmsubx); Bind(SixTen(0b111111, 0b11111), fnmaddx); BindConditional(is64bit, SixTen(0b111011, 0b10110), fsqrtsx); BindConditional(is64bit, SixTen(0b111011, 0b11000), fresx); BindConditional(is64bit, SixTen(0b011110, 0b01000), rldclx); BindConditional(is64bit, SixTen(0b011110, 0b01001), rldcrx); // Optional... Bind(SixTen(0b111111, 0b10110), fsqrtx); Bind(SixTen(0b111111, 0b10111), fselx); Bind(SixTen(0b111111, 0b11010), frsqrtex); } // rldicx, rldiclx, rldicrx, rldimix if(is64bit(model)) { switch(opcode & 0b111111'00000'00000'00000'000000'111'00) { default: break; case 0b011110'00000'00000'00000'000000'000'00: return instruction(opcode); case 0b011110'00000'00000'00000'000000'001'00: return instruction(opcode); case 0b011110'00000'00000'00000'000000'010'00: return instruction(opcode); case 0b011110'00000'00000'00000'000000'011'00: return instruction(opcode); } } // stwcx. and stdcx. switch(opcode & 0b111111'0000'0000'0000'0000'111111111'1) { default: break; case 0b011111'0000'0000'0000'0000'010010110'1: return instruction(opcode); case 0b011111'0000'0000'0000'0000'011010110'1: if(is64bit(model)) return instruction(opcode); return Instruction(opcode); } // std, stdu, ld, ldu, lwa if(is64bit(model)) { switch(opcode & 0b111111'00'00000000'00000000'000000'11) { default: break; case 0b111010'00'00000000'00000000'000000'00: return instruction(opcode); case 0b111010'00'00000000'00000000'000000'01: return instruction(opcode); case 0b111010'00'00000000'00000000'000000'10: return instruction(opcode); case 0b111110'00'00000000'00000000'000000'00: return instruction(opcode); case 0b111110'00'00000000'00000000'000000'01: return instruction(opcode); } } // sc if((opcode & 0b111111'00'00000000'00000000'000000'1'0) == 0b010001'00'00000000'00000000'000000'1'0) { return instruction(opcode); } #undef Six #undef SixTen #undef Bind #undef BindConditional return Instruction(opcode); } template struct InstructionSet::PowerPC::Decoder; template struct InstructionSet::PowerPC::Decoder; template struct InstructionSet::PowerPC::Decoder; template struct InstructionSet::PowerPC::Decoder; template struct InstructionSet::PowerPC::Decoder; template struct InstructionSet::PowerPC::Decoder;