From 1de202d88d391cdc9a9be366552c9e5272227e94 Mon Sep 17 00:00:00 2001 From: MechaCat02 Date: Sun, 13 Sep 2026 20:43:48 +0200 Subject: [PATCH] test(ppc): bring the disassembler's golden fixtures across Three tests failed on the extracted tree for a reason that was not a port defect: disasm_goldens.rs resolves its fixtures through a relative path to xenia-cpu/tests/golden/, and I had copied the test without the data. The fixtures (base + extended mnemonics, VMX128 registers) and the generator test now live in sylpheed-ppc, and the shim test in sylpheed-xexdb points at them. serde/serde_json become dev-dependencies of sylpheed-ppc, which the fixtures need and the library does not. Co-Authored-By: Claude Opus 5 --- Cargo.lock | 2 + crates/sylpheed-ppc/Cargo.toml | 4 + crates/sylpheed-ppc/tests/disasm_goldens.rs | 841 ++++++++++++++++++ .../tests/golden/base_mnemonics.json | 571 ++++++++++++ .../tests/golden/extended_mnemonics.json | 623 +++++++++++++ .../tests/golden/vmx128_registers.json | 137 +++ crates/sylpheed-xexdb/tests/disasm_goldens.rs | 4 +- 7 files changed, 2180 insertions(+), 2 deletions(-) create mode 100644 crates/sylpheed-ppc/tests/disasm_goldens.rs create mode 100644 crates/sylpheed-ppc/tests/golden/base_mnemonics.json create mode 100644 crates/sylpheed-ppc/tests/golden/extended_mnemonics.json create mode 100644 crates/sylpheed-ppc/tests/golden/vmx128_registers.json diff --git a/Cargo.lock b/Cargo.lock index 7bbf4e61..d988c25c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5258,6 +5258,8 @@ name = "sylpheed-ppc" version = "0.1.0" dependencies = [ "bitflags 2.11.0", + "serde", + "serde_json", "thiserror 1.0.69", "tracing", ] diff --git a/crates/sylpheed-ppc/Cargo.toml b/crates/sylpheed-ppc/Cargo.toml index bdf7992c..644eb1ba 100644 --- a/crates/sylpheed-ppc/Cargo.toml +++ b/crates/sylpheed-ppc/Cargo.toml @@ -8,3 +8,7 @@ description = "PowerPC decode and disassembly, for static analysis" tracing = "0.1" bitflags = "2" thiserror = "1" + +[dev-dependencies] +serde = { version = "1", features = ["derive"] } +serde_json = "1" diff --git a/crates/sylpheed-ppc/tests/disasm_goldens.rs b/crates/sylpheed-ppc/tests/disasm_goldens.rs new file mode 100644 index 00000000..e010c382 --- /dev/null +++ b/crates/sylpheed-ppc/tests/disasm_goldens.rs @@ -0,0 +1,841 @@ +//! Assert-based goldens for the PPC disassembler. +//! +//! Each test owns an inline list of `(raw, addr, label)` cases. On a +//! normal run, the test reads the corresponding fixture JSON and asserts +//! that `format(decode(raw, addr))` reproduces every field exactly. On +//! first creation (fixture file missing) or with `REGEN_GOLDENS=1` set, +//! the test (re)writes the fixture from `format()` output. +//! +//! Workflow: +//! ```sh +//! cargo test -p sylpheed-ppc --test disasm_goldens # assert +//! REGEN_GOLDENS=1 cargo test -p sylpheed-ppc --test disasm_goldens # regen +//! ``` +//! +//! The hand-encoded test cases below cover the silent-bug regression +//! cases that lived in the old println-based `disasm_audit.rs` harness +//! (now deleted). + +use std::path::PathBuf; + +use serde::{Deserialize, Serialize}; + +use sylpheed_ppc::decoder::{DecodedInstr, decode}; +use sylpheed_ppc::disasm::format; + +#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)] +struct GoldenRow { + label: String, + raw: String, + addr: String, + mnemonic: String, + operands: String, + #[serde(default, skip_serializing_if = "Option::is_none")] + ext_mnemonic: Option, + #[serde(default, skip_serializing_if = "Option::is_none")] + ext_operands: Option, + #[serde(default, skip_serializing_if = "Option::is_none")] + branch_target: Option, +} + +#[derive(Debug, Deserialize, Serialize)] +struct GoldenFile { + rows: Vec, +} + +fn fixture_path(name: &str) -> PathBuf { + PathBuf::from(env!("CARGO_MANIFEST_DIR")) + .join("tests") + .join("golden") + .join(name) +} + +/// Encode a VMX128 VX128-form (or VX128_R/_2) instruction with canary's +/// 7-bit register layout: VD low at PPC 6-10, high 2 bits at PPC 28-29; +/// VA low at PPC 11-15, mid bit at PPC 26, high bit at PPC 21; VB low at +/// PPC 16-20, high 2 bits at PPC 30-31. `secondary_bits` carries any +/// secondary opcode + VC + Rc + key bits the caller needs. +fn encode_vx128(op6: u32, vd: u32, va: u32, vb: u32, secondary_bits: u32) -> u32 { + ((op6 & 0x3F) << 26) + | ((vd & 0x1F) << 21) + | (((vd >> 5) & 0x3) << 2) + | ((va & 0x1F) << 16) + | (((va >> 5) & 0x1) << 5) + | (((va >> 6) & 0x1) << 10) + | ((vb & 0x1F) << 11) + | (((vb >> 5) & 0x3) << 0) + | secondary_bits +} + +fn build_rows(cases: &[(u32, u32, &str)]) -> Vec { + cases + .iter() + .map(|&(raw, addr, label)| { + let d = decode(raw, addr); + let t = format(&d); + GoldenRow { + label: label.to_string(), + raw: format!("0x{raw:08X}"), + addr: format!("0x{addr:08X}"), + mnemonic: t.mnemonic, + operands: t.operands, + ext_mnemonic: t.ext_mnemonic, + ext_operands: t.ext_operands, + branch_target: t.branch_target.map(|t| format!("0x{t:08X}")), + } + }) + .collect() +} + +/// Compare what `format()` produces against the committed JSON snapshot. +/// Set `REGEN_GOLDENS=1` to overwrite the snapshot from current output. +/// Missing snapshot is treated as "first creation": writes and panics so +/// CI can't accidentally accept blank goldens. +fn assert_or_regen(fixture_name: &str, cases: &[(u32, u32, &str)]) { + let rows = build_rows(cases); + let path = fixture_path(fixture_name); + let regen = std::env::var("REGEN_GOLDENS").is_ok(); + + if regen || !path.exists() { + if let Some(parent) = path.parent() { + std::fs::create_dir_all(parent).unwrap(); + } + let serialized = serde_json::to_string_pretty(&GoldenFile { rows }).unwrap(); + std::fs::write(&path, serialized + "\n").unwrap(); + if !regen { + panic!( + "Generated fixture {} (was missing). Inspect, commit, then re-run.", + path.display() + ); + } + return; + } + + let src = std::fs::read_to_string(&path).unwrap(); + let golden: GoldenFile = serde_json::from_str(&src).unwrap(); + assert_eq!( + rows.len(), + golden.rows.len(), + "row count differs from {} (live={}, fixture={}). Run with REGEN_GOLDENS=1 if the test cases changed intentionally.", + path.display(), + rows.len(), + golden.rows.len() + ); + for (i, (got, expected)) in rows.iter().zip(golden.rows.iter()).enumerate() { + assert_eq!( + got, + expected, + "row {} ({}) differs in {}\n live: {got:#?}\n fixture: {expected:#?}", + i, + expected.label, + path.display() + ); + } +} + +// ── Encoding helpers ──────────────────────────────────────────────────────── +// PPC bit numbering: bit 0 is MSB, bit 31 is LSB. Most helpers below emit +// instructions in canonical hand-readable form: opcode << 26 | . + +#[allow(clippy::too_many_arguments)] +fn xform_xo3(rd: u32, ra: u32, rb: u32, oe: u32, xo: u32, rc: u32) -> u32 { + (31 << 26) | (rd << 21) | (ra << 16) | (rb << 11) | (oe << 10) | (xo << 1) | rc +} + +fn xform_logic(rs: u32, ra: u32, rb: u32, xo: u32, rc: u32) -> u32 { + (31 << 26) | (rs << 21) | (ra << 16) | (rb << 11) | (xo << 1) | rc +} + +fn dform(op: u32, rt: u32, ra: u32, imm: i16) -> u32 { + (op << 26) | (rt << 21) | (ra << 16) | ((imm as u16) as u32) +} + +fn iform_b(target_disp: i32, aa: u32, lk: u32) -> u32 { + // I-form: opcode 18 | LI<<2 | AA<<1 | LK + let li = (target_disp as u32) & 0x03FF_FFFC; + (18 << 26) | li | (aa << 1) | lk +} + +fn bform_bc(bo: u32, bi: u32, target_disp: i32, aa: u32, lk: u32) -> u32 { + // B-form: opcode 16 | BO<<21 | BI<<16 | BD<<2 | AA<<1 | LK + let bd = (target_disp as u32) & 0x0000_FFFC; + (16 << 26) | (bo << 21) | (bi << 16) | bd | (aa << 1) | lk +} + +fn xlform_bclr(bo: u32, bi: u32, lk: u32) -> u32 { + // XL-form: opcode 19 | BO<<21 | BI<<16 | XO=16<<1 | LK + (19 << 26) | (bo << 21) | (bi << 16) | (16 << 1) | lk +} + +fn xlform_bcctr(bo: u32, bi: u32, lk: u32) -> u32 { + (19 << 26) | (bo << 21) | (bi << 16) | (528 << 1) | lk +} + +fn rlwinm(rs: u32, ra: u32, sh: u32, mb: u32, me: u32, rc: u32) -> u32 { + (21 << 26) | (rs << 21) | (ra << 16) | (sh << 11) | (mb << 6) | (me << 1) | rc +} + +fn rldicl(rs: u32, ra: u32, sh: u32, mb: u32, rc: u32) -> u32 { + // MD-form: sh[4:0] at PPC bits 16-20 (host bits 11-15); sh[5] at PPC bit 30 (host bit 1). + // mb[4:0] at PPC bits 21-25 (host bits 6-10); mb[5] at PPC bit 26 (host bit 5). + let sh_lo = sh & 0x1F; + let sh_hi = (sh >> 5) & 1; + let mb_lo = mb & 0x1F; + let mb_hi = (mb >> 5) & 1; + (30 << 26) + | (rs << 21) + | (ra << 16) + | (sh_lo << 11) + | (mb_lo << 6) + | (mb_hi << 5) + | (0 << 2) + | (sh_hi << 1) + | rc +} + +fn mfspr(rd: u32, spr: u32) -> u32 { + let spr_swapped = ((spr & 0x1F) << 5) | ((spr >> 5) & 0x1F); + (31 << 26) | (rd << 21) | (spr_swapped << 11) | (339 << 1) +} + +fn mtspr(rs: u32, spr: u32) -> u32 { + let spr_swapped = ((spr & 0x1F) << 5) | ((spr >> 5) & 0x1F); + (31 << 26) | (rs << 21) | (spr_swapped << 11) | (467 << 1) +} + +// ── Tests ─────────────────────────────────────────────────────────────────── + +#[test] +fn base_mnemonics() { + let cases: &[(u32, u32, &str)] = &[ + // X-form ALU (Rc and OE bits) + (xform_xo3(3, 4, 5, 0, 266, 0), 0x82000000, "add r3,r4,r5"), + (xform_xo3(3, 4, 5, 0, 266, 1), 0x82000000, "add. r3,r4,r5"), + (xform_xo3(3, 4, 5, 1, 266, 0), 0x82000000, "addo r3,r4,r5"), + (xform_xo3(3, 4, 5, 1, 266, 1), 0x82000000, "addo. r3,r4,r5"), + (xform_xo3(3, 4, 0, 0, 104, 0), 0x82000000, "neg r3,r4"), + (xform_xo3(3, 4, 5, 0, 235, 0), 0x82000000, "mullw r3,r4,r5"), + (xform_xo3(3, 4, 5, 0, 491, 0), 0x82000000, "divw r3,r4,r5"), + (xform_xo3(3, 4, 5, 0, 75, 1), 0x82000000, "mulhw. r3,r4,r5"), + (xform_xo3(3, 4, 5, 0, 11, 1), 0x82000000, "mulhwu. r3,r4,r5"), + (xform_xo3(3, 4, 5, 0, 233, 0), 0x82000000, "mulld r3,r4,r5"), + // X-form logical + (xform_logic(4, 3, 5, 28, 0), 0x82000000, "and r3,r4,r5"), + ( + xform_logic(4, 3, 5, 444, 0), + 0x82000000, + "or r3,r4,r5 (non-mr: rs!=rb)", + ), + (xform_logic(4, 3, 5, 316, 0), 0x82000000, "xor r3,r4,r5"), + (xform_logic(4, 3, 5, 124, 0), 0x82000000, "nor r3,r4,r5"), + (xform_logic(4, 3, 5, 476, 0), 0x82000000, "nand r3,r4,r5"), + (xform_logic(4, 3, 5, 284, 0), 0x82000000, "eqv r3,r4,r5"), + (xform_logic(4, 3, 5, 60, 0), 0x82000000, "andc r3,r4,r5"), + (xform_logic(4, 3, 5, 412, 0), 0x82000000, "orc r3,r4,r5"), + // X-form shift + (xform_logic(4, 3, 5, 24, 0), 0x82000000, "slw r3,r4,r5"), + (xform_logic(4, 3, 5, 536, 0), 0x82000000, "srw r3,r4,r5"), + (xform_logic(4, 3, 5, 792, 0), 0x82000000, "sraw r3,r4,r5"), + (xform_logic(4, 3, 5, 27, 0), 0x82000000, "sld r3,r4,r5"), + (xform_logic(4, 3, 5, 539, 0), 0x82000000, "srd r3,r4,r5"), + // srawi / sradi (immediate shifts) + ( + (31 << 26) | (4 << 21) | (3 << 16) | (16 << 11) | (824 << 1), + 0x82000000, + "srawi r3,r4,16", + ), + // Atomics + ( + (31 << 26) | (3 << 21) | (4 << 16) | (5 << 11) | (150 << 1) | 1, + 0x82000000, + "stwcx. r3,r4,r5", + ), + ( + (31 << 26) | (3 << 21) | (4 << 16) | (5 << 11) | (214 << 1) | 1, + 0x82000000, + "stdcx. r3,r4,r5", + ), + ( + (31 << 26) | (3 << 21) | (4 << 16) | (5 << 11) | (20 << 1), + 0x82000000, + "lwarx r3,r4,r5", + ), + ( + (31 << 26) | (3 << 21) | (4 << 16) | (5 << 11) | (84 << 1), + 0x82000000, + "ldarx r3,r4,r5", + ), + // Compares + (dform(11, 0, 3, 16), 0x82000000, "cmpwi cr0, r3, 16"), + (dform(11, 2 << 2, 3, 16), 0x82000000, "cmpwi cr2, r3, 16"), + (dform(10, 0, 3, 16), 0x82000000, "cmplwi cr0, r3, 16"), + ( + (31 << 26) | (3 << 16) | (4 << 11), + 0x82000000, + "cmpw r3,r4 in cr0", + ), + ( + (31 << 26) | (1 << 21) | (3 << 16) | (4 << 11), + 0x82000000, + "cmpd r3,r4", + ), + ( + (31 << 26) | (3 << 16) | (4 << 11) | (32 << 1), + 0x82000000, + "cmplw r3,r4", + ), + // D-form ALU/load/store + (dform(14, 3, 1, 16), 0x82000000, "addi r3, r1, 16"), + ( + dform(15, 3, 1, 0x100), + 0x82000000, + "addis r3, r1, 0x100 (ra!=0)", + ), + (dform(7, 3, 4, 5), 0x82000000, "mulli r3, r4, 5"), + (dform(8, 3, 4, 5), 0x82000000, "subfic r3, r4, 5"), + (dform(12, 3, 4, 16), 0x82000000, "addic r3, r4, 16"), + (dform(13, 3, 4, 16), 0x82000000, "addic. r3, r4, 16"), + ( + dform(24, 3, 4, 0x10), + 0x82000000, + "ori r4, r3, 0x10 (non-nop)", + ), + (dform(25, 3, 4, 0x10), 0x82000000, "oris r4, r3, 0x10"), + (dform(26, 3, 4, 0x10), 0x82000000, "xori r4, r3, 0x10"), + (dform(28, 3, 4, 0x10), 0x82000000, "andi. r4, r3, 0x10"), + // Loads/stores D-form + (dform(32, 5, 1, 0x20), 0x82000000, "lwz r5, 0x20(r1)"), + (dform(36, 5, 1, 0x20), 0x82000000, "stw r5, 0x20(r1)"), + (dform(34, 5, 1, 0x20), 0x82000000, "lbz r5, 0x20(r1)"), + (dform(40, 5, 1, 0x20), 0x82000000, "lhz r5, 0x20(r1)"), + (dform(48, 5, 1, 0x20), 0x82000000, "lfs f5, 0x20(r1)"), + (dform(50, 5, 1, 0x20), 0x82000000, "lfd f5, 0x20(r1)"), + (dform(54, 5, 1, 0x20), 0x82000000, "stfd f5, 0x20(r1)"), + // DS-form 64-bit loads + ( + (58u32 << 26) | (5 << 21) | (1 << 16) | 0x20, + 0x82000000, + "ld r5, 0x20(r1)", + ), + ( + (62u32 << 26) | (5 << 21) | (1 << 16) | 0x20, + 0x82000000, + "std r5, 0x20(r1)", + ), + // Sync / barrier (parameterless) + ( + (31 << 26) | (598 << 1), + 0x82000000, + "sync 0 (extends to sync)", + ), + ((19 << 26) | (150 << 1), 0x82000000, "isync"), + ((31 << 26) | (854 << 1), 0x82000000, "eieio"), + // Cache hints + ( + (31 << 26) | (1 << 16) | (2 << 11) | (54 << 1), + 0x82000000, + "dcbst r1, r2", + ), + ( + (31 << 26) | (1 << 16) | (2 << 11) | (86 << 1), + 0x82000000, + "dcbf r1, r2", + ), + ( + (31 << 26) | (1 << 16) | (2 << 11) | (278 << 1), + 0x82000000, + "dcbt r1, r2", + ), + ( + (31 << 26) | (1 << 16) | (2 << 11) | (1014 << 1), + 0x82000000, + "dcbz r1, r2", + ), + ( + (31 << 26) | (1 << 21) | (1 << 16) | (2 << 11) | (1014 << 1), + 0x82000000, + "dcbz128 r1, r2", + ), + // CR logical (without simplification triggers) + ( + (19 << 26) | (4 << 21) | (5 << 16) | (6 << 11) | (33 << 1), + 0x82000000, + "crnor 4,5,6 (no simplify)", + ), + ( + (19 << 26) | (4 << 21) | (5 << 16) | (6 << 11) | (257 << 1), + 0x82000000, + "crand 4,5,6", + ), + ( + (19 << 26) | (4 << 21) | (5 << 16) | (6 << 11) | (449 << 1), + 0x82000000, + "cror 4,5,6 (no simplify)", + ), + // Trap (no simplification: TO=11 doesn't match the table) + ( + (31 << 26) | (11 << 21) | (3 << 16) | (4 << 11) | (4 << 1), + 0x82000000, + "tw 11, r3, r4 (uncommon TO)", + ), + ( + (2u32 << 26) | (11 << 21) | (3 << 16) | (123u32 & 0xFFFF), + 0x82000000, + "tdi 11, r3, 123", + ), + // mtcr (extended): mtcrf 0xFF, r5 + ( + (31 << 26) | (5 << 21) | (0xFF << 12) | (144 << 1), + 0x82000000, + "mtcrf 0xFF, r5 → mtcr", + ), + // mfcr / mfmsr / mtmsr / mtmsrd + ((31 << 26) | (5 << 21) | (19 << 1), 0x82000000, "mfcr r5"), + ((31 << 26) | (5 << 21) | (83 << 1), 0x82000000, "mfmsr r5"), + ((31 << 26) | (5 << 21) | (146 << 1), 0x82000000, "mtmsr r5"), + ((31 << 26) | (5 << 21) | (178 << 1), 0x82000000, "mtmsrd r5"), + // FPU base + ( + (63u32 << 26) | (3 << 21) | (4 << 16) | (5 << 11) | (21 << 1), + 0x82000000, + "fadd f3, f4, f5", + ), + ( + (63u32 << 26) | (3 << 21) | (4 << 16) | (5 << 11) | (20 << 1), + 0x82000000, + "fsub f3, f4, f5", + ), + ( + (63u32 << 26) | (3 << 21) | (4 << 16) | (5 << 11) | (18 << 1), + 0x82000000, + "fdiv f3, f4, f5", + ), + ( + (63u32 << 26) | (3 << 21) | (5 << 21) | (5 << 11) | (25 << 1), + 0x82000000, + "fmul f3, f0, f5 (encoded)", + ), + ( + (63u32 << 26) | (3 << 21) | (4 << 16) | (40 << 1), + 0x82000000, + "fneg f3, f4", + ), + ( + (63u32 << 26) | (3 << 21) | (4 << 16) | (72 << 1), + 0x82000000, + "fmr f3, f4", + ), + // mtfsf — XFL form (Fix 1). FM at LSB bits 17-24 (PPC bits 7-14). + // Encoding: opcode 63 | FM<<17 | frB<<11 | XO=711<<1 | Rc. + ( + (63u32 << 26) | (0xFF << 17) | (5 << 11) | (711 << 1), + 0x82000000, + "mtfsf 0xFF, f5 (Rc=0)", + ), + ( + (63u32 << 26) | (0xFF << 17) | (5 << 11) | (711 << 1) | 1, + 0x82000000, + "mtfsf. 0xFF, f5 (Rc=1)", + ), + ]; + assert_or_regen("base_mnemonics.json", cases); +} + +#[test] +fn extended_mnemonics() { + let cases: &[(u32, u32, &str)] = &[ + // ori r0, r0, 0 → nop + (dform(24, 0, 0, 0), 0x82000000, "nop"), + // addi r3, r0, imm → li + (dform(14, 3, 0, 16), 0x82000000, "li r3, 16"), + (dform(14, 3, 0, -1), 0x82000000, "li r3, -1"), + // addi r3, r4, neg → subi + (dform(14, 3, 4, -16), 0x82000000, "subi r3, r4, 16"), + // addis r3, r0, imm → lis + (dform(15, 3, 0, 0x1234), 0x82000000, "lis r3, 0x1234"), + // addis r3, r4, neg → subis + (dform(15, 3, 4, -1), 0x82000000, "subis r3, r4, 0xFFFF"), + // or rA, rS, rS → mr + (xform_logic(4, 3, 4, 444, 0), 0x82000000, "mr r3, r4"), + (xform_logic(4, 3, 4, 444, 1), 0x82000000, "mr. r3, r4"), + // and rA, rS, rS → mr (also) + (xform_logic(4, 3, 4, 28, 0), 0x82000000, "mr (via and)"), + // nor rA, rS, rS → not + (xform_logic(4, 3, 4, 124, 0), 0x82000000, "not r3, r4"), + // subf → sub (operand swap) + ( + xform_xo3(3, 4, 5, 0, 40, 0), + 0x82000000, + "subf → sub r3, r5, r4", + ), + // rlwinm simplifications + (rlwinm(4, 3, 4, 0, 31 - 4, 0), 0x82000000, "slwi r3, r4, 4"), + (rlwinm(4, 3, 32 - 4, 4, 31, 0), 0x82000000, "srwi r3, r4, 4"), + (rlwinm(4, 3, 8, 0, 31, 0), 0x82000000, "rotlwi r3, r4, 8"), + (rlwinm(4, 3, 0, 4, 31, 0), 0x82000000, "clrlwi r3, r4, 4"), + (rlwinm(4, 3, 0, 0, 27, 0), 0x82000000, "clrrwi r3, r4, 4"), + (rlwinm(4, 3, 8, 0, 7, 0), 0x82000000, "extlwi r3, r4, 8, 8"), + // rlwinm with Rc + (rlwinm(4, 3, 4, 0, 31 - 4, 1), 0x82000000, "slwi. r3, r4, 4"), + // rlwinm Sylpheed regression + ( + rlwinm(11, 11, 0, 31, 31, 1), + 0x82000000, + "rlwinm. r11,r11,0,31,31 (no simplify)", + ), + // rldicl simplifications + (rldicl(4, 3, 0, 32, 0), 0x82000000, "clrldi r3, r4, 32"), + (rldicl(4, 3, 64u32 - 8, 8, 0), 0x82000000, "srdi r3, r4, 8"), + (rldicl(4, 3, 8, 0, 0), 0x82000000, "rotldi r3, r4, 8"), + // cmpi / cmpli → cmpwi/cmpdi/cmplwi/cmpldi + (dform(11, 0, 3, 16), 0x82000000, "cmpwi cr0, r3, 16"), + ( + dform(11, (1 << 21) | (2 << 23), 3, 16) | (1 << 21), + 0x82000000, + "cmpdi (L=1) variant", + ), + // bclr 20, 0 → blr + (xlform_bclr(20, 0, 0), 0x82000000, "blr"), + (xlform_bclr(20, 0, 1), 0x82000000, "blrl"), + // bcctr 20, 0 → bctr + (xlform_bcctr(20, 0, 0), 0x82000000, "bctr"), + (xlform_bcctr(20, 0, 1), 0x82000000, "bctrl"), + // bclr conditional + ( + xlform_bclr(12, 2, 0), + 0x82000000, + "beqlr (BO=12, BI=2 → cr0.eq true)", + ), + (xlform_bclr(4, 2, 0), 0x82000000, "bnelr"), + // bc with full BO/BI: branch always (BO=20) + (bform_bc(20, 0, 0x40, 0, 0), 0x82000000, "bc → b 0x82000040"), + ( + bform_bc(20, 0, 0x40, 0, 1), + 0x82000000, + "bc l → bl 0x82000040", + ), + // Conditional bc → beq/bne/etc + ( + bform_bc(12, 2, 0x40, 0, 0), + 0x82000000, + "bc 12,cr0.eq → beq 0x82000040", + ), + ( + bform_bc(4, 2, 0x40, 0, 0), + 0x82000000, + "bc 4,cr0.eq → bne 0x82000040", + ), + ( + bform_bc(12, 0, 0x40, 0, 0), + 0x82000000, + "bc 12,cr0.lt → blt 0x82000040", + ), + ( + bform_bc(4, 0, 0x40, 0, 0), + 0x82000000, + "bc 4,cr0.lt → bge 0x82000040", + ), + ( + bform_bc(12, 1, 0x40, 0, 0), + 0x82000000, + "bc 12,cr0.gt → bgt 0x82000040", + ), + ( + bform_bc(4, 1, 0x40, 0, 0), + 0x82000000, + "bc 4,cr0.gt → ble 0x82000040", + ), + // Conditional with non-zero CR field + ( + bform_bc(12, 2 + 8, 0x40, 0, 0), + 0x82000000, + "bc 12, cr2.eq → beq cr2, 0x...040", + ), + // bdnz / bdz (decrement-CTR branches) + (bform_bc(16, 0, 0x40, 0, 0), 0x82000000, "bdnz 0x82000040"), + (bform_bc(18, 0, 0x40, 0, 0), 0x82000000, "bdz 0x82000040"), + // I-form branches + (iform_b(0x40, 0, 0), 0x82000000, "b +0x40 → 0x82000040"), + (iform_b(0x40, 0, 1), 0x82000000, "bl +0x40 → 0x82000040"), + (iform_b(0x40, 1, 0), 0x82000000, "ba 0x40 absolute"), + (iform_b(0x40, 1, 1), 0x82000000, "bla 0x40 absolute"), + // Trap immediate simplifications + ( + (2u32 << 26) | (4 << 21) | (3 << 16) | (123u32 & 0xFFFF), + 0x82000000, + "tdeqi r3, 123", + ), + ( + (3u32 << 26) | (16 << 21) | (3 << 16) | (123u32 & 0xFFFF), + 0x82000000, + "twlti r3, 123", + ), + // mfspr → mflr / mfctr / mfxer + (mfspr(3, 8), 0x82000000, "mflr r3"), + (mfspr(3, 9), 0x82000000, "mfctr r3"), + (mfspr(3, 1), 0x82000000, "mfxer r3"), + // mtspr → mtlr / mtctr / mtxer + (mtspr(3, 8), 0x82000000, "mtlr r3"), + (mtspr(3, 9), 0x82000000, "mtctr r3"), + (mtspr(3, 1), 0x82000000, "mtxer r3"), + // crnor with same source bits → crnot + ( + (19 << 26) | (4 << 21) | (5 << 16) | (5 << 11) | (33 << 1), + 0x82000000, + "crnot 4, 5", + ), + // crxor with all same → crclr + ( + (19 << 26) | (4 << 21) | (4 << 16) | (4 << 11) | (193 << 1), + 0x82000000, + "crclr 4", + ), + // creqv with all same → crset + ( + (19 << 26) | (4 << 21) | (4 << 16) | (4 << 11) | (289 << 1), + 0x82000000, + "crset 4", + ), + // cror with same source bits → crmove + ( + (19 << 26) | (4 << 21) | (5 << 16) | (5 << 11) | (449 << 1), + 0x82000000, + "crmove 4, 5", + ), + // sync L=1 → lwsync + ((31 << 26) | (1 << 21) | (598 << 1), 0x82000000, "lwsync"), + // tw 31, 0, 0 → trap + ((31 << 26) | (31 << 21) | (4 << 1), 0x82000000, "trap"), + // Fix 2: bclr/bcctr with BO=20 and BI≠0 still emits blr/bctr ext. + // BO=20 ignores both CTR test and CR test, so BI is don't-care. + ( + xlform_bclr(20, 4, 0), + 0x82000000, + "blr (BO=20, BI=4 — BI is don't-care)", + ), + (xlform_bclr(20, 7, 1), 0x82000000, "blrl (BO=20, BI=7)"), + (xlform_bcctr(20, 4, 0), 0x82000000, "bctr (BO=20, BI=4)"), + // Fix 3: trap unsigned simplified mnemonics (TO=1, 2, 5, 6 — logical + // compare conditions). Register form (tw/td) and immediate (twi/tdi). + ( + (31u32 << 26) | (2 << 21) | (3 << 16) | (4 << 11) | (4 << 1), + 0x82000000, + "twllt r3, r4 (TO=2)", + ), + ( + (31u32 << 26) | (1 << 21) | (3 << 16) | (4 << 11) | (4 << 1), + 0x82000000, + "twlgt r3, r4 (TO=1)", + ), + ( + (31u32 << 26) | (5 << 21) | (3 << 16) | (4 << 11) | (68 << 1), + 0x82000000, + "tdlge r3, r4 (TO=5)", + ), + ( + (31u32 << 26) | (6 << 21) | (3 << 16) | (4 << 11) | (4 << 1), + 0x82000000, + "twlle r3, r4 (TO=6)", + ), + ( + (3u32 << 26) | (2 << 21) | (3 << 16) | (16u32 & 0xFFFF), + 0x82000000, + "twllti r3, 16", + ), + ( + (2u32 << 26) | (5 << 21) | (3 << 16) | (16u32 & 0xFFFF), + 0x82000000, + "tdlgei r3, 16", + ), + ]; + assert_or_regen("extended_mnemonics.json", cases); +} + +#[test] +fn vmx128_registers() { + // Standard VMX (op=4) — 5-bit registers v0..v31. Verifies that the + // low-register path renders correctly through the new formatter. + let std_vmx = [ + // vaddubm v3, v4, v5 : op=4, 3-op key=0 + ( + (4u32 << 26) | (3 << 21) | (4 << 16) | (5 << 11) | 0, + 0x82000000, + "vaddubm v3, v4, v5", + ), + // vaddfp v3, v4, v5 : op=4, vx=10 + ( + (4u32 << 26) | (3 << 21) | (4 << 16) | (5 << 11) | 10, + 0x82000000, + "vaddfp v3, v4, v5", + ), + // vand v3, v4, v5 : vx=1028 + ( + (4u32 << 26) | (3 << 21) | (4 << 16) | (5 << 11) | 1028, + 0x82000000, + "vand v3, v4, v5", + ), + // vor v3, v4, v5 : vx=1156 + ( + (4u32 << 26) | (3 << 21) | (4 << 16) | (5 << 11) | 1156, + 0x82000000, + "vor v3, v4, v5", + ), + // vxor v3, v4, v5 : vx=1220 + ( + (4u32 << 26) | (3 << 21) | (4 << 16) | (5 << 11) | 1220, + 0x82000000, + "vxor v3, v4, v5", + ), + // vsel v3, v4, v5, v6 : op=4, va_key=42 (4-op) + ( + (4u32 << 26) | (3 << 21) | (4 << 16) | (5 << 11) | (6 << 6) | 42, + 0x82000000, + "vsel v3,v4,v5,v6", + ), + // vperm v3, v4, v5, v6 : va_key=43 + ( + (4u32 << 26) | (3 << 21) | (4 << 16) | (5 << 11) | (6 << 6) | 43, + 0x82000000, + "vperm v3,v4,v5,v6", + ), + // vmaddfp v3, v4, v5, v6 : va_key=46 (operand swap: vd, va, vc, vb) + ( + (4u32 << 26) | (3 << 21) | (4 << 16) | (5 << 11) | (6 << 6) | 46, + 0x82000000, + "vmaddfp v3, v4, v6, v5 (swap)", + ), + // mfvscr v3 : vx=1540 + ((4u32 << 26) | (3 << 21) | 1540, 0x82000000, "mfvscr v3"), + // mtvscr v5 : vx=1604, vb=v5 + ((4u32 << 26) | (5 << 11) | 1604, 0x82000000, "mtvscr v5"), + ]; + + // VMX128 op=5: vperm128 v3, v4, v5, vc=0. Canary FormatVX128: VD low + // at PPC 6-10, VA low at PPC 11-15, VB low at PPC 16-20, VC at PPC 23-25. + // key1 = (bit22<<5)|bit27 = 0 selects vperm128. + let vmx128_op5 = [( + encode_vx128(5, 3, 4, 5, 0), + 0x82000000, + "vperm128 v3, v4, v5, 0 (canary)", + )]; + + // VMX128 op=6 — exercise full 0-127 vd128 range under canary's layout. + // VD128h is at PPC 28-29 (host 2-3): no overlap with secondary opcode key, + // so vd can be freely 0-127 for any op6 instruction. + let vsrw128 = |vd: u32, vb: u32| -> u32 { + // vsrw128 secondary: 0x000001D0 (decode_op6 key5 = 0b011101). + encode_vx128(6, vd, 0, vb, 0x000001D0) + }; + let vpermwi128 = |vd: u32, vb: u32, perm: u32| -> u32 { + // vpermwi128: PERMl at PPC 11-15, PERMh at PPC 23-25, key1 sets bit 22 + bit 27. + let perml = perm & 0x1F; + let permh = (perm >> 5) & 0x7; + let mut raw = (6u32 << 26) + | ((vd & 0x1F) << 21) + | (((vd >> 5) & 0x3) << 2) // VD128h + | (perml << 16) + | ((vb & 0x1F) << 11) + | (((vb >> 5) & 0x3) << 0) // VB128h + | (permh << 6) // PERMh at PPC 23-25 + | (1 << 9) // bit 22 (key1 high) + | (1 << 4); // bit 27 (key1 low) + raw &= !(1 << 10); // PPC 21 = 0 for vpermwi128 + raw + }; + let vrlimi128 = |vd: u32, vb: u32, imm: u32, z: u32| -> u32 { + // vrlimi128: IMM at PPC 11-15, z at PPC 24-25, key2 = 0b1110001 over + // bits 21-23 + 26-27 → bits 21,22,23 = 1, bit 26 = 0, bit 27 = 1. + (6u32 << 26) + | ((vd & 0x1F) << 21) + | (((vd >> 5) & 0x3) << 2) // VD128h + | ((imm & 0x1F) << 16) + | ((vb & 0x1F) << 11) + | (((vb >> 5) & 0x3) << 0) // VB128h + | ((z & 0x3) << 6) // z at PPC 24-25 = host 6-7 + | (1 << 8) // bit 23 (key2) + | (1 << 9) // bit 22 (key2) + | (1 << 10) // bit 21 (key2) + | (1 << 4) // bit 27 (key2) + }; + let vmx128_high = [ + ( + vsrw128(0, 12), + 0x82000000, + "vsrw128 v0, v0, v12 (canary, vd_hi=00)", + ), + ( + vsrw128(32, 12), + 0x82000000, + "vsrw128 v32, v0, v12 (canary, VD128h=01)", + ), + ( + vpermwi128(64, 12, 0xE4), + 0x82000000, + "vpermwi128 v64, v12, 0xE4 (canary, VD128h=10)", + ), + ( + vrlimi128(96, 12, 4, 3), + 0x82000000, + "vrlimi128 v96, v12, 4, 3 (canary, VD128h=11)", + ), + ( + vrlimi128(127, 95, 4, 3), + 0x82000000, + "vrlimi128 v127, v95, 4, 3 (canary)", + ), + ]; + + // Fix 4: VMX128 multiply-add 4-operand layouts. Per canary, the addend + // is the VD register re-used; operand order differs between the three + // mnemonics. Encodings hand-built to satisfy decode_op5's key2 secondary + // opcode (vmaddfp128=0b001101, vmaddcfp128=0b010001, vnmsubfp128=0b010101) + // with bit 22=0 (forced by key2's high nibble) so vd128 high bit 1 = 0. + // vd128 low = 3 (bits 6-10); va128 = 3 | (bit29<<5) = 35; vb128 = 5. + // Distinct VD vs VA verifies the layout isn't trivially aliasing VD. + // + // layout (canary): + // vmaddfp128 VD, VA, VB, VD → "v3, v35, v5, v3" + // vmaddcfp128 VD, VA, VD, VB → "v3, v35, v3, v5" + // vnmsubfp128 VD, VA, VD, VB → "v3, v35, v3, v5" + let vmx128_4op = [ + // Canary FormatVX128 layout: vd=3 (PPC 6-10), va=35 (low 3 at PPC 11-15 + VA128h=1 at PPC 26), + // vb=5 (PPC 16-20), key2 at PPC 22-25 + bit 27. + (0x146328F0u32, 0x82000000, "vmaddfp128 v3, v35, v5, v3"), + (0x14632930u32, 0x82000000, "vmaddcfp128 v3, v35, v3, v5"), + (0x14632970u32, 0x82000000, "vnmsubfp128 v3, v35, v3, v5"), + ]; + + let mut all = Vec::new(); + all.extend_from_slice(&std_vmx); + all.extend_from_slice(&vmx128_op5); + all.extend_from_slice(&vmx128_high); + all.extend_from_slice(&vmx128_4op); + assert_or_regen("vmx128_registers.json", &all); +} + +#[test] +fn sradi_shift_32_decodes_to_32() { + // sradi rA, rS, 32: sh=32 → sh[4:0]=0, sh[5]=1 + // After PPCBUG-040 fix, sh64() must return 32, not 1. + let instr: DecodedInstr = decode(rldicl(3, 4, 32, 63, 0), 0); + // rldicl with mb=63 is not sradi, but tests sh64() extraction. + assert_eq!( + instr.sh64(), + 32, + "sh64 must return 32 for sh=32 (sh5=1, sh_lo=0)" + ); +} + +#[test] +fn sh64_shift_1_decodes_correctly() { + // sh=1: sh[4:0]=1, sh[5]=0 → sh64() must return 1 + let instr: DecodedInstr = decode(rldicl(3, 4, 1, 0, 0), 0); + assert_eq!(instr.sh64(), 1, "sh64 must return 1 for sh=1"); +} + +#[test] +fn sh64_shift_63_decodes_correctly() { + // sh=63: sh[4:0]=31=0x1F, sh[5]=1 → sh64() must return 63 + let instr: DecodedInstr = decode(rldicl(3, 4, 63, 0, 0), 0); + assert_eq!(instr.sh64(), 63, "sh64 must return 63 for sh=63"); +} diff --git a/crates/sylpheed-ppc/tests/golden/base_mnemonics.json b/crates/sylpheed-ppc/tests/golden/base_mnemonics.json new file mode 100644 index 00000000..b0de0887 --- /dev/null +++ b/crates/sylpheed-ppc/tests/golden/base_mnemonics.json @@ -0,0 +1,571 @@ +{ + "rows": [ + { + "label": "add r3,r4,r5", + "raw": "0x7C642A14", + "addr": "0x82000000", + "mnemonic": "add", + "operands": "r3, r4, r5" + }, + { + "label": "add. r3,r4,r5", + "raw": "0x7C642A15", + "addr": "0x82000000", + "mnemonic": "add.", + "operands": "r3, r4, r5" + }, + { + "label": "addo r3,r4,r5", + "raw": "0x7C642E14", + "addr": "0x82000000", + "mnemonic": "addo", + "operands": "r3, r4, r5" + }, + { + "label": "addo. r3,r4,r5", + "raw": "0x7C642E15", + "addr": "0x82000000", + "mnemonic": "addo.", + "operands": "r3, r4, r5" + }, + { + "label": "neg r3,r4", + "raw": "0x7C6400D0", + "addr": "0x82000000", + "mnemonic": "neg", + "operands": "r3, r4" + }, + { + "label": "mullw r3,r4,r5", + "raw": "0x7C6429D6", + "addr": "0x82000000", + "mnemonic": "mullw", + "operands": "r3, r4, r5" + }, + { + "label": "divw r3,r4,r5", + "raw": "0x7C642BD6", + "addr": "0x82000000", + "mnemonic": "divw", + "operands": "r3, r4, r5" + }, + { + "label": "mulhw. r3,r4,r5", + "raw": "0x7C642897", + "addr": "0x82000000", + "mnemonic": "mulhw.", + "operands": "r3, r4, r5" + }, + { + "label": "mulhwu. r3,r4,r5", + "raw": "0x7C642817", + "addr": "0x82000000", + "mnemonic": "mulhwu.", + "operands": "r3, r4, r5" + }, + { + "label": "mulld r3,r4,r5", + "raw": "0x7C6429D2", + "addr": "0x82000000", + "mnemonic": "mulld", + "operands": "r3, r4, r5" + }, + { + "label": "and r3,r4,r5", + "raw": "0x7C832838", + "addr": "0x82000000", + "mnemonic": "and", + "operands": "r3, r4, r5" + }, + { + "label": "or r3,r4,r5 (non-mr: rs!=rb)", + "raw": "0x7C832B78", + "addr": "0x82000000", + "mnemonic": "or", + "operands": "r3, r4, r5" + }, + { + "label": "xor r3,r4,r5", + "raw": "0x7C832A78", + "addr": "0x82000000", + "mnemonic": "xor", + "operands": "r3, r4, r5" + }, + { + "label": "nor r3,r4,r5", + "raw": "0x7C8328F8", + "addr": "0x82000000", + "mnemonic": "nor", + "operands": "r3, r4, r5" + }, + { + "label": "nand r3,r4,r5", + "raw": "0x7C832BB8", + "addr": "0x82000000", + "mnemonic": "nand", + "operands": "r3, r4, r5" + }, + { + "label": "eqv r3,r4,r5", + "raw": "0x7C832A38", + "addr": "0x82000000", + "mnemonic": "eqv", + "operands": "r3, r4, r5" + }, + { + "label": "andc r3,r4,r5", + "raw": "0x7C832878", + "addr": "0x82000000", + "mnemonic": "andc", + "operands": "r3, r4, r5" + }, + { + "label": "orc r3,r4,r5", + "raw": "0x7C832B38", + "addr": "0x82000000", + "mnemonic": "orc", + "operands": "r3, r4, r5" + }, + { + "label": "slw r3,r4,r5", + "raw": "0x7C832830", + "addr": "0x82000000", + "mnemonic": "slw", + "operands": "r3, r4, r5" + }, + { + "label": "srw r3,r4,r5", + "raw": "0x7C832C30", + "addr": "0x82000000", + "mnemonic": "srw", + "operands": "r3, r4, r5" + }, + { + "label": "sraw r3,r4,r5", + "raw": "0x7C832E30", + "addr": "0x82000000", + "mnemonic": "sraw", + "operands": "r3, r4, r5" + }, + { + "label": "sld r3,r4,r5", + "raw": "0x7C832836", + "addr": "0x82000000", + "mnemonic": "sld", + "operands": "r3, r4, r5" + }, + { + "label": "srd r3,r4,r5", + "raw": "0x7C832C36", + "addr": "0x82000000", + "mnemonic": "srd", + "operands": "r3, r4, r5" + }, + { + "label": "srawi r3,r4,16", + "raw": "0x7C838670", + "addr": "0x82000000", + "mnemonic": "srawi", + "operands": "r3, r4, 16" + }, + { + "label": "stwcx. r3,r4,r5", + "raw": "0x7C64292D", + "addr": "0x82000000", + "mnemonic": "stwcx.", + "operands": "r3, r4, r5" + }, + { + "label": "stdcx. r3,r4,r5", + "raw": "0x7C6429AD", + "addr": "0x82000000", + "mnemonic": "stdcx.", + "operands": "r3, r4, r5" + }, + { + "label": "lwarx r3,r4,r5", + "raw": "0x7C642828", + "addr": "0x82000000", + "mnemonic": "lwarx", + "operands": "r3, r4, r5" + }, + { + "label": "ldarx r3,r4,r5", + "raw": "0x7C6428A8", + "addr": "0x82000000", + "mnemonic": "ldarx", + "operands": "r3, r4, r5" + }, + { + "label": "cmpwi cr0, r3, 16", + "raw": "0x2C030010", + "addr": "0x82000000", + "mnemonic": "cmpi", + "operands": "0, r3, 16", + "ext_mnemonic": "cmpwi", + "ext_operands": "r3, 16" + }, + { + "label": "cmpwi cr2, r3, 16", + "raw": "0x2D030010", + "addr": "0x82000000", + "mnemonic": "cmpi", + "operands": "cr2, 0, r3, 16", + "ext_mnemonic": "cmpwi", + "ext_operands": "cr2, r3, 16" + }, + { + "label": "cmplwi cr0, r3, 16", + "raw": "0x28030010", + "addr": "0x82000000", + "mnemonic": "cmpli", + "operands": "0, r3, 0x10", + "ext_mnemonic": "cmplwi", + "ext_operands": "r3, 0x10" + }, + { + "label": "cmpw r3,r4 in cr0", + "raw": "0x7C032000", + "addr": "0x82000000", + "mnemonic": "cmp", + "operands": "0, r3, r4", + "ext_mnemonic": "cmpw", + "ext_operands": "r3, r4" + }, + { + "label": "cmpd r3,r4", + "raw": "0x7C232000", + "addr": "0x82000000", + "mnemonic": "cmp", + "operands": "1, r3, r4", + "ext_mnemonic": "cmpd", + "ext_operands": "r3, r4" + }, + { + "label": "cmplw r3,r4", + "raw": "0x7C032040", + "addr": "0x82000000", + "mnemonic": "cmpl", + "operands": "0, r3, r4", + "ext_mnemonic": "cmplw", + "ext_operands": "r3, r4" + }, + { + "label": "addi r3, r1, 16", + "raw": "0x38610010", + "addr": "0x82000000", + "mnemonic": "addi", + "operands": "r3, r1, 16" + }, + { + "label": "addis r3, r1, 0x100 (ra!=0)", + "raw": "0x3C610100", + "addr": "0x82000000", + "mnemonic": "addis", + "operands": "r3, r1, 0x100" + }, + { + "label": "mulli r3, r4, 5", + "raw": "0x1C640005", + "addr": "0x82000000", + "mnemonic": "mulli", + "operands": "r3, r4, 5" + }, + { + "label": "subfic r3, r4, 5", + "raw": "0x20640005", + "addr": "0x82000000", + "mnemonic": "subfic", + "operands": "r3, r4, 5" + }, + { + "label": "addic r3, r4, 16", + "raw": "0x30640010", + "addr": "0x82000000", + "mnemonic": "addic", + "operands": "r3, r4, 16" + }, + { + "label": "addic. r3, r4, 16", + "raw": "0x34640010", + "addr": "0x82000000", + "mnemonic": "addic.", + "operands": "r3, r4, 16" + }, + { + "label": "ori r4, r3, 0x10 (non-nop)", + "raw": "0x60640010", + "addr": "0x82000000", + "mnemonic": "ori", + "operands": "r4, r3, 0x10" + }, + { + "label": "oris r4, r3, 0x10", + "raw": "0x64640010", + "addr": "0x82000000", + "mnemonic": "oris", + "operands": "r4, r3, 0x10" + }, + { + "label": "xori r4, r3, 0x10", + "raw": "0x68640010", + "addr": "0x82000000", + "mnemonic": "xori", + "operands": "r4, r3, 0x10" + }, + { + "label": "andi. r4, r3, 0x10", + "raw": "0x70640010", + "addr": "0x82000000", + "mnemonic": "andi.", + "operands": "r4, r3, 0x10" + }, + { + "label": "lwz r5, 0x20(r1)", + "raw": "0x80A10020", + "addr": "0x82000000", + "mnemonic": "lwz", + "operands": "r5, 32(r1)" + }, + { + "label": "stw r5, 0x20(r1)", + "raw": "0x90A10020", + "addr": "0x82000000", + "mnemonic": "stw", + "operands": "r5, 32(r1)" + }, + { + "label": "lbz r5, 0x20(r1)", + "raw": "0x88A10020", + "addr": "0x82000000", + "mnemonic": "lbz", + "operands": "r5, 32(r1)" + }, + { + "label": "lhz r5, 0x20(r1)", + "raw": "0xA0A10020", + "addr": "0x82000000", + "mnemonic": "lhz", + "operands": "r5, 32(r1)" + }, + { + "label": "lfs f5, 0x20(r1)", + "raw": "0xC0A10020", + "addr": "0x82000000", + "mnemonic": "lfs", + "operands": "f5, 32(r1)" + }, + { + "label": "lfd f5, 0x20(r1)", + "raw": "0xC8A10020", + "addr": "0x82000000", + "mnemonic": "lfd", + "operands": "f5, 32(r1)" + }, + { + "label": "stfd f5, 0x20(r1)", + "raw": "0xD8A10020", + "addr": "0x82000000", + "mnemonic": "stfd", + "operands": "f5, 32(r1)" + }, + { + "label": "ld r5, 0x20(r1)", + "raw": "0xE8A10020", + "addr": "0x82000000", + "mnemonic": "ld", + "operands": "r5, 32(r1)" + }, + { + "label": "std r5, 0x20(r1)", + "raw": "0xF8A10020", + "addr": "0x82000000", + "mnemonic": "std", + "operands": "r5, 32(r1)" + }, + { + "label": "sync 0 (extends to sync)", + "raw": "0x7C0004AC", + "addr": "0x82000000", + "mnemonic": "sync", + "operands": "" + }, + { + "label": "isync", + "raw": "0x4C00012C", + "addr": "0x82000000", + "mnemonic": "isync", + "operands": "" + }, + { + "label": "eieio", + "raw": "0x7C0006AC", + "addr": "0x82000000", + "mnemonic": "eieio", + "operands": "" + }, + { + "label": "dcbst r1, r2", + "raw": "0x7C01106C", + "addr": "0x82000000", + "mnemonic": "dcbst", + "operands": "r1, r2" + }, + { + "label": "dcbf r1, r2", + "raw": "0x7C0110AC", + "addr": "0x82000000", + "mnemonic": "dcbf", + "operands": "r1, r2" + }, + { + "label": "dcbt r1, r2", + "raw": "0x7C01122C", + "addr": "0x82000000", + "mnemonic": "dcbt", + "operands": "r1, r2" + }, + { + "label": "dcbz r1, r2", + "raw": "0x7C0117EC", + "addr": "0x82000000", + "mnemonic": "dcbz", + "operands": "r1, r2" + }, + { + "label": "dcbz128 r1, r2", + "raw": "0x7C2117EC", + "addr": "0x82000000", + "mnemonic": "dcbz128", + "operands": "r1, r2" + }, + { + "label": "crnor 4,5,6 (no simplify)", + "raw": "0x4C853042", + "addr": "0x82000000", + "mnemonic": "crnor", + "operands": "4*cr1+lt, 4*cr1+gt, 4*cr1+eq" + }, + { + "label": "crand 4,5,6", + "raw": "0x4C853202", + "addr": "0x82000000", + "mnemonic": "crand", + "operands": "4*cr1+lt, 4*cr1+gt, 4*cr1+eq" + }, + { + "label": "cror 4,5,6 (no simplify)", + "raw": "0x4C853382", + "addr": "0x82000000", + "mnemonic": "cror", + "operands": "4*cr1+lt, 4*cr1+gt, 4*cr1+eq" + }, + { + "label": "tw 11, r3, r4 (uncommon TO)", + "raw": "0x7D632008", + "addr": "0x82000000", + "mnemonic": "tw", + "operands": "11, r3, r4" + }, + { + "label": "tdi 11, r3, 123", + "raw": "0x0963007B", + "addr": "0x82000000", + "mnemonic": "tdi", + "operands": "11, r3, 123" + }, + { + "label": "mtcrf 0xFF, r5 → mtcr", + "raw": "0x7CAFF120", + "addr": "0x82000000", + "mnemonic": "mtcrf", + "operands": "0xFF, r5", + "ext_mnemonic": "mtcr", + "ext_operands": "r5" + }, + { + "label": "mfcr r5", + "raw": "0x7CA00026", + "addr": "0x82000000", + "mnemonic": "mfcr", + "operands": "r5" + }, + { + "label": "mfmsr r5", + "raw": "0x7CA000A6", + "addr": "0x82000000", + "mnemonic": "mfmsr", + "operands": "r5" + }, + { + "label": "mtmsr r5", + "raw": "0x7CA00124", + "addr": "0x82000000", + "mnemonic": "mtmsr", + "operands": "r5" + }, + { + "label": "mtmsrd r5", + "raw": "0x7CA00164", + "addr": "0x82000000", + "mnemonic": "mtmsrd", + "operands": "r5" + }, + { + "label": "fadd f3, f4, f5", + "raw": "0xFC64282A", + "addr": "0x82000000", + "mnemonic": "fadd", + "operands": "f3, f4, f5" + }, + { + "label": "fsub f3, f4, f5", + "raw": "0xFC642828", + "addr": "0x82000000", + "mnemonic": "fsub", + "operands": "f3, f4, f5" + }, + { + "label": "fdiv f3, f4, f5", + "raw": "0xFC642824", + "addr": "0x82000000", + "mnemonic": "fdiv", + "operands": "f3, f4, f5" + }, + { + "label": "fmul f3, f0, f5 (encoded)", + "raw": "0xFCE02832", + "addr": "0x82000000", + "mnemonic": "fmul", + "operands": "f7, f0, f0" + }, + { + "label": "fneg f3, f4", + "raw": "0xFC640050", + "addr": "0x82000000", + "mnemonic": "fneg", + "operands": "f3, f0" + }, + { + "label": "fmr f3, f4", + "raw": "0xFC640090", + "addr": "0x82000000", + "mnemonic": "fmr", + "operands": "f3, f0" + }, + { + "label": "mtfsf 0xFF, f5 (Rc=0)", + "raw": "0xFDFE2D8E", + "addr": "0x82000000", + "mnemonic": "mtfsf", + "operands": "0xFF, f5" + }, + { + "label": "mtfsf. 0xFF, f5 (Rc=1)", + "raw": "0xFDFE2D8F", + "addr": "0x82000000", + "mnemonic": "mtfsf.", + "operands": "0xFF, f5" + } + ] +} diff --git a/crates/sylpheed-ppc/tests/golden/extended_mnemonics.json b/crates/sylpheed-ppc/tests/golden/extended_mnemonics.json new file mode 100644 index 00000000..0c442ddd --- /dev/null +++ b/crates/sylpheed-ppc/tests/golden/extended_mnemonics.json @@ -0,0 +1,623 @@ +{ + "rows": [ + { + "label": "nop", + "raw": "0x60000000", + "addr": "0x82000000", + "mnemonic": "ori", + "operands": "r0, r0, 0x0", + "ext_mnemonic": "nop", + "ext_operands": "" + }, + { + "label": "li r3, 16", + "raw": "0x38600010", + "addr": "0x82000000", + "mnemonic": "addi", + "operands": "r3, r0, 16", + "ext_mnemonic": "li", + "ext_operands": "r3, 16" + }, + { + "label": "li r3, -1", + "raw": "0x3860FFFF", + "addr": "0x82000000", + "mnemonic": "addi", + "operands": "r3, r0, -1", + "ext_mnemonic": "li", + "ext_operands": "r3, -1" + }, + { + "label": "subi r3, r4, 16", + "raw": "0x3864FFF0", + "addr": "0x82000000", + "mnemonic": "addi", + "operands": "r3, r4, -16", + "ext_mnemonic": "subi", + "ext_operands": "r3, r4, 16" + }, + { + "label": "lis r3, 0x1234", + "raw": "0x3C601234", + "addr": "0x82000000", + "mnemonic": "addis", + "operands": "r3, r0, 0x1234", + "ext_mnemonic": "lis", + "ext_operands": "r3, 0x1234" + }, + { + "label": "subis r3, r4, 0xFFFF", + "raw": "0x3C64FFFF", + "addr": "0x82000000", + "mnemonic": "addis", + "operands": "r3, r4, 0xFFFF", + "ext_mnemonic": "subis", + "ext_operands": "r3, r4, 0x1" + }, + { + "label": "mr r3, r4", + "raw": "0x7C832378", + "addr": "0x82000000", + "mnemonic": "or", + "operands": "r3, r4, r4", + "ext_mnemonic": "mr", + "ext_operands": "r3, r4" + }, + { + "label": "mr. r3, r4", + "raw": "0x7C832379", + "addr": "0x82000000", + "mnemonic": "or.", + "operands": "r3, r4, r4", + "ext_mnemonic": "mr.", + "ext_operands": "r3, r4" + }, + { + "label": "mr (via and)", + "raw": "0x7C832038", + "addr": "0x82000000", + "mnemonic": "and", + "operands": "r3, r4, r4", + "ext_mnemonic": "mr", + "ext_operands": "r3, r4" + }, + { + "label": "not r3, r4", + "raw": "0x7C8320F8", + "addr": "0x82000000", + "mnemonic": "nor", + "operands": "r3, r4, r4", + "ext_mnemonic": "not", + "ext_operands": "r3, r4" + }, + { + "label": "subf → sub r3, r5, r4", + "raw": "0x7C642850", + "addr": "0x82000000", + "mnemonic": "subf", + "operands": "r3, r4, r5", + "ext_mnemonic": "sub", + "ext_operands": "r3, r5, r4" + }, + { + "label": "slwi r3, r4, 4", + "raw": "0x54832036", + "addr": "0x82000000", + "mnemonic": "rlwinm", + "operands": "r3, r4, 4, 0, 27", + "ext_mnemonic": "slwi", + "ext_operands": "r3, r4, 4" + }, + { + "label": "srwi r3, r4, 4", + "raw": "0x5483E13E", + "addr": "0x82000000", + "mnemonic": "rlwinm", + "operands": "r3, r4, 28, 4, 31", + "ext_mnemonic": "srwi", + "ext_operands": "r3, r4, 4" + }, + { + "label": "rotlwi r3, r4, 8", + "raw": "0x5483403E", + "addr": "0x82000000", + "mnemonic": "rlwinm", + "operands": "r3, r4, 8, 0, 31", + "ext_mnemonic": "rotlwi", + "ext_operands": "r3, r4, 8" + }, + { + "label": "clrlwi r3, r4, 4", + "raw": "0x5483013E", + "addr": "0x82000000", + "mnemonic": "rlwinm", + "operands": "r3, r4, 0, 4, 31", + "ext_mnemonic": "clrlwi", + "ext_operands": "r3, r4, 4" + }, + { + "label": "clrrwi r3, r4, 4", + "raw": "0x54830036", + "addr": "0x82000000", + "mnemonic": "rlwinm", + "operands": "r3, r4, 0, 0, 27", + "ext_mnemonic": "clrrwi", + "ext_operands": "r3, r4, 4" + }, + { + "label": "extlwi r3, r4, 8, 8", + "raw": "0x5483400E", + "addr": "0x82000000", + "mnemonic": "rlwinm", + "operands": "r3, r4, 8, 0, 7", + "ext_mnemonic": "extlwi", + "ext_operands": "r3, r4, 8, 8" + }, + { + "label": "slwi. r3, r4, 4", + "raw": "0x54832037", + "addr": "0x82000000", + "mnemonic": "rlwinm.", + "operands": "r3, r4, 4, 0, 27", + "ext_mnemonic": "slwi.", + "ext_operands": "r3, r4, 4" + }, + { + "label": "rlwinm. r11,r11,0,31,31 (no simplify)", + "raw": "0x556B07FF", + "addr": "0x82000000", + "mnemonic": "rlwinm.", + "operands": "r11, r11, 0, 31, 31", + "ext_mnemonic": "clrlwi.", + "ext_operands": "r11, r11, 31" + }, + { + "label": "clrldi r3, r4, 32", + "raw": "0x78830020", + "addr": "0x82000000", + "mnemonic": "rldicl", + "operands": "r3, r4, 0, 32", + "ext_mnemonic": "clrldi", + "ext_operands": "r3, r4, 32" + }, + { + "label": "srdi r3, r4, 8", + "raw": "0x7883C202", + "addr": "0x82000000", + "mnemonic": "rldicl", + "operands": "r3, r4, 56, 8", + "ext_mnemonic": "srdi", + "ext_operands": "r3, r4, 8" + }, + { + "label": "rotldi r3, r4, 8", + "raw": "0x78834000", + "addr": "0x82000000", + "mnemonic": "rldicl", + "operands": "r3, r4, 8, 0", + "ext_mnemonic": "rotldi", + "ext_operands": "r3, r4, 8" + }, + { + "label": "cmpwi cr0, r3, 16", + "raw": "0x2C030010", + "addr": "0x82000000", + "mnemonic": "cmpi", + "operands": "0, r3, 16", + "ext_mnemonic": "cmpwi", + "ext_operands": "r3, 16" + }, + { + "label": "cmpdi (L=1) variant", + "raw": "0x2C230010", + "addr": "0x82000000", + "mnemonic": "cmpi", + "operands": "1, r3, 16", + "ext_mnemonic": "cmpdi", + "ext_operands": "r3, 16" + }, + { + "label": "blr", + "raw": "0x4E800020", + "addr": "0x82000000", + "mnemonic": "bclr", + "operands": "20, lt", + "ext_mnemonic": "blr", + "ext_operands": "" + }, + { + "label": "blrl", + "raw": "0x4E800021", + "addr": "0x82000000", + "mnemonic": "bclrl", + "operands": "20, lt", + "ext_mnemonic": "blrl", + "ext_operands": "" + }, + { + "label": "bctr", + "raw": "0x4E800420", + "addr": "0x82000000", + "mnemonic": "bcctr", + "operands": "20, lt", + "ext_mnemonic": "bctr", + "ext_operands": "" + }, + { + "label": "bctrl", + "raw": "0x4E800421", + "addr": "0x82000000", + "mnemonic": "bcctrl", + "operands": "20, lt", + "ext_mnemonic": "bctrl", + "ext_operands": "" + }, + { + "label": "beqlr (BO=12, BI=2 → cr0.eq true)", + "raw": "0x4D820020", + "addr": "0x82000000", + "mnemonic": "bclr", + "operands": "12, eq", + "ext_mnemonic": "beqlr", + "ext_operands": "" + }, + { + "label": "bnelr", + "raw": "0x4C820020", + "addr": "0x82000000", + "mnemonic": "bclr", + "operands": "4, eq", + "ext_mnemonic": "bnelr", + "ext_operands": "" + }, + { + "label": "bc → b 0x82000040", + "raw": "0x42800040", + "addr": "0x82000000", + "mnemonic": "bc", + "operands": "20, lt, 0x82000040", + "ext_mnemonic": "b", + "ext_operands": "0x82000040", + "branch_target": "0x82000040" + }, + { + "label": "bc l → bl 0x82000040", + "raw": "0x42800041", + "addr": "0x82000000", + "mnemonic": "bcl", + "operands": "20, lt, 0x82000040", + "ext_mnemonic": "bl", + "ext_operands": "0x82000040", + "branch_target": "0x82000040" + }, + { + "label": "bc 12,cr0.eq → beq 0x82000040", + "raw": "0x41820040", + "addr": "0x82000000", + "mnemonic": "bc", + "operands": "12, eq, 0x82000040", + "ext_mnemonic": "beq", + "ext_operands": "0x82000040", + "branch_target": "0x82000040" + }, + { + "label": "bc 4,cr0.eq → bne 0x82000040", + "raw": "0x40820040", + "addr": "0x82000000", + "mnemonic": "bc", + "operands": "4, eq, 0x82000040", + "ext_mnemonic": "bne", + "ext_operands": "0x82000040", + "branch_target": "0x82000040" + }, + { + "label": "bc 12,cr0.lt → blt 0x82000040", + "raw": "0x41800040", + "addr": "0x82000000", + "mnemonic": "bc", + "operands": "12, lt, 0x82000040", + "ext_mnemonic": "blt", + "ext_operands": "0x82000040", + "branch_target": "0x82000040" + }, + { + "label": "bc 4,cr0.lt → bge 0x82000040", + "raw": "0x40800040", + "addr": "0x82000000", + "mnemonic": "bc", + "operands": "4, lt, 0x82000040", + "ext_mnemonic": "bge", + "ext_operands": "0x82000040", + "branch_target": "0x82000040" + }, + { + "label": "bc 12,cr0.gt → bgt 0x82000040", + "raw": "0x41810040", + "addr": "0x82000000", + "mnemonic": "bc", + "operands": "12, gt, 0x82000040", + "ext_mnemonic": "bgt", + "ext_operands": "0x82000040", + "branch_target": "0x82000040" + }, + { + "label": "bc 4,cr0.gt → ble 0x82000040", + "raw": "0x40810040", + "addr": "0x82000000", + "mnemonic": "bc", + "operands": "4, gt, 0x82000040", + "ext_mnemonic": "ble", + "ext_operands": "0x82000040", + "branch_target": "0x82000040" + }, + { + "label": "bc 12, cr2.eq → beq cr2, 0x...040", + "raw": "0x418A0040", + "addr": "0x82000000", + "mnemonic": "bc", + "operands": "12, 4*cr2+eq, 0x82000040", + "ext_mnemonic": "beq", + "ext_operands": "cr2, 0x82000040", + "branch_target": "0x82000040" + }, + { + "label": "bdnz 0x82000040", + "raw": "0x42000040", + "addr": "0x82000000", + "mnemonic": "bc", + "operands": "16, lt, 0x82000040", + "ext_mnemonic": "bdnz", + "ext_operands": "0x82000040", + "branch_target": "0x82000040" + }, + { + "label": "bdz 0x82000040", + "raw": "0x42400040", + "addr": "0x82000000", + "mnemonic": "bc", + "operands": "18, lt, 0x82000040", + "ext_mnemonic": "bdz", + "ext_operands": "0x82000040", + "branch_target": "0x82000040" + }, + { + "label": "b +0x40 → 0x82000040", + "raw": "0x48000040", + "addr": "0x82000000", + "mnemonic": "b", + "operands": "0x82000040", + "branch_target": "0x82000040" + }, + { + "label": "bl +0x40 → 0x82000040", + "raw": "0x48000041", + "addr": "0x82000000", + "mnemonic": "bl", + "operands": "0x82000040", + "branch_target": "0x82000040" + }, + { + "label": "ba 0x40 absolute", + "raw": "0x48000042", + "addr": "0x82000000", + "mnemonic": "ba", + "operands": "0x00000040", + "branch_target": "0x00000040" + }, + { + "label": "bla 0x40 absolute", + "raw": "0x48000043", + "addr": "0x82000000", + "mnemonic": "bla", + "operands": "0x00000040", + "branch_target": "0x00000040" + }, + { + "label": "tdeqi r3, 123", + "raw": "0x0883007B", + "addr": "0x82000000", + "mnemonic": "tdi", + "operands": "4, r3, 123", + "ext_mnemonic": "tdeqi", + "ext_operands": "r3, 123" + }, + { + "label": "twlti r3, 123", + "raw": "0x0E03007B", + "addr": "0x82000000", + "mnemonic": "twi", + "operands": "16, r3, 123", + "ext_mnemonic": "twlti", + "ext_operands": "r3, 123" + }, + { + "label": "mflr r3", + "raw": "0x7C6802A6", + "addr": "0x82000000", + "mnemonic": "mfspr", + "operands": "r3, LR", + "ext_mnemonic": "mflr", + "ext_operands": "r3" + }, + { + "label": "mfctr r3", + "raw": "0x7C6902A6", + "addr": "0x82000000", + "mnemonic": "mfspr", + "operands": "r3, CTR", + "ext_mnemonic": "mfctr", + "ext_operands": "r3" + }, + { + "label": "mfxer r3", + "raw": "0x7C6102A6", + "addr": "0x82000000", + "mnemonic": "mfspr", + "operands": "r3, XER", + "ext_mnemonic": "mfxer", + "ext_operands": "r3" + }, + { + "label": "mtlr r3", + "raw": "0x7C6803A6", + "addr": "0x82000000", + "mnemonic": "mtspr", + "operands": "LR, r3", + "ext_mnemonic": "mtlr", + "ext_operands": "r3" + }, + { + "label": "mtctr r3", + "raw": "0x7C6903A6", + "addr": "0x82000000", + "mnemonic": "mtspr", + "operands": "CTR, r3", + "ext_mnemonic": "mtctr", + "ext_operands": "r3" + }, + { + "label": "mtxer r3", + "raw": "0x7C6103A6", + "addr": "0x82000000", + "mnemonic": "mtspr", + "operands": "XER, r3", + "ext_mnemonic": "mtxer", + "ext_operands": "r3" + }, + { + "label": "crnot 4, 5", + "raw": "0x4C852842", + "addr": "0x82000000", + "mnemonic": "crnor", + "operands": "4*cr1+lt, 4*cr1+gt, 4*cr1+gt", + "ext_mnemonic": "crnot", + "ext_operands": "4*cr1+lt, 4*cr1+gt" + }, + { + "label": "crclr 4", + "raw": "0x4C842182", + "addr": "0x82000000", + "mnemonic": "crxor", + "operands": "4*cr1+lt, 4*cr1+lt, 4*cr1+lt", + "ext_mnemonic": "crclr", + "ext_operands": "4*cr1+lt" + }, + { + "label": "crset 4", + "raw": "0x4C842242", + "addr": "0x82000000", + "mnemonic": "creqv", + "operands": "4*cr1+lt, 4*cr1+lt, 4*cr1+lt", + "ext_mnemonic": "crset", + "ext_operands": "4*cr1+lt" + }, + { + "label": "crmove 4, 5", + "raw": "0x4C852B82", + "addr": "0x82000000", + "mnemonic": "cror", + "operands": "4*cr1+lt, 4*cr1+gt, 4*cr1+gt", + "ext_mnemonic": "crmove", + "ext_operands": "4*cr1+lt, 4*cr1+gt" + }, + { + "label": "lwsync", + "raw": "0x7C2004AC", + "addr": "0x82000000", + "mnemonic": "sync", + "operands": "", + "ext_mnemonic": "lwsync", + "ext_operands": "" + }, + { + "label": "trap", + "raw": "0x7FE00008", + "addr": "0x82000000", + "mnemonic": "tw", + "operands": "31, r0, r0", + "ext_mnemonic": "trap", + "ext_operands": "" + }, + { + "label": "blr (BO=20, BI=4 — BI is don't-care)", + "raw": "0x4E840020", + "addr": "0x82000000", + "mnemonic": "bclr", + "operands": "20, 4*cr1+lt", + "ext_mnemonic": "blr", + "ext_operands": "" + }, + { + "label": "blrl (BO=20, BI=7)", + "raw": "0x4E870021", + "addr": "0x82000000", + "mnemonic": "bclrl", + "operands": "20, 4*cr1+so", + "ext_mnemonic": "blrl", + "ext_operands": "" + }, + { + "label": "bctr (BO=20, BI=4)", + "raw": "0x4E840420", + "addr": "0x82000000", + "mnemonic": "bcctr", + "operands": "20, 4*cr1+lt", + "ext_mnemonic": "bctr", + "ext_operands": "" + }, + { + "label": "twllt r3, r4 (TO=2)", + "raw": "0x7C432008", + "addr": "0x82000000", + "mnemonic": "tw", + "operands": "2, r3, r4", + "ext_mnemonic": "twllt", + "ext_operands": "r3, r4" + }, + { + "label": "twlgt r3, r4 (TO=1)", + "raw": "0x7C232008", + "addr": "0x82000000", + "mnemonic": "tw", + "operands": "1, r3, r4", + "ext_mnemonic": "twlgt", + "ext_operands": "r3, r4" + }, + { + "label": "tdlge r3, r4 (TO=5)", + "raw": "0x7CA32088", + "addr": "0x82000000", + "mnemonic": "td", + "operands": "5, r3, r4", + "ext_mnemonic": "tdlge", + "ext_operands": "r3, r4" + }, + { + "label": "twlle r3, r4 (TO=6)", + "raw": "0x7CC32008", + "addr": "0x82000000", + "mnemonic": "tw", + "operands": "6, r3, r4", + "ext_mnemonic": "twlle", + "ext_operands": "r3, r4" + }, + { + "label": "twllti r3, 16", + "raw": "0x0C430010", + "addr": "0x82000000", + "mnemonic": "twi", + "operands": "2, r3, 16", + "ext_mnemonic": "twllti", + "ext_operands": "r3, 16" + }, + { + "label": "tdlgei r3, 16", + "raw": "0x08A30010", + "addr": "0x82000000", + "mnemonic": "tdi", + "operands": "5, r3, 16", + "ext_mnemonic": "tdlgei", + "ext_operands": "r3, 16" + } + ] +} diff --git a/crates/sylpheed-ppc/tests/golden/vmx128_registers.json b/crates/sylpheed-ppc/tests/golden/vmx128_registers.json new file mode 100644 index 00000000..12cf44d4 --- /dev/null +++ b/crates/sylpheed-ppc/tests/golden/vmx128_registers.json @@ -0,0 +1,137 @@ +{ + "rows": [ + { + "label": "vaddubm v3, v4, v5", + "raw": "0x10642800", + "addr": "0x82000000", + "mnemonic": "vaddubm", + "operands": "v3, v4, v5" + }, + { + "label": "vaddfp v3, v4, v5", + "raw": "0x1064280A", + "addr": "0x82000000", + "mnemonic": "vaddfp", + "operands": "v3, v4, v5" + }, + { + "label": "vand v3, v4, v5", + "raw": "0x10642C04", + "addr": "0x82000000", + "mnemonic": "vand", + "operands": "v3, v4, v5" + }, + { + "label": "vor v3, v4, v5", + "raw": "0x10642C84", + "addr": "0x82000000", + "mnemonic": "vor", + "operands": "v3, v4, v5" + }, + { + "label": "vxor v3, v4, v5", + "raw": "0x10642CC4", + "addr": "0x82000000", + "mnemonic": "vxor", + "operands": "v3, v4, v5" + }, + { + "label": "vsel v3,v4,v5,v6", + "raw": "0x106429AA", + "addr": "0x82000000", + "mnemonic": "vsel", + "operands": "v3, v4, v5, v6" + }, + { + "label": "vperm v3,v4,v5,v6", + "raw": "0x106429AB", + "addr": "0x82000000", + "mnemonic": "vperm", + "operands": "v3, v4, v5, v6" + }, + { + "label": "vmaddfp v3, v4, v6, v5 (swap)", + "raw": "0x106429AE", + "addr": "0x82000000", + "mnemonic": "vmaddfp", + "operands": "v3, v4, v6, v5" + }, + { + "label": "mfvscr v3", + "raw": "0x10600604", + "addr": "0x82000000", + "mnemonic": "mfvscr", + "operands": "v3" + }, + { + "label": "mtvscr v5", + "raw": "0x10002E44", + "addr": "0x82000000", + "mnemonic": "mtvscr", + "operands": "v5" + }, + { + "label": "vperm128 v3, v4, v5, 0 (canary)", + "raw": "0x14642800", + "addr": "0x82000000", + "mnemonic": "vperm128", + "operands": "v3, v4, v5, 0" + }, + { + "label": "vsrw128 v0, v0, v12 (canary, vd_hi=00)", + "raw": "0x180061D0", + "addr": "0x82000000", + "mnemonic": "vsrw128", + "operands": "v0, v0, v12" + }, + { + "label": "vsrw128 v32, v0, v12 (canary, VD128h=01)", + "raw": "0x180061D4", + "addr": "0x82000000", + "mnemonic": "vsrw128", + "operands": "v32, v0, v12" + }, + { + "label": "vpermwi128 v64, v12, 0xE4 (canary, VD128h=10)", + "raw": "0x180463D8", + "addr": "0x82000000", + "mnemonic": "vpermwi128", + "operands": "v64, v12, 0xE4" + }, + { + "label": "vrlimi128 v96, v12, 4, 3 (canary, VD128h=11)", + "raw": "0x180467DC", + "addr": "0x82000000", + "mnemonic": "vrlimi128", + "operands": "v96, v12, 4, 3" + }, + { + "label": "vrlimi128 v127, v95, 4, 3 (canary)", + "raw": "0x1BE4FFDE", + "addr": "0x82000000", + "mnemonic": "vrlimi128", + "operands": "v127, v95, 4, 3" + }, + { + "label": "vmaddfp128 v3, v35, v5, v3", + "raw": "0x146328F0", + "addr": "0x82000000", + "mnemonic": "vmaddfp128", + "operands": "v3, v35, v5, v3" + }, + { + "label": "vmaddcfp128 v3, v35, v3, v5", + "raw": "0x14632930", + "addr": "0x82000000", + "mnemonic": "vmaddcfp128", + "operands": "v3, v35, v3, v5" + }, + { + "label": "vnmsubfp128 v3, v35, v3, v5", + "raw": "0x14632970", + "addr": "0x82000000", + "mnemonic": "vnmsubfp128", + "operands": "v3, v35, v3, v5" + } + ] +} diff --git a/crates/sylpheed-xexdb/tests/disasm_goldens.rs b/crates/sylpheed-xexdb/tests/disasm_goldens.rs index 022a673a..edb3a2c1 100644 --- a/crates/sylpheed-xexdb/tests/disasm_goldens.rs +++ b/crates/sylpheed-xexdb/tests/disasm_goldens.rs @@ -34,7 +34,7 @@ struct GoldenFile { fn cpu_fixture(name: &str) -> PathBuf { PathBuf::from(env!("CARGO_MANIFEST_DIR")) .join("..") - .join("xenia-cpu") + .join("sylpheed-ppc") .join("tests") .join("golden") .join(name) @@ -54,7 +54,7 @@ fn check_fixture(fixture_name: &str) { let path = cpu_fixture(fixture_name); assert!( path.exists(), - "missing fixture {} — run `cargo test -p xenia-cpu --test disasm_goldens` to (re)generate it", + "missing fixture {} — run `cargo test -p sylpheed-ppc --test disasm_goldens` to (re)generate it", path.display() ); let src = std::fs::read_to_string(&path).unwrap();