1 diff --exclude=*CVS* -urN ocaml/asmcomp/linearize.ml ocaml+powerpcfix/asmcomp/linearize.ml
2 --- ocaml/asmcomp/linearize.ml Mon Feb 5 09:49:10 2001
3 +++ ocaml+powerpcfix/asmcomp/linearize.ml Tue Feb 19 18:06:40 2002
6 (***********************************************************************)
11 (* Transformation of Mach code into a list of pseudo-instructions. *)
16 { mutable desc: instruction_desc;
18 + mutable next: instruction;
22 diff --exclude=*CVS* -urN ocaml/asmcomp/linearize.mli ocaml+powerpcfix/asmcomp/linearize.mli
23 --- ocaml/asmcomp/linearize.mli Mon Feb 5 09:49:10 2001
24 +++ ocaml+powerpcfix/asmcomp/linearize.mli Tue Feb 19 18:06:40 2002
27 (***********************************************************************)
32 (* Transformation of Mach code into a list of pseudo-instructions. *)
37 { mutable desc: instruction_desc;
39 + mutable next: instruction;
44 val end_instr: instruction
46 instruction_desc -> Reg.t array -> Reg.t array -> instruction -> instruction
47 +val invert_test: Mach.test -> Mach.test
51 diff --exclude=*CVS* -urN ocaml/asmcomp/power/arch.ml ocaml+powerpcfix/asmcomp/power/arch.ml
52 --- ocaml/asmcomp/power/arch.ml Fri Apr 21 10:11:10 2000
53 +++ ocaml+powerpcfix/asmcomp/power/arch.ml Tue Feb 19 18:06:42 2002
56 (***********************************************************************)
61 (* Specific operations for the PowerPC processor *)
64 type specific_operation =
65 Imultaddf (* multiply and add *)
66 | Imultsubf (* multiply and subtract *)
67 + | Ialloc_far of int (* allocation in large functions *)
69 (* Addressing modes *)
73 fprintf ppf "%a *f %a -f %a"
74 printreg arg.(0) printreg arg.(1) printreg arg.(2)
76 + fprintf ppf "alloc_far %d" n
78 (* Distinguish between the PowerPC and the Power/RS6000 submodels *)
80 diff --exclude=*CVS* -urN ocaml/asmcomp/power/emit.mlp ocaml+powerpcfix/asmcomp/power/emit.mlp
81 --- ocaml/asmcomp/power/emit.mlp Fri Mar 10 15:31:06 2000
82 +++ ocaml+powerpcfix/asmcomp/power/emit.mlp Tue Feb 19 18:06:42 2002
85 (***********************************************************************)
90 (* Emission of PowerPC assembly code *)
93 let name_for_specific = function
95 | Imultsubf -> "fmsub"
96 + | _ -> Misc.fatal_error "Emit.Ispecific"
98 (* Name of current function *)
99 let function_name = ref ""
100 @@ -365,6 +366,132 @@
101 (* Number of jumptable entries *)
102 let num_jumptbl_entries = ref 0
104 +(* Fixup conditional branches that exceed hardware allowed range *)
106 +let load_store_size = function
108 + | Iindexed ofs -> if is_immediate ofs then 1 else 3
111 +let instr_size = function
113 + | Lop(Imove | Ispill | Ireload) -> 1
114 + | Lop(Iconst_int n) -> if is_native_immediate n then 1 else 2
115 + | Lop(Iconst_float s) -> if toc then 1 else 2
116 + | Lop(Iconst_symbol s) -> if toc then 1 else 2
117 + | Lop(Icall_ind) -> if toc then 6 else 2
118 + | Lop(Icall_imm s) ->
119 + if toc && not (StringSet.mem s !defined_functions) then 2 else 1
120 + | Lop(Itailcall_ind) -> if toc then 7 else 5
121 + | Lop(Itailcall_imm s) ->
122 + if s = !function_name then 1
123 + else if not toc || StringSet.mem s !defined_functions then 4
125 + | Lop(Iextcall(s, true)) -> if toc then 2 else 3
126 + | Lop(Iextcall(s, false)) -> if pic_externals then 4 else 1
127 + | Lop(Istackoffset n) -> 1
128 + | Lop(Iload(chunk, addr)) ->
129 + if chunk = Byte_signed
130 + then load_store_size addr + 1
131 + else load_store_size addr
132 + | Lop(Istore(chunk, addr)) -> load_store_size addr
133 + | Lop(Ialloc n) -> 4
134 + | Lop(Ispecific(Ialloc_far n)) -> 5
135 + | Lop(Iintop Imod) -> if powerpc then 3 else 2
136 + | Lop(Iintop(Icomp cmp)) -> 4
137 + | Lop(Iintop op) -> 1
138 + | Lop(Iintop_imm(Idiv, n)) -> 2
139 + | Lop(Iintop_imm(Imod, n)) -> 4
140 + | Lop(Iintop_imm(Icomp cmp, n)) -> 4
141 + | Lop(Iintop_imm(op, n)) -> 1
142 + | Lop(Inegf | Iabsf | Iaddf | Isubf | Imulf | Idivf) -> 1
143 + | Lop(Ifloatofint) -> 9
144 + | Lop(Iintoffloat) -> 4
145 + | Lop(Ispecific sop) -> 1
146 + | Lreloadretaddr -> 2
150 + | Lcondbranch(tst, lbl) -> 2
151 + | Lcondbranch3(lbl0, lbl1, lbl2) ->
152 + 1 + (if lbl0 = None then 0 else 1)
153 + + (if lbl1 = None then 0 else 1)
154 + + (if lbl2 = None then 0 else 1)
155 + | Lswitch jumptbl -> 8
156 + | Lsetuptrap lbl -> 1
157 + | Lpushtrap -> if toc then 5 else 4
159 + | Lraise -> if toc then 7 else 6
161 +let label_map code =
162 + let map = Hashtbl.create 37 in
163 + let rec fill_map pc instr =
164 + match instr.desc with
166 + | Llabel lbl -> Hashtbl.add map lbl pc; fill_map pc instr.next
167 + | op -> fill_map (pc + instr_size op) instr.next
170 +let max_branch_offset = 8180
171 +(* 14-bit signed offset in words. Remember to cut some slack
172 + for multi-word instructions where the branch can be anywhere in
173 + the middle. 12 words of slack is plenty. *)
175 +let branch_overflows map pc_branch lbl_dest =
176 + let pc_dest = Hashtbl.find map lbl_dest in
177 + let delta = pc_dest - (pc_branch + 1) in
178 + delta <= -max_branch_offset || delta >= max_branch_offset
180 +let opt_branch_overflows map pc_branch opt_lbl_dest =
181 + match opt_lbl_dest with
183 + | Some lbl_dest -> branch_overflows map pc_branch lbl_dest
185 +let fixup_branches codesize map code =
186 + let expand_optbranch lbl n arg next =
190 + instr_cons (Lcondbranch(Iinttest_imm(Isigned Ceq, n), l))
192 + let rec fixup did_fix pc instr =
193 + match instr.desc with
195 + | Lcondbranch(test, lbl) when branch_overflows map pc lbl ->
196 + let lbl2 = new_label() in
198 + instr_cons (Lbranch lbl) [||] [||]
199 + (instr_cons (Llabel lbl2) [||] [||] instr.next) in
200 + instr.desc <- Lcondbranch(invert_test test, lbl2);
201 + instr.next <- cont;
202 + fixup true (pc + 2) instr.next
203 + | Lcondbranch3(lbl0, lbl1, lbl2)
204 + when opt_branch_overflows map pc lbl0
205 + || opt_branch_overflows map pc lbl1
206 + || opt_branch_overflows map pc lbl2 ->
208 + expand_optbranch lbl0 0 instr.arg
209 + (expand_optbranch lbl1 1 instr.arg
210 + (expand_optbranch lbl2 2 instr.arg instr.next)) in
211 + instr.desc <- cont.desc;
212 + instr.next <- cont.next;
213 + fixup true pc instr
214 + | Lop(Ialloc n) when codesize - pc >= max_branch_offset ->
215 + instr.desc <- Lop(Ispecific(Ialloc_far n));
216 + fixup true (pc + 4) instr.next
218 + fixup did_fix (pc + instr_size op) instr.next
219 + in fixup false 0 code
221 +(* Iterate branch expansion till all conditional branches are OK *)
223 +let rec branch_normalization code =
224 + let (codesize, map) = label_map code in
225 + if codesize >= max_branch_offset && fixup_branches codesize map code
226 + then branch_normalization code
230 (* Output the assembly code for an instruction *)
232 let rec emit_instr i dslot =
234 ` addi {emit_reg i.res.(0)}, {emit_gpr 31}, 4\n`;
236 ` bltl {emit_label !call_gc_label}\n`
237 + | Lop(Ispecific(Ialloc_far n)) ->
238 + if !call_gc_label = 0 then call_gc_label := new_label();
239 + let lbl = new_label() in
240 + ` addi {emit_gpr 31}, {emit_gpr 31}, {emit_int(-n)}\n`;
241 + ` cmplw {emit_gpr 31}, {emit_gpr 30}\n`;
242 + ` bge {emit_label lbl}\n`;
243 + record_frame i.live;
244 + ` bl {emit_label !call_gc_label}\n`;
245 + `{emit_label lbl}: addi {emit_reg i.res.(0)}, {emit_gpr 31}, 4\n`
246 | Lop(Iintop Isub) -> (* subf has swapped arguments *)
247 (* Use subfc instead of subf for RS6000 compatibility. *)
248 ` subfc {emit_reg i.res.(0)}, {emit_reg i.arg.(1)}, {emit_reg i.arg.(0)}\n`
250 ` lwz {emit_gpr 29}, 4({emit_gpr 1})\n`;
252 ` lwz {emit_gpr 2}, 20({emit_gpr 1})\n`;
253 - ` addi {emit_gpr 1}, {emit_gpr 1}, {emit_int trap_frame_size}\n\n`;
254 + ` addi {emit_gpr 1}, {emit_gpr 1}, {emit_int trap_frame_size}\n`;
257 and emit_delay = function
259 ` addi {emit_gpr 1}, {emit_gpr 1}, {emit_int(-n)}\n`
261 `{emit_label !tailrec_entry_point}:\n`;
262 + branch_normalization fundecl.fun_body;
263 emit_all fundecl.fun_body;
264 (* Emit the glue code to call the GC *)
265 if !call_gc_label > 0 then begin