ocaml/asmcomp/arm/reload.ml

58 lines
2.6 KiB
OCaml

(**************************************************************************)
(* *)
(* OCaml *)
(* *)
(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *)
(* *)
(* Copyright 1998 Institut National de Recherche en Informatique et *)
(* en Automatique. *)
(* *)
(* All rights reserved. This file is distributed under the terms of *)
(* the GNU Lesser General Public License version 2.1, with the *)
(* special exception on linking described in the file LICENSE. *)
(* *)
(**************************************************************************)
open Arch
open Mach
(* Reloading for the ARM *)
class reload = object
inherit Reloadgen.reload_generic as super
method! reload_operation op arg res =
let ((arg', res') as argres') = super#reload_operation op arg res in
match op with
| Iintop Imul | Ispecific Imuladd ->
(* On ARM v4 and v5, module [Selection] adds a second, dummy
result to multiplication instructions (mul and muladd). This
second result is the same pseudoregister as the first
argument to the multiplication. As shown in MPR#7642,
reloading must maintain this invariant. Otherwise, the second
result and the first argument can end up in different registers,
and the second result can be used later, even though
it is not initialized. *)
if Array.length res' >= 2 then res'.(1) <- arg'.(0);
argres'
| Ispecific(Imuladdf | Inegmuladdf | Imulsubf | Inegmulsubf) ->
(* VFP float multiply-add instructions are "two-address" in the
sense that they must have [arg.(0) = res.(0)].
Preserve this invariant. *)
(arg', [|arg'.(0)|])
| Iabsf | Inegf when !fpu = Soft ->
(* Soft FP neg and abs also have a "two-address" constraint of sorts.
64-bit floats are represented by pairs of 32-bit integers,
hence there are two arguments and two results.
The code emitter assumes [arg.(0) = res.(0)] but supports
[arg.(1)] and [res.(1)] being in different registers. *)
res'.(0) <- arg'.(0);
argres'
| _ ->
argres'
end
let fundecl f num_stack_slots =
(new reload)#fundecl f num_stack_slots