diff --git a/.gitignore b/.gitignore index 92bc8d3..161d7f2 100644 --- a/.gitignore +++ b/.gitignore @@ -28,3 +28,4 @@ Cargo.lock *.bin .vscode/ +test_binary_translate* \ No newline at end of file diff --git a/run.sh b/run.sh index 45ea602..31240d2 100755 --- a/run.sh +++ b/run.sh @@ -1,9 +1,31 @@ #!/usr/bin/env bash ASM_FILE=$1 +PLATFORM="" +LD_FLAGS="" +BENCHMARKING="false" # "true" to enable +if [[ -z "$ASM_FILE" ]]; then + echo "Error: Assembly (.S) file is not passed in." + echo "Usage: ./run.sh test_binary_translate_add.S" + exit 1 +fi -aarch64-linux-gnu-as $ASM_FILE -o $ASM_FILE.as -aarch64-linux-gnu-ld $ASM_FILE.as -o $ASM_FILE.bin -./$ASM_FILE.bin -echo $? +if [[ "$OSTYPE" == "linux-gnu"* ]]; then + PLATFORM="aarch64-linux-gnu" +fi + +if [[ "$OSTYPE" == "darwin"* ]]; then + LD_FLAGS="-lSystem -macosx_version_min 11.3 -L/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/lib" +fi + + +"$PLATFORM"as "$ASM_FILE" -o "$ASM_FILE".as || { echo "Assembly compilation failed"; exit 1; } +"$PLATFORM"ld "$ASM_FILE".as -o "$ASM_FILE".bin $LD_FLAGS || { echo "Linking failed"; exit 1; } + +./"$ASM_FILE".bin +echo "$?" + +if [ "$BENCHMARKING" = true ]; then + hyperfine -r 1000 -w 100 -Ni ./"$ASM_FILE".bin +fi diff --git a/src/instruction.rs b/src/instruction.rs index 67d8789..d8cfa43 100644 --- a/src/instruction.rs +++ b/src/instruction.rs @@ -15,7 +15,7 @@ use strum_macros::EnumString; pub enum RiscVSyscalls { WRITE, - EXIT + EXIT, } impl RiscVSyscalls { @@ -55,7 +55,7 @@ pub enum RiscVInstruction { Addl { dest: RiscVRegister, src: RiscVRegister, - label: RiscVVal + label: RiscVVal, }, /// add register /// either add or addw @@ -75,12 +75,12 @@ pub enum RiscVInstruction { Ble { arg1: RiscVRegister, arg2: RiscVRegister, - target: RiscVVal + target: RiscVVal, }, /// call label #[strum(serialize = "call")] Call { - label: RiscVVal + label: RiscVVal, }, /// Store values from register rs2 to memory. /// @@ -102,15 +102,15 @@ pub enum RiscVInstruction { }, Directive { name: String, - operands: String + operands: String, }, Label { - name: String + name: String, }, #[strum(serialize = "lui")] Lui { dest: RiscVRegister, - src: RiscVVal + src: RiscVVal, }, // Copy register // `mv rd, rs1` expands to `addi rd, rs, 0` @@ -136,7 +136,9 @@ pub enum RiscVInstruction { }, /// Jump label #[strum(serialize = "j")] - J { target: RiscVVal }, + J { + target: RiscVVal, + }, /// Jump Register /// Jump to address and place return address in rd. /// jal rd,offset @@ -145,7 +147,9 @@ pub enum RiscVInstruction { /// jr offset => jal x1, offset /// #[strum(serialize = "jr")] - Jr { target: RiscVRegister }, + Jr { + target: RiscVRegister, + }, /// Load Immediate /// This is a pseudo instruction, so it's not a real instruction /// @@ -156,12 +160,17 @@ pub enum RiscVInstruction { /// semantics. /// https://michaeljclark.github.io/asm.html #[strum(serialize = "li")] - Li { dest: RiscVRegister, imm: i32 }, + Li { + dest: RiscVRegister, + imm: i32, + }, /// System Call #[strum(serialize = "ecall")] ECall, #[strum(serialize = "verbatim")] - Verbatim { text: String }, + Verbatim { + text: String, + }, } impl Default for RiscVInstruction { @@ -175,7 +184,7 @@ impl Default for RiscVInstruction { pub enum ArmSyscalls { WRITE, - EXIT + EXIT, } impl ArmSyscalls { @@ -192,7 +201,7 @@ pub enum ArmVal { Reg(ArmRegister), Imm(i32), RegOffset(ArmRegister, i32), - LabelOffset(String, i32) + LabelOffset(String, i32), } impl Default for ArmVal { @@ -240,26 +249,38 @@ pub enum ArmInstruction { #[strum(serialize = "adrp")] Adrp { dest: ArmRegister, - label: ArmVal + label: ArmVal, }, /// B Branch R15 := address #[strum(serialize = "b")] - B { target: ArmVal }, + B { + target: ArmVal, + }, /// BLR Xn #[strum(serialize = "blr")] - Blr { target: ArmRegisterName }, + Blr { + target: ArmRegisterName, + }, /// BLE label #[strum(serialize = "ble")] - Ble { arg1: ArmRegister, arg2: ArmRegister, target: ArmVal }, + Ble { + arg1: ArmRegister, + arg2: ArmRegister, + target: ArmVal, + }, /// BL label #[strum(serialize = "bl")] - Bl {target: ArmVal}, + Bl { + target: ArmVal, + }, /// label: - Label { name: String }, + Label { + name: String, + }, /// .directive operands Directive { - name: String, - operands: String + name: String, + operands: String, }, #[strum(serialize = "ldr")] Ldr { @@ -271,7 +292,7 @@ pub enum ArmInstruction { Mov { width: ArmWidth, dest: ArmRegister, - src: ArmVal + src: ArmVal, }, #[strum(serialize = "ret")] Ret, @@ -291,21 +312,37 @@ pub enum ArmInstruction { }, /// sign extend to word #[strum(serialize = "sxtw")] - Sxtw { dest: ArmRegister, src: ArmRegister }, - /// service call + Sxtw { + dest: ArmRegister, + src: ArmRegister, + }, + /// service call #[strum(serialize = "svc")] - Svc { id: i32 }, + Svc { + id: i32, + }, /// compare - Cmp { op1: ArmRegister, op2: ArmVal }, - Verbatim { text: String }, + Cmp { + op1: ArmRegister, + op2: ArmVal, + }, + Verbatim { + text: String, + }, } impl Default for ArmInstruction { fn default() -> Self { ArmInstruction::Mov { - width: ArmWidth::Double, - dest: ArmRegister { width: ArmWidth::Double, name: ArmRegisterName::X0 }, - src: ArmVal::Reg(ArmRegister { width: ArmWidth::Double, name: ArmRegisterName::X0 }) + width: ArmWidth::Double, + dest: ArmRegister { + width: ArmWidth::Double, + name: ArmRegisterName::X0, + }, + src: ArmVal::Reg(ArmRegister { + width: ArmWidth::Double, + name: ArmRegisterName::X0, + }), } } } @@ -321,8 +358,8 @@ pub enum RiscVVal { }, LabelOffset { label: String, - offset: i32 - } + offset: i32, + }, } impl Default for RiscVVal { @@ -534,65 +571,59 @@ impl Into for ArmInstruction { ArmInstruction::Adc => todo!(), ArmInstruction::Add { dest, arg1, arg2 } => { format!("add {}, {}, {}", dest, arg1, arg2) - }, + } ArmInstruction::And => todo!(), ArmInstruction::Adrp { dest, label } => { format!("adrp {}, {}", dest, label) } ArmInstruction::B { target } => { format!("b {}", target) - }, + } ArmInstruction::Ble { arg1, arg2, target } => { format!("cmp {}, {}\nble {}", arg1, arg2, target) - }, + } ArmInstruction::Blr { target } => { format!("blr {}", Into::::into(target)) - }, - ArmInstruction::Ldr { width, dest, src } => { - match width { - ArmWidth::Word | ArmWidth::Double => format!("ldr {}, {}", dest, src), - _ => todo!() - } + } + ArmInstruction::Ldr { width, dest, src } => match width { + ArmWidth::Word | ArmWidth::Double => format!("ldr {}, {}", dest, src), + _ => todo!(), }, ArmInstruction::Mov { width, dest, src } => { format!("mov {}, {}", dest, src) - }, + } ArmInstruction::Ret => todo!(), - ArmInstruction::Str { width, src, dest } => { - match width { - ArmWidth::Word => format!("str {}, {}", src, dest), - ArmWidth::Double => format!("str {}, {}", src, dest), - _ => todo!("{:?}", width) - } + ArmInstruction::Str { width, src, dest } => match width { + ArmWidth::Word => format!("str {}, {}", src, dest), + ArmWidth::Double => format!("str {}, {}", src, dest), + _ => todo!("{:?}", width), }, - ArmInstruction::Sub { dest, arg1, arg2 } => - { + ArmInstruction::Sub { dest, arg1, arg2 } => { format!("sub {}, {}, {}", dest, arg1, arg2) - }, + } ArmInstruction::Sxtw { dest, src } => { format!("sxtw {}, {}", dest, src) - }, + } ArmInstruction::Bl { target } => { format!("bl {}", target) - }, + } ArmInstruction::Label { name } => { format!("{}:", name) - }, + } ArmInstruction::Directive { name, operands } => { format!(".{} {}", name, operands) } ArmInstruction::Svc { id } => { format!("svc {}", id) - }, + } ArmInstruction::Cmp { op1, op2 } => { format!("cmp {}, {}", op1, op2) } - ArmInstruction::Verbatim { text } => text + ArmInstruction::Verbatim { text } => text, } } } - impl Into for ArmRegister { fn into(self) -> String { let s: &str = match (self.name, self.width) { @@ -816,16 +847,16 @@ impl Display for ArmVal { ArmVal::RegOffset(arm_register, offset) => { let double_reg = ArmRegister { name: arm_register.name, - width: ArmWidth::Double + width: ArmWidth::Double, }; write!(f, "[{}, {}]", double_reg, offset) - }, + } ArmVal::LabelOffset(name, offset) => { match offset { 0 => write!(f, "{}", name), 9998 => write!(f, "{}", name), // %hi in riscv is adrp with no offset in arm 9999 => write!(f, ":lo12:{}", name), // reserved for 12 low bits of label addr - _ => write!(f, "[{}, {}]", name, offset) + _ => write!(f, "[{}, {}]", name, offset), } } } @@ -834,6 +865,9 @@ impl Display for ArmVal { impl Into for ArmRegisterName { fn into(self) -> ArmRegister { - ArmRegister { width: ArmWidth::Double, name: self } + ArmRegister { + width: ArmWidth::Double, + name: self, + } } } diff --git a/src/translate.rs b/src/translate.rs index cd62f02..f1d0a98 100644 --- a/src/translate.rs +++ b/src/translate.rs @@ -35,17 +35,17 @@ pub fn translate(riscv_instr: RiscVInstruction) -> Vec { arg2: ArmVal::Imm(imm.abs()), }] } - }, + } RiscVInstruction::Ble { arg1, arg2, target } => vec![{ let width = RiscVWidth::Double; ArmInstruction::Ble { arg1: map_register(arg1, &width), arg2: map_register(arg2, &width), - target: map_val(target, &width) + target: map_val(target, &width), } }], RiscVInstruction::J { target } => vec![ArmInstruction::B { - target: map_val(target, &RiscVWidth::Double) + target: map_val(target, &RiscVWidth::Double), }], RiscVInstruction::S { width, src, dest } => vec![ArmInstruction::Str { width: map_width(&width), @@ -59,7 +59,10 @@ pub fn translate(riscv_instr: RiscVInstruction) -> Vec { }], RiscVInstruction::Directive { name, operands } => { let arm_operands = operands.replace("@", "%"); - vec![ArmInstruction::Directive { name, operands: arm_operands }] + vec![ArmInstruction::Directive { + name, + operands: arm_operands, + }] } RiscVInstruction::Label { name } => vec![ArmInstruction::Label { name }], RiscVInstruction::Mv { dest, src } => { @@ -69,15 +72,15 @@ pub fn translate(riscv_instr: RiscVInstruction) -> Vec { arg1: map_register(src, &width), arg2: ArmVal::Imm(0), }] - }, - RiscVInstruction::Mvi { dest, imm } => { + } + RiscVInstruction::Mvi { dest, imm } => { let width = RiscVWidth::Double; vec![ArmInstruction::Mov { width: map_width(&width), dest: map_register(dest, &width), - src: ArmVal::Imm(imm) + src: ArmVal::Imm(imm), }] - }, + } RiscVInstruction::Add { width, dest, @@ -132,7 +135,7 @@ pub fn translate(riscv_instr: RiscVInstruction) -> Vec { // }, // arg2: ArmVal::Imm(imm), // } - }, + } RiscVInstruction::Addl { dest, src, label } => { let width = RiscVWidth::Double; vec![ArmInstruction::Add { @@ -140,7 +143,7 @@ pub fn translate(riscv_instr: RiscVInstruction) -> Vec { arg1: map_register(src, &width), arg2: map_val(label, &width), }] - }, + } RiscVInstruction::Lui { dest, src } => { // only used to load upper bits or adrp in arm let width = RiscVWidth::Double; @@ -148,7 +151,7 @@ pub fn translate(riscv_instr: RiscVInstruction) -> Vec { dest: map_register(dest, &width), label: map_val(src, &width), }] - }, + } RiscVInstruction::Call { label } => { let width = RiscVWidth::Double; vec![ArmInstruction::Bl { @@ -156,9 +159,9 @@ pub fn translate(riscv_instr: RiscVInstruction) -> Vec { }] } RiscVInstruction::ECall => { - let syscall_num_reg = ArmRegister{ + let syscall_num_reg = ArmRegister { width: ArmWidth::Double, - name: ArmRegisterName::X8 + name: ArmRegisterName::X8, }; vec![ // ArmInstruction::Cmp(syscall_num_reg, ArmVal::Imm(RISCV_WRITE)), // if (x8 == RISCV_WRITE) { @@ -169,10 +172,10 @@ pub fn translate(riscv_instr: RiscVInstruction) -> Vec { // ArmInstruction::Mov { width: ArmWidth::Double, dest: x8, src: ArmVal::Imm(__) }, // x8 = ARM_EXIT // // } // ArmInstruction::Label("done"), - ArmInstruction::Svc { id: 0 } + ArmInstruction::Svc { id: 0 }, ] } - RiscVInstruction::Verbatim { text } => vec![ArmInstruction::Verbatim { text }] + RiscVInstruction::Verbatim { text } => vec![ArmInstruction::Verbatim { text }], } } @@ -196,15 +199,15 @@ fn map_register_name(riscv_reg: RiscVRegister) -> ArmRegisterName { RiscVRegister::T1 => ArmRegisterName::X10, RiscVRegister::T2 => ArmRegisterName::X11, // skipped X5 -// RiscVRegister::S1 => ArmRegisterName::X6, -// RiscVRegister::A0 => ArmRegisterName::X0, -// RiscVRegister::A1 => ArmRegisterName::X1, -// RiscVRegister::A2 => ArmRegisterName::X2, -// RiscVRegister::A3 => ArmRegisterName::X3, -// RiscVRegister::A4 => ArmRegisterName::X4, -// RiscVRegister::A5 => ArmRegisterName::X5, -// RiscVRegister::A6 => ArmRegisterName::X6, -// RiscVRegister::A7 => ArmRegisterName::X7, + // RiscVRegister::S1 => ArmRegisterName::X6, + // RiscVRegister::A0 => ArmRegisterName::X0, + // RiscVRegister::A1 => ArmRegisterName::X1, + // RiscVRegister::A2 => ArmRegisterName::X2, + // RiscVRegister::A3 => ArmRegisterName::X3, + // RiscVRegister::A4 => ArmRegisterName::X4, + // RiscVRegister::A5 => ArmRegisterName::X5, + // RiscVRegister::A6 => ArmRegisterName::X6, + // RiscVRegister::A7 => ArmRegisterName::X7, RiscVRegister::S1 => ArmRegisterName::X13, RiscVRegister::A0 => ArmRegisterName::X0, // return value/syscall arg 0 RiscVRegister::A1 => ArmRegisterName::X1, // syscall arg 1 @@ -236,7 +239,9 @@ fn map_val(riscv_val: RiscVVal, riscv_width: &RiscVWidth) -> ArmVal { match riscv_val { RiscVVal::RiscVRegister(riscv_reg) => ArmVal::Reg(map_register(riscv_reg, riscv_width)), RiscVVal::Immediate(imm) => ArmVal::Imm(imm), - RiscVVal::Offset { register, offset } => ArmVal::RegOffset(map_register(register, riscv_width), offset), + RiscVVal::Offset { register, offset } => { + ArmVal::RegOffset(map_register(register, riscv_width), offset) + } RiscVVal::LabelOffset { label, offset } => ArmVal::LabelOffset(label, offset), } } @@ -254,7 +259,8 @@ fn map_width(riscv_width: &RiscVWidth) -> ArmWidth { pub fn translate_instrs(riscv_instrs: Vec) -> Vec { riscv_instrs .into_iter() - .map(translate).fold(vec![], |mut acc, x|{ + .map(translate) + .fold(vec![], |mut acc, x| { acc.extend(x); acc }) diff --git a/src/utils.rs b/src/utils.rs index e1fe8f8..a0c9f46 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -6,16 +6,19 @@ pub const START: &str = r#" .text .global _start +.global _main +.balign 4 _start: bl main mov x8, #93 svc #0 +.balign 4 +_main: main: "#; - pub fn translate_to_file(instrs: Vec, path: String) { let arm_instrs = translate_instrs(instrs); let mut contents = String::new(); @@ -25,4 +28,4 @@ pub fn translate_to_file(instrs: Vec, path: String) { contents.push_str("\n"); } fs::write(path, contents).expect("Unable to write file"); -} \ No newline at end of file +} diff --git a/test_binary_translate_add.S b/test_binary_translate_add.S index e18b534..391c523 100644 --- a/test_binary_translate_add.S +++ b/test_binary_translate_add.S @@ -2,13 +2,18 @@ .text .global _start +.global _main +.balign 4 _start: bl main mov x8, #93 svc #0 +.balign 4 +_main: main: + sub sp, sp, 32 str lr, [sp, 24] str x29, [sp, 16] diff --git a/tests/test_echo.rs b/tests/test_echo.rs index 46f37e1..33725b8 100644 --- a/tests/test_echo.rs +++ b/tests/test_echo.rs @@ -6,7 +6,7 @@ mod tests { use binary_room::utils::translate_to_file; use binary_room::utils::START; -const buf: &str = r#" + const buf: &str = r#" .buf: .string "hello world" "#; @@ -15,26 +15,59 @@ const buf: &str = r#" fn test_print_translate() { let riscv_asm: Vec = vec![ // RiscVInstruction::Verbatim { text: buf.to_string() }, - RiscVInstruction::Verbatim { text: START.to_string() }, + RiscVInstruction::Verbatim { + text: START.to_string(), + }, // read syscall - RiscVInstruction::Addi { dest: RiscVRegister::SP, src: RiscVRegister::SP, imm: -32 }, // sub stack pointer - RiscVInstruction::Li { dest: RiscVRegister::A7, imm: 63 }, // read syscall # - RiscVInstruction::Li { dest: RiscVRegister::A2, imm: 32 }, // read 5 bytes - RiscVInstruction::Mv { dest: RiscVRegister::A1, src: RiscVRegister::SP }, - RiscVInstruction::Li { dest: RiscVRegister::A0, imm: 0 }, + RiscVInstruction::Addi { + dest: RiscVRegister::SP, + src: RiscVRegister::SP, + imm: -32, + }, // sub stack pointer + RiscVInstruction::Li { + dest: RiscVRegister::A7, + imm: 63, + }, // read syscall # + RiscVInstruction::Li { + dest: RiscVRegister::A2, + imm: 32, + }, // read 5 bytes + RiscVInstruction::Mv { + dest: RiscVRegister::A1, + src: RiscVRegister::SP, + }, + RiscVInstruction::Li { + dest: RiscVRegister::A0, + imm: 0, + }, RiscVInstruction::ECall, // write syscall - RiscVInstruction::Li { dest: RiscVRegister::A7, imm: 64 }, - RiscVInstruction::Li { dest: RiscVRegister::A2, imm: 14 }, - RiscVInstruction::Mv { dest: RiscVRegister::A1, src: RiscVRegister::SP }, - RiscVInstruction::Li { dest: RiscVRegister::A0, imm: 1 }, + RiscVInstruction::Li { + dest: RiscVRegister::A7, + imm: 64, + }, + RiscVInstruction::Li { + dest: RiscVRegister::A2, + imm: 14, + }, + RiscVInstruction::Mv { + dest: RiscVRegister::A1, + src: RiscVRegister::SP, + }, + RiscVInstruction::Li { + dest: RiscVRegister::A0, + imm: 1, + }, RiscVInstruction::ECall, // exit syscall - RiscVInstruction::Li { dest: RiscVRegister::A7, imm: 93 }, + RiscVInstruction::Li { + dest: RiscVRegister::A7, + imm: 93, + }, // RiscVInstruction::Li { dest: RiscVRegister::A0, imm: 0 }, - RiscVInstruction::ECall + RiscVInstruction::ECall, ]; - translate_to_file(riscv_asm, "test_echo.S".to_string()); + translate_to_file(riscv_asm, "test_binary_translate_echo.S".to_string()); } } diff --git a/tests/test_print.rs b/tests/test_print.rs index e073b44..07840dc 100644 --- a/tests/test_print.rs +++ b/tests/test_print.rs @@ -6,7 +6,7 @@ mod tests { use binary_room::utils::translate_to_file; use binary_room::utils::START; -const buf: &str = r#" + const buf: &str = r#" .buf: .string "hello world\n" "#; @@ -14,28 +14,50 @@ const buf: &str = r#" #[test] fn test_print_translate() { let riscv_asm: Vec = vec![ - RiscVInstruction::Verbatim { text: buf.to_string() }, - RiscVInstruction::Verbatim { text: START.to_string() }, + RiscVInstruction::Verbatim { + text: buf.to_string(), + }, + RiscVInstruction::Verbatim { + text: START.to_string(), + }, // write syscall - RiscVInstruction::Li { dest: RiscVRegister::A7, imm: 64 }, - RiscVInstruction::Li { dest: RiscVRegister::A2, imm: 14 }, - RiscVInstruction::Lui { dest: RiscVRegister::A0, src: RiscVVal::LabelOffset { label: ".buf".to_string(), offset: 9998 } }, - RiscVInstruction::Addl { - dest: RiscVRegister::A1, + RiscVInstruction::Li { + dest: RiscVRegister::A7, + imm: 64, + }, + RiscVInstruction::Li { + dest: RiscVRegister::A2, + imm: 14, + }, + RiscVInstruction::Lui { + dest: RiscVRegister::A0, + src: RiscVVal::LabelOffset { + label: ".buf".to_string(), + offset: 9998, + }, + }, + RiscVInstruction::Addl { + dest: RiscVRegister::A1, src: RiscVRegister::A0, - label: RiscVVal::LabelOffset { - label: ".buf".to_string(), - offset: 9999 - } + label: RiscVVal::LabelOffset { + label: ".buf".to_string(), + offset: 9999, + }, + }, + RiscVInstruction::Li { + dest: RiscVRegister::A0, + imm: 1, }, - RiscVInstruction::Li { dest: RiscVRegister::A0, imm: 1 }, RiscVInstruction::ECall, // exit syscall - RiscVInstruction::Li { dest: RiscVRegister::A7, imm: 93 }, + RiscVInstruction::Li { + dest: RiscVRegister::A7, + imm: 93, + }, // RiscVInstruction::Li { dest: RiscVRegister::A0, imm: 0 }, - RiscVInstruction::ECall + RiscVInstruction::ECall, ]; - translate_to_file(riscv_asm, "test_print.S".to_string()); + translate_to_file(riscv_asm, "test_binary_translate_print.S".to_string()); } } diff --git a/tests/test_translation.rs b/tests/test_translation.rs index 6780d8c..dfc4251 100644 --- a/tests/test_translation.rs +++ b/tests/test_translation.rs @@ -9,6 +9,9 @@ mod tests { #[test] fn test_binary_translate() { let riscv_asm: Vec = vec![ + RiscVInstruction::Verbatim { + text: START.to_string(), + }, RiscVInstruction::Addi { dest: RiscVRegister::SP, src: RiscVRegister::SP, @@ -125,24 +128,28 @@ mod tests { #[test] fn test_syscall_translate() { let riscv_asm: Vec = vec![ - RiscVInstruction::Label { name: ".LC0".to_string() }, + RiscVInstruction::Label { + name: ".LC0".to_string(), + }, RiscVInstruction::Directive { name: "string".to_string(), - operands: "\"hello, world!\\n\"" .to_string() + operands: "\"hello, world!\\n\"".to_string(), }, RiscVInstruction::Directive { name: "align".to_string(), - operands: "2".to_string() + operands: "2".to_string(), }, RiscVInstruction::Directive { name: "global".to_string(), - operands: "main".to_string() + operands: "main".to_string(), }, RiscVInstruction::Directive { name: "type".to_string(), - operands: "main, @function".to_string() + operands: "main, @function".to_string(), + }, + RiscVInstruction::Label { + name: "main".to_string(), }, - RiscVInstruction::Label { name: "main".to_string() }, RiscVInstruction::Addi { dest: RiscVRegister::SP, src: RiscVRegister::SP, @@ -161,7 +168,7 @@ mod tests { src: RiscVRegister::S0FP, dest: RiscVVal::Offset { register: RiscVRegister::SP, - offset: 0 + offset: 0, }, }, RiscVInstruction::Addi { @@ -234,30 +241,141 @@ mod tests { #[test] fn test_loop() { let riscv_asm: Vec = vec![ - RiscVInstruction::Verbatim { text: START.to_string() }, - RiscVInstruction::Label { name: "main".to_string() }, - RiscVInstruction::Addi { dest: RiscVRegister::SP, src: RiscVRegister::SP, imm: -32 }, - RiscVInstruction::S { width: RiscVWidth::Double, src: RiscVRegister::S0FP, dest: RiscVVal::Offset { register: RiscVRegister::SP, offset: 24 } }, - RiscVInstruction::Addi { dest: RiscVRegister::S0FP, src: RiscVRegister::SP, imm: 32 }, - RiscVInstruction::S { width: RiscVWidth::Word, src: RiscVRegister::X0, dest: RiscVVal::Offset { register: RiscVRegister::S0FP, offset: -20 } }, - RiscVInstruction::J { target: RiscVVal::LabelOffset { label: ".L2".to_string(), offset: 0 }}, - RiscVInstruction::Label { name: ".L3".to_string() }, - RiscVInstruction::L { width: RiscVWidth::Word, dest: RiscVRegister::A5, src: RiscVVal::Offset { register:RiscVRegister::S0FP, offset: -24 } }, - RiscVInstruction::Addi { dest: RiscVRegister::A5, src: RiscVRegister::A5, imm: 1 }, - RiscVInstruction::S { width: RiscVWidth::Word, src: RiscVRegister::A5, dest: RiscVVal::Offset { register: RiscVRegister::S0FP, offset: -24 } }, - RiscVInstruction::L { width: RiscVWidth::Word, dest: RiscVRegister::A5, src: RiscVVal::Offset { register: RiscVRegister::S0FP, offset: -20 } }, - RiscVInstruction::Addi { dest: RiscVRegister::A5, src: RiscVRegister::A5, imm: 1 }, - RiscVInstruction::S { width: RiscVWidth::Word, src: RiscVRegister::A5, dest: RiscVVal::Offset { register: RiscVRegister::S0FP, offset: -20 } }, - RiscVInstruction::Label { name: ".L2".to_string() }, - RiscVInstruction::L { width: RiscVWidth::Word, dest: RiscVRegister::A5, src: RiscVVal::Offset { register:RiscVRegister::S0FP, offset: -20 } }, - RiscVInstruction::SextW { dest: RiscVRegister::A4, src: RiscVRegister::A5 }, - RiscVInstruction::Li { dest:RiscVRegister::A5, imm: 4 }, - RiscVInstruction::Ble { arg1: RiscVRegister::A4, arg2: RiscVRegister::A5, target: RiscVVal::LabelOffset { label: ".L3".to_string(), offset: 0 } }, - RiscVInstruction::L { width: RiscVWidth::Word, dest: RiscVRegister::A5, src: RiscVVal::Offset { register: RiscVRegister::S0FP, offset: -24 } }, - RiscVInstruction::Mv { dest: RiscVRegister::A0, src: RiscVRegister::A5 }, - RiscVInstruction::L { width: RiscVWidth::Double, dest: RiscVRegister::S0FP, src: RiscVVal::Offset { register: RiscVRegister::S0FP, offset: 24 } }, - RiscVInstruction::Addi { dest: RiscVRegister::SP, src: RiscVRegister::SP, imm: 32 }, - RiscVInstruction::Jr { target: RiscVRegister::RA }, + RiscVInstruction::Verbatim { + text: START.to_string(), + }, + RiscVInstruction::Addi { + dest: RiscVRegister::SP, + src: RiscVRegister::SP, + imm: -32, + }, + RiscVInstruction::S { + width: RiscVWidth::Double, + src: RiscVRegister::S0FP, + dest: RiscVVal::Offset { + register: RiscVRegister::SP, + offset: 24, + }, + }, + RiscVInstruction::Addi { + dest: RiscVRegister::S0FP, + src: RiscVRegister::SP, + imm: 32, + }, + RiscVInstruction::S { + width: RiscVWidth::Word, + src: RiscVRegister::X0, + dest: RiscVVal::Offset { + register: RiscVRegister::S0FP, + offset: -20, + }, + }, + RiscVInstruction::J { + target: RiscVVal::LabelOffset { + label: ".L2".to_string(), + offset: 0, + }, + }, + RiscVInstruction::Label { + name: ".L3".to_string(), + }, + RiscVInstruction::L { + width: RiscVWidth::Word, + dest: RiscVRegister::A5, + src: RiscVVal::Offset { + register: RiscVRegister::S0FP, + offset: -24, + }, + }, + RiscVInstruction::Addi { + dest: RiscVRegister::A5, + src: RiscVRegister::A5, + imm: 1, + }, + RiscVInstruction::S { + width: RiscVWidth::Word, + src: RiscVRegister::A5, + dest: RiscVVal::Offset { + register: RiscVRegister::S0FP, + offset: -24, + }, + }, + RiscVInstruction::L { + width: RiscVWidth::Word, + dest: RiscVRegister::A5, + src: RiscVVal::Offset { + register: RiscVRegister::S0FP, + offset: -20, + }, + }, + RiscVInstruction::Addi { + dest: RiscVRegister::A5, + src: RiscVRegister::A5, + imm: 1, + }, + RiscVInstruction::S { + width: RiscVWidth::Word, + src: RiscVRegister::A5, + dest: RiscVVal::Offset { + register: RiscVRegister::S0FP, + offset: -20, + }, + }, + RiscVInstruction::Label { + name: ".L2".to_string(), + }, + RiscVInstruction::L { + width: RiscVWidth::Word, + dest: RiscVRegister::A5, + src: RiscVVal::Offset { + register: RiscVRegister::S0FP, + offset: -20, + }, + }, + RiscVInstruction::SextW { + dest: RiscVRegister::A4, + src: RiscVRegister::A5, + }, + RiscVInstruction::Li { + dest: RiscVRegister::A5, + imm: 4, + }, + RiscVInstruction::Ble { + arg1: RiscVRegister::A4, + arg2: RiscVRegister::A5, + target: RiscVVal::LabelOffset { + label: ".L3".to_string(), + offset: 0, + }, + }, + RiscVInstruction::L { + width: RiscVWidth::Word, + dest: RiscVRegister::A5, + src: RiscVVal::Offset { + register: RiscVRegister::S0FP, + offset: -24, + }, + }, + RiscVInstruction::Mv { + dest: RiscVRegister::A0, + src: RiscVRegister::A5, + }, + RiscVInstruction::L { + width: RiscVWidth::Double, + dest: RiscVRegister::S0FP, + src: RiscVVal::Offset { + register: RiscVRegister::S0FP, + offset: 24, + }, + }, + RiscVInstruction::Addi { + dest: RiscVRegister::SP, + src: RiscVRegister::SP, + imm: 32, + }, + RiscVInstruction::Jr { + target: RiscVRegister::RA, + }, ]; translate_to_file(riscv_asm, "test_binary_translate_loop.S".to_string()); }