aboutsummaryrefslogtreecommitdiffstats
path: root/powerpc
diff options
context:
space:
mode:
Diffstat (limited to 'powerpc')
-rw-r--r--powerpc/CBuiltins.ml69
-rw-r--r--powerpc/PrintAsm.ml110
-rw-r--r--powerpc/eabi/CPragmas.ml69
3 files changed, 209 insertions, 39 deletions
diff --git a/powerpc/CBuiltins.ml b/powerpc/CBuiltins.ml
new file mode 100644
index 00000000..65cd5b4f
--- /dev/null
+++ b/powerpc/CBuiltins.ml
@@ -0,0 +1,69 @@
+(* *********************************************************************)
+(* *)
+(* The Compcert verified compiler *)
+(* *)
+(* Xavier Leroy, INRIA Paris-Rocquencourt *)
+(* *)
+(* Copyright Institut National de Recherche en Informatique et en *)
+(* Automatique. All rights reserved. This file is distributed *)
+(* under the terms of the GNU General Public License as published by *)
+(* the Free Software Foundation, either version 2 of the License, or *)
+(* (at your option) any later version. This file is also distributed *)
+(* under the terms of the INRIA Non-Commercial License Agreement. *)
+(* *)
+(* *********************************************************************)
+
+(* Processor-dependent builtin C functions *)
+
+open Cparser
+open C
+
+let builtins = {
+ Builtins.typedefs = [];
+ Builtins.functions = [
+ (* Integer arithmetic *)
+ "__builtin_mulhw",
+ (TInt(IInt, []), [TInt(IInt, []); TInt(IInt, [])], false);
+ "__builtin_mulhwu",
+ (TInt(IUInt, []), [TInt(IUInt, []); TInt(IUInt, [])], false);
+ "__builtin_cntlzw",
+ (TInt(IUInt, []), [TInt(IUInt, [])], false);
+ (* Float arithmetic *)
+ "__builtin_fmadd",
+ (TFloat(FDouble, []),
+ [TFloat(FDouble, []); TFloat(FDouble, []); TFloat(FDouble, [])],
+ false);
+ "__builtin_fmsub",
+ (TFloat(FDouble, []),
+ [TFloat(FDouble, []); TFloat(FDouble, []); TFloat(FDouble, [])],
+ false);
+ "__builtin_fabs",
+ (TFloat(FDouble, []), [TFloat(FDouble, [])], false);
+ "__builtin_fsqrt",
+ (TFloat(FDouble, []), [TFloat(FDouble, [])], false);
+ "__builtin_frsqrte",
+ (TFloat(FDouble, []), [TFloat(FDouble, [])], false);
+ "__builtin_fres",
+ (TFloat(FFloat, []), [TFloat(FFloat, [])], false);
+ "__builtin_fsel",
+ (TFloat(FDouble, []),
+ [TFloat(FDouble, []); TFloat(FDouble, []); TFloat(FDouble, [])],
+ false);
+ (* Memory accesses *)
+ "__builtin_read_int16_reversed",
+ (TInt(IUShort, []), [TPtr(TInt(IUShort, []), [])], false);
+ "__builtin_read_int32_reversed",
+ (TInt(IUInt, []), [TPtr(TInt(IUInt, []), [])], false);
+ "__builtin_write_int16_reversed",
+ (TVoid [], [TPtr(TInt(IUShort, []), []); TInt(IUShort, [])], false);
+ "__builtin_write_int32_reversed",
+ (TVoid [], [TPtr(TInt(IUInt, []), []); TInt(IUInt, [])], false);
+ (* Synchronization *)
+ "__builtin_eieio",
+ (TVoid [], [], false);
+ "__builtin_sync",
+ (TVoid [], [], false);
+ "__builtin_isync",
+ (TVoid [], [], false)
+ ]
+}
diff --git a/powerpc/PrintAsm.ml b/powerpc/PrintAsm.ml
index d69d0aff..69cbc173 100644
--- a/powerpc/PrintAsm.ml
+++ b/powerpc/PrintAsm.ml
@@ -212,6 +212,100 @@ let rolm_mask n =
assert (!count = 2 || (!count = 0 && !last));
(!mb, !me-1)
+(* Built-in functions *)
+
+let re_builtin_function = Str.regexp "__builtin_"
+
+let is_builtin_function s =
+ Str.string_match re_builtin_function (extern_atom s) 0
+
+let print_builtin_function oc s =
+ (* int args: GPR3, GPR4 float args: FPR1, FPR2, FPR3
+ int res: GPR3 float res: FPR1
+ Watch out for MacOSX/EABI incompatibility: functions that take
+ some floats then some ints. There are none here. *)
+ match extern_atom s with
+ (* Volatile reads *)
+ | "__builtin_volatile_read_int8unsigned" ->
+ fprintf oc " lbz %a, 0(%a)\n" ireg GPR3 ireg GPR3
+ | "__builtin_volatile_read_int8signed" ->
+ fprintf oc " lbz %a, 0(%a)\n" ireg GPR3 ireg GPR3;
+ fprintf oc " extsb %a, %a\n" ireg GPR3 ireg GPR3
+ | "__builtin_volatile_read_int16unsigned" ->
+ fprintf oc " lhz %a, 0(%a)\n" ireg GPR3 ireg GPR3
+ | "__builtin_volatile_read_int16signed" ->
+ fprintf oc " lha %a, 0(%a)\n" ireg GPR3 ireg GPR3
+ | "__builtin_volatile_read_int32"
+ | "__builtin_volatile_read_pointer" ->
+ fprintf oc " lwz %a, 0(%a)\n" ireg GPR3 ireg GPR3
+ | "__builtin_volatile_read_float32" ->
+ fprintf oc " lfs %a, 0(%a)\n" freg FPR1 ireg GPR3
+ | "__builtin_volatile_read_float64" ->
+ fprintf oc " lfd %a, 0(%a)\n" freg FPR1 ireg GPR3
+ (* Volatile writes *)
+ | "__builtin_volatile_write_int8unsigned"
+ | "__builtin_volatile_write_int8signed" ->
+ fprintf oc " stb %a, 0(%a)\n" ireg GPR4 ireg GPR3
+ | "__builtin_volatile_write_int16unsigned"
+ | "__builtin_volatile_write_int16signed" ->
+ fprintf oc " sth %a, 0(%a)\n" ireg GPR4 ireg GPR3
+ | "__builtin_volatile_write_int32"
+ | "__builtin_volatile_write_pointer" ->
+ fprintf oc " stw %a, 0(%a)\n" ireg GPR4 ireg GPR3
+ | "__builtin_volatile_write_float32" ->
+ fprintf oc " frsp %a, %a\n" freg FPR1 freg FPR1;
+ fprintf oc " stfs %a, 0(%a)\n" freg FPR1 ireg GPR3
+ | "__builtin_volatile_write_float64" ->
+ fprintf oc " stfd %a, 0(%a)\n" freg FPR1 ireg GPR3
+ (* Integer arithmetic *)
+ | "__builtin_mulhw" ->
+ fprintf oc " mulhw %a, %a, %a\n" ireg GPR3 ireg GPR3 ireg GPR4
+ | "__builtin_mulhwu" ->
+ fprintf oc " mulhwu %a, %a, %a\n" ireg GPR3 ireg GPR3 ireg GPR4
+ | "__builtin_cntlzw" ->
+ fprintf oc " cntlzw %a, %a\n" ireg GPR3 ireg GPR3
+ (* Float arithmetic *)
+ | "__builtin_fmadd" ->
+ fprintf oc " fmadd %a, %a, %a, %a\n"
+ freg FPR1 freg FPR1 freg FPR2 freg FPR3
+ | "__builtin_fmsub" ->
+ fprintf oc " fmsub %a, %a, %a, %a\n"
+ freg FPR1 freg FPR1 freg FPR2 freg FPR3
+ | "__builtin_fabs" ->
+ fprintf oc " fabs %a, %a\n" freg FPR1 freg FPR1
+ | "__builtin_fsqrt" ->
+ fprintf oc " fsqrt %a, %a\n" freg FPR1 freg FPR1
+ | "__builtin_frsqrte" ->
+ fprintf oc " frsqrte %a, %a\n" freg FPR1 freg FPR1
+ | "__builtin_fres" ->
+ fprintf oc " fres %a, %a\n" freg FPR1 freg FPR1
+ | "__builtin_fsel" ->
+ fprintf oc " fsel %a, %a, %a, %a\n"
+ freg FPR1 freg FPR1 freg FPR2 freg FPR3
+ (* Memory accesses *)
+ | "__builtin_read_int16_reversed" ->
+ fprintf oc " lhbrx %a, %a, %a\n"
+ ireg GPR3 ireg_or_zero GPR0 ireg GPR3
+ | "__builtin_read_int32_reversed" ->
+ fprintf oc " lwbrx %a, %a, %a\n"
+ ireg GPR3 ireg_or_zero GPR0 ireg GPR3
+ | "__builtin_write_int16_reversed" ->
+ fprintf oc " sthbrx %a, %a, %a\n"
+ ireg GPR4 ireg_or_zero GPR0 ireg GPR3
+ | "__builtin_write_int32_reversed" ->
+ fprintf oc " stwbrx %a, %a, %a\n"
+ ireg GPR4 ireg_or_zero GPR0 ireg GPR3
+ (* Synchronization *)
+ | "__builtin_eieio" ->
+ fprintf oc " eieio\n"
+ | "__builtin_sync" ->
+ fprintf oc " sync\n"
+ | "__builtin_isync" ->
+ fprintf oc " isync\n"
+ (* Catch-all *)
+ | s ->
+ invalid_arg ("unrecognized builtin function " ^ s)
+
(* Printing of instructions *)
module Labelset = Set.Make(struct type t = label let compare = compare end)
@@ -251,9 +345,17 @@ let print_instruction oc labels = function
| Pbf(bit, lbl) ->
fprintf oc " bf %a, %a\n" crbit bit label (transl_label lbl)
| Pbl s ->
- fprintf oc " bl %a\n" symbol s
+ if not (is_builtin_function s) then
+ fprintf oc " bl %a\n" symbol s
+ else
+ print_builtin_function oc s
| Pbs s ->
- fprintf oc " b %a\n" symbol s
+ if not (is_builtin_function s) then
+ fprintf oc " b %a\n" symbol s
+ else begin
+ print_builtin_function oc s;
+ fprintf oc " blr\n"
+ end
| Pblr ->
fprintf oc " blr\n"
| Pbt(bit, lbl) ->
@@ -653,13 +755,13 @@ let stub_function =
let print_fundef oc (Coq_pair(name, defn)) =
match defn with
| Internal code -> print_function oc name code
- | External ef -> stub_function oc name ef
+ | External ef -> if not(is_builtin_function name) then stub_function oc name ef
let record_extfun (Coq_pair(name, defn)) =
match defn with
| Internal _ -> ()
| External _ ->
- if function_needs_stub name then
+ if function_needs_stub name && not (is_builtin_function name) then
stubbed_functions := IdentSet.add name !stubbed_functions
let print_init oc = function
diff --git a/powerpc/eabi/CPragmas.ml b/powerpc/eabi/CPragmas.ml
index d4b79b52..4bb7786e 100644
--- a/powerpc/eabi/CPragmas.ml
+++ b/powerpc/eabi/CPragmas.ml
@@ -16,8 +16,8 @@
(* Platform-dependent handling of pragmas *)
open Printf
-open Cil
open Camlcoq
+open Cparser
type section_info = {
sec_name_init: string;
@@ -94,7 +94,7 @@ let process_use_section_pragma classname id =
let info = Hashtbl.find section_table classname in
Hashtbl.add use_section_table (intern_string id) info
with Not_found ->
- Cil2Csyntax.error (sprintf "unknown section name `%s'" classname)
+ C2Clight.error (sprintf "unknown section name `%s'" classname)
let default_use_section id classname =
if not (Hashtbl.mem use_section_table id) then begin
@@ -104,23 +104,25 @@ let default_use_section id classname =
Hashtbl.add use_section_table id info
end
-let define_function id v =
+let define_function id d =
default_use_section id "CODE"
-let define_stringlit id v =
+let define_stringlit id =
default_use_section id "STRING"
-let define_variable id v =
- let sz = Cil.bitsSizeOf v.vtype / 8 in
+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 Cil2Csyntax.var_is_readonly v then
- if sz <= !Clflags.option_small_const then "SCONST" else "CONST"
+ if C2Clight.atom_is_readonly id then
+ if is_small !Clflags.option_small_const then "SCONST" else "CONST"
else
- if sz <= !Clflags.option_small_data then "SDATA" else "DATA" in
+ if is_small !Clflags.option_small_data then "SDATA" else "DATA" in
default_use_section id sect
-(* CIL does not parse the "section" and "use_section" pragmas, which
- have irregular syntax, so we parse them using regexps *)
+(* Parsing of pragmas using regexps *)
let re_start_pragma_section = Str.regexp "section\\b"
@@ -142,7 +144,7 @@ let re_pragma_use_section = Str.regexp
let re_split_idents = Str.regexp "[ \t,]+"
-let process_pragma (Attr(name, _)) =
+let process_pragma name =
if Str.string_match re_pragma_section name 0 then begin
process_section_pragma
(Str.matched_group 1 name) (* classname *)
@@ -152,44 +154,41 @@ let process_pragma (Attr(name, _)) =
(Str.matched_group 5 name); (* accmode *)
true
end else if Str.string_match re_start_pragma_section name 0 then
- Cil2Csyntax.error "ill-formed `section' pragma"
+ (C2Clight.error "ill-formed `section' pragma"; true)
else if Str.string_match re_pragma_use_section name 0 then begin
let classname = Str.matched_group 1 name
and idents = Str.matched_group 2 name in
let identlist = Str.split re_split_idents idents in
- if identlist = [] then Cil2Csyntax.warning "vacuous `use_section' pragma";
+ if identlist = [] then C2Clight.warning "vacuous `use_section' pragma";
List.iter (process_use_section_pragma classname) identlist;
true
end else if Str.string_match re_start_pragma_use_section name 0 then
- Cil2Csyntax.error "ill-formed `use_section' pragma"
+ (C2Clight.error "ill-formed `use_section' pragma"; true)
else
false
let initialize () =
- Cil2Csyntax.process_pragma_hook := process_pragma;
- Cil2Csyntax.define_variable_hook := define_variable;
- Cil2Csyntax.define_function_hook := define_function;
- Cil2Csyntax.define_stringlit_hook := define_stringlit
+ 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 =
- begin try
- let v = Hashtbl.find Cil2Csyntax.varinfo_atom a in
- let sz = Cil.bitsSizeOf v.vtype / 8 in
- 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 Cil2Csyntax.var_is_readonly v
- then sz <= !Clflags.option_small_const
- else sz <= !Clflags.option_small_data
- end else
- false
- with Not_found ->
- false
- end
+ 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 *)