Blob Blame History Raw
From b81417ea168c3cf9454eeb41f1f723b66b3210aa Mon Sep 17 00:00:00 2001
From: Nicolas Ojeda Bar <n.oje.bar@gmail.com>
Date: Tue, 22 Nov 2016 22:30:35 +0100
Subject: [PATCH 09/10] Fix immediates' range when adjusting/indexing sp

---
 asmcomp/riscv/arch.ml      |  3 +++
 asmcomp/riscv/emit.mlp     | 53 ++++++++++++++++++++++++++++++++++------------
 asmcomp/riscv/selection.ml |  2 +-
 3 files changed, 44 insertions(+), 14 deletions(-)

diff --git a/asmcomp/riscv/arch.ml b/asmcomp/riscv/arch.ml
index 61a38b1..22c807c 100644
--- a/asmcomp/riscv/arch.ml
+++ b/asmcomp/riscv/arch.ml
@@ -32,6 +32,9 @@ let spacetime_node_hole_pointer_is_live_before = function
 type addressing_mode =
   | Iindexed of int                     (* reg + displ *)
 
+let is_immediate n =
+  (n <= 2047) && (n >= -2048)
+
 (* Sizes, endianness *)
 
 let big_endian = false
diff --git a/asmcomp/riscv/emit.mlp b/asmcomp/riscv/emit.mlp
index 6d0e3ae..97c49ce 100644
--- a/asmcomp/riscv/emit.mlp
+++ b/asmcomp/riscv/emit.mlp
@@ -93,6 +93,34 @@ let emit_stack r =
       let ofs = slot_offset s (register_class r) in `{emit_int ofs}(sp)`
   | _ -> fatal_error "Emit.emit_stack"
 
+(* Adjust sp by the given byte amount *)
+
+let emit_stack_adjustment = function
+  | 0 -> ()
+  | n when is_immediate n ->
+      `	addi	sp, sp, {emit_int n}\n`
+  | n ->
+      `	li	{emit_reg reg_tmp1}, {emit_int n}\n`;
+      `	add	sp, sp, {emit_reg reg_tmp1}\n`
+
+let emit_store src ofs =
+  if is_immediate ofs then
+    `	{emit_string stg}	{emit_reg src}, {emit_int ofs}(sp)\n`
+  else begin
+    `	li	{emit_reg reg_tmp1}, {emit_int ofs}\n`;
+    `	add	{emit_reg reg_tmp1}, sp, {emit_reg reg_tmp1}\n`;
+    `	{emit_string stg}	{emit_reg src}, 0({emit_reg reg_tmp1})\n`
+  end
+
+let emit_load dst ofs =
+  if is_immediate ofs then
+    `	{emit_string lg}	{emit_reg dst}, {emit_int ofs}(sp)\n`
+  else begin
+    `	li	{emit_reg reg_tmp1}, {emit_int ofs}\n`;
+    `	add	{emit_reg reg_tmp1}, sp, {emit_reg reg_tmp1}\n`;
+    `	{emit_string lg}	{emit_reg dst}, 0({emit_reg reg_tmp1})\n`
+  end
+
 (* Record live pointers at call points *)
 
 let record_frame_label ?label live raise_ dbg =
@@ -218,6 +246,7 @@ let name_for_specific = function
 
 (* Name of current function *)
 let function_name = ref ""
+
 (* Entry point for tail recursive calls *)
 let tailrec_entry_point = ref 0
 
@@ -234,12 +263,14 @@ let emit_instr i =
             `	mv      {emit_reg dst}, {emit_reg src}\n`
         | {loc = Reg _; typ = Float}, {loc = Reg _; typ = Float} ->
             `	fmv.d   {emit_reg dst}, {emit_reg src}\n`
-        | {loc = Reg _; typ = (Val | Int | Addr)}, {loc = Stack _} ->
-            `	{emit_string stg}	{emit_reg src}, {emit_stack dst}\n`
+        | {loc = Reg _; typ = (Val | Int | Addr)}, {loc = Stack s} ->
+            let ofs = slot_offset s (register_class dst) in
+            emit_store src ofs
         | {loc = Reg _; typ = Float}, {loc = Stack _} ->
             `	fsd	{emit_reg src}, {emit_stack dst}\n`
-        | {loc = Stack _; typ = (Val | Int | Addr)}, {loc = Reg _ } ->
-            `	{emit_string lg}	{emit_reg dst}, {emit_stack src}\n`
+        | {loc = Stack s; typ = (Val | Int | Addr)}, {loc = Reg _} ->
+            let ofs = slot_offset s (register_class src) in
+            emit_load dst ofs
         | {loc = Stack _; typ = Float}, {loc = Reg _} ->
             `	fld	{emit_reg dst}, {emit_stack src}\n`
         | _ ->
@@ -263,8 +294,7 @@ let emit_instr i =
       let n = frame_size() in
       if !contains_calls then
         `	{emit_string lg}	ra, {emit_int(n - size_addr)}(sp)\n`;
-      if n > 0 then
-        `	addi	sp, sp, {emit_int n}\n`;
+      emit_stack_adjustment n;
       `	jr	{emit_reg i.arg.(0)}\n`
   | Lop(Itailcall_imm {func; label_after = _}) ->
       if func = !function_name then begin
@@ -273,8 +303,7 @@ let emit_instr i =
         let n = frame_size() in
         if !contains_calls then
           `	{emit_string lg}	ra, {emit_int(n - size_addr)}(sp)\n`;
-        if n > 0 then
-          `	addi	sp, sp, {emit_int n}\n`;
+        emit_stack_adjustment n;
         `	tail	{emit_symbol func}\n`
       end
   | Lop(Iextcall{func; alloc = true; label_after = label}) ->
@@ -285,7 +314,7 @@ let emit_instr i =
       `	call	{emit_symbol func}\n`
   | Lop(Istackoffset n) ->
       assert (n mod 16 = 0);
-      `	addi	sp, sp, {emit_int (-n)}\n`;
+      emit_stack_adjustment (-n);
       stack_offset := !stack_offset + n
   | Lop(Iload(Single, Iindexed ofs)) ->
       `	flw	{emit_reg i.res.(0)}, {emit_int ofs}({emit_reg i.arg.(0)})\n`;
@@ -398,8 +427,7 @@ let emit_instr i =
       `	{emit_string lg}	ra, {emit_int(n - size_addr)}(sp)\n`
   | Lreturn ->
       let n = frame_size() in
-      if n > 0 then
-        `	addi	sp, sp, {emit_int n}\n`;
+      emit_stack_adjustment n;
       `	ret\n`
   | Llabel lbl ->
       `{emit_label lbl}:\n`
@@ -513,8 +541,7 @@ let fundecl fundecl =
   `	.align	2\n`;
   `{emit_symbol fundecl.fun_name}:\n`;
   let n = frame_size() in
-  if n > 0 then
-    `	addi	sp, sp, {emit_int(-n)}\n`;
+  emit_stack_adjustment (-n);
   if !contains_calls then
     `	{emit_string stg}	ra, {emit_int(n - size_addr)}(sp)\n`;
   `{emit_label !tailrec_entry_point}:\n`;
diff --git a/asmcomp/riscv/selection.ml b/asmcomp/riscv/selection.ml
index ad2b26e..2832336 100644
--- a/asmcomp/riscv/selection.ml
+++ b/asmcomp/riscv/selection.ml
@@ -22,7 +22,7 @@ class selector = object (self)
 
 inherit Selectgen.selector_generic as super
 
-method is_immediate n = (n <= 0x7FF) && (n >= -0x800)
+method is_immediate n = is_immediate n
 
 method select_addressing _ = function
   | Cop(Cadda, [arg; Cconst_int n]) when self#is_immediate n ->
-- 
2.9.3