use crate::{Instruction, Opcode, Operand, Power, Register, SPR}; use crate::HintStyle; use crate::SyncControl; #[cfg(feature = "fmt")] use crate::display; use yaxpeax_arch::AddressDiff; /// either a hardware-defined [`Opcode`], or a human-friendly [alias][`AliasOp`] defined by a Power /// ISA manual. #[derive(Debug, PartialEq, Eq, Copy, Clone, Hash, PartialOrd, Ord)] pub enum OpcodeAlias { /// the enclosing `InstructionAlias` does not actually refer to an assembler alias, and instead /// is this hardware `Opcode` (and operands). Hardware(Opcode), /// the enclosing `InstructionAlias` is an assembler alias, and the aliased operation is the /// inner item. Alias(AliasOp), } impl OpcodeAlias { /// is this opcode (or alias) a branch instruction? /// /// this is functionally equivalent to [`Opcode::is_branch()`] pub fn is_branch(&self) -> bool { match self { OpcodeAlias::Hardware(op) => { op.is_branch() } OpcodeAlias::Alias(_) => { // no branch aliases (yet?) false } } } } #[allow(non_camel_case_types)] #[non_exhaustive] #[allow(missing_docs)] #[derive(Debug, PartialEq, Eq, Copy, Clone, Hash, PartialOrd, Ord)] pub enum AliasOp { HWSYNC = 0x1000, LWSYNC, PTESYNC, TRAP, TWLE, TWGE, TWLT, TWGT, TWNE, TWEQ, TWLGE, TWLLE, TWLGT, TWLLT, TDLT, TDGT, TDNE, TDEQ, TDLGE, TDLLE, MR, NOP, NOT, LI, LIS, SUBI, SUBIS, CRCLR, CRSET, CRNOT, CRMOVE, MTXER, MTLR, MTCTR, MFXER, MFLR, MFCTR, MTCR, MTMSR, MTMSRD, MTMSRD_Xenon, MTMSREE, MTFSF, SRDI, CLRLDI, SLDI, CLRRDI, CLRRWI, CLRLWI, ROTLWI, SLWI, SRWI, EXTLWI, CMPLDI, CMPLWI, CMPDI, CMPWI, CMPD, CMPW, TDGEI, TDLEI, TDGTI, TDLTI, TDLGTI, TDLLTI, TDLGEI, TDLLEI, TDEQI, TDNEI, TWGTI, TWLTI, TWGEI, TWLEI, TWLGTI, TWLLTI, TWLGEI, TWLLEI, TWEQI, TWNEI, CMPLD, CMPLW, ROTLW, INSLWI, DCBF, DCBFL, DCBFLP, DCBTCT, DCBTDS, DCBTT, DCBTSTCT, DCBTSTDS, DCBTSTT, TSUSPEND, TRESUME, TEND, TENDALL, } /// a Power ISA instruction, as described by the manual's assembler aliasing rules. /// /// this corresponds to some unique [`Instruction`], and can be converted back to one with /// [`InstructionAlias::dealias`]. #[derive(Debug)] pub struct InstructionAlias { opcode: OpcodeAlias, pub(crate) operands: [Option; 5], rc: bool, aa: bool, lk: bool, oe: bool, hint_style: Option, pub(crate) len: u64, } impl InstructionAlias { fn init_from(inst: &Instruction) -> Self { Self { opcode: OpcodeAlias::Hardware(inst.opcode), operands: inst.operands.clone(), rc: inst.rc, aa: inst.aa, lk: inst.lk, oe: inst.oe, hint_style: inst.hint_style, len: inst.len, } } /// get the [`OpcodeAlias`] for this instruction. pub fn opcode(&self) -> OpcodeAlias { self.opcode } /// get the `idx`'th operand for this instruction. /// /// returns `None` if there is no operand at the requested index. pub fn operand(&self, idx: u8) -> Option<&Operand> { if let Some(op) = self.operands.get(idx as usize) { op.as_ref() } else { None } } /// get the number of operands for this instruction. /// /// `Instruction::operand` returns `Some` for any `idx` below the returned count, and `None` /// otherwise.. pub fn operand_count(&self) -> usize { let mut count = 0; for op in self.operands.iter() { if op.is_some() { count += 1; } else { break; } } count } /// get the instruction's RECORD (`Rc`) bit. /// /// the RECORD bit indicates if the condition register should be updated as part of executing /// this instruction. it is indicated as a trailing `.` after instruction mnemonics in textual /// form. pub fn rc(&self) -> bool { self.rc } /// get the instruction's Absolute Address (`AA`) bit. /// /// the Absolute Address bit indicates if a branch uses a relative or absolute addressing mode. /// this is unlikely to be useful; it is redundant with both the `BranchAbs`/`BranchOffset` /// operand forms and `BA`/`BCA`/`BLA`/`BCLA` where `AA` already resulted in an opcode with /// trailing `A` meaning this same thing. /// /// for non-branches this is not meaningful and always `false`. pub fn aa(&self) -> bool { self.aa } /// get the instruction's LINK (`Lk`) bit. /// /// the LINK bit indicates if a branch sets the Link Register (`lr`) with the address of the /// instruction after the branch as part of execution. like `aa()` above, this is redundant /// with opcodes which include the "set link" implication: `BL`, `BCL`, `BLA`, `BCLA`. /// /// for non-branches this is not meaningful and always `false`. pub fn lk(&self) -> bool { self.lk } /// get the instruction's OE bit. /// /// the OE bit indicates if this instruction sets the OV and SO bits in XER as part of /// execution. this is also indicated with a trailing `o` after the instruction mnemonic but /// before an optional `.` in textual form. /// /// this is only relevant for XO-form instructions, mostly arithmetic. pub fn oe(&self) -> bool { self.oe } /// get the instruction's branch prediction hint /// /// across the various POWER family implementations, the `BO` field of branches have been made /// home to taken/not-taken static branch prediction hints. the *interpretation* of this field, /// had a substantial change in the PowerPC-before-v2.0 and Power ISA v2.0-and-later. /// /// if this field is none, either this instruction is not a conditional branch, or it was /// decoded as if by POWER or POWER2, where `BO` never encoded taken/not-taken hints. pub fn hint_style(&self) -> Option { self.hint_style } /// accumulate this instruction with a `DisplayRules` to get a tuple out which is suitable for /// `DisplaySink` or any general `format!()` use. #[cfg(feature = "fmt")] pub fn display_rules<'a, 'rules, Rules>( &'a self, rules: &'rules Rules, ) -> display::InstructionAliasRuleBundle<'a, 'rules, Rules> { display::InstructionAliasRuleBundle { instr: self, rules, } } } impl yaxpeax_arch::LengthedInstruction for InstructionAlias { type Unit = AddressDiff<::Address>; #[inline] fn len(&self) -> Self::Unit { AddressDiff::from_const(self.len) } #[inline] fn min_size() -> Self::Unit { AddressDiff::from_const(2) } } impl yaxpeax_arch::InstructionAlias for InstructionAlias { fn compute_alias(t: &Instruction) -> Self { let mut alias = InstructionAlias::init_from(t); match t.opcode { Opcode::SYNC => { // implementations before 2.03 just had a blanket `sync`, but later forms add more // granular sync controls. before then, there simply was not a reported operand. if let Some(ll) = alias.operands[0].take() { match ll.as_ll_unwrap() { // TODO: alsp shown as `msync`? as in v2.03 at least. SyncControl::Default => { alias.opcode = OpcodeAlias::Alias(AliasOp::HWSYNC); } SyncControl::LW => { alias.opcode = OpcodeAlias::Alias(AliasOp::LWSYNC); } SyncControl::PTE => { alias.opcode = OpcodeAlias::Alias(AliasOp::PTESYNC); } SyncControl::Reserved => { /* reserved! retain sync with this control bit */ alias.operands[0] = Some(Operand::LL(SyncControl::Reserved)); } } } } Opcode::TW => { let to = alias.operands[0].as_ref().unwrap().as_imm8_unwrap() as usize; let ra = alias.operands[1].as_ref().unwrap().as_reg_unwrap(); let rb = alias.operands[2].as_ref().unwrap().as_reg_unwrap(); if to == 31 && ra.reg == 0 && rb.reg == 0 { alias.opcode = OpcodeAlias::Alias(AliasOp::TRAP); alias.operands = [None; 5]; return alias; } static CONDITIONS: [Option; 32] = [ None, Some(OpcodeAlias::Alias(AliasOp::TWLGT)),Some(OpcodeAlias::Alias(AliasOp::TWLLT)), None, Some(OpcodeAlias::Alias(AliasOp::TWEQ)),Some(OpcodeAlias::Alias(AliasOp::TWLGE)),Some(OpcodeAlias::Alias(AliasOp::TWLLE)), None, Some(OpcodeAlias::Alias(AliasOp::TWGT)), None, None, None, Some(OpcodeAlias::Alias(AliasOp::TWGE)), None, None, None, Some(OpcodeAlias::Alias(AliasOp::TWLT)), None, None, None, Some(OpcodeAlias::Alias(AliasOp::TWLE)), None, None, None, Some(OpcodeAlias::Alias(AliasOp::TWNE)), None, None, None, None, None, None, None, ]; let to = alias.operands[0].as_ref().unwrap().as_imm8_unwrap(); if let Some(alias_op) = CONDITIONS[to as usize] { alias.opcode = alias_op; alias.operands[0] = alias.operands[1]; alias.operands[1] = alias.operands[2]; alias.operands[2] = None; } } Opcode::TDI => { static CONDITIONS: [Option; 32] = [ None, Some(OpcodeAlias::Alias(AliasOp::TDLGTI)),Some(OpcodeAlias::Alias(AliasOp::TDLLTI)), None, Some(OpcodeAlias::Alias(AliasOp::TDEQI)),Some(OpcodeAlias::Alias(AliasOp::TDLGEI)),Some(OpcodeAlias::Alias(AliasOp::TDLLEI)), None, Some(OpcodeAlias::Alias(AliasOp::TDGTI)), None, None, None, Some(OpcodeAlias::Alias(AliasOp::TDGEI)), None, None, None, Some(OpcodeAlias::Alias(AliasOp::TDLTI)), None, None, None, Some(OpcodeAlias::Alias(AliasOp::TDLEI)), None, None, None, Some(OpcodeAlias::Alias(AliasOp::TDNEI)), None, None, None, None, None, None, None, ]; let to = alias.operands[0].as_ref().unwrap().as_imm8_unwrap(); if let Some(alias_op) = CONDITIONS[to as usize] { alias.opcode = alias_op; alias.operands[0] = alias.operands[1]; alias.operands[1] = alias.operands[2]; alias.operands[2] = None; } } Opcode::TWI => { static CONDITIONS: [Option; 32] = [ None, Some(OpcodeAlias::Alias(AliasOp::TWLGTI)),Some(OpcodeAlias::Alias(AliasOp::TWLLTI)), None, Some(OpcodeAlias::Alias(AliasOp::TWEQI)),Some(OpcodeAlias::Alias(AliasOp::TWLGEI)),Some(OpcodeAlias::Alias(AliasOp::TWLLEI)), None, Some(OpcodeAlias::Alias(AliasOp::TWGTI)), None, None, None, Some(OpcodeAlias::Alias(AliasOp::TWGEI)), None, None, None, Some(OpcodeAlias::Alias(AliasOp::TWLTI)), None, None, None, Some(OpcodeAlias::Alias(AliasOp::TWLEI)), None, None, None, Some(OpcodeAlias::Alias(AliasOp::TWNEI)), None, None, None, None, None, None, None, ]; let to = alias.operands[0].as_ref().unwrap().as_imm8_unwrap(); if let Some(alias_op) = CONDITIONS[to as usize] { alias.opcode = alias_op; alias.operands[0] = alias.operands[1]; alias.operands[1] = alias.operands[2]; alias.operands[2] = None; } } Opcode::OR => { let rs = alias.operands[1].as_ref().unwrap().as_reg_unwrap(); let rb = alias.operands[2].as_ref().unwrap().as_reg_unwrap(); if rs.reg == rb.reg { alias.opcode = OpcodeAlias::Alias(AliasOp::MR); alias.operands[1] = alias.operands[2]; alias.operands[2] = None; } } Opcode::NOR => { let rs = alias.operands[1].as_ref().unwrap().as_reg_unwrap(); let rb = alias.operands[2].as_ref().unwrap().as_reg_unwrap(); if rs.reg == rb.reg { alias.opcode = OpcodeAlias::Alias(AliasOp::NOT); alias.operands[1] = alias.operands[2]; alias.operands[2] = None; } } Opcode::ORI => { let rt = alias.operands[0].as_ref().unwrap().as_reg_unwrap().reg; let ra = alias.operands[1].as_ref().unwrap().as_reg_unwrap().reg; let si = alias.operands[2].as_ref().unwrap().as_imm16_unwrap(); if rt == ra && rt == 0 && si == 0 { alias.opcode = OpcodeAlias::Alias(AliasOp::NOP); alias.operands = [None; 5]; } } Opcode::ADDI => { if let Some(Register { reg: 0 }) = alias.operands[1].as_ref().unwrap().as_reg_or_zero() { alias.opcode = OpcodeAlias::Alias(AliasOp::LI); alias.operands[1] = alias.operands[2]; alias.operands[2] = None; } else if let Some(imm) = alias.operands[2].as_ref().unwrap().as_signed_imm() { if imm < 0 { alias.opcode = OpcodeAlias::Alias(AliasOp::SUBI); alias.operands[2] = Some(Operand::ImmU32(-(imm as i32) as u32)); } } } Opcode::ADDIS => { if let Some(Register { reg: 0 }) = alias.operands[1].as_ref().unwrap().as_reg_or_zero() { alias.opcode = OpcodeAlias::Alias(AliasOp::LIS); alias.operands[1] = alias.operands[2]; alias.operands[2] = None; } else if let Some(imm) = alias.operands[2].as_ref().unwrap().as_signed_imm() { if imm < 0 { alias.opcode = OpcodeAlias::Alias(AliasOp::SUBIS); alias.operands[2] = Some(Operand::ImmU32(-(imm as i32) as u32)); } } } Opcode::CRNOR => { if alias.operands[1] == alias.operands[2] { alias.opcode = OpcodeAlias::Alias(AliasOp::CRNOT); alias.operands[2] = None; } } Opcode::CROR => { if alias.operands[1] == alias.operands[2] { alias.opcode = OpcodeAlias::Alias(AliasOp::CRMOVE); alias.operands[2] = None; } } Opcode::CRXOR => { if alias.operands[0] == alias.operands[1] && alias.operands[1] == alias.operands[2] { alias.opcode = OpcodeAlias::Alias(AliasOp::CRCLR); alias.operands[2] = None; alias.operands[1] = None; } } Opcode::CREQV => { if alias.operands[0] == alias.operands[1] && alias.operands[1] == alias.operands[2] { alias.opcode = OpcodeAlias::Alias(AliasOp::CRSET); alias.operands[2] = None; alias.operands[1] = None; } } Opcode::MTSPR => { let SPR { reg: spr } = alias.operands[0].as_ref().unwrap().as_spr_unwrap(); let mut aliased = false; match spr { 1 => { alias.opcode = OpcodeAlias::Alias(AliasOp::MTXER); aliased = true; }, 8 => { alias.opcode = OpcodeAlias::Alias(AliasOp::MTLR); aliased = true; }, 9 => { alias.opcode = OpcodeAlias::Alias(AliasOp::MTCTR); aliased = true; }, _ => { /* not an aliasing SPR */ }, } if aliased { alias.operands[0] = alias.operands[1]; alias.operands[1] = None; } } Opcode::MFSPR => { let SPR { reg: spr } = alias.operands[1].as_ref().unwrap().as_spr_unwrap(); let mut aliased = false; match spr { 1 => { alias.opcode = OpcodeAlias::Alias(AliasOp::MFXER); aliased = true; }, 8 => { alias.opcode = OpcodeAlias::Alias(AliasOp::MFLR); aliased = true; }, 9 => { alias.opcode = OpcodeAlias::Alias(AliasOp::MFCTR); aliased = true; }, _ => { /* not an aliasing SPR */ }, } if aliased { alias.operands[1] = None; } } Opcode::MTCRF => { let imm = alias.operands[0].as_ref().unwrap().as_cr_mask_unwrap(); if imm == 0xff { alias.opcode = OpcodeAlias::Alias(AliasOp::MTCR); alias.operands[0] = alias.operands[1]; alias.operands[1] = None; } } Opcode::MTMSR => { let imm = alias.operands[1].as_ref().map(|op| op.as_imm8_unwrap()); match imm { Some(0) => { // an immediate of 0 just removes the operand, leaving the opcode // unchanged. alias.opcode = OpcodeAlias::Alias(AliasOp::MTMSR); alias.operands[1] = None; } _ => {} } } Opcode::MTMSRD => { let imm = alias.operands[1].as_ref().map(|op| op.as_imm8_unwrap()); match imm { Some(0) => { // an immediate of 0 just removes the operand, leaving the opcode // unchanged. alias.opcode = OpcodeAlias::Alias(AliasOp::MTMSRD); alias.operands[1] = None; } _ => {} } } Opcode::MTMSRD_Xenon => { let imm = alias.operands[1].as_ref().map(|op| op.as_imm8_unwrap()); match imm { Some(0) => { // an immediate of 0 just removes the operand, leaving the opcode // unchanged. // // this has the somewhat-absurd MTMSRD_Xenon form rather than MTMSRD so // that it isn't incorrectly "dealiased" to the other non-Xenon MTMSRD. alias.opcode = OpcodeAlias::Alias(AliasOp::MTMSRD_Xenon); alias.operands[1] = None; } Some(1) => { // allegedly on Xenon specifically, `mtmsrd` with `L=1` is `mtmsree`. in v2.02 this // is documented as bits 48 and 62, which are (via 2.2.3 Machine State Register) // bits EE (external interrupt enable) and RI (recoverable interrupt). // Xenia does not decode this, but objdump does. alias.opcode = OpcodeAlias::Alias(AliasOp::MTMSREE); alias.operands[1] = None; } _ => {} } } Opcode::MTFSF => { if alias.operands[3].is_some() { let l = alias.operands[2].as_ref().unwrap().as_imm8_unwrap(); let w = alias.operands[3].as_ref().unwrap().as_imm8_unwrap(); if l == 0 && w == 0 { alias.opcode = OpcodeAlias::Alias(AliasOp::MTFSF); alias.operands[3] = None; alias.operands[2] = None; } else if w == 0 { alias.opcode = OpcodeAlias::Alias(AliasOp::MTFSF); alias.operands[3] = None; } } } Opcode::RLDICL => { let sh = alias.operands[2].as_ref().unwrap().as_imm8_unwrap(); let me = alias.operands[3].as_ref().unwrap().as_imm8_unwrap(); if sh + me == 64 { alias.opcode = OpcodeAlias::Alias(AliasOp::SRDI); alias.operands[3] = None; alias.operands[2] = None; alias.operands[2] = Some(Operand::Imm8(64 - sh)); } else if sh == 0 { alias.opcode = OpcodeAlias::Alias(AliasOp::CLRLDI); alias.operands[3] = None; alias.operands[2] = None; alias.operands[2] = Some(Operand::Imm8(me)); } } Opcode::RLDICR => { let sh = alias.operands[2].as_ref().unwrap().as_imm8_unwrap(); let me = alias.operands[3].as_ref().unwrap().as_imm8_unwrap(); if sh + me == 63 { alias.opcode = OpcodeAlias::Alias(AliasOp::SLDI); alias.operands[3] = None; alias.operands[2] = None; alias.operands[2] = Some(Operand::Imm8(sh)); } else if sh == 0 { alias.opcode = OpcodeAlias::Alias(AliasOp::CLRRDI); alias.operands[3] = None; alias.operands[2] = None; alias.operands[2] = Some(Operand::Imm8(63 - me)); } } Opcode::CMPLI => { let long = alias.operands[1].as_ref().unwrap().as_imm8_unwrap() != 0; if long { alias.opcode = OpcodeAlias::Alias(AliasOp::CMPLDI); } else { alias.opcode = OpcodeAlias::Alias(AliasOp::CMPLWI); } alias.operands[1] = alias.operands[2]; alias.operands[2] = alias.operands[3]; alias.operands[3] = None; if alias.operands[0] == Some(Operand::CrField(0)) { alias.operands[0] = alias.operands[1]; alias.operands[1] = alias.operands[2]; alias.operands[2] = None; } } Opcode::CMPI => { let long = alias.operands[1].as_ref().unwrap().as_imm8_unwrap() != 0; if long { alias.opcode = OpcodeAlias::Alias(AliasOp::CMPDI); } else { alias.opcode = OpcodeAlias::Alias(AliasOp::CMPWI); } alias.operands[1] = alias.operands[2]; alias.operands[2] = alias.operands[3]; alias.operands[3] = None; if alias.operands[0] == Some(Operand::CrField(0)) { alias.operands[0] = alias.operands[1]; alias.operands[1] = alias.operands[2]; alias.operands[2] = None; } } Opcode::CMPL => { let long = alias.operands[1].as_ref().unwrap().as_imm8_unwrap() != 0; if long { alias.opcode = OpcodeAlias::Alias(AliasOp::CMPLD); } else { alias.opcode = OpcodeAlias::Alias(AliasOp::CMPLW); } alias.operands[1] = alias.operands[2]; alias.operands[2] = alias.operands[3]; alias.operands[3] = None; if alias.operands[0] == Some(Operand::CrField(0)) { alias.operands[0] = alias.operands[1]; alias.operands[1] = alias.operands[2]; alias.operands[2] = None; } } Opcode::CMP => { let long = alias.operands[1].as_ref().unwrap().as_imm8_unwrap() != 0; if long { alias.opcode = OpcodeAlias::Alias(AliasOp::CMPD); } else { alias.opcode = OpcodeAlias::Alias(AliasOp::CMPW); } alias.operands[1] = alias.operands[2]; alias.operands[2] = alias.operands[3]; alias.operands[3] = None; if alias.operands[0] == Some(Operand::CrField(0)) { alias.operands[0] = alias.operands[1]; alias.operands[1] = alias.operands[2]; alias.operands[2] = None; } } Opcode::RLWNM => { let mb = alias.operands[3].as_ref().unwrap().as_imm8_unwrap(); let me = alias.operands[4].as_ref().unwrap().as_imm8_unwrap(); if mb == 0 && me == 31 { alias.opcode = OpcodeAlias::Alias(AliasOp::ROTLW); alias.operands[3] = None; alias.operands[4] = None; } } Opcode::RLWIMI => { let sh = alias.operands[2].as_ref().unwrap().as_imm8_unwrap(); let mb = alias.operands[3].as_ref().unwrap().as_imm8_unwrap(); let me = alias.operands[4].as_ref().unwrap().as_imm8_unwrap(); let n = sh; let b = mb; if sh + mb == 32 && me != 31 && me == b.wrapping_add(n).wrapping_sub(1) { alias.opcode = OpcodeAlias::Alias(AliasOp::INSLWI); alias.operands[2] = None; alias.operands[3] = None; alias.operands[4] = None; alias.operands[2] = Some(Operand::Imm8(n)); alias.operands[3] = Some(Operand::Imm8(b)); } } Opcode::RLWINM => { let sh = alias.operands[2].as_ref().unwrap().as_imm8_unwrap(); let mb = alias.operands[3].as_ref().unwrap().as_imm8_unwrap(); let me = alias.operands[4].as_ref().unwrap().as_imm8_unwrap(); if sh == 0 && mb == 0 && me != 31 { let n = 31 - me; alias.opcode = OpcodeAlias::Alias(AliasOp::CLRRWI); alias.operands[2] = None; alias.operands[3] = None; alias.operands[4] = None; alias.operands[2] = Some(Operand::Imm8(n)); } else if sh == 0 && me == 31 && mb != 0 { let n = mb; alias.opcode = OpcodeAlias::Alias(AliasOp::CLRLWI); alias.operands[2] = None; alias.operands[3] = None; alias.operands[4] = None; alias.operands[2] = Some(Operand::Imm8(n)); } else if mb == 0 && me == 31 && sh != 0 { let n = sh; alias.opcode = OpcodeAlias::Alias(AliasOp::ROTLWI); alias.operands[2] = None; alias.operands[3] = None; alias.operands[4] = None; alias.operands[2] = Some(Operand::Imm8(n)); } else if sh + me == 31 && mb == 0 { let n = sh; alias.opcode = OpcodeAlias::Alias(AliasOp::SLWI); alias.operands[2] = None; alias.operands[3] = None; alias.operands[4] = None; alias.operands[2] = Some(Operand::Imm8(n)); } else if sh + mb == 32 && me == 31 { let n = mb; alias.opcode = OpcodeAlias::Alias(AliasOp::SRWI); alias.operands[2] = None; alias.operands[3] = None; alias.operands[4] = None; alias.operands[2] = Some(Operand::Imm8(n)); } else if mb == 0 && me != 31 { let b = sh; let n = me + 1; alias.opcode = OpcodeAlias::Alias(AliasOp::EXTLWI); alias.operands[2] = None; alias.operands[3] = None; alias.operands[4] = None; alias.operands[2] = Some(Operand::Imm8(n)); alias.operands[3] = Some(Operand::Imm8(b)); } } Opcode::DCBF => { if let Some(l) = alias.operands[1].as_ref().map(|op| op.as_imm8_unwrap()) { match l { 0 => { alias.opcode = OpcodeAlias::Alias(AliasOp::DCBF); alias.operands[1] = None; } 1 => { alias.opcode = OpcodeAlias::Alias(AliasOp::DCBFL); alias.operands[1] = None; } 3 => { alias.opcode = OpcodeAlias::Alias(AliasOp::DCBFLP); alias.operands[1] = None; } _ => {} } } } Opcode::DCBT => { if let Some(l) = alias.operands[1].as_ref().map(|op| op.as_imm8_unwrap()) { if l < 0b01000 { alias.opcode = OpcodeAlias::Alias(AliasOp::DCBTCT); } else if l < 0b10000 { alias.opcode = OpcodeAlias::Alias(AliasOp::DCBTDS); } else if l == 0b10000 { alias.opcode = OpcodeAlias::Alias(AliasOp::DCBTT); // unlike the above, the alias implies a specific `TH`, so the manual // discards the field for this case. alias.operands[1] = None; } } } Opcode::DCBTST => { if let Some(l) = alias.operands[1].as_ref().map(|op| op.as_imm8_unwrap()) { if l < 0b01000 { alias.opcode = OpcodeAlias::Alias(AliasOp::DCBTSTCT); } else if l < 0b10000 { alias.opcode = OpcodeAlias::Alias(AliasOp::DCBTSTDS); } else if l == 0b10000 { alias.opcode = OpcodeAlias::Alias(AliasOp::DCBTSTT); alias.operands[1] = None; } } } Opcode::TSR => { let l = alias.operands[0].unwrap().as_imm8_unwrap(); if l == 0 { alias.opcode = OpcodeAlias::Alias(AliasOp::TSUSPEND); alias.operands[0] = None; } else if l == 1 { alias.opcode = OpcodeAlias::Alias(AliasOp::TRESUME); alias.operands[0] = None; } } Opcode::TEND => { let a = alias.operands[0].unwrap().as_imm8_unwrap(); if a == 0 { alias.opcode = OpcodeAlias::Alias(AliasOp::TEND); alias.operands[0] = None; } else if a == 1 { alias.opcode = OpcodeAlias::Alias(AliasOp::TENDALL); alias.operands[0] = None; } } _ => { // for everything else, do the normal stuff } } alias } fn dealias(&self) -> Instruction { let mut dealias = Instruction::init_from(self); match self.opcode { OpcodeAlias::Hardware(op) => { // the alias was not actually any different, just put the opcode back and we're // done. dealias.opcode = op; } OpcodeAlias::Alias(AliasOp::TEND) => { dealias.opcode = Opcode::TEND; dealias.operands[0] = Some(Operand::Imm8(0)); } OpcodeAlias::Alias(AliasOp::TENDALL) => { dealias.opcode = Opcode::TEND; dealias.operands[0] = Some(Operand::Imm8(1)); } OpcodeAlias::Alias(AliasOp::TSUSPEND) => { dealias.opcode = Opcode::TSR; dealias.operands[0] = Some(Operand::Imm8(0)); } OpcodeAlias::Alias(AliasOp::TRESUME) => { dealias.opcode = Opcode::TSR; dealias.operands[0] = Some(Operand::Imm8(1)); } OpcodeAlias::Alias(AliasOp::DCBTSTCT) => { dealias.opcode = Opcode::DCBTST; } OpcodeAlias::Alias(AliasOp::DCBTSTDS) => { dealias.opcode = Opcode::DCBTST; } OpcodeAlias::Alias(AliasOp::DCBTSTT) => { dealias.opcode = Opcode::DCBTST; dealias.operands[1] = Some(Operand::Imm8(0b10000)); } OpcodeAlias::Alias(AliasOp::DCBTCT) => { dealias.opcode = Opcode::DCBT; } OpcodeAlias::Alias(AliasOp::DCBTDS) => { dealias.opcode = Opcode::DCBT; } OpcodeAlias::Alias(AliasOp::DCBTT) => { dealias.opcode = Opcode::DCBT; dealias.operands[1] = Some(Operand::Imm8(0b10000)); } OpcodeAlias::Alias(AliasOp::DCBF) => { dealias.opcode = Opcode::DCBF; dealias.operands[1] = Some(Operand::Imm8(0)); } OpcodeAlias::Alias(AliasOp::DCBFL) => { dealias.opcode = Opcode::DCBF; dealias.operands[1] = Some(Operand::Imm8(1)); } OpcodeAlias::Alias(AliasOp::DCBFLP) => { dealias.opcode = Opcode::DCBF; dealias.operands[1] = Some(Operand::Imm8(3)); } OpcodeAlias::Alias(AliasOp::CLRRWI) => { dealias.opcode = Opcode::RLWINM; let n = dealias.operands[2].as_ref().unwrap().as_imm8_unwrap(); let me = 31 - n; dealias.operands[2] = Some(Operand::Imm8(0)); dealias.operands[3] = Some(Operand::Imm8(0)); dealias.operands[4] = Some(Operand::Imm8(me)); } OpcodeAlias::Alias(AliasOp::CLRLWI) => { dealias.opcode = Opcode::RLWINM; dealias.operands[3] = dealias.operands[2]; dealias.operands[2] = Some(Operand::Imm8(0)); dealias.operands[4] = Some(Operand::Imm8(31)); } OpcodeAlias::Alias(AliasOp::ROTLWI) => { dealias.opcode = Opcode::RLWINM; dealias.operands[3] = Some(Operand::Imm8(0)); dealias.operands[4] = Some(Operand::Imm8(31)); } OpcodeAlias::Alias(AliasOp::SLWI) => { dealias.opcode = Opcode::RLWINM; let sh = dealias.operands[2].as_ref().unwrap().as_imm8_unwrap(); dealias.operands[3] = Some(Operand::Imm8(0)); dealias.operands[4] = Some(Operand::Imm8(31 - sh)); } OpcodeAlias::Alias(AliasOp::SRWI) => { dealias.opcode = Opcode::RLWINM; let sh = dealias.operands[2].as_ref().unwrap().as_imm8_unwrap(); dealias.operands[3] = dealias.operands[2]; dealias.operands[2] = Some(Operand::Imm8(32 - sh)); dealias.operands[4] = Some(Operand::Imm8(31)); } OpcodeAlias::Alias(AliasOp::EXTLWI) => { dealias.opcode = Opcode::RLWINM; let n = dealias.operands[2].as_ref().unwrap().as_imm8_unwrap(); let b = dealias.operands[3].as_ref().unwrap().as_imm8_unwrap(); let me = n - 1; let mb = 0; let sh = b; dealias.operands[2] = Some(Operand::Imm8(sh)); dealias.operands[3] = Some(Operand::Imm8(mb)); dealias.operands[4] = Some(Operand::Imm8(me)); } OpcodeAlias::Alias(AliasOp::INSLWI) => { dealias.opcode = Opcode::RLWIMI; let n = dealias.operands[2].as_ref().unwrap().as_imm8_unwrap(); let b = dealias.operands[3].as_ref().unwrap().as_imm8_unwrap(); let me = b.wrapping_add(n).wrapping_sub(1); dealias.operands[4] = Some(Operand::Imm8(me)); } OpcodeAlias::Alias(AliasOp::ROTLW) => { dealias.opcode = Opcode::RLWNM; dealias.operands[3] = Some(Operand::Imm8(0)); dealias.operands[4] = Some(Operand::Imm8(31)); } OpcodeAlias::Alias(AliasOp::CMPD) => { dealias.opcode = Opcode::CMP; if dealias.operands[2].is_none() { dealias.operands[2] = dealias.operands[1].clone(); dealias.operands[1] = dealias.operands[0].clone(); dealias.operands[0] = Some(Operand::CrField(0)); } dealias.operands[3] = dealias.operands[2].clone(); dealias.operands[2] = dealias.operands[1].clone(); dealias.operands[1] = Some(Operand::Imm8(1)); } OpcodeAlias::Alias(AliasOp::CMPW) => { dealias.opcode = Opcode::CMP; if dealias.operands[2].is_none() { dealias.operands[2] = dealias.operands[1].clone(); dealias.operands[1] = dealias.operands[0].clone(); dealias.operands[0] = Some(Operand::CrField(0)); } dealias.operands[3] = dealias.operands[2].clone(); dealias.operands[2] = dealias.operands[1].clone(); dealias.operands[1] = Some(Operand::Imm8(0)); } OpcodeAlias::Alias(AliasOp::CMPLD) => { dealias.opcode = Opcode::CMPL; if dealias.operands[2].is_none() { dealias.operands[2] = dealias.operands[1].clone(); dealias.operands[1] = dealias.operands[0].clone(); dealias.operands[0] = Some(Operand::CrField(0)); } dealias.operands[3] = dealias.operands[2].clone(); dealias.operands[2] = dealias.operands[1].clone(); dealias.operands[1] = Some(Operand::Imm8(1)); } OpcodeAlias::Alias(AliasOp::CMPLW) => { dealias.opcode = Opcode::CMPL; if dealias.operands[2].is_none() { dealias.operands[2] = dealias.operands[1].clone(); dealias.operands[1] = dealias.operands[0].clone(); dealias.operands[0] = Some(Operand::CrField(0)); } dealias.operands[3] = dealias.operands[2].clone(); dealias.operands[2] = dealias.operands[1].clone(); dealias.operands[1] = Some(Operand::Imm8(0)); } OpcodeAlias::Alias(AliasOp::CMPDI) => { dealias.opcode = Opcode::CMPI; if dealias.operands[2].is_none() { dealias.operands[2] = dealias.operands[1].clone(); dealias.operands[1] = dealias.operands[0].clone(); dealias.operands[0] = Some(Operand::CrField(0)); } dealias.operands[3] = dealias.operands[2].clone(); dealias.operands[2] = dealias.operands[1].clone(); dealias.operands[1] = Some(Operand::Imm8(1)); } OpcodeAlias::Alias(AliasOp::CMPWI) => { dealias.opcode = Opcode::CMPI; if dealias.operands[2].is_none() { dealias.operands[2] = dealias.operands[1].clone(); dealias.operands[1] = dealias.operands[0].clone(); dealias.operands[0] = Some(Operand::CrField(0)); } dealias.operands[3] = dealias.operands[2].clone(); dealias.operands[2] = dealias.operands[1].clone(); dealias.operands[1] = Some(Operand::Imm8(0)); } OpcodeAlias::Alias(AliasOp::CMPLDI) => { dealias.opcode = Opcode::CMPLI; if dealias.operands[2].is_none() { dealias.operands[2] = dealias.operands[1].clone(); dealias.operands[1] = dealias.operands[0].clone(); dealias.operands[0] = Some(Operand::CrField(0)); } dealias.operands[3] = dealias.operands[2].clone(); dealias.operands[2] = dealias.operands[1].clone(); dealias.operands[1] = Some(Operand::Imm8(1)); } OpcodeAlias::Alias(AliasOp::CMPLWI) => { dealias.opcode = Opcode::CMPLI; if dealias.operands[2].is_none() { dealias.operands[2] = dealias.operands[1].clone(); dealias.operands[1] = dealias.operands[0].clone(); dealias.operands[0] = Some(Operand::CrField(0)); } dealias.operands[3] = dealias.operands[2].clone(); dealias.operands[2] = dealias.operands[1].clone(); dealias.operands[1] = Some(Operand::Imm8(0)); } OpcodeAlias::Alias(AliasOp::CLRRDI) => { dealias.opcode = Opcode::RLDICR; let op2 = dealias.operands[2].as_ref().unwrap().as_imm8_unwrap(); let me = 63 - op2; dealias.operands[2] = Some(Operand::Imm8(0)); dealias.operands[3] = Some(Operand::Imm8(me)); } OpcodeAlias::Alias(AliasOp::SLDI) => { dealias.opcode = Opcode::RLDICR; let sh = dealias.operands[2].as_ref().unwrap().as_imm8_unwrap(); let me = 63 - sh; dealias.operands[2] = Some(Operand::Imm8(sh)); dealias.operands[3] = Some(Operand::Imm8(me)); } OpcodeAlias::Alias(AliasOp::CLRLDI) => { dealias.opcode = Opcode::RLDICL; let op2 = dealias.operands[2].as_ref().unwrap().as_imm8_unwrap(); dealias.operands[2] = Some(Operand::Imm8(0)); dealias.operands[3] = Some(Operand::Imm8(op2)); } OpcodeAlias::Alias(AliasOp::SRDI) => { dealias.opcode = Opcode::RLDICL; let me = dealias.operands[2].as_ref().unwrap().as_imm8_unwrap(); let sh = 64 - me; dealias.operands[2] = Some(Operand::Imm8(sh)); dealias.operands[3] = Some(Operand::Imm8(me)); } OpcodeAlias::Alias(AliasOp::MTFSF) => { dealias.opcode = Opcode::MTFSF; // by being an AliasOp there's *some* dealiasing to do, just.. how much? if dealias.operands[2].is_none() { dealias.operands[2] = Some(Operand::Imm8(0)); dealias.operands[3] = Some(Operand::Imm8(0)); } else { dealias.operands[3] = Some(Operand::Imm8(0)); } } OpcodeAlias::Alias(AliasOp::MTMSREE) => { dealias.opcode = Opcode::MTMSRD_Xenon; dealias.operands[1] = Some(Operand::Imm8(1)); } OpcodeAlias::Alias(AliasOp::MTMSRD_Xenon) => { dealias.opcode = Opcode::MTMSRD_Xenon; dealias.operands[1] = Some(Operand::Imm8(0)); } OpcodeAlias::Alias(AliasOp::MTMSRD) => { dealias.opcode = Opcode::MTMSRD; dealias.operands[1] = Some(Operand::Imm8(0)); } OpcodeAlias::Alias(AliasOp::MTMSR) => { dealias.opcode = Opcode::MTMSR; dealias.operands[1] = Some(Operand::Imm8(0)); } OpcodeAlias::Alias(AliasOp::MTCR) => { dealias.opcode = Opcode::MTCRF; dealias.operands[1] = dealias.operands[0].clone(); dealias.operands[0] = Some(Operand::CrMask(0xff)); } OpcodeAlias::Alias(AliasOp::CRSET) => { dealias.opcode = Opcode::CREQV; dealias.operands[1] = dealias.operands[0].clone(); dealias.operands[2] = dealias.operands[0].clone(); } OpcodeAlias::Alias(AliasOp::CRCLR) => { dealias.opcode = Opcode::CRXOR; dealias.operands[1] = dealias.operands[0].clone(); dealias.operands[2] = dealias.operands[0].clone(); } OpcodeAlias::Alias(AliasOp::CRMOVE) => { dealias.opcode = Opcode::CROR; dealias.operands[2] = dealias.operands[1].clone(); } OpcodeAlias::Alias(AliasOp::CRNOT) => { dealias.opcode = Opcode::CRNOR; dealias.operands[2] = dealias.operands[1].clone(); } OpcodeAlias::Alias(AliasOp::SUBIS) => { let imm = dealias.operands[2].as_ref().unwrap().as_imm32_unwrap(); dealias.opcode = Opcode::ADDIS; // the negative and type juggling is not lossy because it came *from* an i16.. dealias.operands[2] = Some(Operand::ImmExts16(-(imm as i32) as i16)); } OpcodeAlias::Alias(AliasOp::LIS) => { dealias.opcode = Opcode::ADDIS; dealias.operands[2] = dealias.operands[1].clone(); dealias.operands[1] = Some(Operand::RegisterOrZero(Register { reg: 0 })); } OpcodeAlias::Alias(AliasOp::SUBI) => { let imm = dealias.operands[2].as_ref().unwrap().as_imm32_unwrap(); dealias.opcode = Opcode::ADDI; // the negative and type juggling is not lossy because it came *from* an i16.. dealias.operands[2] = Some(Operand::ImmExts16(-(imm as i32) as i16)); } OpcodeAlias::Alias(AliasOp::LI) => { dealias.opcode = Opcode::ADDI; dealias.operands[2] = dealias.operands[1].clone(); dealias.operands[1] = Some(Operand::RegisterOrZero(Register { reg: 0 })); } OpcodeAlias::Alias(AliasOp::NOP) => { dealias.opcode = Opcode::ORI; dealias.operands[0] = Some(Operand::Register(Register { reg: 0 })); dealias.operands[1] = Some(Operand::Register(Register { reg: 0 })); dealias.operands[2] = Some(Operand::ImmU16(0)); } OpcodeAlias::Alias(AliasOp::NOT) => { dealias.opcode = Opcode::NOR; dealias.operands[2] = dealias.operands[1].clone(); } OpcodeAlias::Alias(AliasOp::MR) => { dealias.opcode = Opcode::OR; dealias.operands[2] = dealias.operands[1].clone(); } OpcodeAlias::Alias(AliasOp::MTXER) => { dealias.opcode = Opcode::MTSPR; dealias.operands[1] = dealias.operands[0].clone(); dealias.operands[0] = Some(Operand::SPR(SPR { reg: 1 })); } OpcodeAlias::Alias(AliasOp::MTLR) => { dealias.opcode = Opcode::MTSPR; dealias.operands[1] = dealias.operands[0].clone(); dealias.operands[0] = Some(Operand::SPR(SPR { reg: 8 })); } OpcodeAlias::Alias(AliasOp::MTCTR) => { dealias.opcode = Opcode::MTSPR; dealias.operands[1] = dealias.operands[0].clone(); dealias.operands[0] = Some(Operand::SPR(SPR { reg: 9 })); } OpcodeAlias::Alias(AliasOp::MFXER) => { dealias.opcode = Opcode::MFSPR; dealias.operands[1] = Some(Operand::SPR(SPR { reg: 1 })); } OpcodeAlias::Alias(AliasOp::MFLR) => { dealias.opcode = Opcode::MFSPR; dealias.operands[1] = Some(Operand::SPR(SPR { reg: 8 })); } OpcodeAlias::Alias(AliasOp::MFCTR) => { dealias.opcode = Opcode::MFSPR; dealias.operands[1] = Some(Operand::SPR(SPR { reg: 9 })); } OpcodeAlias::Alias(AliasOp::TRAP) => { dealias.opcode = Opcode::TW; dealias.operands[0] = Some(Operand::Imm8(31)); dealias.operands[1] = Some(Operand::Register(Register { reg: 0 })); dealias.operands[2] = Some(Operand::Register(Register { reg: 0 })); } OpcodeAlias::Alias(AliasOp::TWLGT) => { dealias.opcode = Opcode::TW; dealias.operands[2] = dealias.operands[1].clone(); dealias.operands[1] = dealias.operands[0].clone(); dealias.operands[0] = Some(Operand::Imm8(1)); } OpcodeAlias::Alias(AliasOp::TWLLT) => { dealias.opcode = Opcode::TW; dealias.operands[2] = dealias.operands[1].clone(); dealias.operands[1] = dealias.operands[0].clone(); dealias.operands[0] = Some(Operand::Imm8(2)); } OpcodeAlias::Alias(AliasOp::TWEQ) => { dealias.opcode = Opcode::TW; dealias.operands[2] = dealias.operands[1].clone(); dealias.operands[1] = dealias.operands[0].clone(); dealias.operands[0] = Some(Operand::Imm8(4)); } OpcodeAlias::Alias(AliasOp::TWLGE) => { dealias.opcode = Opcode::TW; dealias.operands[2] = dealias.operands[1].clone(); dealias.operands[1] = dealias.operands[0].clone(); dealias.operands[0] = Some(Operand::Imm8(5)); } OpcodeAlias::Alias(AliasOp::TWLLE) => { dealias.opcode = Opcode::TW; dealias.operands[2] = dealias.operands[1].clone(); dealias.operands[1] = dealias.operands[0].clone(); dealias.operands[0] = Some(Operand::Imm8(6)); } OpcodeAlias::Alias(AliasOp::TWGT) => { dealias.opcode = Opcode::TW; dealias.operands[2] = dealias.operands[1].clone(); dealias.operands[1] = dealias.operands[0].clone(); dealias.operands[0] = Some(Operand::Imm8(8)); } OpcodeAlias::Alias(AliasOp::TWGE) => { dealias.opcode = Opcode::TW; dealias.operands[2] = dealias.operands[1].clone(); dealias.operands[1] = dealias.operands[0].clone(); dealias.operands[0] = Some(Operand::Imm8(12)); } OpcodeAlias::Alias(AliasOp::TWLT) => { dealias.opcode = Opcode::TW; dealias.operands[2] = dealias.operands[1].clone(); dealias.operands[1] = dealias.operands[0].clone(); dealias.operands[0] = Some(Operand::Imm8(16)); } OpcodeAlias::Alias(AliasOp::TWLE) => { dealias.opcode = Opcode::TW; dealias.operands[2] = dealias.operands[1].clone(); dealias.operands[1] = dealias.operands[0].clone(); dealias.operands[0] = Some(Operand::Imm8(20)); } OpcodeAlias::Alias(AliasOp::TWNE) => { dealias.opcode = Opcode::TW; dealias.operands[2] = dealias.operands[1].clone(); dealias.operands[1] = dealias.operands[0].clone(); dealias.operands[0] = Some(Operand::Imm8(24)); } OpcodeAlias::Alias(AliasOp::TDLGTI) => { dealias.opcode = Opcode::TDI; dealias.operands[2] = dealias.operands[1].clone(); dealias.operands[1] = dealias.operands[0].clone(); dealias.operands[0] = Some(Operand::Imm8(1)); } OpcodeAlias::Alias(AliasOp::TDLLTI) => { dealias.opcode = Opcode::TDI; dealias.operands[2] = dealias.operands[1].clone(); dealias.operands[1] = dealias.operands[0].clone(); dealias.operands[0] = Some(Operand::Imm8(2)); } OpcodeAlias::Alias(AliasOp::TDEQI) => { dealias.opcode = Opcode::TDI; dealias.operands[2] = dealias.operands[1].clone(); dealias.operands[1] = dealias.operands[0].clone(); dealias.operands[0] = Some(Operand::Imm8(4)); } OpcodeAlias::Alias(AliasOp::TDLGEI) => { dealias.opcode = Opcode::TDI; dealias.operands[2] = dealias.operands[1].clone(); dealias.operands[1] = dealias.operands[0].clone(); dealias.operands[0] = Some(Operand::Imm8(5)); } OpcodeAlias::Alias(AliasOp::TDLLEI) => { dealias.opcode = Opcode::TDI; dealias.operands[2] = dealias.operands[1].clone(); dealias.operands[1] = dealias.operands[0].clone(); dealias.operands[0] = Some(Operand::Imm8(6)); } OpcodeAlias::Alias(AliasOp::TDGTI) => { dealias.opcode = Opcode::TDI; dealias.operands[2] = dealias.operands[1].clone(); dealias.operands[1] = dealias.operands[0].clone(); dealias.operands[0] = Some(Operand::Imm8(8)); } OpcodeAlias::Alias(AliasOp::TDGEI) => { dealias.opcode = Opcode::TDI; dealias.operands[2] = dealias.operands[1].clone(); dealias.operands[1] = dealias.operands[0].clone(); dealias.operands[0] = Some(Operand::Imm8(12)); } OpcodeAlias::Alias(AliasOp::TDLTI) => { dealias.opcode = Opcode::TDI; dealias.operands[2] = dealias.operands[1].clone(); dealias.operands[1] = dealias.operands[0].clone(); dealias.operands[0] = Some(Operand::Imm8(16)); } OpcodeAlias::Alias(AliasOp::TDLEI) => { dealias.opcode = Opcode::TDI; dealias.operands[2] = dealias.operands[1].clone(); dealias.operands[1] = dealias.operands[0].clone(); dealias.operands[0] = Some(Operand::Imm8(20)); } OpcodeAlias::Alias(AliasOp::TDNEI) => { dealias.opcode = Opcode::TDI; dealias.operands[2] = dealias.operands[1].clone(); dealias.operands[1] = dealias.operands[0].clone(); dealias.operands[0] = Some(Operand::Imm8(24)); } OpcodeAlias::Alias(AliasOp::TWLGTI) => { dealias.opcode = Opcode::TWI; dealias.operands[2] = dealias.operands[1].clone(); dealias.operands[1] = dealias.operands[0].clone(); dealias.operands[0] = Some(Operand::Imm8(1)); } OpcodeAlias::Alias(AliasOp::TWLLTI) => { dealias.opcode = Opcode::TWI; dealias.operands[2] = dealias.operands[1].clone(); dealias.operands[1] = dealias.operands[0].clone(); dealias.operands[0] = Some(Operand::Imm8(2)); } OpcodeAlias::Alias(AliasOp::TWEQI) => { dealias.opcode = Opcode::TWI; dealias.operands[2] = dealias.operands[1].clone(); dealias.operands[1] = dealias.operands[0].clone(); dealias.operands[0] = Some(Operand::Imm8(4)); } OpcodeAlias::Alias(AliasOp::TWLGEI) => { dealias.opcode = Opcode::TWI; dealias.operands[2] = dealias.operands[1].clone(); dealias.operands[1] = dealias.operands[0].clone(); dealias.operands[0] = Some(Operand::Imm8(5)); } OpcodeAlias::Alias(AliasOp::TWLLEI) => { dealias.opcode = Opcode::TWI; dealias.operands[2] = dealias.operands[1].clone(); dealias.operands[1] = dealias.operands[0].clone(); dealias.operands[0] = Some(Operand::Imm8(6)); } OpcodeAlias::Alias(AliasOp::TWGTI) => { dealias.opcode = Opcode::TWI; dealias.operands[2] = dealias.operands[1].clone(); dealias.operands[1] = dealias.operands[0].clone(); dealias.operands[0] = Some(Operand::Imm8(8)); } OpcodeAlias::Alias(AliasOp::TWGEI) => { dealias.opcode = Opcode::TWI; dealias.operands[2] = dealias.operands[1].clone(); dealias.operands[1] = dealias.operands[0].clone(); dealias.operands[0] = Some(Operand::Imm8(12)); } OpcodeAlias::Alias(AliasOp::TWLTI) => { dealias.opcode = Opcode::TWI; dealias.operands[2] = dealias.operands[1].clone(); dealias.operands[1] = dealias.operands[0].clone(); dealias.operands[0] = Some(Operand::Imm8(16)); } OpcodeAlias::Alias(AliasOp::TWLEI) => { dealias.opcode = Opcode::TWI; dealias.operands[2] = dealias.operands[1].clone(); dealias.operands[1] = dealias.operands[0].clone(); dealias.operands[0] = Some(Operand::Imm8(20)); } OpcodeAlias::Alias(AliasOp::TWNEI) => { dealias.opcode = Opcode::TWI; dealias.operands[2] = dealias.operands[1].clone(); dealias.operands[1] = dealias.operands[0].clone(); dealias.operands[0] = Some(Operand::Imm8(24)); } OpcodeAlias::Alias(AliasOp::HWSYNC) => { dealias.opcode = Opcode::SYNC; dealias.operands[0] = Some(Operand::LL(SyncControl::Default)); } OpcodeAlias::Alias(AliasOp::LWSYNC) => { dealias.opcode = Opcode::SYNC; dealias.operands[0] = Some(Operand::LL(SyncControl::LW)); } OpcodeAlias::Alias(AliasOp::PTESYNC) => { dealias.opcode = Opcode::SYNC; dealias.operands[0] = Some(Operand::LL(SyncControl::PTE)); } rest => { panic!("rest: {:?}", rest); } } dealias } }