Unverified Commit 028aaefc authored by Bernhard Schommer's avatar Bernhard Schommer
Browse files

Implement support for big endian arm targets.

Adds support for the big endian arm targets by making the target
endianess flag configurable, adding support for the big endian
calling conventions, rewriting memory access patterns and adding
big endian versions of the runtime functions.
Bug 19418
parent 4ac759d0
......@@ -202,6 +202,7 @@ compcert.ini: Makefile.config
echo "arch=$(ARCH)"; \
echo "model=$(MODEL)"; \
echo "abi=$(ABI)"; \
echo "endianness=$(ENDIANNESS)"; \
echo "system=$(SYSTEM)"; \
echo "has_runtime_lib=$(HAS_RUNTIME_LIB)"; \
echo "has_standard_headers=$(HAS_STANDARD_HEADERS)"; \
......
......@@ -20,7 +20,7 @@ Require Import ZArith.
Require Import Fappli_IEEE.
Require Import Fappli_IEEE_bits.
Definition big_endian := false.
Parameter big_endian: bool.
Notation align_int64 := 8%Z (only parsing).
Notation align_float64 := 8%Z (only parsing).
......@@ -45,8 +45,7 @@ Definition choose_binop_pl_32 (s1: bool) (pl1: nan_pl 24) (s2: bool) (pl2: nan_p
Definition float_of_single_preserves_sNaN := false.
Global Opaque big_endian
default_pl_64 choose_binop_pl_64
Global Opaque default_pl_64 choose_binop_pl_64
default_pl_32 choose_binop_pl_32
float_of_single_preserves_sNaN.
......
......@@ -185,13 +185,14 @@ let expand_builtin_vload_common chunk base ofs res =
| Mint32, BR(IR res) ->
emit (Pldr (res, base, SOimm ofs))
| Mint64, BR_splitlong(BR(IR res1), BR(IR res2)) ->
let ofs' = Int.add ofs _4 in
let ofs_hi = if Archi.big_endian then ofs else Int.add ofs _4 in
let ofs_lo = if Archi.big_endian then Int.add ofs _4 else ofs in
if base <> res2 then begin
emit (Pldr (res2, base, SOimm ofs));
emit (Pldr (res1, base, SOimm ofs'))
emit (Pldr (res2, base, SOimm ofs_lo));
emit (Pldr (res1, base, SOimm ofs_hi))
end else begin
emit (Pldr (res1, base, SOimm ofs'));
emit (Pldr (res2, base, SOimm ofs))
emit (Pldr (res1, base, SOimm ofs_hi));
emit (Pldr (res2, base, SOimm ofs_lo))
end
| Mfloat32, BR(FR res) ->
emit (Pflds (res, base, ofs))
......@@ -226,9 +227,10 @@ let expand_builtin_vstore_common chunk base ofs src =
| Mint32, BA(IR src) ->
emit (Pstr (src, base, SOimm ofs))
| Mint64, BA_splitlong(BA(IR src1), BA(IR src2)) ->
let ofs' = Int.add ofs _4 in
emit (Pstr (src2, base, SOimm ofs));
emit (Pstr (src1, base, SOimm ofs'))
let ofs_hi = if Archi.big_endian then ofs else Int.add ofs _4 in
let ofs_lo = if Archi.big_endian then Int.add ofs _4 else ofs in
emit (Pstr (src2, base, SOimm ofs_lo));
emit (Pstr (src1, base, SOimm ofs_hi))
| Mfloat32, BA(FR src) ->
emit (Pfsts (src, base, ofs))
| Mfloat64, BA(FR src) ->
......
......@@ -85,15 +85,21 @@ Definition dummy_float_reg := F0. (**r Used in [Coloring]. *)
For the "softfloat" convention, results of FP types should be passed
in [R0] or [R0,R1]. This doesn't fit the CompCert register model,
so we have code in [arm/PrintAsm.ml] that inserts additional moves
to/from [F0]. *)
so we have code in [arm/TargetPrinter.ml] that inserts additional moves
to/from [F0].
Concerning endianness for 64bit values in register pairs, the contents
of the registers is as if the value had been loaded from memory
representation with a single LDM instruction. *)
Definition loc_result (s: signature) : rpair mreg :=
match s.(sig_res) with
| None => One R0
| Some (Tint | Tany32) => One R0
| Some (Tfloat | Tsingle | Tany64) => One F0
| Some Tlong => Twolong R1 R0
| Some Tlong => if Archi.big_endian
then Twolong R0 R1
else Twolong R1 R0
end.
(** The result registers have types compatible with that given in the signature. *)
......@@ -102,7 +108,7 @@ Lemma loc_result_type:
forall sig,
subtype (proj_sig_res sig) (typ_rpair mreg_type (loc_result sig)) = true.
Proof.
intros. unfold proj_sig_res, loc_result. destruct (sig_res sig) as [[]|]; auto.
intros. unfold proj_sig_res, loc_result. destruct (sig_res sig) as [[]|]; destruct Archi.big_endian; auto.
Qed.
(** The result locations are caller-save registers *)
......@@ -112,7 +118,7 @@ Lemma loc_result_caller_save:
forall_rpair (fun r => is_callee_save r = false) (loc_result s).
Proof.
intros.
unfold loc_result. destruct (sig_res s) as [[]|]; simpl; auto.
unfold loc_result. destruct (sig_res s) as [[]|]; destruct Archi.big_endian; simpl; auto.
Qed.
(** If the result is in a pair of registers, those registers are distinct and have type [Tint] at least. *)
......@@ -124,7 +130,9 @@ Lemma loc_result_pair:
| Twolong r1 r2 => r1 <> r2 /\ sg.(sig_res) = Some Tlong /\ subtype Tint (mreg_type r1) = true /\ subtype Tint (mreg_type r2) = true
end.
Proof.
intros; unfold loc_result; destruct (sig_res sg) as [[]|]; auto. intuition congruence.
intros; unfold loc_result; destruct (sig_res sg) as [[]|]; destruct Archi.big_endian; auto.
intuition congruence.
intuition congruence.
Qed.
(** ** Location of function arguments *)
......@@ -176,11 +184,13 @@ Fixpoint loc_arguments_hf
then One (R (freg_param fr)) :: loc_arguments_hf tys ir (fr + 1) ofs
else One (S Outgoing ofs Tsingle) :: loc_arguments_hf tys ir fr (ofs + 1)
| Tlong :: tys =>
let ohi := if Archi.big_endian then 0 else 1 in
let olo := if Archi.big_endian then 1 else 0 in
let ir := align ir 2 in
if zlt ir 4
then Twolong (R (ireg_param (ir + 1))) (R (ireg_param ir)) :: loc_arguments_hf tys (ir + 2) fr ofs
then Twolong (R (ireg_param (ir + ohi))) (R (ireg_param (ir + olo))) :: loc_arguments_hf tys (ir + 2) fr ofs
else let ofs := align ofs 2 in
Twolong (S Outgoing (ofs + 1) Tint) (S Outgoing ofs Tint) :: loc_arguments_hf tys ir fr (ofs + 2)
Twolong (S Outgoing (ofs + ohi) Tint) (S Outgoing (ofs + olo) Tint) :: loc_arguments_hf tys ir fr (ofs + 2)
end.
(** For the "softfloat" configuration, as well as for variable-argument functions
......@@ -218,9 +228,11 @@ Fixpoint loc_arguments_sf
One (if zlt ofs 0 then R (freg_param (ofs + 4)) else S Outgoing ofs Tsingle)
:: loc_arguments_sf tys (ofs + 1)
| Tlong :: tys =>
let ohi := if Archi.big_endian then 0 else 1 in
let olo := if Archi.big_endian then 1 else 0 in
let ofs := align ofs 2 in
Twolong (if zlt ofs 0 then R (ireg_param (ofs+1+4)) else S Outgoing (ofs+1) Tint)
(if zlt ofs 0 then R (ireg_param (ofs+4)) else S Outgoing ofs Tint)
Twolong (if zlt ofs 0 then R (ireg_param (ofs+ohi+4)) else S Outgoing (ofs+ohi) Tint)
(if zlt ofs 0 then R (ireg_param (ofs+olo+4)) else S Outgoing (ofs+olo) Tint)
:: loc_arguments_sf tys (ofs + 2)
end.
......@@ -341,9 +353,9 @@ Proof.
set (ir' := align ir 2) in *.
assert (ofs <= align ofs 2) by (apply align_le; omega).
destruct (zlt ir' 4).
destruct H. subst p. split; apply ireg_param_caller_save.
destruct H. subst p. split; apply ireg_param_caller_save.
eapply IHtyl; eauto.
destruct H. subst p. split; (split; [ omega | auto ]).
destruct H. subst p. split; destruct Archi.big_endian; (split; [ omega | auto ]).
eapply Y. eapply IHtyl; eauto. omega.
- (* single *)
destruct (zlt fr 8); destruct H.
......@@ -396,7 +408,7 @@ Proof.
destruct H.
destruct (zlt ofs' 0); subst p.
split; apply ireg_param_caller_save.
split; (split; [xomega|auto]).
split; destruct Archi.big_endian; (split; [xomega|auto]).
eapply Y. eapply IHtyl; eauto. omega.
- (* single *)
destruct H.
......@@ -513,6 +525,12 @@ Proof.
- (* long *)
destruct (zlt (align ir 2) 4).
destruct H. discriminate. destruct H. discriminate. eauto.
destruct Archi.big_endian.
destruct H. inv H.
eapply Zle_trans. 2: apply size_arguments_hf_above. simpl; omega.
destruct H. inv H.
rewrite <- Zplus_assoc. simpl. apply size_arguments_hf_above.
eauto.
destruct H. inv H.
rewrite <- Zplus_assoc. simpl. apply size_arguments_hf_above.
destruct H. inv H.
......@@ -556,9 +574,15 @@ Proof.
eauto.
- (* long *)
destruct H.
destruct Archi.big_endian.
destruct (zlt (align ofs0 2) 0); inv H.
eapply Zle_trans. 2: apply size_arguments_sf_above. simpl; xomega.
destruct (zlt (align ofs0 2) 0); inv H.
rewrite <- Zplus_assoc. simpl. apply size_arguments_sf_above.
destruct H.
destruct Archi.big_endian.
destruct (zlt (align ofs0 2) 0); inv H.
rewrite <- Zplus_assoc. simpl. apply size_arguments_sf_above.
destruct (zlt (align ofs0 2) 0); inv H.
eapply Zle_trans. 2: apply size_arguments_sf_above. simpl; xomega.
eauto.
......
......@@ -220,10 +220,12 @@ module Target (Opt: PRINTER_OPTIONS) : TARGET =
fprintf oc " .balign 4\n";
Hashtbl.iter
(fun bf lbl ->
(* Little-endian floats *)
(* Big or little-endian floats *)
let bfhi = Int64.shift_right_logical bf 32
and bflo = Int64.logand bf 0xFFFF_FFFFL in
fprintf oc ".L%d: .word 0x%Lx, 0x%Lx\n" lbl bflo bfhi)
if Archi.big_endian
then fprintf oc ".L%d: .word 0x%Lx, 0x%Lx\n" lbl bfhi bflo
else fprintf oc ".L%d: .word 0x%Lx, 0x%Lx\n" lbl bflo bfhi)
float_labels;
Hashtbl.iter
(fun bf lbl ->
......@@ -310,7 +312,9 @@ module Target (Opt: PRINTER_OPTIONS) : TARGET =
| (Tfloat | Tany64) :: tyl' ->
let i = (i + 1) land (-2) in
if i >= 4 then 0 else begin
fixup_double oc dir (freg_param i) (ireg_param i) (ireg_param (i+1));
if Archi.big_endian
then fixup_double oc dir (freg_param i) (ireg_param (i+1)) (ireg_param i)
else fixup_double oc dir (freg_param i) (ireg_param i) (ireg_param (i+1));
1 + fixup (i+2) tyl'
end
| Tsingle :: tyl' ->
......@@ -855,14 +859,12 @@ module Target (Opt: PRINTER_OPTIONS) : TARGET =
cfi_section oc
end
let print_epilogue oc =
if !Clflags.option_g then begin
Debug.compute_gnu_file_enum (fun f -> ignore (print_file oc f));
section oc Section_text;
end
let default_falignment = 4
let label = elf_label
......
......@@ -24,3 +24,7 @@ Extract Constant Archi.abi =>
| ""hardfloat"" -> Hardfloat
| _ -> assert false
end".
(* Choice of endianness *)
Extract Constant Archi.big_endian =>
"Configuration.is_big_endian".
......@@ -1890,7 +1890,8 @@ Proof.
{ eapply loc_unconstrained_satisf. eapply can_undef_satisf; eauto.
eapply reg_unconstrained_satisf. eauto.
eapply add_equations_satisf; eauto. assumption.
rewrite Regmap.gss. apply Val.lessdef_trans with v1'; auto.
rewrite Regmap.gss.
apply Val.lessdef_trans with v1'; unfold sel_val; unfold kind_first_word; unfold v1'; destruct Archi.big_endian; auto.
}
exploit (exec_moves mv2); eauto. intros [ls3 [A3 B3]].
assert (LD3: Val.lessdef_list rs##args (reglist ls3 args2')).
......@@ -1906,7 +1907,8 @@ Proof.
assert (SAT4: satisf (rs#dst <- v) ls4 e0).
{ eapply loc_unconstrained_satisf. eapply can_undef_satisf; eauto.
eapply add_equations_satisf; eauto. assumption.
rewrite Regmap.gss. apply Val.lessdef_trans with v2'; auto.
rewrite Regmap.gss.
apply Val.lessdef_trans with v2'; unfold sel_val; unfold kind_second_word; unfold v2'; destruct Archi.big_endian; auto.
}
exploit (exec_moves mv3); eauto. intros [ls5 [A5 B5]].
econstructor; split.
......@@ -1938,7 +1940,8 @@ Proof.
set (ls2 := Locmap.set (R dst') v1'' (undef_regs (destroyed_by_load Mint32 addr) ls1)).
assert (SAT2: satisf (rs#dst <- v) ls2 e0).
{ eapply parallel_assignment_satisf; eauto.
apply Val.lessdef_trans with v1'; auto.
apply Val.lessdef_trans with v1';
unfold sel_val; unfold kind_first_word; unfold v1'; destruct Archi.big_endian; auto.
eapply can_undef_satisf. eauto. eapply add_equations_satisf; eauto.
}
exploit (exec_moves mv2); eauto. intros [ls3 [A3 B3]].
......@@ -1968,7 +1971,7 @@ Proof.
set (ls2 := Locmap.set (R dst') v2'' (undef_regs (destroyed_by_load Mint32 addr2) ls1)).
assert (SAT2: satisf (rs#dst <- v) ls2 e0).
{ eapply parallel_assignment_satisf; eauto.
apply Val.lessdef_trans with v2'; auto.
apply Val.lessdef_trans with v2'; unfold sel_val; unfold kind_second_word; unfold v2'; destruct Archi.big_endian; auto.
eapply can_undef_satisf. eauto. eapply add_equations_satisf; eauto.
}
exploit (exec_moves mv2); eauto. intros [ls3 [A3 B3]].
......
......@@ -864,11 +864,12 @@ Proof.
with ((Byte Byte.zero :: nil) ++ list_repeat n0 (Byte Byte.zero)).
apply Mem.loadbytes_concat.
eapply Mem.loadbytes_unchanged_on with (P := fun b1 ofs1 => ofs1 = p).
eapply store_zeros_unchanged; eauto. intros; omega.
eapply store_zeros_unchanged; eauto. intros; omega.
intros; omega.
change (Byte Byte.zero :: nil) with (encode_val Mint8unsigned Vzero).
replace (Byte Byte.zero :: nil) with (encode_val Mint8unsigned Vzero).
change 1 with (size_chunk Mint8unsigned).
eapply Mem.loadbytes_store_same; eauto.
unfold encode_val; unfold encode_int; unfold rev_if_be; destruct Archi.big_endian; reflexivity.
eapply IHo; eauto. omega. omega. omega. omega.
+ eapply IHo; eauto. omega. omega.
- discriminate.
......@@ -973,7 +974,7 @@ Proof.
transitivity (Some(decode_val chunk (list_repeat (size_chunk_nat chunk) (Byte Byte.zero)))).
apply Mem.loadbytes_load; auto. rewrite size_chunk_conv.
eapply store_zeros_loadbytes; eauto. rewrite <- size_chunk_conv; auto.
f_equal. destruct chunk; reflexivity.
f_equal. destruct chunk; unfold decode_val; unfold decode_int; unfold rev_if_be; destruct Archi.big_endian; reflexivity.
Qed.
Fixpoint load_store_init_data (m: mem) (b: block) (p: Z) (il: list init_data) {struct il} : Prop :=
......
......@@ -12,7 +12,7 @@
# #
#######################################################################
prefix=/usr/local
prefix='/usr/local'
bindir='$(PREFIX)/bin'
libdir='$(PREFIX)/lib/compcert'
toolprefix=''
......@@ -24,44 +24,51 @@ clightgen=false
usage='Usage: ./configure [options] target
Supported targets:
ppc-eabi (PowerPC, EABI with GNU/Unix tools)
ppc-eabi-diab (PowerPC, EABI with Diab tools)
ppc-linux (PowerPC, Linux)
arm-eabi (ARM, EABI)
arm-linux (ARM, EABI)
arm-eabihf (ARM, EABI using hardware FP registers)
arm-hardfloat (ARM, EABI using hardware FP registers)
ia32-linux (x86 32 bits, Linux)
ia32-bsd (x86 32 bits, BSD)
ia32-macosx (x86 32 bits, MacOS X)
ia32-cygwin (x86 32 bits, Cygwin environment under Windows)
manual (edit configuration file by hand)
ppc-eabi (PowerPC, EABI with GNU/Unix tools)
ppc-eabi-diab (PowerPC, EABI with Diab tools)
ppc-linux (PowerPC, Linux)
arm-eabi (ARM, EABI)
arm-linux (ARM, EABI)
arm-eabihf (ARM, EABI using hardware FP registers)
arm-hardfloat (ARM, EABI using hardware FP registers)
ia32-linux (x86 32 bits, Linux)
ia32-bsd (x86 32 bits, BSD)
ia32-macosx (x86 32 bits, MacOS X)
ia32-cygwin (x86 32 bits, Cygwin environment under Windows)
manual (edit configuration file by hand)
For PowerPC targets, the "ppc-" prefix can be refined into:
ppc64- PowerPC 64 bits
e5500- Freescale e5500 core (PowerPC 64 bits + EREF extensions)
ppc64- PowerPC 64 bits
e5500- Freescale e5500 core (PowerPC 64 bit, EREF extensions)
For ARM targets, the "arm-" prefix can be refined into:
armv6- ARMv6 + VFPv2
armv7a- ARMv7-A + VFPv3-d16 (default)
armv7r- ARMv7-R + VFPv3-d16
armv7m- ARMv7-M + VFPv3-d16
armv6- ARMv6 + VFPv2
armv7a- ARMv7-A + VFPv3-d16 (default)
armv7r- ARMv7-R + VFPv3-d16
armv7m- ARMv7-M + VFPv3-d16
For ARM targets, the endianness can optionally be speficied as a suffix:
-big Big endian
-little Little endian (default)
Options:
-prefix <dir> Install in <dir>/bin and <dir>/lib/compcert
-bindir <dir> Install binaries in <dir>
-libdir <dir> Install libraries in <dir>
-toolprefix <pref> Prefix names of tools ("gcc", etc) with <pref>
-no-runtime-lib Do not compile nor install the runtime support library
-prefix <dir> Install in <dir>/bin and <dir>/lib/compcert
-bindir <dir> Install binaries in <dir>
-libdir <dir> Install libraries in <dir>
-toolprefix <pref> Prefix names of tools ("gcc", etc) with <pref>
-no-runtime-lib Do not compile nor install the runtime support library
-no-standard-headers Do not install nor use the standard .h headers
-clightgen Also compile the clightgen tool
-clightgen Also compile the clightgen tool
'
# Parse command-line arguments
#
# Parse Command-Line Arguments
#
while : ; do
case "$1" in
"") break;;
"")
break;;
-prefix|--prefix)
prefix="$2"; shift;;
-bindir|--bindir)
......@@ -83,179 +90,260 @@ while : ; do
shift
done
# Per-target configuration
casmruntime=""
#
# Extract Architecture, Model and Default Endianness
#
case "$target" in
arm-*|armv7a-*)
arch="arm"; model="armv7a"; endianness="little";;
armv6-*)
arch="arm"; model="armv6"; endianness="little";;
armv7r-*)
arch="arm"; model="armv7r"; endianness="little";;
armv7m-*)
arch="arm"; model="armv7m"; endianness="little";;
ia32-*)
arch="ia32"; model="sse2"; endianness="little";;
powerpc-*|ppc-*)
arch="powerpc"; model="ppc32"; endianness="big";;
powerpc64-*|ppc64-*)
arch="powerpc"; model="ppc64"; endianness="big";;
e5500-*)
arch="powerpc"; model="e5500"; endianness="big";;
manual)
;;
"")
echo "Error: no target architecture specified." 1>&2
echo "$usage" 1>&2
exit 2
;;
*)
echo "Error: unknown target architecture: '$target'." 1>&2
echo "$usage" 1>&2
exit 2
;;
esac
target=${target#[a-zA-Z0-9]*-}
#
# ARM: Optional Endianness Specification
#
if test "$arch" = "arm"; then
case "$target" in
*-big)
endianness="big";
target=${target%"-big"}
;;
*-little)
endianness="little";
target=${target%"-little"}
;;
esac
else
case "$target" in
*-big|*-little)
echo "Error: endianness may only be specified for ARM architecture." 1>&2
echo "$usage" 1>&2
exit 2
;;
*)
;;
esac
fi
# Per-target configuration
asm_supports_cfi=""
struct_passing=""
struct_return=""
casm_options=""
cprepro_options=""
casmruntime=""
clinker_options=""
cprepro_options=""
struct_passing=""
struct_return=""
case "$target" in
powerpc-*|ppc-*|powerpc64-*|ppc64-*|e5500-*)
arch="powerpc"
case "$target" in
powerpc64-*|ppc64-*) model="ppc64";;
e5500-*) model="e5500";;
*) model="ppc32";;
esac
abi="eabi"
struct_passing="ref-caller"
case "$target" in
*-linux) struct_return="ref";;
*) struct_return="int1-8";;
esac
case "$target" in
*-eabi-diab)
system="diab"
cc="${toolprefix}dcc"
cprepro="${toolprefix}dcc"
cprepro_options="-E -D__GNUC__"
#
# ARM Target Configuration
#
if test "$arch" = "arm"; then
case "$target" in
eabi|linux)
abi="eabi"
;;
eabihf|hf|hardfloat)
abi="hardfloat"
;;
*)
echo "Error: invalid eabi/system '$target' for architecture ARM." 1>&2
echo "$usage" 1>&2
exit 2;;
esac
casm="${toolprefix}gcc"
casm_options="-c"
cc="${toolprefix}gcc"
clinker="${toolprefix}gcc"
cprepro="${toolprefix}gcc"
cprepro_options="-std=c99 -U__GNUC__ '-D__REDIRECT(name,proto,alias)=name proto' '-D__REDIRECT_NTH(name,proto,alias)=name proto' -E"
libmath="-lm"
struct_passing="ints"
struct_return="int1-4"
system="linux"
fi
#
# PowerPC Target Configuration
#
if test "$arch" = "powerpc"; then
case "$target" in
eabi|eabi-diab|linux)
;;
*)
echo "Error: invalid eabi/system '$target' for architecture PowerPC." 1>&2
echo "$usage" 1>&2
exit 2;;
esac
case "$target" in
linux)
struct_return="ref"
;;
*)
struct_return="int1-8"
;;
esac
case "$target" in
eabi-diab)
abi="eabi"
asm_supports_cfi=false
casm="${toolprefix}das"
casm_options="-Xalign-value"
asm_supports_cfi=false
cc="${toolprefix}dcc"
clinker="${toolprefix}dcc"
cprepro="${toolprefix}dcc"
cprepro_options="-E -D__GNUC__"
libmath="-lm"
struct_passing="ref-caller"
system="diab"
;;
*)
system="linux"
*)
abi="eabi"
casm="${toolprefix}gcc"
casm_options="-c"
casmruntime="${toolprefix}gcc -c -Wa,-mregnames"
cc="${toolprefix}gcc"
clinker="${toolprefix}gcc"
cprepro="${toolprefix}gcc"
cprepro_options="-std=c99 -U__GNUC__ -E"
libmath="-lm"
struct_passing="ref-caller"
system="linux"
;;
esac
fi
#
# IA32 Target Configuration
#
if test "$arch" = "ia32"; then
case "$target" in
bsd)
abi="standard"
casm="${toolprefix}gcc"
casm_options="-c"
casmruntime="${toolprefix}gcc -c -Wa,-mregnames"
casm_options="-m32 -c"
cc="${toolprefix}gcc -m32"
clinker="${toolprefix}gcc"
clinker_options="-m32"
cprepro="${toolprefix}gcc"
cprepro_options="-std=c99 -m32 -U__GNUC__ -E"
libmath="-lm"
esac;;
arm*-*)
arch="arm"
case "$target" in
armv6-*) model="armv6";;
arm-*|armv7a-*) model="armv7a";;
armv7r-*) model="armv7r";;