Merge pull request #9864 from xavierleroy/is_immediate-refactored
Revised detection of arithmetic instructions with immediate operandsmaster
commit
72dbcb8433
|
@ -109,6 +109,7 @@ testsuite/tests/lib-unix/win-stat/fakeclock.c typo.missing-header=fals
|
|||
testsuite/tests/misc-unsafe/almabench.ml typo.long-line
|
||||
testsuite/tests/tool-toplevel/strings.ml typo.utf8
|
||||
testsuite/tests/win-unicode/*.ml typo.utf8
|
||||
testsuite/tests/asmgen/immediates.cmm typo.very-long-line
|
||||
testsuite/tools/*.S typo.missing-header
|
||||
testsuite/tools/*.asm typo.missing-header
|
||||
testsuite/typing typo.missing-header
|
||||
|
|
5
Changes
5
Changes
|
@ -149,6 +149,11 @@ Working version
|
|||
possible, improving instruction selection.
|
||||
(Stephen Dolan, review by Leo White and Xavier Leroy)
|
||||
|
||||
- #9864: Revised recognition of immediate arguments to integer operations.
|
||||
Fixes several issues that could have led to producing assembly code
|
||||
that is rejected by the assembler.
|
||||
(Xavier Leroy, review by Stephen Dolan)
|
||||
|
||||
### Standard library:
|
||||
|
||||
- #9865: add Format.pp_print_seq
|
||||
|
|
|
@ -121,17 +121,24 @@ let inline_ops =
|
|||
[ "sqrt"; "caml_bswap16_direct"; "caml_int32_direct_bswap";
|
||||
"caml_int64_direct_bswap"; "caml_nativeint_direct_bswap" ]
|
||||
|
||||
let is_immediate n = n <= 0x7FFF_FFFF && n >= -0x8000_0000
|
||||
|
||||
let is_immediate_natint n = n <= 0x7FFF_FFFFn && n >= -0x8000_0000n
|
||||
|
||||
(* The selector class *)
|
||||
|
||||
class selector = object (self)
|
||||
|
||||
inherit Spacetime_profiling.instruction_selection as super
|
||||
|
||||
method is_immediate n = n <= 0x7FFF_FFFF && n >= (-1-0x7FFF_FFFF)
|
||||
(* -1-.... : hack so that this can be compiled on 32-bit
|
||||
(cf 'make check_all_arches') *)
|
||||
method! is_immediate op n =
|
||||
match op with
|
||||
| Iadd | Isub | Imul | Iand | Ior | Ixor | Icomp _ | Icheckbound _ ->
|
||||
is_immediate n
|
||||
| _ ->
|
||||
super#is_immediate op n
|
||||
|
||||
method is_immediate_natint n = n <= 0x7FFFFFFFn && n >= -0x80000000n
|
||||
method is_immediate_test _cmp n = is_immediate n
|
||||
|
||||
method! is_simple_expr e =
|
||||
match e with
|
||||
|
@ -153,7 +160,7 @@ method! effects_of e =
|
|||
method select_addressing _chunk exp =
|
||||
let (a, d) = select_addr exp in
|
||||
(* PR#4625: displacement must be a signed 32-bit immediate *)
|
||||
if not (self # is_immediate d)
|
||||
if not (is_immediate d)
|
||||
then (Iindexed 0, exp)
|
||||
else match a with
|
||||
| Asymbol s ->
|
||||
|
@ -169,12 +176,12 @@ method select_addressing _chunk exp =
|
|||
|
||||
method! select_store is_assign addr exp =
|
||||
match exp with
|
||||
Cconst_int (n, _dbg) when self#is_immediate n ->
|
||||
Cconst_int (n, _dbg) when is_immediate n ->
|
||||
(Ispecific(Istore_int(Nativeint.of_int n, addr, is_assign)), Ctuple [])
|
||||
| (Cconst_natint (n, _dbg)) when self#is_immediate_natint n ->
|
||||
| (Cconst_natint (n, _dbg)) when is_immediate_natint n ->
|
||||
(Ispecific(Istore_int(n, addr, is_assign)), Ctuple [])
|
||||
| (Cblockheader(n, _dbg))
|
||||
when self#is_immediate_natint n && not Config.spacetime ->
|
||||
when is_immediate_natint n && not Config.spacetime ->
|
||||
(Ispecific(Istore_int(n, addr, is_assign)), Ctuple [])
|
||||
| _ ->
|
||||
super#select_store is_assign addr exp
|
||||
|
@ -211,7 +218,7 @@ method! select_operation op args dbg =
|
|||
| Cstore ((Word_int|Word_val as chunk), _init) ->
|
||||
begin match args with
|
||||
[loc; Cop(Caddi, [Cop(Cload _, [loc'], _); Cconst_int (n, _dbg)], _)]
|
||||
when loc = loc' && self#is_immediate n ->
|
||||
when loc = loc' && is_immediate n ->
|
||||
let (addr, arg) = self#select_addressing chunk loc in
|
||||
(Ispecific(Ioffset_loc(n, addr)), [arg])
|
||||
| _ ->
|
||||
|
@ -224,12 +231,9 @@ method! select_operation op args dbg =
|
|||
| Cextcall("caml_int64_direct_bswap", _, _, _, _)
|
||||
| Cextcall("caml_nativeint_direct_bswap", _, _, _, _) ->
|
||||
(Ispecific (Ibswap 64), args)
|
||||
(* AMD64 does not support immediate operands for multiply high signed *)
|
||||
| Cmulhi ->
|
||||
(Iintop Imulh, args)
|
||||
(* Recognize sign extension *)
|
||||
| Casr ->
|
||||
begin match args with
|
||||
(* Recognize sign extension *)
|
||||
[Cop(Clsl, [k; Cconst_int (32, _)], _); Cconst_int (32, _)] ->
|
||||
(Ispecific Isextend32, [k])
|
||||
| _ -> super#select_operation op args dbg
|
||||
|
|
|
@ -102,8 +102,15 @@ method! regs_for tyv =
|
|||
tyv
|
||||
end)
|
||||
|
||||
method is_immediate n =
|
||||
is_immediate (Int32.of_int n)
|
||||
method! is_immediate op n =
|
||||
match op with
|
||||
| Iadd | Isub | Iand | Ior | Ixor | Icomp _ | Icheckbound _ ->
|
||||
Arch.is_immediate (Int32.of_int n)
|
||||
| _ ->
|
||||
super#is_immediate op n
|
||||
|
||||
method is_immediate_test _op n =
|
||||
Arch.is_immediate (Int32.of_int n)
|
||||
|
||||
method! is_simple_expr = function
|
||||
(* inlined floating-point ops are simple if their arguments are *)
|
||||
|
@ -185,18 +192,19 @@ method private iextcall func ty_res ty_args =
|
|||
|
||||
method! select_operation op args dbg =
|
||||
match (op, args) with
|
||||
(* Recognize special shift arithmetic *)
|
||||
((Caddv | Cadda | Caddi), [arg; Cconst_int (n, _)])
|
||||
when n < 0 && self#is_immediate (-n) ->
|
||||
(* Recognize special forms of add immediate / sub immediate *)
|
||||
| ((Caddv | Cadda | Caddi), [arg; Cconst_int (n, _)])
|
||||
when n < 0 && Arch.is_immediate (Int32.of_int (-n)) ->
|
||||
(Iintop_imm(Isub, -n), [arg])
|
||||
| ((Caddv | Cadda | Caddi as op), args) ->
|
||||
self#select_shift_arith op dbg Ishiftadd Ishiftadd args
|
||||
| (Csubi, [arg; Cconst_int (n, _)])
|
||||
when n < 0 && self#is_immediate (-n) ->
|
||||
when n < 0 && Arch.is_immediate (Int32.of_int (-n)) ->
|
||||
(Iintop_imm(Iadd, -n), [arg])
|
||||
| (Csubi, [Cconst_int (n, _); arg])
|
||||
when self#is_immediate n ->
|
||||
when Arch.is_immediate (Int32.of_int n) ->
|
||||
(Ispecific(Irevsubimm n), [arg])
|
||||
(* Recognize special shift arithmetic *)
|
||||
| ((Caddv | Cadda | Caddi as op), args) ->
|
||||
self#select_shift_arith op dbg Ishiftadd Ishiftadd args
|
||||
| (Csubi as op, args) ->
|
||||
self#select_shift_arith op dbg Ishiftsub Ishiftsubrev args
|
||||
| (Cand as op, args) ->
|
||||
|
@ -209,11 +217,6 @@ method! select_operation op args dbg =
|
|||
[Cop(Clsl | Clsr | Casr as op, [arg1; Cconst_int (n, _)], _); arg2])
|
||||
when n > 0 && n < 32 ->
|
||||
(Ispecific(Ishiftcheckbound(select_shiftop op, n)), [arg1; arg2])
|
||||
(* ARM does not support immediate operands for multiplication *)
|
||||
| (Cmuli, args) ->
|
||||
(Iintop Imul, args)
|
||||
| (Cmulhi, args) ->
|
||||
(Iintop Imulh, args)
|
||||
(* Turn integer division/modulus into runtime ABI calls *)
|
||||
| (Cdivi, args) ->
|
||||
(self#iextcall "__aeabi_idiv" typ_int [], args)
|
||||
|
|
|
@ -321,6 +321,37 @@ let output_epilogue f =
|
|||
(* reset CFA back because function body may continue *)
|
||||
if n > 0 then cfi_adjust_cfa_offset n
|
||||
|
||||
(* Output add-immediate / sub-immediate / cmp-immediate instructions *)
|
||||
|
||||
let rec emit_addimm rd rs n =
|
||||
if n < 0 then emit_subimm rd rs (-n)
|
||||
else if n <= 0xFFF then
|
||||
` add {emit_reg rd}, {emit_reg rs}, #{emit_int n}\n`
|
||||
else begin
|
||||
assert (n <= 0xFFF_FFF);
|
||||
let nl = n land 0xFFF and nh = n land 0xFFF_000 in
|
||||
` add {emit_reg rd}, {emit_reg rs}, #{emit_int nh}\n`;
|
||||
if nl <> 0 then
|
||||
` add {emit_reg rd}, {emit_reg rd}, #{emit_int nl}\n`
|
||||
end
|
||||
|
||||
and emit_subimm rd rs n =
|
||||
if n < 0 then emit_addimm rd rs (-n)
|
||||
else if n <= 0xFFF then
|
||||
` sub {emit_reg rd}, {emit_reg rs}, #{emit_int n}\n`
|
||||
else begin
|
||||
assert (n <= 0xFFF_FFF);
|
||||
let nl = n land 0xFFF and nh = n land 0xFFF_000 in
|
||||
` sub {emit_reg rd}, {emit_reg rs}, #{emit_int nh}\n`;
|
||||
if nl <> 0 then
|
||||
` sub {emit_reg rd}, {emit_reg rd}, #{emit_int nl}\n`
|
||||
end
|
||||
|
||||
let emit_cmpimm rs n =
|
||||
if n >= 0
|
||||
then ` cmp {emit_reg rs}, #{emit_int n}\n`
|
||||
else ` cmn {emit_reg rs}, #{emit_int (-n)}\n`
|
||||
|
||||
(* Name of current function *)
|
||||
let function_name = ref ""
|
||||
(* Entry point for tail recursive calls *)
|
||||
|
@ -746,11 +777,15 @@ let emit_instr i =
|
|||
assembly_code_for_allocation i ~n ~far:false ~label_after_call_gc ~dbginfo
|
||||
| Lop(Ispecific (Ifar_alloc { bytes = n; label_after_call_gc; dbginfo })) ->
|
||||
assembly_code_for_allocation i ~n ~far:true ~label_after_call_gc ~dbginfo
|
||||
| Lop(Iintop_imm(Iadd, n)) ->
|
||||
emit_addimm i.res.(0) i.arg.(0) n
|
||||
| Lop(Iintop_imm(Isub, n)) ->
|
||||
emit_subimm i.res.(0) i.arg.(0) n
|
||||
| Lop(Iintop(Icomp cmp)) ->
|
||||
` cmp {emit_reg i.arg.(0)}, {emit_reg i.arg.(1)}\n`;
|
||||
` cset {emit_reg i.res.(0)}, {emit_string (name_for_comparison cmp)}\n`
|
||||
| Lop(Iintop_imm(Icomp cmp, n)) ->
|
||||
` cmp {emit_reg i.arg.(0)}, #{emit_int n}\n`;
|
||||
emit_cmpimm i.arg.(0) n;
|
||||
` cset {emit_reg i.res.(0)}, {emit_string (name_for_comparison cmp)}\n`
|
||||
| Lop(Iintop (Icheckbound { label_after_error; })) ->
|
||||
let lbl = bound_error_label i.dbg ?label:label_after_error in
|
||||
|
@ -765,7 +800,7 @@ let emit_instr i =
|
|||
`{emit_label lbl2}:\n`;
|
||||
| Lop(Iintop_imm(Icheckbound { label_after_error; }, n)) ->
|
||||
let lbl = bound_error_label i.dbg ?label:label_after_error in
|
||||
` cmp {emit_reg i.arg.(0)}, #{emit_int n}\n`;
|
||||
emit_cmpimm i.arg.(0) n;
|
||||
` b.ls {emit_label lbl}\n`
|
||||
| Lop(Ispecific(
|
||||
Ifar_intop_imm_checkbound { bound; label_after_error; })) ->
|
||||
|
@ -869,7 +904,7 @@ let emit_instr i =
|
|||
let comp = name_for_comparison cmp in
|
||||
` b.{emit_string comp} {emit_label lbl}\n`
|
||||
| Iinttest_imm(cmp, n) ->
|
||||
` cmp {emit_reg i.arg.(0)}, #{emit_int n}\n`;
|
||||
emit_cmpimm i.arg.(0) n;
|
||||
let comp = name_for_comparison cmp in
|
||||
` b.{emit_string comp} {emit_label lbl}\n`
|
||||
| Ifloattest cmp ->
|
||||
|
|
|
@ -76,6 +76,13 @@ let rec run_automata nbits state input =
|
|||
let is_logical_immediate n =
|
||||
n <> 0 && n <> -1 && run_automata 64 0 n
|
||||
|
||||
(* Signed immediates are simpler *)
|
||||
|
||||
let is_immediate n =
|
||||
let mn = -n in
|
||||
n land 0xFFF = n || n land 0xFFF_000 = n
|
||||
|| mn land 0xFFF = mn || mn land 0xFFF_000 = mn
|
||||
|
||||
(* If you update [inline_ops], you may need to update [is_simple_expr] and/or
|
||||
[effects_of], below. *)
|
||||
let inline_ops =
|
||||
|
@ -96,10 +103,15 @@ class selector = object(self)
|
|||
|
||||
inherit Selectgen.selector_generic as super
|
||||
|
||||
method is_immediate n =
|
||||
let mn = -n in
|
||||
n land 0xFFF = n || n land 0xFFF_000 = n
|
||||
|| mn land 0xFFF = mn || mn land 0xFFF_000 = mn
|
||||
method is_immediate_test _cmp n =
|
||||
is_immediate n
|
||||
|
||||
method! is_immediate op n =
|
||||
match op with
|
||||
| Iadd | Isub -> n <= 0xFFF_FFF && n >= -0xFFF_FFF
|
||||
| Iand | Ior | Ixor -> is_logical_immediate n
|
||||
| Icomp _ | Icheckbound _ -> is_immediate n
|
||||
| _ -> super#is_immediate op n
|
||||
|
||||
method! is_simple_expr = function
|
||||
(* inlined floating-point ops are simple if their arguments are *)
|
||||
|
@ -135,13 +147,6 @@ method! select_operation op args dbg =
|
|||
(* Integer addition *)
|
||||
| Caddi | Caddv | Cadda ->
|
||||
begin match args with
|
||||
(* Add immediate *)
|
||||
| [arg; Cconst_int (n, _)] when self#is_immediate n ->
|
||||
((if n >= 0 then Iintop_imm(Iadd, n) else Iintop_imm(Isub, -n)),
|
||||
[arg])
|
||||
| [Cconst_int (n, _); arg] when self#is_immediate n ->
|
||||
((if n >= 0 then Iintop_imm(Iadd, n) else Iintop_imm(Isub, -n)),
|
||||
[arg])
|
||||
(* Shift-add *)
|
||||
| [arg1; Cop(Clsl, [arg2; Cconst_int (n, _)], _)] when n > 0 && n < 64 ->
|
||||
(Ispecific(Ishiftarith(Ishiftadd, n)), [arg1; arg2])
|
||||
|
@ -167,10 +172,6 @@ method! select_operation op args dbg =
|
|||
(* Integer subtraction *)
|
||||
| Csubi ->
|
||||
begin match args with
|
||||
(* Sub immediate *)
|
||||
| [arg; Cconst_int (n, _)] when self#is_immediate n ->
|
||||
((if n >= 0 then Iintop_imm(Isub, n) else Iintop_imm(Iadd, -n)),
|
||||
[arg])
|
||||
(* Shift-sub *)
|
||||
| [arg1; Cop(Clsl, [arg2; Cconst_int (n, _)], _)] when n > 0 && n < 64 ->
|
||||
(Ispecific(Ishiftarith(Ishiftsub, n)), [arg1; arg2])
|
||||
|
@ -198,17 +199,6 @@ method! select_operation op args dbg =
|
|||
| _ ->
|
||||
super#select_operation op args dbg
|
||||
end
|
||||
(* Integer multiplication *)
|
||||
(* ARM does not support immediate operands for multiplication *)
|
||||
| Cmuli ->
|
||||
(Iintop Imul, args)
|
||||
| Cmulhi ->
|
||||
(Iintop Imulh, args)
|
||||
(* Bitwise logical operations 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
|
||||
(* Recognize floating-point negate and multiply *)
|
||||
| Cnegf ->
|
||||
begin match args with
|
||||
|
@ -247,14 +237,6 @@ method! select_operation op args dbg =
|
|||
| _ ->
|
||||
super#select_operation op args dbg
|
||||
|
||||
method select_logical op = function
|
||||
| [arg; Cconst_int (n, _)] when is_logical_immediate n ->
|
||||
(Iintop_imm(op, n), [arg])
|
||||
| [Cconst_int (n, _); arg] when is_logical_immediate n ->
|
||||
(Iintop_imm(op, n), [arg])
|
||||
| args ->
|
||||
(Iintop op, args)
|
||||
|
||||
method! insert_move_extcall_arg env ty_arg src dst =
|
||||
if macosx && ty_arg = XInt32 && is_stack_slot dst
|
||||
then self#insert env (Iop (Ispecific Imove32)) src dst
|
||||
|
|
|
@ -158,7 +158,14 @@ class selector = object (self)
|
|||
|
||||
inherit Selectgen.selector_generic as super
|
||||
|
||||
method is_immediate (_n : int) = true
|
||||
method! is_immediate op n =
|
||||
match op with
|
||||
| Iadd | Isub | Imul | Iand | Ior | Ixor | Icomp _ | Icheckbound _ ->
|
||||
true
|
||||
| _ ->
|
||||
super#is_immediate op n
|
||||
|
||||
method is_immediate_test _cmp _n = true
|
||||
|
||||
method! is_simple_expr e =
|
||||
match e with
|
||||
|
@ -236,9 +243,6 @@ method! select_operation op args dbg =
|
|||
| Cextcall(fn, _ty_res, _ty_args, false, _label)
|
||||
when !fast_math && List.mem fn inline_float_ops ->
|
||||
(Ispecific(Ifloatspecial fn), args)
|
||||
(* i386 does not support immediate operands for multiply high signed *)
|
||||
| Cmulhi ->
|
||||
(Iintop Imulh, args)
|
||||
(* Default *)
|
||||
| _ -> super#select_operation op args dbg
|
||||
|
||||
|
|
|
@ -43,13 +43,29 @@ let rec select_addr = function
|
|||
| exp ->
|
||||
(Alinear exp, 0, Debuginfo.none)
|
||||
|
||||
let is_immediate n = n <= 0x7FFF && n >= -0x8000
|
||||
let is_immediate_logical n = n <= 0xFFFF && n >= 0
|
||||
|
||||
(* Instruction selection *)
|
||||
|
||||
class selector = object (self)
|
||||
|
||||
inherit Selectgen.selector_generic as super
|
||||
|
||||
method is_immediate n = (n <= 32767) && (n >= -32768)
|
||||
method is_immediate_test cmp n =
|
||||
match cmp with
|
||||
| Isigned _ -> is_immediate n
|
||||
| Iunsigned _ -> is_immediate_logical n
|
||||
|
||||
method! is_immediate op n =
|
||||
match op with
|
||||
| Iadd | Imul -> is_immediate n
|
||||
| Isub -> is_immediate (-n) (* turned into add opposite *)
|
||||
| Iand | Ior | Ixor -> is_immediate_logical n
|
||||
| Icomp c -> self#is_immediate_test c n
|
||||
| Icheckbound _ -> 0 <= n && n <= 0x7FFF
|
||||
(* twlle takes a 16-bit signed immediate but performs an unsigned compare *)
|
||||
| _ -> super#is_immediate op n
|
||||
|
||||
method select_addressing _chunk exp =
|
||||
match select_addr exp with
|
||||
|
@ -64,13 +80,6 @@ method select_addressing _chunk exp =
|
|||
|
||||
method! select_operation op args dbg =
|
||||
match (op, args) with
|
||||
(* PowerPC does not support immediate operands for multiply high *)
|
||||
(Cmulhi, _) -> (Iintop Imulh, 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
|
||||
(* Recognize mult-add and mult-sub instructions *)
|
||||
| (Caddf, [Cop(Cmulf, [arg1; arg2], _); arg3]) ->
|
||||
(Ispecific Imultaddf, [arg1; arg2; arg3])
|
||||
|
@ -81,14 +90,6 @@ method! select_operation op args dbg =
|
|||
| _ ->
|
||||
super#select_operation op args dbg
|
||||
|
||||
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
|
||||
|
|
|
@ -428,12 +428,6 @@ let emit_instr i =
|
|||
` {emit_string instr} {emit_reg i.res.(0)}, {emit_reg i.arg.(0)}, {emit_reg i.arg.(1)}\n`
|
||||
| Lop(Iintop_imm(Isub, n)) ->
|
||||
` addi {emit_reg i.res.(0)}, {emit_reg i.arg.(0)}, {emit_int(-n)}\n`
|
||||
| Lop(Iintop_imm(Icomp _, _)) ->
|
||||
Misc.fatal_error "Emit.emit_instr (Iintop_imm (Icomp _, _))"
|
||||
| Lop(Iintop_imm(Icheckbound {label_after_error = label; _}, n)) ->
|
||||
let lbl = bound_error_label ?label i.dbg in
|
||||
` li {emit_reg reg_tmp}, {emit_int n}\n`;
|
||||
` bleu {emit_reg i.arg.(0)}, {emit_reg reg_tmp}, {emit_label lbl}\n`
|
||||
| Lop(Iintop_imm(op, n)) ->
|
||||
let instr = name_for_intop_imm op in
|
||||
` {emit_string instr} {emit_reg i.res.(0)}, {emit_reg i.arg.(0)}, {emit_int n}\n`
|
||||
|
|
|
@ -21,17 +21,25 @@ open Mach
|
|||
|
||||
(* Instruction selection *)
|
||||
|
||||
class selector = object (self)
|
||||
class selector = object
|
||||
|
||||
inherit Selectgen.selector_generic as super
|
||||
|
||||
method is_immediate n = is_immediate n
|
||||
(* RISC-V does not support immediate operands for comparison operators *)
|
||||
method is_immediate_test _cmp _n = false
|
||||
|
||||
method! is_immediate op n =
|
||||
match op with
|
||||
| Iadd | Iand | Ior | Ixor -> is_immediate n
|
||||
(* sub immediate is turned into add immediate opposite *)
|
||||
| Isub -> is_immediate (-n)
|
||||
| _ -> super#is_immediate op n
|
||||
|
||||
method select_addressing _ = function
|
||||
| Cop(Cadda, [arg; Cconst_int (n, _)], _) when self#is_immediate n ->
|
||||
| Cop(Cadda, [arg; Cconst_int (n, _)], _) when is_immediate n ->
|
||||
(Iindexed n, arg)
|
||||
| Cop(Cadda, [arg1; Cop(Caddi, [arg2; Cconst_int (n, _)], _)], dbg)
|
||||
when self#is_immediate n ->
|
||||
when is_immediate n ->
|
||||
(Iindexed n, Cop(Caddi, [arg1; arg2], dbg))
|
||||
| arg ->
|
||||
(Iindexed 0, arg)
|
||||
|
@ -48,28 +56,9 @@ method! select_operation op args dbg =
|
|||
(Ispecific (Imultsubf true), [arg1; arg2; arg3])
|
||||
| (Cnegf, [Cop(Caddf, [Cop(Cmulf, [arg1; arg2], _); arg3], _)]) ->
|
||||
(Ispecific (Imultaddf true), [arg1; arg2; arg3])
|
||||
(* RISC-V does not support immediate operands for comparison operators *)
|
||||
| (Ccmpi comp, args) -> (Iintop(Icomp (Isigned comp)), args)
|
||||
| (Ccmpa comp, args) -> (Iintop(Icomp (Iunsigned comp)), args)
|
||||
(* RISC-V does not support immediate operands for multiply/multiply high *)
|
||||
| (Cmuli, _) -> (Iintop Imul, args)
|
||||
| (Cmulhi, _) -> (Iintop Imulh, args)
|
||||
| _ ->
|
||||
super#select_operation op args dbg
|
||||
|
||||
(* Instruction selection for conditionals *)
|
||||
|
||||
method! select_condition = function
|
||||
Cop(Ccmpi cmp, args, _) ->
|
||||
(Iinttest(Isigned cmp), Ctuple args)
|
||||
| Cop(Ccmpa cmp, args, _) ->
|
||||
(Iinttest(Iunsigned cmp), Ctuple args)
|
||||
| Cop(Ccmpf cmp, args, _) ->
|
||||
(Ifloattest cmp, Ctuple args)
|
||||
| Cop(Cand, [arg; Cconst_int (1, _)], _) ->
|
||||
(Ioddtest, arg)
|
||||
| arg ->
|
||||
(Itruetest, arg)
|
||||
end
|
||||
|
||||
let fundecl f = (new selector)#emit_fundecl f
|
||||
|
|
|
@ -58,13 +58,27 @@ let pseudoregs_for_operation op arg res =
|
|||
(* Other instructions are regular *)
|
||||
| _ -> raise Use_default
|
||||
|
||||
let is_immediate n = n <= 0x7FFF_FFFF && n >= -0x8000_0000
|
||||
let is_immediate_logical n = n <= 0xFFFF_FFFF && n >= 0
|
||||
|
||||
class selector = object (self)
|
||||
|
||||
inherit Selectgen.selector_generic as super
|
||||
|
||||
method is_immediate n = n <= 0x7FFF_FFFF && n >= (-1-0x7FFF_FFFF)
|
||||
(* -1-.... : hack so that this can be compiled on 32-bit
|
||||
(cf 'make check_all_arches') *)
|
||||
method is_immediate_test cmp n =
|
||||
match cmp with
|
||||
| Isigned _ -> is_immediate n
|
||||
| Iunsigned _ -> is_immediate_logical n
|
||||
|
||||
method! is_immediate op n =
|
||||
match op with
|
||||
| Iadd | Imul -> is_immediate n
|
||||
| Isub -> is_immediate (-n)
|
||||
| Iand -> n <= -1 && n >= -0x1_0000_0000
|
||||
| Ior | Ixor -> is_immediate_logical n
|
||||
| Icomp c -> self#is_immediate_test c n
|
||||
| Icheckbound _ -> is_immediate_logical n (* unsigned comparison *)
|
||||
| _ -> super#is_immediate op n
|
||||
|
||||
method select_addressing _chunk exp =
|
||||
let (a, d) = select_addr exp in
|
||||
|
@ -78,20 +92,6 @@ method select_addressing _chunk exp =
|
|||
|
||||
method! select_operation op args dbg =
|
||||
match (op, args) with
|
||||
(* Z does not support immediate operands for multiply high *)
|
||||
(Cmulhi, _) -> (Iintop Imulh, args)
|
||||
(* sub immediate is turned into add immediate opposite,
|
||||
hence the immediate range is special *)
|
||||
| (Csubi, [arg; Cconst_int (n, _)]) when self#is_immediate (-n) ->
|
||||
(Iintop_imm(Isub, n), [arg])
|
||||
| (Csubi, _) ->
|
||||
(Iintop Isub, args)
|
||||
(* The and, or and xor instructions have a different range of immediate
|
||||
operands than the other instructions *)
|
||||
| (Cand, _) ->
|
||||
self#select_logical Iand (-1 lsl 32 (*0x1_0000_0000*)) (-1) args
|
||||
| (Cor, _) -> self#select_logical Ior 0 (1 lsl 32 - 1 (*0xFFFF_FFFF*)) args
|
||||
| (Cxor, _) -> self#select_logical Ixor 0 (1 lsl 32 - 1 (*0xFFFF_FFFF*)) args
|
||||
(* Recognize mult-add and mult-sub instructions *)
|
||||
| (Caddf, [Cop(Cmulf, [arg1; arg2], _); arg3]) ->
|
||||
(Ispecific Imultaddf, [arg1; arg2; arg3])
|
||||
|
@ -102,15 +102,6 @@ method! select_operation op args dbg =
|
|||
| _ ->
|
||||
super#select_operation op args dbg
|
||||
|
||||
method select_logical op lo hi = function
|
||||
[arg; Cconst_int (n, _)] when n >= lo && n <= hi ->
|
||||
(Iintop_imm(op, n), [arg])
|
||||
| [Cconst_int (n, _); arg] when n >= lo && n <= hi ->
|
||||
(Iintop_imm(op, n), [arg])
|
||||
| args ->
|
||||
(Iintop op, args)
|
||||
|
||||
|
||||
method! insert_op_debug env op dbg rs rd =
|
||||
try
|
||||
let (rsrc, rdst) = pseudoregs_for_operation op rs rd in
|
||||
|
|
|
@ -379,9 +379,18 @@ method effects_of exp =
|
|||
| Cassign _ | Cswitch _ | Ccatch _ | Cexit _ | Ctrywith _ ->
|
||||
EC.arbitrary
|
||||
|
||||
(* Says whether an integer constant is a suitable immediate argument *)
|
||||
(* Says whether an integer constant is a suitable immediate argument for
|
||||
the given integer operation *)
|
||||
|
||||
method virtual is_immediate : int -> bool
|
||||
method is_immediate op n =
|
||||
match op with
|
||||
| Ilsl | Ilsr | Iasr -> n >= 0 && n < Arch.size_int * 8
|
||||
| _ -> false
|
||||
|
||||
(* Says whether an integer constant is a suitable immediate argument for
|
||||
the given integer test *)
|
||||
|
||||
method virtual is_immediate_test : integer_comparison -> int -> bool
|
||||
|
||||
(* Selection of addressing modes *)
|
||||
|
||||
|
@ -480,9 +489,9 @@ method select_operation op args _dbg =
|
|||
| (Cand, _) -> self#select_arith_comm Iand args
|
||||
| (Cor, _) -> self#select_arith_comm Ior args
|
||||
| (Cxor, _) -> self#select_arith_comm Ixor args
|
||||
| (Clsl, _) -> self#select_shift Ilsl args
|
||||
| (Clsr, _) -> self#select_shift Ilsr args
|
||||
| (Casr, _) -> self#select_shift Iasr args
|
||||
| (Clsl, _) -> self#select_arith Ilsl args
|
||||
| (Clsr, _) -> self#select_arith Ilsr args
|
||||
| (Casr, _) -> self#select_arith Iasr args
|
||||
| (Ccmpi comp, _) -> self#select_arith_comp (Isigned comp) args
|
||||
| (Caddv, _) -> self#select_arith_comm Iadd args
|
||||
| (Cadda, _) -> self#select_arith_comm Iadd args
|
||||
|
@ -502,29 +511,24 @@ method select_operation op args _dbg =
|
|||
| _ -> Misc.fatal_error "Selection.select_oper"
|
||||
|
||||
method private select_arith_comm op = function
|
||||
[arg; Cconst_int (n, _)] when self#is_immediate n ->
|
||||
| [arg; Cconst_int (n, _)] when self#is_immediate op n ->
|
||||
(Iintop_imm(op, n), [arg])
|
||||
| [Cconst_int (n, _); arg] when self#is_immediate n ->
|
||||
| [Cconst_int (n, _); arg] when self#is_immediate op n ->
|
||||
(Iintop_imm(op, n), [arg])
|
||||
| args ->
|
||||
(Iintop op, args)
|
||||
|
||||
method private select_arith op = function
|
||||
[arg; Cconst_int (n, _)] when self#is_immediate n ->
|
||||
(Iintop_imm(op, n), [arg])
|
||||
| args ->
|
||||
(Iintop op, args)
|
||||
|
||||
method private select_shift op = function
|
||||
[arg; Cconst_int (n, _)] when n >= 0 && n < Arch.size_int * 8 ->
|
||||
| [arg; Cconst_int (n, _)] when self#is_immediate op n ->
|
||||
(Iintop_imm(op, n), [arg])
|
||||
| args ->
|
||||
(Iintop op, args)
|
||||
|
||||
method private select_arith_comp cmp = function
|
||||
[arg; Cconst_int (n, _)] when self#is_immediate n ->
|
||||
| [arg; Cconst_int (n, _)] when self#is_immediate (Icomp cmp) n ->
|
||||
(Iintop_imm(Icomp cmp, n), [arg])
|
||||
| [Cconst_int (n, _); arg] when self#is_immediate n ->
|
||||
| [Cconst_int (n, _); arg]
|
||||
when self#is_immediate (Icomp(swap_intcomp cmp)) n ->
|
||||
(Iintop_imm(Icomp(swap_intcomp cmp), n), [arg])
|
||||
| args ->
|
||||
(Iintop(Icomp cmp), args)
|
||||
|
@ -532,15 +536,19 @@ method private select_arith_comp cmp = function
|
|||
(* Instruction selection for conditionals *)
|
||||
|
||||
method select_condition = function
|
||||
Cop(Ccmpi cmp, [arg1; Cconst_int (n, _)], _) when self#is_immediate n ->
|
||||
| Cop(Ccmpi cmp, [arg1; Cconst_int (n, _)], _)
|
||||
when self#is_immediate_test (Isigned cmp) n ->
|
||||
(Iinttest_imm(Isigned cmp, n), arg1)
|
||||
| Cop(Ccmpi cmp, [Cconst_int (n, _); arg2], _) when self#is_immediate n ->
|
||||
| Cop(Ccmpi cmp, [Cconst_int (n, _); arg2], _)
|
||||
when self#is_immediate_test (Isigned (swap_integer_comparison cmp)) n ->
|
||||
(Iinttest_imm(Isigned(swap_integer_comparison cmp), n), arg2)
|
||||
| Cop(Ccmpi cmp, args, _) ->
|
||||
(Iinttest(Isigned cmp), Ctuple args)
|
||||
| Cop(Ccmpa cmp, [arg1; Cconst_int (n, _)], _) when self#is_immediate n ->
|
||||
| Cop(Ccmpa cmp, [arg1; Cconst_int (n, _)], _)
|
||||
when self#is_immediate_test (Iunsigned cmp) n ->
|
||||
(Iinttest_imm(Iunsigned cmp, n), arg1)
|
||||
| Cop(Ccmpa cmp, [Cconst_int (n, _); arg2], _) when self#is_immediate n ->
|
||||
| Cop(Ccmpa cmp, [Cconst_int (n, _); arg2], _)
|
||||
when self#is_immediate_test (Iunsigned (swap_integer_comparison cmp)) n ->
|
||||
(Iinttest_imm(Iunsigned(swap_integer_comparison cmp), n), arg2)
|
||||
| Cop(Ccmpa cmp, args, _) ->
|
||||
(Iinttest(Iunsigned cmp), Ctuple args)
|
||||
|
|
|
@ -62,9 +62,14 @@ end
|
|||
class virtual selector_generic : object
|
||||
(* The following methods must or can be overridden by the processor
|
||||
description *)
|
||||
method virtual is_immediate : int -> bool
|
||||
method is_immediate : Mach.integer_operation -> int -> bool
|
||||
(* Must be overriden to indicate whether a constant is a suitable
|
||||
immediate operand to the given integer arithmetic instruction.
|
||||
The default implementation handles shifts by immediate amounts,
|
||||
but produces no immediate operations otherwise. *)
|
||||
method virtual is_immediate_test : Mach.integer_comparison -> int -> bool
|
||||
(* Must be defined to indicate whether a constant is a suitable
|
||||
immediate operand to arithmetic instructions *)
|
||||
immediate operand to the given integer test *)
|
||||
method virtual select_addressing :
|
||||
Cmm.memory_chunk -> Cmm.expression -> Arch.addressing_mode * Cmm.expression
|
||||
(* Must be defined to select addressing modes *)
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
(* TEST
|
||||
files = "mainimmed.c"
|
||||
arguments = "-I ${test_source_directory} mainimmed.c"
|
||||
* asmgen
|
||||
*)
|
||||
(* Regenerate with cpp -P immediates.cmmpp > immediates.cmm *)
|
||||
(function "testimm" ()
|
||||
(let x (load int "X")
|
||||
(let r "R"
|
||||
(letmut i int 0
|
||||
(addraset r i (+ x 0)) (assign i (+ i 1)) (addraset r i (- x 0)) (assign i (+ i 1)) (addraset r i ( * x 0)) (assign i (+ i 1)) (addraset r i (and x 0)) (assign i (+ i 1)) (addraset r i (or x 0)) (assign i (+ i 1)) (addraset r i (xor x 0)) (assign i (+ i 1)) (addraset r i (< x 0)) (assign i (+ i 1)) (checkbound i 0)
|
||||
(addraset r i (+ x 1)) (assign i (+ i 1)) (addraset r i (- x 1)) (assign i (+ i 1)) (addraset r i ( * x 1)) (assign i (+ i 1)) (addraset r i (and x 1)) (assign i (+ i 1)) (addraset r i (or x 1)) (assign i (+ i 1)) (addraset r i (xor x 1)) (assign i (+ i 1)) (addraset r i (< x 1)) (assign i (+ i 1)) (checkbound i 1)
|
||||
(addraset r i (+ x 0xFF)) (assign i (+ i 1)) (addraset r i (- x 0xFF)) (assign i (+ i 1)) (addraset r i ( * x 0xFF)) (assign i (+ i 1)) (addraset r i (and x 0xFF)) (assign i (+ i 1)) (addraset r i (or x 0xFF)) (assign i (+ i 1)) (addraset r i (xor x 0xFF)) (assign i (+ i 1)) (addraset r i (< x 0xFF)) (assign i (+ i 1)) (checkbound i 0xFF)
|
||||
(addraset r i (+ x 0x100)) (assign i (+ i 1)) (addraset r i (- x 0x100)) (assign i (+ i 1)) (addraset r i ( * x 0x100)) (assign i (+ i 1)) (addraset r i (and x 0x100)) (assign i (+ i 1)) (addraset r i (or x 0x100)) (assign i (+ i 1)) (addraset r i (xor x 0x100)) (assign i (+ i 1)) (addraset r i (< x 0x100)) (assign i (+ i 1)) (checkbound i 0x100)
|
||||
(addraset r i (+ x 0x3FC)) (assign i (+ i 1)) (addraset r i (- x 0x3FC)) (assign i (+ i 1)) (addraset r i ( * x 0x3FC)) (assign i (+ i 1)) (addraset r i (and x 0x3FC)) (assign i (+ i 1)) (addraset r i (or x 0x3FC)) (assign i (+ i 1)) (addraset r i (xor x 0x3FC)) (assign i (+ i 1)) (addraset r i (< x 0x3FC)) (assign i (+ i 1)) (checkbound i 0x3FC)
|
||||
(addraset r i (+ x 0x3FF)) (assign i (+ i 1)) (addraset r i (- x 0x3FF)) (assign i (+ i 1)) (addraset r i ( * x 0x3FF)) (assign i (+ i 1)) (addraset r i (and x 0x3FF)) (assign i (+ i 1)) (addraset r i (or x 0x3FF)) (assign i (+ i 1)) (addraset r i (xor x 0x3FF)) (assign i (+ i 1)) (addraset r i (< x 0x3FF)) (assign i (+ i 1)) (checkbound i 0x3FF)
|
||||
(addraset r i (+ x 0x7FF)) (assign i (+ i 1)) (addraset r i (- x 0x7FF)) (assign i (+ i 1)) (addraset r i ( * x 0x7FF)) (assign i (+ i 1)) (addraset r i (and x 0x7FF)) (assign i (+ i 1)) (addraset r i (or x 0x7FF)) (assign i (+ i 1)) (addraset r i (xor x 0x7FF)) (assign i (+ i 1)) (addraset r i (< x 0x7FF)) (assign i (+ i 1)) (checkbound i 0x7FF)
|
||||
(addraset r i (+ x 0x800)) (assign i (+ i 1)) (addraset r i (- x 0x800)) (assign i (+ i 1)) (addraset r i ( * x 0x800)) (assign i (+ i 1)) (addraset r i (and x 0x800)) (assign i (+ i 1)) (addraset r i (or x 0x800)) (assign i (+ i 1)) (addraset r i (xor x 0x800)) (assign i (+ i 1)) (addraset r i (< x 0x800)) (assign i (+ i 1)) (checkbound i 0x800)
|
||||
(addraset r i (+ x 0x801)) (assign i (+ i 1)) (addraset r i (- x 0x801)) (assign i (+ i 1)) (addraset r i ( * x 0x801)) (assign i (+ i 1)) (addraset r i (and x 0x801)) (assign i (+ i 1)) (addraset r i (or x 0x801)) (assign i (+ i 1)) (addraset r i (xor x 0x801)) (assign i (+ i 1)) (addraset r i (< x 0x801)) (assign i (+ i 1)) (checkbound i 0x801)
|
||||
(addraset r i (+ x 0xFFF)) (assign i (+ i 1)) (addraset r i (- x 0xFFF)) (assign i (+ i 1)) (addraset r i ( * x 0xFFF)) (assign i (+ i 1)) (addraset r i (and x 0xFFF)) (assign i (+ i 1)) (addraset r i (or x 0xFFF)) (assign i (+ i 1)) (addraset r i (xor x 0xFFF)) (assign i (+ i 1)) (addraset r i (< x 0xFFF)) (assign i (+ i 1)) (checkbound i 0xFFF)
|
||||
(addraset r i (+ x 0x1000)) (assign i (+ i 1)) (addraset r i (- x 0x1000)) (assign i (+ i 1)) (addraset r i ( * x 0x1000)) (assign i (+ i 1)) (addraset r i (and x 0x1000)) (assign i (+ i 1)) (addraset r i (or x 0x1000)) (assign i (+ i 1)) (addraset r i (xor x 0x1000)) (assign i (+ i 1)) (addraset r i (< x 0x1000)) (assign i (+ i 1)) (checkbound i 0x1000)
|
||||
(addraset r i (+ x 0x1001)) (assign i (+ i 1)) (addraset r i (- x 0x1001)) (assign i (+ i 1)) (addraset r i ( * x 0x1001)) (assign i (+ i 1)) (addraset r i (and x 0x1001)) (assign i (+ i 1)) (addraset r i (or x 0x1001)) (assign i (+ i 1)) (addraset r i (xor x 0x1001)) (assign i (+ i 1)) (addraset r i (< x 0x1001)) (assign i (+ i 1)) (checkbound i 0x1001)
|
||||
(addraset r i (+ x 0x7FFF)) (assign i (+ i 1)) (addraset r i (- x 0x7FFF)) (assign i (+ i 1)) (addraset r i ( * x 0x7FFF)) (assign i (+ i 1)) (addraset r i (and x 0x7FFF)) (assign i (+ i 1)) (addraset r i (or x 0x7FFF)) (assign i (+ i 1)) (addraset r i (xor x 0x7FFF)) (assign i (+ i 1)) (addraset r i (< x 0x7FFF)) (assign i (+ i 1)) (checkbound i 0x7FFF)
|
||||
(addraset r i (+ x 0x8000)) (assign i (+ i 1)) (addraset r i (- x 0x8000)) (assign i (+ i 1)) (addraset r i ( * x 0x8000)) (assign i (+ i 1)) (addraset r i (and x 0x8000)) (assign i (+ i 1)) (addraset r i (or x 0x8000)) (assign i (+ i 1)) (addraset r i (xor x 0x8000)) (assign i (+ i 1)) (addraset r i (< x 0x8000)) (assign i (+ i 1)) (checkbound i 0x8000)
|
||||
(addraset r i (+ x 0x8001)) (assign i (+ i 1)) (addraset r i (- x 0x8001)) (assign i (+ i 1)) (addraset r i ( * x 0x8001)) (assign i (+ i 1)) (addraset r i (and x 0x8001)) (assign i (+ i 1)) (addraset r i (or x 0x8001)) (assign i (+ i 1)) (addraset r i (xor x 0x8001)) (assign i (+ i 1)) (addraset r i (< x 0x8001)) (assign i (+ i 1)) (checkbound i 0x8001)
|
||||
(addraset r i (+ x 0xFFF000)) (assign i (+ i 1)) (addraset r i (- x 0xFFF000)) (assign i (+ i 1)) (addraset r i ( * x 0xFFF000)) (assign i (+ i 1)) (addraset r i (and x 0xFFF000)) (assign i (+ i 1)) (addraset r i (or x 0xFFF000)) (assign i (+ i 1)) (addraset r i (xor x 0xFFF000)) (assign i (+ i 1)) (addraset r i (< x 0xFFF000)) (assign i (+ i 1)) (checkbound i 0xFFF000)
|
||||
(addraset r i (+ x 0xFFFFFF)) (assign i (+ i 1)) (addraset r i (- x 0xFFFFFF)) (assign i (+ i 1)) (addraset r i ( * x 0xFFFFFF)) (assign i (+ i 1)) (addraset r i (and x 0xFFFFFF)) (assign i (+ i 1)) (addraset r i (or x 0xFFFFFF)) (assign i (+ i 1)) (addraset r i (xor x 0xFFFFFF)) (assign i (+ i 1)) (addraset r i (< x 0xFFFFFF)) (assign i (+ i 1)) (checkbound i 0xFFFFFF)
|
||||
(addraset r i (+ x 0x1000000)) (assign i (+ i 1)) (addraset r i (- x 0x1000000)) (assign i (+ i 1)) (addraset r i ( * x 0x1000000)) (assign i (+ i 1)) (addraset r i (and x 0x1000000)) (assign i (+ i 1)) (addraset r i (or x 0x1000000)) (assign i (+ i 1)) (addraset r i (xor x 0x1000000)) (assign i (+ i 1)) (addraset r i (< x 0x1000000)) (assign i (+ i 1)) (checkbound i 0x1000000)
|
||||
(addraset r i (+ x 0x1000001)) (assign i (+ i 1)) (addraset r i (- x 0x1000001)) (assign i (+ i 1)) (addraset r i ( * x 0x1000001)) (assign i (+ i 1)) (addraset r i (and x 0x1000001)) (assign i (+ i 1)) (addraset r i (or x 0x1000001)) (assign i (+ i 1)) (addraset r i (xor x 0x1000001)) (assign i (+ i 1)) (addraset r i (< x 0x1000001)) (assign i (+ i 1)) (checkbound i 0x1000001)
|
||||
(addraset r i (+ x -1)) (assign i (+ i 1)) (addraset r i (- x -1)) (assign i (+ i 1)) (addraset r i ( * x -1)) (assign i (+ i 1)) (addraset r i (and x -1)) (assign i (+ i 1)) (addraset r i (or x -1)) (assign i (+ i 1)) (addraset r i (xor x -1)) (assign i (+ i 1)) (addraset r i (< x -1)) (assign i (+ i 1)) (checkbound i -1)
|
||||
(addraset r i (+ x -0xFF)) (assign i (+ i 1)) (addraset r i (- x -0xFF)) (assign i (+ i 1)) (addraset r i ( * x -0xFF)) (assign i (+ i 1)) (addraset r i (and x -0xFF)) (assign i (+ i 1)) (addraset r i (or x -0xFF)) (assign i (+ i 1)) (addraset r i (xor x -0xFF)) (assign i (+ i 1)) (addraset r i (< x -0xFF)) (assign i (+ i 1)) (checkbound i -0xFF)
|
||||
(addraset r i (+ x -0x100)) (assign i (+ i 1)) (addraset r i (- x -0x100)) (assign i (+ i 1)) (addraset r i ( * x -0x100)) (assign i (+ i 1)) (addraset r i (and x -0x100)) (assign i (+ i 1)) (addraset r i (or x -0x100)) (assign i (+ i 1)) (addraset r i (xor x -0x100)) (assign i (+ i 1)) (addraset r i (< x -0x100)) (assign i (+ i 1)) (checkbound i -0x100)
|
||||
(addraset r i (+ x -0x3FC)) (assign i (+ i 1)) (addraset r i (- x -0x3FC)) (assign i (+ i 1)) (addraset r i ( * x -0x3FC)) (assign i (+ i 1)) (addraset r i (and x -0x3FC)) (assign i (+ i 1)) (addraset r i (or x -0x3FC)) (assign i (+ i 1)) (addraset r i (xor x -0x3FC)) (assign i (+ i 1)) (addraset r i (< x -0x3FC)) (assign i (+ i 1)) (checkbound i -0x3FC)
|
||||
(addraset r i (+ x -0x3FF)) (assign i (+ i 1)) (addraset r i (- x -0x3FF)) (assign i (+ i 1)) (addraset r i ( * x -0x3FF)) (assign i (+ i 1)) (addraset r i (and x -0x3FF)) (assign i (+ i 1)) (addraset r i (or x -0x3FF)) (assign i (+ i 1)) (addraset r i (xor x -0x3FF)) (assign i (+ i 1)) (addraset r i (< x -0x3FF)) (assign i (+ i 1)) (checkbound i -0x3FF)
|
||||
(addraset r i (+ x -0x7FF)) (assign i (+ i 1)) (addraset r i (- x -0x7FF)) (assign i (+ i 1)) (addraset r i ( * x -0x7FF)) (assign i (+ i 1)) (addraset r i (and x -0x7FF)) (assign i (+ i 1)) (addraset r i (or x -0x7FF)) (assign i (+ i 1)) (addraset r i (xor x -0x7FF)) (assign i (+ i 1)) (addraset r i (< x -0x7FF)) (assign i (+ i 1)) (checkbound i -0x7FF)
|
||||
(addraset r i (+ x -0x800)) (assign i (+ i 1)) (addraset r i (- x -0x800)) (assign i (+ i 1)) (addraset r i ( * x -0x800)) (assign i (+ i 1)) (addraset r i (and x -0x800)) (assign i (+ i 1)) (addraset r i (or x -0x800)) (assign i (+ i 1)) (addraset r i (xor x -0x800)) (assign i (+ i 1)) (addraset r i (< x -0x800)) (assign i (+ i 1)) (checkbound i -0x800)
|
||||
(addraset r i (+ x -0x801)) (assign i (+ i 1)) (addraset r i (- x -0x801)) (assign i (+ i 1)) (addraset r i ( * x -0x801)) (assign i (+ i 1)) (addraset r i (and x -0x801)) (assign i (+ i 1)) (addraset r i (or x -0x801)) (assign i (+ i 1)) (addraset r i (xor x -0x801)) (assign i (+ i 1)) (addraset r i (< x -0x801)) (assign i (+ i 1)) (checkbound i -0x801)
|
||||
(addraset r i (+ x -0xFFF)) (assign i (+ i 1)) (addraset r i (- x -0xFFF)) (assign i (+ i 1)) (addraset r i ( * x -0xFFF)) (assign i (+ i 1)) (addraset r i (and x -0xFFF)) (assign i (+ i 1)) (addraset r i (or x -0xFFF)) (assign i (+ i 1)) (addraset r i (xor x -0xFFF)) (assign i (+ i 1)) (addraset r i (< x -0xFFF)) (assign i (+ i 1)) (checkbound i -0xFFF)
|
||||
(addraset r i (+ x -0x1000)) (assign i (+ i 1)) (addraset r i (- x -0x1000)) (assign i (+ i 1)) (addraset r i ( * x -0x1000)) (assign i (+ i 1)) (addraset r i (and x -0x1000)) (assign i (+ i 1)) (addraset r i (or x -0x1000)) (assign i (+ i 1)) (addraset r i (xor x -0x1000)) (assign i (+ i 1)) (addraset r i (< x -0x1000)) (assign i (+ i 1)) (checkbound i -0x1000)
|
||||
(addraset r i (+ x -0x1001)) (assign i (+ i 1)) (addraset r i (- x -0x1001)) (assign i (+ i 1)) (addraset r i ( * x -0x1001)) (assign i (+ i 1)) (addraset r i (and x -0x1001)) (assign i (+ i 1)) (addraset r i (or x -0x1001)) (assign i (+ i 1)) (addraset r i (xor x -0x1001)) (assign i (+ i 1)) (addraset r i (< x -0x1001)) (assign i (+ i 1)) (checkbound i -0x1001)
|
||||
(addraset r i (+ x -0x7FFF)) (assign i (+ i 1)) (addraset r i (- x -0x7FFF)) (assign i (+ i 1)) (addraset r i ( * x -0x7FFF)) (assign i (+ i 1)) (addraset r i (and x -0x7FFF)) (assign i (+ i 1)) (addraset r i (or x -0x7FFF)) (assign i (+ i 1)) (addraset r i (xor x -0x7FFF)) (assign i (+ i 1)) (addraset r i (< x -0x7FFF)) (assign i (+ i 1)) (checkbound i -0x7FFF)
|
||||
(addraset r i (+ x -0x8000)) (assign i (+ i 1)) (addraset r i (- x -0x8000)) (assign i (+ i 1)) (addraset r i ( * x -0x8000)) (assign i (+ i 1)) (addraset r i (and x -0x8000)) (assign i (+ i 1)) (addraset r i (or x -0x8000)) (assign i (+ i 1)) (addraset r i (xor x -0x8000)) (assign i (+ i 1)) (addraset r i (< x -0x8000)) (assign i (+ i 1)) (checkbound i -0x8000)
|
||||
(addraset r i (+ x -0x8001)) (assign i (+ i 1)) (addraset r i (- x -0x8001)) (assign i (+ i 1)) (addraset r i ( * x -0x8001)) (assign i (+ i 1)) (addraset r i (and x -0x8001)) (assign i (+ i 1)) (addraset r i (or x -0x8001)) (assign i (+ i 1)) (addraset r i (xor x -0x8001)) (assign i (+ i 1)) (addraset r i (< x -0x8001)) (assign i (+ i 1)) (checkbound i -0x8001)
|
||||
(addraset r i (+ x -0xFFF000)) (assign i (+ i 1)) (addraset r i (- x -0xFFF000)) (assign i (+ i 1)) (addraset r i ( * x -0xFFF000)) (assign i (+ i 1)) (addraset r i (and x -0xFFF000)) (assign i (+ i 1)) (addraset r i (or x -0xFFF000)) (assign i (+ i 1)) (addraset r i (xor x -0xFFF000)) (assign i (+ i 1)) (addraset r i (< x -0xFFF000)) (assign i (+ i 1)) (checkbound i -0xFFF000)
|
||||
(addraset r i (+ x -0xFFFFFF)) (assign i (+ i 1)) (addraset r i (- x -0xFFFFFF)) (assign i (+ i 1)) (addraset r i ( * x -0xFFFFFF)) (assign i (+ i 1)) (addraset r i (and x -0xFFFFFF)) (assign i (+ i 1)) (addraset r i (or x -0xFFFFFF)) (assign i (+ i 1)) (addraset r i (xor x -0xFFFFFF)) (assign i (+ i 1)) (addraset r i (< x -0xFFFFFF)) (assign i (+ i 1)) (checkbound i -0xFFFFFF)
|
||||
(addraset r i (+ x -0x1000000)) (assign i (+ i 1)) (addraset r i (- x -0x1000000)) (assign i (+ i 1)) (addraset r i ( * x -0x1000000)) (assign i (+ i 1)) (addraset r i (and x -0x1000000)) (assign i (+ i 1)) (addraset r i (or x -0x1000000)) (assign i (+ i 1)) (addraset r i (xor x -0x1000000)) (assign i (+ i 1)) (addraset r i (< x -0x1000000)) (assign i (+ i 1)) (checkbound i -0x1000000)
|
||||
(addraset r i (+ x -0x1000001)) (assign i (+ i 1)) (addraset r i (- x -0x1000001)) (assign i (+ i 1)) (addraset r i ( * x -0x1000001)) (assign i (+ i 1)) (addraset r i (and x -0x1000001)) (assign i (+ i 1)) (addraset r i (or x -0x1000001)) (assign i (+ i 1)) (addraset r i (xor x -0x1000001)) (assign i (+ i 1)) (addraset r i (< x -0x1000001)) (assign i (+ i 1)) (checkbound i -0x1000001)
|
||||
))))
|
|
@ -0,0 +1,26 @@
|
|||
#define T TEST
|
||||
|
||||
(* T
|
||||
files = "mainimmed.c"
|
||||
arguments = "-I ${test_source_directory} mainimmed.c"
|
||||
* asmgen
|
||||
*)
|
||||
|
||||
(* Regenerate with cpp -P immediates.cmmpp > immediates.cmm *)
|
||||
|
||||
#define F(N) \
|
||||
(addraset r i (+ x N)) (assign i (+ i 1)) \
|
||||
(addraset r i (- x N)) (assign i (+ i 1)) \
|
||||
(addraset r i ( * x N)) (assign i (+ i 1)) \
|
||||
(addraset r i (and x N)) (assign i (+ i 1)) \
|
||||
(addraset r i (or x N)) (assign i (+ i 1)) \
|
||||
(addraset r i (xor x N)) (assign i (+ i 1)) \
|
||||
(addraset r i (< x N)) (assign i (+ i 1)) \
|
||||
(checkbound i N)
|
||||
|
||||
(function "testimm" ()
|
||||
(let x (load int "X")
|
||||
(let r "R"
|
||||
(letmut i int 0
|
||||
#include "immediates.tbl"
|
||||
))))
|
|
@ -0,0 +1,37 @@
|
|||
F(0)
|
||||
F(1)
|
||||
F(0xFF)
|
||||
F(0x100)
|
||||
F(0x3FC)
|
||||
F(0x3FF)
|
||||
F(0x7FF)
|
||||
F(0x800)
|
||||
F(0x801)
|
||||
F(0xFFF)
|
||||
F(0x1000)
|
||||
F(0x1001)
|
||||
F(0x7FFF)
|
||||
F(0x8000)
|
||||
F(0x8001)
|
||||
F(0xFFF000)
|
||||
F(0xFFFFFF)
|
||||
F(0x1000000)
|
||||
F(0x1000001)
|
||||
F(-1)
|
||||
F(-0xFF)
|
||||
F(-0x100)
|
||||
F(-0x3FC)
|
||||
F(-0x3FF)
|
||||
F(-0x7FF)
|
||||
F(-0x800)
|
||||
F(-0x801)
|
||||
F(-0xFFF)
|
||||
F(-0x1000)
|
||||
F(-0x1001)
|
||||
F(-0x7FFF)
|
||||
F(-0x8000)
|
||||
F(-0x8001)
|
||||
F(-0xFFF000)
|
||||
F(-0xFFFFFF)
|
||||
F(-0x1000000)
|
||||
F(-0x1000001)
|
|
@ -0,0 +1,78 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <caml/config.h>
|
||||
|
||||
#define NUMTESTS 37
|
||||
intnat R[NUMTESTS][7];
|
||||
intnat X;
|
||||
|
||||
extern void call_gen_code(void (*)(void));
|
||||
extern void testimm(void);
|
||||
|
||||
void caml_ml_array_bound_error(void)
|
||||
{
|
||||
fprintf(stderr, "Fatal error: out-of-bound access in array or string\n");
|
||||
exit(2);
|
||||
}
|
||||
|
||||
/* One round of testing */
|
||||
|
||||
#define FMT ARCH_INTNAT_PRINTF_FORMAT
|
||||
|
||||
static void check(int i, intnat x, intnat result, intnat expected)
|
||||
{
|
||||
if (result != expected) {
|
||||
printf("Test %d, argument %"FMT"d: got %"FMT"d, expected %"FMT"d\n",
|
||||
i, x, result, expected);
|
||||
}
|
||||
}
|
||||
|
||||
static void test_one(int i, intnat x, intnat y)
|
||||
{
|
||||
check(i, x, R[i][0], x + y);
|
||||
check(i, x, R[i][1], x - y);
|
||||
check(i, x, R[i][2], x * y);
|
||||
check(i, x, R[i][3], x & y);
|
||||
check(i, x, R[i][4], x | y);
|
||||
check(i, x, R[i][5], x ^ y);
|
||||
check(i, x, R[i][6], x < y);
|
||||
}
|
||||
|
||||
static void do_test(intnat x)
|
||||
{
|
||||
int i;
|
||||
|
||||
X = x;
|
||||
call_gen_code(testimm);
|
||||
i = 0;
|
||||
#define F(N) test_one(i++, x, N);
|
||||
#include "immediates.tbl"
|
||||
}
|
||||
|
||||
/* A simple linear congruential PRNG */
|
||||
|
||||
#ifdef ARCH_SIXTYFOUR
|
||||
#define RAND_A 6364136223846793005ULL
|
||||
#define RAND_C 1442695040888963407ULL
|
||||
#else
|
||||
#define RAND_A 214013U
|
||||
#define RAND_C 2531011U
|
||||
#endif
|
||||
|
||||
static intnat rnd(void)
|
||||
{
|
||||
static uintnat seed = 0;
|
||||
seed = seed * RAND_A + RAND_C;
|
||||
return (intnat) seed;
|
||||
}
|
||||
|
||||
/* Test harness */
|
||||
|
||||
#define NUM_RANDOM_ITERATIONS 1000000
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < NUM_RANDOM_ITERATIONS; i++) do_test(rnd());
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue