MinCamlの配列を生成するRISC-Vコードを出力
配列のテストコード。
code:test/array_test.ml
let a = Array.make 3 5 in
let _ = a.(0) <- 4649 in
let _ = a.(1) <- 5963 in
let _ = a.(2) <- 246911 in
let p = 3.14 in
let b = (Array.make 4 1.23) in
let _ = print_float b.(0); print_newline () in
let _ = print_float b.(1); print_newline () in
let _ = print_float b.(2); print_newline () in
let _ = print_float b.(3); print_newline () in
let _ = b.(0) <- p in
let _ = b.(1) <- p *. p in
let _ = b.(2) <- p *. p *. p in
let _ = b.(3) <- p *. p *. p *. p in
(* print int array *)
print_int a.(0); (* => 4649 *)
print_newline ();
print_int a.(1); (* => 5963 *)
print_newline ();
print_int a.(2); (* => 249611 *)
print_newline ();
(* print float array *)
print_float b.(0); (* => 3.14 *)
print_newline ();
print_float b.(1); (* => 9.859600 *)
print_newline ();
print_float b.(2); (* => 30.959144 *)
print_newline ();
print_float b.(3); (* => 97.21171216 *)
print_newline ()
配列を扱えるようにしたコード。
code:diff
diff --git a/RV32/emit.ml b/RV32/emit.ml
index 096588a..5417f6f 100644
--- a/RV32/emit.ml
+++ b/RV32/emit.ml
@@ -62,11 +62,7 @@ and g' oc = function (* 各命令のアセンブリ生成 (caml2html: emit_gprim
| NonTail(_), Nop -> ()
| NonTail(x), Li(i) when -32768 <= i && i < 32768 -> Printf.fprintf oc "\tli\t%s, %d\n" (reg x) i
| NonTail(x), Li(i) ->
- let n = i lsr 12 in
- let m = i lxor (n lsl 12) in
- let r = reg x in
- Printf.fprintf oc "\tlui %s, %d\n" r n;
- Printf.fprintf oc "\taddi %s, %s, %d\n" r r m
+ Printf.fprintf oc "\tli %s, %d\n" (reg x) i
| NonTail(x), FLi(Id.L(l)) ->
Printf.fprintf oc "\tlui %s, %%hi(%s)\n" (reg reg_tmp) l;
Printf.fprintf oc "\tflw %s, %%lo(%s)(%s)\n" (reg x) l (reg reg_tmp)
@@ -81,7 +77,7 @@ and g' oc = function (* 各命令のアセンブリ生成 (caml2html: emit_gprim
| NonTail(x), Sub(y, V(z)) -> Printf.fprintf oc "\tsub\t%s, %s, %s\n" (reg x) (reg y) (reg z)
| NonTail(x), Sub(y, C(z)) -> Printf.fprintf oc "\taddi %s, %s, %d\n" (reg x) (reg y) ((-1) * z)
| NonTail(x), Slw(y, V(z)) -> Printf.fprintf oc "\tslw\t%s, %s, %s\n" (reg x) (reg y) (reg z)
- | NonTail(x), Slw(y, C(z)) -> Printf.fprintf oc "\tslwi\t%s, %s, %d\n" (reg x) (reg y) z
+ | NonTail(x), Slw(y, C(z)) -> Printf.fprintf oc "\tslli %s, %s, %d\n" (reg x) (reg y) z
| NonTail(x), Lwz(y, V(z)) -> Printf.fprintf oc "\tlwzx\t%s, %s, %s\n" (reg x) (reg y) (reg z)
| NonTail(x), Lwz(y, C(z)) -> Printf.fprintf oc "\tlw %s, %d(%s)\n" (reg x) z (reg y)
| NonTail(_), Stw(x, y, V(z)) -> Printf.fprintf oc "\tstwx\t%s, %s, %s\n" (reg x) (reg y) (reg z)
@@ -93,10 +89,13 @@ and g' oc = function (* 各命令のアセンブリ生成 (caml2html: emit_gprim
| NonTail(x), FSub(y, z) -> Printf.fprintf oc "\tfsub.s %s, %s, %s\n" (reg x) (reg y) (reg z)
| NonTail(x), FMul(y, z) -> Printf.fprintf oc "\tfmul.s %s, %s, %s\n" (reg x) (reg y) (reg z)
| NonTail(x), FDiv(y, z) -> Printf.fprintf oc "\tfdiv.s %s, %s, %s\n" (reg x) (reg y) (reg z)
- | NonTail(x), Lfd(y, V(z)) -> Printf.fprintf oc "\tlfdx\t%s, %s, %s\n" (reg x) (reg y) (reg z)
- | NonTail(x), Lfd(y, C(z)) -> Printf.fprintf oc "\tlfd\t%s, %d(%s)\n" (reg x) z (reg y)
+ | NonTail(x), Lfd(y, V(z)) ->
+ Printf.fprintf oc "\tadd %s, %s, %s\n" (reg reg_tmp) (reg y) (reg z);
+ Printf.fprintf oc "\tflw %s, 0(%s)\n" (reg x) (reg reg_tmp)
+ | NonTail(x), Lfd(y, C(z)) ->
+ Printf.fprintf oc "\tflw %s, %d(%s)\n" (reg x) z (reg y)
| NonTail(_), Stfd(x, y, V(z)) -> Printf.fprintf oc "\tstfdx\t%s, %s, %s\n" (reg x) (reg y) (reg z)
- | NonTail(_), Stfd(x, y, C(z)) -> Printf.fprintf oc "\tstfd\t%s, %d(%s)\n" (reg x) z (reg y)
+ | NonTail(_), Stfd(x, y, C(z)) -> Printf.fprintf oc "\tfsw %s, %d(%s)\n" (reg x) z (reg y)
| NonTail(_), Comment(s) -> Printf.fprintf oc "#\t%s\n" s
(* 退避の仮想命令の実装 (caml2html: emit_save) *)
| NonTail(_), Save(x, y) when List.mem x allregs && not (S.mem y !stackset) ->
@@ -162,8 +161,9 @@ and g' oc = function (* 各命令のアセンブリ生成 (caml2html: emit_gprim
Printf.fprintf oc "\tcmpw\tcr7@@IfEq, %s, %s\n" (reg x) (reg y);
g'_non_tail_if oc (NonTail(z)) e1 e2 "beq" "bne"
| NonTail(z), IfEq(x, C(y), e1, e2) ->
- Printf.fprintf oc "\tcmpwi\tcr7@@IfEq, %s, %d\n" (reg x) y;
- g'_non_tail_if oc (NonTail(z)) e1 e2 "beq" "bne"
+ (* 新しい if 実装済み(浮動小数点数対応) *)
+ Printf.fprintf oc "\tli %s, %d\n" (reg reg_tmp) y;
+ g'_non_tail_if_new oc (reg x) (reg reg_tmp) (NonTail(z)) e1 e2 "beq" "bne"
| NonTail(z), IfLE(x, V(y), e1, e2) ->
(* 新しい if 実装済み *)
g'_non_tail_if_new oc (reg x) (reg y) (NonTail(z)) e1 e2 "ble" "bgt"
@@ -211,7 +211,7 @@ and g' oc = function (* 各命令のアセンブリ生成 (caml2html: emit_gprim
Printf.fprintf oc "\taddi %s, %s, %d\n" (reg reg_sp) (reg reg_sp) ((-1) * ss);
Printf.fprintf oc "\tlw %s, %d(%s)\n" (reg reg_tmp) (ss - 4) (reg reg_sp);
if List.mem a allregs && a <> regs.(0) then
- Printf.fprintf oc "\tmr\t%s, %s\n" (reg a) (reg regs.(0))
+ Printf.fprintf oc "\tmv %s, %s\n" (reg a) (reg regs.(0))
else if List.mem a allfregs && a <> fregs.(0) then
Printf.fprintf oc "\tfmr\t%s, %s\n" (reg a) (reg fregs.(0));
(* tmp レジスタから ra を復帰 *)
diff --git a/RV32/libmincaml.S b/RV32/libmincaml.S
index 1c2c771..0f4aab9 100644
--- a/RV32/libmincaml.S
+++ b/RV32/libmincaml.S
@@ -8,3 +8,39 @@ LC1:
LC2:
.long 1127219200
.long -2147483648
+
+// create_array
+// a0: number of elements
+// a1: initial value
+ .globl min_caml_create_array
+min_caml_create_array:
+ mv t2, a0 // t2 = number of elements
+ mv a0, s11 // a0 = hp
+min_caml_create_array_loop:
+ // if number of elements = 0
+ beq t2, zero, min_caml_create_array_exit
+ // if number of elements > 0
+ sw a1, 0(s11)
+ addi s11, s11, 4
+ addi t2, t2, -1
+ j min_caml_create_array_loop
+min_caml_create_array_exit:
+ ret
+
+// create_float_array
+// a0: number of elements
+// fa0: initial value
+ .globl min_caml_create_float_array
+min_caml_create_float_array:
+ mv t2, a0 // t2 = number of elements
+ mv a0, s11 // a0 = hp
+min_caml_create_float_array_loop:
+ // if number of elements = 0
+ beq t2, zero, min_caml_create_float_array_exit
+ // if number of elements > 0
+ fsw fa0, 0(s11)
+ addi s11, s11, 4
+ addi t2, t2, -1
+ j min_caml_create_float_array_loop
+min_caml_create_float_array_exit:
+ ret
diff --git a/RV32/virtual.ml b/RV32/virtual.ml
index d762c97..562ddb1 100644
--- a/RV32/virtual.ml
+++ b/RV32/virtual.ml
@@ -124,7 +124,7 @@ let rec g env = function (* 式の仮想マシンコード生成 (caml2html: vir
| Type.Array(Type.Float) ->
(* TODO: double(8バイト)ではなくfloat(4バイト)なので修正する必要がありそう *)
- Let((offset, Type.Int), Slw(y, C(3)),
+ Let((offset, Type.Int), Slw(y, C(2)),
Ans(Lfd(x, V(offset))))
| Type.Array(_) ->
Let((offset, Type.Int), Slw(y, C(2)),
@@ -135,7 +135,7 @@ let rec g env = function (* 式の仮想マシンコード生成 (caml2html: vir
(match M.find x env with
| Type.Array(Type.Unit) -> Ans(Nop)
| Type.Array(Type.Float) ->
- Let((offset, Type.Int), Slw(y, C(3)),
+ Let((offset, Type.Int), Slw(y, C(2)),
Ans(Stfd(z, x, V(offset))))
| Type.Array(_) ->
Let((offset, Type.Int), Slw(y, C(2)),
いい感じに動いてそう。
code:sh
$ make clean test/array_test
$ spike /opt/riscv/pk/riscv32-unknown-elf/bin/pk test/array_test
1.23
1.23
1.23
1.23
4649
5963
246911
3.14
9.8596
30.9591
97.2117