108 lines
3.6 KiB
OCaml
108 lines
3.6 KiB
OCaml
(***********************************************************************)
|
|
(* *)
|
|
(* Objective Caml *)
|
|
(* *)
|
|
(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *)
|
|
(* *)
|
|
(* Copyright 1997 Institut National de Recherche en Informatique et *)
|
|
(* en Automatique. All rights reserved. This file is distributed *)
|
|
(* under the terms of the Q Public License version 1.0. *)
|
|
(* *)
|
|
(***********************************************************************)
|
|
|
|
(* $Id$ *)
|
|
|
|
(* Instruction selection for the Power PC processor *)
|
|
|
|
open Misc
|
|
open Cmm
|
|
open Reg
|
|
open Arch
|
|
open Mach
|
|
|
|
(* Recognition of addressing modes *)
|
|
|
|
type addressing_expr =
|
|
Asymbol of string
|
|
| Alinear of expression
|
|
| Aadd of expression * expression
|
|
|
|
let rec select_addr = function
|
|
Cconst_symbol s when not toc ->
|
|
(* don't recognize this mode in the TOC-based model *)
|
|
(Asymbol s, 0)
|
|
| Cop((Caddi | Cadda), [arg; Cconst_int m]) ->
|
|
let (a, n) = select_addr arg in (a, n + m)
|
|
| Cop((Caddi | Cadda), [Cconst_int m; arg]) ->
|
|
let (a, n) = select_addr arg in (a, n + m)
|
|
| Cop((Caddi | Cadda), [arg1; arg2]) ->
|
|
begin match (select_addr arg1, select_addr arg2) with
|
|
((Alinear e1, n1), (Alinear e2, n2)) ->
|
|
(Aadd(e1, e2), n1 + n2)
|
|
| _ ->
|
|
(Aadd(arg1, arg2), 0)
|
|
end
|
|
| exp ->
|
|
(Alinear exp, 0)
|
|
|
|
(* Instruction selection *)
|
|
|
|
class selector = object (self)
|
|
|
|
inherit Selectgen.selector_generic as super
|
|
|
|
method is_immediate n = (n <= 32767) && (n >= -32768)
|
|
|
|
method select_addressing exp =
|
|
match select_addr exp with
|
|
(Asymbol s, d) ->
|
|
(Ibased(s, d), Ctuple [])
|
|
| (Alinear e, d) ->
|
|
(Iindexed d, e)
|
|
| (Aadd(e1, e2), d) ->
|
|
if d = 0
|
|
then (Iindexed2, Ctuple[e1; e2])
|
|
else (Iindexed d, Cop(Cadda, [e1; e2]))
|
|
|
|
method select_operation op args =
|
|
match (op, args) with
|
|
(* Prevent the recognition of (x / cst) and (x % cst) when cst is not
|
|
a power of 2, which do not correspond to an instruction. *)
|
|
(Cdivi, [arg; Cconst_int n]) when n = 1 lsl (Misc.log2 n) ->
|
|
(Iintop_imm(Idiv, n), [arg])
|
|
| (Cdivi, _) ->
|
|
(Iintop Idiv, args)
|
|
| (Cmodi, [arg; Cconst_int n]) when n = 1 lsl (Misc.log2 n) ->
|
|
(Iintop_imm(Imod, n), [arg])
|
|
| (Cmodi, _) ->
|
|
(Iintop Imod, args)
|
|
(* The and, or and xor instructions have a different range of immediate
|
|
operands than the other instructions *)
|
|
| (Cand, _) -> self#select_logical Iand args
|
|
| (Cor, _) -> self#select_logical Ior args
|
|
| (Cxor, _) -> self#select_logical Ixor args
|
|
(* intoffloat goes through a library function on the RS6000 *)
|
|
| (Cintoffloat, _) when not powerpc ->
|
|
(Iextcall("itrunc", false), args)
|
|
(* Recognize mult-add and mult-sub instructions *)
|
|
| (Caddf, [Cop(Cmulf, [arg1; arg2]); arg3]) ->
|
|
(Ispecific Imultaddf, [arg1; arg2; arg3])
|
|
| (Caddf, [arg3; Cop(Cmulf, [arg1; arg2])]) ->
|
|
(Ispecific Imultaddf, [arg1; arg2; arg3])
|
|
| (Csubf, [Cop(Cmulf, [arg1; arg2]); arg3]) ->
|
|
(Ispecific Imultsubf, [arg1; arg2; arg3])
|
|
| _ ->
|
|
super#select_operation op args
|
|
|
|
method select_logical op = function
|
|
[arg; Cconst_int n] when n >= 0 && n <= 0xFFFF ->
|
|
(Iintop_imm(op, n), [arg])
|
|
| [Cconst_int n; arg] when n >= 0 && n <= 0xFFFF ->
|
|
(Iintop_imm(op, n), [arg])
|
|
| args ->
|
|
(Iintop op, args)
|
|
|
|
end
|
|
|
|
let fundecl f = (new selector)#emit_fundecl f
|