aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoriximeow <me@iximeow.net>2021-12-29 16:40:17 -0800
committeriximeow <me@iximeow.net>2021-12-29 16:40:17 -0800
commit1d17d723300bccc0ba7f7c0af3ea1acc39794dbc (patch)
tree2a33e73703ff156157bb3f70c31f564fdec90d8c
parent125966cd2ae732c3e8faa9ce0b1423dee91fc026 (diff)
memory tags
-rw-r--r--src/armv8/a64.rs86
1 files changed, 86 insertions, 0 deletions
diff --git a/src/armv8/a64.rs b/src/armv8/a64.rs
index e6ed329..9dec1d4 100644
--- a/src/armv8/a64.rs
+++ b/src/armv8/a64.rs
@@ -1240,6 +1240,15 @@ pub enum Opcode {
TBX,
FCADD,
+
+ LDGM,
+ LDG,
+ STGM,
+ STZGM,
+ STG,
+ STZG,
+ ST2G,
+ STZ2G,
}
impl Display for Opcode {
@@ -2001,6 +2010,14 @@ impl Display for Opcode {
Opcode::TBL => "tbl",
Opcode::TBX => "tbx",
Opcode::FCADD => "fcadd",
+ Opcode::LDGM => "ldgm",
+ Opcode::LDG => "ldm",
+ Opcode::STGM => "stgm",
+ Opcode::STZGM => "stzgm",
+ Opcode::STG => "stg",
+ Opcode::STZG => "stzg",
+ Opcode::ST2G => "st2g",
+ Opcode::STZ2G => "stz2g",
Opcode::Bcc(cond) => {
return write!(fmt, "b.{}", Operand::ConditionCode(cond));
@@ -7405,6 +7422,75 @@ impl Decoder<ARMv8> for InstDecoder {
Operand::Nothing,
];
},
+ 0b01010 |
+ 0b01011 => {
+ // `Load/store memory tags`, `Load/store exclusive`
+ let op0 = (word >> 28) & 0b11111;
+ let op3 = (word >> 16) & 0b111111;
+ let op4 = (word >> 10) & 0b11;
+
+ if op3 & 0b100000 == 0 {
+ if op4 != 0b00 {
+ return Err(DecodeError::InvalidOpcode);
+ }
+ // else, `LDAPR/STLR (unscaled immediate)`
+ } else {
+ if op0 != 0b1101 {
+ return Err(DecodeError::InvalidOpcode);
+ }
+ // else, `Load/store memory tags`
+ let opc = (word >> 22) & 0b11;
+ let imm9 = (word >> 12) & 0b111_111_111;
+ let op2 = (word >> 10) & 0b11;
+ let Rn = ((word >> 5) & 0b11111) as u16;
+ let Rt = ((word >> 0) & 0b11111) as u16;
+
+ let simm = ((imm9 as i16) << 7) >> 7;
+
+ let opcode = &[
+ Opcode::STZGM, Opcode::STG, Opcode::STG, Opcode::STG,
+ Opcode::LDG, Opcode::STZG, Opcode::STZG, Opcode::STZG,
+ Opcode::STGM, Opcode::ST2G, Opcode::ST2G, Opcode::ST2G,
+ Opcode::LDGM, Opcode::STZ2G, Opcode::STZ2G, Opcode::STZ2G,
+ ][((opc << 2) | (op2)) as usize];
+
+ inst.opcode = *opcode;
+
+ if op2 == 0 && imm9 != 0 {
+ if opc == 0b01 {
+ // ldg
+ inst.operands = [
+ Operand::Register(SizeCode::X, Rt),
+ Operand::RegOffset(Rn, simm),
+ Operand::Nothing,
+ Operand::Nothing,
+ ];
+ return Ok(());
+ } else {
+ return Err(DecodeError::InvalidOperand);
+ }
+ }
+
+ inst.operands = [
+ if op2 == 0b00 {
+ Operand::Register(SizeCode::X, Rt)
+ } else {
+ Operand::RegisterOrSP(SizeCode::X, Rt)
+ },
+ if op2 == 0b00 {
+ Operand::RegOffset(Rn, 0)
+ } else if op2 == 0b01 {
+ Operand::RegPostIndex(Rn, simm as i32)
+ } else if op2 == 0b10 {
+ Operand::RegOffset(Rn, simm)
+ } else {
+ Operand::RegPreIndex(Rn, simm as i32, true)
+ },
+ Operand::Nothing,
+ Operand::Nothing,
+ ];
+ }
+ },
0b01100 |
0b01101 => {
// load register (literal)