aboutsummaryrefslogtreecommitdiffstats
path: root/lib/hipe/rtl/hipe_rtl_arith.inc
diff options
context:
space:
mode:
Diffstat (limited to 'lib/hipe/rtl/hipe_rtl_arith.inc')
-rw-r--r--lib/hipe/rtl/hipe_rtl_arith.inc177
1 files changed, 177 insertions, 0 deletions
diff --git a/lib/hipe/rtl/hipe_rtl_arith.inc b/lib/hipe/rtl/hipe_rtl_arith.inc
new file mode 100644
index 0000000000..31fedd927e
--- /dev/null
+++ b/lib/hipe/rtl/hipe_rtl_arith.inc
@@ -0,0 +1,177 @@
+%% -*- Erlang -*-
+%% -*- erlang-indent-level: 2 -*-
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2004-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+%%----------------------------------------------------------------------
+%% File : hipe_rtl_arith.inc
+%% Created : Feb 2004
+%% Purpose : Implements arithmetic which is parameterized by the size
+%% of the word of the target architecture (given as defines).
+%%----------------------------------------------------------------------
+
+
+%% Returns a tuple
+%% {Res, Sign, Zero, Overflow, Carry}
+%% Res will be a number in the range
+%% MAX_SIGNED_INT >= Res >= MIN_SIGNED_INT
+%% The other four values are flags that are either true or false
+%%
+eval_alu(Op, Arg1, Arg2)
+ when Arg1 =< ?MAX_SIGNED_INT,
+ Arg1 >= ?MIN_SIGNED_INT,
+ Arg2 =< ?MAX_SIGNED_INT,
+ Arg2 >= ?MIN_SIGNED_INT ->
+
+ Sign1 = sign_bit(Arg1),
+ Sign2 = sign_bit(Arg2),
+
+ case Op of
+ 'sub' ->
+ Res = (Arg1 - Arg2) band ?WORDMASK,
+ N = sign_bit(Res),
+ Z = zero(Res),
+ V = (Sign1 and (not Sign2) and (not N))
+ or
+ ((not Sign1) and Sign2 and N),
+ C = ((not Sign1) and Sign2)
+ or
+ (N and ((not Sign1) or Sign2));
+ 'add' ->
+ Res = (Arg1 + Arg2) band ?WORDMASK,
+ N = sign_bit(Res),
+ Z = zero(Res),
+ V = (Sign1 and Sign2 and (not N))
+ or
+ ((not Sign1) and (not Sign2) and N),
+ C = (Sign1 and Sign2)
+ or
+ ((not N) and (Sign1 or Sign2));
+ 'mul' ->
+ FullRes = Arg1 * Arg2,
+ Res = FullRes band ?WORDMASK,
+ ResHi = FullRes bsr ?BITS,
+ N = sign_bit(Res),
+ Z = zero(Res),
+ V = (N and (ResHi =/= -1)) or ((not N) and (ResHi =/= 0)),
+ C = V;
+ 'sra' ->
+ Res = (Arg1 bsr Arg2) band ?WORDMASK,
+ N = sign_bit(Res),
+ Z = zero(Res),
+ V = 0,
+ C = 0;
+ 'srl' ->
+ Res = (Arg1 bsr Arg2) band shiftmask(Arg2),
+ N = sign_bit(Res),
+ Z = zero(Res),
+ V = 0,
+ C = 0;
+ 'sll' ->
+ Res = (Arg1 bsl Arg2) band ?WORDMASK,
+ N = sign_bit(Res),
+ Z = zero(Res),
+ V = 0,
+ C = 0;
+ 'or' ->
+ Res = (Arg1 bor Arg2) band ?WORDMASK,
+ N = sign_bit(Res),
+ Z = zero(Res),
+ V = 0,
+ C = 0;
+ 'and' ->
+ Res = (Arg1 band Arg2) band ?WORDMASK,
+ N = sign_bit(Res),
+ Z = zero(Res),
+ V = 0,
+ C = 0;
+ 'xor' ->
+ Res = (Arg1 bxor Arg2) band ?WORDMASK,
+ N = sign_bit(Res),
+ Z = zero(Res),
+ V = 0,
+ C = 0;
+ Op ->
+ Res = N = Z = V = C = 0,
+ ?EXIT({"unknown alu op", Op})
+ end,
+ {two_comp_to_erl(Res), N, Z, V, C};
+eval_alu(Op, Arg1, Arg2) ->
+ ?EXIT({argument_overflow,Op,Arg1,Arg2}).
+
+%% Bj�rn & Bjarni:
+%% We need to be able to do evaluations based only on the bits, since
+%% there are cases where we can evaluate a subset of the bits, but can
+%% not do a full eval-alub call (eg. a + 0 gives no carry)
+%%
+-spec eval_cond_bits(atom(), boolean(), boolean(), boolean(), boolean()) -> boolean().
+
+eval_cond_bits(Cond, N, Z, V, C) ->
+ case Cond of
+ 'eq' ->
+ Z;
+ 'ne' ->
+ not Z;
+ 'gt' ->
+ not (Z or (N xor V));
+ 'gtu' ->
+ not (C or Z);
+ 'ge' ->
+ not (N xor V);
+ 'geu'->
+ not C;
+ 'lt' ->
+ N xor V;
+ 'ltu'->
+ C;
+ 'le' ->
+ Z or (N xor V);
+ 'leu'->
+ C or Z;
+ 'overflow' ->
+ V;
+ 'not_overflow' ->
+ not V;
+ _ ->
+ ?EXIT({'condition code not handled',Cond})
+ end.
+
+eval_alub(Op, Cond, Arg1, Arg2) ->
+ {Res, N, Z, V, C} = eval_alu(Op, Arg1, Arg2),
+ {Res, eval_cond_bits(Cond, N, Z, V, C)}.
+
+eval_cond(Cond, Arg1, Arg2) ->
+ {_, Bool} = eval_alub('sub', Cond, Arg1, Arg2),
+ Bool.
+
+sign_bit(Val) ->
+ ((Val bsr ?SIGN_BIT) band 1) =:= 1.
+
+two_comp_to_erl(V) ->
+ if V > ?MAX_SIGNED_INT ->
+ - ((?MAX_UNSIGNED_INT + 1) - V);
+ true -> V
+ end.
+
+shiftmask(Arg) ->
+ Setbits = ?BITS - Arg,
+ (1 bsl Setbits) - 1.
+
+zero(Val) ->
+ Val =:= 0.
+