58 lines
2.6 KiB
OCaml
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
|