1+ use std:: default;
2+
13/// This file defines all the supported ARM and RISC-V instructions we support.
24/// We use `strum` to assist in serializing asm files to our [`Instruction`] enum.
35///
911/// https://github.com/nbdd0121/r2vm/blob/5118be6b9e757c6fef2f019385873f403c23c548/lib/riscv/src/op.rs#L30
1012use strum_macros:: EnumString ;
1113
14+ #[ derive( Debug , Default ) ]
15+ pub enum RiscVWidth {
16+ Word ,
17+ #[ default]
18+ Double ,
19+ }
20+
1221/// RISC-V Instructions
1322/// https://msyksphinz-self.github.io/riscv-isadoc/html/rvi.html
1423///
@@ -26,39 +35,44 @@ pub enum RiscVInstruction {
2635 src : RiscVRegister ,
2736 imm : i32 ,
2837 } ,
29- /// Store 64-bit, values from register rs2 to memory.
38+ /// add register
39+ /// either add or addw
40+ /// (addw is 32 bits on 64 bit riscv)
41+ ///
42+ /// `x[rd] = sext((x[rs1] + x[rs2])[31:0])`
43+ #[ strum( serialize = "addw" ) ]
44+ Add {
45+ // dest = arg1 + arg2
46+ width : RiscVWidth ,
47+ dest : RiscVRegister ,
48+ arg1 : RiscVRegister ,
49+ arg2 : RiscVRegister ,
50+ } ,
51+ /// Store values from register rs2 to memory.
3052 ///
31- /// `M[x[rs1] + sext(offset)] = x[rs2][63:0] `
53+ /// `M[x[rs1] + sext(offset)] = x[rs2]`
3254 #[ strum( serialize = "sd" ) ]
33- Sd {
55+ S {
56+ width : RiscVWidth ,
3457 src : RiscVRegister ,
3558 dest : RiscVVal ,
3659 } ,
37- /// Loads a 64-bit value from memory into register rd for RV64I.
60+ /// Loads a value from memory into register rd for RV64I.
3861 ///
39- /// `x[rd] = M[x[rs1] + sext(offset)][63:0] `
62+ /// `x[rd] = M[x[rs1] + sext(offset)]`
4063 #[ strum( serialize = "ld" ) ]
41- Ld { dest : RiscVRegister , src : RiscVVal } ,
42- /// Loads a 32-bit value from memory and sign-extends this to XLEN bits
43- /// before storing it in register rd.
44- ///
45- /// `x[rd] = sext(M[x[rs1] + sext(offset)][31:0])`
46- #[ strum( serialize = "lw" ) ]
47- Lw { dest : RiscVRegister , src : RiscVVal } ,
48- /// Store 32-bit, values from the low bits of register rs2 to memory.
49- ///
50- /// `M[x[rs1] + sext(offset)] = x[rs2][31:0]`
51- #[ strum( serialize = "sw" ) ]
52- Sw { dest : RiscVRegister , src : RiscVVal } ,
64+ L {
65+ width : RiscVWidth ,
66+ dest : RiscVRegister ,
67+ src : RiscVVal ,
68+ } ,
5369 // Copy register
5470 // `mv rd, rs1` expands to `addi rd, rs, 0`
5571 #[ strum( serialize = "mv" ) ]
5672 Mv {
5773 dest : RiscVRegister ,
5874 src : RiscVRegister ,
5975 } ,
60- #[ strum( serialize = "addw" ) ]
61- Addw ,
6276 /// Sign extend Word
6377 ///
6478 /// psuedo instruction which translates to `addiw rd, rs, 0`
@@ -67,6 +81,13 @@ pub enum RiscVInstruction {
6781 dest : RiscVRegister ,
6882 src : RiscVRegister ,
6983 } ,
84+ /// Jump Register
85+ /// Jump to address and place return address in rd.
86+ /// jal rd,offset
87+ ///
88+ /// Psuedo instruction:
89+ /// jr offset => jal x1, offset
90+ ///
7091 #[ strum( serialize = "jr" ) ]
7192 Jr { target : RiscVRegister } ,
7293 /// Load Immediate
@@ -79,7 +100,16 @@ pub enum RiscVInstruction {
79100 /// semantics.
80101 /// https://michaeljclark.github.io/asm.html
81102 #[ strum( serialize = "li" ) ]
82- Li { imm : i32 } ,
103+ Li { dest : RiscVRegister , imm : i32 } ,
104+ }
105+
106+ impl Default for RiscVInstruction {
107+ fn default ( ) -> Self {
108+ Self :: Li {
109+ dest : RiscVRegister :: X0 ,
110+ imm : 0 ,
111+ }
112+ }
83113}
84114
85115#[ derive( Debug ) ]
@@ -89,6 +119,28 @@ pub enum ArmVal {
89119 RegOffset ( ArmRegister , i32 ) ,
90120}
91121
122+ impl Default for ArmVal {
123+ fn default ( ) -> Self {
124+ todo ! ( )
125+ }
126+ }
127+
128+ #[ derive( Debug ) ]
129+ pub enum ArmWidth {
130+ Byte ,
131+ SignedByte ,
132+ Half ,
133+ SignedHalf ,
134+ Word ,
135+ Double ,
136+ }
137+
138+ impl Default for ArmWidth {
139+ fn default ( ) -> Self {
140+ todo ! ( )
141+ }
142+ }
143+
92144/// ARM Instructions
93145/// `https://iitd-plos.github.io/col718/ref/arm-instructionset.pdf#page=3`
94146#[ derive( Debug , EnumString ) ]
@@ -111,30 +163,47 @@ pub enum ArmInstruction {
111163 /// B Branch R15 := address
112164 #[ strum( serialize = "b" ) ]
113165 B ,
166+ /// BLR Xn
167+ #[ strum( serialize = "blr" ) ]
168+ Blr { target : ArmRegisterName } ,
114169 #[ strum( serialize = "ldr" ) ]
115- Ldr ,
170+ Ldr {
171+ width : ArmWidth ,
172+ dest : ArmRegister ,
173+ src : ArmVal ,
174+ } ,
116175 #[ strum( serialize = "mov" ) ]
117176 Mov ,
118177 #[ strum( serialize = "ret" ) ]
119178 Ret ,
120179 /// Str [r2 + offset] = r1
121180 #[ strum( serialize = "str" ) ]
122181 Str {
182+ width : ArmWidth ,
123183 src : ArmRegister ,
124- dst : ArmVal ,
125- }
184+ dest : ArmVal ,
185+ } ,
126186 /// Sub Sub Rd := Rn - Op2
127187 #[ strum( serialize = "sub" ) ]
128188 Sub {
129189 dest : ArmRegister ,
130190 arg1 : ArmRegister ,
131191 arg2 : ArmVal ,
132192 } ,
193+ /// sign extend to word
194+ #[ strum( serialize = "sxtw" ) ]
195+ Sxtw { dest : ArmRegister , src : ArmRegister } ,
196+ }
197+
198+ impl Default for ArmInstruction {
199+ fn default ( ) -> Self {
200+ ArmInstruction :: B
201+ }
133202}
134203
135204#[ derive( Debug ) ]
136205pub enum RiscVVal {
137- RiscVRegister ,
206+ RiscVRegister ( RiscVRegister ) ,
138207 Immediate ( i32 ) ,
139208 /// This is for arguments to opcodes which have an offset
140209 Offset {
@@ -143,10 +212,17 @@ pub enum RiscVVal {
143212 } ,
144213}
145214
215+ impl Default for RiscVVal {
216+ fn default ( ) -> Self {
217+ Self :: Immediate ( 0 )
218+ }
219+ }
220+
146221/// RISC-V Registers
147222/// https://msyksphinz-self.github.io/riscv-isadoc/html/regs.html
148- #[ derive( Debug , EnumString ) ]
223+ #[ derive( Debug , EnumString , Default ) ]
149224pub enum RiscVRegister {
225+ #[ default]
150226 #[ strum( serialize = "x0" ) ]
151227 /// Hard-wired zero
152228 X0 ,
@@ -245,10 +321,22 @@ pub enum RiscVRegister {
245321 T6 ,
246322}
247323
324+ #[ derive( Debug ) ]
325+ pub struct ArmRegister {
326+ pub width : ArmWidth ,
327+ pub name : ArmRegisterName ,
328+ }
329+
330+ impl Default for ArmRegister {
331+ fn default ( ) -> Self {
332+ todo ! ( )
333+ }
334+ }
335+
248336/// ARM Registers
249337/// https://developer.arm.com/documentation/dui0056/d/using-the-procedure-call-standard/register-roles-and-names/register-names
250338#[ derive( Debug , EnumString ) ]
251- pub enum ArmRegister {
339+ pub enum ArmRegisterName {
252340 #[ strum( serialize = "pc" ) ]
253341 /// Program counter.
254342 Pc ,
@@ -297,6 +385,14 @@ pub enum ArmRegister {
297385 #[ strum( serialize = "a1" ) ]
298386 /// Argument/result/scratch register 1.
299387 A1 ,
388+ #[ strum( serialize = "wzr" , serialize = "xzr" ) ]
389+ Zero ,
390+ }
391+
392+ impl Default for ArmRegisterName {
393+ fn default ( ) -> Self {
394+ todo ! ( )
395+ }
300396}
301397
302398/// Parse a text file into our enum.
@@ -310,7 +406,8 @@ pub fn parse_asm(asm: &str) -> Vec<RiscVInstruction> {
310406 if parts. is_empty ( ) {
311407 None
312408 } else {
313- RiscVInstruction :: from_str ( parts[ 0 ] ) . ok ( )
409+ // RiscVInstruction::from_str(parts[0]).ok()
410+ todo ! ( )
314411 }
315412 } )
316413 . collect ( )
0 commit comments