1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-11-26 23:52:26 +00:00
CLK/InstructionSets/PowerPC/Instruction.hpp

1532 lines
30 KiB
C++
Raw Normal View History

2020-12-31 03:55:59 +00:00
//
2021-01-15 23:16:01 +00:00
// Instruction.hpp
2020-12-31 03:55:59 +00:00
// Clock Signal
//
// Created by Thomas Harte on 15/01/21.
2021-01-15 23:16:01 +00:00
// Copyright © 2021 Thomas Harte. All rights reserved.
2020-12-31 03:55:59 +00:00
//
#pragma once
2020-12-31 03:55:59 +00:00
#include <cstdint>
2023-05-10 21:02:18 +00:00
namespace InstructionSet::PowerPC {
2020-12-31 03:55:59 +00:00
2022-03-21 14:17:55 +00:00
enum class CacheLine: uint32_t {
Instruction = 0b01100,
Data = 0b1101,
Minimum = 0b01110,
Maximum = 0b01111,
};
/// Provides the meaning of individual bits within the condition register;
/// bits are counted in IBM/Motorola order, so *bit 0 is the most significant.*
enum class Condition: uint32_t {
// CR0
Negative = 0, // LT
Positive = 1, // GT
Zero = 2, // EQ
SummaryOverflow = 3, // SO
// CR1
FPException = 4, // FX
FPEnabledException = 5, // FEX
FPInvalidException = 6, // VX
FPOverflowException = 7, // OX
// CRs27 fill out the condition register.
};
2022-03-25 12:41:57 +00:00
enum class BranchOption: uint32_t {
// Naming convention:
//
// Dec_ prefix => decrement the CTR;
// condition starting NotZero or Zero => test CTR;
// condition ending Set or Clear => test the condition bit.
Dec_NotZeroAndClear = 0b0000,
Dec_ZeroAndClear = 0b0001,
Clear = 0b0010,
Dec_NotZeroAndSet = 0b0100,
Dec_ZeroAndSet = 0b0101,
Set = 0b0110,
Dec_NotZero = 0b1000,
Dec_Zero = 0b1001,
Always = 0b1010,
};
2022-04-04 00:33:32 +00:00
/// @returns @c 0 if reg == 0; @c ~0 otherwise.
/// @discussion Provides a branchless way to substitute the value 0 for the value of r0
2022-04-04 00:37:09 +00:00
/// in affected instructions. Assumes arithmetic shifts.
2022-04-04 00:33:32 +00:00
template <typename IntT> constexpr IntT is_zero_mask(uint32_t reg) {
2022-04-04 00:37:09 +00:00
return ~IntT((int(reg) - 1) >> 5);
2022-04-04 00:33:32 +00:00
}
2020-12-31 03:55:59 +00:00
enum class Operation: uint8_t {
Undefined,
//
// MARK: - 601-exclusive instructions.
//
// A lot of them are carry-overs from POWER, left in place
// due to the tight original development timeline.
//
// These are not part of the PowerPC architecture.
2022-03-21 14:17:55 +00:00
/// Absolute.
/// abs abs. abso abso.
/// rD(), rA() [oe(), rc()]
2022-03-21 14:17:55 +00:00
absx,
/// Cache line compute size.
/// clcs
/// rD(), rA()
2022-03-21 14:17:55 +00:00
clcs,
/// Divide short.
/// divs divs. divso divso.
/// rD(), rA(), rB() [rc(), eo()]
2022-03-21 14:49:01 +00:00
divsx,
2022-04-09 14:20:03 +00:00
/// Divide.
/// div div. divo divo.
/// rD(), rA(), rB() [rc(), oe()]
2022-04-09 14:20:03 +00:00
divx,
2022-03-21 14:49:01 +00:00
/// Difference or zero immediate.
/// dozi
/// rD(), rA(), simm()
2022-03-21 14:49:01 +00:00
dozi,
2022-04-09 14:20:03 +00:00
/// Difference or zero.
/// doz doz. dozo dozo.
/// rD(), rA(), rB() [rc(), oe()]
dozx,
2022-04-02 14:26:47 +00:00
/// Load string and compare byte indexed.
/// lscbx lsxbx.
2022-04-03 22:29:40 +00:00
/// rD(), rA(), rB() [rc()]
2022-04-02 14:26:47 +00:00
lscbxx,
2022-04-03 12:06:59 +00:00
/// Mask generate.
/// maskg maskg.
/// rA(), rS(), rB() [rc()]
maskgx,
/// Mask insert from register.
/// maskir maskir.
/// rA(), rS(), rB() [rc()]
maskirx,
/// Multiply.
/// mul mul. mulo mulo.
/// rA(), rB(), rD()
mulx,
2022-04-07 00:53:44 +00:00
/// Negative absolute.
/// nabs nabs. nabso nabso.
/// rD(), rA() [rc(), oe()]
nabsx,
/// Rotate left then mask insert.
/// rlmi rlmi.
2022-04-10 13:35:58 +00:00
/// rA(), rS(), rB(), mb(), me() [rc()]
2022-04-10 12:57:09 +00:00
/// Cf. rotate_mask()
2022-04-07 00:53:44 +00:00
rlmix,
/// Rotate right and insert bit.
/// rrib rrib.
/// rA(), rS(), rB() [rc()]
rribx,
/// Shift left extended with MQ.
/// sleq sleq.
/// rA(), rS(), rB() [rc()]
sleqx,
2022-04-09 14:20:03 +00:00
/// Shift left extended.
/// sle sle.
/// rA(), rS(), rB() [rc()]
slex,
2022-04-07 00:53:44 +00:00
/// Shift left immediate with MQ.
/// sliq sliq.
2022-04-10 13:35:58 +00:00
/// rA(), rS(), sh() [rc()]
2022-04-07 00:53:44 +00:00
sliqx,
/// Shift left long immediate with MQ.
/// slliq slliq.
2022-04-10 13:35:58 +00:00
/// rA(), rS(), sh() [rc()]
2022-04-07 00:53:44 +00:00
slliqx,
/// Shift left long with MQ.
/// sllq sllq.
/// rA(), rS(), rB() [rc()]
sllqx,
/// Shift left with MQ.
/// slq slq.
/// rA(), rS(), rB() [rc()]
slqx,
/// Shift right algebraic immediate with MQ.
/// sraiq sraiq.
2022-04-10 13:35:58 +00:00
/// rA(), rS(), sh() [rc()]
2022-04-07 00:53:44 +00:00
sraiqx,
/// Shift right algebraic with MQ.
/// sraq sraq.
/// rA(), rS(), rB() [rc()]
sraqx,
/// Shift right extended algebraic.
/// srea srea.
/// rA(), rS(), rB() [rc()]
sreax,
/// Shift right extended with MQ.
/// sreq sreq.
2022-04-07 01:09:58 +00:00
/// rA(), rS(), rB() [rc()]
2022-04-07 00:53:44 +00:00
sreqx,
2022-04-09 14:20:03 +00:00
/// Shift right extended.
/// sre sre.
/// rA(), rS(), rB() [rc()]
srex,
2022-04-07 00:53:44 +00:00
/// Shift right immediate with MQ.
/// sriq sriq.
2022-04-10 13:35:58 +00:00
/// rA(), rS(), sh() [rc()]
2022-04-07 00:53:44 +00:00
sriqx,
/// Shift right long immediate with MQ.
/// srliq srliq.
2022-04-10 13:35:58 +00:00
/// rA(), rS(), sh() [rc()]
2022-04-07 00:53:44 +00:00
srliqx,
/// Shift right long with MQ.
/// srlq srlq.
/// rA(), rS(), rB() [rc()]
srlqx,
/// Shidt right with MQ.
/// srq srq.
/// rA(), rS(), rB() [rc()]
srqx,
2021-01-15 23:16:01 +00:00
//
// MARK: - 32- and 64-bit PowerPC instructions.
//
/// Add.
/// add add. addo addo.
/// rD(), rA(), rB() [rc(), oe()]
addx,
/// Add carrying.
/// addc addc. addco addco.
/// rD(), rA(), rB() [rc(), oe()]
addcx,
/// Add extended.
/// adde adde. addeo addeo.
/// rD(), rA(), rB() [rc(), eo()]
addex,
/// Add immediate.
/// addi
/// rD(), rA(), simm()
addi,
/// Add immediate carrying.
/// addic
/// rD(), rA(), simm()
addic,
/// Add immediate carrying and record.
/// addic.
/// rD(), rA(), simm()
addic_,
/// Add immediate shifted.
/// addis.
/// rD(), rA(), simm()
addis,
/// Add to minus one.
/// addme addme. addmeo addmeo.
/// rD(), rA() [rc(), oe()]
addmex,
/// Add to zero extended.
/// addze addze. addzeo addzeo.
/// rD(), rA() [rc(), oe()]
addzex,
/// And.
/// and, and.
/// rA(), rS(), rB() [rc()]
andx,
2022-03-29 18:37:21 +00:00
/// And with complement.
/// andc, andc.
/// rA(), rS(), rB() [rc()]
2022-03-29 18:37:21 +00:00
andcx,
/// And immediate.
/// andi.
/// rA(), rS(), uimm()
2022-03-29 18:37:21 +00:00
andi_,
/// And immediate shifted.
/// andis.
/// rA(), rS(), uimm()
2022-03-29 18:37:21 +00:00
andis_,
/// Branch unconditional.
/// b bl ba bla
/// li() [aa(), lk()]
bx,
/// Branch conditional.
/// bne bne+ beq bdnzt+ bdnzf bdnzt bdnzfla ...
/// bo(), bi(), bd() [aa(), lk()]
bcx,
/// Branch conditional to count register.
/// bctr bctrl bnectrl bnectrl bltctr blectr ...
/// bo(), bi() [aa(), lk()]
bcctrx,
2022-03-25 10:25:06 +00:00
/// Branch conditional to link register.
/// blr blrl bltlr blelrl bnelrl ...
/// bo(), bi() [aa(), lk()]
2022-03-25 10:25:06 +00:00
bclrx,
/// Compare
/// cmp
/// crfD(), l(), rA(), rB()
cmp,
/// Compare immediate.
/// cmpi
/// crfD(), l(), rA(), simm()
cmpi,
/// Compare logical.
/// cmpl
/// crfD(), l(), rA(), rB()
cmpl,
/// Compare logical immediate.
/// cmpli
/// crfD(), l(), rA(), uimm()
cmpli,
/// Count leading zero words.
/// cntlzw cntlzw.
/// rA(), rS() [rc()]
cntlzwx,
/// Condition register and.
/// crand
/// crbD(), crbA(), crbB()
crand,
/// Condition register and with complement.
/// crandc
/// crbD(), crbA(), crbB()
crandc,
/// Condition register equivalent.
/// creqv
/// crbD(), crbA(), crbB()
creqv,
/// Condition register nand.
/// crnand
/// crbD(), crbA(), crbB()
crnand,
/// Condition register nor.
/// crnor
/// crbD(), crbA(), crbB()
crnor,
/// Condition register or.
/// cror
/// crbD(), crbA(), crbB()
cror,
/// Condition register or with complement.
/// crorc
/// crbD(), crbA(), crbB()
crorc,
/// Condition register xor.
/// crxor
/// crbD(), crbA(), crbB()
crxor,
/// Data cache block flush.
/// dcbf
/// rA(), rB()
dcbf,
/// Data cache block store.
/// dcbst
/// rA(), rB()
dcbst,
/// Data cache block touch.
/// dcbt
/// rA(), rB()
dcbt,
/// Data cache block touch for store.
/// dcbtst
/// rA(), rB()
dcbtst,
/// Data cache block set to zero.
/// dcbz
/// rA(), rB()
dcbz,
2022-04-09 14:20:03 +00:00
/// Divide word.
/// divw divw. divwo divwo.
/// rD(), rA(), rB() [rc(), oe()]
divwx,
/// Divide word unsigned.
/// divwu divwu. divwuo divwuo.
/// rD(), rA(), rB() [rc(), oe()]
divwux,
/// External control in word indexed.
/// eciwx
/// rD(), rA(), rB()
eciwx,
/// External control out word indexed.
/// ecowx
/// rS(), rA(), rB()
ecowx,
/// Enforce in-order execition of I/O
/// eieio
eieio,
/// Equivalent.
/// eqv eqv.
/// rA(), rS(), rB() [rc()]
eqvx,
/// Extend sign byte.
/// extsb extsb.
/// rA(), rS() [rc()]
extsbx,
/// Extend sign half-word.
/// extsh extsh.
/// rA(), rS() [rc()]
extshx,
/// Floating point absolute.
/// fabs fabs.
2022-04-03 12:06:59 +00:00
/// frD(), frB() [rc()]
fabsx,
2022-04-09 14:20:03 +00:00
/// Floating point add.
/// fadd fadd.
/// frD(), frA(), frB() [rc()]
faddx,
/// Floating point add single precision.
/// fadds fadds.
/// frD(), frA(), frB() [rc()]
faddsx,
/// Floating point compare ordered.
/// fcmpo
2022-04-03 19:50:03 +00:00
/// crfD(), frA(), frB()
fcmpo,
/// Floating point compare unordered.
/// fcmpu
2022-04-03 19:50:03 +00:00
/// crfD(), frA(), frB()
fcmpu,
/// Floating point convert to integer word.
/// fctiw fctiw.
/// frD(), frB() [rc()]
fctiwx,
/// Floating point convert to integer word with round towards zero.
/// fctiw fctiw.
/// frD(), frB() [rc()]
fctiwzx,
2022-04-09 14:20:03 +00:00
/// Floating point divide.
/// fdiv fdiv.
/// frD(), frA(), frB() [rc()]
fdivx,
/// Floating point divide single precision.
/// fdiv fdiv.
/// frD(), frA(), frB() [rc()]
fdivsx,
2022-04-09 14:20:03 +00:00
/// Floating point multiply add.
/// fmadd fmadd.
/// frD(), frA(), frC(), frB() [rc()]
fmaddx,
/// Floating point multiply add single precision.
/// fmadds fmadds.
/// frD(), frA(), frC(), frB() [rc()]
fmaddsx,
2022-04-03 12:06:59 +00:00
/// Floating point register move.
/// fmr fmr.
/// frD(), frB() [rc()]
fmrx,
2022-04-09 14:20:03 +00:00
/// Floating point multiply subtract.
/// fmsub fmsub.
/// frD(), frA(), frC(), frB() [rc()]
fmsubx,
/// Floating point multiply subtract single precision.
/// fmsubx fmsubx.
/// frD(), frA(), frC(), frB() [rc()]
fmsubsx,
2022-04-09 14:20:03 +00:00
/// Floating point multiply.
/// fmul fmul.
/// frD(), frA(), frC() [rc()]
fmulx,
/// Floating point multiply single precision.
/// fmuls fmuls.
/// frD(), frA(), frC() [rc()]
fmulsx,
2022-04-03 12:06:59 +00:00
/// Floating negative absolute value.
/// fnabs fnabs.
/// frD(), frB() [rc()]
fnabsx,
/// Floating negative.
/// fneg fneg.
/// frD(), frB() [rc()]
fnegx,
2022-04-09 14:20:03 +00:00
/// Floating point negative multiply add.
/// fnmadd fnmadd.
/// frD(), frA(), frC(), frB() [rc()]
2022-04-09 14:20:03 +00:00
fnmaddx,
/// Floating point negative multiply add single precision.
/// fnmadds fnmadds.
/// frD(), frA(), frC(), frB() [rc()]
fnmaddsx,
2022-04-09 14:20:03 +00:00
/// Floating point negative multiply subtract.
/// fnmsub fnmsub.
/// frD(), frA(), frC(), frB() [rc()]
fnmsubx,
/// Floating point negative multiply add.
/// fnmsubs fnmsubs.
/// frD(), frA(), frC(), frB() [rc()]
fnmsubsx,
2022-04-03 12:06:59 +00:00
/// Floating point round to single precision.
/// frsp frsp.
/// frD(), frB() [rc()]
frspx,
2022-04-09 14:20:03 +00:00
/// Floating point subtract.
/// fsub fsub.
/// frD(), frA(), frB() [rc()]
fsubx,
/// Floating point subtract single precision.
/// fsubs fsubs.
/// frD(), frA(), frB() [rc()]
fsubsx,
2022-04-03 22:29:40 +00:00
/// Instruction cache block invalidate.
/// icbi
/// rA(), rB()
icbi,
/// Instruction synchronise.
/// isync
isync,
2022-04-02 19:27:12 +00:00
/// Load byte and zero.
/// lbz
/// rD(), d() [ rA() ]
lbz,
/// Load byte and zero with update.
/// lbz
/// rD(), d() [ rA() ]
lbzu,
2022-03-26 12:45:07 +00:00
/// Load byte and zero with update indexed.
/// lbzux
2022-04-02 19:27:12 +00:00
/// rD(), rA(), rB()
2022-03-26 12:45:07 +00:00
lbzux,
/// Load byte and zero indexed.
/// lbzx
2022-04-02 19:27:12 +00:00
/// rD(), rA(), rB()
2022-03-26 12:45:07 +00:00
lbzx,
2022-04-02 19:40:17 +00:00
/// Load floating point double precision.
/// lfd
/// frD(), d() [ rA() ]
lfd,
/// Load floating point double precision with update.
/// lfdu
/// frD(), d() [ rA() ]
lfdu,
/// Load floating point double precision with update indexed.
/// lfdux
/// frD(), rA(), rB()
lfdux,
/// Load floating point double precision indexed.
/// lfdx
/// frD(), rA(), rB()
lfdx,
/// Load floating point single precision.
/// lfs
/// frD(), d() [ rA() ]
lfs,
/// Load floating point single precision with update.
/// lfsu
/// frD(), d() [ rA() ]
lfsu,
/// Load floating point single precision with update indexed.
/// lfsux
/// frD(), rA(), rB()
lfsux,
/// Load floating point single precision indexed.
/// lfsx
/// frD(), rA(), rB()
lfsx,
2022-04-02 19:27:12 +00:00
/// Load half word algebraic.
/// lha
/// rD(), d() [ rA() ]
lha,
/// Load half word algebraic with update.
/// lha
/// rD(), d() [ rA() ]
lhau,
/// Load half-word algebraic with update indexed.
/// lhaux
/// rD(), rA(), rB()
lhaux,
/// Load half-word algebraic indexed.
/// lhax
/// rD(), rA(), rB()
lhax,
/// Load half word byte-reverse indexed.
/// lhbrx
/// rD(), rA(), rB()
lhbrx,
/// Load half word and zero.
/// lhz
2022-04-02 19:27:12 +00:00
/// rD(), d() [ rA() ]
lhz,
/// Load half-word and zero with update.
/// lhzu
2022-04-02 19:27:12 +00:00
/// rD(), d() [ rA() ]
lhzu,
/// Load half-word and zero with update indexed.
/// lhzux
/// rD(), rA(), rB()
lhzux,
/// Load half-word and zero indexed.
/// lhzx
/// rD(), rA(), rB()
lhzx,
2022-04-02 14:26:47 +00:00
/// Load multiple word.
/// lmw
/// rD(), d() [ rA() ]
lmw,
2022-04-02 14:26:47 +00:00
/// Load string word immediate.
/// lswi
/// rD(), rA(), nb()
lswi,
/// Load string word indexed.
/// lswx
/// rD(), rA(), rB()
lswx,
/// Load word and reserve indexed.
/// lwarx
/// rD(), rA(), rB()
lwarx,
/// Load word byte-reverse indexed.
/// lwbrx
/// rD(), rA(), rB()
lwbrx,
/// Load word and zero.
/// lwz
/// rD(), d() [ rA() ]
lwz,
/// Load word and zero with update.
/// lwzu
/// rD(), d() [ rA() ]
lwzu,
2022-03-26 00:31:47 +00:00
2022-03-26 12:45:07 +00:00
/// Load word and zero with update indexed.
/// lwzux
2022-03-26 00:31:47 +00:00
lwzux,
2022-03-26 00:23:21 +00:00
/// Load word and zero indexed.
/// lwzx
2022-03-26 00:23:21 +00:00
lwzx,
2022-04-03 12:06:59 +00:00
/// Move condition register field.
/// mcrf
/// crfD(), crfS()
mcrf,
/// Move to condition register from FPSCR.
/// mcrfs
/// crfD(), crfS()
mcrfs,
2022-04-03 12:55:28 +00:00
/// Move to condition register from XER.
/// mcrxr
/// crfD()
2022-04-03 12:06:59 +00:00
mcrxr,
2022-04-03 12:55:28 +00:00
/// Move from condition register.
/// mfcr
/// rD()
mfcr,
2022-04-04 00:33:32 +00:00
/// Move from FPSCR.
/// mffs mffs.
/// frD() [rc()]
mffsx,
/// Move from machine state register.
/// mfmsr
/// rD()
mfmsr,
/// Move from special purpose record.
/// mfmsr
/// rD(), spr()
mfspr,
/// Move from segment register.
/// mfsr
/// rD(), sr()
mfsr,
/// Move from segment register indirect.
/// mfsrin
/// rD(), rB()
mfsrin,
/// Move to condition register fields.
/// mtcrf
/// rS(), crm()
mtcrf,
2022-04-03 12:55:28 +00:00
/// Move to FPSCR bit 0.
/// mtfsb0 mtfsb0.
/// crbD()
mtfsb0x,
/// Move to FPSCR bit 1.
/// mtfsb1 mtfsb1.
/// crbD()
mtfsb1x,
/// Move to FPSCR fields.
/// mtfsf mtfsf.
/// fm(), frB() [rc()]
mtfsfx,
/// Move to FPSCR field immediate.
/// mtfsfi mtfsfi.
/// crfD(), imm()
mtfsfix,
2022-04-04 00:33:32 +00:00
/// Move to FPSCR.
/// mtfs
/// frS()
mtmsr,
/// Move to special purpose record.
/// mtmsr
/// rD(), spr()
mtspr,
/// Move to segment register.
/// mfsr
/// sr(), rS()
mtsr,
/// Move to segment register indirect.
/// mtsrin
/// rD(), rB()
mtsrin,
/// Multiply high word.
/// mulhw mulgw.
/// rD(), rA(), rB(), rc()
mulhwx,
/// Multiply high word unsigned.
/// mulhwu mulhwu.
/// rD(), rA(), rB(), rc()
mulhwux,
/// Multiply low immediate.
2022-04-09 14:20:03 +00:00
/// mulli
/// rD(), rA(), simm()
mulli,
/// Multiply low word.
/// mullw mullw. mullwo mullwo.
/// rA(), rB(), rD()
mullwx,
2022-04-08 14:01:52 +00:00
/// NAND.
/// nand nand.
/// rA(), rS(), rB() [rc()]
nandx,
/// 'Negate' (negative).
/// neg neg. nego nego.
/// rD(), rA() [rc(), oe()]
negx,
/// NOR
/// nor nor.
/// rA(), rS(), rB() [rc()]
norx,
/// OR.
/// or or.
/// rA(), rS(), rB() [rc()]
orx,
2022-04-08 14:01:52 +00:00
/// OR with complement.
/// orc orc.
/// rA(), rS(), rB() [rc()]
orcx,
/// OR immediate.
/// ori
/// rA(), rS(), uimm()
ori,
/// OR immediate shifted.
/// oris
/// rA(), rS(), uimm()
oris,
/// Return from interrupt.
/// rfi
rfi,
/// Rotate left word immediate then mask insert.
/// rlwimi rlwimi.
2022-04-10 13:35:58 +00:00
/// rA(), rS(), sh(), mb(), me() [rc()]
2022-04-10 12:57:09 +00:00
/// Cf. rotate_mask()
2022-04-08 14:01:52 +00:00
rlwimix,
2022-03-30 20:43:09 +00:00
/// Rotate left word immediate then AND with mask.
/// rlwinm rlwinm.
2022-04-10 13:35:58 +00:00
/// rA(), rS(), sh(), mb(), me() [rc()]
2022-04-10 12:57:09 +00:00
/// Cf. rotate_mask()
2022-03-30 20:43:09 +00:00
rlwinmx,
/// Rotate left word then AND with mask
/// rlwimi rlwimi.
2022-04-10 13:35:58 +00:00
/// rA(), rB(), rS(), mb(), me() [rc()]
2022-04-10 12:57:09 +00:00
/// Cf. rotate_mask()
2022-03-30 20:43:09 +00:00
rlwnmx,
/// System call.
/// sc
sc,
/// Shift left word.
/// slw slw.
/// rA(), rS(), rB() [rc()]
slwx,
2022-04-09 14:20:03 +00:00
/// Shift right algebraic word.
/// sraw sraw.
/// rA(), rS(), rB() [rc()]
srawx,
/// Shift right algebraic word immediate.
/// srawi srawi.
2022-04-10 13:35:58 +00:00
/// rA(), rS(), sh() [rc()]
srawix,
2022-04-01 21:22:32 +00:00
/// Shift right word.
/// srw srw.
/// rA(), rS(), rB() [rc()]
srwx,
/// Store byte indexed.
/// stbx
/// rS(), rA(), rB()
stbx,
/// Store byte.
/// stb
/// rS(), d() [ rA() ]
stb,
/// Store byte with update.
/// stbu
/// rS(), d() [ rA() ]
stbu,
/// Store byte with update indexed.
/// stbux
/// rS(), rA(), rB()
stbux,
/// Store floating point double precision.
/// stfd
/// frS(), d() [ rA() ]
stfd,
/// Store floating point double precision with update.
/// stfdu
/// frS(), d() [ rA() ]
stfdu,
/// Store floating point double precision with update indexed.
/// stfdux
/// frS(), rA(), rB()
stfdux,
/// Store floating point double precision indexed.
/// stfdux
/// frS(), rA(), rB()
stfdx,
2022-04-02 00:37:36 +00:00
/// Store floating point single precision.
/// stfs
2022-04-02 19:40:17 +00:00
/// frS(), d() [ rA() ]
2022-04-02 00:37:36 +00:00
stfs,
/// Store floating point single precision with update.
2022-04-02 19:27:12 +00:00
/// stfsu
2022-04-02 19:40:17 +00:00
/// frS(), d() [ rA() ]
2022-04-02 00:37:36 +00:00
stfsu,
2022-04-02 19:27:12 +00:00
/// Store floating point single precision with update indexed.
/// stfsux
/// frS(), rA(), rB()
stfsux,
/// Store floating point single precisionindexed.
/// stfsx
/// frS(), rA(), rB()
stfsx,
/// Store half word.
/// sth
/// rS(), d() [ rA() ]
sth,
/// Store half word byte-reverse indexed.
/// sthbrx
/// rS(), rA(), rB()
sthbrx,
/// Store half word with update.
/// sthu
/// rS(), d() [ rA() ]
sthu,
/// Store half-word with update indexed.
2022-04-02 19:27:12 +00:00
/// sthux
/// rS(), rA(), rB()
sthux,
/// Store half-word indexed.
2022-04-02 19:27:12 +00:00
/// sthx
/// rS(), rA(), rB()
sthx,
2022-04-02 19:27:12 +00:00
/// Store multiple word.
/// stmw
/// rS(), d() [ rA() ]
stmw,
/// Store string word immediate.
/// stswi
/// rS(), rA(), nb()
stswi,
/// Store string word indexed.
/// stswx
/// rS(), rA(), rB()
stswx,
/// Store word.
/// stw
/// rS(), d() [ rA() ]
stw,
2022-04-02 00:37:36 +00:00
/// Store word byte-reverse indexed.
/// stwbrx
/// rS(), rA(), rB()
stwbrx,
/// Store word conditional.
/// stwcx.
/// rS(), rA(), rB()
stwcx_,
/// Store word with update.
/// stwu
/// rS(), d() [ rA() ]
stwu,
/// Store word with update indexed.
2022-04-02 00:37:36 +00:00
/// stwux
/// rS(), rA(), rB()
stwux,
/// Store word indexed.
2022-04-02 00:37:36 +00:00
/// stwx
/// rS(), rA(), rB()
stwx,
/// Subtract from.
/// subf subf. subfo subfo.
/// rD(), rA(), rB() [rc(), oe()]
subfx,
2022-03-29 00:18:41 +00:00
/// Subtract from carrying.
/// subfc subfc. subfco subfco.
2022-04-08 14:01:52 +00:00
/// rD(), rA(), rB() [rc(), oe()]
2022-03-29 00:18:41 +00:00
subfcx,
2022-04-02 00:37:36 +00:00
2022-04-08 14:01:52 +00:00
/// Subtract from extended.
/// subfe subfe. subfeo subfeo.
/// rD(), rA(), rB() [rc(), oe()]
subfex,
/// Subtract from immediate carrying
2022-04-08 14:01:52 +00:00
/// subfic
/// rD(), rA(), simm()
subfic,
2022-04-08 14:01:52 +00:00
/// Subtract from minus one extended.
/// subfme subfme. subfmeo subfmeo.
/// rD(), rA() [rc(), oe()]
subfmex,
/// Subtract from zero extended.
/// subfze subfze. subfzeo subfzeo.
/// rD(), rA() [rc(), oe()]
subfzex,
/// Synchronise.
/// sync
sync,
2022-04-02 14:09:58 +00:00
/// Trap word.
/// tw tweq tweqi twge twgei ...
/// to(), rA(), rB()
tw,
/// Trap word immediate.
/// twi
/// to(), rA(), simm()
twi,
/// Xor.
/// xor xor.
/// rA(), rS(), rB() [rc()]
xorx,
2022-04-02 14:09:58 +00:00
/// Xor immediate.
/// xori
/// rA(), rs(), uimm()
xori,
/// Xor immediate shifted.
/// xoris
/// rA(), rS(), uimm()
xoris,
2021-01-01 02:12:36 +00:00
//
// MARK: - 32-bit, supervisor level.
//
/// Data cache block invalidate.
/// dcbi
/// rA(), rB()
2020-12-31 03:55:59 +00:00
dcbi,
2021-01-01 02:12:36 +00:00
//
// MARK: - Supervisor, optional.
//
2022-04-04 00:33:32 +00:00
2022-04-09 14:20:03 +00:00
/// Translation lookaside buffer ('TLB') invalidate all.
2022-04-04 00:33:32 +00:00
/// tlbia
tlbia,
2022-04-09 14:20:03 +00:00
/// Translation lookaside buffer ('TLB') invalidate entry.
2022-04-04 00:33:32 +00:00
/// tlbie
/// rB()
tlbie,
2022-04-09 14:20:03 +00:00
/// Translation lookaside buffer ('TLB') synchronise.
2022-04-04 00:33:32 +00:00
/// tlbsync
tlbsync,
2021-01-01 02:12:36 +00:00
//
// MARK: - Optional.
//
2022-04-09 14:20:03 +00:00
/// Move from time base.
/// mftb
/// rD(), tbr()
mftb,
/// Floaring point reciprocal estimate single precision.
/// fres fres.
/// frD(), frB() [rc()]
fresx,
2022-04-03 12:06:59 +00:00
/// Floating point reciprocal square root estimation.
/// frsqrte frsqrte.
/// frD(), frB() [rc()]
frsqrtex,
/// Floating point select.
/// fsel fsel.
/// frD(), frA(), frC(), frB() [rc()]
fselx,
2022-04-08 14:01:52 +00:00
/// Floating Point square root.
/// fsqrt fsqrt.
/// frD(), frB() [rc()]
fsqrtx,
2022-04-02 14:09:58 +00:00
/// Floating point square root single precision.
/// fsqrts fsqrts.
/// frD(), frB() [rc()]
fsqrtsx,
2022-04-02 00:37:36 +00:00
/// Store floating point as integer word indexed.
/// stfiwx
/// frS(), rA(), rB()
stfiwx,
2020-12-31 03:55:59 +00:00
//
// MARK: - 64-bit only PowerPC instructions.
//
2022-04-09 14:20:03 +00:00
/// Count leading zero double word.
/// cntlzd cntlzd.
/// rA(), rS() [rc()]
cntlzdx,
2022-04-09 14:20:03 +00:00
/// Divide double word.
/// divd divd. divdo divdo.
/// rD(), rA(), rB() [rc(), oe()]
divdx,
/// Divide double word unsigned.
/// divdu divdu. divduo divduo.
/// rD(), rA(), rB() [rc(), oe()]
divdux,
/// Extend sign word.
/// extsw extsw.
/// rA(), rS() [rc()]
extswx,
/// Floating point convert from integer double word.
/// fcfid fcfid.
/// frD(), frB() [rc()]
fcfidx,
/// Floating point convert to integer double word.
/// fctid fctid.
/// frD(), frB() [rc()]
fctidx,
/// Floating point convert to integer double word with round towards zero.
/// fctid fctid.
/// frD(), frB() [rc()]
fctidzx,
2022-04-09 23:20:13 +00:00
/// Load double word.
/// ld
/// rD(), ds() [ rA() ]
ld,
2022-04-09 23:20:13 +00:00
/// Load double word and reserve indexed.
2022-04-09 14:20:03 +00:00
/// ldarx
/// rD(), rA(), rB()
ldarx,
2022-04-09 23:20:13 +00:00
/// Load double word with update.
/// ldu
/// rD(), ds() [ rA() ]
ldu,
2022-04-09 14:20:03 +00:00
/// Load double word with update indexed.
/// ldux
2022-04-09 23:20:13 +00:00
/// rD(), rA(), rB()
2022-04-09 14:20:03 +00:00
ldux,
/// Load double word indexed.
/// ldx
2022-04-09 23:20:13 +00:00
/// rD(), rA(), rB()
2022-04-09 14:20:03 +00:00
ldx,
/// Load word algebraic.
/// lwa
2022-04-09 23:20:13 +00:00
/// rD(), ds() [ rA() ]
2022-04-09 14:20:03 +00:00
lwa,
/// Load word algebraic with update indexed.
/// lwaux
/// rD(), rA(), rB()
lwaux,
/// Load word algebraic indexed.
/// lwax
/// rD(), rA(), rB()
lwax,
/// Multiply high double word.
/// mulhd mulhd.
/// rD(), rA(), rB() [rc()]
mulhdx,
/// Multiply high double word unsigned.
/// mulhdy mulhdu.
/// rD(), rA(), rB() [rc()]
mulhdux,
2022-04-09 14:20:03 +00:00
/// Multiply low double word.
/// mulld mulld. mulldo mulldo.
/// rD(), rA(), rB() [rc()]
mulldx,
2022-04-09 23:20:13 +00:00
/// Rotate left double word then clear left.
/// rldcl rldcl.
2022-04-10 12:57:09 +00:00
/// rA(), rS(), rB(), mb<uint64_t>() [rc()]
rldclx,
2022-04-09 23:20:13 +00:00
/// Rotate left double word then clear right.
/// rldcr rldcr.
2022-04-10 12:57:09 +00:00
/// rA(), rS(), rB(), mb<uint64_t>() [rc()]
rldcrx,
2022-04-09 23:20:13 +00:00
/// Rotate left double word then clear.
/// rldic rldic.
2022-04-10 12:57:09 +00:00
/// rA(), rS(), rB(), sh<uint64_t>(), mb<uint64_t>() [rc()]
rldicx,
2022-04-09 23:20:13 +00:00
/// Rotate left double word then clear left.
/// rldicl rldicl.
2022-04-10 12:57:09 +00:00
/// rA(), rS(), rB(), sh<uint64_t>(), mb<uint64_t>() [rc()]
rldiclx,
2022-04-09 23:20:13 +00:00
/// Rotate left double word then clear right.
/// rldicr rldicr.
2022-04-10 12:57:09 +00:00
/// rA(), rS(), rB(), sh<uint64_t>(), me<uint64_t>() [rc()]
rldicrx,
2022-04-09 23:20:13 +00:00
/// Rotate left double word immediate then mask insert.
/// rldiml rldimi.
2022-04-10 12:57:09 +00:00
/// rA(), rS(), rB(), sh<uint64_t>(), mb<uint64_t>() [rc()]
rldimix,
2022-04-09 14:20:03 +00:00
/// Segment lookaside buffer ('SLB') invalidate all.
/// slbia
slbia,
/// Segment lookaside buffer ('SLB') invalidate entry.
/// slbie
/// rB()
slbie,
/// Shift left double word.
/// sld sld.
/// rA(), rS(), rB()
sldx,
/// Shift right algebraic double word.
/// srad srad,
/// rA(), rS(), rB() [rc()]
sradx,
/// Shift right algebraic double word immediate.
/// sradi sradi.
2022-04-10 12:57:09 +00:00
/// rA(), rS(),sh<uint64_t>() [rc()]
sradix,
2022-04-09 14:20:03 +00:00
/// Shift right double word.
/// srd srd.
/// rA(), rS(), rB() [rc()]
srdx,
/// Store double.
/// std
/// rS(), ds() [ rA() ]
std,
/// Store double word conditional indexed.
/// stdcx.
/// rS(), rA(), rB()
stdcx_,
/// Store double word with update.
/// stdu
/// rS(), ds() [ rA() ]
stdu,
/// Store double word with update indexed.
/// stdux
/// rS(), rA(), rB()
stdux,
/// Store double word indexed.
/// stdx
/// rS(), rA(), rB()
stdx,
2022-04-09 14:20:03 +00:00
/// Trap double word.
/// td
/// to(), rA(), rB()
td,
2022-04-09 14:20:03 +00:00
/// Trap double word immediate.
/// tdi
/// to(), rA(), simm()
tdi,
2020-12-31 03:55:59 +00:00
};
/*!
Holds a decoded PowerPC instruction.
Implementation note: because the PowerPC encoding is particularly straightforward,
only the operation has been decoded ahead of time; all other fields are decoded on-demand.
It would be possible to partition the ordering of Operations into user followed by supervisor,
eliminating the storage necessary for a flag, but it wouldn't save anything due to alignment.
*/
2020-12-31 03:55:59 +00:00
struct Instruction {
Operation operation = Operation::Undefined;
bool is_supervisor = false;
uint32_t opcode = 0;
2020-12-31 03:55:59 +00:00
2024-02-17 02:35:49 +00:00
constexpr Instruction() noexcept = default;
constexpr Instruction(uint32_t opcode) noexcept : opcode(opcode) {}
constexpr Instruction(Operation operation, uint32_t opcode, bool is_supervisor = false) noexcept : operation(operation), is_supervisor(is_supervisor), opcode(opcode) {}
2020-12-31 03:55:59 +00:00
2021-01-01 16:46:26 +00:00
// Instruction fields are decoded below; naming is a compromise between
// Motorola's documentation and IBM's.
//
// I've dutifully implemented various synonyms with unique entry points,
// in order to capture that information here rather than thrusting it upon
// the reader of whatever implementation may follow.
2021-01-01 21:38:40 +00:00
// Currently omitted: OPCD and XO, which I think are unnecessary given that
// full decoding has already occurred.
2021-01-01 02:12:36 +00:00
2021-01-01 16:46:26 +00:00
/// Immediate field used to specify an unsigned 16-bit integer.
2021-01-05 03:36:39 +00:00
uint16_t uimm() const { return uint16_t(opcode & 0xffff); }
2021-01-01 16:46:26 +00:00
/// Immediate field used to specify a signed 16-bit integer.
2021-01-05 03:36:39 +00:00
int16_t simm() const { return int16_t(opcode & 0xffff); }
2021-01-01 21:38:40 +00:00
/// Immediate field used to specify a signed 16-bit integer.
2021-01-05 03:36:39 +00:00
int16_t d() const { return int16_t(opcode & 0xffff); }
2021-01-01 21:38:40 +00:00
/// Immediate field used to specify a signed 14-bit integer [64-bit only].
2021-01-05 03:36:39 +00:00
int16_t ds() const { return int16_t(opcode & 0xfffc); }
2021-01-01 16:46:26 +00:00
/// Immediate field used as data to be placed into a field in the floating point status and condition register.
2021-01-05 03:36:39 +00:00
int32_t imm() const { return (opcode >> 12) & 0xf; }
2021-01-01 16:46:26 +00:00
/// Specifies the conditions on which to trap.
int32_t to() const { return (opcode >> 21) & 0x1f; }
2021-01-01 16:46:26 +00:00
/// Register source A or destination.
uint32_t rA() const { return (opcode >> 16) & 0x1f; }
2021-01-01 16:46:26 +00:00
/// Register source B.
uint32_t rB() const { return (opcode >> 11) & 0x1f; }
2021-01-01 16:46:26 +00:00
/// Register destination.
uint32_t rD() const { return (opcode >> 21) & 0x1f; }
2021-01-01 16:46:26 +00:00
/// Register source.
uint32_t rS() const { return (opcode >> 21) & 0x1f; }
2021-01-01 16:46:26 +00:00
/// Floating point register source A.
uint32_t frA() const { return (opcode >> 16) & 0x1f; }
2021-01-01 16:46:26 +00:00
/// Floating point register source B.
uint32_t frB() const { return (opcode >> 11) & 0x1f; }
2021-01-01 16:46:26 +00:00
/// Floating point register source C.
uint32_t frC() const { return (opcode >> 6) & 0x1f; }
2021-01-01 16:46:26 +00:00
/// Floating point register source.
uint32_t frS() const { return (opcode >> 21) & 0x1f; }
2021-01-01 16:46:26 +00:00
/// Floating point register destination.
uint32_t frD() const { return (opcode >> 21) & 0x1f; }
2021-01-01 16:46:26 +00:00
/// Branch conditional options as per PowerPC spec, i.e. options + branch-prediction flag.
uint32_t bo() const { return (opcode >> 21) & 0x1f; }
/// Just the branch options, with the branch prediction flag severed.
2022-03-25 12:41:57 +00:00
BranchOption branch_options() const {
return BranchOption((opcode >> 22) & 0xf);
}
/// Just the branch-prediction hint; @c 0 => expect untaken; @c non-0 => expect take.
uint32_t branch_prediction_hint() const {
return opcode & 0x200000;
}
2021-01-01 16:46:26 +00:00
/// Source condition register bit for branch conditionals.
uint32_t bi() const { return (opcode >> 16) & 0x1f; }
2021-01-01 16:46:26 +00:00
/// Branch displacement; provided as already sign extended.
2021-01-05 03:36:39 +00:00
int16_t bd() const { return int16_t(opcode & 0xfffc); }
2021-01-01 16:46:26 +00:00
/// Specifies the first 1 bit of a 32-bit mask for 32-bit rotate operations.
2022-04-10 13:35:58 +00:00
template <typename IntT = uint32_t> IntT mb() const {
if constexpr (sizeof(IntT) == 4) {
return (opcode >> 6) & 0x1f;
} else {
return (opcode >> 5) & 0x3f;
}
}
2021-01-01 21:38:40 +00:00
/// Specifies the first 1 bit of a 32/64-bit mask for rotate operations.
/// Specify IntT as uint32_t for the 32-bit rotate instructions, uint64_t for the 64-bit.
2022-04-10 13:35:58 +00:00
template <typename IntT = uint32_t> IntT me() const {
if constexpr (sizeof(IntT) == 4) {
return (opcode >> 1) & 0x1f;
} else {
return (opcode >> 5) & 0x3f;
}
}
/// Provides the mask described by 32-bit rotate operations.
2022-04-10 13:31:39 +00:00
///
/// Per IBM's rules:
/// mb < me+1 => set [mb, me]
/// mb == me+1 => set all bits
/// mb > me+1 => complement of set [me+1, mb-1]
template <typename IntT> IntT rotate_mask() const {
2022-04-10 13:35:58 +00:00
const auto mb_bit = mb();
const auto me_bit = me();
2022-04-10 13:31:39 +00:00
const IntT result = (0xffff'ffff >> mb_bit) ^ (0x7fff'ffff >> me_bit);
const IntT sign = ~IntT((int32_t(mb_bit) - int32_t(me_bit+1)) >> 16);
return result ^ sign;
}
2021-01-01 21:38:40 +00:00
2021-01-01 16:46:26 +00:00
/// Condition register source bit A.
2021-01-05 03:36:39 +00:00
uint32_t crbA() const { return (opcode >> 16) & 0x1f; }
2021-01-01 16:46:26 +00:00
/// Condition register source bit B.
2021-01-05 03:36:39 +00:00
uint32_t crbB() const { return (opcode >> 11) & 0x1f; }
2021-01-01 16:46:26 +00:00
/// Condition register (or floating point status & condition register) destination bit.
2021-01-05 03:36:39 +00:00
uint32_t crbD() const { return (opcode >> 21) & 0x1f; }
2021-01-01 16:46:26 +00:00
/// Condition register (or floating point status & condition register) destination field.
2021-01-05 03:36:39 +00:00
uint32_t crfD() const { return (opcode >> 23) & 0x07; }
2021-01-01 16:46:26 +00:00
/// Condition register (or floating point status & condition register) source field.
2021-01-05 03:36:39 +00:00
uint32_t crfS() const { return (opcode >> 18) & 0x07; }
2021-01-01 16:46:26 +00:00
/// Mask identifying fields to be updated by mtcrf.
2021-01-05 03:36:39 +00:00
uint32_t crm() const { return (opcode >> 12) & 0xff; }
2021-01-01 16:46:26 +00:00
/// Mask identifying fields to be updated by mtfsf.
2021-01-05 03:36:39 +00:00
uint32_t fm() const { return (opcode >> 17) & 0xff; }
2021-01-01 16:46:26 +00:00
2021-01-01 21:38:40 +00:00
/// Specifies the number of bytes to move in an immediate string load or store.
2022-04-03 22:29:40 +00:00
uint32_t nb() const {
// Map nb == 0 to 32, branchlessly, given that this is
// a five-bit field.
const uint32_t nb = (opcode >> 11) & 0x1f;
return ((nb - 1) & 31) + 1;
}
2021-01-01 21:38:40 +00:00
/// Specifies a shift amount. Use IntT = uint32_t to get the shift value embedded in
/// 32-bit instructions, uint64_t for 64-bit instructions.
2022-04-10 13:35:58 +00:00
template <typename IntT = uint32_t> uint32_t sh() const {
uint32_t sh = (opcode >> 11) & 0x1f;
if constexpr (sizeof(IntT) == 8) {
sh |= (opcode & 2) << 4;
}
return sh;
}
2021-01-01 21:38:40 +00:00
/// Specifies one of the 16 segment registers [32-bit only].
2021-01-05 03:36:39 +00:00
uint32_t sr() const { return (opcode >> 16) & 0xf; }
2021-01-01 21:38:40 +00:00
2021-01-01 16:46:26 +00:00
/// A 24-bit signed number; provided as already sign extended.
2021-01-05 03:36:39 +00:00
int32_t li() const {
2021-01-01 16:46:26 +00:00
constexpr uint32_t extensions[2] = {
0x0000'0000,
0xfc00'0000
};
2021-01-03 16:14:43 +00:00
const uint32_t value = (opcode & 0x03ff'fffc) | extensions[(opcode >> 25) & 1];
2021-01-01 16:46:26 +00:00
return int32_t(value);
}
/// Absolute address bit; @c 0 or @c non-0.
2021-01-05 03:36:39 +00:00
uint32_t aa() const { return opcode & 0x02; }
2021-01-01 16:46:26 +00:00
/// Link bit; @c 0 or @c non-0.
2021-01-05 03:36:39 +00:00
uint32_t lk() const { return opcode & 0x01; }
2021-01-01 16:46:26 +00:00
/// Record bit; @c 0 or @c non-0.
2021-01-05 03:36:39 +00:00
uint32_t rc() const { return opcode & 0x01; }
2021-01-01 16:46:26 +00:00
/// Whether to compare 32-bit or 64-bit numbers [for 64-bit implementations only]; @c 0 or @c non-0.
2021-01-05 03:36:39 +00:00
uint32_t l() const { return opcode & 0x200000; }
2021-01-01 16:46:26 +00:00
/// Enables setting of OV and SO in the XER; @c 0 or @c non-0.
uint32_t oe() const { return opcode & 0x400; }
2022-04-04 00:33:32 +00:00
/// Identifies a special purpose register.
uint32_t spr() const { return (opcode >> 11) & 0x3ff; }
2022-04-04 00:33:32 +00:00
/// Identifies a time base register.
uint32_t tbr() const { return (opcode >> 11) & 0x3ff; }
2020-12-31 03:55:59 +00:00
};
2021-01-15 23:16:01 +00:00
// Sanity check on Instruction size.
static_assert(sizeof(Instruction) <= 8);
2020-12-31 03:55:59 +00:00
}