diff options
Diffstat (limited to 'lib/hipe/rtl/hipe_rtl_arith.inc')
-rw-r--r-- | lib/hipe/rtl/hipe_rtl_arith.inc | 177 |
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. + |