aboutsummaryrefslogtreecommitdiff
path: root/src/armv8/a64.rs
diff options
context:
space:
mode:
authoriximeow <me@iximeow.net>2021-10-26 00:35:19 -0700
committeriximeow <me@iximeow.net>2021-10-26 00:35:19 -0700
commitd384d7fda7589de7451e8c6a82c25e7864c5cb0f (patch)
tree4b12b0bf08d9944b90ddf196cf98dfe59da140bf /src/armv8/a64.rs
parent135c63429f450dc8044fc97442dd33779050fec8 (diff)
ldrsw, correct some bitmasks, more ld/st
Diffstat (limited to 'src/armv8/a64.rs')
-rw-r--r--src/armv8/a64.rs166
1 files changed, 158 insertions, 8 deletions
diff --git a/src/armv8/a64.rs b/src/armv8/a64.rs
index 67cdb31..f3fada2 100644
--- a/src/armv8/a64.rs
+++ b/src/armv8/a64.rs
@@ -2327,10 +2327,10 @@ impl Decoder<ARMv8> for InstDecoder {
let Rt = (word & 0x1f) as u16;
let Rn = ((word >> 5) & 0x1f) as u16;
let Rt2 = ((word >> 10) & 0x1f) as u16;
- let o0 = (word & 0x0080) >> 7;
+ let o0 = (word & 0x8000) >> 15;
let Rs = ((word >> 16) & 0x1f) as u16;
let Lo1 = (word & 0x600000) >> 21;
- let size = (word >> 29) & 0x3;
+ let size = (word >> 30) & 0x3;
// load/store exclusive
// o2 == 0
inst.opcode = match size {
@@ -2394,7 +2394,7 @@ impl Decoder<ARMv8> for InstDecoder {
inst.operands = [
Operand::Register(SizeCode::W, Rs),
Operand::Register(size_code, Rt),
- Operand::RegisterOrSP(SizeCode::X, Rn), // memory operand?
+ Operand::RegOffset(Rn, 0),
Operand::Nothing,
];
match o0 {
@@ -2408,7 +2408,7 @@ impl Decoder<ARMv8> for InstDecoder {
Operand::Register(SizeCode::W, Rs),
Operand::Register(size_code, Rt),
Operand::Register(size_code, Rt2),
- Operand::RegisterOrSP(SizeCode::X, Rn), // memory operand?
+ Operand::RegOffset(Rn, 0),
];
match o0 {
0b0 => Opcode::STXP,
@@ -2419,7 +2419,7 @@ impl Decoder<ARMv8> for InstDecoder {
0b10 => {
inst.operands = [
Operand::Register(size_code, Rt),
- Operand::RegisterOrSP(SizeCode::X, Rn), // memory operand?
+ Operand::RegOffset(Rn, 0),
Operand::Nothing,
Operand::Nothing,
];
@@ -2433,7 +2433,7 @@ impl Decoder<ARMv8> for InstDecoder {
inst.operands = [
Operand::Register(size_code, Rt),
Operand::Register(size_code, Rt2),
- Operand::RegisterOrSP(SizeCode::X, Rn), // memory operand?
+ Operand::RegOffset(Rn, 0),
Operand::Nothing,
];
match o0 {
@@ -2919,7 +2919,7 @@ impl Decoder<ARMv8> for InstDecoder {
Ok((Opcode::LDRSH, SizeCode::W)),
Ok((Opcode::STR, SizeCode::W)),
Ok((Opcode::LDR, SizeCode::W)),
- Err(DecodeError::InvalidOpcode),
+ Ok((Opcode::LDRSW, SizeCode::X)),
Err(DecodeError::InvalidOpcode),
Ok((Opcode::STR, SizeCode::X)),
Ok((Opcode::LDR, SizeCode::X)),
@@ -2954,7 +2954,157 @@ impl Decoder<ARMv8> for InstDecoder {
* unprivileged, immediate pre-indexd, register offset}
* V == 1
*/
- return Err(DecodeError::IncompleteDecoder);
+ let Rt = (word & 0x1f) as u16;
+ let Rn = ((word >> 5) & 0x1f) as u16;
+ let size_opc = ((word >> 22) & 0x03) | ((word >> 28) & 0x0c);
+
+ let op4 = ((word >> 16) & 0x3f) as u8;
+ let op5 = ((word >> 10) & 0x03) as u8;
+ if op4 < 0b10_0000 {
+ let imm9 = ((((word >> 12) & 0x1ff) as i16) << 7) >> 7;
+ match op5 {
+ 0b00 => {
+ // Load/store register (unscaled immediate)
+ // V == 1
+ const OPCODES: &[Result<(Opcode, SIMDSizeCode), DecodeError>] = &[
+ Ok((Opcode::STUR, SIMDSizeCode::B)),
+ Ok((Opcode::LDUR, SIMDSizeCode::B)),
+ Ok((Opcode::STUR, SIMDSizeCode::Q)),
+ Ok((Opcode::LDUR, SIMDSizeCode::Q)),
+ // 01 1 0x
+ Ok((Opcode::STUR, SIMDSizeCode::H)),
+ Ok((Opcode::LDUR, SIMDSizeCode::H)),
+ // 01 1 1x
+ Err(DecodeError::InvalidOpcode),
+ Err(DecodeError::InvalidOpcode),
+ // 10 1 0x
+ Ok((Opcode::STUR, SIMDSizeCode::S)),
+ Ok((Opcode::LDUR, SIMDSizeCode::S)),
+ // 10 1 1x
+ Err(DecodeError::InvalidOpcode),
+ Err(DecodeError::InvalidOpcode),
+ // 11 1 0x
+ Ok((Opcode::STUR, SIMDSizeCode::D)),
+ Ok((Opcode::LDUR, SIMDSizeCode::D)),
+ // 11 1 1x
+ Err(DecodeError::InvalidOpcode),
+ Err(DecodeError::InvalidOpcode),
+ ];
+
+ let (opcode, size) = OPCODES[size_opc as usize]?;
+ inst.opcode = opcode;
+
+ inst.operands = [
+ Operand::SIMDRegister(size, Rt),
+ Operand::RegPreIndex(Rn, imm9),
+ Operand::Nothing,
+ Operand::Nothing,
+ ];
+ }
+ 0b10 => {
+ // Load/store register (unprivileged)
+ // V == 1
+ // this entire section in the manual is currently `Unallocated`
+ return Err(DecodeError::InvalidOpcode);
+ }
+ 0b01 |
+ 0b11 => {
+ // Load/store register (immediate post-indexed)
+ // and
+ // Load/store register (immediate pre-indexed)
+ // V == 1
+ let pre_or_post = (word >> 11) & 0x01;
+ const OPCODES: &[Result<(Opcode, SIMDSizeCode), DecodeError>] = &[
+ Ok((Opcode::STR, SIMDSizeCode::B)),
+ Ok((Opcode::LDR, SIMDSizeCode::B)),
+ Ok((Opcode::STR, SIMDSizeCode::Q)),
+ Ok((Opcode::LDR, SIMDSizeCode::Q)),
+ // 01 1 0x
+ Ok((Opcode::STR, SIMDSizeCode::H)),
+ Ok((Opcode::LDR, SIMDSizeCode::H)),
+ // 01 1 1x
+ Err(DecodeError::InvalidOpcode),
+ Err(DecodeError::InvalidOpcode),
+ // 10 1 0x
+ Ok((Opcode::STR, SIMDSizeCode::S)),
+ Ok((Opcode::LDR, SIMDSizeCode::S)),
+ // 10 1 1x
+ Err(DecodeError::InvalidOpcode),
+ Err(DecodeError::InvalidOpcode),
+ // 11 1 0x
+ Ok((Opcode::STR, SIMDSizeCode::D)),
+ Ok((Opcode::LDR, SIMDSizeCode::D)),
+ // 11 1 1x
+ Err(DecodeError::InvalidOpcode),
+ Err(DecodeError::InvalidOpcode),
+ ];
+
+ let (opcode, size) = OPCODES[size_opc as usize]?;
+ inst.opcode = opcode;
+
+ inst.operands = [
+ Operand::SIMDRegister(size, Rt),
+ if pre_or_post == 1 {
+ Operand::RegPreIndex(Rn, imm9)
+ } else {
+ Operand::RegPostIndex(Rn, imm9)
+ },
+ Operand::Nothing,
+ Operand::Nothing,
+ ];
+ }
+ _ => {
+ unreachable!("op5 is two bits");
+ }
+ }
+ } else {
+ match op5 {
+ 0b00 => {
+ // Atomic memory operations
+ // V == 1
+ // all `V == 1` atomic operations are unallocated.
+ return Err(DecodeError::InvalidOpcode);
+ }
+ 0b10 => {
+ // Load/store register (register offset)
+ // V == 1
+ const OPCODES: &[Result<Opcode, DecodeError>] = &[
+ Ok(Opcode::STR),
+ Ok(Opcode::LDR),
+ Ok(Opcode::STR),
+ Ok(Opcode::LDR),
+ Ok(Opcode::STR),
+ Ok(Opcode::LDR),
+ Ok(Opcode::STR),
+ Ok(Opcode::LDR),
+ // 01 1 1x
+ Err(DecodeError::InvalidOpcode),
+ Err(DecodeError::InvalidOpcode),
+ // 10 1 0x
+ Ok(Opcode::STR),
+ Ok(Opcode::LDR),
+ // 10 1 1x
+ Err(DecodeError::InvalidOpcode),
+ Err(DecodeError::InvalidOpcode),
+ // 11 1 0x
+ Ok(Opcode::STR),
+ Ok(Opcode::LDR),
+ // 11 1 1x
+ Err(DecodeError::InvalidOpcode),
+ Err(DecodeError::InvalidOpcode),
+ ];
+
+ inst.opcode = OPCODES[size_opc as usize]?;
+ return Err(DecodeError::IncompleteDecoder);
+ }
+ _ => {
+ // Load/store register (pac)
+ // not clearly named in a table but looks like all `V == 1` are
+ // unallocated.
+ return Err(DecodeError::InvalidOpcode);
+ }
+ }
+ }
}
0b11010 |
0b11011 => {