(**************************************************************************) (* *) (* 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