fix(xexdb): clear the lint gate on the imported crates
rustfmt, then clippy -D warnings across the three new crates. Mechanical,
except three decisions that are stated rather than silently allowed:
* lzx.rs gets file-scoped needless_range_loop/explicit_counter_loop allows.
Index arithmetic IS the algorithm -- LZX is defined over symbol indices,
Huffman slots and window positions, and a decompressor that is merely
idiomatic is worth nothing if it is not bit-exact.
* sylpheed-xexdb gets crate-scoped allows for needless_range_loop (nine
sites index reg[r] where r is the PowerPC register number -- the index is
the meaning), too_many_arguments and type_complexity. This code arrived
whole from a retired repository; a refactor here would be an unreviewed
edit dressed as a lint fix.
* Everything else clippy asked for is FIXED, including all 14 doc-indent
sites, the let-else, and a Prepared type alias in the binary.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -12,13 +12,17 @@
|
||||
use std::io::BufRead;
|
||||
|
||||
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
let path = std::env::args().nth(1).ok_or("usage: decode_table_check <table>")?;
|
||||
let path = std::env::args()
|
||||
.nth(1)
|
||||
.ok_or("usage: decode_table_check <table>")?;
|
||||
let f = std::io::BufReader::new(std::fs::File::open(path)?);
|
||||
let (mut ok, mut bad, mut invalid) = (0u32, 0u32, 0u32);
|
||||
for line in f.lines() {
|
||||
let line = line?;
|
||||
let mut it = line.split_whitespace();
|
||||
let (Some(w), Some(name)) = (it.next(), it.next()) else { continue };
|
||||
let (Some(w), Some(name)) = (it.next(), it.next()) else {
|
||||
continue;
|
||||
};
|
||||
let word = u32::from_str_radix(w.trim_start_matches("0x"), 16)?;
|
||||
let d = sylpheed_ppc::decoder::decode(word, 0x8200_0000);
|
||||
let got = format!("{:?}", d.opcode);
|
||||
|
||||
@@ -18,34 +18,68 @@ impl DecodedInstr {
|
||||
// Common field extractors (PPC bit numbering)
|
||||
|
||||
/// Primary opcode (bits 0-5)
|
||||
#[inline] pub fn op(&self) -> u32 { extract_bits(self.raw, 0, 5) }
|
||||
#[inline]
|
||||
pub fn op(&self) -> u32 {
|
||||
extract_bits(self.raw, 0, 5)
|
||||
}
|
||||
|
||||
/// rD/rS/rT (bits 6-10) - destination/source register
|
||||
#[inline] pub fn rd(&self) -> usize { extract_bits(self.raw, 6, 10) as usize }
|
||||
#[inline] pub fn rs(&self) -> usize { self.rd() }
|
||||
#[inline] pub fn rt(&self) -> usize { self.rd() }
|
||||
#[inline]
|
||||
pub fn rd(&self) -> usize {
|
||||
extract_bits(self.raw, 6, 10) as usize
|
||||
}
|
||||
#[inline]
|
||||
pub fn rs(&self) -> usize {
|
||||
self.rd()
|
||||
}
|
||||
#[inline]
|
||||
pub fn rt(&self) -> usize {
|
||||
self.rd()
|
||||
}
|
||||
|
||||
/// rA (bits 11-15)
|
||||
#[inline] pub fn ra(&self) -> usize { extract_bits(self.raw, 11, 15) as usize }
|
||||
#[inline]
|
||||
pub fn ra(&self) -> usize {
|
||||
extract_bits(self.raw, 11, 15) as usize
|
||||
}
|
||||
|
||||
/// rB (bits 16-20)
|
||||
#[inline] pub fn rb(&self) -> usize { extract_bits(self.raw, 16, 20) as usize }
|
||||
#[inline]
|
||||
pub fn rb(&self) -> usize {
|
||||
extract_bits(self.raw, 16, 20) as usize
|
||||
}
|
||||
|
||||
/// rC (bits 21-25) - for 4-operand instructions
|
||||
#[inline] pub fn rc(&self) -> usize { extract_bits(self.raw, 21, 25) as usize }
|
||||
#[inline]
|
||||
pub fn rc(&self) -> usize {
|
||||
extract_bits(self.raw, 21, 25) as usize
|
||||
}
|
||||
|
||||
/// SIMM/UIMM (bits 16-31) - signed/unsigned immediate
|
||||
#[inline] pub fn simm16(&self) -> i16 { (self.raw & 0xFFFF) as i16 }
|
||||
#[inline] pub fn uimm16(&self) -> u16 { (self.raw & 0xFFFF) as u16 }
|
||||
#[inline]
|
||||
pub fn simm16(&self) -> i16 {
|
||||
(self.raw & 0xFFFF) as i16
|
||||
}
|
||||
#[inline]
|
||||
pub fn uimm16(&self) -> u16 {
|
||||
(self.raw & 0xFFFF) as u16
|
||||
}
|
||||
|
||||
/// D-form displacement (signed, bits 16-31)
|
||||
#[inline] pub fn d(&self) -> i32 { self.simm16() as i32 }
|
||||
#[inline]
|
||||
pub fn d(&self) -> i32 {
|
||||
self.simm16() as i32
|
||||
}
|
||||
|
||||
/// DS-form displacement (signed, bits 16-29, shifted left 2)
|
||||
#[inline] pub fn ds(&self) -> i32 { (self.raw & 0xFFFC) as i16 as i32 }
|
||||
#[inline]
|
||||
pub fn ds(&self) -> i32 {
|
||||
(self.raw & 0xFFFC) as i16 as i32
|
||||
}
|
||||
|
||||
/// LI field for branch (bits 6-29, sign-extended, shifted left 2)
|
||||
#[inline] pub fn li(&self) -> i32 {
|
||||
#[inline]
|
||||
pub fn li(&self) -> i32 {
|
||||
let li = extract_bits(self.raw, 6, 29);
|
||||
// Sign-extend from 24 bits, then shift left 2
|
||||
let sign_extended = ((li as i32) << 8) >> 8;
|
||||
@@ -53,87 +87,154 @@ impl DecodedInstr {
|
||||
}
|
||||
|
||||
/// BD field for conditional branch (bits 16-29, sign-extended, shifted left 2)
|
||||
#[inline] pub fn bd(&self) -> i32 {
|
||||
#[inline]
|
||||
pub fn bd(&self) -> i32 {
|
||||
let bd = extract_bits(self.raw, 16, 29);
|
||||
let sign_extended = ((bd as i32) << 18) >> 18;
|
||||
sign_extended << 2
|
||||
}
|
||||
|
||||
/// BO field (bits 6-10) - branch options
|
||||
#[inline] pub fn bo(&self) -> u32 { extract_bits(self.raw, 6, 10) }
|
||||
#[inline]
|
||||
pub fn bo(&self) -> u32 {
|
||||
extract_bits(self.raw, 6, 10)
|
||||
}
|
||||
|
||||
/// BI field (bits 11-15) - branch condition
|
||||
#[inline] pub fn bi(&self) -> u32 { extract_bits(self.raw, 11, 15) }
|
||||
#[inline]
|
||||
pub fn bi(&self) -> u32 {
|
||||
extract_bits(self.raw, 11, 15)
|
||||
}
|
||||
|
||||
/// AA bit (bit 30) - absolute address
|
||||
#[inline] pub fn aa(&self) -> bool { (self.raw >> 1) & 1 != 0 }
|
||||
#[inline]
|
||||
pub fn aa(&self) -> bool {
|
||||
(self.raw >> 1) & 1 != 0
|
||||
}
|
||||
|
||||
/// LK bit (bit 31) - link (update LR)
|
||||
#[inline] pub fn lk(&self) -> bool { self.raw & 1 != 0 }
|
||||
#[inline]
|
||||
pub fn lk(&self) -> bool {
|
||||
self.raw & 1 != 0
|
||||
}
|
||||
|
||||
/// Rc bit (bit 31) - record CR0
|
||||
#[inline] pub fn rc_bit(&self) -> bool { self.raw & 1 != 0 }
|
||||
#[inline]
|
||||
pub fn rc_bit(&self) -> bool {
|
||||
self.raw & 1 != 0
|
||||
}
|
||||
|
||||
/// Rc for VC-form vector compare instructions — PPC bit 21 = host bit 10.
|
||||
#[inline] pub fn vc_rc_bit(&self) -> bool { (self.raw >> 10) & 1 != 0 }
|
||||
#[inline]
|
||||
pub fn vc_rc_bit(&self) -> bool {
|
||||
(self.raw >> 10) & 1 != 0
|
||||
}
|
||||
/// Rc for VX128_R-form vector compare instructions — PPC bit 27 = host bit 4.
|
||||
/// VX128_R Rc bit — PPC bit 25 (host bit 6) per canary's FormatVX128_R
|
||||
/// bitfield layout. PPCBUG-700.
|
||||
#[inline] pub fn vx128r_rc_bit(&self) -> bool { (self.raw >> 6) & 1 != 0 }
|
||||
#[inline]
|
||||
pub fn vx128r_rc_bit(&self) -> bool {
|
||||
(self.raw >> 6) & 1 != 0
|
||||
}
|
||||
|
||||
/// IMM field for VX128_4-form instructions (vrlimi128) — 5-bit blend mask at PPC bits 11-15.
|
||||
#[inline] pub fn vx128_4_imm(&self) -> u32 { extract_bits(self.raw, 11, 15) }
|
||||
#[inline]
|
||||
pub fn vx128_4_imm(&self) -> u32 {
|
||||
extract_bits(self.raw, 11, 15)
|
||||
}
|
||||
/// z field for VX128_4-form instructions (vrlimi128) — 2-bit rotation index at PPC bits 24-25.
|
||||
#[inline] pub fn vx128_4_z(&self) -> u32 { extract_bits(self.raw, 24, 25) }
|
||||
#[inline]
|
||||
pub fn vx128_4_z(&self) -> u32 {
|
||||
extract_bits(self.raw, 24, 25)
|
||||
}
|
||||
|
||||
/// OE bit (bit 21) - overflow enable
|
||||
#[inline] pub fn oe(&self) -> bool { extract_bits(self.raw, 21, 21) != 0 }
|
||||
#[inline]
|
||||
pub fn oe(&self) -> bool {
|
||||
extract_bits(self.raw, 21, 21) != 0
|
||||
}
|
||||
|
||||
/// TO field (bits 6-10) for tw/twi/td/tdi trap instructions.
|
||||
#[inline] pub fn to(&self) -> u32 { extract_bits(self.raw, 6, 10) }
|
||||
#[inline]
|
||||
pub fn to(&self) -> u32 {
|
||||
extract_bits(self.raw, 6, 10)
|
||||
}
|
||||
|
||||
/// MB, ME fields for rotate instructions
|
||||
#[inline] pub fn mb(&self) -> u32 { extract_bits(self.raw, 21, 25) }
|
||||
#[inline] pub fn me(&self) -> u32 { extract_bits(self.raw, 26, 30) }
|
||||
#[inline]
|
||||
pub fn mb(&self) -> u32 {
|
||||
extract_bits(self.raw, 21, 25)
|
||||
}
|
||||
#[inline]
|
||||
pub fn me(&self) -> u32 {
|
||||
extract_bits(self.raw, 26, 30)
|
||||
}
|
||||
|
||||
/// SH field (bits 16-20) for shift instructions
|
||||
#[inline] pub fn sh(&self) -> u32 { extract_bits(self.raw, 16, 20) }
|
||||
#[inline]
|
||||
pub fn sh(&self) -> u32 {
|
||||
extract_bits(self.raw, 16, 20)
|
||||
}
|
||||
|
||||
/// SH field for 64-bit shifts (bits 16-20 + bit 30)
|
||||
#[inline] pub fn sh64(&self) -> u32 {
|
||||
#[inline]
|
||||
pub fn sh64(&self) -> u32 {
|
||||
(extract_bits(self.raw, 30, 30) << 5) | extract_bits(self.raw, 16, 20)
|
||||
}
|
||||
|
||||
/// MB/ME field for MD-form and MDS-form instructions (6-bit field, split encoding).
|
||||
/// MB[4:0] at PPC bits 21-25; MB[5] at PPC bit 26.
|
||||
#[inline] pub fn mb_md(&self) -> u32 {
|
||||
#[inline]
|
||||
pub fn mb_md(&self) -> u32 {
|
||||
extract_bits(self.raw, 21, 25) | (extract_bits(self.raw, 26, 26) << 5)
|
||||
}
|
||||
|
||||
/// SPR field (bits 11-20, swapped halves)
|
||||
#[inline] pub fn spr(&self) -> u32 {
|
||||
#[inline]
|
||||
pub fn spr(&self) -> u32 {
|
||||
let spr_raw = extract_bits(self.raw, 11, 20);
|
||||
((spr_raw & 0x1F) << 5) | ((spr_raw >> 5) & 0x1F)
|
||||
}
|
||||
|
||||
/// CRM field (bits 12-19) for mtcrf
|
||||
#[inline] pub fn crm(&self) -> u32 { extract_bits(self.raw, 12, 19) }
|
||||
#[inline]
|
||||
pub fn crm(&self) -> u32 {
|
||||
extract_bits(self.raw, 12, 19)
|
||||
}
|
||||
|
||||
/// crfD (bits 6-8) - condition register field destination
|
||||
#[inline] pub fn crfd(&self) -> usize { extract_bits(self.raw, 6, 8) as usize }
|
||||
#[inline]
|
||||
pub fn crfd(&self) -> usize {
|
||||
extract_bits(self.raw, 6, 8) as usize
|
||||
}
|
||||
|
||||
/// crfS (bits 11-13)
|
||||
#[inline] pub fn crfs(&self) -> usize { extract_bits(self.raw, 11, 13) as usize }
|
||||
#[inline]
|
||||
pub fn crfs(&self) -> usize {
|
||||
extract_bits(self.raw, 11, 13) as usize
|
||||
}
|
||||
|
||||
/// L bit (bit 10) - 64-bit compare
|
||||
#[inline] pub fn l(&self) -> bool { extract_bits(self.raw, 10, 10) != 0 }
|
||||
#[inline]
|
||||
pub fn l(&self) -> bool {
|
||||
extract_bits(self.raw, 10, 10) != 0
|
||||
}
|
||||
|
||||
/// crbD (bits 6-10)
|
||||
#[inline] pub fn crbd(&self) -> u32 { extract_bits(self.raw, 6, 10) }
|
||||
#[inline]
|
||||
pub fn crbd(&self) -> u32 {
|
||||
extract_bits(self.raw, 6, 10)
|
||||
}
|
||||
/// crbA (bits 11-15)
|
||||
#[inline] pub fn crba(&self) -> u32 { extract_bits(self.raw, 11, 15) }
|
||||
#[inline]
|
||||
pub fn crba(&self) -> u32 {
|
||||
extract_bits(self.raw, 11, 15)
|
||||
}
|
||||
/// crbB (bits 16-20)
|
||||
#[inline] pub fn crbb(&self) -> u32 { extract_bits(self.raw, 16, 20) }
|
||||
#[inline]
|
||||
pub fn crbb(&self) -> u32 {
|
||||
extract_bits(self.raw, 16, 20)
|
||||
}
|
||||
|
||||
// VMX128 field extractors — bit positions match canary's
|
||||
// FormatVX128/VX128_2/VX128_4/VX128_5/VX128_R bitfield layout
|
||||
@@ -141,7 +242,8 @@ impl DecodedInstr {
|
||||
|
||||
/// VA128 = VA128l(5) | VA128h(1) << 5 | VA128H(1) << 6.
|
||||
/// Canonical 7-bit register selector: PPC 11-15 (low), PPC 26 (mid), PPC 21 (high).
|
||||
#[inline] pub fn va128(&self) -> usize {
|
||||
#[inline]
|
||||
pub fn va128(&self) -> usize {
|
||||
(extract_bits(self.raw, 11, 15)
|
||||
| (extract_bits(self.raw, 26, 26) << 5)
|
||||
| (extract_bits(self.raw, 21, 21) << 6)) as usize
|
||||
@@ -149,35 +251,48 @@ impl DecodedInstr {
|
||||
|
||||
/// VB128 = VB128l(5) | VB128h(2) << 5. Canary's VB128h is a 2-bit
|
||||
/// contiguous field at PPC 30-31 (host bits 0-1).
|
||||
#[inline] pub fn vb128(&self) -> usize {
|
||||
(extract_bits(self.raw, 16, 20)
|
||||
| (extract_bits(self.raw, 30, 31) << 5)) as usize
|
||||
#[inline]
|
||||
pub fn vb128(&self) -> usize {
|
||||
(extract_bits(self.raw, 16, 20) | (extract_bits(self.raw, 30, 31) << 5)) as usize
|
||||
}
|
||||
|
||||
/// VD128 = VD128l(5) | VD128h(2) << 5. Canary's VD128h is a 2-bit
|
||||
/// contiguous field at PPC 28-29 (host bits 2-3).
|
||||
#[inline] pub fn vd128(&self) -> usize {
|
||||
(extract_bits(self.raw, 6, 10)
|
||||
| (extract_bits(self.raw, 28, 29) << 5)) as usize
|
||||
#[inline]
|
||||
pub fn vd128(&self) -> usize {
|
||||
(extract_bits(self.raw, 6, 10) | (extract_bits(self.raw, 28, 29) << 5)) as usize
|
||||
}
|
||||
|
||||
/// VS128 - same encoding as VD128
|
||||
#[inline] pub fn vs128(&self) -> usize { self.vd128() }
|
||||
#[inline]
|
||||
pub fn vs128(&self) -> usize {
|
||||
self.vd128()
|
||||
}
|
||||
|
||||
/// VC register for VX128_2-form instructions (vperm128) — 3-bit at PPC bits 23-25.
|
||||
#[inline] pub fn vc128_2(&self) -> usize { extract_bits(self.raw, 23, 25) as usize }
|
||||
#[inline]
|
||||
pub fn vc128_2(&self) -> usize {
|
||||
extract_bits(self.raw, 23, 25) as usize
|
||||
}
|
||||
|
||||
/// NB field (bits 16-20) for lswi/stswi
|
||||
#[inline] pub fn nb(&self) -> u32 { extract_bits(self.raw, 16, 20) }
|
||||
#[inline]
|
||||
pub fn nb(&self) -> u32 {
|
||||
extract_bits(self.raw, 16, 20)
|
||||
}
|
||||
|
||||
/// PERM field for VX128_P-form instructions (vpermwi128) — 8-bit split encoding.
|
||||
/// PERMl (5 bits) at PPC bits 11-15; PERMh (3 bits) at PPC bits 23-25.
|
||||
#[inline] pub fn vx128_p_perm(&self) -> u32 {
|
||||
#[inline]
|
||||
pub fn vx128_p_perm(&self) -> u32 {
|
||||
extract_bits(self.raw, 11, 15) | (extract_bits(self.raw, 23, 25) << 5)
|
||||
}
|
||||
|
||||
/// SH field for VX128_5-form instructions (vsldoi128) — 4-bit shift at PPC bits 22-25.
|
||||
#[inline] pub fn vx128_5_sh(&self) -> u32 { extract_bits(self.raw, 22, 25) }
|
||||
#[inline]
|
||||
pub fn vx128_5_sh(&self) -> u32 {
|
||||
extract_bits(self.raw, 22, 25)
|
||||
}
|
||||
}
|
||||
|
||||
/// Extract the 5-bit `UIMM` (`VX128_3`) / `IMM` (`VX128_4`) field. Canary
|
||||
@@ -1057,8 +1172,15 @@ mod tests {
|
||||
/// vd_hi is 2 bits (PPC 28-29). Same shape for vb128 (vb_lo at PPC 16-20,
|
||||
/// vb_hi 2 bits at PPC 30-31). va128 = va_lo | (va_h26<<5) | (va_h21<<6)
|
||||
/// per canary's 7-bit VA selector.
|
||||
fn vmx128_test_word(vd_lo: u32, vd_hi: u32, va_lo: u32, va_h26: u32, va_h21: u32,
|
||||
vb_lo: u32, vb_hi: u32) -> u32 {
|
||||
fn vmx128_test_word(
|
||||
vd_lo: u32,
|
||||
vd_hi: u32,
|
||||
va_lo: u32,
|
||||
va_h26: u32,
|
||||
va_h21: u32,
|
||||
vb_lo: u32,
|
||||
vb_hi: u32,
|
||||
) -> u32 {
|
||||
// PPC bit i -> host bit (31-i).
|
||||
(vd_lo << (31 - 10)) // VD128l: PPC 6-10 = host 21-25
|
||||
| (vd_hi << (31 - 29)) // VD128h: PPC 28-29 = host 2-3 (LSB at host 2)
|
||||
@@ -1066,15 +1188,19 @@ mod tests {
|
||||
| (va_h26 << (31 - 26)) // VA128h: PPC 26 = host 5
|
||||
| (va_h21 << (31 - 21)) // VA128H: PPC 21 = host 10
|
||||
| (vb_lo << (31 - 20)) // VB128l: PPC 16-20 = host 11-15
|
||||
| (vb_hi << (31 - 31)) // VB128h: PPC 30-31 = host 0-1 (LSB at host 0)
|
||||
| vb_hi // VB128h: PPC 30-31 = host 0-1 (LSB at host 0)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn vmx128_vd128_low_5_bits_only() {
|
||||
// vd_lo = 0..31, vd_hi = 0 → vd128 = vd_lo
|
||||
for r in 0..32u32 {
|
||||
let raw = (r as u32) << (31 - 10);
|
||||
let d = DecodedInstr { opcode: PpcOpcode::Invalid, raw, addr: 0 };
|
||||
let raw = r << (31 - 10);
|
||||
let d = DecodedInstr {
|
||||
opcode: PpcOpcode::Invalid,
|
||||
raw,
|
||||
addr: 0,
|
||||
};
|
||||
assert_eq!(d.vd128(), r as usize, "vd_lo={r}");
|
||||
}
|
||||
}
|
||||
@@ -1082,26 +1208,36 @@ mod tests {
|
||||
#[test]
|
||||
fn vmx128_vd128_high_low_bit_adds_32() {
|
||||
// vd_lo = 0, VD128h = 0b01 (LSB only at host bit 2 = PPC 29) → vd128 = 32
|
||||
let raw = (1u32 << (31 - 29));
|
||||
let d = DecodedInstr { opcode: PpcOpcode::Invalid, raw, addr: 0 };
|
||||
let raw = 1u32 << (31 - 29);
|
||||
let d = DecodedInstr {
|
||||
opcode: PpcOpcode::Invalid,
|
||||
raw,
|
||||
addr: 0,
|
||||
};
|
||||
assert_eq!(d.vd128(), 32);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn vmx128_vd128_high_high_bit_adds_64() {
|
||||
// vd_lo = 0, VD128h = 0b10 (MSB only at host bit 3 = PPC 28) → vd128 = 64
|
||||
let raw = (1u32 << (31 - 28));
|
||||
let d = DecodedInstr { opcode: PpcOpcode::Invalid, raw, addr: 0 };
|
||||
let raw = 1u32 << (31 - 28);
|
||||
let d = DecodedInstr {
|
||||
opcode: PpcOpcode::Invalid,
|
||||
raw,
|
||||
addr: 0,
|
||||
};
|
||||
assert_eq!(d.vd128(), 64);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn vmx128_vd128_full_127() {
|
||||
// vd_lo = 31, VD128h = 0b11 → vd128 = 127
|
||||
let raw = (31u32 << (31 - 10))
|
||||
| (1u32 << (31 - 28))
|
||||
| (1u32 << (31 - 29));
|
||||
let d = DecodedInstr { opcode: PpcOpcode::Invalid, raw, addr: 0 };
|
||||
let raw = (31u32 << (31 - 10)) | (1u32 << (31 - 28)) | (1u32 << (31 - 29));
|
||||
let d = DecodedInstr {
|
||||
opcode: PpcOpcode::Invalid,
|
||||
raw,
|
||||
addr: 0,
|
||||
};
|
||||
assert_eq!(d.vd128(), 127);
|
||||
}
|
||||
|
||||
@@ -1109,11 +1245,19 @@ mod tests {
|
||||
fn vmx128_va128_canary_layout() {
|
||||
// va_lo = 7 at PPC 11-15, VA128h = 1 at PPC 26 → va128 = 7 | 32 = 39
|
||||
let raw = (7u32 << (31 - 15)) | (1u32 << (31 - 26));
|
||||
let d = DecodedInstr { opcode: PpcOpcode::Invalid, raw, addr: 0 };
|
||||
let d = DecodedInstr {
|
||||
opcode: PpcOpcode::Invalid,
|
||||
raw,
|
||||
addr: 0,
|
||||
};
|
||||
assert_eq!(d.va128(), 39);
|
||||
// VA128H = 1 at PPC 21 → va128 += 64 = 103
|
||||
let raw = raw | (1u32 << (31 - 21));
|
||||
let d = DecodedInstr { opcode: PpcOpcode::Invalid, raw, addr: 0 };
|
||||
let d = DecodedInstr {
|
||||
opcode: PpcOpcode::Invalid,
|
||||
raw,
|
||||
addr: 0,
|
||||
};
|
||||
assert_eq!(d.va128(), 7 | 32 | 64);
|
||||
}
|
||||
|
||||
@@ -1122,10 +1266,18 @@ mod tests {
|
||||
// vb_lo = 5 at PPC 16-20. VB128h = 0b01 (LSB at PPC 31 = host 0) → +32.
|
||||
// VB128h = 0b11 → +96.
|
||||
let raw = (5u32 << (31 - 20)) | (1u32 << (31 - 31));
|
||||
let d = DecodedInstr { opcode: PpcOpcode::Invalid, raw, addr: 0 };
|
||||
let d = DecodedInstr {
|
||||
opcode: PpcOpcode::Invalid,
|
||||
raw,
|
||||
addr: 0,
|
||||
};
|
||||
assert_eq!(d.vb128(), 5 | 32);
|
||||
let raw = raw | (1u32 << (31 - 30));
|
||||
let d = DecodedInstr { opcode: PpcOpcode::Invalid, raw, addr: 0 };
|
||||
let d = DecodedInstr {
|
||||
opcode: PpcOpcode::Invalid,
|
||||
raw,
|
||||
addr: 0,
|
||||
};
|
||||
assert_eq!(d.vb128(), 5 | 32 | 64);
|
||||
}
|
||||
|
||||
@@ -1135,9 +1287,12 @@ mod tests {
|
||||
for r in [0u32, 31, 32, 64, 96, 127] {
|
||||
let lo = r & 0x1F;
|
||||
let hi = (r >> 5) & 0x3;
|
||||
let raw = (lo << (31 - 10))
|
||||
| (hi << (31 - 29));
|
||||
let d = DecodedInstr { opcode: PpcOpcode::Invalid, raw, addr: 0 };
|
||||
let raw = (lo << (31 - 10)) | (hi << (31 - 29));
|
||||
let d = DecodedInstr {
|
||||
opcode: PpcOpcode::Invalid,
|
||||
raw,
|
||||
addr: 0,
|
||||
};
|
||||
assert_eq!(d.vd128(), r as usize, "vd128 mismatch for r={r}");
|
||||
assert_eq!(d.vs128(), r as usize, "vs128 mismatch for r={r}");
|
||||
assert_eq!(d.vd128(), d.vs128());
|
||||
@@ -1150,7 +1305,11 @@ mod tests {
|
||||
// Keep the helper validated against the real accessor.
|
||||
// vd_lo=5, vd_hi=0b11 → vd128 = 5 | 96 = 101
|
||||
let raw = vmx128_test_word(5, 3, 0, 0, 0, 0, 0);
|
||||
let d = DecodedInstr { opcode: PpcOpcode::Invalid, raw, addr: 0 };
|
||||
let d = DecodedInstr {
|
||||
opcode: PpcOpcode::Invalid,
|
||||
raw,
|
||||
addr: 0,
|
||||
};
|
||||
assert_eq!(d.vd128(), 5 | 32 | 64);
|
||||
}
|
||||
|
||||
@@ -1160,21 +1319,37 @@ mod tests {
|
||||
// Host bit 9 = 1 (PPC bit 22), host bits 6-8 = 0.
|
||||
// So raw bit 9 set = raw |= 1 << 9 = 0x200
|
||||
let raw = 0x200u32; // host bit 9 set only
|
||||
let d = DecodedInstr { opcode: PpcOpcode::Invalid, raw, addr: 0 };
|
||||
let d = DecodedInstr {
|
||||
opcode: PpcOpcode::Invalid,
|
||||
raw,
|
||||
addr: 0,
|
||||
};
|
||||
assert_eq!(d.vx128_5_sh(), 8, "SH=8: MSB at PPC bit 22");
|
||||
|
||||
// SH=1 (binary 0001): host bit 6 set = raw |= 1 << 6 = 0x40
|
||||
let raw = 0x40u32;
|
||||
let d = DecodedInstr { opcode: PpcOpcode::Invalid, raw, addr: 0 };
|
||||
let d = DecodedInstr {
|
||||
opcode: PpcOpcode::Invalid,
|
||||
raw,
|
||||
addr: 0,
|
||||
};
|
||||
assert_eq!(d.vx128_5_sh(), 1, "SH=1: LSB at PPC bit 25");
|
||||
|
||||
// SH=15 (binary 1111): host bits 6-9 all set = raw |= 0xF << 6 = 0x3C0
|
||||
let raw = 0x3C0u32;
|
||||
let d = DecodedInstr { opcode: PpcOpcode::Invalid, raw, addr: 0 };
|
||||
let d = DecodedInstr {
|
||||
opcode: PpcOpcode::Invalid,
|
||||
raw,
|
||||
addr: 0,
|
||||
};
|
||||
assert_eq!(d.vx128_5_sh(), 15, "SH=15: all 4 bits set");
|
||||
|
||||
// SH=0: raw=0
|
||||
let d = DecodedInstr { opcode: PpcOpcode::Invalid, raw: 0, addr: 0 };
|
||||
let d = DecodedInstr {
|
||||
opcode: PpcOpcode::Invalid,
|
||||
raw: 0,
|
||||
addr: 0,
|
||||
};
|
||||
assert_eq!(d.vx128_5_sh(), 0, "SH=0");
|
||||
}
|
||||
|
||||
@@ -1182,23 +1357,39 @@ mod tests {
|
||||
fn vx128_4_accessors_correct_bit_positions() {
|
||||
// z=3 (binary 11) at PPC bits 24-25 = host bits 6-7
|
||||
let raw = 0b11u32 << 6;
|
||||
let d = DecodedInstr { opcode: PpcOpcode::Invalid, raw, addr: 0 };
|
||||
let d = DecodedInstr {
|
||||
opcode: PpcOpcode::Invalid,
|
||||
raw,
|
||||
addr: 0,
|
||||
};
|
||||
assert_eq!(d.vx128_4_z(), 3, "z=3 from host bits 6-7");
|
||||
|
||||
// IMM=0x15 (binary 10101) at PPC bits 11-15 = host bits 16-20
|
||||
let raw2 = 0x15u32 << 16;
|
||||
let d2 = DecodedInstr { opcode: PpcOpcode::Invalid, raw: raw2, addr: 0 };
|
||||
let d2 = DecodedInstr {
|
||||
opcode: PpcOpcode::Invalid,
|
||||
raw: raw2,
|
||||
addr: 0,
|
||||
};
|
||||
assert_eq!(d2.vx128_4_imm(), 0x15, "IMM=0x15 from host bits 16-20");
|
||||
|
||||
// Combined: z=1, IMM=0xA — fields must not bleed into each other
|
||||
let raw3 = (0x1u32 << 6) | (0xAu32 << 16);
|
||||
let d3 = DecodedInstr { opcode: PpcOpcode::Invalid, raw: raw3, addr: 0 };
|
||||
let d3 = DecodedInstr {
|
||||
opcode: PpcOpcode::Invalid,
|
||||
raw: raw3,
|
||||
addr: 0,
|
||||
};
|
||||
assert_eq!(d3.vx128_4_z(), 1, "z=1 combined");
|
||||
assert_eq!(d3.vx128_4_imm(), 0xA, "IMM=0xA combined");
|
||||
|
||||
// z=2, IMM=0xF — max 4-bit blend mask, exercises the full lower nibble
|
||||
let raw4 = (0b10u32 << 6) | (0xFu32 << 16);
|
||||
let d4 = DecodedInstr { opcode: PpcOpcode::Invalid, raw: raw4, addr: 0 };
|
||||
let d4 = DecodedInstr {
|
||||
opcode: PpcOpcode::Invalid,
|
||||
raw: raw4,
|
||||
addr: 0,
|
||||
};
|
||||
assert_eq!(d4.vx128_4_z(), 2, "z=2 from binary 10");
|
||||
assert_eq!(d4.vx128_4_imm(), 0xF, "IMM=0xF all-ones nibble");
|
||||
}
|
||||
@@ -1208,16 +1399,32 @@ mod tests {
|
||||
// VC=5 (binary 101) at PPC bits 23-25 = host bits 6-8
|
||||
// extract_bits(raw, 23, 25) = (raw >> (31-25)) & 0x7 = (raw >> 6) & 0x7
|
||||
let raw = 5u32 << 6; // host bits 6-8 = 5
|
||||
let d = DecodedInstr { opcode: PpcOpcode::Invalid, raw, addr: 0 };
|
||||
let d = DecodedInstr {
|
||||
opcode: PpcOpcode::Invalid,
|
||||
raw,
|
||||
addr: 0,
|
||||
};
|
||||
assert_eq!(d.vc128_2(), 5);
|
||||
|
||||
let d0 = DecodedInstr { opcode: PpcOpcode::Invalid, raw: 0, addr: 0 };
|
||||
let d0 = DecodedInstr {
|
||||
opcode: PpcOpcode::Invalid,
|
||||
raw: 0,
|
||||
addr: 0,
|
||||
};
|
||||
assert_eq!(d0.vc128_2(), 0);
|
||||
|
||||
let d7 = DecodedInstr { opcode: PpcOpcode::Invalid, raw: 7u32 << 6, addr: 0 };
|
||||
let d7 = DecodedInstr {
|
||||
opcode: PpcOpcode::Invalid,
|
||||
raw: 7u32 << 6,
|
||||
addr: 0,
|
||||
};
|
||||
assert_eq!(d7.vc128_2(), 7);
|
||||
|
||||
let d1 = DecodedInstr { opcode: PpcOpcode::Invalid, raw: 1u32 << 6, addr: 0 };
|
||||
let d1 = DecodedInstr {
|
||||
opcode: PpcOpcode::Invalid,
|
||||
raw: 1u32 << 6,
|
||||
addr: 0,
|
||||
};
|
||||
assert_eq!(d1.vc128_2(), 1);
|
||||
}
|
||||
|
||||
@@ -1225,21 +1432,37 @@ mod tests {
|
||||
fn vx128_p_perm_assembles_correctly() {
|
||||
// PERMl=0x1F (all 5 bits set) at host bits 16-20: raw = 0x1F << 16
|
||||
let raw = 0x1Fu32 << 16;
|
||||
let d = DecodedInstr { opcode: PpcOpcode::Invalid, raw, addr: 0 };
|
||||
let d = DecodedInstr {
|
||||
opcode: PpcOpcode::Invalid,
|
||||
raw,
|
||||
addr: 0,
|
||||
};
|
||||
assert_eq!(d.vx128_p_perm(), 0x1F, "PERMl only");
|
||||
|
||||
// PERMh=0x7 (all 3 bits set) at host bits 6-8: raw = 0x7 << 6 = 0x1C0
|
||||
let raw = 0x7u32 << 6;
|
||||
let d = DecodedInstr { opcode: PpcOpcode::Invalid, raw, addr: 0 };
|
||||
let d = DecodedInstr {
|
||||
opcode: PpcOpcode::Invalid,
|
||||
raw,
|
||||
addr: 0,
|
||||
};
|
||||
assert_eq!(d.vx128_p_perm(), 0x7 << 5, "PERMh only: bits 5-7");
|
||||
|
||||
// PERMl=0xA, PERMh=0x5: raw = (0xA << 16) | (0x5 << 6)
|
||||
let raw = (0xAu32 << 16) | (0x5u32 << 6);
|
||||
let d = DecodedInstr { opcode: PpcOpcode::Invalid, raw, addr: 0 };
|
||||
let d = DecodedInstr {
|
||||
opcode: PpcOpcode::Invalid,
|
||||
raw,
|
||||
addr: 0,
|
||||
};
|
||||
assert_eq!(d.vx128_p_perm(), 0xA | (0x5 << 5));
|
||||
|
||||
// PERMl and PERMh bits must not bleed into each other
|
||||
let d = DecodedInstr { opcode: PpcOpcode::Invalid, raw: 0, addr: 0 };
|
||||
let d = DecodedInstr {
|
||||
opcode: PpcOpcode::Invalid,
|
||||
raw: 0,
|
||||
addr: 0,
|
||||
};
|
||||
assert_eq!(d.vx128_p_perm(), 0);
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -5,131 +5,498 @@
|
||||
#[allow(non_camel_case_types)]
|
||||
pub enum PpcOpcode {
|
||||
// ALU
|
||||
addcx, addex, addi, addic, addicx, addis, addmex, addx, addzex,
|
||||
andcx, andisx, andix, andx,
|
||||
addcx,
|
||||
addex,
|
||||
addi,
|
||||
addic,
|
||||
addicx,
|
||||
addis,
|
||||
addmex,
|
||||
addx,
|
||||
addzex,
|
||||
andcx,
|
||||
andisx,
|
||||
andix,
|
||||
andx,
|
||||
// Branch
|
||||
bcctrx, bclrx, bcx, bx,
|
||||
bcctrx,
|
||||
bclrx,
|
||||
bcx,
|
||||
bx,
|
||||
// Compare
|
||||
cmp, cmpi, cmpl, cmpli,
|
||||
cmp,
|
||||
cmpi,
|
||||
cmpl,
|
||||
cmpli,
|
||||
// Count leading zeros
|
||||
cntlzdx, cntlzwx,
|
||||
cntlzdx,
|
||||
cntlzwx,
|
||||
// Condition register
|
||||
crand, crandc, creqv, crnand, crnor, cror, crorc, crxor,
|
||||
crand,
|
||||
crandc,
|
||||
creqv,
|
||||
crnand,
|
||||
crnor,
|
||||
cror,
|
||||
crorc,
|
||||
crxor,
|
||||
// Data cache
|
||||
dcbf, dcbi, dcbst, dcbt, dcbtst, dcbz, dcbz128,
|
||||
dcbf,
|
||||
dcbi,
|
||||
dcbst,
|
||||
dcbt,
|
||||
dcbtst,
|
||||
dcbz,
|
||||
dcbz128,
|
||||
// Division
|
||||
divdux, divdx, divwux, divwx,
|
||||
divdux,
|
||||
divdx,
|
||||
divwux,
|
||||
divwx,
|
||||
// Sync/barrier
|
||||
eieio,
|
||||
// Logical
|
||||
eqvx, extsbx, extshx, extswx,
|
||||
eqvx,
|
||||
extsbx,
|
||||
extshx,
|
||||
extswx,
|
||||
// FPU
|
||||
fabsx, faddsx, faddx, fcfidx, fcmpo, fcmpu, fctidx, fctidzx, fctiwx, fctiwzx,
|
||||
fdivsx, fdivx, fmaddsx, fmaddx, fmrx, fmsubsx, fmsubx, fmulsx, fmulx,
|
||||
fnabsx, fnegx, fnmaddsx, fnmaddx, fnmsubsx, fnmsubx, fresx, frspx, frsqrtex,
|
||||
fselx, fsqrtsx, fsqrtx, fsubsx, fsubx,
|
||||
fabsx,
|
||||
faddsx,
|
||||
faddx,
|
||||
fcfidx,
|
||||
fcmpo,
|
||||
fcmpu,
|
||||
fctidx,
|
||||
fctidzx,
|
||||
fctiwx,
|
||||
fctiwzx,
|
||||
fdivsx,
|
||||
fdivx,
|
||||
fmaddsx,
|
||||
fmaddx,
|
||||
fmrx,
|
||||
fmsubsx,
|
||||
fmsubx,
|
||||
fmulsx,
|
||||
fmulx,
|
||||
fnabsx,
|
||||
fnegx,
|
||||
fnmaddsx,
|
||||
fnmaddx,
|
||||
fnmsubsx,
|
||||
fnmsubx,
|
||||
fresx,
|
||||
frspx,
|
||||
frsqrtex,
|
||||
fselx,
|
||||
fsqrtsx,
|
||||
fsqrtx,
|
||||
fsubsx,
|
||||
fsubx,
|
||||
// Instruction cache
|
||||
icbi, isync,
|
||||
icbi,
|
||||
isync,
|
||||
// Load byte
|
||||
lbz, lbzu, lbzux, lbzx,
|
||||
lbz,
|
||||
lbzu,
|
||||
lbzux,
|
||||
lbzx,
|
||||
// Load doubleword
|
||||
ld, ldarx, ldbrx, ldu, ldux, ldx,
|
||||
ld,
|
||||
ldarx,
|
||||
ldbrx,
|
||||
ldu,
|
||||
ldux,
|
||||
ldx,
|
||||
// Load float
|
||||
lfd, lfdu, lfdux, lfdx, lfs, lfsu, lfsux, lfsx,
|
||||
lfd,
|
||||
lfdu,
|
||||
lfdux,
|
||||
lfdx,
|
||||
lfs,
|
||||
lfsu,
|
||||
lfsux,
|
||||
lfsx,
|
||||
// Load halfword
|
||||
lha, lhau, lhaux, lhax, lhbrx, lhz, lhzu, lhzux, lhzx,
|
||||
lha,
|
||||
lhau,
|
||||
lhaux,
|
||||
lhax,
|
||||
lhbrx,
|
||||
lhz,
|
||||
lhzu,
|
||||
lhzux,
|
||||
lhzx,
|
||||
// Load multiple/string
|
||||
lmw, lswi, lswx,
|
||||
lmw,
|
||||
lswi,
|
||||
lswx,
|
||||
// Load vector
|
||||
lvebx, lvehx, lvewx, lvewx128, lvlx, lvlx128, lvlxl, lvlxl128,
|
||||
lvrx, lvrx128, lvrxl, lvrxl128,
|
||||
lvsl, lvsl128, lvsr, lvsr128,
|
||||
lvx, lvx128, lvxl, lvxl128,
|
||||
lvebx,
|
||||
lvehx,
|
||||
lvewx,
|
||||
lvewx128,
|
||||
lvlx,
|
||||
lvlx128,
|
||||
lvlxl,
|
||||
lvlxl128,
|
||||
lvrx,
|
||||
lvrx128,
|
||||
lvrxl,
|
||||
lvrxl128,
|
||||
lvsl,
|
||||
lvsl128,
|
||||
lvsr,
|
||||
lvsr128,
|
||||
lvx,
|
||||
lvx128,
|
||||
lvxl,
|
||||
lvxl128,
|
||||
// Load word
|
||||
lwa, lwarx, lwaux, lwax, lwbrx, lwz, lwzu, lwzux, lwzx,
|
||||
lwa,
|
||||
lwarx,
|
||||
lwaux,
|
||||
lwax,
|
||||
lwbrx,
|
||||
lwz,
|
||||
lwzu,
|
||||
lwzux,
|
||||
lwzx,
|
||||
// Move CR
|
||||
mcrf, mcrfs, mcrxr,
|
||||
mcrf,
|
||||
mcrfs,
|
||||
mcrxr,
|
||||
// Move from special
|
||||
mfcr, mffsx, mfmsr, mfspr, mftb, mfvscr,
|
||||
mfcr,
|
||||
mffsx,
|
||||
mfmsr,
|
||||
mfspr,
|
||||
mftb,
|
||||
mfvscr,
|
||||
// Move to special
|
||||
mtcrf, mtfsb0x, mtfsb1x, mtfsfix, mtfsfx, mtmsr, mtmsrd, mtspr, mtvscr,
|
||||
mtcrf,
|
||||
mtfsb0x,
|
||||
mtfsb1x,
|
||||
mtfsfix,
|
||||
mtfsfx,
|
||||
mtmsr,
|
||||
mtmsrd,
|
||||
mtspr,
|
||||
mtvscr,
|
||||
// Multiply
|
||||
mulhdux, mulhdx, mulhwux, mulhwx, mulldx, mulli, mullwx,
|
||||
mulhdux,
|
||||
mulhdx,
|
||||
mulhwux,
|
||||
mulhwx,
|
||||
mulldx,
|
||||
mulli,
|
||||
mullwx,
|
||||
// Logical
|
||||
nandx, negx, norx, orcx, ori, oris, orx,
|
||||
nandx,
|
||||
negx,
|
||||
norx,
|
||||
orcx,
|
||||
ori,
|
||||
oris,
|
||||
orx,
|
||||
// Rotate
|
||||
rldclx, rldcrx, rldiclx, rldicrx, rldicx, rldimix, rlwimix, rlwinmx, rlwnmx,
|
||||
rldclx,
|
||||
rldcrx,
|
||||
rldiclx,
|
||||
rldicrx,
|
||||
rldicx,
|
||||
rldimix,
|
||||
rlwimix,
|
||||
rlwinmx,
|
||||
rlwnmx,
|
||||
// System call
|
||||
sc,
|
||||
// Shift
|
||||
sldx, slwx, sradix, sradx, srawix, srawx, srdx, srwx,
|
||||
sldx,
|
||||
slwx,
|
||||
sradix,
|
||||
sradx,
|
||||
srawix,
|
||||
srawx,
|
||||
srdx,
|
||||
srwx,
|
||||
// Store byte
|
||||
stb, stbu, stbux, stbx,
|
||||
stb,
|
||||
stbu,
|
||||
stbux,
|
||||
stbx,
|
||||
// Store doubleword
|
||||
std, stdbrx, stdcx, stdu, stdux, stdx,
|
||||
std,
|
||||
stdbrx,
|
||||
stdcx,
|
||||
stdu,
|
||||
stdux,
|
||||
stdx,
|
||||
// Store float
|
||||
stfd, stfdu, stfdux, stfdx, stfiwx, stfs, stfsu, stfsux, stfsx,
|
||||
stfd,
|
||||
stfdu,
|
||||
stfdux,
|
||||
stfdx,
|
||||
stfiwx,
|
||||
stfs,
|
||||
stfsu,
|
||||
stfsux,
|
||||
stfsx,
|
||||
// Store halfword
|
||||
sth, sthbrx, sthu, sthux, sthx,
|
||||
sth,
|
||||
sthbrx,
|
||||
sthu,
|
||||
sthux,
|
||||
sthx,
|
||||
// Store multiple/string
|
||||
stmw, stswi, stswx,
|
||||
stmw,
|
||||
stswi,
|
||||
stswx,
|
||||
// Store vector
|
||||
stvebx, stvehx, stvewx, stvewx128, stvlx, stvlx128, stvlxl, stvlxl128,
|
||||
stvrx, stvrx128, stvrxl, stvrxl128,
|
||||
stvx, stvx128, stvxl, stvxl128,
|
||||
stvebx,
|
||||
stvehx,
|
||||
stvewx,
|
||||
stvewx128,
|
||||
stvlx,
|
||||
stvlx128,
|
||||
stvlxl,
|
||||
stvlxl128,
|
||||
stvrx,
|
||||
stvrx128,
|
||||
stvrxl,
|
||||
stvrxl128,
|
||||
stvx,
|
||||
stvx128,
|
||||
stvxl,
|
||||
stvxl128,
|
||||
// Store word
|
||||
stw, stwbrx, stwcx, stwu, stwux, stwx,
|
||||
stw,
|
||||
stwbrx,
|
||||
stwcx,
|
||||
stwu,
|
||||
stwux,
|
||||
stwx,
|
||||
// Subtract
|
||||
subfcx, subfex, subficx, subfmex, subfx, subfzex,
|
||||
subfcx,
|
||||
subfex,
|
||||
subficx,
|
||||
subfmex,
|
||||
subfx,
|
||||
subfzex,
|
||||
// Sync
|
||||
sync,
|
||||
// Trap
|
||||
td, tdi, tw, twi,
|
||||
td,
|
||||
tdi,
|
||||
tw,
|
||||
twi,
|
||||
// VMX integer
|
||||
vaddcuw, vaddfp, vaddfp128, vaddsbs, vaddshs, vaddsws,
|
||||
vaddubm, vaddubs, vadduhm, vadduhs, vadduwm, vadduws,
|
||||
vand, vand128, vandc, vandc128,
|
||||
vavgsb, vavgsh, vavgsw, vavgub, vavguh, vavguw,
|
||||
vcfpsxws128, vcfpuxws128, vcfsx, vcfux,
|
||||
vcmpbfp, vcmpbfp128, vcmpeqfp, vcmpeqfp128,
|
||||
vcmpequb, vcmpequh, vcmpequw, vcmpequw128,
|
||||
vcmpgefp, vcmpgefp128, vcmpgtfp, vcmpgtfp128,
|
||||
vcmpgtsb, vcmpgtsh, vcmpgtsw, vcmpgtub, vcmpgtuh, vcmpgtuw,
|
||||
vcsxwfp128, vctsxs, vctuxs, vcuxwfp128,
|
||||
vexptefp, vexptefp128, vlogefp, vlogefp128,
|
||||
vmaddcfp128, vmaddfp, vmaddfp128,
|
||||
vmaxfp, vmaxfp128, vmaxsb, vmaxsh, vmaxsw, vmaxub, vmaxuh, vmaxuw,
|
||||
vmhaddshs, vmhraddshs,
|
||||
vminfp, vminfp128, vminsb, vminsh, vminsw, vminub, vminuh, vminuw,
|
||||
vaddcuw,
|
||||
vaddfp,
|
||||
vaddfp128,
|
||||
vaddsbs,
|
||||
vaddshs,
|
||||
vaddsws,
|
||||
vaddubm,
|
||||
vaddubs,
|
||||
vadduhm,
|
||||
vadduhs,
|
||||
vadduwm,
|
||||
vadduws,
|
||||
vand,
|
||||
vand128,
|
||||
vandc,
|
||||
vandc128,
|
||||
vavgsb,
|
||||
vavgsh,
|
||||
vavgsw,
|
||||
vavgub,
|
||||
vavguh,
|
||||
vavguw,
|
||||
vcfpsxws128,
|
||||
vcfpuxws128,
|
||||
vcfsx,
|
||||
vcfux,
|
||||
vcmpbfp,
|
||||
vcmpbfp128,
|
||||
vcmpeqfp,
|
||||
vcmpeqfp128,
|
||||
vcmpequb,
|
||||
vcmpequh,
|
||||
vcmpequw,
|
||||
vcmpequw128,
|
||||
vcmpgefp,
|
||||
vcmpgefp128,
|
||||
vcmpgtfp,
|
||||
vcmpgtfp128,
|
||||
vcmpgtsb,
|
||||
vcmpgtsh,
|
||||
vcmpgtsw,
|
||||
vcmpgtub,
|
||||
vcmpgtuh,
|
||||
vcmpgtuw,
|
||||
vcsxwfp128,
|
||||
vctsxs,
|
||||
vctuxs,
|
||||
vcuxwfp128,
|
||||
vexptefp,
|
||||
vexptefp128,
|
||||
vlogefp,
|
||||
vlogefp128,
|
||||
vmaddcfp128,
|
||||
vmaddfp,
|
||||
vmaddfp128,
|
||||
vmaxfp,
|
||||
vmaxfp128,
|
||||
vmaxsb,
|
||||
vmaxsh,
|
||||
vmaxsw,
|
||||
vmaxub,
|
||||
vmaxuh,
|
||||
vmaxuw,
|
||||
vmhaddshs,
|
||||
vmhraddshs,
|
||||
vminfp,
|
||||
vminfp128,
|
||||
vminsb,
|
||||
vminsh,
|
||||
vminsw,
|
||||
vminub,
|
||||
vminuh,
|
||||
vminuw,
|
||||
vmladduhm,
|
||||
vmrghb, vmrghh, vmrghw, vmrghw128, vmrglb, vmrglh, vmrglw, vmrglw128,
|
||||
vmsum3fp128, vmsum4fp128,
|
||||
vmsummbm, vmsumshm, vmsumshs, vmsumubm, vmsumuhm, vmsumuhs,
|
||||
vmulesb, vmulesh, vmuleub, vmuleuh, vmulfp128,
|
||||
vmulosb, vmulosh, vmuloub, vmulouh,
|
||||
vnmsubfp, vnmsubfp128, vnor, vnor128,
|
||||
vor, vor128,
|
||||
vperm, vperm128, vpermwi128, vpkd3d128,
|
||||
vpkpx, vpkshss, vpkshss128, vpkshus, vpkshus128,
|
||||
vpkswss, vpkswss128, vpkswus, vpkswus128,
|
||||
vpkuhum, vpkuhum128, vpkuhus, vpkuhus128,
|
||||
vpkuwum, vpkuwum128, vpkuwus, vpkuwus128,
|
||||
vrefp, vrefp128,
|
||||
vrfim, vrfim128, vrfin, vrfin128, vrfip, vrfip128, vrfiz, vrfiz128,
|
||||
vrlb, vrlh, vrlimi128, vrlw, vrlw128,
|
||||
vrsqrtefp, vrsqrtefp128,
|
||||
vsel, vsel128,
|
||||
vsl, vslb, vsldoi, vsldoi128, vslh, vslo, vslo128, vslw, vslw128,
|
||||
vspltb, vsplth, vspltisb, vspltish, vspltisw, vspltisw128, vspltw, vspltw128,
|
||||
vsr, vsrab, vsrah, vsraw, vsraw128, vsrb, vsrh, vsro, vsro128, vsrw, vsrw128,
|
||||
vsubcuw, vsubfp, vsubfp128, vsubsbs, vsubshs, vsubsws,
|
||||
vsububm, vsububs, vsubuhm, vsubuhs, vsubuwm, vsubuws,
|
||||
vsum2sws, vsum4sbs, vsum4shs, vsum4ubs, vsumsws,
|
||||
vupkd3d128, vupkhpx, vupkhsb, vupkhsb128, vupkhsh,
|
||||
vupklpx, vupklsb, vupklsb128, vupklsh,
|
||||
vxor, vxor128,
|
||||
vmrghb,
|
||||
vmrghh,
|
||||
vmrghw,
|
||||
vmrghw128,
|
||||
vmrglb,
|
||||
vmrglh,
|
||||
vmrglw,
|
||||
vmrglw128,
|
||||
vmsum3fp128,
|
||||
vmsum4fp128,
|
||||
vmsummbm,
|
||||
vmsumshm,
|
||||
vmsumshs,
|
||||
vmsumubm,
|
||||
vmsumuhm,
|
||||
vmsumuhs,
|
||||
vmulesb,
|
||||
vmulesh,
|
||||
vmuleub,
|
||||
vmuleuh,
|
||||
vmulfp128,
|
||||
vmulosb,
|
||||
vmulosh,
|
||||
vmuloub,
|
||||
vmulouh,
|
||||
vnmsubfp,
|
||||
vnmsubfp128,
|
||||
vnor,
|
||||
vnor128,
|
||||
vor,
|
||||
vor128,
|
||||
vperm,
|
||||
vperm128,
|
||||
vpermwi128,
|
||||
vpkd3d128,
|
||||
vpkpx,
|
||||
vpkshss,
|
||||
vpkshss128,
|
||||
vpkshus,
|
||||
vpkshus128,
|
||||
vpkswss,
|
||||
vpkswss128,
|
||||
vpkswus,
|
||||
vpkswus128,
|
||||
vpkuhum,
|
||||
vpkuhum128,
|
||||
vpkuhus,
|
||||
vpkuhus128,
|
||||
vpkuwum,
|
||||
vpkuwum128,
|
||||
vpkuwus,
|
||||
vpkuwus128,
|
||||
vrefp,
|
||||
vrefp128,
|
||||
vrfim,
|
||||
vrfim128,
|
||||
vrfin,
|
||||
vrfin128,
|
||||
vrfip,
|
||||
vrfip128,
|
||||
vrfiz,
|
||||
vrfiz128,
|
||||
vrlb,
|
||||
vrlh,
|
||||
vrlimi128,
|
||||
vrlw,
|
||||
vrlw128,
|
||||
vrsqrtefp,
|
||||
vrsqrtefp128,
|
||||
vsel,
|
||||
vsel128,
|
||||
vsl,
|
||||
vslb,
|
||||
vsldoi,
|
||||
vsldoi128,
|
||||
vslh,
|
||||
vslo,
|
||||
vslo128,
|
||||
vslw,
|
||||
vslw128,
|
||||
vspltb,
|
||||
vsplth,
|
||||
vspltisb,
|
||||
vspltish,
|
||||
vspltisw,
|
||||
vspltisw128,
|
||||
vspltw,
|
||||
vspltw128,
|
||||
vsr,
|
||||
vsrab,
|
||||
vsrah,
|
||||
vsraw,
|
||||
vsraw128,
|
||||
vsrb,
|
||||
vsrh,
|
||||
vsro,
|
||||
vsro128,
|
||||
vsrw,
|
||||
vsrw128,
|
||||
vsubcuw,
|
||||
vsubfp,
|
||||
vsubfp128,
|
||||
vsubsbs,
|
||||
vsubshs,
|
||||
vsubsws,
|
||||
vsububm,
|
||||
vsububs,
|
||||
vsubuhm,
|
||||
vsubuhs,
|
||||
vsubuwm,
|
||||
vsubuws,
|
||||
vsum2sws,
|
||||
vsum4sbs,
|
||||
vsum4shs,
|
||||
vsum4ubs,
|
||||
vsumsws,
|
||||
vupkd3d128,
|
||||
vupkhpx,
|
||||
vupkhsb,
|
||||
vupkhsb128,
|
||||
vupkhsh,
|
||||
vupklpx,
|
||||
vupklsb,
|
||||
vupklsb128,
|
||||
vupklsh,
|
||||
vxor,
|
||||
vxor128,
|
||||
// XOR immediate
|
||||
xori, xoris, xorx,
|
||||
xori,
|
||||
xoris,
|
||||
xorx,
|
||||
// Invalid
|
||||
Invalid,
|
||||
}
|
||||
@@ -165,42 +532,102 @@ impl PpcOpcode {
|
||||
pub fn terminates_block(&self) -> bool {
|
||||
matches!(
|
||||
self,
|
||||
Self::bx | Self::bcx | Self::bclrx | Self::bcctrx
|
||||
Self::bx
|
||||
| Self::bcx
|
||||
| Self::bclrx
|
||||
| Self::bcctrx
|
||||
| Self::sc
|
||||
| Self::td | Self::tdi | Self::tw | Self::twi
|
||||
| Self::td
|
||||
| Self::tdi
|
||||
| Self::tw
|
||||
| Self::twi
|
||||
| Self::Invalid
|
||||
)
|
||||
}
|
||||
|
||||
/// Returns true if this is a load instruction.
|
||||
pub fn is_load(&self) -> bool {
|
||||
matches!(self,
|
||||
Self::lbz | Self::lbzu | Self::lbzux | Self::lbzx |
|
||||
Self::lhz | Self::lhzu | Self::lhzux | Self::lhzx |
|
||||
Self::lha | Self::lhau | Self::lhaux | Self::lhax |
|
||||
Self::lwz | Self::lwzu | Self::lwzux | Self::lwzx |
|
||||
Self::lwa | Self::lwax | Self::lwaux |
|
||||
Self::ld | Self::ldu | Self::ldux | Self::ldx |
|
||||
Self::lfs | Self::lfsu | Self::lfsux | Self::lfsx |
|
||||
Self::lfd | Self::lfdu | Self::lfdux | Self::lfdx |
|
||||
Self::lhbrx | Self::lwbrx | Self::ldbrx |
|
||||
Self::lmw | Self::lswi | Self::lswx |
|
||||
Self::lwarx | Self::ldarx
|
||||
matches!(
|
||||
self,
|
||||
Self::lbz
|
||||
| Self::lbzu
|
||||
| Self::lbzux
|
||||
| Self::lbzx
|
||||
| Self::lhz
|
||||
| Self::lhzu
|
||||
| Self::lhzux
|
||||
| Self::lhzx
|
||||
| Self::lha
|
||||
| Self::lhau
|
||||
| Self::lhaux
|
||||
| Self::lhax
|
||||
| Self::lwz
|
||||
| Self::lwzu
|
||||
| Self::lwzux
|
||||
| Self::lwzx
|
||||
| Self::lwa
|
||||
| Self::lwax
|
||||
| Self::lwaux
|
||||
| Self::ld
|
||||
| Self::ldu
|
||||
| Self::ldux
|
||||
| Self::ldx
|
||||
| Self::lfs
|
||||
| Self::lfsu
|
||||
| Self::lfsux
|
||||
| Self::lfsx
|
||||
| Self::lfd
|
||||
| Self::lfdu
|
||||
| Self::lfdux
|
||||
| Self::lfdx
|
||||
| Self::lhbrx
|
||||
| Self::lwbrx
|
||||
| Self::ldbrx
|
||||
| Self::lmw
|
||||
| Self::lswi
|
||||
| Self::lswx
|
||||
| Self::lwarx
|
||||
| Self::ldarx
|
||||
)
|
||||
}
|
||||
|
||||
/// Returns true if this is a store instruction.
|
||||
pub fn is_store(&self) -> bool {
|
||||
matches!(self,
|
||||
Self::stb | Self::stbu | Self::stbux | Self::stbx |
|
||||
Self::sth | Self::sthu | Self::sthux | Self::sthx |
|
||||
Self::stw | Self::stwu | Self::stwux | Self::stwx |
|
||||
Self::std | Self::stdu | Self::stdux | Self::stdx |
|
||||
Self::stfs | Self::stfsu | Self::stfsux | Self::stfsx |
|
||||
Self::stfd | Self::stfdu | Self::stfdux | Self::stfdx |
|
||||
Self::sthbrx | Self::stwbrx | Self::stdbrx |
|
||||
Self::stmw | Self::stswi | Self::stswx |
|
||||
Self::stwcx | Self::stdcx | Self::stfiwx
|
||||
matches!(
|
||||
self,
|
||||
Self::stb
|
||||
| Self::stbu
|
||||
| Self::stbux
|
||||
| Self::stbx
|
||||
| Self::sth
|
||||
| Self::sthu
|
||||
| Self::sthux
|
||||
| Self::sthx
|
||||
| Self::stw
|
||||
| Self::stwu
|
||||
| Self::stwux
|
||||
| Self::stwx
|
||||
| Self::std
|
||||
| Self::stdu
|
||||
| Self::stdux
|
||||
| Self::stdx
|
||||
| Self::stfs
|
||||
| Self::stfsu
|
||||
| Self::stfsux
|
||||
| Self::stfsx
|
||||
| Self::stfd
|
||||
| Self::stfdu
|
||||
| Self::stfdux
|
||||
| Self::stfdx
|
||||
| Self::sthbrx
|
||||
| Self::stwbrx
|
||||
| Self::stdbrx
|
||||
| Self::stmw
|
||||
| Self::stswi
|
||||
| Self::stswx
|
||||
| Self::stwcx
|
||||
| Self::stdcx
|
||||
| Self::stfiwx
|
||||
)
|
||||
}
|
||||
|
||||
@@ -227,8 +654,13 @@ impl PpcOpcode {
|
||||
pub fn is_sync_sensitive(&self) -> bool {
|
||||
matches!(
|
||||
self,
|
||||
Self::lwarx | Self::ldarx | Self::stwcx | Self::stdcx
|
||||
| Self::sync | Self::eieio | Self::isync
|
||||
Self::lwarx
|
||||
| Self::ldarx
|
||||
| Self::stwcx
|
||||
| Self::stdcx
|
||||
| Self::sync
|
||||
| Self::eieio
|
||||
| Self::isync
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user