summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authoriximeow <me@iximeow.net>2025-03-29 02:27:42 -0700
committeriximeow <me@iximeow.net>2025-03-29 02:27:42 -0700
commit8bcec993e3c5b9832ccee91e94eb5de6e80c9b24 (patch)
treef6bd0dae1803f0178257b69e1a945a463316b94a /src
parente5849e3fa4830c83825f2d2cf9ef62853012aea2 (diff)
1101* is all thats left...
Diffstat (limited to 'src')
-rw-r--r--src/display.rs28
-rw-r--r--src/lib.rs122
2 files changed, 148 insertions, 2 deletions
diff --git a/src/display.rs b/src/display.rs
index ecd9a26..6e1c376 100644
--- a/src/display.rs
+++ b/src/display.rs
@@ -1,7 +1,7 @@
use core::fmt;
use crate::{Instruction, InstructionPacket, Opcode, Operand};
-use crate::{AssignMode, BranchHint, DomainHint};
+use crate::{AssignMode, BranchHint, DomainHint, RawMode};
fn special_display_rules(op: &Opcode) -> bool {
*op as u16 & 0x8000 == 0x8000
@@ -80,6 +80,12 @@ impl fmt::Display for Instruction {
self.dest.as_ref().unwrap(), self.alt_dest.as_ref().unwrap(),
self.opcode, self.sources[0]);
}
+ Opcode::Any8VcmpbEq => {
+ return write!(f, "{} = {}any8(vcmpb.eq({}, {}))",
+ self.dest.as_ref().unwrap(),
+ if self.flags.negated { "!" } else { "" },
+ self.sources[0], self.sources[1]);
+ }
_ => {
unreachable!("TODO: should be exhaustive for opcodes with special display rules");
}
@@ -315,6 +321,12 @@ impl fmt::Display for Instruction {
None => {}
}
+ match self.flags.raw_mode {
+ Some(RawMode::Lo) => { f.write_str(":raw:lo")? },
+ Some(RawMode::Hi) => { f.write_str(":raw:hi")? },
+ None => {}
+ }
+
// DeallocateFrame is shown with `:raw` as a suffix, but after the taken/not-taken hint
// same for DeallocReturn
if self.opcode == Opcode::AllocFrame || self.opcode == Opcode::DeallocFrame || self.opcode == Opcode::DeallocReturn {
@@ -586,6 +598,20 @@ impl fmt::Display for Opcode {
Opcode::SfFixupr => { f.write_str("sffixupr") },
Opcode::SfInvsqrta => { f.write_str("sfinvsqrta") },
Opcode::Swiz => { f.write_str("swiz") },
+ Opcode::Parity => { f.write_str("parity") },
+ Opcode::Tlbmatch => { f.write_str("tlbmatch") },
+ Opcode::Boundscheck => { f.write_str("boundscheck") },
+ Opcode::Any8VcmpbEq => { f.write_str("any8vcmpbeq") },
+ Opcode::Vmux => { f.write_str("vmux") },
+ Opcode::VcmpwEq => { f.write_str("vcmpw.eq") },
+ Opcode::VcmpwGt => { f.write_str("vcmpw.gt") },
+ Opcode::VcmpwGtu => { f.write_str("vcmpw.gtu") },
+ Opcode::VcmphEq => { f.write_str("vcmph.eq") },
+ Opcode::VcmphGt => { f.write_str("vcmph.gt") },
+ Opcode::VcmphGtu => { f.write_str("vcmph.gtu") },
+ Opcode::VcmpbEq => { f.write_str("vcmpb.eq") },
+ Opcode::VcmpbGt => { f.write_str("vcmpb.gt") },
+ Opcode::VcmpbGtu => { f.write_str("vcmpb.gtu") },
}
}
}
diff --git a/src/lib.rs b/src/lib.rs
index c225ed1..7a9970c 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -303,6 +303,12 @@ enum AssignMode {
}
#[derive(Debug, Copy, Clone)]
+enum RawMode {
+ Lo,
+ Hi,
+}
+
+#[derive(Debug, Copy, Clone)]
struct InstFlags {
predicate: Option<Predicate>,
branch_hint: Option<BranchHint>,
@@ -312,6 +318,7 @@ struct InstFlags {
rounded: Option<RoundingMode>,
threads: Option<DomainHint>,
assign_mode: Option<AssignMode>,
+ raw_mode: Option<RawMode>,
}
#[derive(Debug, Copy, Clone)]
@@ -331,6 +338,7 @@ impl Default for InstFlags {
rounded: None,
threads: None,
assign_mode: None,
+ raw_mode: None,
}
}
}
@@ -651,6 +659,20 @@ pub enum Opcode {
SfFixupr,
Swiz,
+ Parity,
+ Vmux,
+ VcmpwEq,
+ VcmpwGt,
+ VcmpwGtu,
+ VcmphEq,
+ VcmphGt,
+ VcmphGtu,
+ VcmpbEq,
+ VcmpbGt,
+ VcmpbGtu,
+ Tlbmatch,
+ Boundscheck,
+
AndAnd = 0x8000,
AndOr,
OrAnd,
@@ -663,6 +685,7 @@ pub enum Opcode {
OrOrNot,
AddClb,
SfInvsqrta,
+ Any8VcmpbEq,
}
impl Opcode {
@@ -1140,6 +1163,7 @@ trait DecodeHandler<T: Reader<<Hexagon as Arch>::Address, <Hexagon as Arch>::Wor
fn domain_hint(&mut self, _domain: DomainHint) -> Result<(), <Hexagon as Arch>::DecodeError> { Ok(()) }
fn rounded(&mut self, _mode: RoundingMode) -> Result<(), <Hexagon as Arch>::DecodeError> { Ok(()) }
fn chop(&mut self) -> Result<(), <Hexagon as Arch>::DecodeError> { Ok(()) }
+ fn raw_mode(&mut self, _mode: RawMode) -> Result<(), <Hexagon as Arch>::DecodeError> { Ok(()) }
fn on_word_read(&mut self, _word: <Hexagon as Arch>::Word) {}
}
@@ -1224,6 +1248,12 @@ impl<T: yaxpeax_arch::Reader<<Hexagon as Arch>::Address, <Hexagon as Arch>::Word
flags.chop = true;
Ok(())
}
+ fn raw_mode(&mut self, mode: RawMode) -> Result<(), <Hexagon as Arch>::DecodeError> {
+ let flags = &mut self.instructions[self.instruction_count as usize].flags;
+ assert!(flags.raw_mode.is_none());
+ flags.raw_mode = Some(mode);
+ Ok(())
+ }
#[inline(always)]
fn read_inst_word(&mut self, words: &mut T) -> Result<u32, <Hexagon as Arch>::DecodeError> {
self.word_count += 1;
@@ -4363,7 +4393,97 @@ fn decode_instruction<
}
}
0b1101 => {
- todo!("iclass 1101");
+ let opc_hi = (inst >> 24) & 0b1111;
+ let ddddd = reg_b0(inst);
+ let ttttt = reg_b8(inst);
+ let sssss = reg_b16(inst);
+
+ match opc_hi {
+ 0b0000 => {
+ handler.on_dest_decoded(Operand::gpr(ddddd))?;
+ handler.on_source_decoded(Operand::gprpair(sssss)?)?;
+ handler.on_source_decoded(Operand::gprpair(ttttt)?)?;
+ handler.on_opcode_decoded(Opcode::Parity)?;
+ }
+ 0b0001 => {
+ let uu = ((inst >> 5) & 0b11) as u8;
+ handler.on_dest_decoded(Operand::gprpair(ddddd)?)?;
+ handler.on_source_decoded(Operand::pred(uu))?;
+ handler.on_source_decoded(Operand::gprpair(sssss)?)?;
+ handler.on_source_decoded(Operand::gprpair(ttttt)?)?;
+ handler.on_opcode_decoded(Opcode::Vmux)?;
+ }
+ 0b0010 => {
+ opcode_check!(inst & 0x80_00_00 == 0);
+
+ let ophi = (inst >> 13) & 1;
+ let oplo = (inst >> 5) & 0b111;
+ let opc = oplo | (ophi << 3);
+ let dd = ddddd & 0b11;
+
+ handler.on_dest_decoded(Operand::pred(dd))?;
+ handler.on_source_decoded(Operand::gprpair(sssss)?)?;
+ if opc != 0b1011 {
+ handler.on_source_decoded(Operand::gprpair(ttttt)?)?;
+ } else {
+ handler.on_source_decoded(Operand::gpr(ttttt))?;
+ }
+
+ match opc {
+ 0b0000 => {
+ handler.on_opcode_decoded(Opcode::VcmpwEq)?;
+ }
+ 0b0001 => {
+ handler.on_opcode_decoded(Opcode::VcmpwGt)?;
+ }
+ 0b0010 => {
+ handler.on_opcode_decoded(Opcode::VcmpwGtu)?;
+ }
+ 0b0011 => {
+ handler.on_opcode_decoded(Opcode::VcmphEq)?;
+ }
+ 0b0100 => {
+ handler.on_opcode_decoded(Opcode::VcmphGt)?;
+ }
+ 0b0101 => {
+ handler.on_opcode_decoded(Opcode::VcmphGtu)?;
+ }
+ 0b0110 => {
+ handler.on_opcode_decoded(Opcode::VcmpbEq)?;
+ }
+ 0b0111 => {
+ handler.on_opcode_decoded(Opcode::VcmpbGtu)?;
+ }
+ 0b1000 => {
+ handler.on_opcode_decoded(Opcode::Any8VcmpbEq)?;
+ }
+ 0b1001 => {
+ handler.on_opcode_decoded(Opcode::Any8VcmpbEq)?;
+ handler.negate_result();
+ }
+ 0b1010 => {
+ handler.on_opcode_decoded(Opcode::VcmpbGt)?;
+ }
+ 0b1011 => {
+ handler.on_opcode_decoded(Opcode::Tlbmatch)?;
+ }
+ 0b1100 => {
+ handler.on_opcode_decoded(Opcode::Boundscheck)?;
+ handler.raw_mode(RawMode::Lo)?;
+ }
+ 0b1101 => {
+ handler.on_opcode_decoded(Opcode::Boundscheck)?;
+ handler.raw_mode(RawMode::Hi)?;
+ }
+ _ => {
+ return Err(DecodeError::InvalidOpcode);
+ }
+ }
+ }
+ _ => {
+ todo!("other");
+ },
+ }
}
0b1111 => {
let ddddd = reg_b0(inst);