1 (***********************************************************************)
5 (* Xavier Leroy, projet Cristal, INRIA Rocquencourt *)
7 (* Copyright 1998 Institut National de Recherche en Informatique et *)
8 (* en Automatique. All rights reserved. This file is distributed *)
9 (* under the terms of the Q Public License version 1.0. *)
11 (***********************************************************************)
13 (* $Id: selection.ml 8768 2008-01-11 16:13:18Z doligez $ *)
15 (* Instruction selection for the ARM processor *)
23 (* Immediate operands are 8-bit immediate values, zero-extended, and rotated
24 right by 0, 2, 4, ... 30 bits.
25 To avoid problems with Caml's 31-bit arithmetic,
26 we check only with 8-bit values shifted left 0 to 22 bits. *)
28 let rec is_immed n shift =
29 if shift > 22 then false
30 else if n land (0xFF lsl shift) = n then true
31 else is_immed n (shift + 2)
33 (* We have 12-bit + sign byte offsets for word accesses,
34 8-bit + sign word offsets for float accesses,
35 and 8-bit + sign byte offsets for bytes and shorts.
36 Use lowest common denominator. *)
38 let is_offset n = n < 256 && n > -256
40 let is_intconst = function Cconst_int n -> true | _ -> false
42 (* Instruction selection *)
43 class selector = object(self)
45 inherit Selectgen.selector_generic as super
47 method is_immediate n =
48 n land 0xFF = n || is_immed n 2
50 method select_addressing = function
51 Cop(Cadda, [arg; Cconst_int n]) when is_offset n ->
53 | Cop(Cadda, [arg1; Cop(Caddi, [arg2; Cconst_int n])]) when is_offset n ->
54 (Iindexed n, Cop(Cadda, [arg1; arg2]))
58 method select_shift_arith op shiftop shiftrevop args =
60 [arg1; Cop(Clsl, [arg2; Cconst_int n])]
61 when n > 0 && n < 32 && not(is_intconst arg2) ->
62 (Ispecific(Ishiftarith(shiftop, n)), [arg1; arg2])
63 | [arg1; Cop(Casr, [arg2; Cconst_int n])]
64 when n > 0 && n < 32 && not(is_intconst arg2) ->
65 (Ispecific(Ishiftarith(shiftop, -n)), [arg1; arg2])
66 | [Cop(Clsl, [arg1; Cconst_int n]); arg2]
67 when n > 0 && n < 32 && not(is_intconst arg1) ->
68 (Ispecific(Ishiftarith(shiftrevop, n)), [arg2; arg1])
69 | [Cop(Casr, [arg1; Cconst_int n]); arg2]
70 when n > 0 && n < 32 && not(is_intconst arg1) ->
71 (Ispecific(Ishiftarith(shiftrevop, -n)), [arg2; arg1])
73 super#select_operation op args
75 method select_operation op args =
79 [arg1; Cconst_int n] when n < 0 && self#is_immediate (-n) ->
80 (Iintop_imm(Isub, -n), [arg1])
82 self#select_shift_arith op Ishiftadd Ishiftadd args
86 [arg1; Cconst_int n] when n < 0 && self#is_immediate (-n) ->
87 (Iintop_imm(Iadd, -n), [arg1])
88 | [Cconst_int n; arg2] when self#is_immediate n ->
89 (Ispecific(Irevsubimm n), [arg2])
91 self#select_shift_arith op Ishiftsub Ishiftsubrev args
93 | Cmuli -> (* no multiply immediate *)
97 [arg1; Cconst_int n] when n = 1 lsl (Misc.log2 n) ->
98 (Iintop_imm(Idiv, n), [arg1])
100 (Iextcall("__divsi3", false), args)
103 begin match args with
104 [arg1; Cconst_int n] when n = 1 lsl (Misc.log2 n) ->
105 (Iintop_imm(Imod, n), [arg1])
107 (Iextcall("__modsi3", false), args)
110 begin match args with
111 [Cop(Clsr, [arg1; Cconst_int n]); arg2]
112 when n > 0 && n < 32 && not(is_intconst arg2) ->
113 (Ispecific(Ishiftcheckbound n), [arg1; arg2])
115 super#select_operation op args
117 | _ -> super#select_operation op args
119 (* In mul rd, rm, rs, the registers rm and rd must be different.
120 We deal with this by pretending that rm is also a result of the mul
123 method insert_op_debug op dbg rs rd =
124 if op = Iintop(Imul) then begin
125 self#insert_debug (Iop op) dbg rs [| rd.(0); rs.(0) |]; rd
127 super#insert_op_debug op dbg rs rd
131 let fundecl f = (new selector)#emit_fundecl f