test/adder.ml をRISC-Vで動かす
#MinCaml #RISC-V
from MinCamlでRISC-Vのアセンブリコードを出力したい
修正箇所
code:diff
diff --git a/RV32/emit.ml b/RV32/emit.ml
index 1a2bfbc..0772682 100644
--- a/RV32/emit.ml
+++ b/RV32/emit.ml
@@ -33,8 +33,8 @@ let reg r =
let load_label r label =
let r' = reg r in
Printf.sprintf
- "\tlis\t%s, ha16(%s)\n\taddi\t%s, %s, lo16(%s)\n"
- r' label r' r' label
+ "\tla %s, %s\n"
+ r' label
(* 関数呼び出しのために引数を並べ替える(register shuffling) (caml2html: emit_shuffle) *)
let rec shuffle sw xys =
@@ -83,9 +83,9 @@ and g' oc = function (* 各命令のアセンブリ生成 (caml2html: emit_gprim
| 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), 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 "\tlwz\t%s, %d(%s)\n" (reg x) z (reg y)
+ | 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)
- | NonTail(_), Stw(x, y, C(z)) -> Printf.fprintf oc "\tstw\t%s, %d(%s)\n" (reg x) z (reg y)
+ | NonTail(_), Stw(x, y, C(z)) -> Printf.fprintf oc "\tsw %s, %d(%s)\n" (reg x) z (reg y)
| NonTail(x), FMr(y) when x = y -> ()
| NonTail(x), FMr(y) -> Printf.fprintf oc "\tfmr\t%s, %s\n" (reg x) (reg y)
| NonTail(x), FNeg(y) -> Printf.fprintf oc "\tfneg.s %s, %s\n" (reg x) (reg y)
@@ -187,28 +187,35 @@ and g' oc = function (* 各命令のアセンブリ生成 (caml2html: emit_gprim
(* 関数呼び出しの仮想命令の実装 (caml2html: emit_call) *)
| Tail, CallCls(x, ys, zs) -> (* 末尾呼び出し (caml2html: emit_tailcall) *)
g'_args oc (x, reg_cl) ys zs;
- Printf.fprintf oc "\tlwz\t%s, 0(%s)\n" (reg reg_sw) (reg reg_cl);
+ Printf.fprintf oc "\tlw %s, 0(%s)\n" (reg reg_sw) (reg reg_cl);
Printf.fprintf oc "\tmtctr\t%s\n\tbctr\n" (reg reg_sw);
| Tail, CallDir(Id.L(x), ys, zs) -> (* 末尾呼び出し *)
g'_args oc [] ys zs;
(* NOTE: 末尾呼び出し時には call ではなく j で遷移する *)
Printf.fprintf oc "\tj %s\n" x
| NonTail(a), CallCls(x, ys, zs) ->
- Printf.fprintf oc "\tmflr\t%s\n" (reg reg_tmp);
+ (* ra を tmp レジスタへ退避 *)
+ Printf.fprintf oc "\tmv %s, ra\n" (reg reg_tmp);
g'_args oc (x, reg_cl) ys zs;
let ss = stacksize () in
- Printf.fprintf oc "\tstw\t%s, %d(%s)\n" (reg reg_tmp) (ss - 4) (reg reg_sp);
+ Printf.fprintf oc "\tsw %s, %d(%s)\n" (reg reg_tmp) (ss - 4) (reg reg_sp);
Printf.fprintf oc "\taddi\t%s, %s, %d\n" (reg reg_sp) (reg reg_sp) ss;
- Printf.fprintf oc "\tlwz\t%s, 0(%s)\n" (reg reg_tmp) (reg reg_cl);
- Printf.fprintf oc "\tmtctr\t%s\n" (reg reg_tmp);
- Printf.fprintf oc "\tbctrl\n";
- Printf.fprintf oc "\tsubi\t%s, %s, %d\n" (reg reg_sp) (reg reg_sp) ss;
- Printf.fprintf oc "\tlwz\t%s, %d(%s)\n" (reg reg_tmp) (ss - 4) (reg reg_sp);
+
+ (* クロージャを呼び出し *)
+ (* 参考: https://ie.u-ryukyu.ac.jp/~kono/compiler/c2/powerpc.html *)
+ Printf.fprintf oc "\tlw %s, 0(%s)\n" (reg reg_tmp) (reg reg_cl);
+ Printf.fprintf oc "\tjalr %s\n" (reg reg_tmp);
+ (* Printf.fprintf oc "\tmtctr\t%s\n" (reg reg_tmp);
+ Printf.fprintf oc "\tbctrl\n"; *)
+
+ 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))
else if List.mem a allfregs && a <> fregs.(0) then
Printf.fprintf oc "\tfmr\t%s, %s\n" (reg a) (reg fregs.(0));
- Printf.fprintf oc "\tmtlr\t%s\n" (reg reg_tmp)
+ (* tmp レジスタから ra を復帰 *)
+ Printf.fprintf oc "\tmv ra, %s\n" (reg reg_tmp)
| (NonTail(a), CallDir(Id.L(x), ys, zs)) ->
(* ra を tmp レジスタへ退避 *)
Printf.fprintf oc "\tmv %s, ra\n" (reg reg_tmp);
動作確認
うごいたー!!
code:sh
$ make clean test/adder
$ spike /opt/riscv/pk/riscv32-unknown-elf/bin/pk test/adder
10