diff --git a/0001-Add-.gitignore-file-to-ignore-generated-files.patch b/0001-Add-.gitignore-file-to-ignore-generated-files.patch index f94d614..fec77ec 100644 --- a/0001-Add-.gitignore-file-to-ignore-generated-files.patch +++ b/0001-Add-.gitignore-file-to-ignore-generated-files.patch @@ -1,7 +1,7 @@ From 07839dfc746ccee318601b9668aa094d4465bc6e Mon Sep 17 00:00:00 2001 From: "Richard W.M. Jones" Date: Thu, 7 Jun 2012 16:00:28 +0100 -Subject: [PATCH 1/7] Add .gitignore file to ignore generated files. +Subject: [PATCH 01/11] Add .gitignore file to ignore generated files. --- .gitignore | 347 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ @@ -362,5 +362,5 @@ index 0000000..7191b83 +/yacc/ocamlyacc +/yacc/version.h -- -1.8.3.1 +1.8.4.2 diff --git a/0001-stdlib-arg-Allow-flags-such-as-flag-arg-as-well-as-f.patch b/0001-stdlib-arg-Allow-flags-such-as-flag-arg-as-well-as-f.patch deleted file mode 100644 index 2c4d053..0000000 --- a/0001-stdlib-arg-Allow-flags-such-as-flag-arg-as-well-as-f.patch +++ /dev/null @@ -1,165 +0,0 @@ -From 33962967111fbed55e93260b12cd65e372a0958a Mon Sep 17 00:00:00 2001 -From: "Richard W.M. Jones" -Date: Sat, 9 Nov 2013 09:11:30 +0000 -Subject: [PATCH] stdlib: arg: Allow flags such as --flag=arg as well as --flag - arg. - -Fix for the following issue: -http://caml.inria.fr/mantis/view.php?id=5197 ---- - stdlib/arg.ml | 85 ++++++++++++++++++++++++++++++++++------------------------ - stdlib/arg.mli | 3 ++- - 2 files changed, 52 insertions(+), 36 deletions(-) - -diff --git a/stdlib/arg.ml b/stdlib/arg.ml -index 8b64236..d94b75f 100644 ---- a/stdlib/arg.ml -+++ b/stdlib/arg.ml -@@ -55,6 +55,12 @@ let rec assoc3 x l = - | _ :: t -> assoc3 x t - ;; - -+let split s = -+ let i = String.index s '=' in -+ let len = String.length s in -+ String.sub s 0 i, String.sub s (i+1) (len-(i+1)) -+;; -+ - let make_symlist prefix sep suffix l = - match l with - | [] -> "" -@@ -130,73 +136,82 @@ let parse_argv_dynamic ?(current=current) argv speclist anonfun errmsg = - while !current < l do - let s = argv.(!current) in - if String.length s >= 1 && String.get s 0 = '-' then begin -- let action = -- try assoc3 s !speclist -- with Not_found -> stop (Unknown s) -+ let action, follow = -+ try assoc3 s !speclist, None -+ with Not_found -> -+ try -+ let keyword, arg = split s in -+ assoc3 keyword !speclist, Some arg -+ with Not_found -> stop (Unknown s) -+ in -+ let no_arg () = -+ match follow with -+ | None -> () -+ | Some arg -> stop (Wrong (s, arg, "no argument")) -+ in -+ let get_arg () = -+ match follow with -+ | None -> -+ if !current + 1 < l then begin -+ incr current; -+ argv.(!current) -+ end -+ else stop (Missing s) -+ | Some arg -> arg - in - begin try - let rec treat_action = function -- | Unit f -> f (); -- | Bool f when !current + 1 < l -> -- let arg = argv.(!current + 1) in -+ | Unit f -> no_arg (); f (); -+ | Bool f -> -+ let arg = get_arg () in - begin try f (bool_of_string arg) - with Invalid_argument "bool_of_string" -> - raise (Stop (Wrong (s, arg, "a boolean"))) - end; -- incr current; -- | Set r -> r := true; -- | Clear r -> r := false; -- | String f when !current + 1 < l -> -- f argv.(!current + 1); -- incr current; -- | Symbol (symb, f) when !current + 1 < l -> -- let arg = argv.(!current + 1) in -+ | Set r -> no_arg (); r := true; -+ | Clear r -> no_arg (); r := false; -+ | String f -> -+ f (get_arg ()); -+ | Symbol (symb, f) -> -+ let arg = get_arg () in - if List.mem arg symb then begin -- f argv.(!current + 1); -- incr current; -+ f arg; - end else begin - raise (Stop (Wrong (s, arg, "one of: " - ^ (make_symlist "" " " "" symb)))) - end -- | Set_string r when !current + 1 < l -> -- r := argv.(!current + 1); -- incr current; -- | Int f when !current + 1 < l -> -- let arg = argv.(!current + 1) in -+ | Set_string r -> -+ r := get_arg (); -+ | Int f -> -+ let arg = get_arg () in - begin try f (int_of_string arg) - with Failure "int_of_string" -> - raise (Stop (Wrong (s, arg, "an integer"))) - end; -- incr current; -- | Set_int r when !current + 1 < l -> -- let arg = argv.(!current + 1) in -+ | Set_int r -> -+ let arg = get_arg () in - begin try r := (int_of_string arg) - with Failure "int_of_string" -> - raise (Stop (Wrong (s, arg, "an integer"))) - end; -- incr current; -- | Float f when !current + 1 < l -> -- let arg = argv.(!current + 1) in -+ | Float f -> -+ let arg = get_arg () in - begin try f (float_of_string arg); - with Failure "float_of_string" -> - raise (Stop (Wrong (s, arg, "a float"))) - end; -- incr current; -- | Set_float r when !current + 1 < l -> -- let arg = argv.(!current + 1) in -+ | Set_float r -> -+ let arg = get_arg () in - begin try r := (float_of_string arg); - with Failure "float_of_string" -> - raise (Stop (Wrong (s, arg, "a float"))) - end; -- incr current; - | Tuple specs -> - List.iter treat_action specs; - | Rest f -> - while !current < l - 1 do -- f argv.(!current + 1); -- incr current; -- done; -- | _ -> raise (Stop (Missing s)) -+ f (get_arg ()); -+ done - in - treat_action action - with Bad m -> stop (Message m); -diff --git a/stdlib/arg.mli b/stdlib/arg.mli -index 869d030..b8c6f11 100644 ---- a/stdlib/arg.mli -+++ b/stdlib/arg.mli -@@ -25,7 +25,8 @@ - [Unit], [Set] and [Clear] keywords take no argument. A [Rest] - keyword takes the remaining of the command line as arguments. - Every other keyword takes the following word on the command line -- as argument. -+ as argument. For compatibility with GNU getopt_long, [keyword=arg] -+ is also allowed. - Arguments not preceded by a keyword are called anonymous arguments. - - Examples ([cmd] is assumed to be the command name): --- -1.8.3.1 - diff --git a/0002-Ensure-empty-compilerlibs-directory-is-created-by-gi.patch b/0002-Ensure-empty-compilerlibs-directory-is-created-by-gi.patch index 3166287..21fa682 100644 --- a/0002-Ensure-empty-compilerlibs-directory-is-created-by-gi.patch +++ b/0002-Ensure-empty-compilerlibs-directory-is-created-by-gi.patch @@ -1,7 +1,7 @@ From 7756582741dc56070c03629a3b4640147723beda Mon Sep 17 00:00:00 2001 From: "Richard W.M. Jones" Date: Thu, 7 Jun 2012 15:36:16 +0100 -Subject: [PATCH 2/7] Ensure empty compilerlibs/ directory is created by git. +Subject: [PATCH 02/11] Ensure empty compilerlibs/ directory is created by git. This directory exists in the OCaml tarball, but is empty. As a result, git ignores it unless we put a dummy file in it. @@ -14,5 +14,5 @@ diff --git a/compilerlibs/.exists b/compilerlibs/.exists new file mode 100644 index 0000000..e69de29 -- -1.8.3.1 +1.8.4.2 diff --git a/0003-ocamlbyteinfo-ocamlplugininfo-Useful-utilities-from-.patch b/0003-ocamlbyteinfo-ocamlplugininfo-Useful-utilities-from-.patch index 241f363..6f7cd51 100644 --- a/0003-ocamlbyteinfo-ocamlplugininfo-Useful-utilities-from-.patch +++ b/0003-ocamlbyteinfo-ocamlplugininfo-Useful-utilities-from-.patch @@ -1,7 +1,7 @@ From a6d87cd4bc62d3987835c1ac844f35cc06804294 Mon Sep 17 00:00:00 2001 From: "Richard W.M. Jones" Date: Tue, 29 May 2012 20:40:36 +0100 -Subject: [PATCH 3/7] ocamlbyteinfo, ocamlplugininfo: Useful utilities from +Subject: [PATCH 03/11] ocamlbyteinfo, ocamlplugininfo: Useful utilities from Debian, sent upstream. See: @@ -236,5 +236,5 @@ index 0000000..e28800f + header.units + end -- -1.8.3.1 +1.8.4.2 diff --git a/0004-Don-t-add-rpaths-to-libraries.patch b/0004-Don-t-add-rpaths-to-libraries.patch index 650caf4..1a140ba 100644 --- a/0004-Don-t-add-rpaths-to-libraries.patch +++ b/0004-Don-t-add-rpaths-to-libraries.patch @@ -1,7 +1,7 @@ From c3a733c10827896a6e3c217b383e874df303d50b Mon Sep 17 00:00:00 2001 From: "Richard W.M. Jones" Date: Tue, 29 May 2012 20:43:34 +0100 -Subject: [PATCH 4/7] Don't add rpaths to libraries. +Subject: [PATCH 04/11] Don't add rpaths to libraries. --- tools/Makefile.shared | 3 --- @@ -22,5 +22,5 @@ index 117f576..cad227d 100644 ocamlmklib.mlp >> ocamlmklib.ml -- -1.8.3.1 +1.8.4.2 diff --git a/0005-configure-Allow-user-defined-C-compiler-flags.patch b/0005-configure-Allow-user-defined-C-compiler-flags.patch index 69d80b4..0ae0163 100644 --- a/0005-configure-Allow-user-defined-C-compiler-flags.patch +++ b/0005-configure-Allow-user-defined-C-compiler-flags.patch @@ -1,7 +1,7 @@ From 459e9550f174e11176a2ece013fc4dd2b08a06bb Mon Sep 17 00:00:00 2001 From: "Richard W.M. Jones" Date: Tue, 29 May 2012 20:44:18 +0100 -Subject: [PATCH 5/7] configure: Allow user defined C compiler flags. +Subject: [PATCH 05/11] configure: Allow user defined C compiler flags. --- configure | 4 ++++ @@ -23,5 +23,5 @@ index 07b1c35..39b38dc 100755 cclibs="$cclibs $mathlib" -- -1.8.3.1 +1.8.4.2 diff --git a/0006-Add-support-for-ppc64.patch b/0006-Add-support-for-ppc64.patch index a979555..895d0da 100644 --- a/0006-Add-support-for-ppc64.patch +++ b/0006-Add-support-for-ppc64.patch @@ -1,7 +1,7 @@ From a85437a0d2ffdf7a340d379789500eb583ae4708 Mon Sep 17 00:00:00 2001 From: "Richard W.M. Jones" Date: Tue, 29 May 2012 20:47:07 +0100 -Subject: [PATCH 6/7] Add support for ppc64. +Subject: [PATCH 06/11] Add support for ppc64. Note (1): This patch was rejected upstream because they don't have appropriate hardware for testing. @@ -2126,5 +2126,5 @@ index 39b38dc..9b02664 100755 aspp="$bytecc -c";; sparc,*,solaris) as='as' -- -1.8.3.1 +1.8.4.2 diff --git a/0007-yacc-Use-mkstemp-instead-of-mktemp.patch b/0007-yacc-Use-mkstemp-instead-of-mktemp.patch index 7085935..6055445 100644 --- a/0007-yacc-Use-mkstemp-instead-of-mktemp.patch +++ b/0007-yacc-Use-mkstemp-instead-of-mktemp.patch @@ -1,7 +1,7 @@ From 761242718c3a7513d3b93ca96d24d1f61a4126f0 Mon Sep 17 00:00:00 2001 From: "Richard W.M. Jones" Date: Fri, 13 Sep 2013 21:29:58 +0100 -Subject: [PATCH 7/7] yacc: Use mkstemp instead of mktemp. +Subject: [PATCH 07/11] yacc: Use mkstemp instead of mktemp. --- yacc/main.c | 2 +- @@ -21,5 +21,5 @@ index f6cac60..3067000 100644 #endif -- -1.8.3.1 +1.8.4.2 diff --git a/0008-stdlib-arg-Allow-flags-such-as-flag-arg-as-well-as-f.patch b/0008-stdlib-arg-Allow-flags-such-as-flag-arg-as-well-as-f.patch new file mode 100644 index 0000000..3373cfc --- /dev/null +++ b/0008-stdlib-arg-Allow-flags-such-as-flag-arg-as-well-as-f.patch @@ -0,0 +1,165 @@ +From 33962967111fbed55e93260b12cd65e372a0958a Mon Sep 17 00:00:00 2001 +From: "Richard W.M. Jones" +Date: Sat, 9 Nov 2013 09:11:30 +0000 +Subject: [PATCH 08/11] stdlib: arg: Allow flags such as --flag=arg as well as + --flag arg. + +Fix for the following issue: +http://caml.inria.fr/mantis/view.php?id=5197 +--- + stdlib/arg.ml | 85 ++++++++++++++++++++++++++++++++++------------------------ + stdlib/arg.mli | 3 ++- + 2 files changed, 52 insertions(+), 36 deletions(-) + +diff --git a/stdlib/arg.ml b/stdlib/arg.ml +index 8b64236..d94b75f 100644 +--- a/stdlib/arg.ml ++++ b/stdlib/arg.ml +@@ -55,6 +55,12 @@ let rec assoc3 x l = + | _ :: t -> assoc3 x t + ;; + ++let split s = ++ let i = String.index s '=' in ++ let len = String.length s in ++ String.sub s 0 i, String.sub s (i+1) (len-(i+1)) ++;; ++ + let make_symlist prefix sep suffix l = + match l with + | [] -> "" +@@ -130,73 +136,82 @@ let parse_argv_dynamic ?(current=current) argv speclist anonfun errmsg = + while !current < l do + let s = argv.(!current) in + if String.length s >= 1 && String.get s 0 = '-' then begin +- let action = +- try assoc3 s !speclist +- with Not_found -> stop (Unknown s) ++ let action, follow = ++ try assoc3 s !speclist, None ++ with Not_found -> ++ try ++ let keyword, arg = split s in ++ assoc3 keyword !speclist, Some arg ++ with Not_found -> stop (Unknown s) ++ in ++ let no_arg () = ++ match follow with ++ | None -> () ++ | Some arg -> stop (Wrong (s, arg, "no argument")) ++ in ++ let get_arg () = ++ match follow with ++ | None -> ++ if !current + 1 < l then begin ++ incr current; ++ argv.(!current) ++ end ++ else stop (Missing s) ++ | Some arg -> arg + in + begin try + let rec treat_action = function +- | Unit f -> f (); +- | Bool f when !current + 1 < l -> +- let arg = argv.(!current + 1) in ++ | Unit f -> no_arg (); f (); ++ | Bool f -> ++ let arg = get_arg () in + begin try f (bool_of_string arg) + with Invalid_argument "bool_of_string" -> + raise (Stop (Wrong (s, arg, "a boolean"))) + end; +- incr current; +- | Set r -> r := true; +- | Clear r -> r := false; +- | String f when !current + 1 < l -> +- f argv.(!current + 1); +- incr current; +- | Symbol (symb, f) when !current + 1 < l -> +- let arg = argv.(!current + 1) in ++ | Set r -> no_arg (); r := true; ++ | Clear r -> no_arg (); r := false; ++ | String f -> ++ f (get_arg ()); ++ | Symbol (symb, f) -> ++ let arg = get_arg () in + if List.mem arg symb then begin +- f argv.(!current + 1); +- incr current; ++ f arg; + end else begin + raise (Stop (Wrong (s, arg, "one of: " + ^ (make_symlist "" " " "" symb)))) + end +- | Set_string r when !current + 1 < l -> +- r := argv.(!current + 1); +- incr current; +- | Int f when !current + 1 < l -> +- let arg = argv.(!current + 1) in ++ | Set_string r -> ++ r := get_arg (); ++ | Int f -> ++ let arg = get_arg () in + begin try f (int_of_string arg) + with Failure "int_of_string" -> + raise (Stop (Wrong (s, arg, "an integer"))) + end; +- incr current; +- | Set_int r when !current + 1 < l -> +- let arg = argv.(!current + 1) in ++ | Set_int r -> ++ let arg = get_arg () in + begin try r := (int_of_string arg) + with Failure "int_of_string" -> + raise (Stop (Wrong (s, arg, "an integer"))) + end; +- incr current; +- | Float f when !current + 1 < l -> +- let arg = argv.(!current + 1) in ++ | Float f -> ++ let arg = get_arg () in + begin try f (float_of_string arg); + with Failure "float_of_string" -> + raise (Stop (Wrong (s, arg, "a float"))) + end; +- incr current; +- | Set_float r when !current + 1 < l -> +- let arg = argv.(!current + 1) in ++ | Set_float r -> ++ let arg = get_arg () in + begin try r := (float_of_string arg); + with Failure "float_of_string" -> + raise (Stop (Wrong (s, arg, "a float"))) + end; +- incr current; + | Tuple specs -> + List.iter treat_action specs; + | Rest f -> + while !current < l - 1 do +- f argv.(!current + 1); +- incr current; +- done; +- | _ -> raise (Stop (Missing s)) ++ f (get_arg ()); ++ done + in + treat_action action + with Bad m -> stop (Message m); +diff --git a/stdlib/arg.mli b/stdlib/arg.mli +index 869d030..b8c6f11 100644 +--- a/stdlib/arg.mli ++++ b/stdlib/arg.mli +@@ -25,7 +25,8 @@ + [Unit], [Set] and [Clear] keywords take no argument. A [Rest] + keyword takes the remaining of the command line as arguments. + Every other keyword takes the following word on the command line +- as argument. ++ as argument. For compatibility with GNU getopt_long, [keyword=arg] ++ is also allowed. + Arguments not preceded by a keyword are called anonymous arguments. + + Examples ([cmd] is assumed to be the command name): +-- +1.8.4.2 + diff --git a/0009-Port-to-the-ARM-64-bits-AArch64-architecture-experim.patch b/0009-Port-to-the-ARM-64-bits-AArch64-architecture-experim.patch new file mode 100644 index 0000000..e2d8ebb --- /dev/null +++ b/0009-Port-to-the-ARM-64-bits-AArch64-architecture-experim.patch @@ -0,0 +1,2280 @@ +From 10d852d542f4ecdc5efc5afbae2d42167df4539c Mon Sep 17 00:00:00 2001 +From: Xavier Leroy +Date: Thu, 18 Jul 2013 16:09:20 +0000 +Subject: [PATCH 09/11] Port to the ARM 64-bits (AArch64) architecture + (experimental). Merge of branch branches/arm64. + +git-svn-id: http://caml.inria.fr/svn/ocaml/trunk@13909 f963ae5c-01c2-4b8c-9fe0-0dff7051ff02 +(cherry picked from commit 055d5c0379e42b4f561cb1fc5159659d8e9a7b6f) +--- + asmcomp/arm64/arch.ml | 146 ++++++++ + asmcomp/arm64/emit.mlp | 742 +++++++++++++++++++++++++++++++++++++++ + asmcomp/arm64/proc.ml | 212 +++++++++++ + asmcomp/arm64/reload.ml | 16 + + asmcomp/arm64/scheduling.ml | 18 + + asmcomp/arm64/selection.ml | 265 ++++++++++++++ + asmcomp/compilenv.ml | 9 + + asmcomp/compilenv.mli | 4 + + asmrun/arm64.S | 535 ++++++++++++++++++++++++++++ + asmrun/signals_osdep.h | 19 + + asmrun/stack.h | 5 + + byterun/interp.c | 6 + + configure | 5 +- + otherlibs/num/bng.c | 6 +- + otherlibs/num/bng_arm64.c | 20 ++ + testsuite/tests/asmcomp/Makefile | 2 +- + testsuite/tests/asmcomp/arm64.S | 52 +++ + testsuite/tests/asmcomp/main.ml | 1 + + 18 files changed, 2057 insertions(+), 6 deletions(-) + create mode 100644 asmcomp/arm64/arch.ml + create mode 100644 asmcomp/arm64/emit.mlp + create mode 100644 asmcomp/arm64/proc.ml + create mode 100644 asmcomp/arm64/reload.ml + create mode 100644 asmcomp/arm64/scheduling.ml + create mode 100644 asmcomp/arm64/selection.ml + create mode 100644 asmrun/arm64.S + create mode 100644 otherlibs/num/bng_arm64.c + create mode 100644 testsuite/tests/asmcomp/arm64.S + +diff --git a/asmcomp/arm64/arch.ml b/asmcomp/arm64/arch.ml +new file mode 100644 +index 0000000..a53251f +--- /dev/null ++++ b/asmcomp/arm64/arch.ml +@@ -0,0 +1,146 @@ ++(***********************************************************************) ++(* *) ++(* OCaml *) ++(* *) ++(* Xavier Leroy, projet Gallium, INRIA Rocquencourt *) ++(* Benedikt Meurer, University of Siegen *) ++(* *) ++(* Copyright 2013 Institut National de Recherche en Informatique *) ++(* et en Automatique. Copyright 2012 Benedikt Meurer. All rights *) ++(* reserved. This file is distributed under the terms of the Q *) ++(* Public License version 1.0. *) ++(* *) ++(***********************************************************************) ++ ++let command_line_options = [] ++ ++(* Specific operations for the ARM processor, 64-bit mode *) ++ ++open Format ++ ++let command_line_options = [] ++ ++(* Addressing modes *) ++ ++type addressing_mode = ++ | Iindexed of int (* reg + displ *) ++ | Ibased of string * int (* global var + displ *) ++ ++(* We do not support the reg + shifted reg addressing mode, because ++ what we really need is reg + shifted reg + displ, ++ and this is decomposed in two instructions (reg + shifted reg -> tmp, ++ then addressing tmp + displ). *) ++ ++(* Specific operations *) ++ ++type specific_operation = ++ | Ishiftarith of arith_operation * int ++ | Ishiftcheckbound of int ++ | Imuladd (* multiply and add *) ++ | Imulsub (* multiply and subtract *) ++ | Inegmulf (* floating-point negate and multiply *) ++ | Imuladdf (* floating-point multiply and add *) ++ | Inegmuladdf (* floating-point negate, multiply and add *) ++ | Imulsubf (* floating-point multiply and subtract *) ++ | Inegmulsubf (* floating-point negate, multiply and subtract *) ++ | Isqrtf (* floating-point square root *) ++ | Ibswap of int (* endianess conversion *) ++ ++and arith_operation = ++ Ishiftadd ++ | Ishiftsub ++ ++(* Sizes, endianness *) ++ ++let big_endian = false ++ ++let size_addr = 8 ++let size_int = 8 ++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 ++ | Iindexed n -> Iindexed(n + delta) ++ | Ibased(s, n) -> Ibased(s, n + delta) ++ ++let num_args_addressing = function ++ | Iindexed n -> 1 ++ | Ibased(s, n) -> 0 ++ ++(* Printing operations and addressing modes *) ++ ++let print_addressing printreg addr ppf arg = ++ match addr with ++ | Iindexed n -> ++ printreg ppf arg.(0); ++ if n <> 0 then fprintf ppf " + %i" n ++ | Ibased(s, 0) -> ++ fprintf ppf "\"%s\"" s ++ | Ibased(s, n) -> ++ fprintf ppf "\"%s\" + %i" s n ++ ++let print_specific_operation printreg op ppf arg = ++ match op with ++ | Ishiftarith(op, shift) -> ++ let op_name = function ++ | Ishiftadd -> "+" ++ | Ishiftsub -> "-" in ++ let shift_mark = ++ if shift >= 0 ++ then sprintf "<< %i" shift ++ else sprintf ">> %i" (-shift) in ++ fprintf ppf "%a %s %a %s" ++ printreg arg.(0) (op_name op) printreg arg.(1) shift_mark ++ | Ishiftcheckbound n -> ++ fprintf ppf "check %a >> %i > %a" printreg arg.(0) n printreg arg.(1) ++ | Imuladd -> ++ fprintf ppf "(%a * %a) + %a" ++ printreg arg.(0) ++ printreg arg.(1) ++ printreg arg.(2) ++ | Imulsub -> ++ fprintf ppf "-(%a * %a) + %a" ++ printreg arg.(0) ++ printreg arg.(1) ++ printreg arg.(2) ++ | Inegmulf -> ++ fprintf ppf "-f (%a *f %a)" ++ printreg arg.(0) ++ printreg arg.(1) ++ | Imuladdf -> ++ fprintf ppf "%a +f (%a *f %a)" ++ printreg arg.(0) ++ printreg arg.(1) ++ printreg arg.(2) ++ | Inegmuladdf -> ++ fprintf ppf "(-f %a) -f (%a *f %a)" ++ printreg arg.(0) ++ printreg arg.(1) ++ printreg arg.(2) ++ | Imulsubf -> ++ fprintf ppf "%a -f (%a *f %a)" ++ printreg arg.(0) ++ printreg arg.(1) ++ printreg arg.(2) ++ | Inegmulsubf -> ++ fprintf ppf "(-f %a) +f (%a *f %a)" ++ printreg arg.(0) ++ printreg arg.(1) ++ printreg arg.(2) ++ | Isqrtf -> ++ fprintf ppf "sqrtf %a" ++ printreg arg.(0) ++ | Ibswap n -> ++ fprintf ppf "bswap%i %a" n ++ printreg arg.(0) ++ +diff --git a/asmcomp/arm64/emit.mlp b/asmcomp/arm64/emit.mlp +new file mode 100644 +index 0000000..fc9649c +--- /dev/null ++++ b/asmcomp/arm64/emit.mlp +@@ -0,0 +1,742 @@ ++(***********************************************************************) ++(* *) ++(* OCaml *) ++(* *) ++(* Xavier Leroy, projet Gallium, INRIA Rocquencourt *) ++(* Benedikt Meurer, University of Siegen *) ++(* *) ++(* Copyright 2013 Institut National de Recherche en Informatique *) ++(* et en Automatique. Copyright 2012 Benedikt Meurer. All rights *) ++(* reserved. This file is distributed under the terms of the Q *) ++(* Public License version 1.0. *) ++(* *) ++(***********************************************************************) ++ ++(* Emission of ARM assembly code, 64-bit mode *) ++ ++open Misc ++open Cmm ++open Arch ++open Proc ++open Reg ++open Mach ++open Linearize ++open Emitaux ++ ++(* Tradeoff between code size and code speed *) ++ ++let fastcode_flag = ref true ++ ++(* Names for special regs *) ++ ++let reg_trap_ptr = phys_reg 23 ++let reg_alloc_ptr = phys_reg 24 ++let reg_alloc_limit = phys_reg 25 ++let reg_tmp1 = phys_reg 26 ++let reg_tmp2 = phys_reg 27 ++let reg_x15 = phys_reg 15 ++ ++(* Output a label *) ++ ++let emit_label lbl = ++ emit_string ".L"; emit_int lbl ++ ++let emit_data_label lbl = ++ emit_string ".Ld"; emit_int lbl ++ ++(* Symbols *) ++ ++let emit_symbol s = ++ Emitaux.emit_symbol '$' s ++ ++(* Output a pseudo-register *) ++ ++let emit_reg = function ++ {loc = Reg r} -> emit_string (register_name r) ++ | _ -> fatal_error "Emit.emit_reg" ++ ++(* Likewise, but with the 32-bit name of the register *) ++ ++let int_reg_name_w = ++ [| "w0"; "w1"; "w2"; "w3"; "w4"; "w5"; "w6"; "w7"; ++ "w8"; "w9"; "w10"; "w11"; "w12"; "w13"; "w14"; "w15"; ++ "w19"; "w20"; "w21"; "w22"; "w23"; "w24"; "w25"; ++ "w26"; "w27"; "w28"; "w16"; "w17" |] ++ ++let emit_wreg = function ++ {loc = Reg r} -> emit_string int_reg_name_w.(r) ++ | _ -> fatal_error "Emit.emit_wreg" ++ ++(* Layout of the stack frame *) ++ ++let stack_offset = ref 0 ++ ++let frame_size () = ++ let sz = ++ !stack_offset + ++ 8 * num_stack_slots.(0) + ++ 8 * num_stack_slots.(1) + ++ (if !contains_calls then 8 else 0) ++ in Misc.align sz 16 ++ ++let slot_offset loc cl = ++ match loc with ++ Incoming n -> ++ assert (n >= 0); ++ frame_size() + n ++ | Local n -> ++ !stack_offset + ++ (if cl = 0 ++ then n * 8 ++ else num_stack_slots.(0) * 8 + n * 8) ++ | Outgoing n -> ++ assert (n >= 0); ++ n ++ ++(* 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 an addressing mode *) ++ ++let emit_symbol_offset s ofs = ++ emit_symbol s; ++ if ofs > 0 then `+{emit_int ofs}` ++ else if ofs < 0 then `-{emit_int (-ofs)}` ++ else () ++ ++let emit_addressing addr r = ++ match addr with ++ | Iindexed ofs -> ++ `[{emit_reg r}, #{emit_int ofs}]` ++ | Ibased(s, ofs) -> ++ `[{emit_reg r}, #:lo12:{emit_symbol_offset s ofs}]` ++ ++(* Record live pointers at call points *) ++ ++let record_frame_label live dbg = ++ let lbl = new_label() in ++ let live_offset = ref [] in ++ Reg.Set.iter ++ (function ++ {typ = Addr; loc = Reg r} -> ++ live_offset := ((r lsl 1) + 1) :: !live_offset ++ | {typ = Addr; loc = Stack s} as reg -> ++ live_offset := slot_offset s (register_class reg) :: !live_offset ++ | _ -> ()) ++ live; ++ frame_descriptors := ++ { fd_lbl = lbl; ++ fd_frame_size = frame_size(); ++ fd_live_offset = !live_offset; ++ fd_debuginfo = dbg } :: !frame_descriptors; ++ lbl ++ ++let record_frame live dbg = ++ let lbl = record_frame_label live dbg in `{emit_label lbl}:` ++ ++(* Record calls to the GC -- we've moved them out of the way *) ++ ++type gc_call = ++ { gc_lbl: label; (* Entry label *) ++ gc_return_lbl: label; (* Where to branch after GC *) ++ gc_frame_lbl: label } (* Label of frame descriptor *) ++ ++let call_gc_sites = ref ([] : gc_call list) ++ ++let emit_call_gc gc = ++ `{emit_label gc.gc_lbl}: bl {emit_symbol "caml_call_gc"}\n`; ++ `{emit_label gc.gc_frame_lbl}: b {emit_label gc.gc_return_lbl}\n` ++ ++(* Record calls to caml_ml_array_bound_error. ++ In debug mode, we maintain one call to caml_ml_array_bound_error ++ per bound check site. Otherwise, we can share a single call. *) ++ ++type bound_error_call = ++ { bd_lbl: label; (* Entry label *) ++ bd_frame_lbl: label } (* Label of frame descriptor *) ++ ++let bound_error_sites = ref ([] : bound_error_call list) ++ ++let bound_error_label dbg = ++ if !Clflags.debug || !bound_error_sites = [] then begin ++ let lbl_bound_error = new_label() in ++ let lbl_frame = record_frame_label Reg.Set.empty dbg in ++ bound_error_sites := ++ { bd_lbl = lbl_bound_error; ++ bd_frame_lbl = lbl_frame } :: !bound_error_sites; ++ lbl_bound_error ++ end else begin ++ let bd = List.hd !bound_error_sites in bd.bd_lbl ++ end ++ ++let emit_call_bound_error bd = ++ `{emit_label bd.bd_lbl}: bl {emit_symbol "caml_ml_array_bound_error"}\n`; ++ `{emit_label bd.bd_frame_lbl}:\n` ++ ++(* Names of various instructions *) ++ ++let name_for_comparison = function ++ | Isigned Ceq -> "eq" | Isigned Cne -> "ne" | Isigned Cle -> "le" ++ | Isigned Cge -> "ge" | Isigned Clt -> "lt" | Isigned Cgt -> "gt" ++ | Iunsigned Ceq -> "eq" | Iunsigned Cne -> "ne" | Iunsigned Cle -> "ls" ++ | Iunsigned Cge -> "cs" | Iunsigned Clt -> "cc" | Iunsigned Cgt -> "hi" ++ ++let name_for_int_operation = function ++ | Iadd -> "add" ++ | Isub -> "sub" ++ | Imul -> "mul" ++ | Idiv -> "sdiv" ++ | Iand -> "and" ++ | Ior -> "orr" ++ | Ixor -> "eor" ++ | Ilsl -> "lsl" ++ | Ilsr -> "lsr" ++ | Iasr -> "asr" ++ | _ -> assert false ++ ++(* Load an integer constant into a register *) ++ ++let emit_intconst dst n = ++ let rec emit_pos first shift = ++ if shift < 0 then begin ++ if first then ` mov {emit_reg dst}, xzr\n` ++ end else begin ++ let s = Nativeint.(logand (shift_right_logical n shift) 0xFFFFn) in ++ if s = 0n then emit_pos first (shift - 16) else begin ++ if first then ++ ` movz {emit_reg dst}, #{emit_nativeint s}, lsl #{emit_int shift}\n` ++ else ++ ` movk {emit_reg dst}, #{emit_nativeint s}, lsl #{emit_int shift}\n`; ++ emit_pos false (shift - 16) ++ end ++ end ++ and emit_neg first shift = ++ if shift < 0 then begin ++ if first then ` movn {emit_reg dst}, #0\n` ++ end else begin ++ let s = Nativeint.(logand (shift_right_logical n shift) 0xFFFFn) in ++ if s = 0xFFFFn then emit_neg first (shift - 16) else begin ++ if first then ++ ` movn {emit_reg dst}, #{emit_nativeint (Nativeint.logxor s 0xFFFFn)}, lsl #{emit_int shift}\n` ++ else ++ ` movk {emit_reg dst}, #{emit_nativeint s}, lsl #{emit_int shift}\n`; ++ emit_neg false (shift - 16) ++ end ++ end ++ in ++ if n < 0n then emit_neg true 48 else emit_pos true 48 ++ ++(* Recognize float constants appropriate for FMOV dst, #fpimm instruction: ++ "a normalized binary floating point encoding with 1 sign bit, 4 ++ bits of fraction and a 3-bit exponent" *) ++ ++let is_immediate_float bits = ++ let exp = (Int64.(to_int (shift_right_logical bits 52)) land 0x7FF) - 1023 in ++ let mant = Int64.logand bits 0xF_FFFF_FFFF_FFFFL in ++ exp >= -3 && exp <= 4 && Int64.logand mant 0xF_0000_0000_0000L = mant ++ ++(* Adjust sp (up or down) by the given byte amount *) ++ ++let emit_stack_adjustment n = ++ let instr = if n < 0 then "sub" else "add" in ++ let m = abs n in ++ assert (m < 0x1_000_000); ++ let ml = m land 0xFFF and mh = m land 0xFFF_000 in ++ if mh <> 0 then ` {emit_string instr} sp, sp, #{emit_int mh}\n`; ++ if ml <> 0 then ` {emit_string instr} sp, sp, #{emit_int ml}\n`; ++ if n <> 0 then cfi_adjust_cfa_offset (-n) ++ ++(* Deallocate the stack frame and reload the return address ++ before a return or tail call *) ++ ++let output_epilogue f = ++ let n = frame_size() in ++ if !contains_calls then ++ ` ldr x30, [sp, #{emit_int (n-8)}]\n`; ++ if n > 0 then ++ emit_stack_adjustment n; ++ f(); ++ (* reset CFA back because function body may continue *) ++ if n > 0 then cfi_adjust_cfa_offset n ++ ++(* Name of current function *) ++let function_name = ref "" ++(* Entry point for tail recursive calls *) ++let tailrec_entry_point = ref 0 ++(* Pending floating-point literals *) ++let float_literals = ref ([] : (int64 * label) list) ++ ++(* Label a floating-point literal *) ++let float_literal f = ++ try ++ List.assoc f !float_literals ++ with Not_found -> ++ let lbl = new_label() in ++ float_literals := (f, lbl) :: !float_literals; ++ lbl ++ ++(* Emit all pending literals *) ++let emit_literals() = ++ if !float_literals <> [] then begin ++ ` .align 3\n`; ++ List.iter ++ (fun (f, lbl) -> ++ `{emit_label lbl}: .quad `; emit_printf "0x%Lx\n" f) ++ !float_literals; ++ float_literals := [] ++ end ++ ++(* Emit code to load the address of a symbol *) ++ ++let emit_load_symbol_addr dst s = ++ if (not !Clflags.dlcode) || Compilenv.symbol_in_current_unit s then begin ++ ` adrp {emit_reg dst}, {emit_symbol s}\n`; ++ ` add {emit_reg dst}, {emit_reg dst}, #:lo12:{emit_symbol s}\n` ++ end else begin ++ ` adrp {emit_reg dst}, :got:{emit_symbol s}\n`; ++ ` ldr {emit_reg dst}, [{emit_reg dst}, #:got_lo12:{emit_symbol s}]\n` ++ end ++ ++(* Output the assembly code for an instruction *) ++ ++let emit_instr i = ++ emit_debug_info i.dbg; ++ match i.desc with ++ | Lend -> () ++ | Lop(Imove | Ispill | Ireload) -> ++ let src = i.arg.(0) and dst = i.res.(0) in ++ if src.loc <> dst.loc then begin ++ match (src, dst) with ++ | {loc = Reg _; typ = Float}, {loc = Reg _} -> ++ ` fmov {emit_reg dst}, {emit_reg src}\n` ++ | {loc = Reg _}, {loc = Reg _} -> ++ ` mov {emit_reg dst}, {emit_reg src}\n` ++ | {loc = Reg _}, {loc = Stack _} -> ++ ` str {emit_reg src}, {emit_stack dst}\n` ++ | {loc = Stack _}, {loc = Reg _} -> ++ ` ldr {emit_reg dst}, {emit_stack src}\n` ++ | _ -> ++ assert false ++ end ++ | Lop(Iconst_int n) -> ++ emit_intconst i.res.(0) n ++ | Lop(Iconst_float f) -> ++ let b = Int64.bits_of_float(float_of_string f) in ++ if b = 0L then ++ ` fmov {emit_reg i.res.(0)}, xzr /* {emit_string f} */\n` ++ else if is_immediate_float b then ++ ` fmov {emit_reg i.res.(0)}, #{emit_printf "0x%Lx" b} /* {emit_string f} */\n` ++ else begin ++ let lbl = float_literal b in ++ ` adrp {emit_reg reg_tmp1}, {emit_label lbl}\n`; ++ ` ldr {emit_reg i.res.(0)}, [{emit_reg reg_tmp1}, #:lo12:{emit_label lbl}] /* {emit_string f} */\n` ++ end ++ | Lop(Iconst_symbol s) -> ++ emit_load_symbol_addr i.res.(0) s ++ | Lop(Icall_ind) -> ++ ` blr {emit_reg i.arg.(0)}\n`; ++ `{record_frame i.live i.dbg}\n` ++ | Lop(Icall_imm s) -> ++ ` bl {emit_symbol s}\n`; ++ `{record_frame i.live i.dbg}\n` ++ | Lop(Itailcall_ind) -> ++ output_epilogue (fun () -> ` br {emit_reg i.arg.(0)}\n`) ++ | Lop(Itailcall_imm s) -> ++ if s = !function_name then ++ ` b {emit_label !tailrec_entry_point}\n` ++ else ++ output_epilogue (fun () -> ` b {emit_symbol s}\n`) ++ | Lop(Iextcall(s, false)) -> ++ ` bl {emit_symbol s}\n` ++ | Lop(Iextcall(s, true)) -> ++ emit_load_symbol_addr reg_x15 s; ++ ` bl {emit_symbol "caml_c_call"}\n`; ++ `{record_frame i.live i.dbg}\n` ++ | Lop(Istackoffset n) -> ++ assert (n mod 16 = 0); ++ emit_stack_adjustment (-n); ++ stack_offset := !stack_offset + n ++ | Lop(Iload(size, addr)) -> ++ let dst = i.res.(0) in ++ let base = ++ match addr with ++ | Iindexed ofs -> i.arg.(0) ++ | Ibased(s, ofs) -> ++ ` adrp {emit_reg reg_tmp1}, {emit_symbol_offset s ofs}\n`; ++ reg_tmp1 in ++ begin match size with ++ | Byte_unsigned -> ++ ` ldrb {emit_wreg dst}, {emit_addressing addr base}\n` ++ | Byte_signed -> ++ ` ldrsb {emit_reg dst}, {emit_addressing addr base}\n` ++ | Sixteen_unsigned -> ++ ` ldrh {emit_wreg dst}, {emit_addressing addr base}\n` ++ | Sixteen_signed -> ++ ` ldrsh {emit_reg dst}, {emit_addressing addr base}\n` ++ | Thirtytwo_unsigned -> ++ ` ldr {emit_wreg dst}, {emit_addressing addr base}\n` ++ | Thirtytwo_signed -> ++ ` ldrsw {emit_reg dst}, {emit_addressing addr base}\n` ++ | Single -> ++ ` ldr s7, {emit_addressing addr base}\n`; ++ ` fcvt {emit_reg dst}, s7\n` ++ | Word | Double | Double_u -> ++ ` ldr {emit_reg dst}, {emit_addressing addr base}\n` ++ end ++ | Lop(Istore(size, addr)) -> ++ let src = i.arg.(0) in ++ let base = ++ match addr with ++ | Iindexed ofs -> i.arg.(1) ++ | Ibased(s, ofs) -> ++ ` adrp {emit_reg reg_tmp1}, {emit_symbol_offset s ofs}\n`; ++ reg_tmp1 in ++ begin match size with ++ | Byte_unsigned | Byte_signed -> ++ ` strb {emit_wreg src}, {emit_addressing addr base}\n` ++ | Sixteen_unsigned | Sixteen_signed -> ++ ` strh {emit_wreg src}, {emit_addressing addr base}\n` ++ | Thirtytwo_unsigned | Thirtytwo_signed -> ++ ` str {emit_wreg src}, {emit_addressing addr base}\n` ++ | Single -> ++ ` fcvt s7, {emit_reg src}\n`; ++ ` str s7, {emit_addressing addr base}\n`; ++ | Word | Double | Double_u -> ++ ` str {emit_reg src}, {emit_addressing addr base}\n` ++ end ++ | Lop(Ialloc n) -> ++ let lbl_frame = record_frame_label i.live i.dbg in ++ if !fastcode_flag then begin ++ let lbl_redo = new_label() in ++ let lbl_call_gc = new_label() in ++ `{emit_label lbl_redo}:`; ++ ` sub {emit_reg reg_alloc_ptr}, {emit_reg reg_alloc_ptr}, #{emit_int n}\n`; ++ ` cmp {emit_reg reg_alloc_ptr}, {emit_reg reg_alloc_limit}\n`; ++ ` add {emit_reg i.res.(0)}, {emit_reg reg_alloc_ptr}, #8\n`; ++ ` b.lo {emit_label lbl_call_gc}\n`; ++ call_gc_sites := ++ { gc_lbl = lbl_call_gc; ++ gc_return_lbl = lbl_redo; ++ gc_frame_lbl = lbl_frame } :: !call_gc_sites ++ end else begin ++ begin match n with ++ | 16 -> ` bl {emit_symbol "caml_alloc1"}\n` ++ | 24 -> ` bl {emit_symbol "caml_alloc2"}\n` ++ | 32 -> ` bl {emit_symbol "caml_alloc3"}\n` ++ | _ -> emit_intconst reg_x15 (Nativeint.of_int n); ++ ` bl {emit_symbol "caml_allocN"}\n` ++ end; ++ `{emit_label lbl_frame}: add {emit_reg i.res.(0)}, {emit_reg reg_alloc_ptr}, #8\n` ++ end ++ | Lop(Iintop(Icomp cmp)) -> ++ ` cmp {emit_reg i.arg.(0)}, {emit_reg i.arg.(1)}\n`; ++ ` cset {emit_reg i.res.(0)}, {emit_string (name_for_comparison cmp)}\n` ++ | Lop(Iintop_imm(Icomp cmp, n)) -> ++ ` cmp {emit_reg i.arg.(0)}, #{emit_int n}\n`; ++ ` cset {emit_reg i.res.(0)}, {emit_string (name_for_comparison cmp)}\n` ++ | Lop(Iintop Icheckbound) -> ++ let lbl = bound_error_label i.dbg in ++ ` cmp {emit_reg i.arg.(0)}, {emit_reg i.arg.(1)}\n`; ++ ` b.ls {emit_label lbl}\n` ++ | Lop(Iintop_imm(Icheckbound, n)) -> ++ let lbl = bound_error_label i.dbg in ++ ` cmp {emit_reg i.arg.(0)}, #{emit_int n}\n`; ++ ` b.ls {emit_label lbl}\n` ++ | Lop(Ispecific(Ishiftcheckbound shift)) -> ++ let lbl = bound_error_label i.dbg in ++ ` cmp {emit_reg i.arg.(1)}, {emit_reg i.arg.(0)}, lsr #{emit_int shift}\n`; ++ ` b.cs {emit_label lbl}\n` ++ | Lop(Iintop Imod) -> ++ ` sdiv {emit_reg reg_tmp1}, {emit_reg i.arg.(0)}, {emit_reg i.arg.(1)}\n`; ++ ` msub {emit_reg i.res.(0)}, {emit_reg reg_tmp1}, {emit_reg i.arg.(1)}, {emit_reg i.arg.(0)}\n` ++ | Lop(Iintop_imm(Idiv, n)) -> (* n is a power of 2 *) ++ let l = Misc.log2 n in ++ ` asr {emit_reg reg_tmp1}, {emit_reg i.arg.(0)}, #63\n`; ++ ` add {emit_reg reg_tmp1}, {emit_reg i.arg.(0)}, {emit_reg reg_tmp1}, lsr {emit_int (64-l)}\n`; ++ ` asr {emit_reg i.res.(0)}, {emit_reg reg_tmp1}, {emit_int l}\n` ++ | Lop(Iintop_imm(Imod, n)) -> (* n is a power of 2 *) ++ let l = Misc.log2 n in ++ ` asr {emit_reg reg_tmp1}, {emit_reg i.arg.(0)}, #63\n`; ++ ` add {emit_reg reg_tmp1}, {emit_reg i.arg.(0)}, {emit_reg reg_tmp1}, lsr {emit_int (64-l)}\n`; ++ ` asr {emit_reg reg_tmp1}, {emit_reg reg_tmp1}, {emit_int l}\n`; ++ ` sub {emit_reg i.res.(0)}, {emit_reg i.arg.(0)}, {emit_reg reg_tmp1}, lsl {emit_int l}\n` ++ | Lop(Iintop op) -> ++ let instr = name_for_int_operation op in ++ ` {emit_string instr} {emit_reg i.res.(0)}, {emit_reg i.arg.(0)}, {emit_reg i.arg.(1)}\n` ++ | Lop(Iintop_imm(op, n)) -> ++ let instr = name_for_int_operation op in ++ ` {emit_string instr} {emit_reg i.res.(0)}, {emit_reg i.arg.(0)}, #{emit_int n}\n` ++ | Lop(Ifloatofint | Iintoffloat | Iabsf | Inegf | Ispecific Isqrtf as op) -> ++ let instr = (match op with ++ | Ifloatofint -> "scvtf" ++ | Iintoffloat -> "fcvtzs" ++ | Iabsf -> "fabs" ++ | Inegf -> "fneg" ++ | Ispecific Isqrtf -> "fsqrt" ++ | _ -> assert false) in ++ ` {emit_string instr} {emit_reg i.res.(0)}, {emit_reg i.arg.(0)}\n` ++ | Lop(Iaddf | Isubf | Imulf | Idivf | Ispecific Inegmulf as op) -> ++ let instr = (match op with ++ | Iaddf -> "fadd" ++ | Isubf -> "fsub" ++ | Imulf -> "fmul" ++ | Idivf -> "fdiv" ++ | Ispecific Inegmulf -> "fnmul" ++ | _ -> assert false) in ++ ` {emit_string instr} {emit_reg i.res.(0)}, {emit_reg i.arg.(0)}, {emit_reg i.arg.(1)}\n` ++ | Lop(Ispecific(Imuladdf | Inegmuladdf | Imulsubf | Inegmulsubf as op)) -> ++ let instr = (match op with ++ | Imuladdf -> "fmadd" ++ | Inegmuladdf -> "fnmadd" ++ | Imulsubf -> "fmsub" ++ | Inegmulsubf -> "fnmsub" ++ | _ -> assert false) in ++ ` {emit_string instr} {emit_reg i.res.(0)}, {emit_reg i.arg.(1)}, {emit_reg i.arg.(2)}, {emit_reg i.arg.(0)}\n` ++ | Lop(Ispecific(Ishiftarith(op, shift))) -> ++ let instr = (match op with ++ Ishiftadd -> "add" ++ | Ishiftsub -> "sub") in ++ ` {emit_string instr} {emit_reg i.res.(0)}, {emit_reg i.arg.(0)}, {emit_reg i.arg.(1)}`; ++ if shift >= 0 ++ then `, lsl #{emit_int shift}\n` ++ else `, asr #{emit_int (-shift)}\n` ++ | Lop(Ispecific(Imuladd | Imulsub as op)) -> ++ let instr = (match op with ++ Imuladd -> "madd" ++ | Imulsub -> "msub" ++ | _ -> assert false) in ++ ` {emit_string instr} {emit_reg i.res.(0)}, {emit_reg i.arg.(0)}, {emit_reg i.arg.(1)}, {emit_reg i.arg.(2)}\n` ++ | Lop(Ispecific(Ibswap size)) -> ++ begin match size with ++ | 16 -> ++ ` rev16 {emit_wreg i.res.(0)}, {emit_wreg i.arg.(0)}\n`; ++ ` ubfm {emit_reg i.res.(0)}, {emit_reg i.res.(0)}, #0, #16\n` ++ | 32 -> ++ ` rev {emit_wreg i.res.(0)}, {emit_wreg i.arg.(0)}\n` ++ | 64 -> ++ ` rev {emit_reg i.res.(0)}, {emit_reg i.arg.(0)}\n` ++ | _ -> ++ assert false ++ end ++ | Lreloadretaddr -> ++ () ++ | Lreturn -> ++ output_epilogue (fun () -> ` ret\n`) ++ | Llabel lbl -> ++ `{emit_label lbl}:\n` ++ | Lbranch lbl -> ++ ` b {emit_label lbl}\n` ++ | Lcondbranch(tst, lbl) -> ++ begin match tst with ++ | Itruetest -> ++ ` cbnz {emit_reg i.arg.(0)}, {emit_label lbl}\n` ++ | Ifalsetest -> ++ ` cbz {emit_reg i.arg.(0)}, {emit_label lbl}\n` ++ | Iinttest cmp -> ++ ` cmp {emit_reg i.arg.(0)}, {emit_reg i.arg.(1)}\n`; ++ let comp = name_for_comparison cmp in ++ ` b.{emit_string comp} {emit_label lbl}\n` ++ | Iinttest_imm(cmp, n) -> ++ ` cmp {emit_reg i.arg.(0)}, #{emit_int n}\n`; ++ let comp = name_for_comparison cmp in ++ ` b.{emit_string comp} {emit_label lbl}\n` ++ | Ifloattest(cmp, neg) -> ++ let comp = (match (cmp, neg) with ++ | (Ceq, false) | (Cne, true) -> "eq" ++ | (Cne, false) | (Ceq, true) -> "ne" ++ | (Clt, false) -> "cc" ++ | (Clt, true) -> "cs" ++ | (Cle, false) -> "ls" ++ | (Cle, true) -> "hi" ++ | (Cgt, false) -> "gt" ++ | (Cgt, true) -> "le" ++ | (Cge, false) -> "ge" ++ | (Cge, true) -> "lt") in ++ ` fcmp {emit_reg i.arg.(0)}, {emit_reg i.arg.(1)}\n`; ++ ` b.{emit_string comp} {emit_label lbl}\n` ++ | Ioddtest -> ++ ` tbnz {emit_reg i.arg.(0)}, #0, {emit_label lbl}\n` ++ | Ieventest -> ++ ` tbz {emit_reg i.arg.(0)}, #0, {emit_label lbl}\n` ++ end ++ | Lcondbranch3(lbl0, lbl1, lbl2) -> ++ ` cmp {emit_reg i.arg.(0)}, #1\n`; ++ begin match lbl0 with ++ None -> () ++ | Some lbl -> ` b.lt {emit_label lbl}\n` ++ end; ++ begin match lbl1 with ++ None -> () ++ | Some lbl -> ` b.eq {emit_label lbl}\n` ++ end; ++ begin match lbl2 with ++ None -> () ++ | Some lbl -> ` b.gt {emit_label lbl}\n` ++ end ++ | Lswitch jumptbl -> ++ let lbltbl = new_label() in ++ ` adr {emit_reg reg_tmp1}, {emit_label lbltbl}\n`; ++ ` add {emit_reg reg_tmp1}, {emit_reg reg_tmp1}, {emit_reg i.arg.(0)}, lsl #2\n`; ++ ` br {emit_reg reg_tmp1}\n`; ++ `{emit_label lbltbl}:`; ++ for j = 0 to Array.length jumptbl - 1 do ++ ` b {emit_label jumptbl.(j)}\n` ++ done ++(* Alternative: ++ let lbltbl = new_label() in ++ ` adr {emit_reg reg_tmp1}, {emit_label lbltbl}\n`; ++ ` ldr {emit_wreg reg_tmp2}, [{emit_reg reg_tmp1}, {emit_reg i.arg.(0)}, lsl #2]\n`; ++ ` add {emit_reg reg_tmp1}, {emit_wreg reg_tmp2}, sxtb\n`; ++ ` br {emit_reg reg_tmp1}\n`; ++ `{emit_label lbltbl}:\n`; ++ for j = 0 to Array.length jumptbl - 1 do ++ ` .word {emit_label jumptbl.(j)} - {emit_label lbltbl}\n` ++ done ++*) ++ | Lsetuptrap lbl -> ++ let lblnext = new_label() in ++ ` adr {emit_reg reg_tmp1}, {emit_label lblnext}\n`; ++ ` b {emit_label lbl}\n`; ++ `{emit_label lblnext}:\n` ++ | Lpushtrap -> ++ stack_offset := !stack_offset + 16; ++ ` str {emit_reg reg_trap_ptr}, [sp, -16]!\n`; ++ ` str {emit_reg reg_tmp1}, [sp, #8]\n`; ++ cfi_adjust_cfa_offset 16; ++ ` mov {emit_reg reg_trap_ptr}, sp\n` ++ | Lpoptrap -> ++ ` ldr {emit_reg reg_trap_ptr}, [sp], 16\n`; ++ cfi_adjust_cfa_offset (-16); ++ stack_offset := !stack_offset - 16 ++ | Lraise -> ++ if !Clflags.debug then begin ++ ` bl {emit_symbol "caml_raise_exn"}\n`; ++ `{record_frame Reg.Set.empty i.dbg}\n` ++ end else begin ++ ` mov sp, {emit_reg reg_trap_ptr}\n`; ++ ` ldr {emit_reg reg_tmp1}, [sp, #8]\n`; ++ ` ldr {emit_reg reg_trap_ptr}, [sp], 16\n`; ++ ` br {emit_reg reg_tmp1}\n` ++ end ++ ++(* Emission of an instruction sequence *) ++ ++let rec emit_all i = ++ if i.desc = Lend then () else (emit_instr i; emit_all i.next) ++ ++(* Emission of the profiling prelude *) ++ ++let emit_profile() = () (* TODO *) ++(* ++ match Config.system with ++ "linux_eabi" | "linux_eabihf" -> ++ ` push \{lr}\n`; ++ ` {emit_call "__gnu_mcount_nc"}\n` ++ | _ -> () ++*) ++ ++(* Emission of a function declaration *) ++ ++let fundecl fundecl = ++ function_name := fundecl.fun_name; ++ fastcode_flag := fundecl.fun_fast; ++ tailrec_entry_point := new_label(); ++ float_literals := []; ++ stack_offset := 0; ++ call_gc_sites := []; ++ bound_error_sites := []; ++ ` .text\n`; ++ ` .align 2\n`; ++ ` .globl {emit_symbol fundecl.fun_name}\n`; ++ ` .type {emit_symbol fundecl.fun_name}, %function\n`; ++ `{emit_symbol fundecl.fun_name}:\n`; ++ emit_debug_info fundecl.fun_dbg; ++ cfi_startproc(); ++ if !Clflags.gprofile then emit_profile(); ++ let n = frame_size() in ++ if n > 0 then ++ emit_stack_adjustment (-n); ++ if !contains_calls then ++ ` str x30, [sp, #{emit_int (n-8)}]\n`; ++ `{emit_label !tailrec_entry_point}:\n`; ++ emit_all fundecl.fun_body; ++ List.iter emit_call_gc !call_gc_sites; ++ List.iter emit_call_bound_error !bound_error_sites; ++ cfi_endproc(); ++ ` .type {emit_symbol fundecl.fun_name}, %function\n`; ++ ` .size {emit_symbol fundecl.fun_name}, .-{emit_symbol fundecl.fun_name}\n`; ++ emit_literals() ++ ++(* Emission of data *) ++ ++let emit_item = function ++ | Cglobal_symbol s -> ` .globl {emit_symbol s}\n`; ++ | Cdefine_symbol s -> `{emit_symbol s}:\n` ++ | Cdefine_label lbl -> `{emit_data_label lbl}:\n` ++ | Cint8 n -> ` .byte {emit_int n}\n` ++ | Cint16 n -> ` .short {emit_int n}\n` ++ | Cint32 n -> ` .long {emit_nativeint n}\n` ++ | Cint n -> ` .quad {emit_nativeint n}\n` ++ | Csingle f -> emit_float32_directive ".long" f ++ | Cdouble f -> emit_float64_directive ".quad" f ++ | Csymbol_address s -> ` .quad {emit_symbol s}\n` ++ | Clabel_address lbl -> ` .quad {emit_data_label lbl}\n` ++ | Cstring s -> emit_string_directive " .ascii " s ++ | Cskip n -> if n > 0 then ` .space {emit_int n}\n` ++ | Calign n -> ` .align {emit_int(Misc.log2 n)}\n` ++ ++let data l = ++ ` .data\n`; ++ List.iter emit_item l ++ ++(* Beginning / end of an assembly file *) ++ ++let begin_assembly() = ++ reset_debug_info(); ++ let lbl_begin = Compilenv.make_symbol (Some "data_begin") in ++ ` .data\n`; ++ ` .globl {emit_symbol lbl_begin}\n`; ++ `{emit_symbol lbl_begin}:\n`; ++ let lbl_begin = Compilenv.make_symbol (Some "code_begin") in ++ ` .text\n`; ++ ` .globl {emit_symbol lbl_begin}\n`; ++ `{emit_symbol lbl_begin}:\n` ++ ++let end_assembly () = ++ let lbl_end = Compilenv.make_symbol (Some "code_end") in ++ ` .text\n`; ++ ` .globl {emit_symbol lbl_end}\n`; ++ `{emit_symbol lbl_end}:\n`; ++ let lbl_end = Compilenv.make_symbol (Some "data_end") in ++ ` .data\n`; ++ ` .globl {emit_symbol lbl_end}\n`; ++ `{emit_symbol lbl_end}:\n`; ++ ` .long 0\n`; ++ let lbl = Compilenv.make_symbol (Some "frametable") in ++ ` .globl {emit_symbol lbl}\n`; ++ `{emit_symbol lbl}:\n`; ++ emit_frames ++ { efa_label = (fun lbl -> ++ ` .type {emit_label lbl}, %function\n`; ++ ` .quad {emit_label lbl}\n`); ++ efa_16 = (fun n -> ` .short {emit_int n}\n`); ++ efa_32 = (fun n -> ` .long {emit_int32 n}\n`); ++ efa_word = (fun n -> ` .quad {emit_int n}\n`); ++ efa_align = (fun n -> ` .align {emit_int(Misc.log2 n)}\n`); ++ efa_label_rel = (fun lbl ofs -> ++ ` .long {emit_label lbl} - . + {emit_int32 ofs}\n`); ++ efa_def_label = (fun lbl -> `{emit_label lbl}:\n`); ++ efa_string = (fun s -> emit_string_directive " .asciz " s) }; ++ ` .type {emit_symbol lbl}, %object\n`; ++ ` .size {emit_symbol lbl}, .-{emit_symbol lbl}\n`; ++ begin match Config.system with ++ | "linux" -> ++ (* Mark stack as non-executable *) ++ ` .section .note.GNU-stack,\"\",%progbits\n` ++ | _ -> () ++ end +diff --git a/asmcomp/arm64/proc.ml b/asmcomp/arm64/proc.ml +new file mode 100644 +index 0000000..b52c2fd +--- /dev/null ++++ b/asmcomp/arm64/proc.ml +@@ -0,0 +1,212 @@ ++(***********************************************************************) ++(* *) ++(* OCaml *) ++(* *) ++(* Xavier Leroy, projet Gallium, INRIA Rocquencourt *) ++(* Benedikt Meurer, University of Siegen *) ++(* *) ++(* Copyright 2013 Institut National de Recherche en Informatique *) ++(* et en Automatique. Copyright 2012 Benedikt Meurer. All rights *) ++(* reserved. This file is distributed under the terms of the Q *) ++(* Public License version 1.0. *) ++(* *) ++(***********************************************************************) ++ ++(* Description of the ARM processor in 64-bit mode *) ++ ++open Misc ++open Cmm ++open Reg ++open Arch ++open Mach ++ ++(* Instruction selection *) ++ ++let word_addressed = false ++ ++(* Registers available for register allocation *) ++ ++(* Integer register map: ++ x0 - x15 general purpose (caller-save) ++ x16, x17 temporaries (used by call veeners) ++ x18 platform register (reserved) ++ x19 - x25 general purpose (callee-save) ++ x26 trap pointer ++ x27 alloc pointer ++ x28 alloc limit ++ x29 frame pointer ++ x30 return address ++ sp / xzr stack pointer / zero register ++ Floating-point register map: ++ d0 - d7 general purpose (caller-save) ++ d8 - d15 general purpose (callee-save) ++ d16 - d31 generat purpose (caller-save) ++*) ++ ++let int_reg_name = ++ [| "x0"; "x1"; "x2"; "x3"; "x4"; "x5"; "x6"; "x7"; ++ "x8"; "x9"; "x10"; "x11"; "x12"; "x13"; "x14"; "x15"; ++ "x19"; "x20"; "x21"; "x22"; "x23"; "x24"; "x25"; ++ "x26"; "x27"; "x28"; "x16"; "x17" |] ++ ++let float_reg_name = ++ [| "d0"; "d1"; "d2"; "d3"; "d4"; "d5"; "d6"; "d7"; ++ "d8"; "d9"; "d10"; "d11"; "d12"; "d13"; "d14"; "d15"; ++ "d16"; "d17"; "d18"; "d19"; "d20"; "d21"; "d22"; "d23"; ++ "d24"; "d25"; "d26"; "d27"; "d28"; "d29"; "d30"; "d31" |] ++ ++let num_register_classes = 2 ++ ++let register_class r = ++ match r.typ with ++ | (Int | Addr) -> 0 ++ | Float -> 1 ++ ++let num_available_registers = ++ [| 23; 32 |] (* first 23 int regs allocatable; all float regs allocatable *) ++ ++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.create 28 Reg.dummy in ++ for i = 0 to 27 do ++ v.(i) <- Reg.at_location Int (Reg i) ++ done; ++ v ++ ++let hard_float_reg = ++ let v = Array.create 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 hard_float_reg ++ ++let phys_reg n = ++ if n < 100 then hard_int_reg.(n) else hard_float_reg.(n - 100) ++ ++let reg_x15 = phys_reg 15 ++let reg_d7 = phys_reg 107 ++ ++let stack_slot slot ty = ++ Reg.at_location ty (Stack slot) ++ ++(* Calling conventions *) ++ ++let calling_conventions ++ first_int last_int first_float last_float make_stack arg = ++ let loc = Array.create (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 ++ 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 16) (* keep stack 16-aligned *) ++ ++let incoming ofs = Incoming ofs ++let outgoing ofs = Outgoing ofs ++let not_supported ofs = fatal_error "Proc.loc_results: cannot call" ++ ++(* OCaml calling convention: ++ first integer args in r0...r15 ++ first float args in d0...d15 ++ remaining args on stack. ++ Return values in r0...r15 or d0...d15. *) ++ ++let loc_arguments arg = ++ calling_conventions 0 15 100 115 outgoing arg ++let loc_parameters arg = ++ let (loc, _) = calling_conventions 0 15 100 115 incoming arg in loc ++let loc_results res = ++ let (loc, _) = calling_conventions 0 15 100 115 not_supported res in loc ++ ++(* C calling convention: ++ first integer args in r0...r7 ++ first float args in d0...d7 ++ remaining args on stack. ++ Return values in r0...r1 or d0. *) ++ ++let loc_external_arguments arg = ++ calling_conventions 0 7 100 107 outgoing arg ++let loc_external_results res = ++ let (loc, _) = calling_conventions 0 1 100 100 not_supported res in loc ++ ++let loc_exn_bucket = phys_reg 0 ++ ++(* Registers destroyed by operations *) ++ ++let destroyed_at_c_call = ++ (* x19-x28, d8-d15 preserved *) ++ Array.of_list (List.map phys_reg ++ [0;1;2;3;4;5;6;7;8;9;10;11;12;13;14;15; ++ 100;101;102;103;104;105;106;107; ++ 116;117;118;119;120;121;122;123; ++ 124;125;126;127;128;129;130;131]) ++ ++let destroyed_at_oper = function ++ | Iop(Icall_ind | Icall_imm _) | Iop(Iextcall(_, true)) -> ++ all_phys_regs ++ | Iop(Iextcall(_, false)) -> ++ destroyed_at_c_call ++ | Iop(Ialloc _) -> ++ [| reg_x15 |] ++ | Iop(Iintoffloat | Ifloatofint | Iload(Single, _) | Istore(Single, _)) -> ++ [| reg_d7 |] (* d7 / s7 destroyed *) ++ | _ -> [||] ++ ++let destroyed_at_raise = all_phys_regs ++ ++(* Maximal register pressure *) ++ ++let safe_register_pressure = function ++ | Iextcall(_, _) -> 8 ++ | Ialloc _ -> 25 ++ | _ -> 26 ++ ++let max_register_pressure = function ++ | Iextcall(_, _) -> [| 10; 8 |] ++ | Ialloc _ -> [| 25; 32 |] ++ | Iintoffloat | Ifloatofint ++ | Iload(Single, _) | Istore(Single, _) -> [| 26; 31 |] ++ | _ -> [| 26; 32 |] ++ ++(* Layout of the stack *) ++ ++let num_stack_slots = [| 0; 0 |] ++let contains_calls = ref false ++ ++(* Calling the assembler *) ++ ++let assemble_file infile outfile = ++ Ccomp.command (Config.asm ^ " -o " ^ ++ Filename.quote outfile ^ " " ^ Filename.quote infile) ++ ++ ++let init () = () +diff --git a/asmcomp/arm64/reload.ml b/asmcomp/arm64/reload.ml +new file mode 100644 +index 0000000..ff9214e +--- /dev/null ++++ b/asmcomp/arm64/reload.ml +@@ -0,0 +1,16 @@ ++(***********************************************************************) ++(* *) ++(* OCaml *) ++(* *) ++(* Xavier Leroy, projet Gallium, INRIA Rocquencourt *) ++(* *) ++(* Copyright 2013 Institut National de Recherche en Informatique et *) ++(* en Automatique. All rights reserved. This file is distributed *) ++(* under the terms of the Q Public License version 1.0. *) ++(* *) ++(***********************************************************************) ++ ++(* Reloading for the ARM 64 bits *) ++ ++let fundecl f = ++ (new Reloadgen.reload_generic)#fundecl f +diff --git a/asmcomp/arm64/scheduling.ml b/asmcomp/arm64/scheduling.ml +new file mode 100644 +index 0000000..cc244be +--- /dev/null ++++ b/asmcomp/arm64/scheduling.ml +@@ -0,0 +1,18 @@ ++(***********************************************************************) ++(* *) ++(* OCaml *) ++(* *) ++(* Xavier Leroy, projet Gallium, INRIA Rocquencourt *) ++(* *) ++(* Copyright 2013 Institut National de Recherche en Informatique et *) ++(* en Automatique. All rights reserved. This file is distributed *) ++(* under the terms of the Q Public License version 1.0. *) ++(* *) ++(***********************************************************************) ++ ++let _ = let module M = Schedgen in () (* to create a dependency *) ++ ++(* Scheduling is turned off because the processor schedules dynamically ++ much better than what we could do. *) ++ ++let fundecl f = f +diff --git a/asmcomp/arm64/selection.ml b/asmcomp/arm64/selection.ml +new file mode 100644 +index 0000000..c74b282 +--- /dev/null ++++ b/asmcomp/arm64/selection.ml +@@ -0,0 +1,265 @@ ++(***********************************************************************) ++(* *) ++(* OCaml *) ++(* *) ++(* Xavier Leroy, projet Gallium, INRIA Rocquencourt *) ++(* Benedikt Meurer, University of Siegen *) ++(* *) ++(* Copyright 2013 Institut National de Recherche en Informatique *) ++(* et en Automatique. Copyright 2012 Benedikt Meurer. All rights *) ++(* reserved. This file is distributed under the terms of the Q *) ++(* Public License version 1.0. *) ++(* *) ++(***********************************************************************) ++ ++(* Instruction selection for the ARM processor *) ++ ++open Arch ++open Cmm ++open Mach ++ ++let is_offset chunk n = ++ (n >= -256 && n <= 255) (* 9 bits signed unscaled *) ++|| (n >= 0 && ++ match chunk with (* 12 bits unsigned, scaled by chunk size *) ++ | Byte_unsigned | Byte_signed -> ++ n < 0x1000 ++ | Sixteen_unsigned | Sixteen_signed -> ++ n land 1 = 0 && n lsr 1 < 0x1000 ++ | Thirtytwo_unsigned | Thirtytwo_signed | Single -> ++ n land 3 = 0 && n lsr 2 < 0x1000 ++ | Word | Double | Double_u -> ++ n land 7 = 0 && n lsr 3 < 0x1000) ++ ++(* An automaton to recognize ( 0+1+0* | 1+0+1* ) ++ ++ 0 1 0 ++ / \ / \ / \ ++ \ / \ / \ / ++ -0--> [1] --1--> [2] --0--> [3] ++ / ++ [0] ++ \ ++ -1--> [4] --0--> [5] --1--> [6] ++ / \ / \ / \ ++ \ / \ / \ / ++ 1 0 1 ++ ++The accepting states are 2, 3, 5 and 6. *) ++ ++let auto_table = [| (* accepting?, next on 0, next on 1 *) ++ (* state 0 *) (false, 1, 4); ++ (* state 1 *) (false, 1, 2); ++ (* state 2 *) (true, 3, 2); ++ (* state 3 *) (true, 3, 7); ++ (* state 4 *) (false, 5, 4); ++ (* state 5 *) (true, 5, 6); ++ (* state 6 *) (true, 7, 6); ++ (* state 7 *) (false, 7, 7) (* error state *) ++|] ++ ++let rec run_automata nbits state input = ++ let (acc, next0, next1) = auto_table.(state) in ++ if nbits <= 0 ++ then acc ++ else run_automata (nbits - 1) ++ (if input land 1 = 0 then next0 else next1) ++ (input asr 1) ++ ++(* We are very conservative wrt what ARM64 supports: we don't support ++ repetitions of a 000111000 or 1110000111 pattern, just a single ++ pattern of this kind. *) ++ ++let is_logical_immediate n = ++ n <> 0 && n <> -1 && run_automata 64 0 n ++ ++let is_intconst = function ++ Cconst_int _ -> true ++ | _ -> false ++ ++let inline_ops = ++ [ "sqrt"; "caml_bswap16_direct"; "caml_int32_direct_bswap"; ++ "caml_int64_direct_bswap"; "caml_nativeint_direct_bswap" ] ++ ++let use_direct_addressing symb = ++ (not !Clflags.dlcode) || Compilenv.symbol_in_current_unit symb ++ ++(* Instruction selection *) ++ ++class selector = object(self) ++ ++inherit Selectgen.selector_generic as super ++ ++method is_immediate n = ++ let mn = -n in ++ n land 0xFFF = n || n land 0xFFF_000 = n ++ || mn land 0xFFF = mn || mn land 0xFFF_000 = mn ++ ++method! is_simple_expr = function ++ (* inlined floating-point ops are simple if their arguments are *) ++ | Cop(Cextcall(fn, _, _, _), args) when List.mem fn inline_ops -> ++ List.for_all self#is_simple_expr args ++ | e -> super#is_simple_expr e ++ ++method select_addressing chunk = function ++ | Cop(Cadda, [Cconst_symbol s; Cconst_int n]) ++ when use_direct_addressing s -> ++ (Ibased(s, n), Ctuple []) ++ | Cop(Cadda, [arg; Cconst_int n]) ++ when is_offset chunk n -> ++ (Iindexed n, arg) ++ | Cop(Cadda, [arg1; Cop(Caddi, [arg2; Cconst_int n])]) ++ when is_offset chunk n -> ++ (Iindexed n, Cop(Cadda, [arg1; arg2])) ++ | Cconst_symbol s ++ when use_direct_addressing s -> ++ (Ibased(s, 0), Ctuple []) ++ | arg -> ++ (Iindexed 0, arg) ++ ++method! select_operation op args = ++ match op with ++ (* Integer addition *) ++ | Caddi | Cadda -> ++ begin match args with ++ (* Add immediate *) ++ | [arg; Cconst_int n] | [Cconst_int n; arg] when self#is_immediate n -> ++ ((if n >= 0 then Iintop_imm(Iadd, n) else Iintop_imm(Isub, -n)), ++ [arg]) ++ (* Shift-add *) ++ | [arg1; Cop(Clsl, [arg2; Cconst_int n])] when n > 0 && n < 64 -> ++ (Ispecific(Ishiftarith(Ishiftadd, n)), [arg1; arg2]) ++ | [arg1; Cop(Casr, [arg2; Cconst_int n])] when n > 0 && n < 64 -> ++ (Ispecific(Ishiftarith(Ishiftadd, -n)), [arg1; arg2]) ++ | [Cop(Clsl, [arg1; Cconst_int n]); arg2] when n > 0 && n < 64 -> ++ (Ispecific(Ishiftarith(Ishiftadd, n)), [arg2; arg1]) ++ | [Cop(Casr, [arg1; Cconst_int n]); arg2] when n > 0 && n < 64 -> ++ (Ispecific(Ishiftarith(Ishiftadd, -n)), [arg2; arg1]) ++ (* Multiply-add *) ++ | [arg1; Cop(Cmuli, args2)] | [Cop(Cmuli, args2); arg1] -> ++ begin match self#select_operation Cmuli args2 with ++ | (Iintop_imm(Ilsl, l), [arg3]) -> ++ (Ispecific(Ishiftarith(Ishiftadd, l)), [arg1; arg3]) ++ | (Iintop Imul, [arg3; arg4]) -> ++ (Ispecific Imuladd, [arg3; arg4; arg1]) ++ | _ -> ++ super#select_operation op args ++ end ++ | _ -> ++ super#select_operation op args ++ end ++ (* Integer subtraction *) ++ | Csubi | Csuba -> ++ begin match args with ++ (* Sub immediate *) ++ | [arg; Cconst_int n] when self#is_immediate n -> ++ ((if n >= 0 then Iintop_imm(Isub, n) else Iintop_imm(Iadd, -n)), ++ [arg]) ++ (* Shift-sub *) ++ | [arg1; Cop(Clsl, [arg2; Cconst_int n])] when n > 0 && n < 64 -> ++ (Ispecific(Ishiftarith(Ishiftsub, n)), [arg1; arg2]) ++ | [arg1; Cop(Casr, [arg2; Cconst_int n])] when n > 0 && n < 64 -> ++ (Ispecific(Ishiftarith(Ishiftsub, -n)), [arg1; arg2]) ++ (* Multiply-sub *) ++ | [arg1; Cop(Cmuli, args2)] -> ++ begin match self#select_operation Cmuli args2 with ++ | (Iintop_imm(Ilsl, l), [arg3]) -> ++ (Ispecific(Ishiftarith(Ishiftsub, l)), [arg1; arg3]) ++ | (Iintop Imul, [arg3; arg4]) -> ++ (Ispecific Imulsub, [arg3; arg4; arg1]) ++ | _ -> ++ super#select_operation op args ++ end ++ | _ -> ++ super#select_operation op args ++ end ++ (* Checkbounds *) ++ | Ccheckbound _ -> ++ begin match args with ++ | [Cop(Clsr, [arg1; Cconst_int n]); arg2] when n > 0 && n < 64 -> ++ (Ispecific(Ishiftcheckbound n), [arg1; arg2]) ++ | _ -> ++ super#select_operation op args ++ end ++ (* Integer multiplication *) ++ (* ARM does not support immediate operands for multiplication *) ++ | Cmuli -> ++ begin match args with ++ | [arg; Cconst_int n] | [Cconst_int n; arg] -> ++ let l = Misc.log2 n in ++ if n = 1 lsl l ++ then (Iintop_imm(Ilsl, l), [arg]) ++ else (Iintop Imul, args) ++ | _ -> ++ (Iintop Imul, args) ++ end ++ (* Division and modulus *) ++ (* Recognize (x / cst) and (x % cst) only if cst is a power of 2. *) ++ | Cdivi -> ++ begin match args with ++ | [arg; Cconst_int n] when n = 1 lsl Misc.log2 n -> ++ ((if n = 1 then Imove else Iintop_imm(Idiv, n)), [arg]) ++ | _ -> ++ (Iintop Idiv, args) ++ end ++ | Cmodi -> ++ begin match args with ++ | [arg; Cconst_int n] when n = 1 lsl Misc.log2 n -> ++ ((if n = 1 then Iconst_int 0n else Iintop_imm(Imod, n)), [arg]) ++ | _ -> ++ (Iintop Imod, args) ++ end ++ (* Bitwise logical operations have a different range of immediate ++ operands than the other instructions *) ++ | Cand -> self#select_logical Iand args ++ | Cor -> self#select_logical Ior args ++ | Cxor -> self#select_logical Ixor args ++ (* Recognize floating-point negate and multiply *) ++ | Cnegf -> ++ begin match args with ++ | [Cop(Cmulf, args)] -> (Ispecific Inegmulf, args) ++ | _ -> super#select_operation op args ++ end ++ (* Recognize floating-point multiply and add/sub *) ++ | Caddf -> ++ begin match args with ++ | [arg; Cop(Cmulf, args)] | [Cop(Cmulf, args); arg] -> ++ (Ispecific Imuladdf, arg :: args) ++ | _ -> ++ super#select_operation op args ++ end ++ | Csubf -> ++ begin match args with ++ | [arg; Cop(Cmulf, args)] -> ++ (Ispecific Imulsubf, arg :: args) ++ | [Cop(Cmulf, args); arg] -> ++ (Ispecific Inegmulsubf, arg :: args) ++ | _ -> ++ super#select_operation op args ++ end ++ (* Recognize floating-point square root *) ++ | Cextcall("sqrt", _, _, _) -> ++ (Ispecific Isqrtf, args) ++ (* Recognize bswap instructions *) ++ | Cextcall("caml_bswap16_direct", _, _, _) -> ++ (Ispecific(Ibswap 16), args) ++ | Cextcall("caml_int32_direct_bswap", _, _, _) -> ++ (Ispecific(Ibswap 32), args) ++ | Cextcall(("caml_int64_direct_bswap"|"caml_nativeint_direct_bswap"), ++ _, _, _) -> ++ (Ispecific (Ibswap 64), args) ++ (* Other operations are regular *) ++ | _ -> ++ super#select_operation op args ++ ++method select_logical op = function ++ | [arg; Cconst_int n] when is_logical_immediate n -> ++ (Iintop_imm(op, n), [arg]) ++ | [Cconst_int n; arg] when is_logical_immediate n -> ++ (Iintop_imm(op, n), [arg]) ++ | args -> ++ (Iintop op, args) ++ ++end ++ ++let fundecl f = (new selector)#emit_fundecl f +diff --git a/asmcomp/compilenv.ml b/asmcomp/compilenv.ml +index 17870c9..280b131 100644 +--- a/asmcomp/compilenv.ml ++++ b/asmcomp/compilenv.ml +@@ -83,6 +83,15 @@ let make_symbol ?(unitname = current_unit.ui_symbol) idopt = + | None -> prefix + | Some id -> prefix ^ "__" ^ id + ++let symbol_in_current_unit name = ++ let prefix = "caml" ^ current_unit.ui_symbol in ++ name = prefix || ++ (let lp = String.length prefix in ++ String.length name >= 2 + lp ++ && String.sub name 0 lp = prefix ++ && name.[lp] = '_' ++ && name.[lp + 1] = '_') ++ + let read_unit_info filename = + let ic = open_in_bin filename in + try +diff --git a/asmcomp/compilenv.mli b/asmcomp/compilenv.mli +index 51cb8c6..9ffb145 100644 +--- a/asmcomp/compilenv.mli ++++ b/asmcomp/compilenv.mli +@@ -31,6 +31,10 @@ val make_symbol: ?unitname:string -> string option -> string + corresponds to symbol [id] in the compilation unit [u] + (or the current unit). *) + ++val symbol_in_current_unit: string -> bool ++ (* Return true if the given asm symbol belongs to the ++ current compilation unit, false otherwise. *) ++ + val symbol_for_global: Ident.t -> string + (* Return the asm symbol that refers to the given global identifier *) + +diff --git a/asmrun/arm64.S b/asmrun/arm64.S +new file mode 100644 +index 0000000..de670e6 +--- /dev/null ++++ b/asmrun/arm64.S +@@ -0,0 +1,535 @@ ++/***********************************************************************/ ++/* */ ++/* OCaml */ ++/* */ ++/* Xavier Leroy, projet Gallium, INRIA Rocquencourt */ ++/* */ ++/* Copyright 2013 Institut National de Recherche en Informatique et */ ++/* en Automatique. All rights reserved. This file is distributed */ ++/* under the terms of the GNU Library General Public License, with */ ++/* the special exception on linking described in file ../LICENSE. */ ++/* */ ++/***********************************************************************/ ++ ++/* Asm part of the runtime system, ARM processor, 64-bit mode */ ++/* Must be preprocessed by cpp */ ++ ++/* Special registers */ ++ ++#define TRAP_PTR x26 ++#define ALLOC_PTR x27 ++#define ALLOC_LIMIT x28 ++#define ARG x15 ++#define TMP x16 ++#define TMP2 x17 ++ ++/* Support for CFI directives */ ++ ++#if defined(ASM_CFI_SUPPORTED) ++#define CFI_STARTPROC .cfi_startproc ++#define CFI_ENDPROC .cfi_endproc ++#define CFI_ADJUST(n) .cfi_adjust_cfa_offset n ++#else ++#define CFI_STARTPROC ++#define CFI_ENDPROC ++#define CFI_ADJUST(n) ++#endif ++ ++/* Support for profiling with gprof */ ++ ++#define PROFILE ++ ++/* Macros to load and store global variables. Destroy TMP2 */ ++ ++#if defined(__PIC__) ++ ++#define ADDRGLOBAL(reg,symb) \ ++ adrp TMP2, :got:symb; \ ++ ldr reg, [TMP2, #:got_lo12:symb] ++ ++#define LOADGLOBAL(reg,symb) \ ++ ADDRGLOBAL(TMP2,symb); \ ++ ldr reg, [TMP2] ++ ++#define STOREGLOBAL(reg,symb) \ ++ ADDRGLOBAL(TMP2,symb); \ ++ str reg, [TMP2] ++ ++#else ++ ++#define ADDRGLOBAL(reg,symb) \ ++ adrp reg, symb; \ ++ add reg, reg, #:lo12:symb ++ ++#define LOADGLOBAL(reg,symb) \ ++ adrp TMP2, symb; \ ++ ldr reg, [TMP2, #:lo12:symb] ++ ++#define STOREGLOBAL(reg,symb) \ ++ adrp TMP2, symb; \ ++ str reg, [TMP2, #:lo12:symb] ++ ++#endif ++ ++/* Allocation functions and GC interface */ ++ ++ .globl caml_system__code_begin ++caml_system__code_begin: ++ ++ .align 2 ++ .globl caml_call_gc ++caml_call_gc: ++ CFI_STARTPROC ++ PROFILE ++ /* Record return address */ ++ STOREGLOBAL(x30, caml_last_return_address) ++.Lcaml_call_gc: ++ /* Record lowest stack address */ ++ mov TMP, sp ++ STOREGLOBAL(TMP, caml_bottom_of_stack) ++ /* Set up stack space, saving return address and frame pointer */ ++ /* (2 regs RA/GP, 24 allocatable int regs, 24 caller-save float regs) * 8 */ ++ stp x29, x30, [sp, -400]! ++ CFI_ADJUST(400) ++ add x29, sp, #0 ++ /* Save allocatable integer registers on the stack, in the order ++ given in proc.ml */ ++ stp x0, x1, [sp, 16] ++ stp x2, x3, [sp, 32] ++ stp x4, x5, [sp, 48] ++ stp x6, x7, [sp, 64] ++ stp x8, x9, [sp, 80] ++ stp x10, x11, [sp, 96] ++ stp x12, x13, [sp, 112] ++ stp x14, x15, [sp, 128] ++ stp x19, x20, [sp, 144] ++ stp x21, x22, [sp, 160] ++ stp x23, x24, [sp, 176] ++ str x25, [sp, 192] ++ /* Save caller-save floating-point registers on the stack ++ (callee-saves are preserved by caml_garbage_collection) */ ++ stp d0, d1, [sp, 208] ++ stp d2, d3, [sp, 224] ++ stp d4, d5, [sp, 240] ++ stp d6, d7, [sp, 256] ++ stp d16, d17, [sp, 272] ++ stp d18, d19, [sp, 288] ++ stp d20, d21, [sp, 304] ++ stp d22, d23, [sp, 320] ++ stp d24, d25, [sp, 336] ++ stp d26, d27, [sp, 352] ++ stp d28, d29, [sp, 368] ++ stp d30, d31, [sp, 384] ++ /* Store pointer to saved integer registers in caml_gc_regs */ ++ add TMP, sp, #16 ++ STOREGLOBAL(TMP, caml_gc_regs) ++ /* Save current allocation pointer for debugging purposes */ ++ STOREGLOBAL(ALLOC_PTR, caml_young_ptr) ++ /* Save trap pointer in case an exception is raised during GC */ ++ STOREGLOBAL(TRAP_PTR, caml_exception_pointer) ++ /* Call the garbage collector */ ++ bl caml_garbage_collection ++ /* Restore registers */ ++ ldp x0, x1, [sp, 16] ++ ldp x2, x3, [sp, 32] ++ ldp x4, x5, [sp, 48] ++ ldp x6, x7, [sp, 64] ++ ldp x8, x9, [sp, 80] ++ ldp x10, x11, [sp, 96] ++ ldp x12, x13, [sp, 112] ++ ldp x14, x15, [sp, 128] ++ ldp x19, x20, [sp, 144] ++ ldp x21, x22, [sp, 160] ++ ldp x23, x24, [sp, 176] ++ ldr x25, [sp, 192] ++ ldp d0, d1, [sp, 208] ++ ldp d2, d3, [sp, 224] ++ ldp d4, d5, [sp, 240] ++ ldp d6, d7, [sp, 256] ++ ldp d16, d17, [sp, 272] ++ ldp d18, d19, [sp, 288] ++ ldp d20, d21, [sp, 304] ++ ldp d22, d23, [sp, 320] ++ ldp d24, d25, [sp, 336] ++ ldp d26, d27, [sp, 352] ++ ldp d28, d29, [sp, 368] ++ ldp d30, d31, [sp, 384] ++ /* Reload new allocation pointer and allocation limit */ ++ LOADGLOBAL(ALLOC_PTR, caml_young_ptr) ++ LOADGLOBAL(ALLOC_LIMIT, caml_young_limit) ++ /* Free stack space and return to caller */ ++ ldp x29, x30, [sp], 400 ++ ret ++ CFI_ENDPROC ++ .type caml_call_gc, %function ++ .size caml_call_gc, .-caml_call_gc ++ ++ .align 2 ++ .globl caml_alloc1 ++caml_alloc1: ++ CFI_STARTPROC ++ PROFILE ++1: sub ALLOC_PTR, ALLOC_PTR, #16 ++ cmp ALLOC_PTR, ALLOC_LIMIT ++ b.lo 2f ++ ret ++2: stp x29, x30, [sp, -16]! ++ CFI_ADJUST(16) ++ add x29, sp, #0 ++ /* Record return address */ ++ STOREGLOBAL(x30, caml_last_return_address) ++ /* Call GC */ ++ bl .Lcaml_call_gc ++ /* Restore return address */ ++ ldp x29, x30, [sp], 16 ++ CFI_ADJUST(-16) ++ /* Try again */ ++ b 1b ++ CFI_ENDPROC ++ .type caml_alloc1, %function ++ .size caml_alloc1, .-caml_alloc1 ++ ++ .align 2 ++ .globl caml_alloc2 ++caml_alloc2: ++ CFI_STARTPROC ++ PROFILE ++1: sub ALLOC_PTR, ALLOC_PTR, #24 ++ cmp ALLOC_PTR, ALLOC_LIMIT ++ b.lo 2f ++ ret ++2: stp x29, x30, [sp, -16]! ++ CFI_ADJUST(16) ++ add x29, sp, #0 ++ /* Record return address */ ++ STOREGLOBAL(x30, caml_last_return_address) ++ /* Call GC */ ++ bl .Lcaml_call_gc ++ /* Restore return address */ ++ ldp x29, x30, [sp], 16 ++ CFI_ADJUST(-16) ++ /* Try again */ ++ b 1b ++ CFI_ENDPROC ++ .type caml_alloc2, %function ++ .size caml_alloc2, .-caml_alloc2 ++ ++ .align 2 ++ .globl caml_alloc3 ++caml_alloc3: ++ CFI_STARTPROC ++ PROFILE ++1: sub ALLOC_PTR, ALLOC_PTR, #32 ++ cmp ALLOC_PTR, ALLOC_LIMIT ++ b.lo 2f ++ ret ++2: stp x29, x30, [sp, -16]! ++ CFI_ADJUST(16) ++ add x29, sp, #0 ++ /* Record return address */ ++ STOREGLOBAL(x30, caml_last_return_address) ++ /* Call GC */ ++ bl .Lcaml_call_gc ++ /* Restore return address */ ++ ldp x29, x30, [sp], 16 ++ CFI_ADJUST(-16) ++ /* Try again */ ++ b 1b ++ CFI_ENDPROC ++ .type caml_alloc2, %function ++ .size caml_alloc2, .-caml_alloc2 ++ ++ .align 2 ++ .globl caml_allocN ++caml_allocN: ++ CFI_STARTPROC ++ PROFILE ++1: sub ALLOC_PTR, ALLOC_PTR, ARG ++ cmp ALLOC_PTR, ALLOC_LIMIT ++ b.lo 2f ++ ret ++2: stp x29, x30, [sp, -16]! ++ CFI_ADJUST(16) ++ add x29, sp, #0 ++ /* Record return address */ ++ STOREGLOBAL(x30, caml_last_return_address) ++ /* Call GC. This preserves ARG */ ++ bl .Lcaml_call_gc ++ /* Restore return address */ ++ ldp x29, x30, [sp], 16 ++ CFI_ADJUST(-16) ++ /* Try again */ ++ b 1b ++ CFI_ENDPROC ++ .type caml_allocN, %function ++ .size caml_allocN, .-caml_allocN ++ ++/* Call a C function from OCaml */ ++/* Function to call is in ARG */ ++ ++ .align 2 ++ .globl caml_c_call ++caml_c_call: ++ CFI_STARTPROC ++ PROFILE ++ /* Preserve return address in callee-save register x19 */ ++ mov x19, x30 ++ /* Record lowest stack address and return address */ ++ STOREGLOBAL(x30, caml_last_return_address) ++ add TMP, sp, #0 ++ STOREGLOBAL(TMP, caml_bottom_of_stack) ++ /* Make the exception handler alloc ptr available to the C code */ ++ STOREGLOBAL(ALLOC_PTR, caml_young_ptr) ++ STOREGLOBAL(TRAP_PTR, caml_exception_pointer) ++ /* Call the function */ ++ blr ARG ++ /* Reload alloc ptr and alloc limit */ ++ LOADGLOBAL(ALLOC_PTR, caml_young_ptr) ++ LOADGLOBAL(ALLOC_LIMIT, caml_young_limit) ++ /* Return */ ++ ret x19 ++ CFI_ENDPROC ++ .type caml_c_call, %function ++ .size caml_c_call, .-caml_c_call ++ ++/* Start the OCaml program */ ++ ++ .align 2 ++ .globl caml_start_program ++caml_start_program: ++ CFI_STARTPROC ++ PROFILE ++ ADDRGLOBAL(ARG, caml_program) ++ ++/* Code shared with caml_callback* */ ++/* Address of OCaml code to call is in ARG */ ++/* Arguments to the OCaml code are in x0...x7 */ ++ ++.Ljump_to_caml: ++ /* Set up stack frame and save callee-save registers */ ++ stp x29, x30, [sp, -160]! ++ CFI_ADJUST(160) ++ add x29, sp, #0 ++ stp x19, x20, [sp, 16] ++ stp x21, x22, [sp, 32] ++ stp x23, x24, [sp, 48] ++ stp x25, x26, [sp, 64] ++ stp x27, x28, [sp, 80] ++ stp d8, d9, [sp, 96] ++ stp d10, d11, [sp, 112] ++ stp d12, d13, [sp, 128] ++ stp d14, d15, [sp, 144] ++ /* Setup a callback link on the stack */ ++ LOADGLOBAL(x8, caml_bottom_of_stack) ++ LOADGLOBAL(x9, caml_last_return_address) ++ LOADGLOBAL(x10, caml_gc_regs) ++ stp x8, x9, [sp, -32]! /* 16-byte alignment */ ++ CFI_ADJUST(32) ++ str x10, [sp, 16] ++ /* Setup a trap frame to catch exceptions escaping the OCaml code */ ++ LOADGLOBAL(x8, caml_exception_pointer) ++ adr x9, .Ltrap_handler ++ stp x8, x9, [sp, -16]! ++ CFI_ADJUST(16) ++ add TRAP_PTR, sp, #0 ++ /* Reload allocation pointers */ ++ LOADGLOBAL(ALLOC_PTR, caml_young_ptr) ++ LOADGLOBAL(ALLOC_LIMIT, caml_young_limit) ++ /* Call the OCaml code */ ++ blr ARG ++.Lcaml_retaddr: ++ /* Pop the trap frame, restoring caml_exception_pointer */ ++ ldr x8, [sp], 16 ++ CFI_ADJUST(-16) ++ STOREGLOBAL(x8, caml_exception_pointer) ++ /* Pop the callback link, restoring the global variables */ ++.Lreturn_result: ++ ldr x10, [sp, 16] ++ ldp x8, x9, [sp], 32 ++ CFI_ADJUST(-32) ++ STOREGLOBAL(x8, caml_bottom_of_stack) ++ STOREGLOBAL(x9, caml_last_return_address) ++ STOREGLOBAL(x10, caml_gc_regs) ++ /* Update allocation pointer */ ++ STOREGLOBAL(ALLOC_PTR, caml_young_ptr) ++ /* Reload callee-save registers and return address */ ++ ldp x19, x20, [sp, 16] ++ ldp x21, x22, [sp, 32] ++ ldp x23, x24, [sp, 48] ++ ldp x25, x26, [sp, 64] ++ ldp x27, x28, [sp, 80] ++ ldp d8, d9, [sp, 96] ++ ldp d10, d11, [sp, 112] ++ ldp d12, d13, [sp, 128] ++ ldp d14, d15, [sp, 144] ++ ldp x29, x30, [sp], 160 ++ CFI_ADJUST(-160) ++ /* Return to C caller */ ++ ret ++ CFI_ENDPROC ++ .type .Lcaml_retaddr, %function ++ .size .Lcaml_retaddr, .-.Lcaml_retaddr ++ .type caml_start_program, %function ++ .size caml_start_program, .-caml_start_program ++ ++/* The trap handler */ ++ ++ .align 2 ++.Ltrap_handler: ++ CFI_STARTPROC ++ /* Save exception pointer */ ++ STOREGLOBAL(TRAP_PTR, caml_exception_pointer) ++ /* Encode exception bucket as an exception result */ ++ orr x0, x0, #2 ++ /* Return it */ ++ b .Lreturn_result ++ CFI_ENDPROC ++ .type .Ltrap_handler, %function ++ .size .Ltrap_handler, .-.Ltrap_handler ++ ++/* Raise an exception from OCaml */ ++ ++ .align 2 ++ .globl caml_raise_exn ++caml_raise_exn: ++ CFI_STARTPROC ++ PROFILE ++ /* Test if backtrace is active */ ++ LOADGLOBAL(TMP, caml_backtrace_active) ++ cbnz TMP, 2f ++1: /* Cut stack at current trap handler */ ++ mov sp, TRAP_PTR ++ /* Pop previous handler and jump to it */ ++ ldr TMP, [sp, 8] ++ ldr TRAP_PTR, [sp], 16 ++ br TMP ++2: /* Preserve exception bucket in callee-save register x19 */ ++ mov x19, x0 ++ /* Stash the backtrace */ ++ /* arg1: exn bucket, already in x0 */ ++ mov x1, x30 /* arg2: pc of raise */ ++ add x2, sp, #0 /* arg3: sp of raise */ ++ mov x3, TRAP_PTR /* arg4: sp of handler */ ++ bl caml_stash_backtrace ++ /* Restore exception bucket and raise */ ++ mov x0, x19 ++ b 1b ++ CFI_ENDPROC ++ .type caml_raise_exn, %function ++ .size caml_raise_exn, .-caml_raise_exn ++ ++/* Raise an exception from C */ ++ ++ .align 2 ++ .globl caml_raise_exception ++caml_raise_exception: ++ CFI_STARTPROC ++ PROFILE ++ /* Reload trap ptr, alloc ptr and alloc limit */ ++ LOADGLOBAL(TRAP_PTR, caml_exception_pointer) ++ LOADGLOBAL(ALLOC_PTR, caml_young_ptr) ++ LOADGLOBAL(ALLOC_LIMIT, caml_young_limit) ++ /* Test if backtrace is active */ ++ LOADGLOBAL(TMP, caml_backtrace_active) ++ cbnz TMP, 2f ++1: /* Cut stack at current trap handler */ ++ mov sp, TRAP_PTR ++ /* Pop previous handler and jump to it */ ++ ldr TMP, [sp, 8] ++ ldr TRAP_PTR, [sp], 16 ++ br TMP ++2: /* Preserve exception bucket in callee-save register x19 */ ++ mov x19, x0 ++ /* Stash the backtrace */ ++ /* arg1: exn bucket, already in x0 */ ++ LOADGLOBAL(x1, caml_last_return_address) /* arg2: pc of raise */ ++ LOADGLOBAL(x2, caml_bottom_of_stack) /* arg3: sp of raise */ ++ mov x3, TRAP_PTR /* arg4: sp of handler */ ++ bl caml_stash_backtrace ++ /* Restore exception bucket and raise */ ++ mov x0, x19 ++ b 1b ++ CFI_ENDPROC ++ .type caml_raise_exception, %function ++ .size caml_raise_exception, .-caml_raise_exception ++ ++/* Callback from C to OCaml */ ++ ++ .align 2 ++ .globl caml_callback_exn ++caml_callback_exn: ++ CFI_STARTPROC ++ PROFILE ++ /* Initial shuffling of arguments (x0 = closure, x1 = first arg) */ ++ mov TMP, x0 ++ mov x0, x1 /* x0 = first arg */ ++ mov x1, TMP /* x1 = closure environment */ ++ ldr ARG, [TMP] /* code pointer */ ++ b .Ljump_to_caml ++ CFI_ENDPROC ++ .type caml_callback_exn, %function ++ .size caml_callback_exn, .-caml_callback_exn ++ ++ .align 2 ++ .globl caml_callback2_exn ++caml_callback2_exn: ++ CFI_STARTPROC ++ PROFILE ++ /* Initial shuffling of arguments (x0 = closure, x1 = arg1, x2 = arg2) */ ++ mov TMP, x0 ++ mov x0, x1 /* x0 = first arg */ ++ mov x1, x2 /* x1 = second arg ++ mov x2, TMP /* x2 = closure environment */ ++ ADDRGLOBAL(ARG, caml_apply2) ++ b .Ljump_to_caml ++ CFI_ENDPROC ++ .type caml_callback2_exn, %function ++ .size caml_callback2_exn, .-caml_callback2_exn ++ ++ .align 2 ++ .globl caml_callback3_exn ++caml_callback3_exn: ++ CFI_STARTPROC ++ PROFILE ++ /* Initial shuffling of arguments */ ++ /* (x0 = closure, x1 = arg1, x2 = arg2, x3 = arg3) */ ++ mov TMP, x0 ++ mov x0, x1 /* x0 = first arg */ ++ mov x1, x2 /* x1 = second arg */ ++ mov x2, x3 /* x2 = third arg */ ++ mov x3, TMP /* x3 = closure environment */ ++ ADDRGLOBAL(ARG, caml_apply3) ++ b .Ljump_to_caml ++ CFI_ENDPROC ++ .type caml_callback3_exn, %function ++ .size caml_callback3_exn, .-caml_callback3_exn ++ ++ .align 2 ++ .globl caml_ml_array_bound_error ++caml_ml_array_bound_error: ++ CFI_STARTPROC ++ PROFILE ++ /* Load address of [caml_array_bound_error] in ARG */ ++ ADDRGLOBAL(ARG, caml_array_bound_error) ++ /* Call that function */ ++ b caml_c_call ++ CFI_ENDPROC ++ .type caml_ml_array_bound_error, %function ++ .size caml_ml_array_bound_error, .-caml_ml_array_bound_error ++ ++ .globl caml_system__code_end ++caml_system__code_end: ++ ++/* GC roots for callback */ ++ ++ .data ++ .align 3 ++ .globl caml_system__frametable ++caml_system__frametable: ++ .quad 1 /* one descriptor */ ++ .quad .Lcaml_retaddr /* return address into callback */ ++ .short -1 /* negative frame size => use callback link */ ++ .short 0 /* no roots */ ++ .align 3 ++ .type caml_system__frametable, %object ++ .size caml_system__frametable, .-caml_system__frametable +diff --git a/asmrun/signals_osdep.h b/asmrun/signals_osdep.h +index ff19847..68ec837 100644 +--- a/asmrun/signals_osdep.h ++++ b/asmrun/signals_osdep.h +@@ -92,6 +92,25 @@ + #define CONTEXT_YOUNG_PTR (context->uc_mcontext.arm_r8) + #define CONTEXT_FAULTING_ADDRESS ((char *) context->uc_mcontext.fault_address) + ++/****************** ARM64, Linux */ ++ ++#elif defined(TARGET_arm64) && defined(SYS_linux) ++ ++ #include ++ ++ #define DECLARE_SIGNAL_HANDLER(name) \ ++ static void name(int sig, siginfo_t * info, ucontext_t * context) ++ ++ #define SET_SIGACT(sigact,name) \ ++ sigact.sa_sigaction = (void (*)(int,siginfo_t *,void *)) (name); \ ++ sigact.sa_flags = SA_SIGINFO ++ ++ typedef unsigned long context_reg; ++ #define CONTEXT_PC (context->uc_mcontext.pc) ++ #define CONTEXT_EXCEPTION_POINTER (context->uc_mcontext.regs[26]) ++ #define CONTEXT_YOUNG_PTR (context->uc_mcontext.regs[27]) ++ #define CONTEXT_FAULTING_ADDRESS ((char *) context->uc_mcontext.fault_address) ++ + /****************** AMD64, Solaris x86 */ + + #elif defined(TARGET_amd64) && defined (SYS_solaris) +diff --git a/asmrun/stack.h b/asmrun/stack.h +index 756db95..031e408 100644 +--- a/asmrun/stack.h ++++ b/asmrun/stack.h +@@ -65,6 +65,11 @@ + #define Callback_link(sp) ((struct caml_context *)((sp) + 16)) + #endif + ++#ifdef TARGET_arm64 ++#define Saved_return_address(sp) *((intnat *)((sp) - 8)) ++#define Callback_link(sp) ((struct caml_context *)((sp) + 16)) ++#endif ++ + /* Structure of OCaml callback contexts */ + + struct caml_context { +diff --git a/byterun/interp.c b/byterun/interp.c +index b99ed2f..af9fa0f 100644 +--- a/byterun/interp.c ++++ b/byterun/interp.c +@@ -173,6 +173,12 @@ sp is a local copy of the global variable caml_extern_sp. */ + #define SP_REG asm("%r14") + #define ACCU_REG asm("%r13") + #endif ++#ifdef __aarch64__ ++#define PC_REG asm("%x19") ++#define SP_REG asm("%x20") ++#define ACCU_REG asm("%x21") ++#define JUMPTBL_BASE_REG asm("%x22") ++#endif + #endif + + /* Division and modulus madness */ +diff --git a/configure b/configure +index 9b02664..36edfab 100755 +--- a/configure ++++ b/configure +@@ -657,6 +657,7 @@ if test $withsharedlibs = "yes"; then + x86_64-*-netbsd*) natdynlink=true;; + i386-*-gnu0.3) natdynlink=true;; + arm*-*-linux*) natdynlink=true;; ++ aarch64-*-linux*) natdynlink=true;; + esac + fi + +@@ -715,6 +716,7 @@ case "$host" in + x86_64-*-netbsd*) arch=amd64; system=netbsd;; + x86_64-*-openbsd*) arch=amd64; system=openbsd;; + x86_64-*-darwin*) arch=amd64; system=macosx;; ++ aarch64-*-linux*) arch=arm64; system=linux;; + esac + + # Some platforms exist both in 32-bit and 64-bit variants, not distinguished +@@ -767,7 +769,7 @@ case "$arch,$model,$system" in + aspp='gcc -m64 -c';; + amd64,*,*) as='as' + aspp='gcc -c';; +- arm,*,*) as='as'; ++ arm,*,*|arm64,*,*)as='as'; + aspp='gcc -c';; + i386,*,solaris) as='as' + aspp='/usr/ccs/bin/as -P';; +@@ -1193,6 +1195,7 @@ case "$arch" in + fi;; + power) bng_arch=ppc; bng_asm_level=1;; + amd64) bng_arch=amd64; bng_asm_level=1;; ++ arm64) bng_arch=arm64; bng_asm_level=1;; + *) bng_arch=generic; bng_asm_level=0;; + esac + +diff --git a/otherlibs/num/bng.c b/otherlibs/num/bng.c +index 5bbedb0..0483ef5 100644 +--- a/otherlibs/num/bng.c ++++ b/otherlibs/num/bng.c +@@ -23,12 +23,10 @@ + #include "bng_amd64.c" + #elif defined(BNG_ARCH_ppc) + #include "bng_ppc.c" +-#elif defined (BNG_ARCH_alpha) +-#include "bng_alpha.c" + #elif defined (BNG_ARCH_sparc) + #include "bng_sparc.c" +-#elif defined (BNG_ARCH_mips) +-#include "bng_mips.c" ++#elif defined (BNG_ARCH_arm64) ++#include "bng_arm64.c" + #endif + #endif + +diff --git a/otherlibs/num/bng_arm64.c b/otherlibs/num/bng_arm64.c +new file mode 100644 +index 0000000..50843a0 +--- /dev/null ++++ b/otherlibs/num/bng_arm64.c +@@ -0,0 +1,20 @@ ++/***********************************************************************/ ++/* */ ++/* OCaml */ ++/* */ ++/* Xavier Leroy, projet Gallium, INRIA Rocquencourt */ ++/* */ ++/* Copyright 2013 Institut National de Recherche en Informatique et */ ++/* en Automatique. All rights reserved. This file is distributed */ ++/* under the terms of the GNU Library General Public License, with */ ++/* the special exception on linking described in file ../../LICENSE. */ ++/* */ ++/***********************************************************************/ ++ ++/* Code specific for the ARM 64 (AArch64) architecture */ ++ ++#define BngMult(resh,resl,arg1,arg2) \ ++ asm("mul %0, %2, %3 \n\t" \ ++ "umulh %1, %2, %3" \ ++ : "=&r" (resl), "=&r" (resh) \ ++ : "r" (arg1), "r" (arg2)) +diff --git a/testsuite/tests/asmcomp/Makefile b/testsuite/tests/asmcomp/Makefile +index fd01d33..9dca023 100644 +--- a/testsuite/tests/asmcomp/Makefile ++++ b/testsuite/tests/asmcomp/Makefile +@@ -126,7 +126,7 @@ parsecmm.mli parsecmm.ml: parsecmm.mly + lexcmm.ml: lexcmm.mll + @$(OCAMLLEX) -q lexcmm.mll + +-CASES=fib tak quicksort quicksort2 soli \ ++CASES=fib tak quicksort quicksort2 soli integr \ + arith checkbound tagged-fib tagged-integr tagged-quicksort tagged-tak + ARGS_fib=-DINT_INT -DFUN=fib main.c + ARGS_tak=-DUNIT_INT -DFUN=takmain main.c +diff --git a/testsuite/tests/asmcomp/arm64.S b/testsuite/tests/asmcomp/arm64.S +new file mode 100644 +index 0000000..3bb4110 +--- /dev/null ++++ b/testsuite/tests/asmcomp/arm64.S +@@ -0,0 +1,52 @@ ++/***********************************************************************/ ++/* */ ++/* OCaml */ ++/* */ ++/* Xavier Leroy, projet Gallium, INRIA Rocquencourt */ ++/* */ ++/* Copyright 2013 Institut National de Recherche en Informatique et */ ++/* en Automatique. All rights reserved. This file is distributed */ ++/* under the terms of the Q Public License version 1.0. */ ++/* */ ++/***********************************************************************/ ++ ++ .globl call_gen_code ++ .align 2 ++call_gen_code: ++ /* Set up stack frame and save callee-save registers */ ++ stp x29, x30, [sp, -160]! ++ add x29, sp, #0 ++ stp x19, x20, [sp, 16] ++ stp x21, x22, [sp, 32] ++ stp x23, x24, [sp, 48] ++ stp x25, x26, [sp, 64] ++ stp x27, x28, [sp, 80] ++ stp d8, d9, [sp, 96] ++ stp d10, d11, [sp, 112] ++ stp d12, d13, [sp, 128] ++ stp d14, d15, [sp, 144] ++ /* Shuffle arguments */ ++ mov x8, x0 ++ mov x0, x1 ++ mov x1, x2 ++ mov x2, x3 ++ mov x3, x4 ++ /* Call generated asm */ ++ blr x8 ++ /* Reload callee-save registers and return address */ ++ ldp x19, x20, [sp, 16] ++ ldp x21, x22, [sp, 32] ++ ldp x23, x24, [sp, 48] ++ ldp x25, x26, [sp, 64] ++ ldp x27, x28, [sp, 80] ++ ldp d8, d9, [sp, 96] ++ ldp d10, d11, [sp, 112] ++ ldp d12, d13, [sp, 128] ++ ldp d14, d15, [sp, 144] ++ ldp x29, x30, [sp], 160 ++ ret ++ ++ .globl caml_c_call ++ .align 2 ++caml_c_call: ++ br x15 +diff --git a/testsuite/tests/asmcomp/main.ml b/testsuite/tests/asmcomp/main.ml +index d67a643..82b699e 100644 +--- a/testsuite/tests/asmcomp/main.ml ++++ b/testsuite/tests/asmcomp/main.ml +@@ -13,6 +13,7 @@ + open Clflags + + let compile_file filename = ++ Clflags.dlcode := false; + Compilenv.reset "test"; + Emit.begin_assembly(); + let ic = open_in filename in +-- +1.8.4.2 + diff --git a/0010-Updated-with-latest-versions-from-FSF.patch b/0010-Updated-with-latest-versions-from-FSF.patch new file mode 100644 index 0000000..fd1e923 --- /dev/null +++ b/0010-Updated-with-latest-versions-from-FSF.patch @@ -0,0 +1,716 @@ +From d36a95566c96d93280bf1439acc65ce7d4d159d0 Mon Sep 17 00:00:00 2001 +From: Xavier Leroy +Date: Thu, 18 Jul 2013 16:07:25 +0000 +Subject: [PATCH 10/11] Updated with latest versions from FSF. + +git-svn-id: http://caml.inria.fr/svn/ocaml/trunk@13907 f963ae5c-01c2-4b8c-9fe0-0dff7051ff02 +(cherry picked from commit 24bb4caeb35e49126aa3a4c0101a412db1091213) +--- + config/gnu/config.guess | 196 ++++++++++++++++++++++++++++-------------------- + config/gnu/config.sub | 117 +++++++++++++++++------------ + 2 files changed, 183 insertions(+), 130 deletions(-) + +diff --git a/config/gnu/config.guess b/config/gnu/config.guess +index 8152efd..b79252d 100755 +--- a/config/gnu/config.guess ++++ b/config/gnu/config.guess +@@ -1,14 +1,12 @@ + #! /bin/sh + # Attempt to guess a canonical system name. +-# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, +-# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, +-# 2011 Free Software Foundation, Inc. ++# Copyright 1992-2013 Free Software Foundation, Inc. + +-timestamp='2011-11-11' ++timestamp='2013-06-10' + + # This file is free software; you can redistribute it and/or modify it + # under the terms of the GNU General Public License as published by +-# the Free Software Foundation; either version 2 of the License, or ++# the Free Software Foundation; either version 3 of the License, or + # (at your option) any later version. + # + # This program is distributed in the hope that it will be useful, but +@@ -17,26 +15,22 @@ timestamp='2011-11-11' + # General Public License for more details. + # + # You should have received a copy of the GNU General Public License +-# along with this program; if not, write to the Free Software +-# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA +-# 02110-1301, USA. ++# along with this program; if not, see . + # + # As a special exception to the GNU General Public License, if you + # distribute this file as part of a program that contains a + # configuration script generated by Autoconf, you may include it under +-# the same distribution terms that you use for the rest of that program. +- +- +-# Originally written by Per Bothner. Please send patches (context +-# diff format) to and include a ChangeLog +-# entry. ++# the same distribution terms that you use for the rest of that ++# program. This Exception is an additional permission under section 7 ++# of the GNU General Public License, version 3 ("GPLv3"). + # +-# This script attempts to guess a canonical system name similar to +-# config.sub. If it succeeds, it prints the system name on stdout, and +-# exits with 0. Otherwise, it exits with 1. ++# Originally written by Per Bothner. + # + # You can get the latest version of this script from: + # http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD ++# ++# Please send patches with a ChangeLog entry to config-patches@gnu.org. ++ + + me=`echo "$0" | sed -e 's,.*/,,'` + +@@ -56,9 +50,7 @@ version="\ + GNU config.guess ($timestamp) + + Originally written by Per Bothner. +-Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, +-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free +-Software Foundation, Inc. ++Copyright 1992-2013 Free Software Foundation, Inc. + + This is free software; see the source for copying conditions. There is NO + warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." +@@ -140,12 +132,33 @@ UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown + UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown + UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown + ++case "${UNAME_SYSTEM}" in ++Linux|GNU|GNU/*) ++ # If the system lacks a compiler, then just pick glibc. ++ # We could probably try harder. ++ LIBC=gnu ++ ++ eval $set_cc_for_build ++ cat <<-EOF > $dummy.c ++ #include ++ #if defined(__UCLIBC__) ++ LIBC=uclibc ++ #elif defined(__dietlibc__) ++ LIBC=dietlibc ++ #else ++ LIBC=gnu ++ #endif ++ EOF ++ eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC'` ++ ;; ++esac ++ + # Note: order is significant - the case branches are not exclusive. + + case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in + *:NetBSD:*:*) + # NetBSD (nbsd) targets should (where applicable) match one or +- # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*, ++ # more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*, + # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently + # switched to ELF, *-*-netbsd* would select the old + # object file format. This provides both forward +@@ -202,6 +215,10 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in + # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. + echo "${machine}-${os}${release}" + exit ;; ++ *:Bitrig:*:*) ++ UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'` ++ echo ${UNAME_MACHINE_ARCH}-unknown-bitrig${UNAME_RELEASE} ++ exit ;; + *:OpenBSD:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` + echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE} +@@ -304,7 +321,7 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in + arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) + echo arm-acorn-riscix${UNAME_RELEASE} + exit ;; +- arm:riscos:*:*|arm:RISCOS:*:*) ++ arm*:riscos:*:*|arm*:RISCOS:*:*) + echo arm-unknown-riscos + exit ;; + SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) +@@ -803,6 +820,9 @@ EOF + i*:CYGWIN*:*) + echo ${UNAME_MACHINE}-pc-cygwin + exit ;; ++ *:MINGW64*:*) ++ echo ${UNAME_MACHINE}-pc-mingw64 ++ exit ;; + *:MINGW*:*) + echo ${UNAME_MACHINE}-pc-mingw32 + exit ;; +@@ -854,15 +874,22 @@ EOF + exit ;; + *:GNU:*:*) + # the GNU system +- echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` ++ echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-${LIBC}`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` + exit ;; + *:GNU/*:*:*) + # other systems with GNU libc and userland +- echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu ++ echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-${LIBC} + exit ;; + i*86:Minix:*:*) + echo ${UNAME_MACHINE}-pc-minix + exit ;; ++ aarch64:Linux:*:*) ++ echo ${UNAME_MACHINE}-unknown-linux-${LIBC} ++ exit ;; ++ aarch64_be:Linux:*:*) ++ UNAME_MACHINE=aarch64_be ++ echo ${UNAME_MACHINE}-unknown-linux-${LIBC} ++ exit ;; + alpha:Linux:*:*) + case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in + EV5) UNAME_MACHINE=alphaev5 ;; +@@ -874,59 +901,54 @@ EOF + EV68*) UNAME_MACHINE=alphaev68 ;; + esac + objdump --private-headers /bin/sh | grep -q ld.so.1 +- if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi +- echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} ++ if test "$?" = 0 ; then LIBC="gnulibc1" ; fi ++ echo ${UNAME_MACHINE}-unknown-linux-${LIBC} ++ exit ;; ++ arc:Linux:*:* | arceb:Linux:*:*) ++ echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + arm*:Linux:*:*) + eval $set_cc_for_build + if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ARM_EABI__ + then +- echo ${UNAME_MACHINE}-unknown-linux-gnu ++ echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + else + if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ARM_PCS_VFP + then +- echo ${UNAME_MACHINE}-unknown-linux-gnueabi ++ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabi + else +- echo ${UNAME_MACHINE}-unknown-linux-gnueabihf ++ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabihf + fi + fi + exit ;; + avr32*:Linux:*:*) +- echo ${UNAME_MACHINE}-unknown-linux-gnu ++ echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + cris:Linux:*:*) +- echo cris-axis-linux-gnu ++ echo ${UNAME_MACHINE}-axis-linux-${LIBC} + exit ;; + crisv32:Linux:*:*) +- echo crisv32-axis-linux-gnu ++ echo ${UNAME_MACHINE}-axis-linux-${LIBC} + exit ;; + frv:Linux:*:*) +- echo frv-unknown-linux-gnu ++ echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + hexagon:Linux:*:*) +- echo hexagon-unknown-linux-gnu ++ echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + i*86:Linux:*:*) +- LIBC=gnu +- eval $set_cc_for_build +- sed 's/^ //' << EOF >$dummy.c +- #ifdef __dietlibc__ +- LIBC=dietlibc +- #endif +-EOF +- eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC'` +- echo "${UNAME_MACHINE}-pc-linux-${LIBC}" ++ echo ${UNAME_MACHINE}-pc-linux-${LIBC} + exit ;; + ia64:Linux:*:*) +- echo ${UNAME_MACHINE}-unknown-linux-gnu ++ echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + m32r*:Linux:*:*) +- echo ${UNAME_MACHINE}-unknown-linux-gnu ++ echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + m68*:Linux:*:*) +- echo ${UNAME_MACHINE}-unknown-linux-gnu ++ echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + mips:Linux:*:* | mips64:Linux:*:*) + eval $set_cc_for_build +@@ -945,54 +967,63 @@ EOF + #endif + EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'` +- test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; } ++ test x"${CPU}" != x && { echo "${CPU}-unknown-linux-${LIBC}"; exit; } + ;; ++ or1k:Linux:*:*) ++ echo ${UNAME_MACHINE}-unknown-linux-${LIBC} ++ exit ;; + or32:Linux:*:*) +- echo or32-unknown-linux-gnu ++ echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + padre:Linux:*:*) +- echo sparc-unknown-linux-gnu ++ echo sparc-unknown-linux-${LIBC} + exit ;; + parisc64:Linux:*:* | hppa64:Linux:*:*) +- echo hppa64-unknown-linux-gnu ++ echo hppa64-unknown-linux-${LIBC} + exit ;; + parisc:Linux:*:* | hppa:Linux:*:*) + # Look for CPU level + case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in +- PA7*) echo hppa1.1-unknown-linux-gnu ;; +- PA8*) echo hppa2.0-unknown-linux-gnu ;; +- *) echo hppa-unknown-linux-gnu ;; ++ PA7*) echo hppa1.1-unknown-linux-${LIBC} ;; ++ PA8*) echo hppa2.0-unknown-linux-${LIBC} ;; ++ *) echo hppa-unknown-linux-${LIBC} ;; + esac + exit ;; + ppc64:Linux:*:*) +- echo powerpc64-unknown-linux-gnu ++ echo powerpc64-unknown-linux-${LIBC} + exit ;; + ppc:Linux:*:*) +- echo powerpc-unknown-linux-gnu ++ echo powerpc-unknown-linux-${LIBC} ++ exit ;; ++ ppc64le:Linux:*:*) ++ echo powerpc64le-unknown-linux-${LIBC} ++ exit ;; ++ ppcle:Linux:*:*) ++ echo powerpcle-unknown-linux-${LIBC} + exit ;; + s390:Linux:*:* | s390x:Linux:*:*) +- echo ${UNAME_MACHINE}-ibm-linux ++ echo ${UNAME_MACHINE}-ibm-linux-${LIBC} + exit ;; + sh64*:Linux:*:*) +- echo ${UNAME_MACHINE}-unknown-linux-gnu ++ echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + sh*:Linux:*:*) +- echo ${UNAME_MACHINE}-unknown-linux-gnu ++ echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + sparc:Linux:*:* | sparc64:Linux:*:*) +- echo ${UNAME_MACHINE}-unknown-linux-gnu ++ echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + tile*:Linux:*:*) +- echo ${UNAME_MACHINE}-unknown-linux-gnu ++ echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + vax:Linux:*:*) +- echo ${UNAME_MACHINE}-dec-linux-gnu ++ echo ${UNAME_MACHINE}-dec-linux-${LIBC} + exit ;; + x86_64:Linux:*:*) +- echo x86_64-unknown-linux-gnu ++ echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + xtensa*:Linux:*:*) +- echo ${UNAME_MACHINE}-unknown-linux-gnu ++ echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + i*86:DYNIX/ptx:4*:*) + # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. +@@ -1196,6 +1227,9 @@ EOF + BePC:Haiku:*:*) # Haiku running on Intel PC compatible. + echo i586-pc-haiku + exit ;; ++ x86_64:Haiku:*:*) ++ echo x86_64-unknown-haiku ++ exit ;; + SX-4:SUPER-UX:*:*) + echo sx4-nec-superux${UNAME_RELEASE} + exit ;; +@@ -1222,19 +1256,21 @@ EOF + exit ;; + *:Darwin:*:*) + UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown +- case $UNAME_PROCESSOR in +- i386) +- eval $set_cc_for_build +- if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then +- if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ +- (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ +- grep IS_64BIT_ARCH >/dev/null +- then +- UNAME_PROCESSOR="x86_64" +- fi +- fi ;; +- unknown) UNAME_PROCESSOR=powerpc ;; +- esac ++ eval $set_cc_for_build ++ if test "$UNAME_PROCESSOR" = unknown ; then ++ UNAME_PROCESSOR=powerpc ++ fi ++ if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then ++ if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ ++ (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ ++ grep IS_64BIT_ARCH >/dev/null ++ then ++ case $UNAME_PROCESSOR in ++ i386) UNAME_PROCESSOR=x86_64 ;; ++ powerpc) UNAME_PROCESSOR=powerpc64 ;; ++ esac ++ fi ++ fi + echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} + exit ;; + *:procnto*:*:* | *:QNX:[0123456789]*:*) +@@ -1251,7 +1287,7 @@ EOF + NEO-?:NONSTOP_KERNEL:*:*) + echo neo-tandem-nsk${UNAME_RELEASE} + exit ;; +- NSE-?:NONSTOP_KERNEL:*:*) ++ NSE-*:NONSTOP_KERNEL:*:*) + echo nse-tandem-nsk${UNAME_RELEASE} + exit ;; + NSR-?:NONSTOP_KERNEL:*:*) +@@ -1320,11 +1356,11 @@ EOF + i*86:AROS:*:*) + echo ${UNAME_MACHINE}-pc-aros + exit ;; ++ x86_64:VMkernel:*:*) ++ echo ${UNAME_MACHINE}-unknown-esx ++ exit ;; + esac + +-#echo '(No uname command or uname output not recognized.)' 1>&2 +-#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2 +- + eval $set_cc_for_build + cat >$dummy.c <. + # + # As a special exception to the GNU General Public License, if you + # distribute this file as part of a program that contains a + # configuration script generated by Autoconf, you may include it under +-# the same distribution terms that you use for the rest of that program. ++# the same distribution terms that you use for the rest of that ++# program. This Exception is an additional permission under section 7 ++# of the GNU General Public License, version 3 ("GPLv3"). + + +-# Please send patches to . Submit a context +-# diff and a properly formatted GNU ChangeLog entry. ++# Please send patches with a ChangeLog entry to config-patches@gnu.org. + # + # Configuration subroutine to validate and canonicalize a configuration type. + # Supply the specified configuration type as an argument. +@@ -75,9 +68,7 @@ Report bugs and patches to ." + version="\ + GNU config.sub ($timestamp) + +-Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, +-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free +-Software Foundation, Inc. ++Copyright 1992-2013 Free Software Foundation, Inc. + + This is free software; see the source for copying conditions. There is NO + warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." +@@ -125,13 +116,17 @@ esac + maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` + case $maybe_os in + nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \ +- linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \ ++ linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \ + knetbsd*-gnu* | netbsd*-gnu* | \ + kopensolaris*-gnu* | \ + storm-chaos* | os2-emx* | rtmk-nova*) + os=-$maybe_os + basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` + ;; ++ android-linux) ++ os=-linux-android ++ basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown ++ ;; + *) + basic_machine=`echo $1 | sed 's/-[^-]*$//'` + if [ $basic_machine != $1 ] +@@ -154,7 +149,7 @@ case $os in + -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ + -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ + -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ +- -apple | -axis | -knuth | -cray | -microblaze) ++ -apple | -axis | -knuth | -cray | -microblaze*) + os= + basic_machine=$1 + ;; +@@ -223,6 +218,12 @@ case $os in + -isc*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; ++ -lynx*178) ++ os=-lynxos178 ++ ;; ++ -lynx*5) ++ os=-lynxos5 ++ ;; + -lynx*) + os=-lynxos + ;; +@@ -247,11 +248,14 @@ case $basic_machine in + # Some are omitted here because they have special meanings below. + 1750a | 580 \ + | a29k \ ++ | aarch64 | aarch64_be \ + | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ + | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ + | am33_2.0 \ +- | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \ +- | be32 | be64 \ ++ | arc | arceb \ ++ | arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \ ++ | avr | avr32 \ ++ | be32 | be64 \ + | bfin \ + | c4x | clipper \ + | d10v | d30v | dlx | dsp16xx \ +@@ -264,7 +268,7 @@ case $basic_machine in + | le32 | le64 \ + | lm32 \ + | m32c | m32r | m32rle | m68000 | m68k | m88k \ +- | maxq | mb | microblaze | mcore | mep | metag \ ++ | maxq | mb | microblaze | microblazeel | mcore | mep | metag \ + | mips | mipsbe | mipseb | mipsel | mipsle \ + | mips16 \ + | mips64 | mips64el \ +@@ -282,16 +286,17 @@ case $basic_machine in + | mipsisa64r2 | mipsisa64r2el \ + | mipsisa64sb1 | mipsisa64sb1el \ + | mipsisa64sr71k | mipsisa64sr71kel \ ++ | mipsr5900 | mipsr5900el \ + | mipstx39 | mipstx39el \ + | mn10200 | mn10300 \ + | moxie \ + | mt \ + | msp430 \ + | nds32 | nds32le | nds32be \ +- | nios | nios2 \ ++ | nios | nios2 | nios2eb | nios2el \ + | ns16k | ns32k \ + | open8 \ +- | or32 \ ++ | or1k | or32 \ + | pdp10 | pdp11 | pj | pjl \ + | powerpc | powerpc64 | powerpc64le | powerpcle \ + | pyramid \ +@@ -319,8 +324,7 @@ case $basic_machine in + c6x) + basic_machine=tic6x-unknown + ;; +- m6811 | m68hc11 | m6812 | m68hc12 | picochip) +- # Motorola 68HC11/12. ++ m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | picochip) + basic_machine=$basic_machine-unknown + os=-none + ;; +@@ -333,7 +337,10 @@ case $basic_machine in + strongarm | thumb | xscale) + basic_machine=arm-unknown + ;; +- ++ xgate) ++ basic_machine=$basic_machine-unknown ++ os=-none ++ ;; + xscaleeb) + basic_machine=armeb-unknown + ;; +@@ -356,9 +363,10 @@ case $basic_machine in + # Recognize the basic CPU types with company name. + 580-* \ + | a29k-* \ ++ | aarch64-* | aarch64_be-* \ + | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ + | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ +- | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \ ++ | alphapca5[67]-* | alpha64pca5[67]-* | arc-* | arceb-* \ + | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ + | avr-* | avr32-* \ + | be32-* | be64-* \ +@@ -377,7 +385,8 @@ case $basic_machine in + | lm32-* \ + | m32c-* | m32r-* | m32rle-* \ + | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ +- | m88110-* | m88k-* | maxq-* | mcore-* | metag-* | microblaze-* \ ++ | m88110-* | m88k-* | maxq-* | mcore-* | metag-* \ ++ | microblaze-* | microblazeel-* \ + | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ + | mips16-* \ + | mips64-* | mips64el-* \ +@@ -395,12 +404,13 @@ case $basic_machine in + | mipsisa64r2-* | mipsisa64r2el-* \ + | mipsisa64sb1-* | mipsisa64sb1el-* \ + | mipsisa64sr71k-* | mipsisa64sr71kel-* \ ++ | mipsr5900-* | mipsr5900el-* \ + | mipstx39-* | mipstx39el-* \ + | mmix-* \ + | mt-* \ + | msp430-* \ + | nds32-* | nds32le-* | nds32be-* \ +- | nios-* | nios2-* \ ++ | nios-* | nios2-* | nios2eb-* | nios2el-* \ + | none-* | np1-* | ns16k-* | ns32k-* \ + | open8-* \ + | orion-* \ +@@ -719,7 +729,6 @@ case $basic_machine in + i370-ibm* | ibm*) + basic_machine=i370-ibm + ;; +-# I'm not sure what "Sysv32" means. Should this be sysv3.2? + i*86v32) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv32 +@@ -777,9 +786,13 @@ case $basic_machine in + basic_machine=ns32k-utek + os=-sysv + ;; +- microblaze) ++ microblaze*) + basic_machine=microblaze-xilinx + ;; ++ mingw64) ++ basic_machine=x86_64-pc ++ os=-mingw64 ++ ;; + mingw32) + basic_machine=i386-pc + os=-mingw32 +@@ -1008,7 +1021,11 @@ case $basic_machine in + basic_machine=i586-unknown + os=-pw32 + ;; +- rdos) ++ rdos | rdos64) ++ basic_machine=x86_64-pc ++ os=-rdos ++ ;; ++ rdos32) + basic_machine=i386-pc + os=-rdos + ;; +@@ -1335,21 +1352,21 @@ case $os in + -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ + | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\ + | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \ +- | -sym* | -kopensolaris* \ ++ | -sym* | -kopensolaris* | -plan9* \ + | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ + | -aos* | -aros* \ + | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ + | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ + | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ +- | -openbsd* | -solidbsd* \ ++ | -bitrig* | -openbsd* | -solidbsd* \ + | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ + | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ + | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ + | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ + | -chorusos* | -chorusrdb* | -cegcc* \ + | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ +- | -mingw32* | -linux-gnu* | -linux-android* \ +- | -linux-newlib* | -linux-uclibc* \ ++ | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \ ++ | -linux-newlib* | -linux-musl* | -linux-uclibc* \ + | -uxpv* | -beos* | -mpeix* | -udk* \ + | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ + | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ +@@ -1481,9 +1498,6 @@ case $os in + -aros*) + os=-aros + ;; +- -kaos*) +- os=-kaos +- ;; + -zvmoe) + os=-zvmoe + ;; +@@ -1532,6 +1546,9 @@ case $basic_machine in + c4x-* | tic4x-*) + os=-coff + ;; ++ hexagon-*) ++ os=-elf ++ ;; + tic54x-*) + os=-coff + ;; +@@ -1559,9 +1576,6 @@ case $basic_machine in + ;; + m68000-sun) + os=-sunos3 +- # This also exists in the configure program, but was not the +- # default. +- # os=-sunos4 + ;; + m68*-cisco) + os=-aout +@@ -1575,6 +1589,9 @@ case $basic_machine in + mips*-*) + os=-elf + ;; ++ or1k-*) ++ os=-elf ++ ;; + or32-*) + os=-coff + ;; +-- +1.8.4.2 + diff --git a/0011-Disable-ocamldoc-and-camlp4opt-aarch64-only.patch b/0011-Disable-ocamldoc-and-camlp4opt-aarch64-only.patch new file mode 100644 index 0000000..085f6b2 --- /dev/null +++ b/0011-Disable-ocamldoc-and-camlp4opt-aarch64-only.patch @@ -0,0 +1,38 @@ +From 55f34d6a262a7e29172ad52ef2d6688ac2c02381 Mon Sep 17 00:00:00 2001 +From: "Richard W.M. Jones" +Date: Mon, 30 Dec 2013 20:32:03 +0000 +Subject: [PATCH 11/11] Disable ocamldoc and camlp4opt (aarch64 only) + +--- + Makefile | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/Makefile b/Makefile +index 10c80d2..e0a7d9e 100644 +--- a/Makefile ++++ b/Makefile +@@ -686,8 +686,8 @@ alldepend:: + ocamldoc: ocamlc ocamlyacc ocamllex otherlibraries + cd ocamldoc && $(MAKE) all + +-ocamldoc.opt: ocamlc.opt ocamlyacc ocamllex +- cd ocamldoc && $(MAKE) opt.opt ++#ocamldoc.opt: ocamlc.opt ocamlyacc ocamllex ++# cd ocamldoc && $(MAKE) opt.opt + + partialclean:: + cd ocamldoc && $(MAKE) clean +@@ -734,8 +734,8 @@ alldepend:: + camlp4out: ocamlc ocamlbuild.byte + ./build/camlp4-byte-only.sh + +-camlp4opt: ocamlopt otherlibrariesopt ocamlbuild-mixed-boot ocamlbuild.native +- ./build/camlp4-native-only.sh ++#camlp4opt: ocamlopt otherlibrariesopt ocamlbuild-mixed-boot ocamlbuild.native ++# ./build/camlp4-native-only.sh + + # Ocamlbuild + #ifeq ($(OCAMLBUILD_NOBOOT),"yes") +-- +1.8.4.2 + diff --git a/ocaml.spec b/ocaml.spec index 5a89ab9..1f4cdac 100644 --- a/ocaml.spec +++ b/ocaml.spec @@ -1,6 +1,6 @@ Name: ocaml Version: 4.01.0 -Release: 4%{?dist} +Release: 5%{?dist} Summary: OCaml compiler and programming environment @@ -35,7 +35,14 @@ Patch0006: 0006-Add-support-for-ppc64.patch Patch0007: 0007-yacc-Use-mkstemp-instead-of-mktemp.patch # NON-upstream patch to allow '--flag=arg' as an alternative to '--flag arg'. -Patch0008: 0001-stdlib-arg-Allow-flags-such-as-flag-arg-as-well-as-f.patch +Patch0008: 0008-stdlib-arg-Allow-flags-such-as-flag-arg-as-well-as-f.patch + +# Aarch64 patches. +%ifarch aarch64 +Patch0009: 0009-Port-to-the-ARM-64-bits-AArch64-architecture-experim.patch +Patch0010: 0010-Updated-with-latest-versions-from-FSF.patch +Patch0011: 0011-Disable-ocamldoc-and-camlp4opt-aarch64-only.patch +%endif BuildRequires: ncurses-devel BuildRequires: gdbm-devel @@ -71,7 +78,7 @@ Provides: ocaml(compiler) = %{version} # We can compile OCaml on just about anything, but the native code # backend is only available on a subset of architectures. -ExclusiveArch: alpha %{arm} ia64 %{ix86} x86_64 ppc ppc64 sparc sparcv9 +ExclusiveArch: aarch64 alpha %{arm} ia64 %{ix86} x86_64 ppc ppc64 sparc sparcv9 %ifarch %{arm} %{ix86} ppc ppc64 sparc sparcv9 x86_64 %global native_compiler 1 @@ -357,6 +364,9 @@ fi %{_bindir}/ocamlopt.opt %{_bindir}/ocamloptp %endif +%ifarch aarch64 +%{_bindir}/ocamloptp +%endif #%{_bindir}/ocamlplugininfo %{_bindir}/ocamlprof %{_bindir}/ocamlyacc @@ -505,6 +515,9 @@ fi %if %{native_compiler} %{_mandir}/man3/* %endif +%ifarch aarch64 +%{_mandir}/man3/* +%endif %files emacs @@ -528,6 +541,9 @@ fi %changelog +* Mon Dec 30 2013 Richard W.M. Jones - 4.01.0-5 +- Add aarch64 (arm64) code generator. + * Thu Nov 21 2013 Richard W.M. Jones - 4.01.0-4 - Add bundled(md5-plumb) (thanks: Tomas Mraz). - Add NON-upstream (but being sent upstream) patch to allow --flag=arg