1use crate::encoder::riscv::RiscVEncoder;
9use crate::encoder::traits::{InstructionEncoder, ParsedInstruction};
10use crate::error::RasError;
11
12pub struct Arx64Encoder {
13 inner: RiscVEncoder,
14}
15
16impl Arx64Encoder {
17 pub fn new() -> Self {
18 Self {
19 inner: RiscVEncoder::new(true),
20 }
21 }
22
23 fn normalize_operand(operand: &str) -> String {
24 let mut out = operand.to_string();
25 for reg in (0..32).rev() {
26 out = out.replace(&format!("r{}", reg), &format!("x{}", reg));
27 out = out.replace(&format!("%r{}", reg), &format!("x{}", reg));
28 }
29 out
30 }
31
32 fn normalize_instruction(inst: &ParsedInstruction) -> ParsedInstruction {
33 ParsedInstruction {
34 opcode: inst.opcode.clone(),
35 operands: inst
36 .operands
37 .iter()
38 .map(|operand| Self::normalize_operand(operand))
39 .collect(),
40 }
41 }
42}
43
44impl Default for Arx64Encoder {
45 fn default() -> Self {
46 Self::new()
47 }
48}
49
50impl InstructionEncoder for Arx64Encoder {
51 fn encode_instruction(&mut self, inst: &ParsedInstruction) -> Result<Vec<u8>, RasError> {
52 let normalized = Self::normalize_instruction(inst);
53 self.inner.encode_instruction(&normalized)
54 }
55
56 fn current_position(&self) -> usize {
57 self.inner.current_position()
58 }
59}
60
61#[cfg(test)]
62mod tests {
63 use super::*;
64
65 fn instr(opcode: &str, operands: &[&str]) -> ParsedInstruction {
66 ParsedInstruction {
67 opcode: opcode.to_string(),
68 operands: operands.iter().map(|s| s.to_string()).collect(),
69 }
70 }
71
72 #[test]
73 fn encodes_arx_register_names() {
74 let bytes = Arx64Encoder::new()
75 .encode_instruction(&instr("add", &["r5", "r6", "r7"]))
76 .expect("encode");
77 let word = u32::from_le_bytes([bytes[0], bytes[1], bytes[2], bytes[3]]);
78 assert_eq!((word >> 7) & 0x1f, 5);
79 assert_eq!((word >> 15) & 0x1f, 6);
80 assert_eq!((word >> 20) & 0x1f, 7);
81 }
82
83 #[test]
84 fn encodes_arx_memory_operand_names() {
85 let bytes = Arx64Encoder::new()
86 .encode_instruction(&instr("ld", &["r5", "8(r2)"]))
87 .expect("encode");
88 let word = u32::from_le_bytes([bytes[0], bytes[1], bytes[2], bytes[3]]);
89 assert_eq!(word & 0x7f, 0x03);
90 assert_eq!((word >> 7) & 0x1f, 5);
91 assert_eq!((word >> 15) & 0x1f, 2);
92 }
93}