From 0bcea6031e3d0b48acb15f6a7dfdab670ec8fcfc Mon Sep 17 00:00:00 2001 From: iximeow Date: Sun, 2 Jan 2022 13:27:48 -0800 Subject: get test situation in order --- tests/armv7/mod.rs | 811 ++++++++++ tests/armv7/thumb.rs | 4084 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 4895 insertions(+) create mode 100644 tests/armv7/mod.rs create mode 100644 tests/armv7/thumb.rs (limited to 'tests/armv7') diff --git a/tests/armv7/mod.rs b/tests/armv7/mod.rs new file mode 100644 index 0000000..a60b50a --- /dev/null +++ b/tests/armv7/mod.rs @@ -0,0 +1,811 @@ +use yaxpeax_arch::{Arch, Decoder, LengthedInstruction}; +use yaxpeax_arm::armv7::{ARMv7, Instruction, ConditionCode, DecodeError, Operand, Opcode, Reg, RegShift}; + +mod thumb; + +type InstDecoder = ::Decoder; + +fn test_invalid_under(decoder: &InstDecoder, data: [u8; 4]) { + let mut reader = yaxpeax_arch::U8Reader::new(&data[..]); + match decoder.decode(&mut reader) { + Err(_) => { }, + Ok(inst) => { + panic!( + "unexpected successful decode for {:02x}{:02x}{:02x}{:02x}\ngot: {}", + data[0], data[1], data[2], data[3], + inst + ); + } + } +} + +fn test_display_under(decoder: &InstDecoder, data: [u8; 4], expected: &'static str) { + let mut reader = yaxpeax_arch::U8Reader::new(&data[..]); + let instr = match decoder.decode(&mut reader) { + Err(e) => { + panic!("failed to decode {:02x}{:02x}{:02x}{:02x}: {}", data[0], data[1], data[2], data[3], e) + }, + Ok(instr) => instr, + }; + let displayed = format!("{}", instr); + assert!( + displayed == expected, + "decode error for {:02x}{:02x}{:02x}{:02x}:\n displayed: {}\n expected: {}\n", + data[0], data[1], data[2], data[3], + displayed, expected + ); +} + +fn test_decode(data: [u8; 4], expected: Instruction) { + let mut reader = yaxpeax_arch::U8Reader::new(&data[..]); + let instr = InstDecoder::default().decode(&mut reader).unwrap(); + assert!( + instr == expected, + "decode error for {:02x}{:02x}{:02x}{:02x}:\n decoded: {:?}\n expected: {:?}\n", + data[0], data[1], data[2], data[3], + instr, expected + ); +} + +fn test_invalid(data: [u8; 4]) { + test_invalid_under(&InstDecoder::default(), data); +} + +fn test_all(data: [u8; 4], expected: &'static str) { + test_display_under(&InstDecoder::armv4(), data, expected); + test_display_under(&InstDecoder::armv5(), data, expected); + test_display_under(&InstDecoder::armv6(), data, expected); + test_display_under(&InstDecoder::armv7(), data, expected); +} +fn test_armv5(data: [u8; 4], expected: &'static str) { + test_display_under(&InstDecoder::armv5(), data, expected); +// test_invalid_under(&InstDecoder::armv4(), data); +} +fn test_armv6(data: [u8; 4], expected: &'static str) { + test_display_under(&InstDecoder::armv6(), data, expected); +// test_invalid_under(&InstDecoder::armv5(), data); +} +fn test_armv6t2(data: [u8; 4], expected: &'static str) { + test_display_under(&InstDecoder::armv6t2(), data, expected); +// test_invalid_under(&InstDecoder::armv6(), data); +} +#[allow(dead_code)] +fn test_armv7(data: [u8; 4], expected: &'static str) { + test_display_under(&InstDecoder::armv7(), data, expected); +// test_invalid_under(&InstDecoder::armv6(), data); +} +fn test_armv7ve(data: [u8; 4], expected: &'static str) { + test_display_under(&InstDecoder::armv7ve(), data, expected); +// test_invalid_under(&InstDecoder::armv7(), data, expected); +} +fn test_arm_security_extensions(data: [u8; 4], expected: &'static str) { + test_display_under(&InstDecoder::armv7vese(), data, expected); +// test_invalid_under(&InstDecoder::armv7ve(), data, expected); +} + +fn test_nonconformant(data: [u8; 4]) { + let mut reader = yaxpeax_arch::U8Reader::new(&data[..]); + let result = InstDecoder::default().decode(&mut reader); + assert!( + result == Err(DecodeError::Nonconforming), + "got bad result: {:?} from {:#x?}", result, data + ); +} + +fn test_display(data: [u8; 4], expected: &'static str) { + let mut reader = yaxpeax_arch::U8Reader::new(&data[..]); + let instr = InstDecoder::default().decode(&mut reader).unwrap(); + let text = format!("{}", instr); + assert!( + text == expected, + "display error for {:02x}{:02x}{:02x}{:02x}:\n decoded: {:?}\n displayed: {}\n expected: {}\n", + data[0], data[1], data[2], data[3], + instr, + text, expected + ); +} + +#[test] +fn test_unpredictable_instructions() { + test_invalid([0x00, 0x02, 0x08, 0x01]); // msr with invalid machine register +} + +#[test] +fn test_decode_str_ldr() { + test_decode( + [0x24, 0xc0, 0x9f, 0xe5], + Instruction { + condition: ConditionCode::AL, + opcode: Opcode::LDR, + operands: [ + Operand::Reg(Reg::from_u8(12)), + Operand::RegDerefPreindexOffset(Reg::from_u8(15), 0x24, true, false), + Operand::Nothing, + Operand::Nothing, + ], + s: false, + thumb_w: false, + thumb: false, + wide: false, + } + ); + test_decode( + [0x10, 0x00, 0x9f, 0xe5], + Instruction { + condition: ConditionCode::AL, + opcode: Opcode::LDR, + operands: [ + Operand::Reg(Reg::from_u8(0)), + Operand::RegDerefPreindexOffset(Reg::from_u8(15), 0x10, true, false), + Operand::Nothing, + Operand::Nothing, + ], + s: false, + thumb_w: false, + thumb: false, + wide: false, + } + ); + test_decode( + [0x04, 0x20, 0x2d, 0xe5], + Instruction { + condition: ConditionCode::AL, + opcode: Opcode::STR, + operands: [ + Operand::Reg(Reg::from_u8(2)), + Operand::RegDerefPreindexOffset(Reg::from_u8(13), 4, false, true), + Operand::Nothing, + Operand::Nothing, + ], + s: false, + thumb_w: false, + thumb: false, + wide: false, + } + ); + test_decode( + [0x04, 0x00, 0x2d, 0xe5], + Instruction { + condition: ConditionCode::AL, + opcode: Opcode::STR, + operands: [ + Operand::Reg(Reg::from_u8(0)), + Operand::RegDerefPreindexOffset(Reg::from_u8(13), 4, false, true), + Operand::Nothing, + Operand::Nothing, + ], + s: false, + thumb_w: false, + thumb: false, + wide: false, + } + ); + test_decode( + [0x14, 0x30, 0x9f, 0xe5], + Instruction { + condition: ConditionCode::AL, + opcode: Opcode::LDR, + operands: [ + Operand::Reg(Reg::from_u8(3)), + Operand::RegDerefPreindexOffset(Reg::from_u8(15), 0x14, true, false), + Operand::Nothing, + Operand::Nothing, + ], + s: false, + thumb_w: false, + thumb: false, + wide: false, + } + ); + test_decode( + [0x14, 0x20, 0x9f, 0xe5], + Instruction { + condition: ConditionCode::AL, + opcode: Opcode::LDR, + operands: [ + Operand::Reg(Reg::from_u8(2)), + Operand::RegDerefPreindexOffset(Reg::from_u8(15), 0x14, true, false), + Operand::Nothing, + Operand::Nothing, + ], + s: false, + thumb_w: false, + thumb: false, + wide: false, + } + ); + test_all([0x10, 0x00, 0x7f, 0xe5], "ldrb r0, [pc, -0x10]!"); + test_all([0x10, 0x00, 0x3f, 0xe5], "ldr r0, [pc, -0x10]!"); + test_all([0x10, 0x00, 0x7f, 0xe4], "ldrbt r0, [pc], -0x10"); + test_all([0x10, 0x00, 0x3f, 0xe4], "ldrt r0, [pc], -0x10"); + test_all([0x10, 0x00, 0x4f, 0xe4], "strb r0, [pc], -0x10"); + // Extra load/store instructions A5.2.8, page A5-201 + test_all([0xbb, 0x38, 0xa5, 0xe1], "strh r3, [r5, fp]!"); + test_all([0xbb, 0x38, 0xb5, 0xe1], "ldrh r3, [r5, fp]!"); + test_all([0xbb, 0x38, 0xe5, 0xe1], "strh r3, [r5, 0x8b]!"); + test_all([0xbb, 0x38, 0xf5, 0xe1], "ldrh r3, [r5, 0x8b]!"); + test_armv5([0xdb, 0x48, 0xa6, 0xe1], "ldrd r4, r5, [r6, fp]!"); + test_invalid([0xdb, 0x38, 0xa5, 0xe1]); + test_all([0xdb, 0x38, 0xb5, 0xe1], "ldrsb r3, [r5, fp]!"); + test_armv5([0xdb, 0x48, 0xe6, 0xe1], "ldrd r4, r5, [r6, 0x8b]!"); + test_invalid([0xdb, 0x38, 0xe5, 0xe1]); + test_all([0xdb, 0x38, 0xf5, 0xe1], "ldrsb r3, [r5, 0x8b]!"); + test_invalid([0xfb, 0x38, 0xa5, 0xe1]); + test_all([0xfb, 0x48, 0xa6, 0xe1], "strd r4, r5, [r6, fp]!"); + test_all([0xfb, 0x38, 0xb5, 0xe1], "ldrsh r3, [r5, fp]!"); + test_invalid([0xfb, 0x38, 0xe5, 0xe1]); + test_all([0xfb, 0x48, 0xe6, 0xe1], "strd r4, r5, [r6, 0x8b]!"); + test_all([0xfb, 0x38, 0xf5, 0xe1], "ldrsh r3, [r5, 0x8b]!"); + test_all([0xfb, 0x38, 0xff, 0xe1], "ldrsh r3, [pc, 0x8b]!"); + +} + +#[test] +fn test_synchronization() { + test_display( + [0x94, 0x8f, 0x8a, 0xe1], + "strex r8, r4, [r10]" + ); + test_display( + [0x9f, 0x8f, 0x9a, 0xe1], + "ldrex r8, [r10]" + ); + test_display( + [0x94, 0x2f, 0xa4, 0xe1], + "strexd r2, r4, r5, [r4]" + ); + test_display( + [0x9f, 0x2f, 0xb4, 0xe1], + "ldrexd r2, r3, [r4]" + ); + test_display( + [0x9f, 0x2f, 0xc4, 0xe1], + "strexb r2, pc, [r4]" + ); + test_display( + [0x9f, 0x2f, 0xd4, 0xe1], + "ldrexb r2, [r4]" + ); + test_display( + [0x9f, 0x2f, 0xe4, 0xe1], + "strexh r2, pc, [r4]" + ); + test_display( + [0x9f, 0x2f, 0xf4, 0xe1], + "ldrexh r2, [r4]" + ); +} + +#[test] +fn test_str() { + test_display( + [0xb5, 0x53, 0x68, 0xe0], + "strht r5, [r8], -0x35" + ); +} + +#[test] +fn test_data_imm() { + test_display( + [0x12, 0x34, 0xa0, 0xe3], + "mov r3, 0x12000000" + ); + test_display( + [0x12, 0x44, 0x9c, 0xe3], + "orrs r4, ip, 0x12000000" + ); +} + +#[test] +fn test_decode_misc() { + test_armv5([0x32, 0xff, 0x2f, 0xe1], "blx r2"); + test_display( + [0x13, 0x5f, 0x6f, 0xe1], + "clz r5, r3" + ); + test_display( + [0xc8, 0xac, 0x0b, 0xe1], + "smlabt fp, r8, ip, r10" + ); + test_display( + [0x32, 0xff, 0x2f, 0xe1], + "blx r2" + ); + test_display( + [0x02, 0x00, 0xa0, 0xe3], + "mov r0, 0x2" + ); + test_display( + [0xe8, 0x10, 0x9f, 0xe5], + "ldr r1, [pc, 0xe8]" + ); + // https://www.raspberrypi.org/forums/viewtopic.php?p=967759&sid=25fa58d95208c0c76b579012ca693380#p967759 + // it looks like gcc toolchains older than 6.1(?) don't support -march=armv7e + test_armv7ve([0x6e, 0x00, 0x60, 0xe1], "eret"); + test_armv5([0x76, 0x00, 0x23, 0xe1], "bkpt 0x3006"); + // ARMv7VE only, capstone (not-next) doesn't have this, no secondary confirmation yet + test_armv7ve([0x76, 0x00, 0x43, 0xe1], "hvc 0x3006"); + test_arm_security_extensions([0x76, 0x00, 0x63, 0xe1], "smc 0x3006"); + test_all([0x6e, 0xf0, 0x28, 0xe3], "msr apsr_nzcvq, 0x6e"); + test_all([0x6e, 0xf0, 0x24, 0xe3], "msr apsr_g, 0x6e"); + test_all([0x6e, 0xf0, 0x2c, 0xe3], "msr apsr_nzcvqg, 0x6e"); + + test_all([0x6e, 0xf0, 0x21, 0xe3], "msr cpsr_c, 0x6e"); + test_all([0x6e, 0xf0, 0x22, 0xe3], "msr cpsr_x, 0x6e"); + test_all([0x6e, 0xf0, 0x23, 0xe3], "msr cpsr_xc, 0x6e"); + test_all([0x6e, 0xf0, 0x25, 0xe3], "msr cpsr_sc, 0x6e"); + test_all([0x6e, 0xf0, 0x26, 0xe3], "msr cpsr_sx, 0x6e"); + test_all([0x6e, 0xf0, 0x27, 0xe3], "msr cpsr_sxc, 0x6e"); + test_all([0x6e, 0xf0, 0x29, 0xe3], "msr cpsr_fc, 0x6e"); + test_all([0x6e, 0xf0, 0x2a, 0xe3], "msr cpsr_fx, 0x6e"); + test_all([0x6e, 0xf0, 0x2b, 0xe3], "msr cpsr_fxc, 0x6e"); + test_all([0x6e, 0xf0, 0x2d, 0xe3], "msr cpsr_fsc, 0x6e"); + test_all([0x6e, 0xf0, 0x2e, 0xe3], "msr cpsr_fsx, 0x6e"); + test_all([0x6e, 0xf0, 0x2f, 0xe3], "msr cpsr_fsxc, 0x6e"); + test_all([0x6e, 0xf0, 0x60, 0xe3], "msr spsr, 0x6e"); + test_all([0x6e, 0xf0, 0x61, 0xe3], "msr spsr_c, 0x6e"); + test_all([0x6e, 0xf0, 0x62, 0xe3], "msr spsr_x, 0x6e"); + test_all([0x6e, 0xf0, 0x63, 0xe3], "msr spsr_xc, 0x6e"); + test_all([0x6e, 0xf0, 0x64, 0xe3], "msr spsr_s, 0x6e"); + test_all([0x6e, 0xf0, 0x65, 0xe3], "msr spsr_sc, 0x6e"); + test_all([0x6e, 0xf0, 0x66, 0xe3], "msr spsr_sx, 0x6e"); + test_all([0x6e, 0xf0, 0x67, 0xe3], "msr spsr_sxc, 0x6e"); + test_all([0x6e, 0xf0, 0x68, 0xe3], "msr spsr_f, 0x6e"); + test_all([0x6e, 0xf0, 0x69, 0xe3], "msr spsr_fc, 0x6e"); + test_all([0x6e, 0xf0, 0x6a, 0xe3], "msr spsr_fx, 0x6e"); + test_all([0x6e, 0xf0, 0x6b, 0xe3], "msr spsr_fxc, 0x6e"); + test_all([0x6e, 0xf0, 0x6c, 0xe3], "msr spsr_fs, 0x6e"); + test_all([0x6e, 0xf0, 0x6d, 0xe3], "msr spsr_fsc, 0x6e"); + test_all([0x6e, 0xf0, 0x6e, 0xe3], "msr spsr_fsx, 0x6e"); + test_all([0x6e, 0xf0, 0x6f, 0xe3], "msr spsr_fsxc, 0x6e"); + test_armv6t2([0x45, 0x67, 0x01, 0xe3], "mov r6, 0x1745"); + test_armv6t2([0x45, 0x67, 0x41, 0xe3], "movt r6, 0x1745"); +} + +#[test] +fn test_decode_pop() { + test_decode( + [0x04, 0x10, 0x9d, 0xe4], + Instruction { + condition: ConditionCode::AL, + opcode: Opcode::LDR, + operands: [ + Operand::Reg(Reg::from_u8(1)), + Operand::RegDerefPostindexOffset(Reg::from_u8(13), 0x4, true, false), + Operand::Nothing, + Operand::Nothing, + ], + s: false, + thumb_w: false, + thumb: false, + wide: false, + } + ); + test_display( + [0x04, 0x10, 0x9d, 0xe4], + "pop {r1}" + ); + test_decode( + [0xf0, 0x40, 0x2d, 0xe9], + Instruction { + condition: ConditionCode::AL, + opcode: Opcode::STM(false, true, false, false), + operands: [ + Operand::RegWBack(Reg::from_u8(13), true), + Operand::RegList(16624), + Operand::Nothing, + Operand::Nothing, + ], + s: false, + thumb_w: false, + thumb: false, + wide: false, + } + ); + test_display( + [0xf0, 0x40, 0x2d, 0xe9], + "push {r4, r5, r6, r7, lr}" + ); + test_decode( + [0xf0, 0x80, 0xbd, 0x18], + Instruction { + condition: ConditionCode::NE, + opcode: Opcode::LDM(true, false, false, false), + operands: [ + Operand::RegWBack(Reg::from_u8(13), true), + Operand::RegList(33008), + Operand::Nothing, + Operand::Nothing, + ], + s: false, + thumb_w: false, + thumb: false, + wide: false, + } + ); + test_display( + [0xf0, 0x80, 0xbd, 0x18], + "popne {r4, r5, r6, r7, pc}" + ); +} + +#[test] +fn test_decode_mov() { + test_decode( + [0x0d, 0x20, 0xa0, 0xe1], + Instruction { + condition: ConditionCode::AL, + opcode: Opcode::MOV, + operands: [ + Operand::Reg(Reg::from_u8(2)), + Operand::Reg(Reg::from_u8(13)), + Operand::Nothing, + Operand::Nothing, + ], + s: false, + thumb_w: false, + thumb: false, + wide: false, + } + ); + test_display([0x0d, 0x20, 0xa0, 0xe1], "mov r2, sp"); + test_nonconformant([0x0d, 0x20, 0xa1, 0xe1]); + test_decode( + [0x00, 0xb0, 0xa0, 0xe3], + Instruction { + condition: ConditionCode::AL, + opcode: Opcode::MOV, + operands: [ + Operand::Reg(Reg::from_u8(11)), + Operand::Imm32(0), + Operand::Nothing, + Operand::Nothing, + ], + s: false, + thumb_w: false, + thumb: false, + wide: false, + } + ); +} + +#[test] +fn test_decode_arithmetic() { + test_decode( + [0x18, 0x1d, 0x00, 0x00], + Instruction { + condition: ConditionCode::EQ, + opcode: Opcode::AND, + operands: [Operand::Reg(Reg::from_u8(1)), Operand::Reg(Reg::from_u8(0)), Operand::RegShift(RegShift::from_raw(0xd18)), Operand::Nothing], + s: false, + thumb_w: false, + thumb: false, + wide: false, + } + ); + test_display( + [0x18, 0x1d, 0x00, 0x00], + "andeq r1, r0, r8, lsl sp", + ); + test_decode( + [0x03, 0x30, 0x8f, 0xe0], + Instruction { + condition: ConditionCode::AL, + opcode: Opcode::ADD, + operands: [Operand::Reg(Reg::from_u8(3)), Operand::Reg(Reg::from_u8(15)), Operand::Reg(Reg::from_u8(3)), Operand::Nothing], + s: false, + thumb_w: false, + thumb: false, + wide: false, + } + ); + test_decode( + [0x03, 0x30, 0x66, 0xe0], + Instruction { + condition: ConditionCode::AL, + opcode: Opcode::RSB, + operands: [Operand::Reg(Reg::from_u8(3)), Operand::Reg(Reg::from_u8(6)), Operand::Reg(Reg::from_u8(3)), Operand::Nothing], + s: false, + thumb_w: false, + thumb: false, + wide: false, + } + ); + test_decode( + [0x43, 0x31, 0xa0, 0xe1], + Instruction { + condition: ConditionCode::AL, + opcode: Opcode::MOV, + operands: [Operand::Reg(Reg::from_u8(3)), Operand::Reg(Reg::from_u8(0)), Operand::RegShift(RegShift::from_raw(0x143)), Operand::Nothing], + s: false, + thumb_w: false, + thumb: false, + wide: false, + } + ); + test_decode( + [0x01, 0x50, 0x43, 0xe2], + Instruction { + condition: ConditionCode::AL, + opcode: Opcode::SUB, + operands: [Operand::Reg(Reg::from_u8(5)), Operand::Reg(Reg::from_u8(3)), Operand::Imm32(1), Operand::Nothing], + s: false, + thumb_w: false, + thumb: false, + wide: false, + } + ); +} + +#[test] +fn test_unconditional() { + test_armv6([0x00, 0x0a, 0x15, 0xf8], "rfeda r5"); + test_nonconformant([0x10, 0x0a, 0x15, 0xf8]); + test_armv6([0x00, 0x0a, 0x1f, 0xf8], "rfeda pc"); + test_armv6([0x00, 0x0a, 0xb5, 0xf8], "rfeia r5!"); + test_armv6([0x00, 0x0a, 0xb5, 0xf9], "rfeib r5!"); + test_armv6([0x0f, 0x05, 0x4d, 0xf8], "srsda sp, 0xf"); + test_nonconformant([0xff, 0x05, 0xed, 0xf8]); + test_armv6([0x0f, 0x05, 0x4d, 0xf8], "srsda sp, 0xf"); + test_armv6([0x0f, 0x05, 0xed, 0xf9], "srsib sp!, 0xf"); + test_armv6([0x0f, 0x05, 0xed, 0xf8], "srsia sp!, 0xf"); + test_armv5([0x01, 0x02, 0x03, 0xfb], "blx $+0xc0806"); + test_armv5([0x01, 0x02, 0x03, 0xfa], "blx $+0xc0804"); + test_armv5([0x12, 0x34, 0xcf, 0xfc], "stc2l p4, c3, [pc], {0x12}"); + test_armv5([0x12, 0x34, 0xdf, 0xfc], "ldc2l p4, c3, [pc], {0x12}"); + test_armv5([0x34, 0x78, 0xff, 0xfc], "ldc2l p8, c7, [pc], 0xd0"); + test_invalid([0x34, 0x78, 0x1f, 0xfc]); + test_armv5([0x34, 0x78, 0x9f, 0xfc], "ldc2 p8, c7, [pc], {0x34}"); + test_armv5([0x34, 0x78, 0xbf, 0xfc], "ldc2 p8, c7, [pc], 0xd0"); + test_armv5([0x34, 0x78, 0xbf, 0xfd], "ldc2 p8, c7, [pc, 0xd0]!"); + test_armv5([0x34, 0x78, 0x9f, 0xfd], "ldc2 p8, c7, [pc, 0xd0]"); + test_armv5([0x34, 0x78, 0x1f, 0xfd], "ldc2 p8, c7, [pc, -0xd0]"); + test_armv5([0x34, 0x78, 0xdf, 0xfc], "ldc2l p8, c7, [pc], {0x34}"); + test_armv6([0x34, 0x78, 0x5a, 0xfc], "mrrc2 p8, 3, r7, r10, c4"); + // Rt/Rt2 may not be r15 + test_invalid([0x34, 0x78, 0x5f, 0xfc]); + test_armv6([0x34, 0x78, 0x4a, 0xfc], "mcrr2 p8, 3, r7, r10, c4"); + // Rt/Rt2 may not be r15 + test_invalid([0x34, 0x78, 0x4f, 0xfc]); + test_armv5([0x34, 0x78, 0x4f, 0xfe], "mcr2 p8, 2, r7, c15, c4, 1"); + test_armv5([0x34, 0x78, 0x5f, 0xfe], "mrc2 p8, 2, r7, c15, c4, 1"); + test_armv5([0x24, 0x78, 0x5f, 0xfe], "cdp2 p8, 5, c7, c15, c4, 1"); + test_armv5([0x24, 0x78, 0x4f, 0xfe], "cdp2 p8, 4, c7, c15, c4, 1"); +} + +#[test] +fn test_saturating_addsub() { + test_armv5([0x50, 0x10, 0x64, 0xe1], "qdsub r1, r0, r4"); + test_nonconformant([0x50, 0x14, 0x64, 0xe1]); + test_armv5([0x50, 0x10, 0x44, 0xe1], "qdadd r1, r0, r4"); + test_nonconformant([0x50, 0x14, 0x44, 0xe1]); + test_armv5([0x50, 0x10, 0x24, 0xe1], "qsub r1, r0, r4"); + test_nonconformant([0x50, 0x14, 0x24, 0xe1]); + test_armv5([0x50, 0x10, 0x04, 0xe1], "qadd r1, r0, r4"); + test_nonconformant([0x50, 0x14, 0x04, 0xe1]); +} + +#[test] +fn test_decode_mul() { + test_decode( + [0x9c, 0x7d, 0x0b, 0x00], + Instruction { + condition: ConditionCode::EQ, + opcode: Opcode::MUL, + operands: [ + Operand::Reg(Reg::from_u8(11)), + Operand::Reg(Reg::from_u8(12)), + Operand::Reg(Reg::from_u8(13)), + Operand::Nothing, + ], + s: false, + thumb_w: false, + thumb: false, + wide: false, + } + ); + test_decode( + [0x90, 0x79, 0x09, 0x00], + Instruction { + condition: ConditionCode::EQ, + opcode: Opcode::MUL, + operands: [ + Operand::Reg(Reg::from_u8(9)), + Operand::Reg(Reg::from_u8(0)), + Operand::Reg(Reg::from_u8(9)), + Operand::Nothing, + ], + s: false, + thumb_w: false, + thumb: false, + wide: false, + } + ); + test_decode( + [0x94, 0x79, 0x09, 0x00], + Instruction { + condition: ConditionCode::EQ, + opcode: Opcode::MUL, + operands: [ + Operand::Reg(Reg::from_u8(9)), + Operand::Reg(Reg::from_u8(4)), + Operand::Reg(Reg::from_u8(9)), + Operand::Nothing, + ], + s: false, + thumb_w: false, + thumb: false, + wide: false, + } + ); +} + +static INSTRUCTION_BYTES: [u8; 4 * 60] = [ + 0x24, 0xc0, 0x9f, 0xe5, + 0x00, 0xb0, 0xa0, 0xe3, + 0x04, 0x10, 0x9d, 0xe4, + 0x0d, 0x20, 0xa0, 0xe1, + 0x04, 0x20, 0x2d, 0xe5, + 0x04, 0x00, 0x2d, 0xe5, + 0x10, 0x00, 0x9f, 0xe5, + 0x10, 0x30, 0x9f, 0xe5, + 0x04, 0xc0, 0x2d, 0xe5, + 0x4b, 0xfe, 0xff, 0xeb, + 0xd5, 0xfd, 0xff, 0xeb, + 0x90, 0x79, 0x09, 0x00, + 0x64, 0xd0, 0x01, 0x00, + 0x94, 0x79, 0x09, 0x00, + 0x14, 0x30, 0x9f, 0xe5, + 0x14, 0x20, 0x9f, 0xe5, + 0x03, 0x30, 0x8f, 0xe0, + 0x02, 0x10, 0x93, 0xe7, + 0x00, 0x00, 0x51, 0xe3, + 0x0e, 0xf0, 0xa0, 0x01, + 0x01, 0xfe, 0xff, 0xea, + 0x58, 0x75, 0x09, 0x00, + 0xec, 0x02, 0x00, 0x00, + 0xf0, 0x40, 0x2d, 0xe9, + 0x54, 0x70, 0x9f, 0xe5, + 0x00, 0x30, 0xd7, 0xe5, + 0x00, 0x00, 0x53, 0xe3, + 0xf0, 0x80, 0xbd, 0x18, + 0x48, 0x60, 0x9f, 0xe5, + 0x48, 0x30, 0x9f, 0xe5, + 0x48, 0x40, 0x9f, 0xe5, + 0x03, 0x30, 0x66, 0xe0, + 0x43, 0x31, 0xa0, 0xe1, + 0x00, 0x20, 0x94, 0xe5, + 0x01, 0x50, 0x43, 0xe2, + 0x05, 0x00, 0x52, 0xe1, + 0x06, 0x00, 0x00, 0x2a, + 0x01, 0x30, 0x82, 0xe2, + 0x00, 0x30, 0x84, 0xe5, + 0x0f, 0xe0, 0xa0, 0xe1, + 0x03, 0xf1, 0x96, 0xe7, + 0x00, 0x20, 0x94, 0xe5, + 0x05, 0x00, 0x52, 0xe1, + 0xf8, 0xff, 0xff, 0x3a, + 0x01, 0x30, 0xa0, 0xe3, + 0x00, 0x30, 0xc7, 0xe5, + 0xf0, 0x80, 0xbd, 0xe8, + 0x9c, 0x7d, 0x0b, 0x00, + 0xa0, 0x33, 0x0b, 0x00, + 0xa4, 0x33, 0x0b, 0x00, + 0xa0, 0x7d, 0x0b, 0x00, + 0x04, 0xe0, 0x2d, 0xe5, + 0x04, 0xf0, 0x9d, 0xe4, + 0x24, 0x00, 0x9f, 0xe5, + 0x00, 0x30, 0x90, 0xe5, + 0x00, 0x00, 0x53, 0xe3, + 0x04, 0xe0, 0x2d, 0xe5, + 0x04, 0xf0, 0x9d, 0x04, + 0x14, 0x30, 0x9f, 0xe5, + 0x00, 0x00, 0x53, 0xe3 + ]; + + +#[test] +fn test_decode_span() { + let mut i = 0u32; + while i < INSTRUCTION_BYTES.len() as u32 { + let mut reader = yaxpeax_arch::U8Reader::new(&INSTRUCTION_BYTES[(i as usize)..]); + let instr = InstDecoder::default().decode(&mut reader).unwrap(); + println!( + "Decoded {:02x}{:02x}{:02x}{:02x}: {}", //{:?}\n {}", + INSTRUCTION_BYTES[i as usize], + INSTRUCTION_BYTES[i as usize + 1], + INSTRUCTION_BYTES[i as usize + 2], + INSTRUCTION_BYTES[i as usize + 3], +// instr, + instr); + i += instr.len(); + } +// panic!("done"); +} +/* + * from debian 5.0.10 bash 3.2-4_arm + * 0x0001bee4 24c09fe5 ldr ip, sym.__libc_csu_fini + * 0x0001bee8 00b0a0e3 mov fp, 0 + * 0x0001beec 04109de4 pop {r1} + * 0x0001bef0 0d20a0e1 mov r2, sp + * 0x0001bef4 04202de5 str r2, [sp, -4]! + * 0x0001bef8 04002de5 str r0, [sp, -4]! + * 0x0001befc 10009fe5 ldr r0, sym.main + * 0x0001bf00 10309fe5 ldr r3, sym.__libc_csu_init + * 0x0001bf04 04c02de5 str ip, [sp, -4]! + * 0x0001bf08 4bfeffeb bl sym.imp.__libc_start_main + * 0x0001bf0c d5fdffeb bl sym.imp.abort + * 0x0001bf10 90790900 muleq sb, r0, sb + * 0x0001bf14 64d00100 andeq sp, r1, r4, rrx + * 0x0001bf18 94790900 muleq sb, r4, sb + * 0x0001bf1c 14309fe5 ldr r3, [0x0001bf38] + * 0x0001bf20 14209fe5 ldr r2, [0x0001bf3c] + * 0x0001bf24 03308fe0 add r3, pc, r3 + * 0x0001bf28 021093e7 ldr r1, [r3, r2] + * 0x0001bf2c 000051e3 cmp r1, 0 + * 0x0001bf30 0ef0a001 moveq pc, lr + * 0x0001bf34 01feffea b loc.imp.__gmon_start__ + * 0x0001bf38 58750900 andeq r7, sb, r8, asr r5 + * 0x0001bf3c ec020000 andeq r0, r0, ip, ror 5 + * 0x0001bf40 f0402de9 push {r4, r5, r6, r7, lr} + * 0x0001bf44 54709fe5 ldr r7, [0x0001bfa0] + * 0x0001bf48 0030d7e5 ldrb r3, [r7] + * 0x0001bf4c 000053e3 cmp r3, 0 + * 0x0001bf50 f080bd18 popne {r4, r5, r6, r7, pc} + * 0x0001bf54 48609fe5 ldr r6, [0x0001bfa4] + * 0x0001bf58 48309fe5 ldr r3, [0x0001bfa8] + * 0x0001bf5c 48409fe5 ldr r4, [0x0001bfac] + * 0x0001bf60 033066e0 rsb r3, r6, r3 + * 0x0001bf64 4331a0e1 asr r3, r3, 2 + * 0x0001bf68 002094e5 ldr r2, [r4] + * 0x0001bf6c 015043e2 sub r5, r3, 1 + * 0x0001bf70 050052e1 cmp r2, r5 + * 0x0001bf74 0600002a bhs 0x1bf94 + * 0x0001bf78 013082e2 add r3, r2, 1 + * 0x0001bf7c 003084e5 str r3, [r4] + * 0x0001bf80 0fe0a0e1 mov lr, pc + * 0x0001bf84 03f196e7 ldr pc, [r6, r3, lsl 2] + * 0x0001bf88 002094e5 ldr r2, [r4] + * 0x0001bf8c 050052e1 cmp r2, r5 + * 0x0001bf90 f8ffff3a blo 0x1bf78 + * 0x0001bf94 0130a0e3 mov r3, 1 + * 0x0001bf98 0030c7e5 strb r3, [r7] + * 0x0001bf9c f080bde8 pop {r4, r5, r6, r7, pc} + * 0x0001bfa0 9c7d0b00 muleq fp, ip, sp + * 0x0001bfa4 a0330b00 andeq r3, fp, r0, lsr 7 + * 0x0001bfa8 a4330b00 andeq r3, fp, r4, lsr 7 + * 0x0001bfac a07d0b00 andeq r7, fp, r0, lsr 27 + * 0x0001bfb0 04e02de5 str lr, [sp, -4]! + * 0x0001bfb4 04f09de4 pop {pc} + * 0x0001bfb8 24009fe5 ldr r0, [0x0001bfe4] + * 0x0001bfbc 003090e5 ldr r3, [r0] + * 0x0001bfc0 000053e3 cmp r3, 0 + * 0x0001bfc4 04e02de5 str lr, [sp, -4]! + * 0x0001bfc8 04f09d04 popeq {pc} + * 0x0001bfcc 14309fe5 ldr r3, [0x0001bfe8] + * 0x0001bfd0 000053e3 cmp r3, 0 + */ + +/* +use test::Bencher; +#[bench] +pub fn bench_60000_instrs(b: &mut Bencher) { + b.iter(|| { + for i in (0..1000) { + let mut iter = INSTRUCTION_BYTES.iter().map(|x| *x); + let decoder = InstDecoder::default(); + let mut result = Instruction::default(); + loop { + match decoder.decode_into(&mut result, &mut iter) { + Ok(result) => { + test::black_box(&result); + }, + Err(_) => { + break; + } + } + } + } + }); +} +*/ diff --git a/tests/armv7/thumb.rs b/tests/armv7/thumb.rs new file mode 100644 index 0000000..9182f6e --- /dev/null +++ b/tests/armv7/thumb.rs @@ -0,0 +1,4084 @@ +use yaxpeax_arch::{Arch, Decoder}; +use yaxpeax_arm::armv7::{ARMv7, Instruction}; + +type InstDecoder = ::Decoder; + +#[allow(dead_code)] +fn test_invalid_under(decoder: &InstDecoder, data: &[u8]) { + let mut reader = yaxpeax_arch::U8Reader::new(&data[..]); + match decoder.decode(&mut reader) { + Err(_) => { }, + Ok(inst) => { + panic!( + "unexpected successful decode for {:#x?}\ngot: {}", + data, + inst + ); + } + } +} + +#[allow(dead_code)] +fn test_display_under(decoder: &InstDecoder, data: [u8; 4], expected: &'static str) { + let mut reader = yaxpeax_arch::U8Reader::new(&data[..]); + let instr = match decoder.decode(&mut reader) { + Err(e) => { + panic!("failed to decode {:#x?}: {}", data, e) + } + Ok(instr) => instr, + }; + let displayed = format!("{}", instr); + assert!( + displayed == expected, + "decode error for {:#x?}:\n decoded: {:?}\n expected: {:?}\n", + data, + displayed, expected + ); +} + +#[allow(dead_code)] +fn test_decode(data: &[u8], expected: Instruction) { + let mut reader = yaxpeax_arch::U8Reader::new(data); + let instr = match InstDecoder::default_thumb().decode(&mut reader) { + Err(e) => { + panic!("failed to decode {:#x?}: {}", data, e) + } + Ok(instr) => instr, + }; + assert!( + instr == expected, + "decode error for {:#x?}:\n decoded: {:?}\n expected: {:?}\n", + data, + instr, expected + ); +} + +#[allow(dead_code)] +fn test_invalid(data: &[u8]) { + test_invalid_under(&InstDecoder::default_thumb(), data); +} + +fn test_display(data: &[u8], expected: &'static str) { + let mut reader = yaxpeax_arch::U8Reader::new(data); + let instr = match InstDecoder::default_thumb().decode(&mut reader) { + Err(e) => { + panic!("failed to decode {:#x?}: {}", data, e) + } + Ok(instr) => instr, + }; + let text = format!("{}", instr); + assert!( + text == expected, + "display error for {:#x?}\n decoded: {:?}\n displayed: {}\n expected: {}\n", + data, + instr, + text, expected + ); +} + +#[test] +fn test_unpredictable_instructions() { + test_invalid(&[0x80, 0xfa, 0x40, 0x00]); +} + +#[test] +fn test_decode_add_cases() { + test_display( + &[0x01, 0x44], + "add r1, r0" + ); + test_display( + &[0x01, 0xa8], + "add r0, sp, 0x4" + ); + test_display( + &[0x01, 0xa9], + "add r1, sp, 0x4" + ); + test_display( + &[0x01, 0xaa], + "add r2, sp, 0x4" + ); + test_display( + &[0x01, 0xab], + "add r3, sp, 0x4" + ); + test_display( + &[0x01, 0xad], + "add r5, sp, 0x4" + ); + test_display( + &[0x01, 0xae], + "add r6, sp, 0x4" + ); + test_display( + &[0x01, 0xaf], + "add r7, sp, 0x4" + ); + test_display( + &[0x05, 0xac], + "add r4, sp, 0x14" + ); + test_display( + &[0x61, 0xb0], + "add sp, sp, 0x184" + ); + test_display( + &[0x01, 0xb0], + "add sp, sp, 0x4" + ); + test_display( + &[0x02, 0x44], + "add r2, r0" + ); + test_display( + &[0x02, 0xb0], + "add sp, sp, 0x8" + ); + test_display( + &[0x03, 0x44], + "add r3, r0" + ); + test_display( + &[0x17, 0x44], + "add r7, r2" + ); + test_display( + &[0x1b, 0x44], + "add r3, r3" + ); + test_display( + &[0x54, 0x44], + "add r4, r10" + ); + test_display( + &[0x57, 0x44], + "add r7, r10" + ); + test_display( + &[0x5a, 0x44], + "add r2, fp" + ); + test_display( + &[0x61, 0x44], + "add r1, ip" + ); + test_display( + &[0x68, 0x44], + "add r0, sp" + ); + test_display( + &[0x69, 0x44], + "add r1, sp" + ); + test_display( + &[0x6a, 0x44], + "add r2, sp" + ); + test_display( + &[0x6b, 0x44], + "add r3, sp" + ); + test_display( + &[0x6d, 0x44], + "add r5, sp" + ); + test_display( + &[0x6e, 0x44], + "add r6, sp" + ); + test_display( + &[0x6f, 0x44], + "add r7, sp" + ); + test_display( + &[0x75, 0x44], + "add r5, lr" + ); + test_display( + &[0x79, 0x44], + "add r1, pc" + ); + test_display( + &[0xc0, 0x44], + "add r8, r8" + ); + test_display( + &[0xc1, 0x44], + "add sb, r8" + ); + test_display( + &[0xc2, 0x44], + "add r10, r8" + ); + test_display( + &[0xc3, 0x44], + "add fp, r8" + ); + test_display( + &[0xc4, 0x44], + "add ip, r8" + ); + test_display( + &[0xc5, 0x44], + "add sp, r8" + ); + test_display( + &[0xc6, 0x44], + "add lr, r8" + ); + test_display( + &[0xc7, 0x44], + "add pc, r8" + ); + test_display( + &[0xc8, 0x44], + "add r8, sb" + ); + test_display( + &[0xc9, 0x44], + "add sb, sb" + ); + test_display( + &[0xca, 0x44], + "add r10, sb" + ); + test_display( + &[0xcb, 0x44], + "add fp, sb" + ); + test_display( + &[0xcc, 0x44], + "add ip, sb" + ); + test_display( + &[0xcd, 0x44], + "add sp, sb" + ); + test_display( + &[0xce, 0x44], + "add lr, sb" + ); + test_display( + &[0xcf, 0x44], + "add pc, sb" + ); + test_display( + &[0xd0, 0x44], + "add r8, r10" + ); + test_display( + &[0xd1, 0x44], + "add sb, r10" + ); + test_display( + &[0xd2, 0x44], + "add r10, r10" + ); + test_display( + &[0xd3, 0x44], + "add fp, r10" + ); + test_display( + &[0xd4, 0x44], + "add ip, r10" + ); + test_display( + &[0xd5, 0x44], + "add sp, r10" + ); + test_display( + &[0xd6, 0x44], + "add lr, r10" + ); + test_display( + &[0xd7, 0x44], + "add pc, r10" + ); + test_display( + &[0xd8, 0x44], + "add r8, fp" + ); + test_display( + &[0xd9, 0x44], + "add sb, fp" + ); + test_display( + &[0xda, 0x44], + "add r10, fp" + ); + test_display( + &[0xdb, 0x44], + "add fp, fp" + ); + test_display( + &[0xdc, 0x44], + "add ip, fp" + ); + test_display( + &[0xdd, 0x44], + "add sp, fp" + ); + test_display( + &[0xde, 0x44], + "add lr, fp" + ); + test_display( + &[0xdf, 0x44], + "add pc, fp" + ); + test_display( + &[0xe0, 0x44], + "add r8, ip" + ); + test_display( + &[0xe1, 0x44], + "add sb, ip" + ); + test_display( + &[0xe2, 0x44], + "add r10, ip" + ); + test_display( + &[0xe3, 0x44], + "add fp, ip" + ); + test_display( + &[0xe4, 0x44], + "add ip, ip" + ); + test_display( + &[0xe5, 0x44], + "add sp, ip" + ); + test_display( + &[0xe6, 0x44], + "add lr, ip" + ); + test_display( + &[0xe7, 0x44], + "add pc, ip" + ); + test_display( + &[0xe8, 0x44], + "add r8, sp" + ); + test_display( + &[0xe9, 0x44], + "add sb, sp" + ); + test_display( + &[0xea, 0x44], + "add r10, sp" + ); + test_display( + &[0xeb, 0x44], + "add fp, sp" + ); + test_display( + &[0xec, 0x44], + "add ip, sp" + ); + test_display( + &[0xed, 0x44], + "add sp, sp" + ); + test_display( + &[0xee, 0x44], + "add lr, sp" + ); + test_display( + &[0xef, 0x44], + "add pc, sp" + ); + test_display( + &[0xf0, 0x44], + "add r8, lr" + ); + test_display( + &[0xf1, 0x44], + "add sb, lr" + ); + test_display( + &[0xf2, 0x44], + "add r10, lr" + ); + test_display( + &[0xf3, 0x44], + "add fp, lr" + ); + test_display( + &[0xf4, 0x44], + "add ip, lr" + ); + test_display( + &[0xf5, 0x44], + "add sp, lr" + ); + test_display( + &[0xf6, 0x44], + "add lr, lr" + ); + test_display( + &[0xf7, 0x44], + "add pc, lr" + ); + test_display( + &[0xf8, 0x44], + "add r8, pc" + ); + test_display( + &[0xf9, 0x44], + "add sb, pc" + ); + test_display( + &[0xfa, 0x44], + "add r10, pc" + ); + test_display( + &[0xfb, 0x44], + "add fp, pc" + ); + test_display( + &[0xfc, 0x44], + "add ip, pc" + ); + test_display( + &[0xfd, 0x44], + "add sp, pc" + ); + test_display( + &[0xfe, 0x44], + "add lr, pc" + ); + test_display( + &[0xff, 0x44], + "add pc, pc" + ); +} +#[test] +fn test_decode_adr_cases() { + test_display( + &[0x00, 0xa3], + "adr r3, 0x0" + ); + test_display( + &[0x28, 0xa7], + "adr r7, 0xa0" + ); + test_display( + &[0x29, 0xa0], + "adr r0, 0xa4" + ); + test_display( + &[0xff, 0xa6], + "adr r6, 0x3fc" + ); + test_display( + &[0xff, 0xa7], + "adr r7, 0x3fc" + ); + test_display( + &[0x0f, 0xf2, 0x4f, 0x56], + "add r6, pc, 0x54f" + ); + test_display( + &[0xaf, 0xf2, 0x4f, 0x56], + "sub r6, pc, 0x54f" + ); +} +#[test] +fn test_decode_bcc_cases() { + test_display( + &[0x80, 0x47], + "blx r0" + ); + test_display( + &[0x88, 0x47], + "blx r1" + ); + test_display( + &[0x90, 0x47], + "blx r2" + ); + test_display( + &[0x98, 0x47], + "blx r3" + ); + test_display( + &[0xa0, 0x47], + "blx r4" + ); + test_display( + &[0xa8, 0x47], + "blx r5" + ); + test_display( + &[0xb0, 0x47], + "blx r6" + ); + test_display( + &[0xb8, 0x47], + "blx r7" + ); + test_display( + &[0xc0, 0x47], + "blx r8" + ); + test_display( + &[0xc8, 0x47], + "blx sb" + ); + test_display( + &[0xd0, 0x47], + "blx r10" + ); + test_display( + &[0xd8, 0x47], + "blx fp" + ); + test_display( + &[0xe0, 0x47], + "blx ip" + ); + test_display( + &[0xe8, 0x47], + "blx sp" + ); + test_display( + &[0xf0, 0x47], + "blx lr" + ); + test_display( + &[0xf8, 0x47], + "blx pc" + ); + test_display( + &[0xfe, 0xd0], + "beq $-0x2" + ); + test_display( + &[0xfe, 0xd1], + "bne $-0x2" + ); + test_display( + &[0xfe, 0xd2], + "bhs $-0x2" + ); + test_display( + &[0xfe, 0xd3], + "blo $-0x2" + ); + test_display( + &[0xfe, 0xd4], + "bmi $-0x2" + ); + test_display( + &[0xfe, 0xd5], + "bpl $-0x2" + ); + test_display( + &[0xfe, 0xd6], + "bvs $-0x2" + ); + test_display( + &[0xfe, 0xd7], + "bvc $-0x2" + ); + test_display( + &[0xfe, 0xd8], + "bhi $-0x2" + ); + test_display( + &[0xfe, 0xd9], + "bls $-0x2" + ); + test_display( + &[0xfe, 0xda], + "bge $-0x2" + ); + test_display( + &[0xfe, 0xdb], + "blt $-0x2" + ); + test_display( + &[0xfe, 0xdc], + "bgt $-0x2" + ); + test_display( + &[0xfe, 0xdd], + "ble $-0x2" + ); + test_display( + &[0xd3, 0xd0], + "beq $-0x58" + ); + test_display( + &[0xd3, 0xd1], + "bne $-0x58" + ); + test_display( + &[0xd3, 0xd2], + "bhs $-0x58" + ); + test_display( + &[0xd3, 0xd3], + "blo $-0x58" + ); + test_display( + &[0xd3, 0xd4], + "bmi $-0x58" + ); + test_display( + &[0xd3, 0xd5], + "bpl $-0x58" + ); + test_display( + &[0xd3, 0xd6], + "bvs $-0x58" + ); + test_display( + &[0xd3, 0xd7], + "bvc $-0x58" + ); + test_display( + &[0xd3, 0xd8], + "bhi $-0x58" + ); + test_display( + &[0xd3, 0xd9], + "bls $-0x58" + ); + test_display( + &[0xd3, 0xda], + "bge $-0x58" + ); + test_display( + &[0xd3, 0xdb], + "blt $-0x58" + ); + test_display( + &[0xd3, 0xdc], + "bgt $-0x58" + ); + test_display( + &[0xd3, 0xdd], + "ble $-0x58" + ); + test_display( + &[0xfd, 0xd0], + "beq $-0x4" + ); + test_display( + &[0xfd, 0xd1], + "bne $-0x4" + ); + test_display( + &[0xfd, 0xd2], + "bhs $-0x4" + ); + test_display( + &[0xfd, 0xd3], + "blo $-0x4" + ); + test_display( + &[0xfd, 0xd4], + "bmi $-0x4" + ); + test_display( + &[0xfd, 0xd5], + "bpl $-0x4" + ); + test_display( + &[0xfd, 0xd6], + "bvs $-0x4" + ); + test_display( + &[0xfd, 0xd7], + "bvc $-0x4" + ); + test_display( + &[0xfd, 0xd8], + "bhi $-0x4" + ); + test_display( + &[0xfd, 0xd9], + "bls $-0x4" + ); + test_display( + &[0xfd, 0xda], + "bge $-0x4" + ); + test_display( + &[0xfd, 0xdb], + "blt $-0x4" + ); + test_display( + &[0xfd, 0xdc], + "bgt $-0x4" + ); + test_display( + &[0xfd, 0xdd], + "ble $-0x4" + ); +} +#[test] +fn test_decode_bkpt_cases() { + test_display( + &[0x00, 0xbe], + "bkpt 0x0" + ); + test_display( + &[0x75, 0xbe], + "bkpt 0x75" + ); + test_display( + &[0xff, 0xbe], + "bkpt 0xff" + ); +} +#[test] +fn test_decode_bx_cases() { + test_display( + &[0x00, 0x47], + "bx r0" + ); + test_display( + &[0x01, 0x47], + "bx r0" + ); + test_display( + &[0x02, 0x47], + "bx r0" + ); + test_display( + &[0x03, 0x47], + "bx r0" + ); + test_display( + &[0x04, 0x47], + "bx r0" + ); + test_display( + &[0x05, 0x47], + "bx r0" + ); + test_display( + &[0x06, 0x47], + "bx r0" + ); + test_display( + &[0x07, 0x47], + "bx r0" + ); + test_display( + &[0x08, 0x47], + "bx r1" + ); + test_display( + &[0x09, 0x47], + "bx r1" + ); + test_display( + &[0x0a, 0x47], + "bx r1" + ); + test_display( + &[0x0b, 0x47], + "bx r1" + ); + test_display( + &[0x0c, 0x47], + "bx r1" + ); + test_display( + &[0x0d, 0x47], + "bx r1" + ); + test_display( + &[0x0e, 0x47], + "bx r1" + ); + test_display( + &[0x0f, 0x47], + "bx r1" + ); + test_display( + &[0x10, 0x47], + "bx r2" + ); + test_display( + &[0x11, 0x47], + "bx r2" + ); + test_display( + &[0x12, 0x47], + "bx r2" + ); + test_display( + &[0x13, 0x47], + "bx r2" + ); + test_display( + &[0x14, 0x47], + "bx r2" + ); + test_display( + &[0x15, 0x47], + "bx r2" + ); + test_display( + &[0x16, 0x47], + "bx r2" + ); + test_display( + &[0x17, 0x47], + "bx r2" + ); + test_display( + &[0x18, 0x47], + "bx r3" + ); + test_display( + &[0x19, 0x47], + "bx r3" + ); + test_display( + &[0x1a, 0x47], + "bx r3" + ); + test_display( + &[0x1b, 0x47], + "bx r3" + ); + test_display( + &[0x1c, 0x47], + "bx r3" + ); + test_display( + &[0x1d, 0x47], + "bx r3" + ); + test_display( + &[0x1e, 0x47], + "bx r3" + ); + test_display( + &[0x1f, 0x47], + "bx r3" + ); + test_display( + &[0x20, 0x47], + "bx r4" + ); + test_display( + &[0x21, 0x47], + "bx r4" + ); + test_display( + &[0x22, 0x47], + "bx r4" + ); + test_display( + &[0x23, 0x47], + "bx r4" + ); + test_display( + &[0x24, 0x47], + "bx r4" + ); + test_display( + &[0x25, 0x47], + "bx r4" + ); + test_display( + &[0x26, 0x47], + "bx r4" + ); + test_display( + &[0x27, 0x47], + "bx r4" + ); + test_display( + &[0x28, 0x47], + "bx r5" + ); + test_display( + &[0x29, 0x47], + "bx r5" + ); + test_display( + &[0x2a, 0x47], + "bx r5" + ); + test_display( + &[0x2b, 0x47], + "bx r5" + ); + test_display( + &[0x2c, 0x47], + "bx r5" + ); + test_display( + &[0x2d, 0x47], + "bx r5" + ); + test_display( + &[0x2e, 0x47], + "bx r5" + ); + test_display( + &[0x2f, 0x47], + "bx r5" + ); + test_display( + &[0x30, 0x47], + "bx r6" + ); + test_display( + &[0x31, 0x47], + "bx r6" + ); + test_display( + &[0x32, 0x47], + "bx r6" + ); + test_display( + &[0x33, 0x47], + "bx r6" + ); + test_display( + &[0x34, 0x47], + "bx r6" + ); + test_display( + &[0x35, 0x47], + "bx r6" + ); + test_display( + &[0x36, 0x47], + "bx r6" + ); + test_display( + &[0x37, 0x47], + "bx r6" + ); + test_display( + &[0x38, 0x47], + "bx r7" + ); + test_display( + &[0x39, 0x47], + "bx r7" + ); + test_display( + &[0x3a, 0x47], + "bx r7" + ); + test_display( + &[0x3b, 0x47], + "bx r7" + ); + test_display( + &[0x3c, 0x47], + "bx r7" + ); + test_display( + &[0x3d, 0x47], + "bx r7" + ); + test_display( + &[0x3e, 0x47], + "bx r7" + ); + test_display( + &[0x3f, 0x47], + "bx r7" + ); + test_display( + &[0x40, 0x47], + "bx r8" + ); + test_display( + &[0x41, 0x47], + "bx r8" + ); + test_display( + &[0x42, 0x47], + "bx r8" + ); + test_display( + &[0x43, 0x47], + "bx r8" + ); + test_display( + &[0x44, 0x47], + "bx r8" + ); + test_display( + &[0x45, 0x47], + "bx r8" + ); + test_display( + &[0x46, 0x47], + "bx r8" + ); + test_display( + &[0x47, 0x47], + "bx r8" + ); + test_display( + &[0x48, 0x47], + "bx sb" + ); + test_display( + &[0x49, 0x47], + "bx sb" + ); + test_display( + &[0x4a, 0x47], + "bx sb" + ); + test_display( + &[0x4b, 0x47], + "bx sb" + ); + test_display( + &[0x4c, 0x47], + "bx sb" + ); + test_display( + &[0x4d, 0x47], + "bx sb" + ); + test_display( + &[0x4e, 0x47], + "bx sb" + ); + test_display( + &[0x4f, 0x47], + "bx sb" + ); + test_display( + &[0x50, 0x47], + "bx r10" + ); + test_display( + &[0x51, 0x47], + "bx r10" + ); + test_display( + &[0x52, 0x47], + "bx r10" + ); + test_display( + &[0x53, 0x47], + "bx r10" + ); + test_display( + &[0x54, 0x47], + "bx r10" + ); + test_display( + &[0x55, 0x47], + "bx r10" + ); + test_display( + &[0x56, 0x47], + "bx r10" + ); + test_display( + &[0x57, 0x47], + "bx r10" + ); + test_display( + &[0x58, 0x47], + "bx fp" + ); + test_display( + &[0x59, 0x47], + "bx fp" + ); + test_display( + &[0x5a, 0x47], + "bx fp" + ); + test_display( + &[0x5b, 0x47], + "bx fp" + ); + test_display( + &[0x5c, 0x47], + "bx fp" + ); + test_display( + &[0x5d, 0x47], + "bx fp" + ); + test_display( + &[0x5e, 0x47], + "bx fp" + ); + test_display( + &[0x5f, 0x47], + "bx fp" + ); + test_display( + &[0x60, 0x47], + "bx ip" + ); + test_display( + &[0x61, 0x47], + "bx ip" + ); + test_display( + &[0x62, 0x47], + "bx ip" + ); + test_display( + &[0x63, 0x47], + "bx ip" + ); + test_display( + &[0x64, 0x47], + "bx ip" + ); + test_display( + &[0x65, 0x47], + "bx ip" + ); + test_display( + &[0x66, 0x47], + "bx ip" + ); + test_display( + &[0x67, 0x47], + "bx ip" + ); + test_display( + &[0x68, 0x47], + "bx sp" + ); + test_display( + &[0x69, 0x47], + "bx sp" + ); + test_display( + &[0x6a, 0x47], + "bx sp" + ); + test_display( + &[0x6b, 0x47], + "bx sp" + ); + test_display( + &[0x6c, 0x47], + "bx sp" + ); + test_display( + &[0x6d, 0x47], + "bx sp" + ); + test_display( + &[0x6e, 0x47], + "bx sp" + ); + test_display( + &[0x6f, 0x47], + "bx sp" + ); + test_display( + &[0x70, 0x47], + "bx lr" + ); + test_display( + &[0x71, 0x47], + "bx lr" + ); + test_display( + &[0x72, 0x47], + "bx lr" + ); + test_display( + &[0x73, 0x47], + "bx lr" + ); + test_display( + &[0x74, 0x47], + "bx lr" + ); + test_display( + &[0x75, 0x47], + "bx lr" + ); + test_display( + &[0x76, 0x47], + "bx lr" + ); + test_display( + &[0x77, 0x47], + "bx lr" + ); + test_display( + &[0x78, 0x47], + "bx pc" + ); + test_display( + &[0x79, 0x47], + "bx pc" + ); + test_display( + &[0x7a, 0x47], + "bx pc" + ); + test_display( + &[0x7b, 0x47], + "bx pc" + ); + test_display( + &[0x7c, 0x47], + "bx pc" + ); + test_display( + &[0x7d, 0x47], + "bx pc" + ); + test_display( + &[0x7e, 0x47], + "bx pc" + ); + test_display( + &[0x7f, 0x47], + "bx pc" + ); +} +#[test] +fn test_decode_cbz_cbnz_cases() { + test_display( + &[0x01, 0xb1], + "cbz r1, $+0x2" // original test: 0x4. assume address is 0, so $ is 2, +2 makes 4? + ); + test_display( + &[0x01, 0xb3], + "cbz r1, $+0x42" // original test: 0x4. assume address is 0, so $ is 2, +2 makes 4? + ); + test_display( + &[0x01, 0xb9], + "cbnz r1, $+0x2" // original test: 0x4. assume address is 0, so $ is 2, +2 makes 4? + ); + test_display( + &[0x01, 0xbb], + "cbnz r1, $+0x42" // original test: 0x4. assume address is 0, so $ is 2, +2 makes 4? + ); + test_display( + &[0x07, 0xb1], + "cbz r7, $+0x2" // original test: 0x4. assume address is 0, so $ is 2, +2 makes 4? + ); + test_display( + &[0x07, 0xb3], + "cbz r7, $+0x42" + ); + test_display( + &[0x07, 0xb9], + "cbnz r7, $+0x2" + ); + test_display( + &[0x07, 0xbb], + "cbnz r7, $+0x42" + ); + test_display( + &[0xff, 0xb1], + "cbz r7, $+0x40" + ); + test_display( + &[0xff, 0xb3], + "cbz r7, $+0x80" + ); + test_display( + &[0xff, 0xb9], + "cbnz r7, $+0x40" + ); + test_display( + &[0xff, 0xbb], + "cbnz r7, $+0x80" + ); +} +#[test] +fn test_decode_cmn_test_cases() { + test_display( + &[0x33, 0x42], + "tst r3, r6" + ); + test_display( + &[0xf3, 0x42], + "cmn r3, r6" + ); +} +#[test] +fn test_decode_cmp_cases() { + test_display( + &[0x00, 0x45], + "cmp r0, r0" + ); + test_display( + &[0x01, 0x45], + "cmp r1, r0" + ); + test_display( + &[0x02, 0x28], + "cmp r0, 0x2" + ); + test_display( + &[0x02, 0x29], + "cmp r1, 0x2" + ); + test_display( + &[0x02, 0x2a], + "cmp r2, 0x2" + ); + test_display( + &[0x02, 0x2b], + "cmp r3, 0x2" + ); + test_display( + &[0x02, 0x2c], + "cmp r4, 0x2" + ); + test_display( + &[0x02, 0x2d], + "cmp r5, 0x2" + ); + test_display( + &[0x02, 0x2e], + "cmp r6, 0x2" + ); + test_display( + &[0x02, 0x2f], + "cmp r7, 0x2" + ); + test_display( + &[0xff, 0x28], + "cmp r0, 0xff" + ); + test_display( + &[0xff, 0x29], + "cmp r1, 0xff" + ); + test_display( + &[0xff, 0x2a], + "cmp r2, 0xff" + ); + test_display( + &[0xff, 0x2b], + "cmp r3, 0xff" + ); + test_display( + &[0xff, 0x2c], + "cmp r4, 0xff" + ); + test_display( + &[0xff, 0x2d], + "cmp r5, 0xff" + ); + test_display( + &[0xff, 0x2e], + "cmp r6, 0xff" + ); + test_display( + &[0xff, 0x2f], + "cmp r7, 0xff" + ); + test_display( + &[0x53, 0x45], + "cmp r3, r10" + ); + test_display( + &[0x6c, 0x45], + "cmp r4, sp" + ); + test_display( + &[0x7e, 0x45], + "cmp r6, pc" + ); + test_display( + &[0xfe, 0x45], + "cmp lr, pc" + ); + test_display( + &[0xff, 0x45], + "cmp pc, pc" + ); +} +#[test] +fn test_decode_it_cases() { + test_display( + &[0x01, 0xbf], + "itttt eq" + ); + test_display( + &[0x03, 0xbf], + "ittte eq" + ); + test_display( + &[0x05, 0xbf], + "ittet eq" + ); + test_display( + &[0x07, 0xbf], + "ittee eq" + ); + test_display( + &[0x09, 0xbf], + "itett eq" + ); + test_display( + &[0x0b, 0xbf], + "itete eq" + ); + test_display( + &[0x0d, 0xbf], + "iteet eq" + ); + test_display( + &[0x0f, 0xbf], + "iteee eq" + ); + test_display( + &[0x11, 0xbf], + "iteee ne" + ); + test_display( + &[0x13, 0xbf], + "iteet ne" + ); + test_display( + &[0x15, 0xbf], + "itete ne" + ); + test_display( + &[0x17, 0xbf], + "itett ne" + ); + test_display( + &[0x19, 0xbf], + "ittee ne" + ); + test_display( + &[0x1b, 0xbf], + "ittet ne" + ); + test_display( + &[0x1d, 0xbf], + "ittte ne" + ); + test_display( + &[0x1f, 0xbf], + "itttt ne" + ); + test_display( + &[0x21, 0xbf], + "itttt hs" + ); + test_display( + &[0x23, 0xbf], + "ittte hs" + ); + test_display( + &[0x25, 0xbf], + "ittet hs" + ); + test_display( + &[0x27, 0xbf], + "ittee hs" + ); + test_display( + &[0x29, 0xbf], + "itett hs" + ); + test_display( + &[0x2b, 0xbf], + "itete hs" + ); + test_display( + &[0x2d, 0xbf], + "iteet hs" + ); + test_display( + &[0x2f, 0xbf], + "iteee hs" + ); + test_display( + &[0x31, 0xbf], + "iteee lo" + ); + test_display( + &[0x33, 0xbf], + "iteet lo" + ); + test_display( + &[0x35, 0xbf], + "itete lo" + ); + test_display( + &[0x37, 0xbf], + "itett lo" + ); + test_display( + &[0x39, 0xbf], + "ittee lo" + ); + test_display( + &[0x3b, 0xbf], + "ittet lo" + ); + test_display( + &[0x3d, 0xbf], + "ittte lo" + ); + test_display( + &[0x3f, 0xbf], + "itttt lo" + ); + test_display( + &[0x41, 0xbf], + "itttt mi" + ); + test_display( + &[0x43, 0xbf], + "ittte mi" + ); + test_display( + &[0x45, 0xbf], + "ittet mi" + ); + test_display( + &[0x47, 0xbf], + "ittee mi" + ); + test_display( + &[0x49, 0xbf], + "itett mi" + ); + test_display( + &[0x4b, 0xbf], + "itete mi" + ); + test_display( + &[0x4d, 0xbf], + "iteet mi" + ); + test_display( + &[0x4f, 0xbf], + "iteee mi" + ); + test_display( + &[0x51, 0xbf], + "iteee pl" + ); + test_display( + &[0x53, 0xbf], + "iteet pl" + ); + test_display( + &[0x55, 0xbf], + "itete pl" + ); + test_display( + &[0x57, 0xbf], + "itett pl" + ); + test_display( + &[0x59, 0xbf], + "ittee pl" + ); + test_display( + &[0x5b, 0xbf], + "ittet pl" + ); + test_display( + &[0x5d, 0xbf], + "ittte pl" + ); + test_display( + &[0x5f, 0xbf], + "itttt pl" + ); + test_display( + &[0x61, 0xbf], + "itttt vs" + ); + test_display( + &[0x63, 0xbf], + "ittte vs" + ); + test_display( + &[0x65, 0xbf], + "ittet vs" + ); + test_display( + &[0x67, 0xbf], + "ittee vs" + ); + test_display( + &[0x69, 0xbf], + "itett vs" + ); + test_display( + &[0x6b, 0xbf], + "itete vs" + ); + test_display( + &[0x6d, 0xbf], + "iteet vs" + ); + test_display( + &[0x6f, 0xbf], + "iteee vs" + ); + test_display( + &[0x71, 0xbf], + "iteee vc" + ); + test_display( + &[0x73, 0xbf], + "iteet vc" + ); + test_display( + &[0x75, 0xbf], + "itete vc" + ); + test_display( + &[0x77, 0xbf], + "itett vc" + ); + test_display( + &[0x79, 0xbf], + "ittee vc" + ); + test_display( + &[0x7b, 0xbf], + "ittet vc" + ); + test_display( + &[0x7d, 0xbf], + "ittte vc" + ); + test_display( + &[0x7f, 0xbf], + "itttt vc" + ); + test_display( + &[0x81, 0xbf], + "itttt hi" + ); + test_display( + &[0x83, 0xbf], + "ittte hi" + ); + test_display( + &[0x85, 0xbf], + "ittet hi" + ); + test_display( + &[0x87, 0xbf], + "ittee hi" + ); + test_display( + &[0x89, 0xbf], + "itett hi" + ); + test_display( + &[0x8b, 0xbf], + "itete hi" + ); + test_display( + &[0x8d, 0xbf], + "iteet hi" + ); + test_display( + &[0x8f, 0xbf], + "iteee hi" + ); + test_display( + &[0x91, 0xbf], + "iteee ls" + ); + test_display( + &[0x93, 0xbf], + "iteet ls" + ); + test_display( + &[0x95, 0xbf], + "itete ls" + ); + test_display( + &[0x97, 0xbf], + "itett ls" + ); + test_display( + &[0x99, 0xbf], + "ittee ls" + ); + test_display( + &[0x9b, 0xbf], + "ittet ls" + ); + test_display( + &[0x9d, 0xbf], + "ittte ls" + ); + test_display( + &[0x9f, 0xbf], + "itttt ls" + ); + test_display( + &[0xa1, 0xbf], + "itttt ge" + ); + test_display( + &[0xa3, 0xbf], + "ittte ge" + ); + test_display( + &[0xa5, 0xbf], + "ittet ge" + ); + test_display( + &[0xa7, 0xbf], + "ittee ge" + ); + test_display( + &[0xa9, 0xbf], + "itett ge" + ); + test_display( + &[0xab, 0xbf], + "itete ge" + ); + test_display( + &[0xad, 0xbf], + "iteet ge" + ); + test_display( + &[0xaf, 0xbf], + "iteee ge" + ); + test_display( + &[0xb1, 0xbf], + "iteee lt" + ); + test_display( + &[0xb3, 0xbf], + "iteet lt" + ); + test_display( + &[0xb5, 0xbf], + "itete lt" + ); + test_display( + &[0xb7, 0xbf], + "itett lt" + ); + test_display( + &[0xb9, 0xbf], + "ittee lt" + ); + test_display( + &[0xbb, 0xbf], + "ittet lt" + ); + test_display( + &[0xbd, 0xbf], + "ittte lt" + ); + test_display( + &[0xbf, 0xbf], + "itttt lt" + ); + test_display( + &[0xc1, 0xbf], + "itttt gt" + ); + test_display( + &[0xc3, 0xbf], + "ittte gt" + ); + test_display( + &[0xc5, 0xbf], + "ittet gt" + ); + test_display( + &[0xc7, 0xbf], + "ittee gt" + ); + test_display( + &[0xc9, 0xbf], + "itett gt" + ); + test_display( + &[0xcb, 0xbf], + "itete gt" + ); + test_display( + &[0xcd, 0xbf], + "iteet gt" + ); + test_display( + &[0xcf, 0xbf], + "iteee gt" + ); + test_display( + &[0xd1, 0xbf], + "iteee le" + ); + test_display( + &[0xd3, 0xbf], + "iteet le" + ); + test_display( + &[0xd5, 0xbf], + "itete le" + ); + test_display( + &[0xd7, 0xbf], + "itett le" + ); + test_display( + &[0xd9, 0xbf], + "ittee le" + ); + test_display( + &[0xdb, 0xbf], + "ittet le" + ); + test_display( + &[0xdd, 0xbf], + "ittte le" + ); + test_display( + &[0xdf, 0xbf], + "itttt le" + ); + test_display( + &[0xe1, 0xbf], + "itttt al" + ); + test_display( + &[0xe3, 0xbf], + "ittte al" + ); + test_display( + &[0xe5, 0xbf], + "ittet al" + ); + test_display( + &[0xe7, 0xbf], + "ittee al" + ); + test_display( + &[0xe9, 0xbf], + "itett al" + ); + test_display( + &[0xeb, 0xbf], + "itete al" + ); + test_display( + &[0xed, 0xbf], + "iteet al" + ); + test_display( + &[0xef, 0xbf], + "iteee al" + ); +} +#[test] +fn test_decode_ldm_16b_cases() { + test_display( + &[0x80, 0xc8], + "ldm r0!, {r7}" + ); + test_display( + &[0x80, 0xc9], + "ldm r1!, {r7}" + ); + test_display( + &[0x80, 0xca], + "ldm r2!, {r7}" + ); + test_display( + &[0x80, 0xcb], + "ldm r3!, {r7}" + ); + test_display( + &[0x80, 0xcc], + "ldm r4!, {r7}" + ); + test_display( + &[0x80, 0xcd], + "ldm r5!, {r7}" + ); + test_display( + &[0x80, 0xce], + "ldm r6!, {r7}" + ); + test_display( + &[0x80, 0xcf], + "ldm r7, {r7}" + ); + test_display( + &[0xb0, 0xce], + "ldm r6!, {r4, r5, r7}" + ); + test_display( + &[0xb0, 0xcf], + "ldm r7, {r4, r5, r7}" + ); + test_display( + &[0xc0, 0xcb], + "ldm r3!, {r6, r7}" + ); + test_display( + &[0xfe, 0xc8], + "ldm r0!, {r1, r2, r3, r4, r5, r6, r7}" + ); + test_display( + &[0xed, 0xcc], + "ldm r4!, {r0, r2, r3, r5, r6, r7}" + ); + test_display( + &[0xef, 0xcc], + "ldm r4!, {r0, r1, r2, r3, r5, r6, r7}" + ); + test_display( + &[0xfe, 0xce], + "ldm r6, {r1, r2, r3, r4, r5, r6, r7}" + ); + test_display( + &[0xff, 0xcd], + "ldm r5, {r0, r1, r2, r3, r4, r5, r6, r7}" + ); +} +#[test] +fn test_decode_ldr_16b_cases() { + test_display( + &[0x00, 0x48], + "ldr r0, [pc]" + ); + test_display( + &[0x00, 0x49], + "ldr r1, [pc]" + ); + test_display( + &[0x00, 0x4a], + "ldr r2, [pc]" + ); + test_display( + &[0x00, 0x4b], + "ldr r3, [pc]" + ); + test_display( + &[0x00, 0x4c], + "ldr r4, [pc]" + ); + test_display( + &[0x00, 0x4d], + "ldr r5, [pc]" + ); + test_display( + &[0x00, 0x4e], + "ldr r6, [pc]" + ); + test_display( + &[0x00, 0x4f], + "ldr r7, [pc]" + ); + test_display( + &[0x00, 0x56], + "ldrsb r0, [r0, r0]" + ); + test_display( + &[0x00, 0x57], + "ldrsb r0, [r0, r4]" + ); + test_display( + &[0x00, 0x58], + "ldr r0, [r0, r0]" + ); + test_display( + &[0x00, 0x59], + "ldr r0, [r0, r4]" + ); + test_display( + &[0x00, 0x5a], + "ldrh r0, [r0, r0]" + ); + test_display( + &[0x00, 0x5b], + "ldrh r0, [r0, r4]" + ); + test_display( + &[0x00, 0x5c], + "ldrb r0, [r0, r0]" + ); + test_display( + &[0x00, 0x5d], + "ldrb r0, [r0, r4]" + ); + test_display( + &[0x00, 0x5e], + "ldrsh r0, [r0, r0]" + ); + test_display( + &[0x00, 0x5f], + "ldrsh r0, [r0, r4]" + ); + test_display( + &[0x00, 0x68], + "ldr r0, [r0]" + ); + test_display( + &[0x00, 0x69], + "ldr r0, [r0, 0x10]" + ); + test_display( + &[0x00, 0x6a], + "ldr r0, [r0, 0x20]" + ); + test_display( + &[0x00, 0x6b], + "ldr r0, [r0, 0x30]" + ); + test_display( + &[0x00, 0x6c], + "ldr r0, [r0, 0x40]" + ); + test_display( + &[0x00, 0x6d], + "ldr r0, [r0, 0x50]" + ); + test_display( + &[0x00, 0x6e], + "ldr r0, [r0, 0x60]" + ); + test_display( + &[0x00, 0x6f], + "ldr r0, [r0, 0x70]" + ); + test_display( + &[0x00, 0x78], + "ldrb r0, [r0]" + ); + test_display( + &[0x00, 0x79], + "ldrb r0, [r0, 0x4]" + ); + test_display( + &[0x00, 0x7a], + "ldrb r0, [r0, 0x8]" + ); + test_display( + &[0x00, 0x7b], + "ldrb r0, [r0, 0xc]" + ); + test_display( + &[0x00, 0x7c], + "ldrb r0, [r0, 0x10]" + ); + test_display( + &[0x00, 0x7d], + "ldrb r0, [r0, 0x14]" + ); + test_display( + &[0x00, 0x7e], + "ldrb r0, [r0, 0x18]" + ); + test_display( + &[0x00, 0x7f], + "ldrb r0, [r0, 0x1c]" + ); + test_display( + &[0x00, 0x88], + "ldrh r0, [r0]" + ); + test_display( + &[0x00, 0x89], + "ldrh r0, [r0, 0x8]" + ); + test_display( + &[0x00, 0x8a], + "ldrh r0, [r0, 0x10]" + ); + test_display( + &[0x00, 0x8b], + "ldrh r0, [r0, 0x18]" + ); + test_display( + &[0x00, 0x8c], + "ldrh r0, [r0, 0x20]" + ); + test_display( + &[0x00, 0x8d], + "ldrh r0, [r0, 0x28]" + ); + test_display( + &[0x00, 0x8e], + "ldrh r0, [r0, 0x30]" + ); + test_display( + &[0x00, 0x8f], + "ldrh r0, [r0, 0x38]" + ); + test_display( + &[0x00, 0x98], + "ldr r0, [sp]" + ); + test_display( + &[0x00, 0x99], + "ldr r1, [sp]" + ); + test_display( + &[0x00, 0x9a], + "ldr r2, [sp]" + ); + test_display( + &[0x00, 0x9b], + "ldr r3, [sp]" + ); + test_display( + &[0x00, 0x9c], + "ldr r4, [sp]" + ); + test_display( + &[0x00, 0x9d], + "ldr r5, [sp]" + ); + test_display( + &[0x00, 0x9e], + "ldr r6, [sp]" + ); + test_display( + &[0x00, 0x9f], + "ldr r7, [sp]" + ); + test_display( + &[0x01, 0x48], + "ldr r0, [pc, 0x4]" + ); + test_display( + &[0x01, 0x49], + "ldr r1, [pc, 0x4]" + ); + test_display( + &[0x01, 0x4a], + "ldr r2, [pc, 0x4]" + ); + test_display( + &[0x01, 0x4b], + "ldr r3, [pc, 0x4]" + ); + test_display( + &[0x01, 0x4c], + "ldr r4, [pc, 0x4]" + ); + test_display( + &[0x01, 0x4d], + "ldr r5, [pc, 0x4]" + ); + test_display( + &[0x01, 0x4e], + "ldr r6, [pc, 0x4]" + ); + test_display( + &[0x01, 0x4f], + "ldr r7, [pc, 0x4]" + ); + test_display( + &[0xff, 0x48], + "ldr r0, [pc, 0x3fc]" + ); + test_display( + &[0xff, 0x49], + "ldr r1, [pc, 0x3fc]" + ); + test_display( + &[0xff, 0x4a], + "ldr r2, [pc, 0x3fc]" + ); + test_display( + &[0xff, 0x4b], + "ldr r3, [pc, 0x3fc]" + ); + test_display( + &[0xff, 0x4c], + "ldr r4, [pc, 0x3fc]" + ); + test_display( + &[0xff, 0x4d], + "ldr r5, [pc, 0x3fc]" + ); + test_display( + &[0xff, 0x4e], + "ldr r6, [pc, 0x3fc]" + ); + test_display( + &[0xff, 0x4f], + "ldr r7, [pc, 0x3fc]" + ); + test_display( + &[0xff, 0x56], + "ldrsb r7, [r7, r3]" + ); + test_display( + &[0xff, 0x58], + "ldr r7, [r7, r3]" + ); + test_display( + &[0xff, 0x5a], + "ldrh r7, [r7, r3]" + ); + test_display( + &[0xff, 0x5c], + "ldrb r7, [r7, r3]" + ); + test_display( + &[0xff, 0x5e], + "ldrsh r7, [r7, r3]" + ); + test_display( + &[0xff, 0x68], + "ldr r7, [r7, 0xc]" + ); + test_display( + &[0xff, 0x69], + "ldr r7, [r7, 0x1c]" + ); + test_display( + &[0xff, 0x6a], + "ldr r7, [r7, 0x2c]" + ); + test_display( + &[0xff, 0x6b], + "ldr r7, [r7, 0x3c]" + ); + test_display( + &[0xff, 0x6c], + "ldr r7, [r7, 0x4c]" + ); + test_display( + &[0xff, 0x6d], + "ldr r7, [r7, 0x5c]" + ); + test_display( + &[0xff, 0x6e], + "ldr r7, [r7, 0x6c]" + ); + test_display( + &[0xff, 0x6f], + "ldr r7, [r7, 0x7c]" + ); + test_display( + &[0xff, 0x78], + "ldrb r7, [r7, 0x3]" + ); + test_display( + &[0xff, 0x79], + "ldrb r7, [r7, 0x7]" + ); + test_display( + &[0xff, 0x7a], + "ldrb r7, [r7, 0xb]" + ); + test_display( + &[0xff, 0x7b], + "ldrb r7, [r7, 0xf]" + ); + test_display( + &[0xff, 0x7c], + "ldrb r7, [r7, 0x13]" + ); + test_display( + &[0xff, 0x7d], + "ldrb r7, [r7, 0x17]" + ); + test_display( + &[0xff, 0x7e], + "ldrb r7, [r7, 0x1b]" + ); + test_display( + &[0xff, 0x7f], + "ldrb r7, [r7, 0x1f]" + ); + test_display( + &[0xff, 0x88], + "ldrh r7, [r7, 0x6]" + ); + test_display( + &[0xff, 0x89], + "ldrh r7, [r7, 0xe]" + ); + test_display( + &[0xff, 0x8a], + "ldrh r7, [r7, 0x16]" + ); + test_display( + &[0xff, 0x8b], + "ldrh r7, [r7, 0x1e]" + ); + test_display( + &[0xff, 0x8c], + "ldrh r7, [r7, 0x26]" + ); + test_display( + &[0xff, 0x8d], + "ldrh r7, [r7, 0x2e]" + ); + test_display( + &[0xff, 0x8e], + "ldrh r7, [r7, 0x36]" + ); + test_display( + &[0xff, 0x8f], + "ldrh r7, [r7, 0x3e]" + ); + test_display( + &[0xff, 0x98], + "ldr r0, [sp, 0x3fc]" + ); + test_display( + &[0xff, 0x99], + "ldr r1, [sp, 0x3fc]" + ); + test_display( + &[0xff, 0x9a], + "ldr r2, [sp, 0x3fc]" + ); + test_display( + &[0xff, 0x9b], + "ldr r3, [sp, 0x3fc]" + ); + test_display( + &[0xff, 0x9c], + "ldr r4, [sp, 0x3fc]" + ); + test_display( + &[0xff, 0x9d], + "ldr r5, [sp, 0x3fc]" + ); + test_display( + &[0xff, 0x9e], + "ldr r6, [sp, 0x3fc]" + ); + test_display( + &[0xff, 0x9f], + "ldr r7, [sp, 0x3fc]" + ); +} +#[test] +fn test_decode_misc_cases() { + test_display( + &[0x00, 0xbf], + "nop" + ); + test_display( + &[0x10, 0xbf], + "yield" + ); + test_display( + &[0x20, 0xbf], + "wfe" + ); + test_display( + &[0x30, 0xbf], + "wfi" + ); + test_display( + &[0x40, 0xbf], + "sev" + ); + test_display( + &[0x50, 0xb6], + "setend le" + ); + test_display( + &[0x50, 0xbf], + "hint 0x5" + ); + test_display( + &[0x58, 0xb6], + "setend be" + ); + test_display( + &[0x60, 0xbf], + "hint 0x6" + ); + test_display( + &[0x61, 0xb6], + "cpsie f" + ); + test_display( + &[0x62, 0xb6], + "cpsie i" + ); + test_display( + &[0x63, 0xb6], + "cpsie if" + ); + test_display( + &[0x64, 0xb6], + "cpsie a" + ); + test_display( + &[0x65, 0xb6], + "cpsie af" + ); + test_display( + &[0x66, 0xb6], + "cpsie ai" + ); + test_display( + &[0x67, 0xb6], + "cpsie aif" + ); + test_display( + &[0x70, 0xbf], + "hint 0x7" + ); + test_display( + &[0x71, 0xb6], + "cpsid f" + ); + test_display( + &[0x72, 0xb6], + "cpsid i" + ); + test_display( + &[0x73, 0xb6], + "cpsid if" + ); + test_display( + &[0x74, 0xb6], + "cpsid a" + ); + test_display( + &[0x75, 0xb6], + "cpsid af" + ); + test_display( + &[0x76, 0xb6], + "cpsid ai" + ); + test_display( + &[0x77, 0xb6], + "cpsid aif" + ); + test_display( + &[0x80, 0xbf], + "hint 0x8" + ); + test_display( + &[0x90, 0xbf], + "hint 0x9" + ); + test_display( + &[0xa0, 0xbf], + "hint 0xa" + ); + test_display( + &[0xb0, 0xbf], + "hint 0xb" + ); + test_display( + &[0xc0, 0xbf], + "hint 0xc" + ); + test_display( + &[0xd0, 0xbf], + "hint 0xd" + ); + test_display( + &[0xe0, 0xbf], + "hint 0xe" + ); + test_display( + &[0xf0, 0xbf], + "hint 0xf" + ); + test_display( + &[0xfe, 0xde], + "udf 0xfe" + ); +} +#[test] +fn test_decode_mov_cases() { + test_display( + &[0x21, 0x46], + "mov r1, r4" + ); + test_display( + &[0x90, 0x46], + "mov r8, r2" + ); + test_display( + &[0x91, 0x46], + "mov sb, r2" + ); + test_display( + &[0x92, 0x46], + "mov r10, r2" + ); + test_display( + &[0x93, 0x46], + "mov fp, r2" + ); + test_display( + &[0x94, 0x46], + "mov ip, r2" + ); + test_display( + &[0x95, 0x46], + "mov sp, r2" + ); + test_display( + &[0x96, 0x46], + "mov lr, r2" + ); + test_display( + &[0x97, 0x46], + "mov pc, r2" + ); + test_display( + &[0xc0, 0x46], + "mov r8, r8" + ); + test_display( + &[0xc1, 0x46], + "mov sb, r8" + ); + test_display( + &[0xc2, 0x46], + "mov r10, r8" + ); + test_display( + &[0xc3, 0x46], + "mov fp, r8" + ); + test_display( + &[0xc4, 0x46], + "mov ip, r8" + ); + test_display( + &[0xc5, 0x46], + "mov sp, r8" + ); + test_display( + &[0xc6, 0x46], + "mov lr, r8" + ); + test_display( + &[0xc7, 0x46], + "mov pc, r8" + ); + test_display( + &[0xc8, 0x46], + "mov r8, sb" + ); + test_display( + &[0xc9, 0x46], + "mov sb, sb" + ); + test_display( + &[0xca, 0x46], + "mov r10, sb" + ); + test_display( + &[0xcb, 0x46], + "mov fp, sb" + ); + test_display( + &[0xcc, 0x46], + "mov ip, sb" + ); + test_display( + &[0xcd, 0x46], + "mov sp, sb" + ); + test_display( + &[0xce, 0x46], + "mov lr, sb" + ); + test_display( + &[0xcf, 0x46], + "mov pc, sb" + ); + test_display( + &[0xfc, 0x46], + "mov ip, pc" + ); + test_display( + &[0xfd, 0x46], + "mov sp, pc" + ); + test_display( + &[0xfe, 0x46], + "mov lr, pc" + ); + test_display( + &[0xff, 0x46], + "mov pc, pc" + ); +} +#[test] +fn test_decode_op_s_cases() { + test_display( + &[0x00, 0x18], + "adds r0, r0, r0" + ); + test_display( + &[0x00, 0x19], + "adds r0, r0, r4" + ); + test_display( + &[0x00, 0x1c], + "adds r0, r0, 0x0" + ); + test_display( + &[0x00, 0x1d], + "adds r0, r0, 0x4" + ); + test_display( + &[0x00, 0x30], + "adds r0, 0x0" + ); + test_display( + &[0x00, 0x31], + "adds r1, 0x0" + ); + test_display( + &[0x00, 0x32], + "adds r2, 0x0" + ); + test_display( + &[0x00, 0x33], + "adds r3, 0x0" + ); + test_display( + &[0x00, 0x34], + "adds r4, 0x0" + ); + test_display( + &[0x00, 0x35], + "adds r5, 0x0" + ); + test_display( + &[0x00, 0x36], + "adds r6, 0x0" + ); + test_display( + &[0x00, 0x37], + "adds r7, 0x0" + ); + test_display( + &[0x00, 0x40], + "ands r0, r0" + ); + test_display( + &[0x00, 0x43], + "orrs r0, r0" + ); + test_display( + &[0x01, 0x08], + "lsrs r1, r0, 0x20" + ); + test_display( + &[0x01, 0x09], + "lsrs r1, r0, 0x4" + ); + test_display( + &[0x01, 0x0a], + "lsrs r1, r0, 0x8" + ); + test_display( + &[0x01, 0x0b], + "lsrs r1, r0, 0xc" + ); + test_display( + &[0x01, 0x0c], + "lsrs r1, r0, 0x10" + ); + test_display( + &[0x01, 0x0d], + "lsrs r1, r0, 0x14" + ); + test_display( + &[0x01, 0x0e], + "lsrs r1, r0, 0x18" + ); + test_display( + &[0x01, 0x0f], + "lsrs r1, r0, 0x1c" + ); + test_display( + &[0x01, 0x10], + "asrs r1, r0, 0x20" + ); + test_display( + &[0x01, 0x11], + "asrs r1, r0, 0x4" + ); + test_display( + &[0x01, 0x12], + "asrs r1, r0, 0x8" + ); + test_display( + &[0x01, 0x13], + "asrs r1, r0, 0xc" + ); + test_display( + &[0x01, 0x14], + "asrs r1, r0, 0x10" + ); + test_display( + &[0x01, 0x15], + "asrs r1, r0, 0x14" + ); + test_display( + &[0x01, 0x16], + "asrs r1, r0, 0x18" + ); + test_display( + &[0x01, 0x17], + "asrs r1, r0, 0x1c" + ); + test_display( + &[0x01, 0x18], + "adds r1, r0, r0" + ); + test_display( + &[0x01, 0x19], + "adds r1, r0, r4" + ); + test_display( + &[0x01, 0x1c], + "adds r1, r0, 0x0" + ); + test_display( + &[0x01, 0x1d], + "adds r1, r0, 0x4" + ); + test_display( + &[0x01, 0x30], + "adds r0, 0x1" + ); + test_display( + &[0x01, 0x31], + "adds r1, 0x1" + ); + test_display( + &[0x01, 0x32], + "adds r2, 0x1" + ); + test_display( + &[0x01, 0x33], + "adds r3, 0x1" + ); + test_display( + &[0x01, 0x34], + "adds r4, 0x1" + ); + test_display( + &[0x01, 0x35], + "adds r5, 0x1" + ); + test_display( + &[0x01, 0x36], + "adds r6, 0x1" + ); + test_display( + &[0x01, 0x37], + "adds r7, 0x1" + ); + test_display( + &[0x0a, 0x01], + "lsls r2, r1, 0x4" + ); + test_display( + &[0x0a, 0x02], + "lsls r2, r1, 0x8" + ); + test_display( + &[0x0a, 0x03], + "lsls r2, r1, 0xc" + ); + test_display( + &[0x0a, 0x04], + "lsls r2, r1, 0x10" + ); + test_display( + &[0x0a, 0x05], + "lsls r2, r1, 0x14" + ); + test_display( + &[0x0a, 0x06], + "lsls r2, r1, 0x18" + ); + test_display( + &[0x0a, 0x07], + "lsls r2, r1, 0x1c" + ); + test_display( + &[0x13, 0x1a], + "subs r3, r2, r0" + ); + test_display( + &[0x13, 0x1b], + "subs r3, r2, r4" + ); + test_display( + &[0x13, 0x1e], + "subs r3, r2, 0x0" + ); + test_display( + &[0x13, 0x1f], + "subs r3, r2, 0x4" + ); + test_display( + &[0x3d, 0x40], + "ands r5, r7" + ); + test_display( + &[0x3d, 0x43], + "orrs r5, r7" + ); + test_display( + &[0x7d, 0x40], + "eors r5, r7" + ); + test_display( + &[0x7d, 0x41], + "adcs r5, r7" + ); + test_display( + &[0x7d, 0x42], + "rsbs r5, r7, 0x0" + ); + test_display( + &[0x7d, 0x43], + "muls r5, r7, r5" + ); + test_display( + &[0xbd, 0x41], + "sbcs r5, r7" + ); + test_display( + &[0xbd, 0x43], + "bics r5, r7" + ); + test_display( + &[0xd6, 0x41], + "rors r6, r2" + ); + test_display( + &[0xd6, 0x43], + "mvns r6, r2" + ); + test_display( + &[0xfd, 0x20], + "movs r0, 0xfd" + ); + test_display( + &[0xfd, 0x20], + "movs r0, 0xfd" + ); + test_display( + &[0xfd, 0x21], + "movs r1, 0xfd" + ); + test_display( + &[0xfd, 0x21], + "movs r1, 0xfd" + ); + test_display( + &[0xfd, 0x22], + "movs r2, 0xfd" + ); + test_display( + &[0xfd, 0x22], + "movs r2, 0xfd" + ); + test_display( + &[0xfd, 0x23], + "movs r3, 0xfd" + ); + test_display( + &[0xfd, 0x23], + "movs r3, 0xfd" + ); + test_display( + &[0xfd, 0x24], + "movs r4, 0xfd" + ); + test_display( + &[0xfd, 0x24], + "movs r4, 0xfd" + ); + test_display( + &[0xfd, 0x25], + "movs r5, 0xfd" + ); + test_display( + &[0xfd, 0x25], + "movs r5, 0xfd" + ); + test_display( + &[0xfd, 0x26], + "movs r6, 0xfd" + ); + test_display( + &[0xfd, 0x26], + "movs r6, 0xfd" + ); + test_display( + &[0xfd, 0x27], + "movs r7, 0xfd" + ); + test_display( + &[0xfd, 0x27], + "movs r7, 0xfd" + ); + test_display( + &[0xfe, 0x00], + "lsls r6, r7, 0x3" + ); + test_display( + &[0xfe, 0x01], + "lsls r6, r7, 0x7" + ); + test_display( + &[0xfe, 0x02], + "lsls r6, r7, 0xb" + ); + test_display( + &[0xfe, 0x03], + "lsls r6, r7, 0xf" + ); + test_display( + &[0xfe, 0x04], + "lsls r6, r7, 0x13" + ); + test_display( + &[0xfe, 0x05], + "lsls r6, r7, 0x17" + ); + test_display( + &[0xfe, 0x06], + "lsls r6, r7, 0x1b" + ); + test_display( + &[0xfe, 0x07], + "lsls r6, r7, 0x1f" + ); + test_display( + &[0xfe, 0x08], + "lsrs r6, r7, 0x3" + ); + test_display( + &[0xfe, 0x09], + "lsrs r6, r7, 0x7" + ); + test_display( + &[0xfe, 0x0a], + "lsrs r6, r7, 0xb" + ); + test_display( + &[0xfe, 0x0b], + "lsrs r6, r7, 0xf" + ); + test_display( + &[0xfe, 0x0c], + "lsrs r6, r7, 0x13" + ); + test_display( + &[0xfe, 0x0d], + "lsrs r6, r7, 0x17" + ); + test_display( + &[0xfe, 0x0e], + "lsrs r6, r7, 0x1b" + ); + test_display( + &[0xfe, 0x0f], + "lsrs r6, r7, 0x1f" + ); + test_display( + &[0xfe, 0x10], + "asrs r6, r7, 0x3" + ); + test_display( + &[0xfe, 0x11], + "asrs r6, r7, 0x7" + ); + test_display( + &[0xfe, 0x12], + "asrs r6, r7, 0xb" + ); + test_display( + &[0xfe, 0x13], + "asrs r6, r7, 0xf" + ); + test_display( + &[0xfe, 0x14], + "asrs r6, r7, 0x13" + ); + test_display( + &[0xfe, 0x15], + "asrs r6, r7, 0x17" + ); + test_display( + &[0xfe, 0x16], + "asrs r6, r7, 0x1b" + ); + test_display( + &[0xfe, 0x17], + "asrs r6, r7, 0x1f" + ); + test_display( + &[0xfe, 0x40], + "lsrs r6, r7" + ); + test_display( + &[0xfe, 0x41], + "rors r6, r7" + ); + test_display( + &[0xfe, 0x43], + "mvns r6, r7" + ); + test_display( + &[0xff, 0x18], + "adds r7, r7, r3" + ); + test_display( + &[0xff, 0x19], + "adds r7, r7, r7" + ); + test_display( + &[0xff, 0x1c], + "adds r7, r7, 0x3" + ); + test_display( + &[0xff, 0x1d], + "adds r7, r7, 0x7" + ); + test_display( + &[0xff, 0x30], + "adds r0, 0xff" + ); + test_display( + &[0xff, 0x31], + "adds r1, 0xff" + ); + test_display( + &[0xff, 0x32], + "adds r2, 0xff" + ); + test_display( + &[0xff, 0x33], + "adds r3, 0xff" + ); + test_display( + &[0xff, 0x34], + "adds r4, 0xff" + ); + test_display( + &[0xff, 0x35], + "adds r5, 0xff" + ); + test_display( + &[0xff, 0x36], + "adds r6, 0xff" + ); + test_display( + &[0xff, 0x37], + "adds r7, 0xff" + ); +} +#[test] +fn test_decode_pop_cases() { + test_display( + &[0x00, 0xbd], + "pop {pc}" + ); + test_display( + &[0x01, 0xbc], + "pop {r0}" + ); + test_display( + &[0x7f, 0xbd], + "pop {r0, r1, r2, r3, r4, r5, r6, pc}" + ); + test_display( + &[0xff, 0xbd], + "pop {r0, r1, r2, r3, r4, r5, r6, r7, pc}" + ); +} +#[test] +fn test_decode_push_cases() { + test_display( + &[0x00, 0xb5], + "push {lr}" + ); + test_display( + &[0x01, 0xb4], + "push {r0}" + ); + test_display( + &[0xff, 0xb5], + "push {r0, r1, r2, r3, r4, r5, r6, r7, lr}" + ); +} +#[test] +fn test_decode_rev_cases() { + test_display( + &[0x0a, 0xba], + "rev r2, r1" + ); + test_display( + &[0x4a, 0xba], + "rev16 r2, r1" + ); + test_display( + &[0xca, 0xba], + "revsh r2, r1" + ); +} +#[test] +fn test_decode_stm_16b_cases() { + test_display( + &[0x01, 0xc0], + "stmia r0!, {r0}" + ); + test_display( + &[0x01, 0xc1], + "stmia r1!, {r0}" + ); + test_display( + &[0x01, 0xc2], + "stmia r2!, {r0}" + ); + test_display( + &[0x01, 0xc3], + "stmia r3!, {r0}" + ); + test_display( + &[0x01, 0xc4], + "stmia r4!, {r0}" + ); + test_display( + &[0x01, 0xc5], + "stmia r5!, {r0}" + ); + test_display( + &[0x01, 0xc6], + "stmia r6!, {r0}" + ); + test_display( + &[0x01, 0xc7], + "stmia r7!, {r0}" + ); + test_display( + &[0xff, 0xc3], + "stmia r3!, {r0, r1, r2, r3, r4, r5, r6, r7}" + ); +} +#[test] +fn test_decode_str_16b_cases() { + test_display( + &[0x00, 0x50], + "str r0, [r0, r0]" + ); + test_display( + &[0x00, 0x51], + "str r0, [r0, r4]" + ); + test_display( + &[0x00, 0x52], + "strh r0, [r0, r0]" + ); + test_display( + &[0x00, 0x53], + "strh r0, [r0, r4]" + ); + test_display( + &[0x00, 0x54], + "strb r0, [r0, r0]" + ); + test_display( + &[0x00, 0x55], + "strb r0, [r0, r4]" + ); + test_display( + &[0xfe, 0x60], + "str r6, [r7, 0xc]" + ); + test_display( + &[0xfe, 0x61], + "str r6, [r7, 0x1c]" + ); + test_display( + &[0xfe, 0x62], + "str r6, [r7, 0x2c]" + ); + test_display( + &[0xfe, 0x63], + "str r6, [r7, 0x3c]" + ); + test_display( + &[0xfe, 0x64], + "str r6, [r7, 0x4c]" + ); + test_display( + &[0xfe, 0x65], + "str r6, [r7, 0x5c]" + ); + test_display( + &[0xfe, 0x66], + "str r6, [r7, 0x6c]" + ); + test_display( + &[0xfe, 0x67], + "str r6, [r7, 0x7c]" + ); + test_display( + &[0xfe, 0x70], + "strb r6, [r7, 0x3]" + ); + test_display( + &[0xfe, 0x71], + "strb r6, [r7, 0x7]" + ); + test_display( + &[0xfe, 0x72], + "strb r6, [r7, 0xb]" + ); + test_display( + &[0xfe, 0x73], + "strb r6, [r7, 0xf]" + ); + test_display( + &[0xfe, 0x74], + "strb r6, [r7, 0x13]" + ); + test_display( + &[0xfe, 0x75], + "strb r6, [r7, 0x17]" + ); + test_display( + &[0xfe, 0x76], + "strb r6, [r7, 0x1b]" + ); + test_display( + &[0xfe, 0x77], + "strb r6, [r7, 0x1f]" + ); + test_display( + &[0xfe, 0x80], + "strh r6, [r7, 0x6]" + ); + test_display( + &[0xfe, 0x81], + "strh r6, [r7, 0xe]" + ); + test_display( + &[0xfe, 0x82], + "strh r6, [r7, 0x16]" + ); + test_display( + &[0xfe, 0x83], + "strh r6, [r7, 0x1e]" + ); + test_display( + &[0xfe, 0x84], + "strh r6, [r7, 0x26]" + ); + test_display( + &[0xfe, 0x85], + "strh r6, [r7, 0x2e]" + ); + test_display( + &[0xfe, 0x86], + "strh r6, [r7, 0x36]" + ); + test_display( + &[0xfe, 0x87], + "strh r6, [r7, 0x3e]" + ); + test_display( + &[0xfe, 0x90], + "str r0, [sp, 0x3f8]" + ); + test_display( + &[0xfe, 0x91], + "str r1, [sp, 0x3f8]" + ); + test_display( + &[0xfe, 0x92], + "str r2, [sp, 0x3f8]" + ); + test_display( + &[0xfe, 0x93], + "str r3, [sp, 0x3f8]" + ); + test_display( + &[0xfe, 0x94], + "str r4, [sp, 0x3f8]" + ); + test_display( + &[0xfe, 0x95], + "str r5, [sp, 0x3f8]" + ); + test_display( + &[0xfe, 0x96], + "str r6, [sp, 0x3f8]" + ); + test_display( + &[0xfe, 0x97], + "str r7, [sp, 0x3f8]" + ); + test_display( + &[0xff, 0x50], + "str r7, [r7, r3]" + ); + test_display( + &[0xff, 0x90], + "str r0, [sp, 0x3fc]" + ); + test_display( + &[0xff, 0x91], + "str r1, [sp, 0x3fc]" + ); + test_display( + &[0xff, 0x92], + "str r2, [sp, 0x3fc]" + ); + test_display( + &[0xff, 0x93], + "str r3, [sp, 0x3fc]" + ); + test_display( + &[0xff, 0x94], + "str r4, [sp, 0x3fc]" + ); + test_display( + &[0xff, 0x95], + "str r5, [sp, 0x3fc]" + ); + test_display( + &[0xff, 0x96], + "str r6, [sp, 0x3fc]" + ); + test_display( + &[0xff, 0x97], + "str r7, [sp, 0x3fc]" + ); +} +#[test] +fn test_decode_sub_cases() { + test_display( + &[0xd8, 0xb0], + "sub sp, sp, 0x160" + ); +} +#[test] +fn test_decode_svc_cases() { + test_display( + &[0x27, 0xdf], + "svc 0x27" + ); + test_display( + &[0xad, 0xdf], + "svc 0xad" + ); +} +#[test] +fn test_decode_udf_cases() { + test_display( + &[0x27, 0xde], + "udf 0x27" + ); + test_display( + &[0xad, 0xde], + "udf 0xad" + ); +} +#[test] +fn test_decode_ux_sx_cases() { + test_display( + &[0x0a, 0xb2], + "sxth r2, r1" + ); + test_display( + &[0x4a, 0xb2], + "sxtb r2, r1" + ); + test_display( + &[0x8a, 0xb2], + "uxth r2, r1" + ); + test_display( + &[0xca, 0xb2], + "uxtb r2, r1" + ); +} + +#[test] +fn test_decode_ldr_32b_cases() { + test_display( + &[0x73, 0xe8, 0x7e, 0x5a], + "ldrd r5, r10, [r3], -0x1f8" + ); + test_display( + &[0x93, 0xf8, 0x7e, 0x5a], + "ldrb.w r5, [r3, 0xa7e]" + ); + test_display( + &[0xb3, 0xf8, 0x7e, 0x5a], + "ldrh.w r5, [r3, 0xa7e]" + ); + test_display( + &[0xd3, 0xf8, 0x7e, 0x5a], + "ldr.w r5, [r3, 0xa7e]" + ); + test_display( + &[0xf3, 0xe8, 0x7e, 0x5a], + "ldrd r5, r10, [r3], 0x1f8" + ); + test_display( + &[0x53, 0xe9, 0x7e, 0x5a], + "ldrd r5, r10, [r3, -0x1f8]" + ); + test_display( + &[0x73, 0xe9, 0x7e, 0x5a], + "ldrd r5, r10, [r3, -0x1f8]!" + ); + test_display( + &[0x93, 0xf9, 0x7e, 0x5a], + "ldrsb.w r5, [r3, 0xa7e]" + ); + test_display( + &[0xb3, 0xf9, 0x7e, 0x5a], + "ldrsh.w r5, [r3, 0xa7e]" + ); + test_display( + &[0xd3, 0xe9, 0x7e, 0x5a], + "ldrd r5, r10, [r3, 0x1f8]" + ); + test_display( + &[0xf3, 0xe9, 0x7e, 0x5a], + "ldrd r5, r10, [r3, 0x1f8]!" + ); +} + +#[test] +fn test_decode_coproc_ld_32b_cases() { + test_display( + &[0x33, 0xfc, 0x7e, 0x54], + "ldc2 p4, c5, [r3], -0x1f8" + ); + test_display( + &[0x73, 0xfc, 0x7e, 0x54], + "ldc2l p4, c5, [r3], -0x1f8" + ); + test_display( + &[0x93, 0xfc, 0x7e, 0x54], + "ldc2 p4, c5, [r3], {0x7e}" + ); + test_display( + &[0xb3, 0xfc, 0x7e, 0x54], + "ldc2 p4, c5, [r3], 0x1f8" + ); + test_display( + &[0xd3, 0xfc, 0x7e, 0x54], + "ldc2l p4, c5, [r3], {0x7e}" + ); + test_display( + &[0xf3, 0xfc, 0x7e, 0x54], + "ldc2l p4, c5, [r3], 0x1f8" + ); + test_display( + &[0x13, 0xfd, 0x7e, 0x54], + "ldc2 p4, c5, [r3, -0x1f8]" + ); + test_display( + &[0x33, 0xfd, 0x7e, 0x54], + "ldc2 p4, c5, [r3, -0x1f8]!" + ); + test_display( + &[0x53, 0xfd, 0x7e, 0x54], + "ldc2l p4, c5, [r3, -0x1f8]" + ); + test_display( + &[0x73, 0xfd, 0x7e, 0x54], + "ldc2l p4, c5, [r3, -0x1f8]!" + ); + test_display( + &[0x93, 0xfd, 0x7e, 0x54], + "ldc2 p4, c5, [r3, 0x1f8]" + ); + test_display( + &[0xb3, 0xfd, 0x7e, 0x54], + "ldc2 p4, c5, [r3, 0x1f8]!" + ); + test_display( + &[0xd3, 0xfd, 0x7e, 0x54], + "ldc2l p4, c5, [r3, 0x1f8]" + ); + test_display( + &[0xf3, 0xfd, 0x7e, 0x54], + "ldc2l p4, c5, [r3, 0x1f8]!" + ); +} +#[test] +fn test_decode_str_32b_cases() { + test_display( + &[0x43, 0xe8, 0x7e, 0x5a], + "strex r10, r5, [r3, 0x1f8]" + ); + test_display( + &[0x63, 0xe8, 0x7e, 0x5a], + "strd r5, r10, [r3], -0x1f8" + ); + test_display( + &[0x83, 0xf8, 0x7e, 0x5a], + "strb.w r5, [r3, 0xa7e]" + ); + test_display( + &[0xa3, 0xf8, 0x7e, 0x5a], + "strh.w r5, [r3, 0xa7e]" + ); + test_display( + &[0xc3, 0xe8, 0x7e, 0x5a], + "strexd lr, r5, r10, [r3]" + ); + test_display( + &[0xc3, 0xf8, 0x7e, 0x5a], + "str.w r5, [r3, 0xa7e]" + ); + test_display( + &[0xe3, 0xe8, 0x7e, 0x5a], + "strd r5, r10, [r3], 0x1f8" + ); + test_display( + &[0x43, 0xe9, 0x7e, 0x5a], + "strd r5, r10, [r3, -0x1f8]" + ); + test_display( + &[0x63, 0xe9, 0x7e, 0x5a], + "strd r5, r10, [r3, -0x1f8]!" + ); + test_display( + &[0xc3, 0xe9, 0x7e, 0x5a], + "strd r5, r10, [r3, 0x1f8]" + ); + test_display( + &[0xe3, 0xe9, 0x7e, 0x5a], + "strd r5, r10, [r3, 0x1f8]!" + ); + test_display( + &[0x41, 0xf8, 0x04, 0x2b], + "str.w r2, [r1], 0x4" + ); + test_display( + &[0x41, 0xf8, 0x00, 0x2b], + "str.w r2, [r1]" + ); +} + +#[test] +fn test_decode_coproc_st_32b_cases() { + test_display( + &[0x23, 0xfc, 0x7e, 0x54], + "stc2 p4, c5, [r3], -0x1f8" + ); + test_display( + &[0x63, 0xfc, 0x7e, 0x54], + "stc2l p4, c5, [r3], -0x1f8" + ); + test_display( + &[0x83, 0xfc, 0x7e, 0x54], + "stc2 p4, c5, [r3], {0x7e}" + ); + test_display( + &[0xa3, 0xfc, 0x7e, 0x54], + "stc2 p4, c5, [r3], 0x1f8" + ); + test_display( + &[0xc3, 0xfc, 0x7e, 0x54], + "stc2l p4, c5, [r3], {0x7e}" + ); + test_display( + &[0xe3, 0xfc, 0x7e, 0x54], + "stc2l p4, c5, [r3], 0x1f8" + ); + test_display( + &[0x03, 0xfd, 0x7e, 0x54], + "stc2 p4, c5, [r3, -0x1f8]" + ); + test_display( + &[0x23, 0xfd, 0x7e, 0x54], + "stc2 p4, c5, [r3, -0x1f8]!" + ); + test_display( + &[0x43, 0xfd, 0x7e, 0x54], + "stc2l p4, c5, [r3, -0x1f8]" + ); + test_display( + &[0x63, 0xfd, 0x7e, 0x54], + "stc2l p4, c5, [r3, -0x1f8]!" + ); + test_display( + &[0x83, 0xfd, 0x7e, 0x54], + "stc2 p4, c5, [r3, 0x1f8]" + ); + test_display( + &[0xa3, 0xfd, 0x7e, 0x54], + "stc2 p4, c5, [r3, 0x1f8]!" + ); + test_display( + &[0xc3, 0xfd, 0x7e, 0x54], + "stc2l p4, c5, [r3, 0x1f8]" + ); + test_display( + &[0xe3, 0xfd, 0x7e, 0x54], + "stc2l p4, c5, [r3, 0x1f8]!" + ); +} +#[test] +fn test_decode_stm_ldm_32b_cases() { + test_display( + &[0x83, 0xe8, 0x7e, 0x5a], + "stm.w r3, {r1, r2, r3, r4, r5, r6, sb, fp, ip, lr}" + ); + test_display( + &[0xa3, 0xe8, 0x7e, 0x5a], + "stm.w r3!, {r1, r2, r3, r4, r5, r6, sb, fp, ip, lr}" + ); + test_display( + &[0x03, 0xe9, 0x7e, 0x5a], + "stmdb r3, {r1, r2, r3, r4, r5, r6, sb, fp, ip, lr}" + ); + test_display( + &[0x23, 0xe9, 0x7e, 0x5a], + "stmdb r3!, {r1, r2, r3, r4, r5, r6, sb, fp, ip, lr}" + ); + + test_display( + &[0x93, 0xe8, 0x7e, 0x5a], + "ldm.w r3, {r1, r2, r3, r4, r5, r6, sb, fp, ip, lr}" + ); + test_display( + &[0xb3, 0xe8, 0x7e, 0x5a], + "ldm.w r3!, {r1, r2, r3, r4, r5, r6, sb, fp, ip, lr}" + ); + test_display( + &[0x13, 0xe9, 0x7e, 0x5a], + "ldmdb r3, {r1, r2, r3, r4, r5, r6, sb, fp, ip, lr}" + ); + test_display( + &[0x33, 0xe9, 0x7e, 0x5a], + "ldmdb r3!, {r1, r2, r3, r4, r5, r6, sb, fp, ip, lr}" + ); +} +#[test] +fn test_decode_sat_ext_32b_cases() { + test_display( + &[0x43, 0xf3, 0x7e, 0x5a], + "sbfx r10, r3, 0x15, 0x1f" + ); + test_display( + &[0xc3, 0xf3, 0x7e, 0x5a], + "ubfx r10, r3, 0x15, 0x1f" + ); + test_display( + &[0x43, 0xf7, 0x7e, 0x5a], + "sbfx r10, r3, 0x15, 0x1f" + ); + test_display( + &[0xc3, 0xf7, 0x7e, 0x5a], + "ubfx r10, r3, 0x15, 0x1f" + ); + + test_display( + &[0x83, 0xf3, 0x7e, 0x5a], + "usat r10, 0x1e, r3, lsl 21" + ); + test_display( + &[0xa3, 0xf3, 0x7e, 0x5a], + "usat r10, 0x1e, r3, asr 21" + ); + test_display( + &[0x83, 0xf7, 0x7e, 0x5a], + "usat r10, 0x1e, r3, lsl 21" + ); + test_display( + &[0xa3, 0xf7, 0x7e, 0x5a], + "usat r10, 0x1e, r3, asr 21" + ); +} +#[test] +fn test_decode_bitwise_32b_cases() { + test_display( + &[0x23, 0xf0, 0x7e, 0x5a], + "bic r10, r3, 0x3f800000" + ); + test_display( + &[0x33, 0xf0, 0x7e, 0x5a], + "bics r10, r3, 0x3f800000" + ); + test_display( + &[0x23, 0xea, 0x7e, 0x5a], + "bic.w r10, r3, lr, ror 21" + ); + test_display( + &[0x33, 0xea, 0x7e, 0x5a], + "bics.w r10, r3, lr, ror 21" + ); + test_display( + &[0x23, 0xf4, 0x7e, 0x5a], + "bic r10, r3, 0x3f80" + ); + test_display( + &[0x33, 0xf4, 0x7e, 0x5a], + "bics r10, r3, 0x3f80" + ); + + test_display( + &[0x03, 0xf0, 0x7e, 0x5a], + "and r10, r3, 0x3f800000" + ); + test_display( + &[0x13, 0xf0, 0x7e, 0x5a], + "ands r10, r3, 0x3f800000" + ); + test_display( + &[0x03, 0xea, 0x7e, 0x5a], + "and.w r10, r3, lr, ror 21" + ); + test_display( + &[0x13, 0xea, 0x7e, 0x5a], + "ands.w r10, r3, lr, ror 21" + ); + test_display( + &[0x03, 0xf4, 0x7e, 0x5a], + "and r10, r3, 0x3f80" + ); + test_display( + &[0x13, 0xf4, 0x7e, 0x5a], + "ands r10, r3, 0x3f80" + ); + + test_display( + &[0x43, 0xf0, 0x7e, 0x5a], + "orr r10, r3, 0x3f800000" + ); + test_display( + &[0x53, 0xf0, 0x7e, 0x5a], + "orrs r10, r3, 0x3f800000" + ); + test_display( + &[0x43, 0xea, 0x7e, 0x5a], + "orr.w r10, r3, lr, ror 21" + ); + test_display( + &[0x53, 0xea, 0x7e, 0x5a], + "orrs.w r10, r3, lr, ror 21" + ); + test_display( + &[0x43, 0xf4, 0x7e, 0x5a], + "orr r10, r3, 0x3f80" + ); + test_display( + &[0x53, 0xf4, 0x7e, 0x5a], + "orrs r10, r3, 0x3f80" + ); + + test_display( + &[0x83, 0xf0, 0x7e, 0x5a], + "eor r10, r3, 0x3f800000" + ); + test_display( + &[0x93, 0xf0, 0x7e, 0x5a], + "eors r10, r3, 0x3f800000" + ); + test_display( + &[0x83, 0xea, 0x7e, 0x5a], + "eor.w r10, r3, lr, ror 21" + ); + test_display( + &[0x93, 0xea, 0x7e, 0x5a], + "eors.w r10, r3, lr, ror 21" + ); + test_display( + &[0x83, 0xf4, 0x7e, 0x5a], + "eor r10, r3, 0x3f80" + ); + test_display( + &[0x93, 0xf4, 0x7e, 0x5a], + "eors r10, r3, 0x3f80" + ); + + test_display( + &[0x63, 0xf0, 0x7e, 0x5a], + "orn r10, r3, 0x3f800000" + ); + test_display( + &[0x73, 0xf0, 0x7e, 0x5a], + "orns r10, r3, 0x3f800000" + ); + test_display( + &[0x63, 0xea, 0x7e, 0x5a], + "orn r10, r3, lr, ror 21" + ); + test_display( + &[0x73, 0xea, 0x7e, 0x5a], + "orns r10, r3, lr, ror 21" + ); + test_display( + &[0x63, 0xf4, 0x7e, 0x5a], + "orn r10, r3, 0x3f80" + ); + test_display( + &[0x73, 0xf4, 0x7e, 0x5a], + "orns r10, r3, 0x3f80" + ); +} +#[test] +fn test_decode_arithmetic_32b_cases() { + test_display( + &[0xa3, 0xf1, 0x7e, 0x5a], + "sub.w r10, r3, 0x3f800000" + ); + test_display( + &[0xb3, 0xf1, 0x7e, 0x5a], + "subs.w r10, r3, 0x3f800000" + ); + test_display( + &[0xa3, 0xf2, 0x7e, 0x5a], + "sub.w r10, r3, 0x57e" + ); + test_display( + &[0xa3, 0xeb, 0x7e, 0x5a], + "sub.w r10, r3, lr, ror 21" + ); + test_display( + &[0xb3, 0xeb, 0x7e, 0x5a], + "subs.w r10, r3, lr, ror 21" + ); + test_display( + &[0xa3, 0xf6, 0x7e, 0x5a], + "sub.w r10, r3, 0xd7e" + ); + test_display( + &[0xa3, 0xf5, 0x7e, 0x5a], + "sub.w r10, r3, 0x3f80" + ); + test_display( + &[0xb3, 0xf5, 0x7e, 0x5a], + "subs.w r10, r3, 0x3f80" + ); + + test_display( + &[0x03, 0xf1, 0x7e, 0x5a], + "add.w r10, r3, 0x3f800000" + ); + test_display( + &[0x13, 0xf1, 0x7e, 0x5a], + "adds.w r10, r3, 0x3f800000" + ); + test_display( + &[0x03, 0xf2, 0x7e, 0x5a], + "add.w r10, r3, 0x57e" + ); + test_display( + &[0x03, 0xeb, 0x7e, 0x5a], + "add.w r10, r3, lr, ror 21" + ); + test_display( + &[0x13, 0xeb, 0x7e, 0x5a], + "adds.w r10, r3, lr, ror 21" + ); + test_display( + &[0x03, 0xf5, 0x7e, 0x5a], + "add.w r10, r3, 0x3f80" + ); + test_display( + &[0x13, 0xf5, 0x7e, 0x5a], + "adds.w r10, r3, 0x3f80" + ); + test_display( + &[0x03, 0xf6, 0x7e, 0x5a], + "add.w r10, r3, 0xd7e" + ); + + test_display( + &[0x43, 0xf1, 0x7e, 0x5a], + "adc r10, r3, 0x3f800000" + ); + test_display( + &[0x53, 0xf1, 0x7e, 0x5a], + "adcs r10, r3, 0x3f800000" + ); + test_display( + &[0x43, 0xeb, 0x7e, 0x5a], + "adc.w r10, r3, lr, ror 21" + ); + test_display( + &[0x53, 0xeb, 0x7e, 0x5a], + "adcs.w r10, r3, lr, ror 21" + ); + test_display( + &[0x43, 0xf5, 0x7e, 0x5a], + "adc r10, r3, 0x3f80" + ); + test_display( + &[0x53, 0xf5, 0x7e, 0x5a], + "adcs r10, r3, 0x3f80" + ); + + test_display( + &[0x63, 0xf1, 0x7e, 0x5a], + "sbc r10, r3, 0x3f800000" + ); + test_display( + &[0x73, 0xf1, 0x7e, 0x5a], + "sbcs r10, r3, 0x3f800000" + ); + test_display( + &[0x63, 0xeb, 0x7e, 0x5a], + "sbc.w r10, r3, lr, ror 21" + ); + test_display( + &[0x73, 0xeb, 0x7e, 0x5a], + "sbcs.w r10, r3, lr, ror 21" + ); + test_display( + &[0x63, 0xf5, 0x7e, 0x5a], + "sbc r10, r3, 0x3f80" + ); + test_display( + &[0x73, 0xf5, 0x7e, 0x5a], + "sbcs r10, r3, 0x3f80" + ); + + test_display( + &[0xc3, 0xf1, 0x7e, 0x5a], + "rsb.w r10, r3, 0x3f800000" + ); + test_display( + &[0xd3, 0xf1, 0x7e, 0x5a], + "rsbs.w r10, r3, 0x3f800000" + ); + test_display( + &[0xc3, 0xeb, 0x7e, 0x5a], + "rsb r10, r3, lr, ror 21" + ); + test_display( + &[0xd3, 0xeb, 0x7e, 0x5a], + "rsbs r10, r3, lr, ror 21" + ); + test_display( + &[0xc3, 0xf5, 0x7e, 0x5a], + "rsb.w r10, r3, 0x3f80" + ); + test_display( + &[0xd3, 0xf5, 0x7e, 0x5a], + "rsbs.w r10, r3, 0x3f80" + ); +} +#[ignore] +#[test] +fn test_decode_simd_32b_cases() { + test_display( + &[0x13, 0xed, 0x7e, 0x5a], + "vldr s10, [r3, -0x1f8]" + ); + test_display( + &[0x53, 0xed, 0x7e, 0x5a], + "vldr s11, [r3, -0x1f8]" + ); + test_display( + &[0x93, 0xed, 0x7e, 0x5a], + "vldr s10, [r3, 0x1f8]" + ); + test_display( + &[0xd3, 0xed, 0x7e, 0x5a], + "vldr s11, [r3, 0x1f8]" + ); + + test_display( + &[0x03, 0xed, 0x7e, 0x5a], + "vstr s10, [r3, -0x1f8]" + ); + test_display( + &[0x43, 0xed, 0x7e, 0x5a], + "vstr s11, [r3, -0x1f8]" + ); + test_display( + &[0x83, 0xed, 0x7e, 0x5a], + "vstr s10, [r3, 0x1f8]" + ); + test_display( + &[0xc3, 0xed, 0x7e, 0x5a], + "vstr s11, [r3, 0x1f8]" + ); + + test_display( + &[0x93, 0xec, 0x7e, 0x5a], + "vldmia r3, {s10, s11, s12, s13, s14, s15, s16, s17, s18, s19, s20, s21, s22, s23, s24, s25, s26, s27, s28, s29, s30, s31}" + ); + test_display( + &[0xb3, 0xec, 0x7e, 0x5a], + "vldmia r3!, {s10, s11, s12, s13, s14, s15, s16, s17, s18, s19, s20, s21, s22, s23, s24, s25, s26, s27, s28, s29, s30, s31}" + ); + test_display( + &[0xd3, 0xec, 0x7e, 0x5a], + "vldmia r3, {s11, s12, s13, s14, s15, s16, s17, s18, s19, s20, s21, s22, s23, s24, s25, s26, s27, s28, s29, s30, s31}" + ); + test_display( + &[0xf3, 0xec, 0x7e, 0x5a], + "vldmia r3!, {s11, s12, s13, s14, s15, s16, s17, s18, s19, s20, s21, s22, s23, s24, s25, s26, s27, s28, s29, s30, s31}" + ); + test_display( + &[0x33, 0xed, 0x7e, 0x5a], + "vldmdb r3!, {s10, s11, s12, s13, s14, s15, s16, s17, s18, s19, s20, s21, s22, s23, s24, s25, s26, s27, s28, s29, s30, s31}" + ); + test_display( + &[0x73, 0xed, 0x7e, 0x5a], + "vldmdb r3!, {s11, s12, s13, s14, s15, s16, s17, s18, s19, s20, s21, s22, s23, s24, s25, s26, s27, s28, s29, s30, s31}" + ); + + test_display( + &[0x83, 0xec, 0x7e, 0x5a], + "vstmia r3, {s10, s11, s12, s13, s14, s15, s16, s17, s18, s19, s20, s21, s22, s23, s24, s25, s26, s27, s28, s29, s30, s31}" + ); + test_display( + &[0xa3, 0xec, 0x7e, 0x5a], + "vstmia r3!, {s10, s11, s12, s13, s14, s15, s16, s17, s18, s19, s20, s21, s22, s23, s24, s25, s26, s27, s28, s29, s30, s31}" + ); + test_display( + &[0xc3, 0xec, 0x7e, 0x5a], + "vstmia r3, {s11, s12, s13, s14, s15, s16, s17, s18, s19, s20, s21, s22, s23, s24, s25, s26, s27, s28, s29, s30, s31}" + ); + test_display( + &[0xe3, 0xec, 0x7e, 0x5a], + "vstmia r3!, {s11, s12, s13, s14, s15, s16, s17, s18, s19, s20, s21, s22, s23, s24, s25, s26, s27, s28, s29, s30, s31}" + ); + test_display( + &[0x23, 0xed, 0x7e, 0x5a], + "vstmdb r3!, {s10, s11, s12, s13, s14, s15, s16, s17, s18, s19, s20, s21, s22, s23, s24, s25, s26, s27, s28, s29, s30, s31}" + ); + test_display( + &[0x63, 0xed, 0x7e, 0x5a], + "vstmdb r3!, {s11, s12, s13, s14, s15, s16, s17, s18, s19, s20, s21, s22, s23, s24, s25, s26, s27, s28, s29, s30, s31}" + ); +} -- cgit v1.1