diff --git a/asmcomp/emit_sparc.mlp b/asmcomp/emit_sparc.mlp index 6f656be71..86b131204 100644 --- a/asmcomp/emit_sparc.mlp +++ b/asmcomp/emit_sparc.mlp @@ -64,7 +64,8 @@ let symbol_prefix = | _ -> fatal_error "Emit_sparc.symbol_prefix" let emit_symbol s = - emit_string symbol_prefix; Emitaux.emit_symbol s + if not(String.length s >= 1 & s.[0] = '.') then emit_string symbol_prefix; + Emitaux.emit_symbol s (* Output a label *) @@ -204,7 +205,6 @@ let emit_float_constant (lbl, cst) = let name_for_int_operation = function Iadd -> "add" | Isub -> "sub" - | Imul -> "smul" | Iand -> "and" | Ior -> "or" | Ixor -> "xor" @@ -370,22 +370,6 @@ let rec emit_instr i dslot = ` mov {emit_int n}, %g4\n`; (* in delay slot *) ` add %g6, 4, {emit_reg i.res.(0)}\n` end - | Lop(Iintop Idiv) -> - ` sra {emit_reg i.arg.(0)}, 31, %g1\n`; - ` wr %g0, %g1, %y\n`; - ` nop\n`; - ` nop\n`; - ` nop\n`; - ` sdiv {emit_reg i.arg.(0)}, {emit_reg i.arg.(1)}, {emit_reg i.res.(0)}\n` - | Lop(Iintop Imod) -> - ` sra {emit_reg i.arg.(0)}, 31, %g1\n`; - ` wr %g0, %g1, %y\n`; - ` nop\n`; - ` nop\n`; - ` nop\n`; - ` sdiv {emit_reg i.arg.(0)}, {emit_reg i.arg.(1)}, %g1\n`; - ` smul %g1, {emit_reg i.arg.(1)}, %g1\n`; - ` sub {emit_reg i.arg.(0)}, %g1, {emit_reg i.res.(0)}\n` | Lop(Iintop(Icomp cmp)) -> let comp = name_for_int_comparison cmp in ` cmp {emit_reg i.arg.(0)}, {emit_reg i.arg.(1)}\n`; @@ -400,45 +384,24 @@ let rec emit_instr i dslot = | Lop(Iintop op) -> let instr = name_for_int_operation op in ` {emit_string instr} {emit_reg i.arg.(0)}, {emit_reg i.arg.(1)}, {emit_reg i.res.(0)}\n` - | Lop(Iintop_imm(Idiv, n)) -> + | Lop(Iintop_imm(Idiv, n)) -> (* n is a power of 2 *) let l = Misc.log2 n in - if n = 1 lsl l then begin - let lbl = new_label() in - ` cmp {emit_reg i.arg.(0)}, 0\n`; - ` bge {emit_label lbl}\n`; - ` mov {emit_reg i.arg.(0)}, %g1\n`; (* in delay slot *) - ` add %g1, {emit_int (n-1)}, %g1\n`; - `{emit_label lbl}:\n`; - ` sra %g1, {emit_int l}, {emit_reg i.res.(0)}\n` - end else begin - ` sra {emit_reg i.arg.(0)}, 31, %g1\n`; - ` wr %g0, %g1, %y\n`; - ` nop\n`; - ` nop\n`; - ` nop\n`; - ` sdiv {emit_reg i.arg.(0)}, {emit_int n}, {emit_reg i.res.(0)}\n` - end - | Lop(Iintop_imm(Imod, n)) -> - let l = Misc.log2 n in - if n = 1 lsl l then begin - let lbl = new_label() in - ` tst {emit_reg i.arg.(0)}\n`; - ` bge {emit_label lbl}\n`; - ` andcc {emit_reg i.arg.(0)}, {emit_int (n-1)}, {emit_reg i.res.(0)}\n`; (* in delay slot *) - ` be {emit_label lbl}\n`; - ` nop\n`; - ` sub {emit_reg i.res.(0)}, {emit_int n}, {emit_reg i.res.(0)}\n`; - `{emit_label lbl}:\n` - end else begin - ` sra {emit_reg i.arg.(0)}, 31, %g1\n`; - ` wr %g0, %g1, %y\n`; - ` nop\n`; - ` nop\n`; - ` nop\n`; - ` sdiv {emit_reg i.arg.(0)}, {emit_int n}, %g1\n`; - ` smul %g1, {emit_int n}, %g1\n`; - ` sub {emit_reg i.arg.(0)}, %g1, {emit_reg i.res.(0)}\n` - end + let lbl = new_label() in + ` cmp {emit_reg i.arg.(0)}, 0\n`; + ` bge {emit_label lbl}\n`; + ` mov {emit_reg i.arg.(0)}, %g1\n`; (* in delay slot *) + ` add %g1, {emit_int (n-1)}, %g1\n`; + `{emit_label lbl}:\n`; + ` sra %g1, {emit_int l}, {emit_reg i.res.(0)}\n` + | Lop(Iintop_imm(Imod, n)) -> (* n is a power of 2 *) + let lbl = new_label() in + ` tst {emit_reg i.arg.(0)}\n`; + ` bge {emit_label lbl}\n`; + ` andcc {emit_reg i.arg.(0)}, {emit_int (n-1)}, {emit_reg i.res.(0)}\n`; (* in delay slot *) + ` be {emit_label lbl}\n`; + ` nop\n`; + ` sub {emit_reg i.res.(0)}, {emit_int n}, {emit_reg i.res.(0)}\n`; + `{emit_label lbl}:\n` | Lop(Iintop_imm(Icomp cmp, n)) -> let comp = name_for_int_comparison cmp in ` cmp {emit_reg i.arg.(0)}, {emit_int n}\n`; diff --git a/asmcomp/proc_sparc.ml b/asmcomp/proc_sparc.ml index 6e4ea00ea..64351254a 100644 --- a/asmcomp/proc_sparc.ml +++ b/asmcomp/proc_sparc.ml @@ -58,7 +58,33 @@ let select_addressing exp = (* Instruction selection *) -let select_oper op args = raise Use_default +let select_oper op args = + (* Multiplication, division and modulus are turned into + calls to C library routines, except if the dividend is a power of 2. *) + (Cmuli, [arg; Cconst_int n]) -> + let l = Misc.log2 n in + if n = 1 lsl l + then (Iintop_imm(Ilsl, l), [arg]) + else (Iextcall(".umul", false), args) + | (Cmuli, [Cconst_int n; arg]) -> + let l = Misc.log2 n in + if n = 1 lsl l + then (Iintop_imm(Ilsl, l), [arg]) + else (Iextcall(".umul", false), args) + | (Cmuli, _) -> + (Iextcall(".umul", false), args) + | (Cdivi, [arg; Cconst_int n]) + when is_immediate n & n = 1 lsl (Misc.log2 n) -> + (Iintop_imm(Idiv, n), [arg]) + | (Cdivi, _) -> + (Iextcall(".div", false), args) + | (Cmodi, [arg; Cconst_int n]) + when is_immediate n & n = 1 lsl (Misc.log2 n) -> + (Iintop_imm(Imod, n), [arg]) + | (Cmodi, _) -> + (Iextcall(".mod", false), args) + | _ -> + raise Use_default let select_store addr exp = raise Use_default @@ -183,7 +209,7 @@ let loc_results res = let (loc, ofs) = calling_conventions 8 13 100 105 not_supported res in loc (* On the Sparc, all arguments to C functions, even floating-point arguments, - are passed in %o..%o5, then on the stack *) + are passed in %o0..%o5, then on the stack *) let loc_external_arguments arg = let loc = Array.new (Array.length arg) Reg.dummy in @@ -244,10 +270,6 @@ let oper_latency = function Ireload -> 3 | Iload(_, _) -> 3 | Iconst_float _ -> 3 (* turned into a load *) - | Iintop Imul -> 10 - | Iintop_imm(Imul, _) -> 10 - | Iintop(Idiv | Imod) -> 20 - | Iintop_imm((Idiv | Imod), _) -> 20 | Iaddf | Isubf -> 3 | Imulf -> 5 | Idivf -> 15