Skip to content

Commit 0ab8b45

Browse files
committed
merge basic control flow
2 parents b6e4099 + 6025db8 commit 0ab8b45

12 files changed

Lines changed: 303 additions & 76 deletions

flake.nix

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
];
3636
packages = with pkgs; [
3737
rust-analyzer-nightly
38+
clang-tools
3839
];
3940
};
4041
}

run.sh

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
#!/usr/bin/env bash
22

3-
aarch64-linux-gnu-as test_binary_translate_add.S
4-
aarch64-linux-gnu-ld a.out -o a.bin
5-
./a.bin
3+
ASM_FILE=$1
4+
5+
6+
aarch64-linux-gnu-as $ASM_FILE -o $ASM_FILE.as
7+
aarch64-linux-gnu-ld $ASM_FILE.as -o $ASM_FILE.bin
8+
./$ASM_FILE.bin
69
echo $?

src/instruction.rs

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,20 @@ use std::fmt::{format, write, Display};
1313
/// https://github.com/nbdd0121/r2vm/blob/5118be6b9e757c6fef2f019385873f403c23c548/lib/riscv/src/op.rs#L30
1414
use strum_macros::EnumString;
1515

16+
pub enum RiscVSyscalls {
17+
WRITE,
18+
EXIT
19+
}
20+
21+
impl RiscVSyscalls {
22+
const fn value(&self) -> i32 {
23+
match self {
24+
Self::WRITE => 64,
25+
Self::EXIT => 0,
26+
}
27+
}
28+
}
29+
1630
#[derive(Debug, Default)]
1731
pub enum RiscVWidth {
1832
Word,
@@ -143,6 +157,11 @@ pub enum RiscVInstruction {
143157
/// https://michaeljclark.github.io/asm.html
144158
#[strum(serialize = "li")]
145159
Li { dest: RiscVRegister, imm: i32 },
160+
/// System Call
161+
#[strum(serialize = "ecall")]
162+
ECall,
163+
#[strum(serialize = "verbatim")]
164+
Verbatim { text: String },
146165
}
147166

148167
impl Default for RiscVInstruction {
@@ -154,6 +173,20 @@ impl Default for RiscVInstruction {
154173
}
155174
}
156175

176+
pub enum ArmSyscalls {
177+
WRITE,
178+
EXIT
179+
}
180+
181+
impl ArmSyscalls {
182+
const fn value(&self) -> i32 {
183+
match self {
184+
Self::WRITE => 64,
185+
Self::EXIT => 0,
186+
}
187+
}
188+
}
189+
157190
#[derive(Debug)]
158191
pub enum ArmVal {
159192
Reg(ArmRegister),
@@ -259,6 +292,12 @@ pub enum ArmInstruction {
259292
/// sign extend to word
260293
#[strum(serialize = "sxtw")]
261294
Sxtw { dest: ArmRegister, src: ArmRegister },
295+
/// service call
296+
#[strum(serialize = "svc")]
297+
Svc { id: i32 },
298+
/// compare
299+
Cmp { op1: ArmRegister, op2: ArmVal },
300+
Verbatim { text: String },
262301
}
263302

264303
impl Default for ArmInstruction {
@@ -542,6 +581,13 @@ impl Into<String> for ArmInstruction {
542581
ArmInstruction::Directive { name, operands } => {
543582
format!(".{} {}", name, operands)
544583
}
584+
ArmInstruction::Svc { id } => {
585+
format!("svc {}", id)
586+
},
587+
ArmInstruction::Cmp { op1, op2 } => {
588+
format!("cmp {}, {}", op1, op2)
589+
}
590+
ArmInstruction::Verbatim { text } => text
545591
}
546592
}
547593
}
@@ -621,7 +667,7 @@ impl Into<String> for ArmRegister {
621667
(ArmRegisterName::X8, ArmWidth::Half) => todo!(),
622668
(ArmRegisterName::X8, ArmWidth::SignedHalf) => todo!(),
623669
(ArmRegisterName::X8, ArmWidth::Word) => todo!(),
624-
(ArmRegisterName::X8, ArmWidth::Double) => todo!(),
670+
(ArmRegisterName::X8, ArmWidth::Double) => "x8",
625671
(ArmRegisterName::X9, ArmWidth::Byte) => todo!(),
626672
(ArmRegisterName::X9, ArmWidth::SignedByte) => todo!(),
627673
(ArmRegisterName::X9, ArmWidth::Half) => todo!(),

src/translate.rs

Lines changed: 82 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ macro_rules! sorry {
1414
/// Run the core logic to match from RISC-V to ARM Instructions.
1515
1616
/// Translate one instruction at a time.
17-
pub fn translate(riscv_instr: RiscVInstruction) -> ArmInstruction {
17+
pub fn translate(riscv_instr: RiscVInstruction) -> Vec<ArmInstruction> {
1818
match riscv_instr {
1919
RiscVInstruction::Addi { dest, src, imm } => {
2020
if let RiscVRegister::X0 = src {
@@ -23,68 +23,68 @@ pub fn translate(riscv_instr: RiscVInstruction) -> ArmInstruction {
2323

2424
let width = RiscVWidth::Double;
2525
if imm >= 0 {
26-
ArmInstruction::Add {
26+
vec![ArmInstruction::Add {
2727
dest: map_register(dest, &width),
2828
arg1: map_register(src, &width),
2929
arg2: ArmVal::Imm(imm),
30-
}
30+
}]
3131
} else {
32-
ArmInstruction::Sub {
32+
vec![ArmInstruction::Sub {
3333
dest: map_register(dest, &width),
3434
arg1: map_register(src, &width),
3535
arg2: ArmVal::Imm(imm.abs()),
36-
}
36+
}]
3737
}
3838
},
39-
RiscVInstruction::Ble { arg1, arg2, target } => {
39+
RiscVInstruction::Ble { arg1, arg2, target } => vec![{
4040
let width = RiscVWidth::Double;
4141
ArmInstruction::Ble {
4242
arg1: map_register(arg1, &width),
4343
arg2: map_register(arg2, &width),
4444
target: map_val(target, &width)
4545
}
46-
},
47-
RiscVInstruction::J { target } => ArmInstruction::B {
46+
}],
47+
RiscVInstruction::J { target } => vec![ArmInstruction::B {
4848
target: map_val(target, &RiscVWidth::Double)
49-
},
50-
RiscVInstruction::S { width, src, dest } => ArmInstruction::Str {
49+
}],
50+
RiscVInstruction::S { width, src, dest } => vec![ArmInstruction::Str {
5151
width: map_width(&width),
5252
src: map_register(src, &width),
5353
dest: map_val(dest, &width),
54-
},
55-
RiscVInstruction::L { width, dest, src } => ArmInstruction::Ldr {
54+
}],
55+
RiscVInstruction::L { width, dest, src } => vec![ArmInstruction::Ldr {
5656
width: map_width(&width),
5757
dest: map_register(dest, &width),
5858
src: map_val(src, &width),
59-
},
59+
}],
6060
RiscVInstruction::Directive { name, operands } => {
6161
let arm_operands = operands.replace("@", "%");
62-
ArmInstruction::Directive { name, operands: arm_operands }
62+
vec![ArmInstruction::Directive { name, operands: arm_operands }]
6363
}
64-
RiscVInstruction::Label { name } => ArmInstruction::Label { name },
64+
RiscVInstruction::Label { name } => vec![ArmInstruction::Label { name }],
6565
RiscVInstruction::Mv { dest, src } => {
6666
let width = RiscVWidth::Double;
67-
ArmInstruction::Add {
67+
vec![ArmInstruction::Add {
6868
dest: map_register(dest, &width),
6969
arg1: map_register(src, &width),
7070
arg2: ArmVal::Imm(0),
71-
}
72-
}
73-
RiscVInstruction::Mvi { dest, imm } => {
71+
}]
72+
},
73+
RiscVInstruction::Mvi { dest, imm } => {
7474
let width = RiscVWidth::Double;
75-
ArmInstruction::Mov {
75+
vec![ArmInstruction::Mov {
7676
width: map_width(&width),
7777
dest: map_register(dest, &width),
78-
src: ArmVal::Imm(imm),
79-
}
80-
}
78+
src: ArmVal::Imm(imm)
79+
}]
80+
},
8181
RiscVInstruction::Add {
8282
width,
8383
dest,
8484
arg1,
8585
arg2,
8686
} => match width {
87-
RiscVWidth::Word => ArmInstruction::Add {
87+
RiscVWidth::Word => vec![ArmInstruction::Add {
8888
dest: ArmRegister {
8989
width: ArmWidth::Word,
9090
name: map_register_name(dest),
@@ -97,10 +97,10 @@ pub fn translate(riscv_instr: RiscVInstruction) -> ArmInstruction {
9797
width: ArmWidth::Word,
9898
name: map_register_name(arg2),
9999
}),
100-
},
100+
}],
101101
RiscVWidth::Double => sorry!(),
102102
},
103-
RiscVInstruction::SextW { dest, src } => ArmInstruction::Sxtw {
103+
RiscVInstruction::SextW { dest, src } => vec![ArmInstruction::Sxtw {
104104
dest: ArmRegister {
105105
width: ArmWidth::Double,
106106
name: map_register_name(dest),
@@ -109,21 +109,21 @@ pub fn translate(riscv_instr: RiscVInstruction) -> ArmInstruction {
109109
width: ArmWidth::Word,
110110
name: map_register_name(src),
111111
},
112-
},
113-
RiscVInstruction::Jr { target } => ArmInstruction::Blr {
112+
}],
113+
RiscVInstruction::Jr { target } => vec![ArmInstruction::Blr {
114114
target: map_register_name(target),
115-
},
115+
}],
116116
RiscVInstruction::Li { dest, imm } => {
117117
if imm > 4095 || imm < 0 {
118118
panic!("Li with imm out of range");
119119
}
120120

121121
let width = RiscVWidth::Double;
122-
ArmInstruction::Mov {
122+
vec![ArmInstruction::Mov {
123123
width: map_width(&width),
124124
dest: map_register(dest, &width),
125125
src: ArmVal::Imm(imm),
126-
}
126+
}]
127127
// ArmInstruction::Add {
128128
// dest: map_register(dest, &RiscVWidth::Double),
129129
// arg1: ArmRegister {
@@ -135,26 +135,44 @@ pub fn translate(riscv_instr: RiscVInstruction) -> ArmInstruction {
135135
},
136136
RiscVInstruction::Addl { dest, src, label } => {
137137
let width = RiscVWidth::Double;
138-
ArmInstruction::Add {
138+
vec![ArmInstruction::Add {
139139
dest: map_register(dest, &width),
140140
arg1: map_register(src, &width),
141141
arg2: map_val(label, &width),
142-
}
142+
}]
143143
},
144144
RiscVInstruction::Lui { dest, src } => {
145145
// only used to load upper bits or adrp in arm
146146
let width = RiscVWidth::Double;
147-
ArmInstruction::Adrp {
147+
vec![ArmInstruction::Adrp {
148148
dest: map_register(dest, &width),
149149
label: map_val(src, &width),
150-
}
150+
}]
151151
},
152152
RiscVInstruction::Call { label } => {
153153
let width = RiscVWidth::Double;
154-
ArmInstruction::Bl {
154+
vec![ArmInstruction::Bl {
155155
target: map_val(label, &width),
156-
}
156+
}]
157+
}
158+
RiscVInstruction::ECall => {
159+
let syscall_num_reg = ArmRegister{
160+
width: ArmWidth::Double,
161+
name: ArmRegisterName::X8
162+
};
163+
vec![
164+
// ArmInstruction::Cmp(syscall_num_reg, ArmVal::Imm(RISCV_WRITE)), // if (x8 == RISCV_WRITE) {
165+
// ArmInstruction::Bne("else"),
166+
// ArmInstruction::Mov { width: ArmWidth::Double, dest: x8, src: ArmVal::Imm(SYS_WRITE) }, // x8 = ARM_WRITE;
167+
// ArmInstruction::B("done"),
168+
// ArmInstruction::Label("else"), // } else {
169+
// ArmInstruction::Mov { width: ArmWidth::Double, dest: x8, src: ArmVal::Imm(__) }, // x8 = ARM_EXIT
170+
// // }
171+
// ArmInstruction::Label("done"),
172+
ArmInstruction::Svc { id: 0 }
173+
]
157174
}
175+
RiscVInstruction::Verbatim { text } => vec![ArmInstruction::Verbatim { text }]
158176
}
159177
}
160178

@@ -172,21 +190,30 @@ fn map_register_name(riscv_reg: RiscVRegister) -> ArmRegisterName {
172190
RiscVRegister::X0 => ArmRegisterName::Zero,
173191
RiscVRegister::RA => ArmRegisterName::Lr,
174192
RiscVRegister::SP => ArmRegisterName::Sp,
175-
RiscVRegister::GP => ArmRegisterName::X0,
176-
RiscVRegister::TP => ArmRegisterName::X1,
177-
RiscVRegister::T0 => ArmRegisterName::X2,
178-
RiscVRegister::T1 => ArmRegisterName::X3,
179-
RiscVRegister::T2 => ArmRegisterName::X4,
193+
RiscVRegister::GP => ArmRegisterName::X12,
194+
RiscVRegister::TP => ArmRegisterName::X14,
195+
RiscVRegister::T0 => ArmRegisterName::X9,
196+
RiscVRegister::T1 => ArmRegisterName::X10,
197+
RiscVRegister::T2 => ArmRegisterName::X11,
180198
// skipped X5
181-
RiscVRegister::S1 => ArmRegisterName::X6,
182-
RiscVRegister::A0 => ArmRegisterName::X0,
183-
RiscVRegister::A1 => ArmRegisterName::X1,
184-
RiscVRegister::A2 => ArmRegisterName::X2,
185-
RiscVRegister::A3 => ArmRegisterName::X3,
186-
RiscVRegister::A4 => ArmRegisterName::X4,
187-
RiscVRegister::A5 => ArmRegisterName::X5,
188-
RiscVRegister::A6 => ArmRegisterName::X6,
189-
RiscVRegister::A7 => ArmRegisterName::X7,
199+
// RiscVRegister::S1 => ArmRegisterName::X6,
200+
// RiscVRegister::A0 => ArmRegisterName::X0,
201+
// RiscVRegister::A1 => ArmRegisterName::X1,
202+
// RiscVRegister::A2 => ArmRegisterName::X2,
203+
// RiscVRegister::A3 => ArmRegisterName::X3,
204+
// RiscVRegister::A4 => ArmRegisterName::X4,
205+
// RiscVRegister::A5 => ArmRegisterName::X5,
206+
// RiscVRegister::A6 => ArmRegisterName::X6,
207+
// RiscVRegister::A7 => ArmRegisterName::X7,
208+
RiscVRegister::S1 => ArmRegisterName::X13,
209+
RiscVRegister::A0 => ArmRegisterName::X0, // return value/syscall arg 0
210+
RiscVRegister::A1 => ArmRegisterName::X1, // syscall arg 1
211+
RiscVRegister::A2 => ArmRegisterName::X2, // syscall arg 2
212+
RiscVRegister::A3 => ArmRegisterName::X3, // syscall arg 3
213+
RiscVRegister::A4 => ArmRegisterName::X4, // syscall arg 4
214+
RiscVRegister::A5 => ArmRegisterName::X5, // syscall arg 5
215+
RiscVRegister::A6 => ArmRegisterName::X6, // syscall arg 6
216+
RiscVRegister::A7 => ArmRegisterName::X8, // syscall number
190217
RiscVRegister::S2 => ArmRegisterName::X15,
191218
RiscVRegister::S3 => ArmRegisterName::X16,
192219
RiscVRegister::S4 => ArmRegisterName::X17,
@@ -227,8 +254,10 @@ fn map_width(riscv_width: &RiscVWidth) -> ArmWidth {
227254
pub fn translate_instrs(riscv_instrs: Vec<RiscVInstruction>) -> Vec<ArmInstruction> {
228255
riscv_instrs
229256
.into_iter()
230-
.map(|instr| translate(instr))
231-
.collect::<Vec<ArmInstruction>>()
257+
.map(translate).fold(vec![], |mut acc, x|{
258+
acc.extend(x);
259+
acc
260+
})
232261
}
233262

234263
/// Runs binary translation

src/utils.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use std::fs;
22

33
use crate::{instruction::RiscVInstruction, translate::translate_instrs};
44

5-
const start: &str = r#"
5+
pub const START: &str = r#"
66
.text
77
88
.global _start
@@ -15,9 +15,10 @@ svc #0
1515
main:
1616
"#;
1717

18+
1819
pub fn translate_to_file(instrs: Vec<RiscVInstruction>, path: String) {
1920
let arm_instrs = translate_instrs(instrs);
20-
let mut contents = String::from(start);
21+
let mut contents = String::new();
2122
for instr in arm_instrs {
2223
let x: String = instr.into();
2324
contents.push_str(&x);

0 commit comments

Comments
 (0)