Merge pull request #9864 from xavierleroy/is_immediate-refactored

Revised detection of arithmetic instructions with immediate operands
master
Xavier Leroy 2020-09-22 09:22:26 +02:00 committed by GitHub
commit 72dbcb8433
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 372 additions and 161 deletions

1
.gitattributes vendored
View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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 ->

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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`

View File

@ -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

View File

@ -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

View File

@ -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)

View File

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

View File

@ -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)
))))

View File

@ -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"
))))

View File

@ -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)

View File

@ -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;
}