diff options
Diffstat (limited to 'powerpc')
-rw-r--r-- | powerpc/PrintAsm.ml | 140 | ||||
-rw-r--r-- | powerpc/eabi/CPragmas.ml | 154 | ||||
-rw-r--r-- | powerpc/extractionMachdep.v | 2 | ||||
-rw-r--r-- | powerpc/macosx/CPragmas.ml | 7 |
4 files changed, 99 insertions, 204 deletions
diff --git a/powerpc/PrintAsm.ml b/powerpc/PrintAsm.ml index 8dab7ae..1fdb1a9 100644 --- a/powerpc/PrintAsm.ml +++ b/powerpc/PrintAsm.ml @@ -15,6 +15,7 @@ open Printf open Datatypes open Camlcoq +open Sections open AST open Asm @@ -177,28 +178,58 @@ let creg oc r = | MacOS|Diab -> fprintf oc "cr%d" r | Linux -> fprintf oc "%d" r -let section oc name = - fprintf oc " %s\n" name - (* Names of sections *) -let (text, data, const_data, float_literal) = +let name_of_section_MacOS = function + | Section_text -> ".text" + | Section_data _ -> ".data" + | Section_small_data _ -> ".data" + | Section_const -> ".const" + | Section_small_const -> ".const" + | Section_string -> ".const" + | Section_literal -> ".const_data" + | Section_jumptable -> ".text" + | Section_user _ -> assert false + +let name_of_section_Linux = function + | Section_text -> ".text" + | Section_data i -> if i then ".data" else ".bss" + | Section_small_data i -> if i then ".sdata" else ".sbss" + | Section_const -> ".rodata" + | Section_small_const -> ".sdata2" + | Section_string -> ".rodata" + | Section_literal -> ".section .rodata.cst8,\"aM\",@progbits,8" + | Section_jumptable -> ".text" + | Section_user(s, wr, ex) -> + sprintf ".section %s,\"a%s%s\",@progbits" + s (if wr then "w" else "") (if ex then "x" else "") + +let name_of_section_Diab = function + | Section_text -> ".text" + | Section_data i -> if i then ".data" else ".bss" + | Section_small_data i -> if i then ".sdata" else ".sbss" + | Section_const -> ".text" + | Section_small_const -> ".sdata2" + | Section_string -> ".text" + | Section_literal -> ".text" + | Section_jumptable -> ".text" + | Section_user(s, wr, ex) -> + sprintf ".section %s,,%c" + s + (match wr, ex with + | true, true -> 'm' (* text+data *) + | true, false -> 'd' (* data *) + | false, true -> 'c' (* text *) + | false, false -> 'r') (* const *) + +let name_of_section = match target with - | MacOS -> - (".text", - ".data", - ".const", - ".const_data") - | Linux -> - (".text", - ".data", - ".rodata", - ".section .rodata.cst8,\"aM\",@progbits,8") - | Diab -> - (".text", - ".data", - ".text", - ".text") + | MacOS -> name_of_section_MacOS + | Linux -> name_of_section_Linux + | Diab -> name_of_section_Diab + +let section oc sec = + fprintf oc " %s\n" (name_of_section sec) (* Encoding masks for rlwinm instructions *) @@ -353,6 +384,9 @@ let print_builtin_function oc s = module Labelset = Set.Make(struct type t = label let compare = compare end) +let float_literals : (int * int64) list ref = ref [] +let jumptables : (int * label list) list ref = ref [] + let print_instruction oc labels = function | Padd(r1, r2, r3) -> fprintf oc " add %a, %a, %a\n" ireg r1 ireg r2 ireg r3 @@ -410,10 +444,7 @@ let print_instruction oc labels = function fprintf oc " lwz %a, %a(%a)\n" ireg GPR12 label_low lbl ireg GPR12; fprintf oc " mtctr %a\n" ireg GPR12; fprintf oc " bctr\n"; - fprintf oc "%a:" label lbl; - List.iter - (fun l -> fprintf oc " .long %a\n" label (transl_label l)) - tbl; + jumptables := (lbl, tbl) :: !jumptables; fprintf oc "%s end pseudoinstr btbl\n" comment | Pcmplw(r1, r2) -> fprintf oc " cmplw %a, %a, %a\n" creg 0 ireg r1 ireg r2 @@ -471,9 +502,7 @@ let print_instruction oc labels = function fprintf oc " lwz %a, 4(%a)\n" ireg r1 ireg GPR1; fprintf oc " addis %a, %a, 0x8000\n" ireg r1 ireg r1; fprintf oc "%a: addi %a, %a, 8\n" label lbl3 ireg GPR1 ireg GPR1; - section oc float_literal; - fprintf oc "%a: .long 0x41e00000, 0x00000000\n" label lbl1; - section oc text; + float_literals := (lbl1, 0x41e00000_00000000L) :: !float_literals; fprintf oc "%s end pseudoinstr fctiu\n" comment | Pfdiv(r1, r2, r3) -> fprintf oc " fdiv %a, %a, %a\n" freg r1 freg r2 freg r3 @@ -503,9 +532,7 @@ let print_instruction oc labels = function fprintf oc " lfd %a, 0(%a)\n" freg r1 ireg GPR1; fprintf oc " addi %a, %a, 8\n" ireg GPR1 ireg GPR1; fprintf oc " fsub %a, %a, %a\n" freg r1 freg r1 freg FPR13; - section oc float_literal; - fprintf oc "%a: .long 0x43300000, 0x80000000\n" label lbl; - section oc text; + float_literals := (lbl, 0x43300000_80000000L) :: !float_literals; fprintf oc "%s end pseudoinstr ictf\n" comment | Piuctf(r1, r2) -> let lbl = new_label() in @@ -518,9 +545,7 @@ let print_instruction oc labels = function fprintf oc " lfd %a, 0(%a)\n" freg r1 ireg GPR1; fprintf oc " addi %a, %a, 8\n" ireg GPR1 ireg GPR1; fprintf oc " fsub %a, %a, %a\n" freg r1 freg r1 freg FPR13; - section oc float_literal; - fprintf oc "%a: .long 0x43300000, 0x00000000\n" label lbl; - section oc text; + float_literals := (lbl, 0x43300000_00000000L) :: !float_literals; fprintf oc "%s end pseudoinstr ictf\n" comment | Plbz(r1, c, r2) -> fprintf oc " lbz %a, %a(%a)\n" ireg r1 constant c ireg r2 @@ -533,14 +558,8 @@ let print_instruction oc labels = function | Plfi(r1, c) -> let lbl = new_label() in fprintf oc " addis %a, 0, %a\n" ireg GPR12 label_high lbl; - fprintf oc " lfd %a, %a(%a)\n" freg r1 label_low lbl ireg GPR12; - section oc float_literal; - let n = Int64.bits_of_float c in - let nlo = Int64.to_int32 n - and nhi = Int64.to_int32(Int64.shift_right_logical n 32) in - fprintf oc "%a: .long 0x%lx, 0x%lx %s %.18g\n" - label lbl nhi nlo comment c; - section oc text + fprintf oc " lfd %a, %a(%a) %s %.18g\n" freg r1 label_low lbl ireg GPR12 comment c; + float_literals := (lbl, Int64.bits_of_float c) :: !float_literals; | Plfs(r1, c, r2) -> fprintf oc " lfs %a, %a(%a)\n" freg r1 constant c ireg r2 | Plfsx(r1, r2, r3) -> @@ -633,6 +652,17 @@ let print_instruction oc labels = function if Labelset.mem lbl labels then fprintf oc "%a:\n" label (transl_label lbl) +let print_literal oc (lbl, n) = + let nlo = Int64.to_int32 n + and nhi = Int64.to_int32(Int64.shift_right_logical n 32) in + fprintf oc "%a: .long 0x%lx, 0x%lx\n" label lbl nhi nlo + +let print_jumptable oc (lbl, tbl) = + fprintf oc "%a:" label lbl; + List.iter + (fun l -> fprintf oc " .long %a\n" label (transl_label l)) + tbl + let rec labels_of_code accu = function | [] -> accu @@ -645,10 +675,10 @@ let rec labels_of_code accu = function let print_function oc name code = Hashtbl.clear current_function_labels; - section oc - (match CPragmas.section_for_atom name true with - | Some s -> s - | None -> text); + float_literals := []; + jumptables := []; + let (text, lit, jmptbl) = sections_for_function name in + section oc text; fprintf oc " .align 2\n"; if not (C2Clight.atom_is_static name) then fprintf oc " .globl %a\n" symbol name; @@ -657,6 +687,16 @@ let print_function oc name code = if target <> MacOS then begin fprintf oc " .type %a, @function\n" symbol name; fprintf oc " .size %a, . - %a\n" symbol name symbol name + end; + if !float_literals <> [] then begin + section oc lit; + List.iter (print_literal oc) !float_literals; + float_literals := [] + end; + if !jumptables <> [] then begin + section oc jmptbl; + List.iter (print_jumptable oc) !jumptables; + jumptables := [] end (* Generation of stub functions *) @@ -761,7 +801,7 @@ let non_variadic_stub oc name = let stub_function oc name ef = let name = extern_atom name in - fprintf oc " .text\n"; + section oc Section_text; fprintf oc " .align 2\n"; fprintf oc "L%s$stub:\n" name; if Str.string_match re_variadic_stub name 0 @@ -777,7 +817,7 @@ end module Stubs_EABI = struct let variadic_stub oc stub_name fun_name args = - fprintf oc " .text\n"; + section oc Section_text; fprintf oc " .align 2\n"; fprintf oc ".L%s$stub:\n" stub_name; (* bit 6 must be set if at least one argument is a float; clear otherwise *) @@ -829,7 +869,6 @@ let print_init oc = function | Init_float32 n -> fprintf oc " .long %ld %s %.18g\n" (Int32.bits_of_float n) comment n | Init_float64 n -> - (* .quad not working on all versions of the MacOSX assembler *) let b = Int64.bits_of_float n in fprintf oc " .long %Ld, %Ld %s %.18g\n" (Int64.shift_right_logical b 32) @@ -857,12 +896,7 @@ let print_var oc (Coq_pair(Coq_pair(name, init_data), _)) = let init = match init_data with [Init_space _] -> false | _ -> true in let sec = - match CPragmas.section_for_atom name init with - | Some s -> s - | None -> - if C2Clight.atom_is_readonly name - then const_data - else data + Sections.section_for_variable name init and align = match C2Clight.atom_alignof name with | Some a -> log2 a diff --git a/powerpc/eabi/CPragmas.ml b/powerpc/eabi/CPragmas.ml index 3104cc8..7dbc215 100644 --- a/powerpc/eabi/CPragmas.ml +++ b/powerpc/eabi/CPragmas.ml @@ -19,111 +19,23 @@ open Printf open Camlcoq open Cparser -type section_info = { - sec_name_init: string; - sec_name_uninit: string; - sec_acc_mode: string; - sec_near_access: bool -} - -let default_section_info = { - sec_name_init = ".data"; - sec_name_uninit = ".data"; (* COMM? *) - sec_acc_mode = "RW"; - sec_near_access = false -} - -let section_table : (string, section_info) Hashtbl.t = - Hashtbl.create 17 - -(* Built-in sections *) - -let _ = - let rodata = - if Configuration.system = "linux" then ".rodata" else ".text" in - List.iter (fun (n, si) -> Hashtbl.add section_table n si) [ - "CODE", {sec_name_init = ".text"; - sec_name_uninit = ".text"; - sec_acc_mode = "RX"; - sec_near_access = false}; - "DATA", {sec_name_init = ".data"; - sec_name_uninit = ".data"; (* COMM? *) - sec_acc_mode = "RW"; - sec_near_access = false}; - "SDATA", {sec_name_init = ".sdata"; - sec_name_uninit = ".sbss"; - sec_acc_mode = "RW"; - sec_near_access = true}; - "CONST", {sec_name_init = rodata; - sec_name_uninit = rodata; - sec_acc_mode = "R"; - sec_near_access = false}; - "SCONST",{sec_name_init = ".sdata2"; - sec_name_uninit = ".sdata2"; - sec_acc_mode = "R"; - sec_near_access = true}; - "STRING",{sec_name_init = rodata; - sec_name_uninit = rodata; - sec_acc_mode = "R"; - sec_near_access = false} - ] - (* #pragma section *) let process_section_pragma classname istring ustring addrmode accmode = - let old_si = - try Hashtbl.find section_table classname - with Not_found -> default_section_info in - let si = - { sec_name_init = - if istring = "" then old_si.sec_name_init else istring; - sec_name_uninit = - if ustring = "" then old_si.sec_name_uninit else ustring; - sec_acc_mode = - if accmode = "" then old_si.sec_acc_mode else accmode; - sec_near_access = - if addrmode = "" - then old_si.sec_near_access - else (addrmode = "near-code") || (addrmode = "near-data") } in - Hashtbl.add section_table classname si + Sections.define_section classname + ?iname: (if istring = "" then None else Some istring) + ?uname: (if ustring = "" then None else Some ustring) + ?writable: (if accmode = "" then None else Some(String.contains accmode 'W')) + ?executable: (if accmode = "" then None else Some(String.contains accmode 'X')) + ?near: (if addrmode = "" then None + else Some(addrmode = "near-code" || addrmode = "near-data")) + () (* #pragma use_section *) -let use_section_table : (AST.ident, section_info) Hashtbl.t = - Hashtbl.create 51 - let process_use_section_pragma classname id = - try - let info = Hashtbl.find section_table classname in - Hashtbl.add use_section_table (intern_string id) info - with Not_found -> - C2Clight.error (sprintf "unknown section name `%s'" classname) - -let default_use_section id classname = - if not (Hashtbl.mem use_section_table id) then begin - let info = - try Hashtbl.find section_table classname - with Not_found -> assert false in - Hashtbl.add use_section_table id info - end - -let define_function id d = - default_use_section id "CODE" - -let define_stringlit id = - default_use_section id "STRING" - -let define_variable id d = - let is_small limit = - match C2Clight.atom_sizeof id with - | None -> false - | Some sz -> sz <= limit in - let sect = - if C2Clight.atom_is_readonly id then - if is_small !Clflags.option_small_const then "SCONST" else "CONST" - else - if is_small !Clflags.option_small_data then "SDATA" else "DATA" in - default_use_section id sect + if not (Sections.use_section_for (intern_string id) classname) + then C2Clight.error (sprintf "unknown section name `%s'" classname) (* #pragma reserve_register *) @@ -193,48 +105,4 @@ let process_pragma name = false let initialize () = - C2Clight.process_pragma_hook := process_pragma; - C2Clight.define_variable_hook := define_variable; - C2Clight.define_function_hook := define_function; - C2Clight.define_stringlit_hook := define_stringlit - -(* PowerPC-specific: say if an atom is in a small data area *) - -let atom_is_small_data a ofs = - match C2Clight.atom_sizeof a with - | None -> false - | Some sz -> - let ofs = camlint_of_coqint ofs in - if ofs >= 0l && ofs < Int32.of_int sz then begin - try - (Hashtbl.find use_section_table a).sec_near_access - with Not_found -> - if C2Clight.atom_is_readonly a - then sz <= !Clflags.option_small_const - else sz <= !Clflags.option_small_data - end else - false - -(* PowerPC-specific: determine section to use for a particular symbol *) - -let section_for_atom a init = - try - let sinfo = Hashtbl.find use_section_table a in - let sname = - if init then sinfo.sec_name_init else sinfo.sec_name_uninit in - if not (String.contains sname '\"') then - Some sname - else begin - (* The following is Diab-specific... *) - let accmode = sinfo.sec_acc_mode in - let is_writable = String.contains accmode 'W' - and is_executable = String.contains accmode 'X' in - let stype = - match is_writable, is_executable with - | true, true -> 'm' (* text+data *) - | true, false -> 'd' (* data *) - | false, true -> 'c' (* text *) - | false, false -> 'r' (* const *) - in Some(sprintf ".section\t%s,,%c" sname stype) - end - with Not_found -> None + C2Clight.process_pragma_hook := process_pragma diff --git a/powerpc/extractionMachdep.v b/powerpc/extractionMachdep.v index 83fda76..a315e8f 100644 --- a/powerpc/extractionMachdep.v +++ b/powerpc/extractionMachdep.v @@ -18,7 +18,7 @@ Extract Constant SelectOp.use_fused_mul => "(fun () -> !Clflags.option_fmadd)". (* Asm *) Extract Constant Asm.low_half => "fun _ -> assert false". Extract Constant Asm.high_half => "fun _ -> assert false". -Extract Constant Asm.symbol_is_small_data => "CPragmas.atom_is_small_data". +Extract Constant Asm.symbol_is_small_data => "Sections.atom_is_small_data". Extract Constant Asm.small_data_area_offset => "fun _ _ _ -> assert false". (* Suppression of stupidly big equality functions *) diff --git a/powerpc/macosx/CPragmas.ml b/powerpc/macosx/CPragmas.ml index f48064c..ede2f38 100644 --- a/powerpc/macosx/CPragmas.ml +++ b/powerpc/macosx/CPragmas.ml @@ -19,10 +19,3 @@ let initialize () = () -(* PowerPC-specific: say if an atom is in a small data area *) - -let atom_is_small_data a ofs = false - -(* PowerPC-specific: determine section to use for a particular symbol *) - -let section_for_atom a init = None |