aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorXavier Leroy <xavier.leroy@inria.fr>2015-05-09 09:00:51 +0200
committerXavier Leroy <xavier.leroy@inria.fr>2015-05-09 09:00:51 +0200
commita6b6bf31121d975c915c01f501618d97df7879fb (patch)
tree061cf73e547622695621fc05ce692c029991c9e0
parent56bac3dc3d45c219db5d9c7b6a97794c00f8115e (diff)
downloadcompcert-kvx-a6b6bf31121d975c915c01f501618d97df7879fb.tar.gz
compcert-kvx-a6b6bf31121d975c915c01f501618d97df7879fb.zip
Extended inline asm: revised treatment of clobbered registers.
- Treat clobbered registers as being destroyed by EF_inline_asm builtins (which is the truth, semantically). - To enable the above, represent clobbers as Coq strings rather than idents and move register_by_name from Machregsaux.ml to Machregs.v. - Side benefit: more efficient implementation of Machregsaux.name_of_register. -# Please enter the commit message for your changes. Lines starting
-rw-r--r--arm/Machregs.v34
-rw-r--r--arm/Machregsaux.ml35
-rw-r--r--arm/Machregsaux.mli1
-rw-r--r--backend/Bounds.v7
-rw-r--r--backend/Regalloc.ml6
-rw-r--r--cfrontend/C2C.ml2
-rw-r--r--cfrontend/PrintCsyntax.ml4
-rw-r--r--common/AST.v4
-rw-r--r--cparser/ExtendedAsm.ml7
-rw-r--r--extraction/extraction.v3
-rw-r--r--ia32/Machregs.v30
-rw-r--r--ia32/Machregsaux.ml31
-rw-r--r--ia32/Machregsaux.mli1
-rw-r--r--powerpc/Machregs.v42
-rw-r--r--powerpc/Machregsaux.ml43
-rw-r--r--powerpc/Machregsaux.mli1
-rw-r--r--test/regression/extasm.c6
17 files changed, 147 insertions, 110 deletions
diff --git a/arm/Machregs.v b/arm/Machregs.v
index f373b434..f46f2904 100644
--- a/arm/Machregs.v
+++ b/arm/Machregs.v
@@ -10,6 +10,7 @@
(* *)
(* *********************************************************************)
+Require Import String.
Require Import Coqlib.
Require Import Maps.
Require Import AST.
@@ -75,6 +76,28 @@ End IndexedMreg.
Definition is_stack_reg (r: mreg) : bool := false.
+(** ** Names of registers *)
+
+Local Open Scope string_scope.
+
+Definition register_names :=
+ ("R0", R0) :: ("R1", R1) :: ("R2", R2) :: ("R3", R3) ::
+ ("R4", R4) :: ("R5", R5) :: ("R6", R6) :: ("R7", R7) ::
+ ("R8", R8) :: ("R9", R9) :: ("R10", R10) :: ("R11", R11) ::
+ ("R12", R12) ::
+ ("F0", F0) :: ("F1", F1) :: ("F2", F2) :: ("F3", F3) ::
+ ("F4", F4) :: ("F5", F5) :: ("F6", F6) :: ("F7", F7) ::
+ ("F8", F8) :: ("F9", F9) :: ("F10", F10) :: ("F11", F11) ::
+ ("F12", F12) ::("F13", F13) ::("F14", F14) :: ("F15", F15) :: nil.
+
+Definition register_by_name (s: string) : option mreg :=
+ let fix assoc (l: list (string * mreg)) : option mreg :=
+ match l with
+ | nil => None
+ | (s1, r1) :: l' => if string_dec s s1 then Some r1 else assoc l'
+ end
+ in assoc register_names.
+
(** ** Destroyed registers, preferred registers *)
Definition destroyed_by_op (op: operation): list mreg :=
@@ -95,9 +118,20 @@ Definition destroyed_by_cond (cond: condition): list mreg :=
Definition destroyed_by_jumptable: list mreg :=
nil.
+Fixpoint destroyed_by_clobber (cl: list string): list mreg :=
+ match cl with
+ | nil => nil
+ | c1 :: cl =>
+ match register_by_name c1 with
+ | Some r => r :: destroyed_by_clobber cl
+ | None => destroyed_by_clobber cl
+ end
+ end.
+
Definition destroyed_by_builtin (ef: external_function): list mreg :=
match ef with
| EF_memcpy sz al => if zle sz 32 then F7 :: nil else R2 :: R3 :: R12 :: nil
+ | EF_inline_asm txt sg clob => destroyed_by_clobber clob
| _ => nil
end.
diff --git a/arm/Machregsaux.ml b/arm/Machregsaux.ml
index 44e6b192..d59ec8b8 100644
--- a/arm/Machregsaux.ml
+++ b/arm/Machregsaux.ml
@@ -12,41 +12,24 @@
(** Auxiliary functions on machine registers *)
+open Camlcoq
open Machregs
-let register_names = [
- ("R0", R0); ("R1", R1); ("R2", R2); ("R3", R3);
- ("R4", R4); ("R5", R5); ("R6", R6); ("R7", R7);
- ("R8", R8); ("R9", R9); ("R10", R10); ("R11", R11);
- ("R12", R12);
- ("F0", F0); ("F1", F1); ("F2", F2); ("F3", F3);
- ("F4", F4); ("F5", F5); ("F6", F6); ("F7", F7);
- ("F8", F8); ("F9", F9); ("F10", F10); ("F11", F11);
- ("F12", F12);("F13", F13);("F14", F14); ("F15", F15)
-]
+let register_names : (mreg, string) Hashtbl.t = Hashtbl.create 31
+
+let _ =
+ List.iter
+ (fun (s, r) -> Hashtbl.add register_names r (camlstring_of_coqstring s))
+ Machregs.register_names
let scratch_register_names = [ "R14" ]
let name_of_register r =
- let rec rev_assoc = function
- | [] -> None
- | (a, b) :: rem -> if b = r then Some a else rev_assoc rem
- in rev_assoc register_names
+ try Some (Hashtbl.find register_names r) with Not_found -> None
let register_by_name s =
- try
- Some(List.assoc (String.uppercase s) register_names)
- with Not_found ->
- None
+ Machregs.register_by_name (coqstring_of_camlstring (String.uppercase s))
let can_reserve_register r =
List.mem r Conventions1.int_callee_save_regs
|| List.mem r Conventions1.float_callee_save_regs
-
-let mregs_of_clobber idl =
- List.fold_left
- (fun l c ->
- match register_by_name (Camlcoq.extern_atom c) with
- | Some r -> r :: l
- | None -> l)
- [] idl
diff --git a/arm/Machregsaux.mli b/arm/Machregsaux.mli
index f0feec96..d4877a62 100644
--- a/arm/Machregsaux.mli
+++ b/arm/Machregsaux.mli
@@ -16,4 +16,3 @@ val name_of_register: Machregs.mreg -> string option
val register_by_name: string -> Machregs.mreg option
val scratch_register_names: string list
val can_reserve_register: Machregs.mreg -> bool
-val mregs_of_clobber: Camlcoq.atom list -> Machregs.mreg list
diff --git a/backend/Bounds.v b/backend/Bounds.v
index 7528b66e..04c1328d 100644
--- a/backend/Bounds.v
+++ b/backend/Bounds.v
@@ -87,8 +87,6 @@ Section BOUNDS.
Variable f: function.
-Parameter mregs_of_clobber: list ident -> list mreg.
-
(** In the proof of the [Stacking] pass, we only need to bound the
registers written by an instruction. Therefore, this function
returns these registers, ignoring registers used only as
@@ -103,7 +101,6 @@ Definition regs_of_instr (i: instruction) : list mreg :=
| Lstore chunk addr args src => nil
| Lcall sig ros => nil
| Ltailcall sig ros => nil
- | Lbuiltin (EF_inline_asm txt typs clob) args res => res ++ mregs_of_clobber clob
| Lbuiltin ef args res => res ++ destroyed_by_builtin ef
| Lannot ef args => nil
| Llabel lbl => nil
@@ -354,9 +351,7 @@ Proof.
(* call *)
eapply size_arguments_bound; eauto.
(* builtin *)
- apply H1. destruct e; apply in_or_app; auto.
- change (destroyed_by_builtin (EF_inline_asm text sg clobbers)) with (@nil mreg) in H2.
- simpl in H2; tauto.
+ apply H1. apply in_or_app; auto.
(* annot *)
apply H0. rewrite slots_of_locs_charact; auto.
Qed.
diff --git a/backend/Regalloc.ml b/backend/Regalloc.ml
index c286e946..aa4efc53 100644
--- a/backend/Regalloc.ml
+++ b/backend/Regalloc.ml
@@ -585,13 +585,11 @@ let add_interfs_instr g instr live =
(* like a move *)
IRC.add_pref g arg res
| EF_inline_asm(txt, sg, clob), _, _ ->
- (* clobbered regs interfere with live set
- and also with res and args for GCC compatibility *)
+ (* clobbered regs interfere with res and args for GCC compatibility *)
List.iter (fun c ->
- match Machregsaux.register_by_name (extern_atom c) with
+ match Machregs.register_by_name c with
| None -> ()
| Some mr ->
- add_interfs_destroyed g across [mr];
add_interfs_list_mreg g args mr;
if sg.sig_res <> None then add_interfs_list_mreg g res mr)
clob
diff --git a/cfrontend/C2C.ml b/cfrontend/C2C.ml
index 94f13aa1..6ecdb14e 100644
--- a/cfrontend/C2C.ml
+++ b/cfrontend/C2C.ml
@@ -847,7 +847,7 @@ let convertAsm loc env txt outputs inputs clobber =
let (txt', output', inputs') =
ExtendedAsm.transf_asm loc env txt outputs inputs clobber in
let clobber' =
- List.map intern_string clobber in
+ List.map (fun s -> coqstring_of_camlstring (String.uppercase s)) clobber in
let ty_res =
match output' with None -> TVoid [] | Some e -> e.etyp in
(* Build the Ebuiltin expression *)
diff --git a/cfrontend/PrintCsyntax.ml b/cfrontend/PrintCsyntax.ml
index 39de282b..bde61cc7 100644
--- a/cfrontend/PrintCsyntax.ml
+++ b/cfrontend/PrintCsyntax.ml
@@ -299,9 +299,9 @@ and extended_asm p txt res args clob =
begin match clob with
| [] -> ()
| c1 :: cl ->
- fprintf p "@ : @[<hov 0>%S" (extern_atom c1);
+ fprintf p "@ : @[<hov 0>%S" (camlstring_of_coqstring c1);
List.iter
- (fun c -> fprintf p ",@ %S" (extern_atom c))
+ (fun c -> fprintf p ",@ %S" (camlstring_of_coqstring c))
cl;
fprintf p "@]"
end;
diff --git a/common/AST.v b/common/AST.v
index 2550844b..08a19789 100644
--- a/common/AST.v
+++ b/common/AST.v
@@ -584,7 +584,7 @@ Inductive external_function : Type :=
(** Another form of annotation that takes one argument, produces
an event carrying the text and the value of this argument,
and returns the value of the argument. *)
- | EF_inline_asm (text: ident) (sg: signature) (clobbers: list ident).
+ | EF_inline_asm (text: ident) (sg: signature) (clobbers: list String.string).
(** Inline [asm] statements. Semantically, treated like an
annotation with no parameters ([EF_annot text nil]). To be
used with caution, as it can invalidate the semantic
@@ -642,7 +642,7 @@ Proof.
generalize ident_eq signature_eq chunk_eq typ_eq zeq Int.eq_dec; intros.
decide equality.
apply list_eq_dec. auto.
- apply list_eq_dec. auto.
+ apply list_eq_dec. apply String.string_dec.
Defined.
Global Opaque external_function_eq.
diff --git a/cparser/ExtendedAsm.ml b/cparser/ExtendedAsm.ml
index 94d23102..fbf8d569 100644
--- a/cparser/ExtendedAsm.ml
+++ b/cparser/ExtendedAsm.ml
@@ -161,9 +161,10 @@ let transf_outputs loc env = function
let check_clobbers loc clob =
List.iter
(fun c ->
- if Machregsaux.register_by_name c <> None
- || List.mem c Machregsaux.scratch_register_names
- || c = "memory" || c = "cc"
+ let c' = String.uppercase c in
+ if Machregsaux.register_by_name c' <> None
+ || List.mem c' Machregsaux.scratch_register_names
+ || c' = "MEMORY" || c' = "CC"
then ()
else error "%aError: unrecognized asm register clobber '%s'"
formatloc loc c)
diff --git a/extraction/extraction.v b/extraction/extraction.v
index 4c400036..f7e99545 100644
--- a/extraction/extraction.v
+++ b/extraction/extraction.v
@@ -77,9 +77,6 @@ Extract Constant Allocation.regalloc => "Regalloc.regalloc".
(* Linearize *)
Extract Constant Linearize.enumerate_aux => "Linearizeaux.enumerate_aux".
-(* Bounds *)
-Extract Constant Bounds.mregs_of_clobber => "Machregsaux.mregs_of_clobber".
-
(* SimplExpr *)
Extract Constant SimplExpr.first_unused_ident => "Camlcoq.first_unused_ident".
Extraction Inline SimplExpr.ret SimplExpr.error SimplExpr.bind SimplExpr.bind2.
diff --git a/ia32/Machregs.v b/ia32/Machregs.v
index a9f2b6c4..65e27599 100644
--- a/ia32/Machregs.v
+++ b/ia32/Machregs.v
@@ -69,6 +69,25 @@ End IndexedMreg.
Definition is_stack_reg (r: mreg) : bool :=
match r with FP0 => true | _ => false end.
+(** ** Names of registers *)
+
+Local Open Scope string_scope.
+
+Definition register_names :=
+ ("EAX", AX) :: ("EBX", BX) :: ("ECX", CX) :: ("EDX", DX) ::
+ ("ESI", SI) :: ("EDI", DI) :: ("EBP", BP) ::
+ ("XMM0", X0) :: ("XMM1", X1) :: ("XMM2", X2) :: ("XMM3", X3) ::
+ ("XMM4", X4) :: ("XMM5", X5) :: ("XMM6", X6) :: ("XMM7", X7) ::
+ ("ST0", FP0) :: nil.
+
+Definition register_by_name (s: string) : option mreg :=
+ let fix assoc (l: list (string * mreg)) : option mreg :=
+ match l with
+ | nil => None
+ | (s1, r1) :: l' => if string_dec s s1 then Some r1 else assoc l'
+ end
+ in assoc register_names.
+
(** ** Destroyed registers, preferred registers *)
Definition destroyed_by_op (op: operation): list mreg :=
@@ -100,7 +119,15 @@ Definition destroyed_by_cond (cond: condition): list mreg :=
Definition destroyed_by_jumptable: list mreg :=
nil.
-Local Open Scope string_scope.
+Fixpoint destroyed_by_clobber (cl: list string): list mreg :=
+ match cl with
+ | nil => nil
+ | c1 :: cl =>
+ match register_by_name c1 with
+ | Some r => r :: destroyed_by_clobber cl
+ | None => destroyed_by_clobber cl
+ end
+ end.
Definition builtin_write16_reversed := ident_of_string "__builtin_write16_reversed".
Definition builtin_write32_reversed := ident_of_string "__builtin_write32_reversed".
@@ -115,6 +142,7 @@ Definition destroyed_by_builtin (ef: external_function): list mreg :=
if ident_eq id builtin_write16_reversed
|| ident_eq id builtin_write32_reversed
then CX :: DX :: nil else nil
+ | EF_inline_asm txt sg clob => destroyed_by_clobber clob
| _ => nil
end.
diff --git a/ia32/Machregsaux.ml b/ia32/Machregsaux.ml
index 5e98b58b..6485e752 100644
--- a/ia32/Machregsaux.ml
+++ b/ia32/Machregsaux.ml
@@ -12,38 +12,25 @@
(** Auxiliary functions on machine registers *)
+open Camlcoq
open Machregs
-let register_names = [
- ("EAX", AX); ("EBX", BX); ("ECX", CX); ("EDX", DX);
- ("ESI", SI); ("EDI", DI); ("EBP", BP);
- ("XMM0", X0); ("XMM1", X1); ("XMM2", X2); ("XMM3", X3);
- ("XMM4", X4); ("XMM5", X5); ("XMM6", X6); ("XMM7", X7);
- ("ST0", FP0)
-]
+let register_names : (mreg, string) Hashtbl.t = Hashtbl.create 31
+
+let _ =
+ List.iter
+ (fun (s, r) -> Hashtbl.add register_names r (camlstring_of_coqstring s))
+ Machregs.register_names
let scratch_register_names = []
let name_of_register r =
- let rec rev_assoc = function
- | [] -> None
- | (a, b) :: rem -> if b = r then Some a else rev_assoc rem
- in rev_assoc register_names
+ try Some (Hashtbl.find register_names r) with Not_found -> None
let register_by_name s =
- try
- Some(List.assoc (String.uppercase s) register_names)
- with Not_found ->
- None
+ Machregs.register_by_name (coqstring_of_camlstring (String.uppercase s))
let can_reserve_register r =
List.mem r Conventions1.int_callee_save_regs
|| List.mem r Conventions1.float_callee_save_regs
-let mregs_of_clobber idl =
- List.fold_left
- (fun l c ->
- match register_by_name (Camlcoq.extern_atom c) with
- | Some r -> r :: l
- | None -> l)
- [] idl
diff --git a/ia32/Machregsaux.mli b/ia32/Machregsaux.mli
index f0feec96..d4877a62 100644
--- a/ia32/Machregsaux.mli
+++ b/ia32/Machregsaux.mli
@@ -16,4 +16,3 @@ val name_of_register: Machregs.mreg -> string option
val register_by_name: string -> Machregs.mreg option
val scratch_register_names: string list
val can_reserve_register: Machregs.mreg -> bool
-val mregs_of_clobber: Camlcoq.atom list -> Machregs.mreg list
diff --git a/powerpc/Machregs.v b/powerpc/Machregs.v
index f7ed7793..3b7cbb76 100644
--- a/powerpc/Machregs.v
+++ b/powerpc/Machregs.v
@@ -10,6 +10,7 @@
(* *)
(* *********************************************************************)
+Require Import String.
Require Import Coqlib.
Require Import Maps.
Require Import AST.
@@ -97,6 +98,36 @@ End IndexedMreg.
Definition is_stack_reg (r: mreg) : bool := false.
+(** ** Names of registers *)
+
+Local Open Scope string_scope.
+
+Definition register_names :=
+ ("R3", R3) :: ("R4", R4) :: ("R5", R5) :: ("R6", R6) ::
+ ("R7", R7) :: ("R8", R8) :: ("R9", R9) :: ("R10", R10) ::
+ ("R11", R11) :: ("R12", R12) ::
+ ("R14", R14) :: ("R15", R15) :: ("R16", R16) ::
+ ("R17", R17) :: ("R18", R18) :: ("R19", R19) :: ("R20", R20) ::
+ ("R21", R21) :: ("R22", R22) :: ("R23", R23) :: ("R24", R24) ::
+ ("R25", R25) :: ("R26", R26) :: ("R27", R27) :: ("R28", R28) ::
+ ("R29", R29) :: ("R30", R30) :: ("R31", R31) ::
+ ("F0", F0) :: ("F1", F1) :: ("F2", F2) :: ("F3", F3) :: ("F4", F4) ::
+ ("F5", F5) :: ("F6", F6) :: ("F7", F7) :: ("F8", F8) ::
+ ("F9", F9) :: ("F10", F10) :: ("F11", F11) :: ("F12", F12) ::
+ ("F13", F13) :: ("F14", F14) :: ("F15", F15) ::
+ ("F16", F16) :: ("F17", F17) :: ("F18", F18) :: ("F19", F19) ::
+ ("F20", F20) :: ("F21", F21) :: ("F22", F22) :: ("F23", F23) ::
+ ("F24", F24) :: ("F25", F25) :: ("F26", F26) :: ("F27", F27) ::
+ ("F28", F28) :: ("F29", F29) :: ("F30", F30) :: ("F31", F31) :: nil.
+
+Definition register_by_name (s: string) : option mreg :=
+ let fix assoc (l: list (string * mreg)) : option mreg :=
+ match l with
+ | nil => None
+ | (s1, r1) :: l' => if string_dec s s1 then Some r1 else assoc l'
+ end
+ in assoc register_names.
+
(** ** Destroyed registers, preferred registers *)
Definition destroyed_by_op (op: operation): list mreg :=
@@ -119,6 +150,16 @@ Definition destroyed_by_cond (cond: condition): list mreg :=
Definition destroyed_by_jumptable: list mreg :=
R12 :: nil.
+Fixpoint destroyed_by_clobber (cl: list string): list mreg :=
+ match cl with
+ | nil => nil
+ | c1 :: cl =>
+ match register_by_name c1 with
+ | Some r => r :: destroyed_by_clobber cl
+ | None => destroyed_by_clobber cl
+ end
+ end.
+
Definition destroyed_by_builtin (ef: external_function): list mreg :=
match ef with
| EF_builtin _ _ => F13 :: nil
@@ -128,6 +169,7 @@ Definition destroyed_by_builtin (ef: external_function): list mreg :=
| EF_vstore_global Mint64 _ _ => R10 :: R11 :: R12 :: nil
| EF_vstore_global _ _ _ => R11 :: R12 :: nil
| EF_memcpy _ _ => R11 :: R12 :: F13 :: nil
+ | EF_inline_asm txt sg clob => destroyed_by_clobber clob
| _ => nil
end.
diff --git a/powerpc/Machregsaux.ml b/powerpc/Machregsaux.ml
index ba111089..8c3017ff 100644
--- a/powerpc/Machregsaux.ml
+++ b/powerpc/Machregsaux.ml
@@ -12,49 +12,24 @@
(** Auxiliary functions on machine registers *)
+open Camlcoq
open Machregs
-let register_names = [
- ("R3", R3); ("R4", R4); ("R5", R5); ("R6", R6);
- ("R7", R7); ("R8", R8); ("R9", R9); ("R10", R10);
- ("R11", R11); ("R12", R12);
- ("R14", R14); ("R15", R15); ("R16", R16);
- ("R17", R17); ("R18", R18); ("R19", R19); ("R20", R20);
- ("R21", R21); ("R22", R22); ("R23", R23); ("R24", R24);
- ("R25", R25); ("R26", R26); ("R27", R27); ("R28", R28);
- ("R29", R29); ("R30", R30); ("R31", R31);
- ("F0", F0); ("F1", F1); ("F2", F2); ("F3", F3); ("F4", F4);
- ("F5", F5); ("F6", F6); ("F7", F7); ("F8", F8);
- ("F9", F9); ("F10", F10); ("F11", F11); ("F12", F12);
- ("F13", F13); ("F14", F14); ("F15", F15);
- ("F16", F16); ("F17", F17); ("F18", F18); ("F19", F19);
- ("F20", F20); ("F21", F21); ("F22", F22); ("F23", F23);
- ("F24", F24); ("F25", F25); ("F26", F26); ("F27", F27);
- ("F28", F28); ("F29", F29); ("F30", F30); ("F31", F31)
-]
+let register_names : (mreg, string) Hashtbl.t = Hashtbl.create 31
+
+let _ =
+ List.iter
+ (fun (s, r) -> Hashtbl.add register_names r (camlstring_of_coqstring s))
+ Machregs.register_names
let scratch_register_names = [ "R0" ]
let name_of_register r =
- let rec rev_assoc = function
- | [] -> None
- | (a, b) :: rem -> if b = r then Some a else rev_assoc rem
- in rev_assoc register_names
+ try Some (Hashtbl.find register_names r) with Not_found -> None
let register_by_name s =
- try
- Some(List.assoc (String.uppercase s) register_names)
- with Not_found ->
- None
+ Machregs.register_by_name (coqstring_of_camlstring (String.uppercase s))
let can_reserve_register r =
List.mem r Conventions1.int_callee_save_regs
|| List.mem r Conventions1.float_callee_save_regs
-
-let mregs_of_clobber idl =
- List.fold_left
- (fun l c ->
- match register_by_name (Camlcoq.extern_atom c) with
- | Some r -> r :: l
- | None -> l)
- [] idl
diff --git a/powerpc/Machregsaux.mli b/powerpc/Machregsaux.mli
index f0feec96..d4877a62 100644
--- a/powerpc/Machregsaux.mli
+++ b/powerpc/Machregsaux.mli
@@ -16,4 +16,3 @@ val name_of_register: Machregs.mreg -> string option
val register_by_name: string -> Machregs.mreg option
val scratch_register_names: string list
val can_reserve_register: Machregs.mreg -> bool
-val mregs_of_clobber: Camlcoq.atom list -> Machregs.mreg list
diff --git a/test/regression/extasm.c b/test/regression/extasm.c
index 4925392e..00a1cd57 100644
--- a/test/regression/extasm.c
+++ b/test/regression/extasm.c
@@ -1,7 +1,7 @@
/* Testing extended asm.
To run the test, compile with -S and grep "TEST" in the generated .s */
-int clobbers(int x)
+int clobbers(int x, int z)
{
int y;
asm("TEST0 out:%0 in:%1" : "=r"(y) : "r"(x) : "cc"
@@ -10,10 +10,10 @@ int clobbers(int x)
#elif defined(__arm__)
, "r0", "r1", "r4"
#elif defined(__PPC__)
- , "r3", "r4", "r31"
+ , "r0", "r3", "r4", "r31"
#endif
);
- return y;
+ return y + z;
}
int main()