summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoriximeow <me@iximeow.net>2025-04-13 01:54:24 -0700
committeriximeow <me@iximeow.net>2025-04-13 01:54:24 -0700
commitc785240f7593abd3fc5b9c8c5da9e05bade61012 (patch)
tree32509de1efb396a8905546259fc2808b0c410f5c
parentfba052bca5783a315dbf9f0d539a27bbe1901c39 (diff)
the rest of the extenders
-rw-r--r--src/lib.rs170
-rw-r--r--tests/from_brain.rs294
2 files changed, 378 insertions, 86 deletions
diff --git a/src/lib.rs b/src/lib.rs
index 28f7865..bed8af0 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -1164,7 +1164,7 @@ pub enum Operand {
RegMemIndexedBrev { base: u8, mu: u8 },
- Absolute { addr: i8 },
+ Absolute { addr: u32 },
GpOffset { offset: u32 },
}
@@ -1919,7 +1919,8 @@ fn decode_instruction<
JumpEq, JumpNeq, JumpGt, JumpLe,
JumpGtu, JumpLeu
];
- handler.on_source_decoded(Operand::imm_u32(lllll as u8 as u32))?;
+
+ handler.on_source_decoded(Operand::immext(lllll as u32, extender, |i| Ok(Operand::imm_u32(i)))?)?;
handler.on_opcode_decoded(OPS[op as usize - 0b10000])?;
} else if op < 0b11000 {
let opc = if op == 0b10110 {
@@ -2034,7 +2035,7 @@ fn decode_instruction<
let vv = ((inst >> 5) & 0b11) as u8;
let iiiiii = (inst >> 7) & 0b11_1111;
let l_hi = (((inst >> 13) & 0b1) << 5) as u8;
- let llllll = (l_lo | l_hi) as u8;
+ let llllll = (l_lo | l_hi) as u32;
let op = (inst >> 21) & 0b11;
let negated = nn & 1 == 1;
@@ -2042,27 +2043,38 @@ fn decode_instruction<
handler.inst_predicated(vv, negated, pred_new)?;
+ let offset = iiiiii;
+ handler.on_dest_decoded(Operand::RegOffset { base: sssss, offset })?;
+
match op {
0b00 => {
handler.on_opcode_decoded(Opcode::StoreMemb)?;
- let offset = iiiiii;
- let imm = (llllll as i8) << 2 >> 2;
- handler.on_dest_decoded(Operand::RegOffset { base: sssss, offset })?;
- handler.on_source_decoded(Operand::imm_i8(imm))?;
+
+ let imm = Operand::with_extension(llllll, extender,
+ |imm| Ok(Operand::imm_u32(imm)),
+ |imm| Ok(Operand::imm_i8((imm as i8) << 2 >> 2)),
+ )?;
+ handler.on_source_decoded(imm)?;
}
0b01 => {
handler.on_opcode_decoded(Opcode::StoreMemh)?;
- let offset = iiiiii << 1;
- let imm = (llllll as i16) << 10 >> 10;
- handler.on_dest_decoded(Operand::RegOffset { base: sssss, offset })?;
- handler.on_source_decoded(Operand::imm_i16(imm))?;
+
+ let imm = Operand::with_extension(llllll, extender,
+ |imm| Ok(Operand::imm_u32(imm)),
+ |imm| Ok(Operand::imm_i16((imm as i16) << 10 >> 10)),
+ )?;
+ handler.on_source_decoded(imm)?;
}
0b10 => {
handler.on_opcode_decoded(Opcode::StoreMemw)?;
- let offset = iiiiii << 2;
let imm = (llllll as i32) << 26 >> 26;
- handler.on_dest_decoded(Operand::RegOffset { base: sssss, offset })?;
handler.on_source_decoded(Operand::imm_i32(imm))?;
+
+ let imm = Operand::with_extension(llllll, extender,
+ |imm| Ok(Operand::imm_u32(imm)),
+ |imm| Ok(Operand::imm_i32((imm as i32) << 26 >> 26)),
+ )?;
+ handler.on_source_decoded(imm)?;
}
_ => {
return Err(DecodeError::InvalidOpcode);
@@ -2454,8 +2466,13 @@ fn decode_instruction<
handler.on_opcode_decoded(Opcode::Jump)?;
let imm = ((inst >> 1) & 0x1fff) | ((inst >> 3) & 0xffe000);
let imm = ((imm as i32) << 10) >> 10;
- // TODO: extend
- handler.on_dest_decoded(Operand::PCRel32 { rel: imm << 2 })?;
+ handler.on_dest_decoded(
+ Operand::with_extension(
+ (imm << 2) as u32, extender,
+ |rel| Ok(Operand::PCRel32 { rel: rel as i32 }),
+ |rel| Ok(Operand::PCRel32 { rel: rel as i32 }),
+ )?
+ )?;
},
0b101 => {
// V73 Call to address
@@ -2467,7 +2484,13 @@ fn decode_instruction<
handler.on_opcode_decoded(Opcode::Call)?;
let imm = ((inst >> 1) & 0x1fff) | ((inst >> 3) & 0xffe000);
let imm = ((imm as i32) << 10) >> 10;
- handler.on_dest_decoded(Operand::PCRel32 { rel: imm << 2 })?;
+ handler.on_dest_decoded(
+ Operand::with_extension(
+ (imm << 2) as u32, extender,
+ |rel| Ok(Operand::PCRel32 { rel: rel as i32 }),
+ |rel| Ok(Operand::PCRel32 { rel: rel as i32 }),
+ )?
+ )?;
},
0b110 => {
// V73 Predicated jump/call relative
@@ -2491,12 +2514,19 @@ fn decode_instruction<
handler.inst_predicated(uu as u8, negated, false)?;
opcode_check!(!dotnew);
} else {
- // ... not shown as extended in the manual?
+ // ... not shown as extended in the manual? does have an
+ // `apply_extension()` though
handler.on_opcode_decoded(Opcode::Jump)?;
handler.inst_predicated(uu as u8, negated, dotnew)?;
handler.branch_hint(hint_taken)?;
}
- handler.on_dest_decoded(Operand::PCRel32 { rel: i15 << 2 })?;
+ handler.on_dest_decoded(
+ Operand::with_extension(
+ (i15 << 2) as u32, extender,
+ |rel| Ok(Operand::PCRel32 { rel: rel as i32 }),
+ |rel| Ok(Operand::PCRel32 { rel: rel as i32 }),
+ )?
+ )?;
}
0b111 => {
return Err(DecodeError::InvalidOpcode);
@@ -2518,7 +2548,13 @@ fn decode_instruction<
let rel = ((i7 << 1) as i8 as i32) << 1;
handler.on_opcode_decoded(Opcode::Loop0)?;
- handler.on_source_decoded(Operand::PCRel32 { rel })?;
+ handler.on_source_decoded(
+ Operand::with_extension(
+ rel as u32, extender,
+ |rel| Ok(Operand::PCRel32 { rel: rel as i32 }),
+ |rel| Ok(Operand::PCRel32 { rel: rel as i32 }),
+ )?
+ )?;
handler.on_source_decoded(Operand::gpr(sssss))?;
}
0b0000001 => {
@@ -2529,7 +2565,13 @@ fn decode_instruction<
let rel = ((i7 << 1) as i8 as i32) << 1;
handler.on_opcode_decoded(Opcode::Loop1)?;
- handler.on_source_decoded(Operand::PCRel32 { rel })?;
+ handler.on_source_decoded(
+ Operand::with_extension(
+ rel as u32, extender,
+ |rel| Ok(Operand::PCRel32 { rel: rel as i32 }),
+ |rel| Ok(Operand::PCRel32 { rel: rel as i32 }),
+ )?
+ )?;
handler.on_source_decoded(Operand::gpr(sssss))?;
}
0b0000010 | 0b0000011 => {
@@ -2543,7 +2585,13 @@ fn decode_instruction<
let rel = ((i7 << 1) as i8 as i32) << 1;
handler.on_opcode_decoded(Opcode::Sp1Loop0)?;
- handler.on_source_decoded(Operand::PCRel32 { rel })?;
+ handler.on_source_decoded(
+ Operand::with_extension(
+ rel as u32, extender,
+ |rel| Ok(Operand::PCRel32 { rel: rel as i32 }),
+ |rel| Ok(Operand::PCRel32 { rel: rel as i32 }),
+ )?
+ )?;
handler.on_source_decoded(Operand::gpr(sssss))?;
handler.on_dest_decoded(Operand::pred(3))?;
}
@@ -2555,7 +2603,13 @@ fn decode_instruction<
let rel = ((i7 << 1) as i8 as i32) << 1;
handler.on_opcode_decoded(Opcode::Sp2Loop0)?;
- handler.on_source_decoded(Operand::PCRel32 { rel })?;
+ handler.on_source_decoded(
+ Operand::with_extension(
+ rel as u32, extender,
+ |rel| Ok(Operand::PCRel32 { rel: rel as i32 }),
+ |rel| Ok(Operand::PCRel32 { rel: rel as i32 }),
+ )?
+ )?;
handler.on_source_decoded(Operand::gpr(sssss))?;
handler.on_dest_decoded(Operand::pred(3))?;
}
@@ -2567,7 +2621,13 @@ fn decode_instruction<
let rel = ((i7 << 1) as i8 as i32) << 1;
handler.on_opcode_decoded(Opcode::Sp3Loop0)?;
- handler.on_source_decoded(Operand::PCRel32 { rel })?;
+ handler.on_source_decoded(
+ Operand::with_extension(
+ rel as u32, extender,
+ |rel| Ok(Operand::PCRel32 { rel: rel as i32 }),
+ |rel| Ok(Operand::PCRel32 { rel: rel as i32 }),
+ )?
+ )?;
handler.on_source_decoded(Operand::gpr(sssss))?;
handler.on_dest_decoded(Operand::pred(3))?;
}
@@ -2893,7 +2953,9 @@ fn decode_instruction<
let ddddd = reg_b0(inst);
handler.on_opcode_decoded(Opcode::Add)?;
handler.on_source_decoded(Operand::cr(9))?;
- handler.on_source_decoded(Operand::imm_u8(iiiiii as u8))?;
+ handler.on_source_decoded(
+ Operand::immext(iiiiii, extender, |i| Ok(Operand::imm_u8(i as u8)) )?
+ )?;
handler.on_dest_decoded(Operand::gpr(ddddd))?;
}
o if o & 0b1111000 == 0b1011000 => {
@@ -3197,9 +3259,9 @@ fn decode_instruction<
if reg_first {
handler.on_source_decoded(Operand::gpr(sssss))?;
- handler.on_source_decoded(Operand::imm_i8(i))?;
+ handler.on_source_decoded(Operand::immext(i as u32, extender, |i| Ok(Operand::imm_i8(i as i8)))?)?;
} else {
- handler.on_source_decoded(Operand::imm_i8(i))?;
+ handler.on_source_decoded(Operand::immext(i as u32, extender, |i| Ok(Operand::imm_i8(i as i8)))?)?;
handler.on_source_decoded(Operand::gpr(sssss))?;
}
}
@@ -3218,7 +3280,7 @@ fn decode_instruction<
handler.inst_predicated(pred_number as u8, negated, dotnew)?;
handler.on_dest_decoded(Operand::gpr(ddddd))?;
handler.on_source_decoded(Operand::gpr(sssss))?;
- handler.on_source_decoded(Operand::imm_i8(i))?;
+ handler.on_source_decoded(Operand::immext(i as u32, extender, |i| Ok(Operand::imm_i8(i as i8)))?)?;
}
0b0101 => {
let sssss = reg_b16(inst);
@@ -3249,9 +3311,9 @@ fn decode_instruction<
handler.on_source_decoded(Operand::gpr(sssss))?;
if opcode == Opcode::CmpGtu {
operand_check!(i >= 0);
- handler.on_source_decoded(Operand::imm_u16(i as u16))?;
+ handler.on_source_decoded(Operand::immext(i as u32, extender, |i| Ok(Operand::imm_u16(i as u16)))?)?;
} else {
- handler.on_source_decoded(Operand::imm_i16(i))?;
+ handler.on_source_decoded(Operand::immext(i as u32, extender, |i| Ok(Operand::imm_i16(i as i16)))?)?;
}
}
0b0110 => {
@@ -3324,7 +3386,7 @@ fn decode_instruction<
handler.on_opcode_decoded(Opcode::Mux)?;
handler.on_dest_decoded(Operand::gpr(ddddd))?;
handler.on_source_decoded(Operand::pred(uu as u8))?;
- handler.on_source_decoded(Operand::imm_i8(i))?;
+ handler.on_source_decoded(Operand::immext(i as u32, extender, |i| Ok(Operand::imm_i8(i as i8)))?)?;
handler.on_source_decoded(Operand::imm_i8(l))?;
}
0b1100 => {
@@ -3337,15 +3399,16 @@ fn decode_instruction<
handler.on_opcode_decoded(Opcode::Combine)?;
handler.on_dest_decoded(Operand::gprpair(ddddd)?)?;
- handler.on_source_decoded(Operand::imm_i8(i))?;
if min_op & 0b100 == 0 {
+ handler.on_source_decoded(Operand::immext(i as u32, extender, |i| Ok(Operand::imm_i8(i as i8)))?)?;
handler.on_source_decoded(Operand::imm_i8(l))?;
} else {
+ handler.on_source_decoded(Operand::imm_i8(i))?;
// TODO: technically more restrictive than the manual - these bits are
// dontcare, not 0
let l = l as u8;
operand_check!(l & 0xc0 == 0);
- handler.on_source_decoded(Operand::imm_u8(l))?;
+ handler.on_source_decoded(Operand::immext(l as u32, extender, |l| Ok(Operand::imm_u8(l as u8)))?)?;
}
}
0b1101 => {
@@ -3369,7 +3432,7 @@ fn decode_instruction<
handler.inst_predicated(pred_number as u8, negated, dotnew)?;
handler.on_dest_decoded(Operand::gpr(ddddd))?;
- handler.on_source_decoded(Operand::imm_i16(i))?;
+ handler.on_source_decoded(Operand::immext(i as u32, extender, |i| Ok(Operand::imm_i16(i as i16)))?)?;
}
0b1111 => {
// 0b0111_1111_...
@@ -4694,7 +4757,10 @@ fn decode_instruction<
let i6 = ((ii_high << 4) | iiii) as i8;
let dotnew = (inst >> 13) & 1 == 1;
decode_store_ops(handler, minbits, ttttt, |_shamt| {
- Ok(Operand::Absolute { addr: i6 })
+ Operand::with_extension(i6 as u32, extender,
+ |addr| Ok(Operand::Absolute { addr }),
+ |addr| Ok(Operand::Absolute { addr }),
+ )
})?;
handler.inst_predicated(vv as u8, negated, dotnew)?;
}
@@ -4714,7 +4780,7 @@ fn decode_instruction<
handler.on_dest_decoded(Operand::gpr(ddddd))?;
handler.on_source_decoded(Operand::gpr(sssss))?;
- handler.on_source_decoded(Operand::imm_i16(i as i16))?;
+ handler.on_source_decoded(Operand::immext(i, extender, |i| Ok(Operand::imm_i16(i as i16)))?)?;
}
0b1100 => {
let ddddd = reg_b0(inst);
@@ -5663,7 +5729,9 @@ fn decode_instruction<
handler.on_opcode_decoded(Opcode::AddMpyi)?;
handler.on_dest_decoded(Operand::gpr(ddddd))?;
- handler.on_source_decoded(Operand::imm_u8(i as u8))?;
+ handler.on_source_decoded(
+ Operand::immext(i, extender, |i| Ok(Operand::imm_u8(i as u8)))?
+ )?;
handler.on_source_decoded(Operand::gpr(sssss))?;
handler.on_source_decoded(Operand::gpr(ttttt))?;
}
@@ -5683,7 +5751,9 @@ fn decode_instruction<
handler.on_opcode_decoded(Opcode::AddMpyi)?;
handler.on_dest_decoded(Operand::gpr(ddddd))?;
- handler.on_source_decoded(Operand::imm_u8(i as u8))?;
+ handler.on_source_decoded(
+ Operand::immext(i, extender, |i| Ok(Operand::imm_u8(i as u8)))?
+ )?;
handler.on_source_decoded(Operand::gpr(sssss))?;
handler.on_source_decoded(Operand::imm_u8(l as u8))?;
}
@@ -5732,12 +5802,13 @@ fn decode_instruction<
let i9 = (inst >> 5) & 0b1_1111_1111;
let i_hi = (inst >> 21) & 1;
let i10 = i9 | (i_hi << 9);
- let i = (i10 as i16) << 6 >> 6;
handler.on_opcode_decoded(Opcode::OrAnd)?;
handler.on_dest_decoded(Operand::gpr(reg_b16(inst)))?;
handler.on_source_decoded(Operand::gpr(reg_b0(inst)))?;
handler.on_source_decoded(Operand::gpr(reg_b16(inst)))?;
- handler.on_source_decoded(Operand::imm_i16(i))?;
+ handler.on_source_decoded(
+ Operand::immext(i10, extender, |i| Ok(Operand::imm_i16((i as i16) << 6 >> 6)))?
+ )?;
}
0b10 => {
let i9 = (inst >> 5) & 0b1_1111_1111;
@@ -5765,7 +5836,6 @@ fn decode_instruction<
let i_mid = (inst >> 13) & 0b1;
let i_hi = (inst >> 21) & 0b11;
let i = i_lo | (i_mid << 3) | (i_hi << 4);
- let s6 = (i as i8) << 2 >> 2;
let op = (inst >> 23) & 1;
@@ -5774,10 +5844,14 @@ fn decode_instruction<
if op == 0 {
handler.on_opcode_decoded(Opcode::AddAdd)?;
handler.on_source_decoded(Operand::gpr(uuuuu))?;
- handler.on_source_decoded(Operand::imm_i8(s6))?;
+ handler.on_source_decoded(
+ Operand::immext(i, extender, |i| Ok(Operand::imm_i8((i as i8) << 2 >> 2)))?
+ )?;
} else {
handler.on_opcode_decoded(Opcode::AddSub)?;
- handler.on_source_decoded(Operand::imm_i8(s6))?;
+ handler.on_source_decoded(
+ Operand::immext(i, extender, |i| Ok(Operand::imm_i8((i as i8) << 2 >> 2)))?
+ )?;
handler.on_source_decoded(Operand::gpr(uuuuu))?;
}
}
@@ -5836,7 +5910,9 @@ fn decode_instruction<
if opc & 0b10_00 != 0 {
operand_check!(imm < 0b1000_0000);
}
- handler.on_source_decoded(Operand::imm_u8(imm as u8))?;
+ handler.on_source_decoded(
+ Operand::immext(imm, extender, |imm| Ok(Operand::imm_u8(imm as u8)))?
+ )?;
}
0b1110 => {
let xxxxx = reg_b16(inst);
@@ -5851,7 +5927,9 @@ fn decode_instruction<
let u5 = reg_b8(inst);
handler.on_dest_decoded(Operand::gpr(xxxxx))?;
- handler.on_source_decoded(Operand::imm_u8(i as u8))?;
+ handler.on_source_decoded(
+ Operand::immext(i, extender, |i| Ok(Operand::imm_u8(i as u8)))?
+ )?;
handler.on_source_decoded(Operand::gpr(xxxxx))?;
handler.on_source_decoded(Operand::imm_u8(u5))?;
@@ -5922,7 +6000,7 @@ fn decode_instruction<
handler.on_opcode_decoded(Opcode::Mpyi)?;
handler.on_dest_decoded(Operand::gpr(reg_b0(inst)))?;
handler.on_source_decoded(Operand::gpr(sssss))?;
- handler.on_source_decoded(Operand::imm_u8(i as u8))?;
+ handler.on_source_decoded(Operand::immext(i, extender, |i| Ok(Operand::imm_u8(i as u8)))?)?;
if op_hi < 0b100 {
handler.assign_mode(AssignMode::AddAssign)?;
} else {
@@ -5935,7 +6013,7 @@ fn decode_instruction<
handler.on_opcode_decoded(Opcode::Add)?;
handler.on_dest_decoded(Operand::gpr(reg_b0(inst)))?;
handler.on_source_decoded(Operand::gpr(sssss))?;
- handler.on_source_decoded(Operand::imm_i8(i as i8))?;
+ handler.on_source_decoded(Operand::immext(i, extender, |i| Ok(Operand::imm_i8(i as i8)))?)?;
if op_hi < 0b100 {
handler.assign_mode(AssignMode::AddAssign)?;
} else {
diff --git a/tests/from_brain.rs b/tests/from_brain.rs
index 334dc82..5eec602 100644
--- a/tests/from_brain.rs
+++ b/tests/from_brain.rs
@@ -26,62 +26,65 @@ fn extenders() {
* // it turns out these are encoded by applying an extender to the `mem{b,ub,...}(gp+#u16)` forms
* [x]: Rd = mem{b,ub,h,uh,w,d}(##U32)
* // predicated loads
- * [ ]: if ([!]Pt[.new]) Rd = mem{b,ub,h,uh,w,d} (Rs + ##U32)
+ * [x]: if ([!]Pt[.new]) Rd = mem{b,ub,h,uh,w,d} (Rs + ##U32)
* [x]: Rd = mem{b,ub,h,uh,w,d} (Rs + ##U32)
* [x]: Rd = mem{b,ub,h,uh,w,d} (Re=##U32)
* [x]: Rd = mem{b,ub,h,uh,w,d} (Rt<<#u2 + ##U32)
- * [ ]: if ([!]Pt[.new]) Rd = mem{b,ub,h,uh,w,d} (##U32)
+ * [x]: if ([!]Pt[.new]) Rd = mem{b,ub,h,uh,w,d} (##U32)
* // it turns out these are encoded by applying an extender to the `mem{b,ub,...}(gp+#u16)` forms
* [x]: mem{b,h,w,d}(##U32) = Rs[.new]
* // predicated stores
- * [ ]: if ([!]Pt[.new]) mem{b,h,w,d}(Rs + ##U32) = Rt[.new]
+ * [x]: if ([!]Pt[.new]) mem{b,h,w,d}(Rs + ##U32) = Rt[.new]
* [x]: mem{b,h,w,d}(Rs + ##U32) = Rt[.new]
* [x]: mem{b,h,w,d}(Rd=##U32) = Rt[.new]
* [x]: mem{b,h,w,d}(Ru<<#u2 + ##U32) = Rt[.new]
- * [ ]: if ([!]Pt[.new]) mem{b,h,w,d}(##U32) = Rt[.new]
- * [ ]: [if [!]Ps] memw(Rs + #u6) = ##U32 // constant store
- * [ ]: memw(Rs + Rt<<#u2) = ##U32 // constant store
- * [ ]: if (cmp.xx(Rs.new,##U32)) jump:hint target
+ * [x]: if ([!]Pt[.new]) mem{b,h,w,d}(##U32) = Rt[.new]
+ * [x]: [if [!]Ps] memw(Rs + #u6) = ##U32 // constant store
+ * // this just does not exist?!
+ * [!]: memw(Rs + Rt<<#u2) = ##U32 // constant store
+ * [x]: if (cmp.xx(Rs.new,##U32)) jump:hint target
* [x]: Rd = ##u32
- * [ ]: Rdd = combine(Rs,##u32)
- * [ ]: Rdd = combine(##u32,Rs)
- * [ ]: Rdd = combine(##u32,#s8)
- * [ ]: Rdd = combine(#s8,##u32)
- * [ ]: Rd = mux(Pu, Rs,##u32)
- * [ ]: Rd = mux(Pu, ##u32, Rs)
- * [ ]: Rd = mux(Pu,##u32,#s8)
- * [ ]: if ([!]Pu[.new]) Rd = add(Rs,##u32)
- * [ ]: if ([!]Pu[.new]) Rd = ##u32
- * [ ]: Pd = [!]cmp.eq (Rs,##u32)
- * [ ]: Pd = [!]cmp.gt (Rs,##u32)
- * [ ]: Pd = [!]cmp.gtu (Rs,##u32)
- * [ ]: Rd = [!]cmp.eq(Rs,##u32)
+ * [x]: Rdd = combine(Rs,##u32)
+ * [x]: Rdd = combine(##u32,Rs)
+ * [x]: Rdd = combine(##u32,#s8)
+ * [x]: Rdd = combine(#s8,##u32)
+ * [x]: Rd = mux(Pu, Rs,##u32)
+ * [x]: Rd = mux(Pu, ##u32, Rs)
+ * [x]: Rd = mux(Pu,##u32,#s8)
+ * [x]: if ([!]Pu[.new]) Rd = add(Rs,##u32)
+ * [x]: if ([!]Pu[.new]) Rd = ##u32
+ * [x]: Pd = [!]cmp.eq (Rs,##u32)
+ * [x]: Pd = [!]cmp.gt (Rs,##u32)
+ * [x]: Pd = [!]cmp.gtu (Rs,##u32)
* [x]: Rd = and(Rs,##u32)
* [x]: Rd = or(Rs,##u32)
* [x]: Rd = sub(##u32,Rs)
- * [ ]: Rd = add(Rs,##s32)
- * [ ]: Rd = mpyi(Rs,##u32)
- * [ ]: Rd += mpyi(Rs,##u32)
- * [ ]: Rd -= mpyi(Rs,##u32)
- * [ ]: Rx += add(Rs,##u32)
- * [ ]: Rx -= add(Rs,##u32)
+ * [x]: Rd = add(Rs,##s32)
+ * // this does not exist...
+ * [!]: Rd = mpyi(Rs,##u32)
+ * [x]: Rd += mpyi(Rs,##u32)
+ * [x]: Rd -= mpyi(Rs,##u32)
+ * [x]: Rx += add(Rs,##u32)
+ * [x]: Rx -= add(Rs,##u32)
* [x]: Rd = ##u32
- * [ ]: Rd = add(Rs,##s32)
- * [ ]: jump (PC + ##s32)
- * [ ]: call (PC + ##s32)
- * [ ]: if ([!]Pu) call (PC + ##s32)
- * [ ]: Pd = spNloop0(PC+##s32,Rs/#U10)
- * [ ]: loop0/1 (PC+##s32,#Rs/#U10)
- * [ ]: Rd = add(pc,##s32)
- * [ ]: Rd = add(##u32,mpyi(Rs,#u6))
- * [ ]: Rd = add(##u32,mpyi(Rs,Rt))
- * [ ]: Rd = add(Rs,add(Rt,##u32))
+ * [x]: Rd = add(Rs,##s32)
+ * [x]: jump (PC + ##s32)
+ * [x]: call (PC + ##s32)
+ * [x]: if ([!]Pu) call (PC + ##s32)
+ * [x]: Pd = spNloop0(PC+##s32,Rs/#U10)
+ * [x]: loop0/1 (PC+##s32,#Rs/#U10)
+ * [x]: Rd = add(pc,##s32)
+ * [x]: Rd = add(##u32,mpyi(Rs,#u6))
+ * [x]: Rd = add(##u32,mpyi(Rs,Rt))
+ * [x]: Rd = add(Rs,add(Rt,##u32))
* [x]: Rd = add(Rs,sub(##u32,Rt))
- * [x]: Rd = sub(##u32,add(Rs,Rt))
+ * // doesn't exist?
+ * [!]: Rd = sub(##u32,add(Rs,Rt))
* [x]: Rd = or(Rs,and(Rt,##u32))
- * [ ]: Rx = add/sub/and/or (##u32,asl/asr/lsr(Rx,#U5))
- * [ ]: Rx = add/sub/and/or (##u32,asl/asr/lsr(Rs,Rx))
- * [ ]: Rx = add/sub/and/or (##u32,asl/asr/lsr(Rx,Rs))
+ * [x]: Rx = add/sub/and/or (##u32,asl/asr/lsr(Rx,#U5))
+ * // neither of these exist?
+ * [!]: Rx = add/sub/and/or (##u32,asl/asr/lsr(Rs,Rx))
+ * [!]: Rx = add/sub/and/or (##u32,asl/asr/lsr(Rx,Rs))
* [ ]: Pd = cmpb/h.{eq,gt,gtu} (Rs,##u32)
*/
@@ -339,6 +342,215 @@ fn extenders() {
0xc7, 0xc6, 0xc4, 0xad,
], "{ memd(r4<<1 + 0x207) = r7:6 }");
+ // not writing out permutations for all predicated instructions come on now
+ // if ([!]Pt[.new]) Rd = mem{b,ub,h,uh,w,d} (Rs + ##U32)
+ test_display(&[
+ 0x08, 0x40, 0x00, 0x00,
+ 0xa8, 0xf0, 0x6a, 0x47,
+ ], "{ if (!p2.new) r8 = memuh(r10+#522) }");
+ // if ([!]Pt[.new]) Rd = mem{b,ub,h,uh,w,d} (##U32)
+ test_display(&[
+ 0x08, 0x40, 0x00, 0x00,
+ 0x90, 0xf5, 0x62, 0x9f,
+ ], "{ if (p2.new) r16 = memuh(##0x205) }");
+ // if ([!]Pt[.new]) mem{b,h,w,d}(Rs + ##U32) = Rt[.new]
+ test_display(&[
+ 0x08, 0x40, 0x00, 0x00,
+ 0x2a, 0xc7, 0x4a, 0x40,
+ ], "{ if (p2) memh(r10+#522) = r7 }");
+ // if ([!]Pt[.new]) mem{b,h,w,d}(##U32) = Rt[.new]
+ test_display(&[
+ 0x08, 0x40, 0x00, 0x00,
+ 0xc9, 0xe6, 0x80, 0xaf,
+ ], "{ if (p1.new) memw(#0x209) = r6 }");
+ // [if [!]Ps] memw(Rs + #u6) = ##U32 // constant store
+ test_display(&[
+ 0x08, 0x40, 0x00, 0x00,
+ 0xbf, 0xe2, 0x84, 0x38,
+ ], "{ if (!p1) memb(r4+#5) = #575 }");
+ // if (cmp.xx(Rs.new,##U32)) jump:hint target
+ test_display(&[
+ 0x08, 0x40, 0x00, 0x00,
+ 0x96, 0xe3, 0xd4, 0x24,
+ ], "{ if (!cmp.gt(r4.new, ##0x203)) jump:t $+0x32c }");
+
+ test_display(&[
+ 0x02, 0x40, 0x00, 0x00,
+ 0x01, 0xd6, 0x49, 0x6a,
+ ], "{ r1 = add(pc, ##0xac) }");
+
+ test_display(&[
+ 0x0c, 0x42, 0xf8, 0x03,
+ 0x17, 0xc2, 0x19, 0xb0,
+ ], "{ r23 = add(r25, ##0x3f808310) }");
+
+ // Rdd = combine(##u32,#s8)
+ test_display(&[
+ 0x08, 0x40, 0x00, 0x00,
+ 0xf0, 0xe0, 0x40, 0x7c,
+ ], "{ r17:16 = combine(##0x207, #-127) }");
+
+ // Rdd = combine(#s8,##u32)
+ test_display(&[
+ 0x08, 0x40, 0x00, 0x00,
+ 0xf0, 0xc0, 0x84, 0x7c,
+ ], "{ r17:16 = combine(#7, ##0x208) }");
+
+ // Rd = mux(Pu, Rs,##u32)
+ test_display(&[
+ 0x08, 0x40, 0x00, 0x00,
+ 0xf0, 0xc0, 0x26, 0x73,
+ ], "{ r16 = mux(p1, r6, ##0x207) }");
+ // Rd = mux(Pu, ##u32, Rs)
+ test_display(&[
+ 0x08, 0x40, 0x00, 0x00,
+ 0xf0, 0xc0, 0xa6, 0x73,
+ ], "{ r16 = mux(p1, ##0x207, r6) }");
+ // Rd = mux(Pu,##u32,#s8)
+ test_display(&[
+ 0x08, 0x40, 0x00, 0x00,
+ 0xf1, 0xe0, 0xa7, 0x7a,
+ ], "{ r17 = mux(p1, ##0x207, #79) }");
+
+ // if ([!]Pu[.new]) Rd = add(Rs,##u32)
+ test_display(&[
+ 0x08, 0x40, 0x00, 0x00,
+ 0xf0, 0xe0, 0xc6, 0x74,
+ ], "{ if (!p2.new) r16 = add(r6, ##0x207) }");
+
+ // if ([!]Pu[.new]) Rd = ##u32
+ test_display(&[
+ 0x08, 0x40, 0x00, 0x00,
+ 0xf0, 0xe0, 0xc0, 0x7e,
+ ], "{ if (!p2.new) r16 = ##0x207 }");
+
+ // Pd = [!]cmp.eq (Rs,##u32)
+ test_display(&[
+ 0x08, 0x40, 0x00, 0x00,
+ 0xf1, 0xc0, 0x06, 0x75,
+ ], "{ p1 = !cmp.eq(r6, ##0x207) }");
+ // Pd = [!]cmp.gt (Rs,##u32)
+ test_display(&[
+ 0x08, 0x40, 0x00, 0x00,
+ 0xf1, 0xc0, 0x46, 0x75,
+ ], "{ p1 = !cmp.gt(r6, ##0x207) }");
+ // Pd = [!]cmp.gtu (Rs,##u32)
+ test_display(&[
+ 0x08, 0x40, 0x00, 0x00,
+ 0xf1, 0xc0, 0x86, 0x75,
+ ], "{ p1 = !cmp.gtu(r6, ##0x207) }");
+
+ // Rd = mpyi(Rs,##u32)
+
+ // Rd += mpyi(Rs,##u32)
+ test_display(&[
+ 0x08, 0x40, 0x00, 0x00,
+ 0x96, 0xc6, 0x14, 0xe1,
+ ], "{ r22 += mpyi(r20, ##0x234) }");
+ // Rd -= mpyi(Rs,##u32)
+ test_display(&[
+ 0x08, 0x40, 0x00, 0x00,
+ 0x96, 0xc6, 0x94, 0xe1,
+ ], "{ r22 -= mpyi(r20, ##0x234) }");
+ // Rx += add(Rs,##u32)
+ test_display(&[
+ 0x08, 0x40, 0x00, 0x00,
+ 0x96, 0xc6, 0x14, 0xe2,
+ ], "{ r22 += add(r20, ##0x234) }");
+ // Rx -= add(Rs,##u32)
+ test_display(&[
+ 0x08, 0x40, 0x00, 0x00,
+ 0x96, 0xc6, 0x94, 0xe2,
+ ], "{ r22 -= add(r20, ##0x234) }");
+ // Rd = add(Rs,##s32)
+ test_display(&[
+ 0x08, 0x40, 0x00, 0x00,
+ 0x02, 0xc0, 0x00, 0x58,
+ ], "{ jump $+0x204 }");
+ // jump (PC + ##s32)
+ test_display(&[
+ 0x08, 0x40, 0x00, 0x00,
+ 0x02, 0xc0, 0x00, 0x5a,
+ ], "{ call $+0x204 }");
+ // call (PC + ##s32)
+ test_display(&[
+ 0x08, 0x40, 0x00, 0x00,
+ 0x02, 0xc1, 0x00, 0x5c,
+ ], "{ if (p1) jump:nt $+0x204 }");
+ test_display(&[
+ 0x08, 0x40, 0x00, 0x00,
+ 0x02, 0xc9, 0x20, 0x5c,
+ ], "{ if (!p1.new) jump:nt $+0x204 }");
+ test_display(&[
+ 0x08, 0x40, 0x00, 0x00,
+ 0x02, 0xc1, 0x20, 0x5d,
+ ], "{ if (!p1) call $+0x204 }");
+ // if ([!]Pu) call (PC + ##s32)
+ test_display(&[
+ 0x08, 0x40, 0x00, 0x00,
+ 0x08, 0xc2, 0xa6, 0x60,
+ ], "{ p3 = sp1loop0($+0x224, r6) }");
+ test_display(&[
+ 0x08, 0x40, 0x00, 0x00,
+ 0x08, 0xc2, 0xc6, 0x60,
+ ], "{ p3 = sp2loop0($+0x224, r6) }");
+ test_display(&[
+ 0x08, 0x40, 0x00, 0x00,
+ 0x08, 0xc2, 0xe6, 0x60,
+ ], "{ p3 = sp3loop0($+0x224, r6) }");
+ // Pd = spNloop0(PC+##s32,Rs/#U10)
+ test_display(&[
+ 0x08, 0x40, 0x00, 0x00,
+ 0x08, 0xc2, 0x06, 0x60,
+ ], "{ loop0($+0x224, r6) }");
+ test_display(&[
+ 0x08, 0x40, 0x00, 0x00,
+ 0x08, 0xc2, 0x26, 0x60,
+ ], "{ loop1($+0x224, r6) }");
+ // loop0/1 (PC+##s32,#Rs/#U10)
+ test_display(&[
+ 0x08, 0x40, 0x00, 0x00,
+ 0x96, 0xe6, 0xd4, 0xd8,
+ ], "{ r6 = add(##0x22c, mpyi(r20, #0x36)) }");
+ // Rd = add(##u32,mpyi(Rs,#u6))
+ test_display(&[
+ 0x08, 0x40, 0x00, 0x00,
+ 0x96, 0xe6, 0x54, 0xd7,
+ ], "{ r22 = add(##0x22c, mpyi(r20, r6)) }");
+ // Rd = add(##u32,mpyi(Rs,Rt))
+ test_display(&[
+ 0x08, 0x40, 0x00, 0x00,
+ 0x96, 0xe6, 0x34, 0xdb,
+ ], "{ r6 = add(r20, add(r22, ##0x21c)) }");
+ // Rd = add(Rs,add(Rt,##u32))
+ test_display(&[
+ 0x08, 0x40, 0x00, 0x00,
+ 0x96, 0xe6, 0xb4, 0xdb,
+ ], "{ r6 = add(r20, sub(##0x21c, r22)) }");
+ // Rd = add(Rs,sub(##u32,Rt))
+
+ // Rd = sub(##u32,add(Rs,Rt))
+
+ test_display(&[
+ 0x08, 0x40, 0x00, 0x00,
+ 0x96, 0xc3, 0x54, 0xda,
+ ], "{ r20 = or(r22, and(r20, ##0x21c)) }");
+ // Rd = or(Rs,and(Rt,##u32))
+ test_display(&[
+ 0x08, 0x40, 0x00, 0x00,
+ 0x84, 0xe6, 0x14, 0xde,
+ ], "{ r20 = add(##0x218, asl(r20, #0x6)) }");
+ // Rx = add/sub/and/or (##u32,asl/asr/lsr(Rx,#U5))
+
+ // neither of these exist?
+ // Rx = add/sub/and/or (##u32,asl/asr/lsr(Rs,Rx))
+ // Rx = add/sub/and/or (##u32,asl/asr/lsr(Rx,Rs))
+
+ // Pd = cmpb/h.{eq,gt,gtu} (Rs,##u32)
+ test_display(&[
+ 0x08, 0x40, 0x00, 0x00,
+ 0x87, 0xe6, 0x14, 0xdd,
+ ], "{ p3 = cmpb.gt(r20, ##0x234) }");
test_display(&[
0x08, 0x40, 0x00, 0x00,
@@ -770,6 +982,8 @@ fn inst_0111() {
test_display(&0b0111_1000110_00110_11_1_0_0000_111_10001u32.to_le_bytes(), "{ r17 = #-15929 }");
+ test_display(&0b0111_101_01_0100111_11_1_00000111_10001u32.to_le_bytes(), "{ r17 = mux(p1, #7, #79) }");
+
test_display(&0b0111_1100010_00000_11_1_0_0000_111_10000u32.to_le_bytes(), "{ r17:16 = combine(#7, #-127) }");
test_display(&0b0111_1100100_10000_11_1_0_0000_111_10000u32.to_le_bytes(), "{ r17:16 = combine(#7, #0x21) }");