diff options
author | Mark Shinwell <mshinwell@janestreet.com> | 2017-04-10 09:18:13 +0100 |
---|---|---|
committer | Mark Shinwell <mshinwell@janestreet.com> | 2017-04-10 09:18:13 +0100 |
commit | 3efe66e043bb2315517e9059066dc5d36aa78cac (patch) | |
tree | 8daa6efbc8688a581ea30552801a6a5785e96f01 /asmcomp | |
parent | 80e7529be59f818f201586d2fbe05db85b62d3c5 (diff) | |
download | ocaml-3efe66e043bb2315517e9059066dc5d36aa78cac.tar.gz |
Remove SPARC backend
Diffstat (limited to 'asmcomp')
-rw-r--r-- | asmcomp/sparc/CSE.ml | 33 | ||||
-rw-r--r-- | asmcomp/sparc/NOTES.md | 17 | ||||
-rw-r--r-- | asmcomp/sparc/arch.ml | 83 | ||||
-rw-r--r-- | asmcomp/sparc/emit.mlp | 771 | ||||
-rw-r--r-- | asmcomp/sparc/proc.ml | 251 | ||||
-rw-r--r-- | asmcomp/sparc/reload.ml | 19 | ||||
-rw-r--r-- | asmcomp/sparc/scheduling.ml | 63 | ||||
-rw-r--r-- | asmcomp/sparc/selection.ml | 80 |
8 files changed, 0 insertions, 1317 deletions
diff --git a/asmcomp/sparc/CSE.ml b/asmcomp/sparc/CSE.ml deleted file mode 100644 index 7d246ba372..0000000000 --- a/asmcomp/sparc/CSE.ml +++ /dev/null @@ -1,33 +0,0 @@ -(**************************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Gallium, INRIA Rocquencourt *) -(* *) -(* Copyright 2014 Institut National de Recherche en Informatique et *) -(* en Automatique. *) -(* *) -(* All rights reserved. This file is distributed under the terms of *) -(* the GNU Lesser General Public License version 2.1, with the *) -(* special exception on linking described in the file LICENSE. *) -(* *) -(**************************************************************************) - -(* CSE for Sparc *) - -open Mach -open CSEgen - -class cse = object - -inherit cse_generic (* as super *) - -method! is_cheap_operation op = - match op with - | Iconst_int n -> n <= 4095n && n >= -4096n - | _ -> false - -end - -let fundecl f = - (new cse)#fundecl f diff --git a/asmcomp/sparc/NOTES.md b/asmcomp/sparc/NOTES.md deleted file mode 100644 index 18c3db4a99..0000000000 --- a/asmcomp/sparc/NOTES.md +++ /dev/null @@ -1,17 +0,0 @@ -# Supported platforms - -SPARC v8 and up, in 32-bit mode. - -Operating systems: Solaris, Linux - (abandoned since major Linux distributions no longer support SPARC). - -Status of this port: nearly abandoned - (no hardware or virtual machine available for testing). - -# Reference documents - -* Instruction set architecture: - _The SPARC Architecture Manual_ version 8. -* ELF application binary interface: - _System V Application Binary Interface, - SPARC Processor Supplement_ diff --git a/asmcomp/sparc/arch.ml b/asmcomp/sparc/arch.ml deleted file mode 100644 index 1f7e2abdef..0000000000 --- a/asmcomp/sparc/arch.ml +++ /dev/null @@ -1,83 +0,0 @@ -(**************************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 Institut National de Recherche en Informatique et *) -(* en Automatique. *) -(* *) -(* All rights reserved. This file is distributed under the terms of *) -(* the GNU Lesser General Public License version 2.1, with the *) -(* special exception on linking described in the file LICENSE. *) -(* *) -(**************************************************************************) - -(* Specific operations for the Sparc processor *) - -open Format - -(* SPARC V8 adds multiply and divide. - SPARC V9 adds double precision float operations, conditional - move, and more instructions that are only useful in 64 bit mode. - Sun calls 32 bit V9 "V8+". *) -type arch_version = SPARC_V7 | SPARC_V8 | SPARC_V9 - -let arch_version = ref SPARC_V7 - -let command_line_options = - [ "-march=v8", Arg.Unit (fun () -> arch_version := SPARC_V8), - " Generate code for SPARC V8 processors"; - "-march=v9", Arg.Unit (fun () -> arch_version := SPARC_V9), - " Generate code for SPARC V9 processors" ] - -type specific_operation = unit (* None worth mentioning *) - -let spacetime_node_hole_pointer_is_live_before _specific_op = false - -(* Addressing modes *) - -type addressing_mode = - Ibased of string * int (* symbol + displ *) - | Iindexed of int (* reg + displ *) - -(* Sizes, endianness *) - -let big_endian = true - -let size_addr = 4 -let size_int = 4 -let size_float = 8 - -let allow_unaligned_access = false - -(* Behavior of division *) - -let division_crashes_on_overflow = false - -(* Operations on addressing modes *) - -let identity_addressing = Iindexed 0 - -let offset_addressing addr delta = - match addr with - Ibased(s, n) -> Ibased(s, n + delta) - | Iindexed n -> Iindexed(n + delta) - -let num_args_addressing = function - Ibased _ -> 0 - | Iindexed _ -> 1 - -(* Printing operations and addressing modes *) - -let print_addressing printreg addr ppf arg = - match addr with - | Ibased(s, n) -> - let idx = if n <> 0 then Printf.sprintf " + %i" n else "" in - fprintf ppf "\"%s\"%s" s idx - | Iindexed n -> - let idx = if n <> 0 then Printf.sprintf " + %i" n else "" in - fprintf ppf "%a%s" printreg arg.(0) idx - -let print_specific_operation _printreg _op _ppf _arg = - Misc.fatal_error "Arch_sparc.print_specific_operation" diff --git a/asmcomp/sparc/emit.mlp b/asmcomp/sparc/emit.mlp deleted file mode 100644 index a4a50f940a..0000000000 --- a/asmcomp/sparc/emit.mlp +++ /dev/null @@ -1,771 +0,0 @@ -#2 "asmcomp/sparc/emit.mlp" -(**************************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 Institut National de Recherche en Informatique et *) -(* en Automatique. *) -(* *) -(* All rights reserved. This file is distributed under the terms of *) -(* the GNU Lesser General Public License version 2.1, with the *) -(* special exception on linking described in the file LICENSE. *) -(* *) -(**************************************************************************) - -(* Emission of Sparc assembly code *) - -open Misc -open Cmm -open Arch -open Proc -open Reg -open Mach -open Linearize -open Emitaux - -(* Solaris vs. the other ports *) - -let solaris = Config.system = "solaris" - -(* Tradeoff between code size and code speed *) - -let fastcode_flag = ref true - -(* Layout of the stack *) -(* Always keep the stack 8-aligned. - Always leave 96 bytes at the bottom of the stack *) - -let stack_offset = ref 0 - -let frame_size () = - let size = - !stack_offset + - 4 * num_stack_slots.(0) + 8 * num_stack_slots.(1) + - (if !contains_calls then 4 else 0) in - Misc.align size 8 - -let slot_offset loc cl = - match loc with - Incoming n -> frame_size() + n + 96 - | Local n -> - if cl = 0 - then !stack_offset + num_stack_slots.(1) * 8 + n * 4 + 96 - else !stack_offset + n * 8 + 96 - | Outgoing n -> n + 96 - -(* Return the other register in a register pair *) - -let next_in_pair = function - {loc = Reg r; typ = (Int | Addr | Val)} -> phys_reg (r + 1) - | {loc = Reg r; typ = Float} -> phys_reg (r + 16) - | _ -> fatal_error "Emit.next_in_pair" - -(* Symbols are prefixed with _ under SunOS *) - -let symbol_prefix = - if Config.system = "sunos" then "_" else "" - -let emit_symbol s = - if String.length s >= 1 && s.[0] = '.' - then emit_string s - else begin emit_string symbol_prefix; Emitaux.emit_symbol '$' s end - -let emit_size lbl = - if Config.system = "solaris" then - ` .size {emit_symbol lbl},.-{emit_symbol lbl}\n` - -let rodata () = - if Config.system = "solaris" (* || Config.system = "linux" *) - (* || Config.system = "gnu" *) then - ` .section \".rodata\"\n` - else - ` .data\n` - -(* Check if an integer or native integer is an immediate operand *) - -let is_immediate n = - n <= 4095 && n >= -4096 - -let is_native_immediate n = - n <= Nativeint.of_int 4095 && n >= Nativeint.of_int (-4096) - -(* Output a label *) - -let label_prefix = - if Config.system = "sunos" then "L" else ".L" - -let emit_label lbl = - emit_string label_prefix; emit_int lbl - -(* Output a pseudo-register *) - -let emit_reg r = - match r.loc with - Reg r -> emit_string (register_name r) - | _ -> fatal_error "Emit.emit_reg" - -(* Output a stack reference *) - -let emit_stack r = - match r.loc with - Stack s -> - let ofs = slot_offset s (register_class r) in `[%sp + {emit_int ofs}]` - | _ -> fatal_error "Emit.emit_stack" - -(* Output a load *) - -let emit_load instr addr arg dst = - match addr with - Ibased(s, 0) -> - ` sethi %hi({emit_symbol s}), %g1\n`; - ` {emit_string instr} [%g1 + %lo({emit_symbol s})], {emit_reg dst}\n` - | Ibased(s, ofs) -> - ` sethi %hi({emit_symbol s} + {emit_int ofs}), %g1\n`; - ` {emit_string instr} [%g1 + %lo({emit_symbol s} + {emit_int ofs})], {emit_reg dst}\n` - | Iindexed ofs -> - if is_immediate ofs then - ` {emit_string instr} [{emit_reg arg.(0)} + {emit_int ofs}], {emit_reg dst}\n` - else begin - ` sethi %hi({emit_int ofs}), %g1\n`; - ` or %g1, %lo({emit_int ofs}), %g1\n`; - ` {emit_string instr} [{emit_reg arg.(0)} + %g1], {emit_reg dst}\n` - end - -(* Output a store *) - -let emit_store instr addr arg src = - match addr with - Ibased(s, 0) -> - ` sethi %hi({emit_symbol s}), %g1\n`; - ` {emit_string instr} {emit_reg src}, [%g1 + %lo({emit_symbol s})]\n` - | Ibased(s, ofs) -> - ` sethi %hi({emit_symbol s} + {emit_int ofs}), %g1\n`; - ` {emit_string instr} {emit_reg src}, [%g1 + %lo({emit_symbol s} + {emit_int ofs})]\n` - | Iindexed ofs -> - if is_immediate ofs then - ` {emit_string instr} {emit_reg src}, [{emit_reg arg.(1)} + {emit_int ofs}]\n` - else begin - ` sethi %hi({emit_int ofs}), %g1\n`; - ` or %g1, %lo({emit_int ofs}), %g1\n`; - ` {emit_string instr} {emit_reg src}, [{emit_reg arg.(1)} + %g1]\n` - end - -(* Record live pointers at call points *) - -type frame_descr = - { fd_lbl: int; (* Return address *) - fd_frame_size: int; (* Size of stack frame *) - fd_live_offset: int list } (* Offsets/regs of live addresses *) - -let frame_descriptors = ref([] : frame_descr list) - -let record_frame ?label live = - let lbl = - match label with - | None -> new_label() - | Some label -> label - in - let live_offset = ref [] in - Reg.Set.iter - (function - | {typ = Val; loc = Reg r} -> - live_offset := ((r lsl 1) + 1) :: !live_offset - | {typ = Val; loc = Stack s} as reg -> - live_offset := slot_offset s (register_class reg) :: !live_offset - | {typ = Addr} as r -> - Misc.fatal_error ("bad GC root " ^ Reg.name r) - | _ -> ()) - live; - live_offset := List.sort_uniq (-) !live_offset; - frame_descriptors := - { fd_lbl = lbl; - fd_frame_size = frame_size(); - fd_live_offset = !live_offset } :: !frame_descriptors; - `{emit_label lbl}:` - -let emit_frame fd = - ` .word {emit_label fd.fd_lbl}\n`; - ` .half {emit_int fd.fd_frame_size}\n`; - ` .half {emit_int (List.length fd.fd_live_offset)}\n`; - List.iter - (fun n -> - ` .half {emit_int n}\n`) - fd.fd_live_offset; - ` .align 4\n` - -(* Record floating-point constants *) - -let float_constants = ref ([] : (int * int64) list) - -let emit_float_constant (lbl, cst) = - rodata (); - ` .align 8\n`; - `{emit_label lbl}:`; - emit_float64_split_directive ".word" cst - -(* Emission of the profiling prelude *) -let emit_profile () = - begin match Config.system with - "solaris" -> - let lbl = new_label() in - ` .section \".bss\"\n`; - `{emit_label lbl}: .skip 4\n`; - ` .text\n`; - ` save %sp,-96,%sp\n`; - ` sethi %hi({emit_label lbl}),%o0\n`; - ` call _mcount\n`; - ` or %o0,%lo({emit_label lbl}),%o0\n`; - ` restore\n` - | _ -> () - end - -(* Names of various instructions *) - -let name_for_int_operation = function - Iadd -> "add" - | Isub -> "sub" - | Iand -> "and" - | Ior -> "or" - | Ixor -> "xor" - | Ilsl -> "sll" - | Ilsr -> "srl" - | Iasr -> "sra" - | Imul -> "smul" - | _ -> Misc.fatal_error "Emit.name_for_int_operation" - -let name_for_float_operation = function - Inegf -> if !arch_version = SPARC_V9 then "fnegd" else "fnegs" - | Iabsf -> if !arch_version = SPARC_V9 then "fabsd" else "fabss" - | Iaddf -> "faddd" - | Isubf -> "fsubd" - | Imulf -> "fmuld" - | Idivf -> "fdivd" - | _ -> Misc.fatal_error "Emit.name_for_float_operation" - -let name_for_int_movcc = function - Isigned Ceq -> "e" | Isigned Cne -> "ne" - | Isigned Cle -> "le" | Isigned Cgt -> "g" - | Isigned Clt -> "l" | Isigned Cge -> "ge" - | Iunsigned Ceq -> "e" | Iunsigned Cne -> "ne" - | Iunsigned Cle -> "leu" | Iunsigned Cgt -> "gu" - | Iunsigned Clt -> "lu" | Iunsigned Cge -> "geu" - -let name_for_int_comparison = function - Isigned Ceq -> "be" | Isigned Cne -> "bne" - | Isigned Cle -> "ble" | Isigned Cgt -> "bg" - | Isigned Clt -> "bl" | Isigned Cge -> "bge" - | Iunsigned Ceq -> "be" | Iunsigned Cne -> "bne" - | Iunsigned Cle -> "bleu" | Iunsigned Cgt -> "bgu" - | Iunsigned Clt -> "blu" | Iunsigned Cge -> "bgeu" - -let name_for_float_comparison cmp neg = - match cmp with - Ceq -> if neg then "fbne" else "fbe" - | Cne -> if neg then "fbe" else "fbne" - | Cle -> if neg then "fbug" else "fble" - | Cgt -> if neg then "fbule" else "fbg" - | Clt -> if neg then "fbuge" else "fbl" - | Cge -> if neg then "fbul" else "fbge" - -(* Output the assembly code for an instruction *) - -let function_name = ref "" -let tailrec_entry_point = ref 0 -let range_check_trap = ref 0 - -let rec emit_instr i dslot = - match i.desc with - Lend -> () - | Lop(Imove | Ispill | Ireload) -> - let src = i.arg.(0) and dst = i.res.(0) in - begin match (src, dst) with - {loc = Reg _; typ = (Int | Addr | Val)}, {loc = Reg _} -> - ` mov {emit_reg src}, {emit_reg dst}\n` - | {loc = Reg _; typ = Float}, {loc = Reg _; typ = Float} -> - if !arch_version = SPARC_V9 then - ` fmovd {emit_reg src}, {emit_reg dst}\n` - else begin - ` fmovs {emit_reg src}, {emit_reg dst}\n`; - ` fmovs {emit_reg(next_in_pair src)}, {emit_reg(next_in_pair dst)}\n` - end - | {loc = Reg _; typ = Float}, {loc = Reg _; typ = (Int | Addr | Val)} -> - (* This happens when calling C functions and passing a float arg - in %o0...%o5 *) - ` sub %sp, 8, %sp\n`; - ` std {emit_reg src}, [%sp + 96]\n`; - ` ld [%sp + 96], {emit_reg dst}\n`; - let dst2 = i.res.(1) in - begin match dst2 with - | {loc = Reg _; typ = Int} -> - ` ld [%sp + 100], {emit_reg dst2}\n`; - | {loc = Stack _; typ = Int} -> - ` ld [%sp + 100], %g1\n`; - ` st %g1, {emit_stack dst2}\n`; - | _ -> - fatal_error "Emit: Imove Float [| _; _ |]" - end; - ` add %sp, 8, %sp\n` - | {loc = Reg _; typ = (Int | Addr | Val)}, {loc = Stack _} -> - ` st {emit_reg src}, {emit_stack dst}\n` - | {loc = Reg _; typ = Float}, {loc = Stack _} -> - ` std {emit_reg src}, {emit_stack dst}\n` - | {loc = Stack _; typ = (Int | Addr | Val)}, {loc = Reg _} -> - ` ld {emit_stack src}, {emit_reg dst}\n` - | {loc = Stack _; typ = Float}, {loc = Reg _} -> - ` ldd {emit_stack src}, {emit_reg dst}\n` - | (_, _) -> - fatal_error "Emit: Imove" - end - | Lop(Iconst_int n) -> - if is_native_immediate n then - ` mov {emit_nativeint n}, {emit_reg i.res.(0)}\n` - else begin - ` sethi %hi({emit_nativeint n}), %g1\n`; - ` or %g1, %lo({emit_nativeint n}), {emit_reg i.res.(0)}\n` - end - | Lop(Iconst_float f) -> - (* On UltraSPARC, the fzero instruction could be used to set a - floating point register pair to zero. *) - let lbl = new_label() in - float_constants := (lbl, f) :: !float_constants; - ` sethi %hi({emit_label lbl}), %g1\n`; - ` ldd [%g1 + %lo({emit_label lbl})], {emit_reg i.res.(0)}\n` - | Lop(Iconst_symbol s) -> - ` sethi %hi({emit_symbol s}), %g1\n`; - ` or %g1, %lo({emit_symbol s}), {emit_reg i.res.(0)}\n` - | Lop(Icall_ind { label_after; }) -> - `{record_frame i.live ~label:label_after} call {emit_reg i.arg.(0)}\n`; - fill_delay_slot dslot - | Lop(Icall_imm { func; label_after; }) -> - `{record_frame i.live ~label:label_after} call {emit_symbol func}\n`; - fill_delay_slot dslot - | Lop(Itailcall_ind { label_after = _; }) -> - let n = frame_size() in - if !contains_calls then - ` ld [%sp + {emit_int(n - 4 + 96)}], %o7\n`; - ` jmp {emit_reg i.arg.(0)}\n`; - ` add %sp, {emit_int n}, %sp\n` (* in delay slot *) - | Lop(Itailcall_imm { func; label_after = _; }) -> - let n = frame_size() in - if func = !function_name then begin - ` b {emit_label !tailrec_entry_point}\n`; - fill_delay_slot dslot - end else begin - if !contains_calls then - ` ld [%sp + {emit_int(n - 4 + 96)}], %o7\n`; - ` sethi %hi({emit_symbol func}), %g1\n`; - ` jmp %g1 + %lo({emit_symbol func})\n`; - ` add %sp, {emit_int n}, %sp\n` (* in delay slot *) - end - | Lop(Iextcall { func; alloc; label_after; }) -> - if alloc then begin - ` sethi %hi({emit_symbol func}), %g2\n`; - `{record_frame i.live ~label:label_after} call {emit_symbol "caml_c_call"}\n`; - ` or %g2, %lo({emit_symbol func}), %g2\n` (* in delay slot *) - end else begin - ` call {emit_symbol func}\n`; - fill_delay_slot dslot - end - | Lop(Istackoffset n) -> - ` add %sp, {emit_int (-n)}, %sp\n`; - stack_offset := !stack_offset + n - | Lop(Iload(chunk, addr)) -> - let dest = i.res.(0) in - begin match chunk with - Double_u -> - emit_load "ld" addr i.arg dest; - emit_load "ld" (offset_addressing addr 4) i.arg (next_in_pair dest) - | Single -> - emit_load "ld" addr i.arg dest; - ` fstod {emit_reg dest}, {emit_reg dest}\n` - | _ -> - let loadinstr = - match chunk with - Byte_unsigned -> "ldub" - | Byte_signed -> "ldsb" - | Sixteen_unsigned -> "lduh" - | Sixteen_signed -> "ldsh" - | Double -> "ldd" - | _ -> "ld" in - emit_load loadinstr addr i.arg dest - end - | Lop(Istore(chunk, addr, _)) -> - let src = i.arg.(0) in - begin match chunk with - Double_u -> - emit_store "st" addr i.arg src; - emit_store "st" (offset_addressing addr 4) i.arg (next_in_pair src) - | Single -> - ` fdtos {emit_reg src}, %f30\n`; - emit_store "st" addr i.arg (phys_reg 115) (* %f30 *) - | _ -> - let storeinstr = - match chunk with - | Byte_unsigned | Byte_signed -> "stb" - | Sixteen_unsigned | Sixteen_signed -> "sth" - | Double -> "std" - | _ -> "st" in - emit_store storeinstr addr i.arg src - end - | Lop(Ialloc { words = n; label_after_call_gc; }) -> - if !fastcode_flag then begin - let lbl_cont = new_label() in - if solaris then begin - ` sub %l6, {emit_int n}, %l6\n`; - ` cmp %l6, %l7\n` - end else begin - ` ld [%l7], %g1\n`; - ` sub %l6, {emit_int n}, %l6\n`; - ` cmp %l6, %g1\n` - end; - ` bgeu {emit_label lbl_cont}\n`; - ` add %l6, 4, {emit_reg i.res.(0)}\n`; (* in delay slot *) - `{record_frame i.live ?label:label_after_call_gc} call {emit_symbol "caml_call_gc"}\n`; - ` mov {emit_int n}, %g2\n`; (* in delay slot *) - ` add %l6, 4, {emit_reg i.res.(0)}\n`; - `{emit_label lbl_cont}:\n` - end else begin - `{record_frame i.live} call {emit_symbol "caml_allocN"}\n`; - ` mov {emit_int n}, %g2\n`; (* in delay slot *) - ` add %l6, 4, {emit_reg i.res.(0)}\n` - end - | Lop(Iintop(Icomp cmp)) -> - ` cmp {emit_reg i.arg.(0)}, {emit_reg i.arg.(1)}\n`; - if !arch_version = SPARC_V9 then begin - let comp = name_for_int_movcc cmp in - ` mov 0, {emit_reg i.res.(0)}\n`; - ` mov{emit_string comp} %icc, 1, {emit_reg i.res.(0)}\n` - end - else begin - let comp = name_for_int_comparison cmp - and lbl = new_label() in - ` {emit_string comp},a {emit_label lbl}\n`; - ` mov 1, {emit_reg i.res.(0)}\n`; - ` mov 0, {emit_reg i.res.(0)}\n`; - `{emit_label lbl}:\n` - end - | Lop(Iintop (Icheckbound _)) -> - ` cmp {emit_reg i.arg.(0)}, {emit_reg i.arg.(1)}\n`; - if solaris then - ` tleu 5\n` (* 5 = ST_RANGE_CHECK *) - else begin - if !range_check_trap = 0 then range_check_trap := new_label(); - ` bleu {emit_label !range_check_trap}\n`; - ` nop\n` (* delay slot *) - end - | Lop(Iintop Idiv) -> - ` sra {emit_reg i.arg.(0)}, 31, %g1\n`; - ` wr %g1, %y\n`; - ` sdiv {emit_reg i.arg.(0)}, {emit_reg i.arg.(1)}, {emit_reg i.res.(0)}\n` - | Lop(Iintop Imulh) -> - ` smul {emit_reg i.arg.(0)}, {emit_reg i.arg.(1)}, %g1\n`; - ` rd %y, {emit_reg i.res.(0)}\n` - | 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(Ilsl, 1)) -> - (* UltraSPARC has two add units but only one shifter. *) - ` add {emit_reg i.arg.(0)}, {emit_reg i.arg.(0)}, {emit_reg i.res.(0)}\n` - | Lop(Iintop_imm(Icomp cmp, n)) -> - ` cmp {emit_reg i.arg.(0)}, {emit_int n}\n`; - if !arch_version = SPARC_V9 then begin - let comp = name_for_int_movcc cmp in - ` mov 0, {emit_reg i.res.(0)}\n`; - ` mov{emit_string comp} %icc, 1, {emit_reg i.res.(0)}\n` - end else begin - let comp = name_for_int_comparison cmp - and lbl = new_label() in - ` {emit_string comp},a {emit_label lbl}\n`; - ` mov 1, {emit_reg i.res.(0)}\n`; - ` mov 0, {emit_reg i.res.(0)}\n`; - `{emit_label lbl}:\n` - end - | Lop(Iintop_imm(Icheckbound _, n)) -> - ` cmp {emit_reg i.arg.(0)}, {emit_int n}\n`; - if solaris then - ` tleu 5\n` (* 5 = ST_RANGE_CHECK *) - else begin - if !range_check_trap = 0 then range_check_trap := new_label(); - ` bleu {emit_label !range_check_trap}\n`; - ` nop\n` (* delay slot *) - end - | Lop(Iintop_imm(Imulh, n)) -> - ` smul {emit_reg i.arg.(0)}, {emit_int n}, %g1\n`; - ` rd %y, {emit_reg i.res.(0)}\n` - | Lop(Iintop_imm(op, n)) -> - let instr = name_for_int_operation op in - ` {emit_string instr} {emit_reg i.arg.(0)}, {emit_int n}, {emit_reg i.res.(0)}\n` - | Lop(Inegf | Iabsf as op) -> - let instr = name_for_float_operation op in - ` {emit_string instr} {emit_reg i.arg.(0)}, {emit_reg i.res.(0)}\n`; - if !arch_version <> SPARC_V9 then - ` fmovs {emit_reg(next_in_pair i.arg.(0))}, {emit_reg(next_in_pair i.res.(0))}\n` - | Lop(Iaddf | Isubf | Imulf | Idivf as op) -> - let instr = name_for_float_operation op in - ` {emit_string instr} {emit_reg i.arg.(0)}, {emit_reg i.arg.(1)}, {emit_reg i.res.(0)}\n` - | Lop(Ifloatofint) -> - ` sub %sp, 8, %sp\n`; - ` st {emit_reg i.arg.(0)}, [%sp + 96]\n`; - ` ld [%sp + 96], %f30\n`; - ` add %sp, 8, %sp\n`; - ` fitod %f30, {emit_reg i.res.(0)}\n` - | Lop(Iintoffloat) -> - ` fdtoi {emit_reg i.arg.(0)}, %f30\n`; - ` sub %sp, 8, %sp\n`; - ` st %f30, [%sp + 96]\n`; - ` ld [%sp + 96], {emit_reg i.res.(0)}\n`; - ` add %sp, 8, %sp\n` - | Lop(Ispecific _) -> - assert false - | Lreloadretaddr -> - let n = frame_size() in - ` ld [%sp + {emit_int(n - 4 + 96)}], %o7\n` - | Lreturn -> - let n = frame_size() in - ` retl\n`; - if n = 0 then - ` nop\n` - else - ` add %sp, {emit_int n}, %sp\n` - | Llabel lbl -> - `{emit_label lbl}:\n` - | Lbranch lbl -> - ` b {emit_label lbl}\n`; - fill_delay_slot dslot - | Lcondbranch(tst, lbl) -> - begin match tst with - Itruetest -> - ` tst {emit_reg i.arg.(0)}\n`; - ` bne {emit_label lbl}\n` - | Ifalsetest -> - ` tst {emit_reg i.arg.(0)}\n`; - ` be {emit_label lbl}\n` - | Iinttest cmp -> - let comp = name_for_int_comparison cmp in - ` cmp {emit_reg i.arg.(0)}, {emit_reg i.arg.(1)}\n`; - ` {emit_string comp} {emit_label lbl}\n` - | Iinttest_imm(cmp, n) -> - let comp = name_for_int_comparison cmp in - ` cmp {emit_reg i.arg.(0)}, {emit_int n}\n`; - ` {emit_string comp} {emit_label lbl}\n` - | Ifloattest(cmp, neg) -> - let comp = name_for_float_comparison cmp neg in - ` fcmpd {emit_reg i.arg.(0)}, {emit_reg i.arg.(1)}\n`; - ` nop\n`; - ` {emit_string comp} {emit_label lbl}\n` - | Ioddtest -> - ` andcc {emit_reg i.arg.(0)}, 1, %g0\n`; - ` bne {emit_label lbl}\n` - | Ieventest -> - ` andcc {emit_reg i.arg.(0)}, 1, %g0\n`; - ` be {emit_label lbl}\n` - end; - fill_delay_slot dslot - | Lcondbranch3(lbl0, lbl1, lbl2) -> - ` cmp {emit_reg i.arg.(0)}, 1\n`; - begin match lbl0 with - None -> () - | Some lbl -> ` bl {emit_label lbl}\n nop\n` - end; - begin match lbl1 with - None -> () - | Some lbl -> ` be {emit_label lbl}\n nop\n` - end; - begin match lbl2 with - None -> () - | Some lbl -> ` bg {emit_label lbl}\n nop\n` - end - | Lswitch jumptbl -> - let lbl_jumptbl = new_label() in - ` sethi %hi({emit_label lbl_jumptbl}), %g1\n`; - ` or %g1, %lo({emit_label lbl_jumptbl}), %g1\n`; - ` sll {emit_reg i.arg.(0)}, 2, %g2\n`; - ` ld [%g1 + %g2], %g1\n`; - ` jmp %g1\n`; (* poor scheduling *) - ` nop\n`; - `{emit_label lbl_jumptbl}:`; - for i = 0 to Array.length jumptbl - 1 do - ` .word {emit_label jumptbl.(i)}\n` - done - | Lsetuptrap lbl -> - ` call {emit_label lbl}\n`; - ` sub %sp, 8, %sp\n` (* in delay slot *) - | Lpushtrap -> - stack_offset := !stack_offset + 8; - ` st %o7, [%sp + 96]\n`; - ` st %l5, [%sp + 100]\n`; - ` mov %sp, %l5\n` - | Lpoptrap -> - ` ld [%sp + 100], %l5\n`; - ` add %sp, 8, %sp\n`; - stack_offset := !stack_offset - 8 - | Lraise _ -> - ` ld [%l5 + 96], %g1\n`; - ` mov %l5, %sp\n`; - ` ld [%sp + 100], %l5\n`; - ` jmp %g1 + 8\n`; - ` add %sp, 8, %sp\n` - -and fill_delay_slot = function - None -> ` nop\n` - | Some i -> emit_instr i None - -(* Checks if a pseudo-instruction expands to exactly one machine instruction - that does not branch. *) - -let is_one_instr_op = function - Imulh | Idiv | Imod | Icomp _ | Icheckbound _ -> false - | _ -> true - -let is_one_instr i = - match i.desc with - Lop op -> - begin match op with - Imove | Ispill | Ireload -> - i.arg.(0).typ <> Float && i.res.(0).typ <> Float - | Iconst_int n -> is_native_immediate n - | Istackoffset _ -> true - | Iload(_, Iindexed n) -> i.res.(0).typ <> Float && is_immediate n - | Istore(_, Iindexed n, _) -> i.arg.(0).typ <> Float && is_immediate n - | Iintop(op) -> is_one_instr_op op - | Iintop_imm(op, _) -> is_one_instr_op op - | Iaddf | Isubf | Imulf | Idivf -> true - | Iabsf | Inegf -> !arch_version = SPARC_V9 - | _ -> false - end - | _ -> false - -let no_interference res arg = - try - for i = 0 to Array.length arg - 1 do - for j = 0 to Array.length res - 1 do - if arg.(i).loc = res.(j).loc then raise Exit - done - done; - true - with Exit -> - false - -(* Emit a sequence of instructions, trying to fill delay slots for branches *) - -let rec emit_all i = - match i with - {desc = Lend} -> () - | {next = {desc = Lop(Icall_imm _) - | Lop(Iextcall { alloc = false; }) | Lbranch _}} - when is_one_instr i -> - emit_instr i.next (Some i); - emit_all i.next.next - | {next = {desc = Lop(Itailcall_imm { func; _ })}} - when func = !function_name && is_one_instr i -> - emit_instr i.next (Some i); - emit_all i.next.next - | {next = {desc = Lop(Icall_ind _)}} - when is_one_instr i && no_interference i.res i.next.arg -> - emit_instr i.next (Some i); - emit_all i.next.next - | {next = {desc = Lcondbranch(_, _)}} - when is_one_instr i && no_interference i.res i.next.arg -> - emit_instr i.next (Some i); - emit_all i.next.next - | _ -> - emit_instr i None; - emit_all i.next - -(* Emission of a function declaration *) - -let fundecl fundecl = - function_name := fundecl.fun_name; - fastcode_flag := fundecl.fun_fast; - tailrec_entry_point := new_label(); - range_check_trap := 0; - stack_offset := 0; - float_constants := []; - ` .text\n`; - ` .align 4\n`; - ` .global {emit_symbol fundecl.fun_name}\n`; - if Config.system = "solaris" then - ` .type {emit_symbol fundecl.fun_name},#function\n`; - `{emit_symbol fundecl.fun_name}:\n`; - if !Clflags.gprofile then emit_profile(); - let n = frame_size() in - if n > 0 then - ` sub %sp, {emit_int n}, %sp\n`; - if !contains_calls then - ` st %o7, [%sp + {emit_int(n - 4 + 96)}]\n`; - `{emit_label !tailrec_entry_point}:\n`; - emit_all fundecl.fun_body; - if !range_check_trap > 0 then begin - `{emit_label !range_check_trap}:\n`; - ` call {emit_symbol "caml_ml_array_bound_error"}\n`; - ` nop\n` - end; - emit_size fundecl.fun_name; - List.iter emit_float_constant !float_constants - -(* Emission of data *) - -let emit_item = function - Cglobal_symbol s -> - ` .global {emit_symbol s}\n`; - | Cdefine_symbol s -> - `{emit_symbol s}:\n` - | Cint8 n -> - ` .byte {emit_int n}\n` - | Cint16 n -> - ` .half {emit_int n}\n` - | Cint32 n -> - ` .word {emit_nativeint n}\n` - | Cint n -> - ` .word {emit_nativeint n}\n` - | Csingle f -> - emit_float32_directive ".word" (Int32.bits_of_float f) - | Cdouble f -> - emit_float64_split_directive ".word" (Int64.bits_of_float f) - | Csymbol_address s -> - ` .word {emit_symbol s}\n` - | Cstring s -> - emit_string_directive " .ascii " s - | Cskip n -> - if n > 0 then ` .skip {emit_int n}\n` - | Calign n -> - ` .align {emit_int n}\n` - -let data l = - ` .data\n`; - List.iter emit_item l - -(* Beginning / end of an assembly file *) - -let begin_assembly() = - let lbl_begin = Compilenv.make_symbol (Some "data_begin") in - ` .data\n`; - ` .global {emit_symbol lbl_begin}\n`; - `{emit_symbol lbl_begin}:\n`; - let lbl_begin = Compilenv.make_symbol (Some "code_begin") in - ` .text\n`; - ` .global {emit_symbol lbl_begin}\n`; - `{emit_symbol lbl_begin}:\n` - -let end_assembly() = - ` .text\n`; - let lbl_end = Compilenv.make_symbol (Some "code_end") in - ` .global {emit_symbol lbl_end}\n`; - `{emit_symbol lbl_end}:\n`; - ` .data\n`; - let lbl_end = Compilenv.make_symbol (Some "data_end") in - ` .global {emit_symbol lbl_end}\n`; - `{emit_symbol lbl_end}:\n`; - ` .word 0\n`; - let lbl = Compilenv.make_symbol (Some "frametable") in - rodata (); - ` .global {emit_symbol lbl}\n`; - if Config.system = "solaris" then - ` .type {emit_symbol lbl},#object\n`; - `{emit_symbol lbl}:\n`; - ` .word {emit_int (List.length !frame_descriptors)}\n`; - List.iter emit_frame !frame_descriptors; - emit_size lbl; - frame_descriptors := [] diff --git a/asmcomp/sparc/proc.ml b/asmcomp/sparc/proc.ml deleted file mode 100644 index 04f3b19c19..0000000000 --- a/asmcomp/sparc/proc.ml +++ /dev/null @@ -1,251 +0,0 @@ -(**************************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 Institut National de Recherche en Informatique et *) -(* en Automatique. *) -(* *) -(* All rights reserved. This file is distributed under the terms of *) -(* the GNU Lesser General Public License version 2.1, with the *) -(* special exception on linking described in the file LICENSE. *) -(* *) -(**************************************************************************) - -(* Description of the Sparc processor *) - -open Misc -open Cmm -open Reg -open Arch -open Mach - -(* Instruction selection *) - -let word_addressed = false - -(* Registers available for register allocation *) - -(* Register map: - %o0 - %o5 0 - 5 function results, C functions args / res - %i0 - %i5 6 - 11 function arguments, preserved by C - %l0 - %l4 12 - 16 general purpose, preserved by C - %g3 - %g4 17 - 18 general purpose, not preserved by C - - %l5 exception pointer - %l6 allocation pointer - %l7 address of allocation limit - - %g0 always zero - %g1 - %g2 temporaries - %g5 - %g7 reserved for system libraries - - %f0 - %f10 100 - 105 function arguments and results - %f12 - %f28 106 - 114 general purpose - %f30 temporary *) - -let int_reg_name = [| - (* 0-5 *) "%o0"; "%o1"; "%o2"; "%o3"; "%o4"; "%o5"; - (* 6-11 *) "%i0"; "%i1"; "%i2"; "%i3"; "%i4"; "%i5"; - (* 12-16 *) "%l0"; "%l1"; "%l2"; "%l3"; "%l4"; - (* 17-18 *) "%g3"; "%g4" -|] - -let float_reg_name = [| - (* 100-105 *) "%f0"; "%f2"; "%f4"; "%f6"; "%f8"; "%f10"; - (* 106-109 *) "%f12"; "%f14"; "%f16"; "%f18"; - (* 110-114 *) "%f20"; "%f22"; "%f24"; "%f26"; "%f28"; - (* 115 *) "%f30"; - (* Odd parts of register pairs *) - (* 116-121 *) "%f1"; "%f3"; "%f5"; "%f7"; "%f9"; "%f11"; - (* 122-125 *) "%f13"; "%f15"; "%f17"; "%f19"; - (* 126-130 *) "%f21"; "%f23"; "%f25"; "%f27"; "%f29"; - (* 131 *) "%f31" -|] - -let num_register_classes = 2 - -let register_class r = - match r.typ with - | Val | Int | Addr -> 0 - | Float -> 1 - -let num_available_registers = [| 19; 15 |] - -let first_available_register = [| 0; 100 |] - -let register_name r = - if r < 100 then int_reg_name.(r) else float_reg_name.(r - 100) - -let rotate_registers = true - -(* Representation of hard registers by pseudo-registers *) - -let hard_int_reg = - let v = Array.make 19 Reg.dummy in - for i = 0 to 18 do v.(i) <- Reg.at_location Int (Reg i) done; - v - -let hard_float_reg = - let v = Array.make 32 Reg.dummy in - for i = 0 to 31 do v.(i) <- Reg.at_location Float (Reg(100 + i)) done; - v - -let all_phys_regs = - Array.append hard_int_reg (Array.sub hard_float_reg 0 15) - (* No need to include the odd parts of float register pairs, - nor the temporary register %f30 *) - -let phys_reg n = - if n < 100 then hard_int_reg.(n) else hard_float_reg.(n - 100) - -let stack_slot slot ty = - Reg.at_location ty (Stack slot) - -let loc_spacetime_node_hole = Reg.dummy (* Spacetime unsupported *) - -(* Calling conventions *) - -let calling_conventions first_int last_int first_float last_float make_stack - arg = - let loc = Array.make (Array.length arg) Reg.dummy in - let int = ref first_int in - let float = ref first_float in - let ofs = ref 0 in - for i = 0 to Array.length arg - 1 do - match arg.(i).typ with - | Val | Int | Addr as ty -> - if !int <= last_int then begin - loc.(i) <- phys_reg !int; - incr int - end else begin - loc.(i) <- stack_slot (make_stack !ofs) ty; - ofs := !ofs + size_int - end - | Float -> - if !float <= last_float then begin - loc.(i) <- phys_reg !float; - incr float - end else begin - loc.(i) <- stack_slot (make_stack !ofs) Float; - ofs := !ofs + size_float - end - done; - (loc, Misc.align !ofs 8) (* Keep stack 8-aligned *) - -let incoming ofs = Incoming ofs -let outgoing ofs = Outgoing ofs -let not_supported _ofs = fatal_error "Proc.loc_results: cannot call" - -let max_arguments_for_tailcalls = 10 - -let loc_arguments arg = - calling_conventions 6 15 100 105 outgoing arg -let loc_parameters arg = - let (loc, _ofs) = calling_conventions 6 15 100 105 incoming arg in loc -let loc_results res = - let (loc, _ofs) = calling_conventions 0 5 100 105 not_supported res in loc - -(* On the Sparc, all arguments to C functions, even floating-point arguments, - are passed in %o0..%o5, then on the stack *) - -let loc_external_arguments arg = - let loc = Array.make (Array.length arg) [| |] in - let reg = ref 0 (* %o0 *) in - let ofs = ref (-4) in (* start at sp + 92 = sp + 96 - 4 *) - let next_loc typ = - if !reg <= 5 (* %o5 *) then begin - assert (size_component typ = size_int); - let loc = phys_reg !reg in - incr reg; - loc - end else begin - let loc = stack_slot (outgoing !ofs) typ in - ofs := !ofs + size_component typ; - loc - end - in - for i = 0 to Array.length arg - 1 do - match arg.(i) with - | [| { typ = (Val | Int | Addr as typ) } |] -> - loc.(i) <- [| next_loc typ |] - | [| { typ = Float } |] -> - if !reg <= 5 then begin - let loc1 = next_loc Int in - let loc2 = next_loc Int in - loc.(i) <- [| loc1; loc2 |] - end else - loc.(i) <- [| next_loc Float |] - | [| { typ = Int }; { typ = Int } |] -> - (* int64 unboxed *) - let loc1 = next_loc Int in - let loc2 = next_loc Int in - loc.(i) <- [| loc1; loc2 |] - | _ -> - fatal_error "Proc.loc_external_arguments: cannot call" - done; - (* Keep stack 8-aligned *) - (loc, Misc.align (!ofs + 4) 8) - -let loc_external_results res = - let (loc, _ofs) = calling_conventions 0 1 100 100 not_supported res in loc - -let loc_exn_bucket = phys_reg 0 (* $o0 *) - -(* Volatile registers: none *) - -let regs_are_volatile _rs = false - -(* Registers destroyed by operations *) - -let destroyed_at_c_call = (* %l0-%l4, %i0-%i5 preserved *) - Array.of_list(List.map phys_reg - [0; 1; 2; 3; 4; 5; 17; 18; - 100; 101; 102; 103; 104; 105; 106; 107; - 108; 109; 110; 111; 112; 113; 114]) - -let destroyed_at_oper = function - Iop(Icall_ind _ | Icall_imm _ | Iextcall { alloc = true; }) -> - all_phys_regs - | Iop(Iextcall { alloc = false; }) -> destroyed_at_c_call - | _ -> [||] - -let destroyed_at_raise = all_phys_regs - -(* Maximal register pressure *) - -let safe_register_pressure = function - Iextcall _ -> 0 - | _ -> 15 - -let max_register_pressure = function - Iextcall _ -> [| 11; 0 |] - | _ -> [| 19; 15 |] - -(* Pure operations (without any side effect besides updating their result - registers). *) - -let op_is_pure = function - | Icall_ind _ | Icall_imm _ | Itailcall_ind _ | Itailcall_imm _ - | Iextcall _ | Istackoffset _ | Istore _ | Ialloc _ - | Iintop(Icheckbound _) | Iintop_imm(Icheckbound _, _) -> false - | _ -> true - -(* Layout of the stack *) - -let num_stack_slots = [| 0; 0 |] -let contains_calls = ref false - -(* Calling the assembler and the archiver *) - -let assemble_file infile outfile = - let asflags = begin match !arch_version with - SPARC_V7 -> " -o " - | SPARC_V8 -> " -xarch=v8 -o " - | SPARC_V9 -> " -xarch=v8plus -o " - end in - Ccomp.command (Config.asm ^ asflags ^ - Filename.quote outfile ^ " " ^ Filename.quote infile) - -let init () = () diff --git a/asmcomp/sparc/reload.ml b/asmcomp/sparc/reload.ml deleted file mode 100644 index 356dc7f12a..0000000000 --- a/asmcomp/sparc/reload.ml +++ /dev/null @@ -1,19 +0,0 @@ -(**************************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 Institut National de Recherche en Informatique et *) -(* en Automatique. *) -(* *) -(* All rights reserved. This file is distributed under the terms of *) -(* the GNU Lesser General Public License version 2.1, with the *) -(* special exception on linking described in the file LICENSE. *) -(* *) -(**************************************************************************) - -(* Reloading for the Sparc *) - -let fundecl f = - (new Reloadgen.reload_generic)#fundecl f diff --git a/asmcomp/sparc/scheduling.ml b/asmcomp/sparc/scheduling.ml deleted file mode 100644 index c169b47501..0000000000 --- a/asmcomp/sparc/scheduling.ml +++ /dev/null @@ -1,63 +0,0 @@ -(**************************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 Institut National de Recherche en Informatique et *) -(* en Automatique. *) -(* *) -(* All rights reserved. This file is distributed under the terms of *) -(* the GNU Lesser General Public License version 2.1, with the *) -(* special exception on linking described in the file LICENSE. *) -(* *) -(**************************************************************************) - -open Cmm -open Mach - -(* Instruction scheduling for the Sparc *) - -class scheduler = object - -inherit Schedgen.scheduler_generic - -(* Latencies (in cycles). *) - -(* UltraSPARC issues two integer operations, plus a single load or store, - per cycle. At most one of the integer instructions may be a shift. - Most integer operations have one cycle latency. Unsigned loads take - two cycles. Signed loads take three cycles. Conditional moves have - two cycle latency and may not issue in the same cycle as any other - instruction. Floating point issue rules are complicated, but in - general independent add and multiply can dual issue with four cycle - latency. *) - -method oper_latency = function - Ireload -> 2 - | Iload((Byte_signed|Sixteen_signed|Thirtytwo_signed), _) -> 3 - | Iload(_, _) -> 2 - | Iconst_float _ -> 2 (* turned into a load *) - | Inegf | Iabsf | Iaddf | Isubf | Imulf -> 4 - | Idivf -> 15 - | _ -> 1 - -(* Issue cycles. Rough approximations. *) - -method oper_issue_cycles = function - Iconst_float _ -> 2 - | Iconst_symbol _ -> 2 - | Ialloc _ -> 6 - | Iintop(Icomp _) -> 4 - | Iintop(Icheckbound _) -> 2 - | Iintop_imm(Icomp _, _) -> 4 - | Iintop_imm(Icheckbound _, _) -> 2 - | Inegf -> 2 - | Iabsf -> 2 - | Ifloatofint -> 6 - | Iintoffloat -> 6 - | _ -> 1 - -end - -let fundecl f = (new scheduler)#schedule_fundecl f diff --git a/asmcomp/sparc/selection.ml b/asmcomp/sparc/selection.ml deleted file mode 100644 index 1083aa38e1..0000000000 --- a/asmcomp/sparc/selection.ml +++ /dev/null @@ -1,80 +0,0 @@ -(**************************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1997 Institut National de Recherche en Informatique et *) -(* en Automatique. *) -(* *) -(* All rights reserved. This file is distributed under the terms of *) -(* the GNU Lesser General Public License version 2.1, with the *) -(* special exception on linking described in the file LICENSE. *) -(* *) -(**************************************************************************) - -(* Instruction selection for the Sparc processor *) - -open Cmm -open Reg -open Arch -open Mach - -class selector = object (self) - -inherit Selectgen.selector_generic as super - -method is_immediate n = (n <= 4095) && (n >= -4096) - -method select_addressing _chunk = function - Cconst_symbol s -> - (Ibased(s, 0), Ctuple []) - | Cop((Caddv | Cadda), [Cconst_symbol s; Cconst_int n], _) -> - (Ibased(s, n), Ctuple []) - | Cop((Caddv | Cadda), [arg; Cconst_int n], _) -> - (Iindexed n, arg) - | Cop((Caddv | Cadda as op), - [arg1; Cop(Caddi, [arg2; Cconst_int n], _)], dbg) -> - (Iindexed n, Cop(op, [arg1; arg2], dbg)) - | arg -> - (Iindexed 0, arg) - -method private iextcall (func, alloc) = - Iextcall { func; alloc; label_after = Cmm.new_label (); } - -method! select_operation op args dbg = - match (op, args) with - (* For SPARC V7 multiplication, division and modulus are turned into - calls to C library routines. - For SPARC V8 and V9, use hardware multiplication and division, - but C library routine for modulus. *) - (Cmuli, _) when !arch_version = SPARC_V7 -> - (self#iextcall(".umul", false), args) - | (Cdivi, _) when !arch_version = SPARC_V7 -> - (self#iextcall(".div", false), args) - | (Cmodi, _) -> - (self#iextcall(".rem", false), args) - | _ -> - super#select_operation op args dbg - -(* Override insert_move_args to deal correctly with floating-point - arguments being passed into pairs of integer registers. *) -method! insert_move_args arg loc stacksize = - if stacksize <> 0 then self#insert (Iop(Istackoffset stacksize)) [||] [||]; - let locpos = ref 0 in - for i = 0 to Array.length arg - 1 do - let src = arg.(i) in - let dst = loc.(!locpos) in - match (src, dst) with - ({typ = Float}, {typ = Int}) -> - let dst2 = loc.(!locpos + 1) in - self#insert (Iop Imove) [|src|] [|dst; dst2|]; - locpos := !locpos + 2 - | (_, _) -> - self#insert_move src dst; - incr locpos - done - -end - -let fundecl f = (new selector)#emit_fundecl f |