diff --git a/src/instruction.rs b/src/instruction.rs index d8cfa43..d099e2f 100644 --- a/src/instruction.rs +++ b/src/instruction.rs @@ -70,13 +70,50 @@ pub enum RiscVInstruction { arg1: RiscVRegister, arg2: RiscVRegister, }, + #[strum(serialize = "subw")] + Sub { + // dest = arg1 - arg2 + width: RiscVWidth, + dest: RiscVRegister, + arg1: RiscVRegister, + arg2: RiscVRegister, + }, /// branch if less than or equal - #[strum(serialize = "call")] + #[strum(serialize = "ble")] Ble { arg1: RiscVRegister, arg2: RiscVRegister, target: RiscVVal, }, + /// branch if greater than or equal + #[strum(serialize = "bge")] + Bge { + arg1: RiscVRegister, + arg2: RiscVRegister, + target: RiscVVal, + }, + /// branch if less than + #[strum(serialize = "blt")] + Blt { + arg1: RiscVRegister, + arg2: RiscVRegister, + target: RiscVVal, + }, + /// branch if greater than + #[strum(serialize = "bgt")] + Bgt { + arg1: RiscVRegister, + arg2: RiscVRegister, + target: RiscVVal, + }, + /// branch if greater than + #[strum(serialize = "bne")] + Bne { + arg1: RiscVRegister, + arg2: RiscVRegister, + target: RiscVVal, + }, + /// branch if greater than or equal to /// call label #[strum(serialize = "call")] Call { @@ -91,6 +128,13 @@ pub enum RiscVInstruction { src: RiscVRegister, dest: RiscVVal, }, + /// Rd := Rs << Imm + #[strum(serialize = "Slli")] + Slli { + dest: RiscVRegister, + src: RiscVRegister, + imm: i32 + }, /// Loads a value from memory into register rd for RV64I. /// /// `x[rd] = M[x[rs1] + sext(offset)]` @@ -268,6 +312,34 @@ pub enum ArmInstruction { arg2: ArmRegister, target: ArmVal, }, + /// BGE label + #[strum(serialize = "bge")] + Bge { + arg1: ArmRegister, + arg2: ArmRegister, + target: ArmVal, + }, + /// BLT label + #[strum(serialize = "blt")] + Blt { + arg1: ArmRegister, + arg2: ArmRegister, + target: ArmVal, + }, + /// BGT label + #[strum(serialize = "bgt")] + Bgt { + arg1: ArmRegister, + arg2: ArmRegister, + target: ArmVal, + }, + /// BNE label + #[strum(serialize = "bne")] + Bne { + arg1: ArmRegister, + arg2: ArmRegister, + target: ArmVal, + }, /// BL label #[strum(serialize = "bl")] Bl { @@ -296,6 +368,13 @@ pub enum ArmInstruction { }, #[strum(serialize = "ret")] Ret, + /// Rd := Rs << Imm + #[strum(serialize = "Lsl")] + Lsl { + dest: ArmRegister, + src: ArmRegister, + imm: i32 + }, /// Str [r2 + offset] = r1 #[strum(serialize = "str")] Str { @@ -579,9 +658,25 @@ impl Into for ArmInstruction { ArmInstruction::B { target } => { format!("b {}", target) } + // TODO: Fix these branching instructions need to map to + // multiple instructions. Would be better separation of concerns + // if this was produced by the translation function instead of a + // hack in the string formatting. ArmInstruction::Ble { arg1, arg2, target } => { format!("cmp {}, {}\nble {}", arg1, arg2, target) } + ArmInstruction::Bge { arg1, arg2, target } => { + format!("cmp {}, {}\nbge {}", arg1, arg2, target) + } + ArmInstruction::Blt { arg1, arg2, target } => { + format!("cmp {}, {}\nblt {}", arg1, arg2, target) + } + ArmInstruction::Bgt { arg1, arg2, target } => { + format!("cmp {}, {}\nbgt {}", arg1, arg2, target) + } + ArmInstruction::Bne { arg1, arg2, target } => { + format!("cmp {}, {}\nbne {}", arg1, arg2, target) + } ArmInstruction::Blr { target } => { format!("blr {}", Into::::into(target)) } @@ -598,6 +693,9 @@ impl Into for ArmInstruction { ArmWidth::Double => format!("str {}, {}", src, dest), _ => todo!("{:?}", width), }, + ArmInstruction::Lsl { dest, src, imm } => { + format!("lsl {}, {}, {}", dest, src, imm) + } ArmInstruction::Sub { dest, arg1, arg2 } => { format!("sub {}, {}, {}", dest, arg1, arg2) } diff --git a/src/translate.rs b/src/translate.rs index f1d0a98..0b49440 100644 --- a/src/translate.rs +++ b/src/translate.rs @@ -44,6 +44,38 @@ pub fn translate(riscv_instr: RiscVInstruction) -> Vec { target: map_val(target, &width), } }], + RiscVInstruction::Bge { arg1, arg2, target } => vec![{ + let width = RiscVWidth::Double; + ArmInstruction::Bge { + arg1: map_register(arg1, &width), + arg2: map_register(arg2, &width), + target: map_val(target, &width), + } + }], + RiscVInstruction::Blt { arg1, arg2, target } => vec![{ + let width = RiscVWidth::Double; + ArmInstruction::Blt { + arg1: map_register(arg1, &width), + arg2: map_register(arg2, &width), + target: map_val(target, &width), + } + }], + RiscVInstruction::Bgt { arg1, arg2, target } => vec![{ + let width = RiscVWidth::Double; + ArmInstruction::Bgt { + arg1: map_register(arg1, &width), + arg2: map_register(arg2, &width), + target: map_val(target, &width), + } + }], + RiscVInstruction::Bne { arg1, arg2, target } => vec![{ + let width = RiscVWidth::Double; + ArmInstruction::Bne { + arg1: map_register(arg1, &width), + arg2: map_register(arg2, &width), + target: map_val(target, &width), + } + }], RiscVInstruction::J { target } => vec![ArmInstruction::B { target: map_val(target, &RiscVWidth::Double), }], @@ -52,6 +84,14 @@ pub fn translate(riscv_instr: RiscVInstruction) -> Vec { src: map_register(src, &width), dest: map_val(dest, &width), }], + RiscVInstruction::Slli { dest, src, imm } => { + let width = RiscVWidth::Double; + vec![ArmInstruction::Lsl { + dest: map_register(dest, &width), + src: map_register(src, &width), + imm: imm + }] + }, RiscVInstruction::L { width, dest, src } => vec![ArmInstruction::Ldr { width: map_width(&width), dest: map_register(dest, &width), @@ -101,7 +141,55 @@ pub fn translate(riscv_instr: RiscVInstruction) -> Vec { name: map_register_name(arg2), }), }], - RiscVWidth::Double => sorry!(), + RiscVWidth::Double => vec![ArmInstruction::Add { + dest: ArmRegister { + width: ArmWidth::Double, + name: map_register_name(dest), + }, + arg1: ArmRegister { + width: ArmWidth::Double, + name: map_register_name(arg1), + }, + arg2: ArmVal::Reg(ArmRegister { + width: ArmWidth::Double, + name: map_register_name(arg2), + }), + }], + }, + RiscVInstruction::Sub { + width, + dest, + arg1, + arg2, + } => match width { + RiscVWidth::Word => vec![ArmInstruction::Sub { + dest: ArmRegister { + width: ArmWidth::Word, + name: map_register_name(dest), + }, + arg1: ArmRegister { + width: ArmWidth::Word, + name: map_register_name(arg1), + }, + arg2: ArmVal::Reg(ArmRegister { + width: ArmWidth::Word, + name: map_register_name(arg2), + }), + }], + RiscVWidth::Double => vec![ArmInstruction::Sub { + dest: ArmRegister { + width: ArmWidth::Double, + name: map_register_name(dest), + }, + arg1: ArmRegister { + width: ArmWidth::Double, + name: map_register_name(arg1), + }, + arg2: ArmVal::Reg(ArmRegister { + width: ArmWidth::Double, + name: map_register_name(arg2), + }), + }], }, RiscVInstruction::SextW { dest, src } => vec![ArmInstruction::Sxtw { dest: ArmRegister { diff --git a/src/utils.rs b/src/utils.rs index eb35249..9e034b1 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -19,6 +19,27 @@ _main: main: "#; +pub const START_NO_MAIN: &str = r#" +.text + +.global _start +.global _main + +.balign 4 +_start: +bl main +mov x8, #93 +svc #0 +"#; + +/// Assembler directives for main only, used when another +/// function defined before main +pub const START_MAIN: &str = r#" +.balign 4 +_main: +main: +"#; + pub fn translate_to_file(instrs: Vec, path: String) { let arm_instrs = translate_instrs(instrs); let mut contents = String::new(); diff --git a/tests/fib/fib.arm.s b/tests/fib/fib.arm.s new file mode 100644 index 0000000..7d7d84c --- /dev/null +++ b/tests/fib/fib.arm.s @@ -0,0 +1,65 @@ + +.text + +.global _start +.global _main + +.balign 4 +_start: +bl main +mov x8, #93 +svc #0 + +.balign 4 +_main: +main: + +sub sp, sp, 64 +str x29, [sp, 56] +add x29, sp, 64 +str xzr, [x29, -64] +str xzr, [x29, -56] +str xzr, [x29, -48] +str xzr, [x29, -40] +str xzr, [x29, -32] +mov x5, 1 +str w5, [x29, -60] +mov x5, 2 +str w5, [x29, -20] +b .L2 +.L3: +ldr w5, [x29, -20] +sub x5, x5, 1 +sxtw x5, w5 +lsl x5, x5, 2 +sub x5, x5, 16 +add x5, x5, x29 +ldr x4, [x5, -48] +ldr x5, [x29, -20] +sub x5, x5, 2 +sxtw x5, w5 +lsl x5, x5, 2 +sub x5, x5, 16 +add x5, x5, x29 +ldr x5, [x5, -48] +add x5, x4, x5 +sxtw x4, w5 +ldr x5, [x29, -20] +lsl x5, x5, 2 +sub x5, x5, 16 +add x5, x5, x29 +str x4, [x5, -48] +ldr x5, [x29, -20] +add x5, x5, 1 +str w5, [x29, -20] +.L2: +ldr x5, [x29, -20] +sxtw x4, w5 +mov x5, 9 +cmp x4, x5 +ble .L3 +ldr w5, [x29, -28] +add x0, x5, 0 +ldr x29, [sp, 56] +add sp, sp, 64 +blr lr diff --git a/tests/fib/fib.riscv.s b/tests/fib/fib.riscv.s new file mode 100644 index 0000000..0d2561a --- /dev/null +++ b/tests/fib/fib.riscv.s @@ -0,0 +1,59 @@ +# int main() { +# int i; +# int a[10] = {}; +# a[1] = 1; +# for (i = 2; i < 10; i++) { +# a[i] = a[i-1] + a[i-2]; +# } +# return a[9]; +# } + +main: +addi sp,sp,-64 +sd s0,56(sp) +addi s0,sp,64 +sd zero,-64(s0) +sd zero,-56(s0) +sd zero,-48(s0) +sd zero,-40(s0) +sd zero,-32(s0) +li a5,1 +sw a5,-60(s0) +li a5,2 +sw a5,-20(s0) +j .L2 +.L3: +lw a5,-20(s0) +addiw a5,a5,-1 +sext.w a5,a5 +slli a5,a5,2 +addi a5,a5,-16 +add a5,a5,s0 +lw a4,-48(a5) +lw a5,-20(s0) +addiw a5,a5,-2 +sext.w a5,a5 +slli a5,a5,2 +addi a5,a5,-16 +add a5,a5,s0 +lw a5,-48(a5) +addw a5,a4,a5 +sext.w a4,a5 +lw a5,-20(s0) +slli a5,a5,2 +addi a5,a5,-16 +add a5,a5,s0 +sw a4,-48(a5) +lw a5,-20(s0) +addiw a5,a5,1 +sw a5,-20(s0) +.L2: +lw a5,-20(s0) +sext.w a4,a5 +li a5,9 +ble a4,a5,.L3 +lw a5,-28(s0) +mv a0,a5 +ld s0,56(sp) +addi sp,sp,64 +jr ra \ No newline at end of file diff --git a/tests/fib/test_fib.rs b/tests/fib/test_fib.rs new file mode 100644 index 0000000..bd1465d --- /dev/null +++ b/tests/fib/test_fib.rs @@ -0,0 +1,308 @@ +#[cfg(test)] +mod tests { + use binary_room::instruction::*; + use binary_room::utils::translate_to_file; + use binary_room::utils::START; + + #[test] + fn test_binary_translate() { + let riscv_asm: Vec = vec![ + RiscVInstruction::Verbatim { + text: START.to_string(), + }, + RiscVInstruction::Addi { + dest: RiscVRegister::SP, + src: RiscVRegister::SP, + imm: -64, + }, + RiscVInstruction::S { + width: RiscVWidth::Double, + src: RiscVRegister::S0FP, + dest: RiscVVal::Offset { + register: RiscVRegister::SP, + offset: 56, + }, + }, + RiscVInstruction::Addi { + dest: RiscVRegister::S0FP, + src: RiscVRegister::SP, + imm: 64, + }, + RiscVInstruction::S { + width: RiscVWidth::Double, + src: RiscVRegister::X0, + dest: RiscVVal::Offset { + register: RiscVRegister::S0FP, + offset: -64, + }, + }, + RiscVInstruction::S { + width: RiscVWidth::Double, + src: RiscVRegister::X0, + dest: RiscVVal::Offset { + register: RiscVRegister::S0FP, + offset: -56, + }, + }, + RiscVInstruction::S { + width: RiscVWidth::Double, + src: RiscVRegister::X0, + dest: RiscVVal::Offset { + register: RiscVRegister::S0FP, + offset: -48, + }, + }, + RiscVInstruction::S { + width: RiscVWidth::Double, + src: RiscVRegister::X0, + dest: RiscVVal::Offset { + register: RiscVRegister::S0FP, + offset: -40, + }, + }, + RiscVInstruction::S { + width: RiscVWidth::Double, + src: RiscVRegister::X0, + dest: RiscVVal::Offset { + register: RiscVRegister::S0FP, + offset: -32, + }, + }, + RiscVInstruction::Li { + dest: RiscVRegister::A5, + imm: 1, + }, + RiscVInstruction::S { + width: RiscVWidth::Word, + src: RiscVRegister::A5, + dest: RiscVVal::Offset { + register: RiscVRegister::S0FP, + offset: -60, + }, + }, + RiscVInstruction::Li { + dest: RiscVRegister::A5, + imm: 2, + }, + RiscVInstruction::S { + width: RiscVWidth::Word, + src: RiscVRegister::A5, + 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: -20, + }, + }, + RiscVInstruction::Addi { + dest: RiscVRegister::A5, + src: RiscVRegister::A5, + imm: -1, + }, + RiscVInstruction::SextW { + dest: RiscVRegister::A5, + src: RiscVRegister::A5, + }, + RiscVInstruction::Slli { + dest: RiscVRegister::A5, + src: RiscVRegister::A5, + imm: 2, + }, + RiscVInstruction::Addi { + dest: RiscVRegister::A5, + src: RiscVRegister::A5, + imm: -16, + }, + RiscVInstruction::Add { + width: RiscVWidth::Double, + dest: RiscVRegister::A5, + arg1: RiscVRegister::A5, + arg2: RiscVRegister::S0FP, + }, + RiscVInstruction::L { + width: RiscVWidth::Double, + dest: RiscVRegister::A4, + src: RiscVVal::Offset { + register: RiscVRegister::A5, + offset: -48, + }, + }, + RiscVInstruction::L { + width: RiscVWidth::Double, + dest: RiscVRegister::A5, + src: RiscVVal::Offset { + register: RiscVRegister::S0FP, + offset: -20, + }, + }, + RiscVInstruction::Addi { + dest: RiscVRegister::A5, + src: RiscVRegister::A5, + imm: -2, + }, + RiscVInstruction::SextW { + dest: RiscVRegister::A5, + src: RiscVRegister::A5, + }, + RiscVInstruction::Slli { + dest: RiscVRegister::A5, + src: RiscVRegister::A5, + imm: 2, + }, + RiscVInstruction::Addi { + dest: RiscVRegister::A5, + src: RiscVRegister::A5, + imm: -16, + }, + RiscVInstruction::Add { + width: RiscVWidth::Double, + dest: RiscVRegister::A5, + arg1: RiscVRegister::A5, + arg2: RiscVRegister::S0FP, + }, + RiscVInstruction::L { + width: RiscVWidth::Double, + dest: RiscVRegister::A5, + src: RiscVVal::Offset { + register: RiscVRegister::A5, + offset: -48, + }, + }, + RiscVInstruction::Add { + width: RiscVWidth::Double, + dest: RiscVRegister::A5, + arg1: RiscVRegister::A4, + arg2: RiscVRegister::A5, + }, + RiscVInstruction::SextW { + dest: RiscVRegister::A4, + src: RiscVRegister::A5, + }, + RiscVInstruction::L { + width: RiscVWidth::Double, + dest: RiscVRegister::A5, + src: RiscVVal::Offset { + register: RiscVRegister::S0FP, + offset: -20, + }, + }, + RiscVInstruction::Slli { + dest: RiscVRegister::A5, + src: RiscVRegister::A5, + imm: 2, + }, + RiscVInstruction::Addi { + dest: RiscVRegister::A5, + src: RiscVRegister::A5, + imm: -16, + }, + RiscVInstruction::Add { + width: RiscVWidth::Double, + dest: RiscVRegister::A5, + arg1: RiscVRegister::A5, + arg2: RiscVRegister::S0FP, + }, + RiscVInstruction::S { + width: RiscVWidth::Double, + src: RiscVRegister::A4, + dest: RiscVVal::Offset { + register: RiscVRegister::A5, + offset: -48, + }, + }, + RiscVInstruction::L { + width: RiscVWidth::Double, + 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::Double, + 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: 9, + }, + 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: -28, + }, + }, + RiscVInstruction::Mv { + dest: RiscVRegister::A0, + src: RiscVRegister::A5, + }, + RiscVInstruction::L { + width: RiscVWidth::Double, + dest: RiscVRegister::S0FP, + src: RiscVVal::Offset { + register: RiscVRegister::SP, + offset: 56, + }, + }, + RiscVInstruction::Addi { + dest: RiscVRegister::SP, + src: RiscVRegister::SP, + imm: 64, + }, + RiscVInstruction::Jr { + target: RiscVRegister::RA, + }, + ]; + + translate_to_file(riscv_asm, "./tests/fib/fib.arm.s".to_string()); + } +} diff --git a/tests/prime/prime.arm.s b/tests/prime/prime.arm.s new file mode 100644 index 0000000..1e5fcff --- /dev/null +++ b/tests/prime/prime.arm.s @@ -0,0 +1,91 @@ + +.text + +.global _start +.global _main + +.balign 4 +_start: +bl main +mov x8, #93 +svc #0 + +is_prime: +sub sp, sp, 48 +str x29, [sp, 40] +add x29, sp, 48 +add x5, x0, 0 +str w5, [x29, -36] +ldr w5, [x29, -36] +sxtw x4, w5 +mov x5, 1 +cmp x4, x5 +bgt .L2 +mov x5, 0 +b .L3 +.L2: +mov x5, 2 +str w5, [x29, -20] +b .L4 +.L8: +ldr w5, [x29, -36] +add x4, x5, 0 +ldr w5, [x29, -20] +sub w5, w4, w5 +str w5, [x29, -24] +b .L5 +.L6: +ldr w5, [x29, -24] +add x4, x5, 0 +ldr w5, [x29, -20] +sub w5, w4, w5 +str w5, [x29, -24] +.L5: +ldr w5, [x29, -24] +add x4, x5, 0 +ldr w5, [x29, -20] +sxtw x4, w4 +sxtw x5, w5 +cmp x4, x5 +bge .L6 +ldr w5, [x29, -24] +sxtw x5, w5 +cmp x5, xzr +bne .L7 +mov x5, 0 +b .L3 +.L7: +ldr w5, [x29, -20] +add x5, x5, 1 +str x5, [x29, -20] +.L4: +ldr w5, [x29, -20] +add x4, x5, 0 +ldr w5, [x29, -36] +sxtw x4, w4 +sxtw x5, w5 +cmp x4, x5 +blt .L8 +mov x5, 1 +.L3: +add x0, x5, 0 +ldr x29, [sp, 40] +add sp, sp, 48 +blr lr + +.balign 4 +_main: +main: + +sub sp, sp, 16 +str lr, [sp, 8] +str x29, [sp, 0] +add x29, sp, 16 +mov x0, 4093 +bl is_prime +add x5, x0, 0 +add x0, x5, 0 +ldr lr, [sp, 8] +ldr x29, [sp, 16] +add sp, sp, 16 +blr lr diff --git a/tests/prime/prime.riscv.s b/tests/prime/prime.riscv.s new file mode 100644 index 0000000..04128fe --- /dev/null +++ b/tests/prime/prime.riscv.s @@ -0,0 +1,92 @@ +# int is_prime(int n) { +# if (n <= 1) { +# return 0; +# } +# for (int i = 2; i < n; i++) { +# int temp = n - i; +# while (temp >= i) { +# temp = temp - i; +# } +# if (temp == 0) { +# // i divides n +# return 0; +# } +# } +# return 1; +# } +# int main(void) { +# return is_prime(4093); +# } + +is_prime: # is_prime(int): +addi sp,sp,-48 +sd s0,40(sp) +addi s0,sp,48 +mv a5,a0 +sw a5,-36(s0) +lw a5,-36(s0) +sext.w a4,a5 +li a5,1 +bgt a4,a5,.L2 +li a5,0 +j .L3 +.L2: +li a5,2 +sw a5,-20(s0) +j .L4 +.L8: +lw a5,-36(s0) +mv a4,a5 +lw a5,-20(s0) +subw a5,a4,a5 +sw a5,-24(s0) +j .L5 +.L6: +lw a5,-24(s0) +mv a4,a5 +lw a5,-20(s0) +subw a5,a4,a5 +sw a5,-24(s0) +.L5: +lw a5,-24(s0) +mv a4,a5 +lw a5,-20(s0) +sext.w a4,a4 +sext.w a5,a5 +bge a4,a5,.L6 +lw a5,-24(s0) +sext.w a5,a5 +bne a5,zero,.L7 +li a5,0 +j .L3 +.L7: +lw a5,-20(s0) +addiw a5,a5,1 +sw a5,-20(s0) +.L4: +lw a5,-20(s0) +mv a4,a5 +lw a5,-36(s0) +sext.w a4,a4 +sext.w a5,a5 +blt a4,a5,.L8 +li a5,1 +.L3: +mv a0,a5 +ld s0,40(sp) +addi sp,sp,48 +jr ra +main: +addi sp,sp,-16 +sd ra,8(sp) +sd s0,0(sp) +addi s0,sp,16 +li a0,4093 +call is_prime +mv a5,a0 +nop +mv a0,a5 +ld ra,8(sp) +ld s0,0(sp) +addi sp,sp,16 +jr ra diff --git a/tests/prime/test_prime.rs b/tests/prime/test_prime.rs new file mode 100644 index 0000000..488875d --- /dev/null +++ b/tests/prime/test_prime.rs @@ -0,0 +1,417 @@ +#[cfg(test)] +mod tests { + use binary_room::instruction::*; + use binary_room::utils::translate_to_file; + use binary_room::utils::START_MAIN; + use binary_room::utils::START_NO_MAIN; + const N: i32 = 4093; + + #[test] + fn test_binary_translate() { + let riscv_asm: Vec = vec![ + RiscVInstruction::Verbatim { + text: START_NO_MAIN.to_string(), + }, + RiscVInstruction::Label { + name: "is_prime".to_string(), + }, + RiscVInstruction::Addi { + dest: RiscVRegister::SP, + src: RiscVRegister::SP, + imm: -48, + }, + RiscVInstruction::S { + width: RiscVWidth::Double, + src: RiscVRegister::S0FP, + dest: RiscVVal::Offset { + register: RiscVRegister::SP, + offset: 40, + }, + }, + RiscVInstruction::Addi { + dest: RiscVRegister::S0FP, + src: RiscVRegister::SP, + imm: 48, + }, + RiscVInstruction::Mv { + dest: RiscVRegister::A5, + src: RiscVRegister::A0, + }, + RiscVInstruction::S { + width: RiscVWidth::Word, + src: RiscVRegister::A5, + dest: RiscVVal::Offset { + register: RiscVRegister::S0FP, + offset: -36, + }, + }, + RiscVInstruction::L { + width: RiscVWidth::Word, + dest: RiscVRegister::A5, + src: RiscVVal::Offset { + register: RiscVRegister::S0FP, + offset: -36, + }, + }, + RiscVInstruction::SextW { + dest: RiscVRegister::A4, + src: RiscVRegister::A5, + }, + RiscVInstruction::Li { + dest: RiscVRegister::A5, + imm: 1, + }, + RiscVInstruction::Bgt { + arg1: RiscVRegister::A4, + arg2: RiscVRegister::A5, + target: RiscVVal::LabelOffset { + label: ".L2".to_string(), + offset: 0, + }, + }, + RiscVInstruction::Li { + dest: RiscVRegister::A5, + imm: 0, + }, + RiscVInstruction::J { + target: RiscVVal::LabelOffset { + label: ".L3".to_string(), + offset: 0, + }, + }, + RiscVInstruction::Label { + name: ".L2".to_string(), + }, + RiscVInstruction::Li { + dest: RiscVRegister::A5, + imm: 2, + }, + RiscVInstruction::S { + width: RiscVWidth::Word, + src: RiscVRegister::A5, + dest: RiscVVal::Offset { + register: RiscVRegister::S0FP, + offset: -20, + }, + }, + RiscVInstruction::J { + target: RiscVVal::LabelOffset { + label: ".L4".to_string(), + offset: 0, + }, + }, + RiscVInstruction::Label { + name: ".L8".to_string(), + }, + RiscVInstruction::L { + width: RiscVWidth::Word, + dest: RiscVRegister::A5, + src: RiscVVal::Offset { + register: RiscVRegister::S0FP, + offset: -36, + }, + }, + RiscVInstruction::Mv { + dest: RiscVRegister::A4, + src: RiscVRegister::A5, + }, + RiscVInstruction::L { + width: RiscVWidth::Word, + dest: RiscVRegister::A5, + src: RiscVVal::Offset { + register: RiscVRegister::S0FP, + offset: -20, + }, + }, + RiscVInstruction::Sub { + width: RiscVWidth::Word, + dest: RiscVRegister::A5, + arg1: RiscVRegister::A4, + arg2: RiscVRegister::A5, + }, + RiscVInstruction::S { + width: RiscVWidth::Word, + src: RiscVRegister::A5, + dest: RiscVVal::Offset { + register: RiscVRegister::S0FP, + offset: -24, + }, + }, + RiscVInstruction::J { + target: RiscVVal::LabelOffset { + label: ".L5".to_string(), + offset: 0, + }, + }, + RiscVInstruction::Label { + name: ".L6".to_string(), + }, + RiscVInstruction::L { + width: RiscVWidth::Word, + dest: RiscVRegister::A5, + src: RiscVVal::Offset { + register: RiscVRegister::S0FP, + offset: -24, + }, + }, + RiscVInstruction::Mv { + dest: RiscVRegister::A4, + src: RiscVRegister::A5, + }, + RiscVInstruction::L { + width: RiscVWidth::Word, + dest: RiscVRegister::A5, + src: RiscVVal::Offset { + register: RiscVRegister::S0FP, + offset: -20, + }, + }, + RiscVInstruction::Sub { + width: RiscVWidth::Word, + dest: RiscVRegister::A5, + arg1: RiscVRegister::A4, + arg2: RiscVRegister::A5, + }, + RiscVInstruction::S { + width: RiscVWidth::Word, + src: RiscVRegister::A5, + dest: RiscVVal::Offset { + register: RiscVRegister::S0FP, + offset: -24, + }, + }, + RiscVInstruction::Label { + name: ".L5".to_string(), + }, + RiscVInstruction::L { + width: RiscVWidth::Word, + dest: RiscVRegister::A5, + src: RiscVVal::Offset { + register: RiscVRegister::S0FP, + offset: -24, + }, + }, + RiscVInstruction::Mv { + dest: RiscVRegister::A4, + src: RiscVRegister::A5, + }, + RiscVInstruction::L { + width: RiscVWidth::Word, + dest: RiscVRegister::A5, + src: RiscVVal::Offset { + register: RiscVRegister::S0FP, + offset: -20, + }, + }, + RiscVInstruction::SextW { + dest: RiscVRegister::A4, + src: RiscVRegister::A4, + }, + RiscVInstruction::SextW { + dest: RiscVRegister::A5, + src: RiscVRegister::A5, + }, + RiscVInstruction::Bge { + arg1: RiscVRegister::A4, + arg2: RiscVRegister::A5, + target: RiscVVal::LabelOffset { + label: ".L6".to_string(), + offset: 0, + }, + }, + RiscVInstruction::L { + width: RiscVWidth::Word, + dest: RiscVRegister::A5, + src: RiscVVal::Offset { + register: RiscVRegister::S0FP, + offset: -24, + }, + }, + RiscVInstruction::SextW { + dest: RiscVRegister::A5, + src: RiscVRegister::A5, + }, + RiscVInstruction::Bne { + arg1: RiscVRegister::A5, + arg2: RiscVRegister::X0, + target: RiscVVal::LabelOffset { + label: ".L7".to_string(), + offset: 0, + }, + }, + RiscVInstruction::Li { + dest: RiscVRegister::A5, + imm: 0, + }, + RiscVInstruction::J { + target: RiscVVal::LabelOffset { + label: ".L3".to_string(), + offset: 0, + }, + }, + RiscVInstruction::Label { + name: ".L7".to_string(), + }, + 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::Double, + src: RiscVRegister::A5, + dest: RiscVVal::Offset { + register: RiscVRegister::S0FP, + offset: -20, + }, + }, + RiscVInstruction::Label { + name: ".L4".to_string(), + }, + RiscVInstruction::L { + width: RiscVWidth::Word, + dest: RiscVRegister::A5, + src: RiscVVal::Offset { + register: RiscVRegister::S0FP, + offset: -20, + }, + }, + RiscVInstruction::Mv { + dest: RiscVRegister::A4, + src: RiscVRegister::A5, + }, + RiscVInstruction::L { + width: RiscVWidth::Word, + dest: RiscVRegister::A5, + src: RiscVVal::Offset { + register: RiscVRegister::S0FP, + offset: -36, + }, + }, + RiscVInstruction::SextW { + dest: RiscVRegister::A4, + src: RiscVRegister::A4, + }, + RiscVInstruction::SextW { + dest: RiscVRegister::A5, + src: RiscVRegister::A5, + }, + RiscVInstruction::Blt { + arg1: RiscVRegister::A4, + arg2: RiscVRegister::A5, + target: RiscVVal::LabelOffset { + label: ".L8".to_string(), + offset: 0, + }, + }, + RiscVInstruction::Li { + dest: RiscVRegister::A5, + imm: 1, + }, + RiscVInstruction::Label { + name: ".L3".to_string(), + }, + RiscVInstruction::Mv { + dest: RiscVRegister::A0, + src: RiscVRegister::A5, + }, + RiscVInstruction::L { + width: RiscVWidth::Double, + dest: RiscVRegister::S0FP, + src: RiscVVal::Offset { + register: RiscVRegister::SP, + offset: 40, + }, + }, + RiscVInstruction::Addi { + dest: RiscVRegister::SP, + src: RiscVRegister::SP, + imm: 48, + }, + RiscVInstruction::Jr { + target: RiscVRegister::RA, + }, + RiscVInstruction::Verbatim { + text: START_MAIN.to_string(), + }, + RiscVInstruction::Addi { + dest: RiscVRegister::SP, + src: RiscVRegister::SP, + imm: -16, + }, + RiscVInstruction::S { + width: RiscVWidth::Double, + src: RiscVRegister::RA, + dest: RiscVVal::Offset { + register: RiscVRegister::SP, + offset: 8, + }, + }, + RiscVInstruction::S { + width: RiscVWidth::Double, + src: RiscVRegister::S0FP, + dest: RiscVVal::Offset { + register: RiscVRegister::SP, + offset: 0, + }, + }, + RiscVInstruction::Addi { + dest: RiscVRegister::S0FP, + src: RiscVRegister::SP, + imm: 16, + }, + RiscVInstruction::Li { + dest: RiscVRegister::A0, + imm: N, + }, + RiscVInstruction::Call { + label: RiscVVal::LabelOffset { + label: "is_prime".to_string(), + offset: 0, + }, + }, + RiscVInstruction::Mv { + dest: RiscVRegister::A5, + src: RiscVRegister::A0, + }, + RiscVInstruction::Mv { + dest: RiscVRegister::A0, + src: RiscVRegister::A5, + }, + RiscVInstruction::L { + width: RiscVWidth::Double, + dest: RiscVRegister::RA, + src: RiscVVal::Offset { + register: RiscVRegister::SP, + offset: 8, + }, + }, + RiscVInstruction::L { + width: RiscVWidth::Double, + dest: RiscVRegister::S0FP, + src: RiscVVal::Offset { + register: RiscVRegister::SP, + offset: 16, + }, + }, + RiscVInstruction::Addi { + dest: RiscVRegister::SP, + src: RiscVRegister::SP, + imm: 16, + }, + RiscVInstruction::Jr { + target: RiscVRegister::RA, + }, + ]; + + translate_to_file(riscv_asm, "./tests/prime/prime.arm.s".to_string()); + } +} diff --git a/tests/tests.rs b/tests/tests.rs index 3bfde3f..5c9591f 100644 --- a/tests/tests.rs +++ b/tests/tests.rs @@ -6,3 +6,9 @@ mod echo; #[path = "print/test_print.rs"] mod print; + +#[path = "fib/test_fib.rs"] +mod fib; + +#[path = "prime/test_prime.rs"] +mod prime; \ No newline at end of file