summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenedikt Meurer <benedikt.meurer@googlemail.com>2013-01-06 17:07:50 +0000
committerBenedikt Meurer <benedikt.meurer@googlemail.com>2013-01-06 17:07:50 +0000
commite0e2f5fb1b7229dab20fbfb29f99bf5d77d731f7 (patch)
tree0fe35a41ad99840054cc9871c9e36fd3225718ec
parent7efba284ceff49b3e9de91a6d229b6b5caa6ca9b (diff)
downloadocaml-e0e2f5fb1b7229dab20fbfb29f99bf5d77d731f7.tar.gz
[arm] Implement the byte swap operations (PR#5774).
Use rev16/movt to implement direct 16-bit byte-swap operation (ARMv6T2 and above) and rev to implement the 32-bit byte-swap operation (ARMv6 and above). git-svn-id: http://caml.inria.fr/svn/ocaml/trunk@13203 f963ae5c-01c2-4b8c-9fe0-0dff7051ff02
-rw-r--r--asmcomp/arm/arch.ml20
-rw-r--r--asmcomp/arm/emit.mlp10
-rw-r--r--asmcomp/arm/selection.ml6
3 files changed, 28 insertions, 8 deletions
diff --git a/asmcomp/arm/arch.ml b/asmcomp/arm/arch.ml
index a1d88ecc6d..cac286aa48 100644
--- a/asmcomp/arm/arch.ml
+++ b/asmcomp/arm/arch.ml
@@ -110,14 +110,15 @@ type specific_operation =
Ishiftarith of arith_operation * int
| Ishiftcheckbound of int
| Irevsubimm 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 *)
+ | 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
@@ -208,6 +209,9 @@ let print_specific_operation printreg op ppf arg =
| Isqrtf ->
fprintf ppf "sqrtf %a"
printreg arg.(0)
+ | Ibswap n ->
+ fprintf ppf "bswap%i %a" n
+ printreg arg.(0)
(* Recognize immediate operands *)
diff --git a/asmcomp/arm/emit.mlp b/asmcomp/arm/emit.mlp
index e0c531c077..4a12615136 100644
--- a/asmcomp/arm/emit.mlp
+++ b/asmcomp/arm/emit.mlp
@@ -682,6 +682,16 @@ let emit_instr i =
| Imulsub -> "mls"
| _ -> 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`; 1
+ | Lop(Ispecific(Ibswap size)) ->
+ begin match size with
+ 16 ->
+ ` rev16 {emit_reg i.res.(0)}, {emit_reg i.arg.(0)}\n`;
+ ` movt {emit_reg i.res.(0)}, #0\n`; 2
+ | 32 ->
+ ` rev {emit_reg i.res.(0)}, {emit_reg i.arg.(0)}\n`; 1
+ | _ ->
+ assert false
+ end
| Lreloadretaddr ->
let n = frame_size() in
` ldr lr, [sp, #{emit_int(n-4)}]\n`; 1
diff --git a/asmcomp/arm/selection.ml b/asmcomp/arm/selection.ml
index bded362911..547166b91a 100644
--- a/asmcomp/arm/selection.ml
+++ b/asmcomp/arm/selection.ml
@@ -174,6 +174,12 @@ method! select_operation op args =
| (Cmodi, args) ->
(* See above for fix up of return register *)
(Iextcall("__aeabi_idivmod", false), args)
+ (* Recognize 16-bit bswap instruction (ARMv6T2 because we need movt) *)
+ | (Cextcall("caml_bswap16_direct", _, _, _), args) when !arch >= ARMv6T2 ->
+ (Ispecific(Ibswap 16), args)
+ (* Recognize 32-bit bswap instructions (ARMv6 and above) *)
+ | (Cextcall("caml_int32_direct_bswap", _, _, _), args) when !arch >= ARMv6 ->
+ (Ispecific(Ibswap 32), args)
(* Turn floating-point operations into runtime ABI calls for softfp *)
| (op, args) when !fpu = Soft -> self#select_operation_softfp op args
(* Select operations for VFPv{2,3} *)