summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--asmcomp/alpha/emit.mlp54
-rw-r--r--asmrun/alpha.S10
2 files changed, 23 insertions, 41 deletions
diff --git a/asmcomp/alpha/emit.mlp b/asmcomp/alpha/emit.mlp
index 94b081f40..475695051 100644
--- a/asmcomp/alpha/emit.mlp
+++ b/asmcomp/alpha/emit.mlp
@@ -46,6 +46,8 @@ let insert_load_gp f =
labels_needing_gp := LabelSet.add lbl !labels_needing_gp
end in
+ let tailrec_entry_point = new_label() in
+
(* Determine if $gp is needed before an instruction.
[next] says whether $gp is needed just after (i.e. by the following
instruction). *)
@@ -57,11 +59,10 @@ let insert_load_gp f =
| Lop(Iconst_float s) -> true (* turned into ldq ($gp) *)
| Lop(Iconst_symbol s) -> true (* turned into ldq ($gp) *)
| Lop(Icall_ind) -> false (* does ldgp if needed afterwards *)
- | Lop(Icall_imm s) -> true (* loads $27 from ($gp) if external, *)
- (* and assume $gp set if internal *)
+ | Lop(Icall_imm s) -> false (* does ldgp if needed afterwards *)
| Lop(Itailcall_ind) -> false
- | Lop(Itailcall_imm s) -> true (* loads $27 from ($gp) if external *)
- (* and assume $gp set if internal *)
+ | Lop(Itailcall_imm s) ->
+ if s = f.fun_name then label_needs_gp tailrec_entry_point else false
| Lop(Iextcall(_, _)) -> true (* loads $27 from ($gp) *)
| Lop(Iload(_, Ibased(_, _))) -> true (* loads address from ($gp) *)
| Lop(Istore(_, Ibased(_, _))) -> true (* loads address from ($gp) *)
@@ -97,7 +98,7 @@ let insert_load_gp f =
while not !fixpoint_reached do
fixpoint_reached := true;
- needs_gp f.fun_body
+ if needs_gp f.fun_body then set_label_needs_gp tailrec_entry_point
done;
(* Insert Ireloadgp instructions after calls where needed *)
@@ -419,26 +420,18 @@ let emit_instr i =
| Lop(Iconst_symbol s) ->
` lda {emit_reg i.res.(0)}, {emit_symbol s}\n`
| Lop(Icall_ind) ->
- ` mov {emit_reg i.arg.(0)}, $27\n`;
- liveregs i live_27;
+ liveregs i 0;
`{record_frame i.live} jsr ({emit_reg i.arg.(0)})\n`
| Lop(Icall_imm s) ->
liveregs i 0;
- begin try
- let lbl = local_entry_point s in
- `{record_frame i.live} bsr $26, {emit_label lbl} # {emit_symbol s}\n`
- with External_function ->
- ` lda $27, {emit_symbol s}\n`;
- `{record_frame i.live} bsr $26, {emit_symbol s}\n`
- end
+ `{record_frame i.live} bsr $26, {emit_symbol s}\n`
| Lop(Itailcall_ind) ->
- ` mov {emit_reg i.arg.(0)}, $27\n`;
let n = frame_size() in
if !contains_calls then
` ldq $26, {emit_int(n - 8)}($sp)\n`;
if n > 0 then
` lda $sp, {emit_int n}($sp)\n`;
- liveregs i (live_26 lor live_27);
+ liveregs i live_26;
` jmp ({emit_reg i.arg.(0)})\n`
| Lop(Itailcall_imm s) ->
if s = !function_name then begin
@@ -450,18 +443,12 @@ let emit_instr i =
if n > 0 then
` lda $sp, {emit_int n}($sp)\n`;
liveregs i live_26;
- try
- let lbl = local_entry_point s in
- ` br {emit_label lbl} # {emit_symbol s}\n`
- with External_function ->
- ` lda $27, {emit_symbol s}\n`;
- ` jmp ($27), {emit_symbol s}\n`
+ ` br {emit_symbol s}\n`
end
| Lop(Iextcall(s, alloc)) ->
if alloc then begin
- ` lda $25, {emit_symbol s}\n`;
- liveregs i live_25;
- ` lda $27, caml_c_call\n`;
+ ` lda $27, {emit_symbol s}\n`;
+ liveregs i live_27;
`{record_frame i.live} bsr $26, caml_c_call\n`
end else begin
` jsr {emit_symbol s}\n`
@@ -711,26 +698,21 @@ let emit_fundecl (fundecl, needs_gp) =
` .globl {emit_symbol fundecl.fun_name}\n`;
` .ent {emit_symbol fundecl.fun_name}\n`;
`{emit_symbol fundecl.fun_name}:\n`;
- if needs_gp then
- ` ldgp $gp, 0($27)\n`;
- let local_entry =
- try
- local_entry_point fundecl.fun_name
- with External_function -> (* should not happen except with testasmcomp *)
- let lbl = new_label() in
- Hashtbl.add local_entry_points fundecl.fun_name lbl;
- lbl in
- `{emit_label local_entry}:\n`;
let n = frame_size() in
if n > 0 then
` lda $sp, -{emit_int n}($sp)\n`;
+ if needs_gp then begin
+ let lbl = new_label() in
+ ` br $27, {emit_label lbl}\n`;
+ `{emit_label lbl}: ldgp $gp, 0($27)\n`
+ end;
if !contains_calls then begin
` stq $26, {emit_int(n - 8)}($sp)\n`;
` .mask 0x04000000, -8\n`;
` .fmask 0x0, 0\n`
end;
` .frame $sp, {emit_int n}, $26\n`;
- ` .prologue {emit_int(if needs_gp then 1 else 0)}\n`;
+ ` .prologue 0\n`;
tailrec_entry_point := new_label();
`{emit_label !tailrec_entry_point}:\n`;
emit_all fundecl.fun_body;
diff --git a/asmrun/alpha.S b/asmrun/alpha.S
index c71edd762..fcc38494c 100644
--- a/asmrun/alpha.S
+++ b/asmrun/alpha.S
@@ -218,18 +218,19 @@ $103: ldgp $gp, 0($27)
.end caml_call_gc
/* Call a C function from Caml */
-/* Function to call is in $25 */
+/* Function to call is in $27 */
.globl caml_c_call
.ent caml_c_call
.align 3
caml_c_call:
.prologue 0
- /* Preserve return address and caller's $gp callee-save registers */
+ /* Preserve return address and caller's $gp in callee-save registers */
mov $26, $9
mov $gp, $10
/* Rebuild $gp */
- ldgp $gp, 8($27)
+ br $25, $104
+$104: ldgp $gp, 0($25)
/* Record lowest stack address and return address */
lda $11, caml_last_return_address
stq $26, 0($11)
@@ -240,8 +241,7 @@ caml_c_call:
lda $14, young_limit
stq $15, caml_exception_pointer
/* Call the function */
- mov $25, $27
- jsr ($25)
+ jsr ($27)
/* Reload alloc ptr and alloc limit */
ldq $13, 0($12) /* $12 still points to young_ptr */
ldq $14, 0($14) /* $14 still points to young_limit */