From 84adefa331c4159d432d22840663c38f155cd4c1 Mon Sep 17 00:00:00 2001 From: Erlang/OTP Date: Fri, 20 Nov 2009 14:54:40 +0000 Subject: The R13B03 release. --- lib/hipe/rtl/hipe_tagscheme.erl | 1209 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 1209 insertions(+) create mode 100644 lib/hipe/rtl/hipe_tagscheme.erl (limited to 'lib/hipe/rtl/hipe_tagscheme.erl') diff --git a/lib/hipe/rtl/hipe_tagscheme.erl b/lib/hipe/rtl/hipe_tagscheme.erl new file mode 100644 index 0000000000..dc44b803a1 --- /dev/null +++ b/lib/hipe/rtl/hipe_tagscheme.erl @@ -0,0 +1,1209 @@ +%% -*- erlang-indent-level: 2 -*- +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2001-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% +%% +%%======================================================================== +%% +%% Filename : hipe_tagscheme.erl +%% Note : This is specific to Erlang 5.* (i.e. R9 to R13). +%% +%% Modifications: +%% 020904: Happi - added support for external pids and ports. +%% +%%======================================================================== +%% $Id$ +%%======================================================================== + +-module(hipe_tagscheme). + +-export([mk_nil/0, mk_fixnum/1, mk_arityval/1, mk_non_value/0]). +-export([is_fixnum/1]). +-export([tag_tuple/2, tag_cons/2]). +-export([test_is_boxed/4, get_header/2]). +-export([test_nil/4, test_cons/4, test_flonum/4, test_fixnum/4, + test_tuple/4, test_atom/4, test_bignum/4, test_pos_bignum/4, + test_any_pid/4, test_any_port/4, + test_ref/4, test_fun/4, test_fun2/5, test_matchstate/4, + test_binary/4, test_bitstr/4, test_list/4, + test_integer/4, test_number/4, test_constant/4, test_tuple_N/5]). +-export([realtag_fixnum/2, tag_fixnum/2, realuntag_fixnum/2, untag_fixnum/2]). +-export([test_two_fixnums/3, test_fixnums/4, unsafe_fixnum_add/3, + unsafe_fixnum_sub/3, + fixnum_gt/5, fixnum_lt/5, fixnum_ge/5, fixnum_le/5, fixnum_val/1, + fixnum_mul/4, + fixnum_addsub/5, fixnum_andorxor/4, fixnum_not/2, + fixnum_bsr/3, fixnum_bsl/3]). +-export([unsafe_car/2, unsafe_cdr/2, + unsafe_constant_element/3, unsafe_update_element/3, element/6]). +-export([unsafe_closure_element/3]). +-export([mk_fun_header/0, tag_fun/2]). +-export([unsafe_untag_float/2, unsafe_tag_float/2]). +-export([mk_sub_binary/6,mk_sub_binary/7]). +-export([unsafe_mk_big/3, unsafe_load_float/3]). +-export([bignum_sizeneed/1,bignum_sizeneed_code/2, get_one_word_pos_bignum/3]). +-export([test_subbinary/3, test_heap_binary/3]). +-export([create_heap_binary/3, create_refc_binary/3, create_refc_binary/4]). +-export([create_matchstate/6, convert_matchstate/1, compare_matchstate/4]). +-export([get_field_from_term/3, get_field_from_pointer/3, + set_field_from_term/3, set_field_from_pointer/3, + extract_matchbuffer/2, extract_binary_bytes/2]). + +-include("hipe_rtl.hrl"). +-include("hipe_literals.hrl"). + +-ifdef(EFT_NATIVE_ADDRESS). +-export([if_fun_get_arity_and_address/5]). +-endif. + +-undef(TAG_PRIMARY_BOXED). +-undef(TAG_IMMED2_MASK). +-undef(TAG_IMMED2_CATCH). +-undef(TAG_IMMED2_SIZE). + +%%------------------------------------------------------------------------ + +-define(TAG_PRIMARY_SIZE, 2). +-define(TAG_PRIMARY_MASK, 16#3). +-define(TAG_PRIMARY_HEADER, 16#0). +-define(TAG_PRIMARY_LIST, 16#1). +-define(TAG_PRIMARY_BOXED, 16#2). +-define(TAG_PRIMARY_IMMED1, 16#3). + +-define(TAG_IMMED1_SIZE, 4). +-define(TAG_IMMED1_MASK, 16#F). +-define(TAG_IMMED1_PID, ((16#0 bsl ?TAG_PRIMARY_SIZE) bor ?TAG_PRIMARY_IMMED1)). +-define(TAG_IMMED1_PORT, ((16#1 bsl ?TAG_PRIMARY_SIZE) bor ?TAG_PRIMARY_IMMED1)). +-define(TAG_IMMED1_IMMED2,((16#2 bsl ?TAG_PRIMARY_SIZE) bor ?TAG_PRIMARY_IMMED1)). +-define(TAG_IMMED1_SMALL, ((16#3 bsl ?TAG_PRIMARY_SIZE) bor ?TAG_PRIMARY_IMMED1)). + +-define(TAG_IMMED2_SIZE, 6). +-define(TAG_IMMED2_MASK, 16#3F). +-define(TAG_IMMED2_ATOM, ((16#0 bsl ?TAG_IMMED1_SIZE) bor ?TAG_IMMED1_IMMED2)). +-define(TAG_IMMED2_CATCH, ((16#1 bsl ?TAG_IMMED1_SIZE) bor ?TAG_IMMED1_IMMED2)). +-define(TAG_IMMED2_NIL, ((16#3 bsl ?TAG_IMMED1_SIZE) bor ?TAG_IMMED1_IMMED2)). + +-define(TAG_HEADER_ARITYVAL,((16#0 bsl ?TAG_PRIMARY_SIZE) bor ?TAG_PRIMARY_HEADER)). +-define(TAG_HEADER_BIN_MATCHSTATE, ((16#1 bsl ?TAG_PRIMARY_SIZE) bor ?TAG_PRIMARY_HEADER)). +-define(TAG_HEADER_POS_BIG, ((16#2 bsl ?TAG_PRIMARY_SIZE) bor ?TAG_PRIMARY_HEADER)). +-define(TAG_HEADER_NEG_BIG, ((16#3 bsl ?TAG_PRIMARY_SIZE) bor ?TAG_PRIMARY_HEADER)). +-define(BIG_SIGN_BIT, (16#1 bsl ?TAG_PRIMARY_SIZE)). +-define(TAG_HEADER_REF, ((16#4 bsl ?TAG_PRIMARY_SIZE) bor ?TAG_PRIMARY_HEADER)). +-define(TAG_HEADER_FUN, ((16#5 bsl ?TAG_PRIMARY_SIZE) bor ?TAG_PRIMARY_HEADER)). +-define(TAG_HEADER_FLOAT, ((16#6 bsl ?TAG_PRIMARY_SIZE) bor ?TAG_PRIMARY_HEADER)). +-define(TAG_HEADER_EXPORT, ((16#7 bsl ?TAG_PRIMARY_SIZE) bor ?TAG_PRIMARY_HEADER)). +-define(BINARY_XXX_MASK, (16#3 bsl ?TAG_PRIMARY_SIZE)). +-define(TAG_HEADER_REFC_BIN,((16#8 bsl ?TAG_PRIMARY_SIZE) bor ?TAG_PRIMARY_HEADER)). +-define(TAG_HEADER_HEAP_BIN,((16#9 bsl ?TAG_PRIMARY_SIZE) bor ?TAG_PRIMARY_HEADER)). +-define(TAG_HEADER_SUB_BIN, ((16#A bsl ?TAG_PRIMARY_SIZE) bor ?TAG_PRIMARY_HEADER)). +-define(TAG_HEADER_EXTERNAL_PID, ((16#C bsl ?TAG_PRIMARY_SIZE) bor ?TAG_PRIMARY_HEADER)). +-define(TAG_HEADER_EXTERNAL_PORT,((16#D bsl ?TAG_PRIMARY_SIZE) bor ?TAG_PRIMARY_HEADER)). +-define(TAG_HEADER_EXTERNAL_REF, ((16#E bsl ?TAG_PRIMARY_SIZE) bor ?TAG_PRIMARY_HEADER)). + +-define(TAG_HEADER_MASK, 16#3F). +-define(HEADER_ARITY_OFFS, 6). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +mk_header(SZ,TAG) -> (SZ bsl ?HEADER_ARITY_OFFS) + TAG. +mk_arityval(SZ) -> mk_header(SZ, ?TAG_HEADER_ARITYVAL). + +size_from_header(Sz, Header) -> + [hipe_rtl:mk_alu(Sz, Header, 'srl', hipe_rtl:mk_imm(?HEADER_ARITY_OFFS))]. + +mk_var_header(Header, Size, Tag) -> + Tmp = hipe_rtl:mk_new_reg_gcsafe(), + [hipe_rtl:mk_alu(Tmp, Size, sll, hipe_rtl:mk_imm(?HEADER_ARITY_OFFS)), + hipe_rtl:mk_alu(Header, Tmp, 'add', hipe_rtl:mk_imm(Tag))]. + +mk_fixnum(X) -> (X bsl ?TAG_IMMED1_SIZE) + ?TAG_IMMED1_SMALL. + +-define(NIL, ((-1 bsl ?TAG_IMMED2_SIZE) bor ?TAG_IMMED2_NIL)). +mk_nil() -> ?NIL. +%% mk_atom(X) -> (X bsl ?TAG_IMMED2_SIZE) + ?TAG_IMMED2_ATOM. +mk_non_value() -> ?THE_NON_VALUE. + +-spec is_fixnum(integer()) -> boolean(). +is_fixnum(N) when is_integer(N) -> + Bits = ?bytes_to_bits(hipe_rtl_arch:word_size()) - ?TAG_IMMED1_SIZE, + (N =< ((1 bsl (Bits - 1)) - 1)) and (N >= -(1 bsl (Bits - 1))). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +-define(HEADER_EXPORT, mk_header(1, ?TAG_HEADER_EXPORT)). +-define(HEADER_FUN, mk_header(?ERL_FUN_SIZE-2, ?TAG_HEADER_FUN)). +-define(HEADER_PROC_BIN, mk_header(?PROC_BIN_WORDSIZE-1, ?TAG_HEADER_REFC_BIN)). +-define(HEADER_SUB_BIN, mk_header(?SUB_BIN_WORDSIZE-2, ?TAG_HEADER_SUB_BIN)). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +tag_boxed(Res, X) -> + hipe_rtl:mk_alu(Res, X, 'add', hipe_rtl:mk_imm(?TAG_PRIMARY_BOXED)). + +%% tag_bignum(Res, X) -> tag_boxed(Res, X). +tag_flonum(Res, X) -> tag_boxed(Res, X). +tag_tuple(Res, X) -> tag_boxed(Res, X). + +tag_cons(Res, X) -> + hipe_rtl:mk_alu(Res, X, 'add', hipe_rtl:mk_imm(?TAG_PRIMARY_LIST)). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%%% Operations to test if an object has a known type T. + +test_nil(X, TrueLab, FalseLab, Pred) -> + hipe_rtl:mk_branch(X, eq, hipe_rtl:mk_imm(?NIL), TrueLab, FalseLab, Pred). + +test_cons(X, TrueLab, FalseLab, Pred) -> + Tmp = hipe_rtl:mk_new_reg_gcsafe(), + Mask = hipe_rtl:mk_imm(?TAG_PRIMARY_MASK - ?TAG_PRIMARY_LIST), + hipe_rtl:mk_alub(Tmp, X, 'and', Mask, 'eq', TrueLab, FalseLab, Pred). + +test_is_boxed(X, TrueLab, FalseLab, Pred) -> + Tmp = hipe_rtl:mk_new_reg_gcsafe(), + Mask = hipe_rtl:mk_imm(?TAG_PRIMARY_MASK - ?TAG_PRIMARY_BOXED), + hipe_rtl:mk_alub(Tmp, X, 'and', Mask, 'eq', TrueLab, FalseLab, Pred). + +get_header(Res, X) -> + hipe_rtl:mk_load(Res, X, hipe_rtl:mk_imm(-(?TAG_PRIMARY_BOXED))). + +mask_and_compare(X, Mask, Value, TrueLab, FalseLab, Pred) -> + Tmp = hipe_rtl:mk_new_reg_gcsafe(), + [hipe_rtl:mk_alu(Tmp, X, 'and', hipe_rtl:mk_imm(Mask)), + hipe_rtl:mk_branch(Tmp, 'eq', hipe_rtl:mk_imm(Value), TrueLab, FalseLab, Pred)]. + +test_immed1(X, Value, TrueLab, FalseLab, Pred) -> + mask_and_compare(X, ?TAG_IMMED1_MASK, Value, TrueLab, FalseLab, Pred). + +test_internal_pid(X, TrueLab, FalseLab, Pred) -> + test_immed1(X, ?TAG_IMMED1_PID, TrueLab, FalseLab, Pred). + +test_any_pid(X, TrueLab, FalseLab, Pred) -> + NotInternalPidLab = hipe_rtl:mk_new_label(), + [test_internal_pid(X, TrueLab, hipe_rtl:label_name(NotInternalPidLab), Pred), + NotInternalPidLab, + test_external_pid(X, TrueLab, FalseLab, Pred)]. + +test_external_pid(X, TrueLab, FalseLab, Pred) -> + Tmp = hipe_rtl:mk_new_reg_gcsafe(), + HalfTrueLab = hipe_rtl:mk_new_label(), + ExternalPidMask = ?TAG_HEADER_MASK, + [test_is_boxed(X, hipe_rtl:label_name(HalfTrueLab), FalseLab, Pred), + HalfTrueLab, + get_header(Tmp, X), + mask_and_compare(Tmp, ExternalPidMask, ?TAG_HEADER_EXTERNAL_PID, + TrueLab, FalseLab, Pred)]. + +test_internal_port(X, TrueLab, FalseLab, Pred) -> + test_immed1(X, ?TAG_IMMED1_PORT, TrueLab, FalseLab, Pred). + +test_any_port(X, TrueLab, FalseLab, Pred) -> + NotInternalPortLab = hipe_rtl:mk_new_label(), + [test_internal_port(X, TrueLab, hipe_rtl:label_name(NotInternalPortLab), Pred), + NotInternalPortLab, + test_external_port(X, TrueLab, FalseLab, Pred)]. + +test_external_port(X, TrueLab, FalseLab, Pred) -> + Tmp = hipe_rtl:mk_new_reg_gcsafe(), + HalfTrueLab = hipe_rtl:mk_new_label(), + ExternalPortMask = ?TAG_HEADER_MASK, + [test_is_boxed(X, hipe_rtl:label_name(HalfTrueLab), FalseLab, Pred), + HalfTrueLab, + get_header(Tmp, X), + mask_and_compare(Tmp, ExternalPortMask, ?TAG_HEADER_EXTERNAL_PORT, + TrueLab, FalseLab, Pred)]. + +test_fixnum(X, TrueLab, FalseLab, Pred) -> + test_immed1(X, ?TAG_IMMED1_SMALL, TrueLab, FalseLab, Pred). + +test_atom(X, TrueLab, FalseLab, Pred) -> + mask_and_compare(X, ?TAG_IMMED2_MASK, ?TAG_IMMED2_ATOM, + TrueLab, FalseLab, Pred). + +test_tuple(X, TrueLab, FalseLab, Pred) -> + Tmp = hipe_rtl:mk_new_reg_gcsafe(), + Tmp2 = hipe_rtl:mk_new_reg_gcsafe(), + HalfTrueLab = hipe_rtl:mk_new_label(), + [test_is_boxed(X, hipe_rtl:label_name(HalfTrueLab), FalseLab, Pred), + HalfTrueLab, + get_header(Tmp, X), + hipe_rtl:mk_alub(Tmp2, Tmp, 'and', hipe_rtl:mk_imm(?TAG_HEADER_MASK), 'eq', + TrueLab, FalseLab, Pred)]. + +test_tuple_N(X, N, TrueLab, FalseLab, Pred) -> + Tmp = hipe_rtl:mk_new_reg_gcsafe(), + HalfTrueLab = hipe_rtl:mk_new_label(), + [test_is_boxed(X, hipe_rtl:label_name(HalfTrueLab), FalseLab, Pred), + HalfTrueLab, + get_header(Tmp, X), + hipe_rtl:mk_branch(Tmp, 'eq', hipe_rtl:mk_imm(mk_arityval(N)), + TrueLab, FalseLab, Pred)]. + +test_ref(X, TrueLab, FalseLab, Pred) -> + Hdr = hipe_rtl:mk_new_reg_gcsafe(), + Tag = hipe_rtl:mk_new_reg_gcsafe(), + HalfTrueLab = hipe_rtl:mk_new_label(), + TwoThirdsTrueLab = hipe_rtl:mk_new_label(), + [test_is_boxed(X, hipe_rtl:label_name(HalfTrueLab), FalseLab, Pred), + HalfTrueLab, + get_header(Hdr, X), + hipe_rtl:mk_alu(Tag, Hdr, 'and', hipe_rtl:mk_imm(?TAG_HEADER_MASK)), + hipe_rtl:mk_branch(Tag, 'eq', hipe_rtl:mk_imm(?TAG_HEADER_REF), + TrueLab, hipe_rtl:label_name(TwoThirdsTrueLab), Pred), + TwoThirdsTrueLab, + hipe_rtl:mk_branch(Tag, 'eq', hipe_rtl:mk_imm(?TAG_HEADER_EXTERNAL_REF), + TrueLab, FalseLab, Pred) + ]. + +-ifdef(EFT_NATIVE_ADDRESS). +test_closure(X, TrueLab, FalseLab, Pred) -> + Tmp = hipe_rtl:mk_new_reg_gcsafe(), + HalfTrueLab = hipe_rtl:mk_new_label(), + [test_is_boxed(X, hipe_rtl:label_name(HalfTrueLab), FalseLab, Pred), + HalfTrueLab, + get_header(Tmp, X), + mask_and_compare(Tmp, ?TAG_HEADER_MASK, ?TAG_HEADER_FUN, + TrueLab, FalseLab, Pred)]. +-endif. + +test_fun(X, TrueLab, FalseLab, Pred) -> + Hdr = hipe_rtl:mk_new_reg_gcsafe(), + Tag = hipe_rtl:mk_new_reg_gcsafe(), + HalfTrueLab = hipe_rtl:mk_new_label(), + TwoThirdsTrueLab = hipe_rtl:mk_new_label(), + [test_is_boxed(X, hipe_rtl:label_name(HalfTrueLab), FalseLab, Pred), + HalfTrueLab, + get_header(Hdr, X), + hipe_rtl:mk_alu(Tag, Hdr, 'and', hipe_rtl:mk_imm(?TAG_HEADER_MASK)), + hipe_rtl:mk_branch(Tag, 'eq', hipe_rtl:mk_imm(?TAG_HEADER_FUN), + TrueLab, hipe_rtl:label_name(TwoThirdsTrueLab), Pred), + TwoThirdsTrueLab, + hipe_rtl:mk_branch(Tag, 'eq', hipe_rtl:mk_imm(?TAG_HEADER_EXPORT), + TrueLab, FalseLab, Pred)]. + +test_fun2(X, Arity, TrueLab, FalseLab, Pred) -> + Tmp = hipe_rtl:mk_new_reg_gcsafe(), + TFalse = hipe_rtl:mk_new_reg_gcsafe(), + HalfTrueLab = hipe_rtl:mk_new_label(), + [hipe_rtl:mk_call([Tmp], {erlang,is_function,2}, [X,Arity], + hipe_rtl:label_name(HalfTrueLab), FalseLab, 'not_remote'), + HalfTrueLab, + hipe_rtl:mk_load_atom(TFalse, 'false'), + hipe_rtl:mk_branch(Tmp, 'ne', TFalse, TrueLab, FalseLab, Pred)]. + +flonum_header() -> + mk_header(8 div hipe_rtl_arch:word_size(), ?TAG_HEADER_FLOAT). + +test_flonum(X, TrueLab, FalseLab, Pred) -> + HeaderFlonum = flonum_header(), + Tmp = hipe_rtl:mk_new_reg_gcsafe(), + HalfTrueLab = hipe_rtl:mk_new_label(), + [test_is_boxed(X, hipe_rtl:label_name(HalfTrueLab), FalseLab, Pred), + HalfTrueLab, + get_header(Tmp, X), + hipe_rtl:mk_branch(Tmp, 'eq', hipe_rtl:mk_imm(HeaderFlonum), + TrueLab, FalseLab, Pred)]. + +test_bignum(X, TrueLab, FalseLab, Pred) -> + Tmp = hipe_rtl:mk_new_reg_gcsafe(), + HalfTrueLab = hipe_rtl:mk_new_label(), + BigMask = ?TAG_HEADER_MASK - ?BIG_SIGN_BIT, + [test_is_boxed(X, hipe_rtl:label_name(HalfTrueLab), FalseLab, Pred), + HalfTrueLab, + get_header(Tmp, X), + mask_and_compare(Tmp, BigMask, ?TAG_HEADER_POS_BIG, + TrueLab, FalseLab, Pred)]. + +test_pos_bignum(X, TrueLab, FalseLab, Pred) -> + Tmp = hipe_rtl:mk_new_reg_gcsafe(), + HalfTrueLab = hipe_rtl:mk_new_label(), + BigMask = ?TAG_HEADER_MASK, + [test_is_boxed(X, hipe_rtl:label_name(HalfTrueLab), FalseLab, Pred), + HalfTrueLab, + get_header(Tmp, X), + mask_and_compare(Tmp, BigMask, ?TAG_HEADER_POS_BIG, + TrueLab, FalseLab, Pred)]. + +test_matchstate(X, TrueLab, FalseLab, Pred) -> + Tmp = hipe_rtl:mk_new_reg_gcsafe(), + HalfTrueLab = hipe_rtl:mk_new_label(), + [test_is_boxed(X, hipe_rtl:label_name(HalfTrueLab), FalseLab, Pred), + HalfTrueLab, + get_header(Tmp, X), + mask_and_compare(Tmp, ?TAG_HEADER_MASK, ?TAG_HEADER_BIN_MATCHSTATE, + TrueLab, FalseLab, Pred)]. + +test_bitstr(X, TrueLab, FalseLab, Pred) -> + Tmp = hipe_rtl:mk_new_reg_gcsafe(), + HalfTrueLab = hipe_rtl:mk_new_label(), + Mask = ?TAG_HEADER_MASK - ?BINARY_XXX_MASK, + [test_is_boxed(X, hipe_rtl:label_name(HalfTrueLab), FalseLab, Pred), + HalfTrueLab, + get_header(Tmp, X), + mask_and_compare(Tmp, Mask, ?TAG_HEADER_REFC_BIN, TrueLab, FalseLab, Pred)]. + +test_binary(X, TrueLab, FalseLab, Pred) -> + Tmp1 = hipe_rtl:mk_new_reg_gcsafe(), + Tmp2 = hipe_rtl:mk_new_reg_gcsafe(), + IsBoxedLab = hipe_rtl:mk_new_label(), + IsBitStrLab = hipe_rtl:mk_new_label(), + IsSubBinLab = hipe_rtl:mk_new_label(), + Mask = ?TAG_HEADER_MASK - ?BINARY_XXX_MASK, + [test_is_boxed(X, hipe_rtl:label_name(IsBoxedLab), FalseLab, Pred), + IsBoxedLab, + get_header(Tmp1, X), + mask_and_compare(Tmp1, Mask, ?TAG_HEADER_REFC_BIN, + hipe_rtl:label_name(IsBitStrLab), FalseLab, Pred), + IsBitStrLab, + mask_and_compare(Tmp1, ?TAG_HEADER_MASK, ?TAG_HEADER_SUB_BIN, + hipe_rtl:label_name(IsSubBinLab), TrueLab, 0.5), + IsSubBinLab, + get_field_from_term({sub_binary, bitsize}, X, Tmp2), + hipe_rtl:mk_branch(Tmp2, eq, hipe_rtl:mk_imm(0), TrueLab, FalseLab, Pred)]. + +test_list(X, TrueLab, FalseLab, Pred) -> + Lab = hipe_rtl:mk_new_label(), + [test_cons(X, TrueLab, hipe_rtl:label_name(Lab), 0.5), + Lab, + test_nil(X, TrueLab, FalseLab, Pred)]. + +test_integer(X, TrueLab, FalseLab, Pred) -> + Lab = hipe_rtl:mk_new_label(), + [test_fixnum(X, TrueLab, hipe_rtl:label_name(Lab), 0.5), + Lab, + test_bignum(X, TrueLab, FalseLab, Pred)]. + +test_number(X, TrueLab, FalseLab, Pred) -> + Lab1 = hipe_rtl:mk_new_label(), + Lab2 = hipe_rtl:mk_new_label(), + Lab3 = hipe_rtl:mk_new_label(), + Tmp = hipe_rtl:mk_new_reg_gcsafe(), + BigMask = ?TAG_HEADER_MASK - ?BIG_SIGN_BIT, + HeaderFlonum = flonum_header(), + [test_fixnum(X, TrueLab, hipe_rtl:label_name(Lab1), 0.5), + Lab1, + test_is_boxed(X, hipe_rtl:label_name(Lab2), FalseLab, 0.5), + Lab2, + get_header(Tmp, X), + mask_and_compare(Tmp, BigMask, ?TAG_HEADER_POS_BIG, + TrueLab, hipe_rtl:label_name(Lab3), 0.5), + Lab3, + hipe_rtl:mk_branch(Tmp, 'eq', hipe_rtl:mk_imm(HeaderFlonum), + TrueLab, FalseLab, Pred)]. + +%% CONS, NIL, and TUPLE are not constants, everything else is +test_constant(X, TrueLab, FalseLab, Pred) -> + Lab1 = hipe_rtl:mk_new_label(), + Lab2 = hipe_rtl:mk_new_label(), + Pred1 = 1-Pred, + [test_cons(X, FalseLab, hipe_rtl:label_name(Lab1), Pred1), + Lab1, + test_nil(X, FalseLab, hipe_rtl:label_name(Lab2), Pred1), + Lab2, + test_tuple(X, FalseLab, TrueLab, Pred1)]. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +tag_fixnum(DestVar, SrcReg) -> + [hipe_rtl:mk_fixnumop(DestVar, SrcReg, tag)]. +%% [hipe_rtl:mk_alu(DestVar, SrcReg, sll, hipe_rtl:mk_imm(?TAG_IMMED1_SIZE)), +%% hipe_rtl:mk_alu(DestVar, DestVar, add, hipe_rtl:mk_imm(?TAG_IMMED1_SMALL))]. + +realtag_fixnum(DestVar, SrcReg) -> + [hipe_rtl:mk_alu(DestVar, SrcReg, sll, hipe_rtl:mk_imm(?TAG_IMMED1_SIZE)), + hipe_rtl:mk_alu(DestVar, DestVar, add, hipe_rtl:mk_imm(?TAG_IMMED1_SMALL))]. + +untag_fixnum(DestReg, SrcVar) -> + hipe_rtl:mk_fixnumop(DestReg, SrcVar, untag). +%% hipe_rtl:mk_alu(DestReg, SrcVar, 'sra', hipe_rtl:mk_imm(?TAG_IMMED1_SIZE)). + +realuntag_fixnum(DestReg, SrcVar) -> + hipe_rtl:mk_alu(DestReg, SrcVar, 'sra', hipe_rtl:mk_imm(?TAG_IMMED1_SIZE)). + +fixnum_val(Fixnum) -> + Fixnum bsr ?TAG_IMMED1_SIZE. + +test_fixnums(Args, TrueLab, FalseLab, Pred) -> + {Reg, Ands} = test_fixnums_1(Args, []), + Ands ++ [test_fixnum(Reg, TrueLab, FalseLab, Pred)]. + +test_fixnums_1([Arg1, Arg2], Acc) -> + Tmp = hipe_rtl:mk_new_reg_gcsafe(), + {Tmp, lists:reverse([hipe_rtl:mk_alu(Tmp, Arg1, 'and', Arg2)|Acc])}; +test_fixnums_1([Arg1, Arg2|Args], Acc) -> + Tmp = hipe_rtl:mk_new_reg_gcsafe(), + test_fixnums_1([Tmp|Args], [hipe_rtl:mk_alu(Tmp, Arg1, 'and', Arg2)|Acc]). + +test_two_fixnums(Arg1, Arg2, FalseLab) -> + TrueLab = hipe_rtl:mk_new_label(), + case hipe_rtl:is_imm(Arg2) of + true -> + Value = hipe_rtl:imm_value(Arg2), + case Value band ?TAG_IMMED1_MASK of + ?TAG_IMMED1_SMALL -> + [test_fixnum(Arg1, hipe_rtl:label_name(TrueLab), FalseLab, 0.99), + TrueLab]; + _ -> + [hipe_rtl:mk_goto(FalseLab)] + end; + false -> + Tmp = hipe_rtl:mk_new_reg_gcsafe(), + [hipe_rtl:mk_alu(Tmp, Arg1, 'and', Arg2), + test_fixnum(Tmp, hipe_rtl:label_name(TrueLab), FalseLab, 0.99), + TrueLab] + end. + +fixnum_cmp(Arg1, Arg2, TrueLab, FalseLab, Pred, CmpOp) -> + hipe_rtl:mk_branch(Arg1, CmpOp, Arg2, TrueLab, FalseLab, Pred). + +fixnum_gt(Arg1, Arg2, TrueLab, FalseLab, Pred) -> + fixnum_cmp(Arg1, Arg2, TrueLab, FalseLab, Pred, gt). + +fixnum_lt(Arg1, Arg2, TrueLab, FalseLab, Pred) -> + fixnum_cmp(Arg1, Arg2, TrueLab, FalseLab, Pred, lt). + +fixnum_ge(Arg1, Arg2, TrueLab, FalseLab, Pred) -> + fixnum_cmp(Arg1, Arg2, TrueLab, FalseLab, Pred, ge). + +fixnum_le(Arg1, Arg2, TrueLab, FalseLab, Pred) -> + fixnum_cmp(Arg1, Arg2, TrueLab, FalseLab, Pred, le). + +%% We know the answer will be a fixnum +unsafe_fixnum_add(Arg1, Arg2, Res) -> + Tmp = hipe_rtl:mk_new_reg_gcsafe(), + [hipe_rtl:mk_alu(Tmp, Arg2, sub, hipe_rtl:mk_imm(?TAG_IMMED1_SMALL)), + hipe_rtl:mk_alu(Res, Arg1, add, Tmp)]. + +%% We know the answer will be a fixnum +unsafe_fixnum_sub(Arg1, Arg2, Res) -> + Tmp = hipe_rtl:mk_new_reg_gcsafe(), + [hipe_rtl:mk_alu(Tmp, Arg2, sub, hipe_rtl:mk_imm(?TAG_IMMED1_SMALL)), + hipe_rtl:mk_alu(Res, Arg1, sub, Tmp)]. + +%%% (16X+tag)+((16Y+tag)-tag) = 16X+tag+16Y = 16(X+Y)+tag +%%% (16X+tag)-((16Y+tag)-tag) = 16X+tag-16Y = 16(X-Y)+tag +fixnum_addsub(AluOp, Arg1, Arg2, Res, OtherLab) -> + Tmp = hipe_rtl:mk_new_reg_gcsafe(), + %% XXX: Consider moving this test to the users of fixnum_addsub. + case Arg1 =/= Res andalso Arg2 =/= Res of + true -> + %% Args differ from res. + NoOverflowLab = hipe_rtl:mk_new_label(), + [hipe_rtl:mk_alu(Tmp, Arg2, sub, hipe_rtl:mk_imm(?TAG_IMMED1_SMALL)), + hipe_rtl:mk_alub(Res, Arg1, AluOp, Tmp, not_overflow, + hipe_rtl:label_name(NoOverflowLab), + hipe_rtl:label_name(OtherLab), 0.99), + NoOverflowLab]; + false -> + %% At least one of the arguments is the same as Res. + Tmp2 = hipe_rtl:mk_new_var(), % XXX: shouldn't this var be a reg? + NoOverflowLab = hipe_rtl:mk_new_label(), + [hipe_rtl:mk_alu(Tmp, Arg2, sub, hipe_rtl:mk_imm(?TAG_IMMED1_SMALL)), + hipe_rtl:mk_alub(Tmp2, Arg1, AluOp, Tmp, not_overflow, + hipe_rtl:label_name(NoOverflowLab), + hipe_rtl:label_name(OtherLab), 0.99), + NoOverflowLab, + hipe_rtl:mk_move(Res, Tmp2)] + end. + +%%% ((16X+tag) div 16) * ((16Y+tag)-tag) + tag = X*16Y+tag = 16(XY)+tag +fixnum_mul(Arg1, Arg2, Res, OtherLab) -> + Tmp = hipe_rtl:mk_new_reg_gcsafe(), + U1 = hipe_rtl:mk_new_reg_gcsafe(), + U2 = hipe_rtl:mk_new_reg_gcsafe(), + NoOverflowLab = hipe_rtl:mk_new_label(), + [untag_fixnum(U1, Arg1), + hipe_rtl:mk_alu(U2, Arg2, 'sub', hipe_rtl:mk_imm(?TAG_IMMED1_SMALL)), + hipe_rtl:mk_alub(Tmp, U1, 'mul', U2, overflow, hipe_rtl:label_name(OtherLab), + hipe_rtl:label_name(NoOverflowLab), 0.01), + NoOverflowLab, + hipe_rtl:mk_alu(Res, Tmp, 'add', hipe_rtl:mk_imm(?TAG_IMMED1_SMALL))]. + +fixnum_andorxor(AluOp, Arg1, Arg2, Res) -> + case AluOp of + 'xor' -> + Tmp = hipe_rtl:mk_new_reg_gcsafe(), + [hipe_rtl:mk_alu(Tmp, Arg1, 'xor', Arg2), % clears tag :-( + hipe_rtl:mk_alu(Res, Tmp, 'or', hipe_rtl:mk_imm(?TAG_IMMED1_SMALL))]; + _ -> hipe_rtl:mk_alu(Res, Arg1, AluOp, Arg2) + end. + +fixnum_not(Arg, Res) -> + Mask = (-1 bsl ?TAG_IMMED1_SIZE), + hipe_rtl:mk_alu(Res, Arg, 'xor', hipe_rtl:mk_imm(Mask)). + +fixnum_bsr(Arg1, Arg2, Res) -> + Tmp1 = hipe_rtl:mk_new_reg_gcsafe(), + Tmp2 = hipe_rtl:mk_new_reg_gcsafe(), + [untag_fixnum(Tmp1, Arg2), + hipe_rtl:mk_alu(Tmp2, Arg1, 'sra', Tmp1), + hipe_rtl:mk_alu(Res, Tmp2, 'or', hipe_rtl:mk_imm(?TAG_IMMED1_SMALL))]. + +%% If someone knows how to make this better, please do. +fixnum_bsl(Arg1, Arg2, Res) -> + Tmp1 = hipe_rtl:mk_new_reg_gcsafe(), + Tmp2 = hipe_rtl:mk_new_reg_gcsafe(), + Tmp3 = hipe_rtl:mk_new_reg_gcsafe(), + [untag_fixnum(Tmp2, Arg2), + hipe_rtl:mk_alu(Tmp1, Arg1, 'sub', hipe_rtl:mk_imm(?TAG_IMMED1_SMALL)), + hipe_rtl:mk_alu(Tmp3, Tmp1, 'sll', Tmp2), + hipe_rtl:mk_alu(Res, Tmp3, 'or', hipe_rtl:mk_imm(?TAG_IMMED1_SMALL))]. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +unsafe_car(Dst, Arg) -> + hipe_rtl:mk_load(Dst, Arg, hipe_rtl:mk_imm(-(?TAG_PRIMARY_LIST))). + +unsafe_cdr(Dst, Arg) -> + WordSize = hipe_rtl_arch:word_size(), + hipe_rtl:mk_load(Dst, Arg, hipe_rtl:mk_imm(-(?TAG_PRIMARY_LIST)+WordSize)). + +unsafe_constant_element(Dst, Index, Tuple) -> % Index is an immediate + WordSize = hipe_rtl_arch:word_size(), + Offset = -(?TAG_PRIMARY_BOXED) + WordSize * hipe_rtl:imm_value(Index), + hipe_rtl:mk_load(Dst, Tuple, hipe_rtl:mk_imm(Offset)). + +unsafe_update_element(Tuple, Index, Value) -> % Index is an immediate + WordSize = hipe_rtl_arch:word_size(), + Offset = -(?TAG_PRIMARY_BOXED) + WordSize * hipe_rtl:imm_value(Index), + hipe_rtl:mk_store(Tuple, hipe_rtl:mk_imm(Offset), Value). + +%%% wrong semantics +%% unsafe_variable_element(Dst, Index, Tuple) -> % Index is an unknown fixnum +%% %% Load word at (Tuple - 2) + ((Index >> 4) << 2). +%% %% Offset = ((Index >> 4) << 2) - 2. +%% %% Index = x..x1111 (fixnum tag is 2#1111). +%% %% (Index >> 2) = 00x..x11 and ((Index >> 4) << 2) = 00x..x00. +%% %% Therefore, ((Index >> 4) << 2) = (Index >> 2) - 3. +%% %% So Offset = ((Index >> 4) << 2) - 2 = (Index >> 2) - (3 + 2). +%% Tmp1 = hipe_rtl:mk_new_reg_gcsafe(), +%% Tmp2 = hipe_rtl:mk_new_reg_gcsafe(), +%% Shift = ?TAG_IMMED1_SIZE - 2, +%% OffAdj = (?TAG_IMMED1_SMALL bsr Shift) + ?TAG_PRIMARY_BOXED, +%% [hipe_rtl:mk_alu(Tmp1, Index, 'srl', hipe_rtl:mk_imm(Shift)), +%% hipe_rtl:mk_alu(Tmp2, Tmp1, 'sub', hipe_rtl:mk_imm(OffAdj)), +%% hipe_rtl:mk_load(Dst, Tuple, Tmp2)]. + +element(Dst, Index, Tuple, FailLabName, {tuple, A}, IndexInfo) -> + FixnumOkLab = hipe_rtl:mk_new_label(), + IndexOkLab = hipe_rtl:mk_new_label(), + Ptr = hipe_rtl:mk_new_reg(), % offset from Tuple + UIndex = hipe_rtl:mk_new_reg_gcsafe(), + Arity = hipe_rtl:mk_imm(A), + InvIndex = hipe_rtl:mk_new_reg_gcsafe(), + Offset = hipe_rtl:mk_new_reg_gcsafe(), + case IndexInfo of + valid -> + %% This is no branch, 1 load and 3 alus = 4 instr + [untag_fixnum(UIndex, Index), + hipe_rtl:mk_alu(Ptr, Tuple, 'sub', hipe_rtl:mk_imm(?TAG_PRIMARY_BOXED)), + hipe_rtl:mk_alu(Offset, UIndex, 'sll', + hipe_rtl:mk_imm(hipe_rtl_arch:log2_word_size())), + hipe_rtl:mk_load(Dst, Ptr, Offset)]; + fixnums -> + %% This is 1 branch, 1 load and 4 alus = 6 instr + [untag_fixnum(UIndex, Index), + hipe_rtl:mk_alu(Ptr, Tuple, 'sub',hipe_rtl:mk_imm(?TAG_PRIMARY_BOXED))| + gen_element_tail(Dst, Ptr, InvIndex, Arity, Offset, UIndex, + FailLabName, IndexOkLab)]; + _ -> + %% This is 3 branches, 1 load and 5 alus = 9 instr + [test_fixnum(Index, hipe_rtl:label_name(FixnumOkLab), + FailLabName, 0.99), + FixnumOkLab, + untag_fixnum(UIndex, Index), + hipe_rtl:mk_alu(Ptr, Tuple, 'sub',hipe_rtl:mk_imm(?TAG_PRIMARY_BOXED))| + gen_element_tail(Dst, Ptr, InvIndex, Arity, Offset, UIndex, + FailLabName, IndexOkLab)] + end; +element(Dst, Index, Tuple, FailLabName, tuple, IndexInfo) -> + FixnumOkLab = hipe_rtl:mk_new_label(), + IndexOkLab = hipe_rtl:mk_new_label(), + Ptr = hipe_rtl:mk_new_reg(), % offset from Tuple + Header = hipe_rtl:mk_new_reg_gcsafe(), + UIndex = hipe_rtl:mk_new_reg_gcsafe(), + Arity = hipe_rtl:mk_new_reg_gcsafe(), + InvIndex = hipe_rtl:mk_new_reg_gcsafe(), + Offset = hipe_rtl:mk_new_reg_gcsafe(), + case IndexInfo of + fixnums -> + %% This is 1 branch, 2 loads and 5 alus = 8 instr + [hipe_rtl:mk_alu(Ptr, Tuple, 'sub', hipe_rtl:mk_imm(?TAG_PRIMARY_BOXED)), + hipe_rtl:mk_load(Header, Ptr, hipe_rtl:mk_imm(0)), + untag_fixnum(UIndex, Index), + hipe_rtl:mk_alu(Arity,Header,'srl',hipe_rtl:mk_imm(?HEADER_ARITY_OFFS))| + gen_element_tail(Dst, Ptr, InvIndex, Arity, Offset, UIndex, + FailLabName, IndexOkLab)]; + Num when is_integer(Num) -> + %% This is 1 branch, 1 load and 3 alus = 5 instr + [hipe_rtl:mk_alu(Ptr, Tuple, 'sub', hipe_rtl:mk_imm(?TAG_PRIMARY_BOXED))| + gen_element_tail(Dst, Ptr, InvIndex, hipe_rtl:mk_imm(Num), + Offset, UIndex, FailLabName, IndexOkLab)]; + _ -> + %% This is 2 branches, 2 loads and 6 alus = 10 instr + [test_fixnum(Index, hipe_rtl:label_name(FixnumOkLab), FailLabName, 0.99), + FixnumOkLab, + hipe_rtl:mk_alu(Ptr, Tuple, 'sub', hipe_rtl:mk_imm(?TAG_PRIMARY_BOXED)), + hipe_rtl:mk_load(Header, Ptr, hipe_rtl:mk_imm(0)), + untag_fixnum(UIndex, Index), + hipe_rtl:mk_alu(Arity,Header,'srl',hipe_rtl:mk_imm(?HEADER_ARITY_OFFS))| + gen_element_tail(Dst, Ptr, InvIndex, Arity, Offset, UIndex, + FailLabName, IndexOkLab)] + end; +element(Dst, Index, Tuple, FailLabName, unknown, IndexInfo) -> + FixnumOkLab = hipe_rtl:mk_new_label(), + BoxedOkLab = hipe_rtl:mk_new_label(), + TupleOkLab = hipe_rtl:mk_new_label(), + IndexOkLab = hipe_rtl:mk_new_label(), + Ptr = hipe_rtl:mk_new_reg(), % offset from Tuple + Header = hipe_rtl:mk_new_reg_gcsafe(), + Tmp = hipe_rtl:mk_new_reg_gcsafe(), + UIndex = hipe_rtl:mk_new_reg_gcsafe(), + Arity = hipe_rtl:mk_new_reg_gcsafe(), + InvIndex = hipe_rtl:mk_new_reg_gcsafe(), + Offset = hipe_rtl:mk_new_reg_gcsafe(), + case IndexInfo of + fixnums -> + %% This is 3 branches, 2 loads and 5 alus = 10 instr + [test_is_boxed(Tuple, hipe_rtl:label_name(BoxedOkLab), + FailLabName, 0.99), + BoxedOkLab, + hipe_rtl:mk_alu(Ptr, Tuple, 'sub', hipe_rtl:mk_imm(?TAG_PRIMARY_BOXED)), + hipe_rtl:mk_load(Header, Ptr, hipe_rtl:mk_imm(0)), + hipe_rtl:mk_alub(Tmp, Header, 'and', + hipe_rtl:mk_imm(?TAG_HEADER_MASK), 'eq', + hipe_rtl:label_name(TupleOkLab), FailLabName, 0.99), + TupleOkLab, + untag_fixnum(UIndex, Index), + hipe_rtl:mk_alu(Arity, Header, 'srl', + hipe_rtl:mk_imm(?HEADER_ARITY_OFFS))| + gen_element_tail(Dst, Ptr, InvIndex, Arity, Offset, + UIndex, FailLabName, IndexOkLab)]; + Num when is_integer(Num) -> + %% This is 3 branches, 2 loads and 4 alus = 9 instr + [test_is_boxed(Tuple, hipe_rtl:label_name(BoxedOkLab), + FailLabName, 0.99), + BoxedOkLab, + hipe_rtl:mk_alu(Ptr, Tuple, 'sub', hipe_rtl:mk_imm(?TAG_PRIMARY_BOXED)), + hipe_rtl:mk_load(Header, Ptr, hipe_rtl:mk_imm(0)), + hipe_rtl:mk_alub(Tmp, Header, 'and', + hipe_rtl:mk_imm(?TAG_HEADER_MASK), 'eq', + hipe_rtl:label_name(TupleOkLab), FailLabName, 0.99), + TupleOkLab, + hipe_rtl:mk_alu(Arity, Header, 'srl', + hipe_rtl:mk_imm(?HEADER_ARITY_OFFS))| + gen_element_tail(Dst, Ptr, InvIndex, Arity, Offset, + hipe_rtl:mk_imm(Num), FailLabName, IndexOkLab)]; + _ -> + %% This is 4 branches, 2 loads, and 6 alus = 12 instr :( + [test_fixnum(Index, hipe_rtl:label_name(FixnumOkLab), + FailLabName, 0.99), + FixnumOkLab, + test_is_boxed(Tuple, hipe_rtl:label_name(BoxedOkLab), + FailLabName, 0.99), + BoxedOkLab, + hipe_rtl:mk_alu(Ptr, Tuple, 'sub', hipe_rtl:mk_imm(?TAG_PRIMARY_BOXED)), + hipe_rtl:mk_load(Header, Ptr, hipe_rtl:mk_imm(0)), + hipe_rtl:mk_alub(Tmp, Header, 'and', + hipe_rtl:mk_imm(?TAG_HEADER_MASK), 'eq', + hipe_rtl:label_name(TupleOkLab), FailLabName, 0.99), + TupleOkLab, + untag_fixnum(UIndex, Index), + hipe_rtl:mk_alu(Arity, Header, 'srl', + hipe_rtl:mk_imm(?HEADER_ARITY_OFFS))| + gen_element_tail(Dst, Ptr, InvIndex, Arity, Offset, + UIndex, FailLabName, IndexOkLab)] + end. + +gen_element_tail(Dst, Ptr, InvIndex, Arity, Offset, + UIndex, FailLabName, IndexOkLab) -> + %% now check that 1 <= UIndex <= Arity + %% if UIndex < 1, then (Arity - UIndex) >= Arity + %% if UIndex > Arity, then (Arity - UIndex) < 0, which is >=u Arity + %% otherwise, 0 <= (Arity - UIndex) < Arity + [hipe_rtl:mk_alu(InvIndex, Arity, 'sub', UIndex), + hipe_rtl:mk_branch(InvIndex, 'geu', Arity, FailLabName, + hipe_rtl:label_name(IndexOkLab), 0.01), + IndexOkLab, + hipe_rtl:mk_alu(Offset, UIndex, 'sll', + hipe_rtl:mk_imm(hipe_rtl_arch:log2_word_size())), + hipe_rtl:mk_load(Dst, Ptr, Offset)]. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +unsafe_closure_element(Dst, Index, Closure) -> % Index is an immediate + Offset = -(?TAG_PRIMARY_BOXED) %% Untag + + ?EFT_ENV %% Field offset + %% Index from 1 to N hence -1) + + (hipe_rtl_arch:word_size() * (hipe_rtl:imm_value(Index)-1)), + hipe_rtl:mk_load(Dst, Closure, hipe_rtl:mk_imm(Offset)). + +mk_fun_header() -> + hipe_rtl:mk_imm(?HEADER_FUN). + +tag_fun(Res, X) -> + tag_boxed(Res, X). + +%% untag_fun(Res, X) -> +%% hipe_rtl:mk_alu(Res, X, 'sub', hipe_rtl:mk_imm(?TAG_PRIMARY_BOXED)). + +-ifdef(EFT_NATIVE_ADDRESS). +if_fun_get_arity_and_address(ArityReg, AddressReg, FunP, BadFunLab, Pred) -> + %% EmuAddressPtrReg = hipe_rtl:mk_new_reg(), + %% FEPtrReg = hipe_rtl:mk_new_reg(), + %% ArityReg = hipe_rtl:mk_new_reg(), + %% NumFreeReg = hipe_rtl:mk_new_reg(), + %% RealArityReg = hipe_rtl:mk_new_reg(), + TrueLab0 = hipe_rtl:mk_new_label(), + %% TrueLab1 = hipe_rtl:mk_new_label(), + IsFunCode = test_closure(FunP, hipe_rtl:label_name(TrueLab0), BadFunLab, Pred), + GetArityCode = + [TrueLab0, + %% Funp->arity contains the arity + hipe_rtl:mk_load(ArityReg, FunP, + hipe_rtl:mk_imm(-(?TAG_PRIMARY_BOXED)+ + ?EFT_ARITY)), + hipe_rtl:mk_load(AddressReg, FunP, + hipe_rtl:mk_imm(-(?TAG_PRIMARY_BOXED)+ + ?EFT_NATIVE_ADDRESS))], + IsFunCode ++ GetArityCode. +-endif. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% +%% Binary Code +%% + +create_heap_binary(Base, Size, Dst) when is_integer(Size) -> + {GetHPInsn, HP, PutHPInsn} = hipe_rtl_arch:heap_pointer(), + WordSize = hipe_rtl_arch:word_size(), + NoWords=(Size + 3*WordSize-1) div WordSize, + NoBytes = NoWords*WordSize, + HeapBinHeader = hipe_rtl:mk_imm(mk_header(NoWords-1, + ?TAG_HEADER_HEAP_BIN)), + [GetHPInsn, + tag_boxed(Dst, HP), + set_field_from_pointer({heap_bin, thing_word}, HP, HeapBinHeader), + set_field_from_pointer({heap_bin, binsize}, HP, hipe_rtl:mk_imm(Size)), + hipe_rtl:mk_alu(Base, HP, add, hipe_rtl:mk_imm(?HEAP_BIN_DATA)), + hipe_rtl:mk_alu(HP, HP, add, hipe_rtl:mk_imm(NoBytes)), + PutHPInsn]; + +create_heap_binary(Base, Size, Dst) -> + {GetHPInsn, HP, PutHPInsn} = hipe_rtl_arch:heap_pointer(), + WordSize = hipe_rtl_arch:word_size(), + Log2WordSize = hipe_rtl_arch:log2_word_size(), + EvenWordSize = hipe_rtl:mk_new_reg_gcsafe(), + Tmp1 = hipe_rtl:mk_new_reg_gcsafe(), + Tmp2 = hipe_rtl:mk_new_reg_gcsafe(), + Header = hipe_rtl:mk_new_reg_gcsafe(), + Tmp3 = hipe_rtl:mk_new_reg(), % offset from HP + Tmp4 = hipe_rtl:mk_new_reg(), % offset from HP + [GetHPInsn, + hipe_rtl:mk_alu(Tmp1, Size, add, hipe_rtl:mk_imm(WordSize-1)), + hipe_rtl:mk_alu(EvenWordSize, Tmp1, sra, hipe_rtl:mk_imm(Log2WordSize)), + hipe_rtl:mk_alu(Tmp2, EvenWordSize, add, hipe_rtl:mk_imm(1)), + hipe_rtl:mk_alu(Base, HP, add, hipe_rtl:mk_imm(?HEAP_BIN_DATA)), + mk_var_header(Header, Tmp2, ?TAG_HEADER_HEAP_BIN), + set_field_from_pointer({heap_bin, thing_word}, HP, Header), + set_field_from_pointer({heap_bin, binsize}, HP, Size), + tag_boxed(Dst, HP), + hipe_rtl:mk_alu(Tmp3, HP, add, Size), + hipe_rtl:mk_alu(Tmp4, Tmp3, add, hipe_rtl:mk_imm(3*WordSize-1)), + hipe_rtl:mk_alu(HP, Tmp4, 'and', hipe_rtl:mk_imm(-WordSize)), + PutHPInsn]. + +create_refc_binary(Base, Size, Dst) -> + create_refc_binary(Base, Size, hipe_rtl:mk_imm(0), Dst). + +create_refc_binary(Base, Size, Flags, Dst) -> + {GetHPInsn, HP, PutHPInsn} = hipe_rtl_arch:heap_pointer(), + ProcBinHeader = hipe_rtl:mk_imm(?HEADER_PROC_BIN), + WordSize = hipe_rtl_arch:word_size(), + Val = hipe_rtl:mk_new_reg(), % offset from Base + [GetHPInsn, + tag_boxed(Dst, HP), + set_field_from_pointer({proc_bin, thing_word}, HP, ProcBinHeader), + set_field_from_pointer({proc_bin, binsize}, HP, Size), + heap_arch_spec(HP), + hipe_rtl:mk_alu(Val, Base, sub, hipe_rtl:mk_imm(?BINARY_ORIG_BYTES)), + set_field_from_pointer({proc_bin, val}, HP, Val), + set_field_from_pointer({proc_bin, bytes}, HP, Base), + set_field_from_pointer({proc_bin, flags}, HP, Flags), + hipe_rtl:mk_alu(HP, HP, add, hipe_rtl:mk_imm(?PROC_BIN_WORDSIZE*WordSize)), + PutHPInsn]. + +heap_arch_spec(HP) -> + Tmp1 = hipe_rtl:mk_new_reg(), % MSO state + [hipe_rtl_arch:pcb_load(Tmp1, ?P_OFF_HEAP_MSO), + set_field_from_pointer({proc_bin, next}, HP, Tmp1), + hipe_rtl_arch:pcb_store(?P_OFF_HEAP_MSO, HP)]. + +test_heap_binary(Binary, TrueLblName, FalseLblName) -> + Tmp1 = hipe_rtl:mk_new_reg_gcsafe(), + Tmp2 = hipe_rtl:mk_new_reg_gcsafe(), + [get_header(Tmp1, Binary), + hipe_rtl:mk_alu(Tmp2, Tmp1, 'and', hipe_rtl:mk_imm(?TAG_HEADER_MASK)), + hipe_rtl:mk_branch(Tmp2, eq, hipe_rtl:mk_imm(?TAG_HEADER_HEAP_BIN), + TrueLblName, FalseLblName)]. + +mk_sub_binary(Dst, ByteSize, ByteOffs, BitSize, BitOffs, Orig) -> + mk_sub_binary(Dst, ByteSize, ByteOffs, BitSize, BitOffs, + hipe_rtl:mk_imm(0), Orig). + +mk_sub_binary(Dst, ByteSize, ByteOffs, BitSize, BitOffs, + Writable, Orig) -> + {GetHPInsn, HP, PutHPInsn} = hipe_rtl_arch:heap_pointer(), + WordSize = hipe_rtl_arch:word_size(), + [GetHPInsn, + tag_boxed(Dst, HP), + build_sub_binary(Dst, ByteSize, ByteOffs, BitSize, BitOffs, Writable, Orig), + hipe_rtl:mk_alu(HP, HP, add, hipe_rtl:mk_imm(?SUB_BIN_WORDSIZE*WordSize)), + PutHPInsn]. + +build_sub_binary(Dst, ByteSize, ByteOffs, BitSize, BitOffs, + Writable, Orig) -> + Head = hipe_rtl:mk_imm(?HEADER_SUB_BIN), + [set_field_from_term({sub_binary, thing_word}, Dst, Head), + set_field_from_term({sub_binary, binsize}, Dst, ByteSize), + set_field_from_term({sub_binary, offset}, Dst, ByteOffs), + set_field_from_term({sub_binary, bitsize}, Dst, BitSize), + set_field_from_term({sub_binary, bitoffset}, Dst, BitOffs), + set_field_from_term({sub_binary, is_writable}, Dst, Writable), + set_field_from_term({sub_binary, orig}, Dst, Orig)]. + +test_subbinary(Binary, TrueLblName, FalseLblName) -> + Tmp1 = hipe_rtl:mk_new_reg_gcsafe(), + Tmp2 = hipe_rtl:mk_new_reg_gcsafe(), + [get_header(Tmp1, Binary), + hipe_rtl:mk_alu(Tmp2, Tmp1, 'and', hipe_rtl:mk_imm(?TAG_HEADER_MASK)), + hipe_rtl:mk_branch(Tmp2, eq, hipe_rtl:mk_imm(?TAG_HEADER_SUB_BIN), TrueLblName, FalseLblName)]. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% +%% Float Code + +unsafe_load_float(DstLo, DstHi, Src) -> + WordSize = hipe_rtl_arch:word_size(), + Offset1 = -(?TAG_PRIMARY_BOXED) + WordSize, + Offset2 = Offset1 + 4, %% This should really be 4 and not WordSize + case hipe_rtl_arch:endianess() of + little -> + [hipe_rtl:mk_load(DstLo, Src, hipe_rtl:mk_imm(Offset1), int32, unsigned), + hipe_rtl:mk_load(DstHi, Src, hipe_rtl:mk_imm(Offset2), int32, unsigned)]; + big -> + [hipe_rtl:mk_load(DstHi, Src, hipe_rtl:mk_imm(Offset1), int32, unsigned), + hipe_rtl:mk_load(DstLo, Src, hipe_rtl:mk_imm(Offset2), int32, unsigned)] + end. + +unsafe_untag_float(Dst, Src) -> + Offset = -(?TAG_PRIMARY_BOXED) + hipe_rtl_arch:word_size(), + [hipe_rtl:mk_fload(Dst, Src, hipe_rtl:mk_imm(Offset))]. + +unsafe_tag_float(Dst, Src) -> + {GetHPInsn, HP, PutHPInsn} = hipe_rtl_arch:heap_pointer(), + Head = hipe_rtl:mk_imm(flonum_header()), + WordSize = hipe_rtl_arch:word_size(), + [GetHPInsn, + hipe_rtl:mk_store(HP, hipe_rtl:mk_imm(0), Head), + hipe_rtl:mk_fstore(HP, hipe_rtl:mk_imm(WordSize), Src), + tag_flonum(Dst, HP), + hipe_rtl:mk_alu(HP, HP, add, hipe_rtl:mk_imm(WordSize+8)), + PutHPInsn]. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% +%% BigNum Code + +unsafe_mk_big(Dst, Src, Signedness) -> + WordSize = hipe_rtl_arch:word_size(), + {GetHPInsn, HP, PutHPInsn} = hipe_rtl_arch:heap_pointer(), + PosHead = hipe_rtl:mk_imm(mk_header(1, ?TAG_HEADER_POS_BIG)), + NegHead = hipe_rtl:mk_imm(mk_header(1, ?TAG_HEADER_NEG_BIG)), + PosLabel = hipe_rtl:mk_new_label(), + NegLabel = hipe_rtl:mk_new_label(), + JoinLabel = hipe_rtl:mk_new_label(), + PutHeaderCode = + case Signedness of + unsigned -> + [hipe_rtl:mk_store(HP, hipe_rtl:mk_imm(0*WordSize), PosHead)]; + signed -> + [hipe_rtl:mk_branch(Src, ge, hipe_rtl:mk_imm(0), + hipe_rtl:label_name(PosLabel), + hipe_rtl:label_name(NegLabel)), + PosLabel, + hipe_rtl:mk_store(HP, hipe_rtl:mk_imm(0*WordSize), PosHead), + hipe_rtl:mk_goto(hipe_rtl:label_name(JoinLabel)), + NegLabel, + hipe_rtl:mk_store(HP, hipe_rtl:mk_imm(0*WordSize), NegHead), + JoinLabel] + end, + RestCode = + [hipe_rtl:mk_store(HP, hipe_rtl:mk_imm(1*WordSize), Src), + tag_boxed(Dst, HP), + hipe_rtl:mk_alu(HP, HP, add, hipe_rtl:mk_imm(2*WordSize)), + PutHPInsn], + [GetHPInsn] ++ PutHeaderCode ++ RestCode. + +get_one_word_pos_bignum(USize, Size, Fail) -> + Header = hipe_rtl:mk_new_reg(), + HalfLbl = hipe_rtl:mk_new_label(), + HalfLblName = hipe_rtl:label_name(HalfLbl), + WordSize = hipe_rtl_arch:word_size(), + PosHead = hipe_rtl:mk_imm(mk_header(1, ?TAG_HEADER_POS_BIG)), + [get_header(Header, Size), + hipe_rtl:mk_branch(Header, eq, PosHead, HalfLblName, Fail), + HalfLbl, + hipe_rtl:mk_load(USize, Size, hipe_rtl:mk_imm(1*WordSize + -?TAG_PRIMARY_BOXED))]. + +-spec bignum_sizeneed(non_neg_integer()) -> non_neg_integer(). + +bignum_sizeneed(Size) -> + WordSizeBits = hipe_rtl_arch:word_size() * 8, + case is_fixnum(1 bsl Size) of + true -> + 0; + false -> + ((Size + (WordSizeBits-1)) div WordSizeBits) + 1 + end. + +bignum_sizeneed_code(SizeReg,FixNumLblName) -> + WordSizeBits = hipe_rtl_arch:word_size() * 8, + WordShifts = hipe_rtl_arch:log2_word_size() + 3, + MaxFixNum = WordSizeBits - ?TAG_IMMED1_SIZE - 1, + ResReg = hipe_rtl:mk_new_reg_gcsafe(), + Tmp1 = hipe_rtl:mk_new_reg_gcsafe(), + BigLbl = hipe_rtl:mk_new_label(), + Code = + [hipe_rtl:mk_branch(SizeReg, le, hipe_rtl:mk_imm(MaxFixNum), + FixNumLblName, hipe_rtl:label_name(BigLbl)), + BigLbl, + hipe_rtl:mk_alu(Tmp1,SizeReg,add,hipe_rtl:mk_imm(WordSizeBits-1)), + hipe_rtl:mk_alu(ResReg,Tmp1,srl,hipe_rtl:mk_imm(WordShifts)), + hipe_rtl:mk_alu(ResReg,ResReg,add,hipe_rtl:mk_imm(1))], + {ResReg,Code}. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% +%% MatchState Code + +create_matchstate(Max, BinSize, Base, Offset, Orig, Ms) -> + WordSize = hipe_rtl_arch:word_size(), + {GetHPInsn, HP, PutHPInsn} = hipe_rtl_arch:heap_pointer(), + ByteSize = (Max+1)*WordSize + ?MS_SAVEOFFSET, + SizeInWords = ((ByteSize div WordSize) - 1), + Header = hipe_rtl:mk_imm(mk_header(SizeInWords, ?TAG_HEADER_BIN_MATCHSTATE)), + [GetHPInsn, + hipe_rtl:mk_alu(Ms, HP, add, hipe_rtl:mk_imm(?TAG_PRIMARY_BOXED)), + set_field_from_term({matchstate,thing_word}, Ms, Header), + set_field_from_term({matchstate,{matchbuffer,orig}}, Ms, Orig), + set_field_from_term({matchstate,{matchbuffer,base}}, Ms, Base), + set_field_from_term({matchstate,{matchbuffer,binsize}}, Ms, BinSize), + set_field_from_term({matchstate,{matchbuffer,offset}}, Ms, Offset), + set_field_from_term({matchstate,{saveoffset, 0}}, Ms, Offset), + hipe_rtl:mk_alu(HP, HP, add, hipe_rtl:mk_imm(ByteSize)), + PutHPInsn]. + +convert_matchstate(Ms) -> + WordSize = hipe_rtl_arch:word_size(), + Header = hipe_rtl:mk_new_reg_gcsafe(), + TmpSize = hipe_rtl:mk_new_reg_gcsafe(), + SavedOffset = hipe_rtl:mk_new_reg_gcsafe(), + Orig = hipe_rtl:mk_new_reg_gcsafe(), + BinSize = hipe_rtl:mk_new_reg_gcsafe(), + ByteSize = hipe_rtl:mk_new_reg_gcsafe(), + BitSize = hipe_rtl:mk_new_reg_gcsafe(), + ByteOffset = hipe_rtl:mk_new_reg_gcsafe(), + BitOffset = hipe_rtl:mk_new_reg_gcsafe(), + SizeInWords = hipe_rtl:mk_new_reg_gcsafe(), + Hole = hipe_rtl:mk_new_reg_gcsafe(), + BigIntHeader = hipe_rtl:mk_new_reg_gcsafe(), + [get_field_from_term({matchstate, {matchbuffer, orig}}, Ms, Orig), + get_field_from_term({matchstate, {matchbuffer, binsize}}, Ms, BinSize), + get_field_from_term({matchstate, {saveoffset, 0}}, Ms, SavedOffset), + get_field_from_term({matchstate, thing_word}, Ms, Header), + hipe_rtl:mk_alu(TmpSize, BinSize, sub, SavedOffset), + hipe_rtl:mk_alu(BitSize, TmpSize, 'and', hipe_rtl:mk_imm(7)), + hipe_rtl:mk_alu(BitOffset, SavedOffset, 'and', hipe_rtl:mk_imm(7)), + hipe_rtl:mk_alu(ByteSize, TmpSize, srl, hipe_rtl:mk_imm(3)), + hipe_rtl:mk_alu(ByteOffset, SavedOffset, srl, hipe_rtl:mk_imm(3)), + build_sub_binary(Ms, ByteSize, ByteOffset, BitSize, BitOffset, + hipe_rtl:mk_imm(0), Orig), + size_from_header(SizeInWords, Header), + hipe_rtl:mk_alu(Hole, SizeInWords, sub, hipe_rtl:mk_imm(?SUB_BIN_WORDSIZE-1)), + mk_var_header(BigIntHeader, Hole, ?TAG_HEADER_POS_BIG), + hipe_rtl:mk_store(Ms, hipe_rtl:mk_imm(?SUB_BIN_WORDSIZE*WordSize-?TAG_PRIMARY_BOXED), + BigIntHeader)]. + +compare_matchstate(Max, Ms, LargeEnough, TooSmall) -> + WordSize = hipe_rtl_arch:word_size(), + ByteSize = (Max+1)*WordSize + ?MS_SAVEOFFSET, + SizeInWords = ((ByteSize div WordSize) - 1), + Header = hipe_rtl:mk_imm(mk_header(SizeInWords, ?TAG_HEADER_BIN_MATCHSTATE)), + RealHeader = hipe_rtl:mk_new_reg_gcsafe(), + [hipe_rtl:mk_load(RealHeader, Ms, hipe_rtl:mk_imm(-?TAG_PRIMARY_BOXED)), + hipe_rtl:mk_branch(RealHeader, ge, Header, LargeEnough, TooSmall)]. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% +%% Struct manipulation code + +get_field_offset({matchstate, thing_word}) -> + ?MS_THING_WORD; +get_field_offset({matchstate, matchbuffer}) -> + ?MS_MATCHBUFFER; +get_field_offset({matchstate, {matchbuffer, _} = Field}) -> + ?MS_MATCHBUFFER + get_field_offset(Field); +get_field_offset({matchstate, {saveoffset, N}} = Field) -> + ?MS_SAVEOFFSET + N*get_field_size1(Field); +get_field_offset({sub_binary, thing_word}) -> + ?SUB_BIN_THING_WORD; +get_field_offset({sub_binary, binsize}) -> + ?SUB_BIN_BINSIZE; +get_field_offset({sub_binary, bitsize}) -> + ?SUB_BIN_BITSIZE; +get_field_offset({sub_binary, offset}) -> + ?SUB_BIN_OFFS; +get_field_offset({sub_binary, bitoffset}) -> + ?SUB_BIN_BITOFFS; +get_field_offset({sub_binary, is_writable}) -> + ?SUB_BIN_WRITABLE; +get_field_offset({sub_binary, orig}) -> + ?SUB_BIN_ORIG; +get_field_offset({proc_bin, thing_word}) -> + ?PROC_BIN_THING_WORD; +get_field_offset({proc_bin, binsize}) -> + ?PROC_BIN_BINSIZE; +get_field_offset({proc_bin, next}) -> + ?PROC_BIN_NEXT; +get_field_offset({proc_bin, val}) -> + ?PROC_BIN_VAL; +get_field_offset({proc_bin, bytes}) -> + ?PROC_BIN_BYTES; +get_field_offset({proc_bin, flags}) -> + ?PROC_BIN_FLAGS; +get_field_offset({binary, orig_bytes}) -> + ?BINARY_ORIG_BYTES; +get_field_offset({binary, orig_size}) -> + ?BINARY_ORIG_SIZE; +get_field_offset({heap_bin, thing_word}) -> + ?HEAP_BIN_THING_WORD; +get_field_offset({heap_bin, binsize}) -> + ?HEAP_BIN_SIZE; +get_field_offset({heap_bin, {data, N}} = Field) -> + ?HEAP_BIN_DATA+N*get_field_size1(Field); +get_field_offset({matchbuffer, offset}) -> + ?MB_OFFSET; +get_field_offset({matchbuffer, orig}) -> + ?MB_ORIG; +get_field_offset({matchbuffer, base}) -> + ?MB_BASE; +get_field_offset({matchbuffer, binsize}) -> + ?MB_SIZE. + +get_field_size(Field) -> + size_to_atom(get_field_size1(Field)). + +size_to_atom(Bytes) -> + WordSize = hipe_rtl_arch:word_size(), + case Bytes of + WordSize -> word; + 4 -> int32; + %%2 -> int16; So far there are no 2 byte fields + 1 -> byte + end. + +get_field_size1({matchstate, thing_word}) -> + ?MS_THING_WORD_SIZE; +get_field_size1({matchstate, {matchbuffer, _} = Field}) -> + get_field_size1(Field); +get_field_size1({matchstate, {saveoffset, _N}}) -> + ?MS_SAVEOFFSET_SIZE; +get_field_size1({sub_binary, thing_word}) -> + ?SUB_BIN_THING_WORD_SIZE; +get_field_size1({sub_binary, binsize}) -> + ?SUB_BIN_BINSIZE_SIZE; +get_field_size1({sub_binary, bitsize}) -> + ?SUB_BIN_BITSIZE_SIZE; +get_field_size1({sub_binary, offset}) -> + ?SUB_BIN_OFFS_SIZE; +get_field_size1({sub_binary, bitoffset}) -> + ?SUB_BIN_BITOFFS_SIZE; +get_field_size1({sub_binary, is_writable}) -> + ?SUB_BIN_WRITABLE_SIZE; +get_field_size1({sub_binary, orig}) -> + ?SUB_BIN_ORIG_SIZE; +get_field_size1({proc_bin, thing_word}) -> + ?PROC_BIN_THING_WORD_SIZE; +get_field_size1({proc_bin, binsize}) -> + ?PROC_BIN_BINSIZE_SIZE; +get_field_size1({proc_bin, next}) -> + ?PROC_BIN_NEXT_SIZE; +get_field_size1({proc_bin, val}) -> + ?PROC_BIN_VAL_SIZE; +get_field_size1({proc_bin, bytes}) -> + ?PROC_BIN_BYTES_SIZE; +get_field_size1({proc_bin, flags}) -> + ?PROC_BIN_FLAGS_SIZE; +get_field_size1({binary, orig_bytes}) -> + ?BINARY_ORIG_BYTES_SIZE; +get_field_size1({binary, orig_size}) -> + ?BINARY_ORIG_SIZE_SIZE; +get_field_size1({heap_bin, thing_word}) -> + ?HEAP_BIN_THING_WORD_SIZE; +get_field_size1({heap_bin, binsize}) -> + ?HEAP_BIN_SIZE_SIZE; +get_field_size1({heap_bin, {data, _}}) -> + ?HEAP_BIN_DATA_SIZE; +get_field_size1({matchbuffer, offset}) -> + ?MB_OFFSET_SIZE; +get_field_size1({matchbuffer, orig}) -> + ?MB_ORIG_SIZE; +get_field_size1({matchbuffer, base}) -> + ?MB_BASE_SIZE; +get_field_size1({matchbuffer, binsize}) -> + ?MB_SIZE_SIZE. + +get_field_from_term(Struct, Term, Dst) -> + Offset = hipe_rtl:mk_imm(get_field_offset(Struct) - ?TAG_PRIMARY_BOXED), + Size = get_field_size(Struct), + hipe_rtl:mk_load(Dst, Term, Offset, Size, unsigned). + +set_field_from_term(Struct, Term, Value) -> + Offset = hipe_rtl:mk_imm(get_field_offset(Struct) - ?TAG_PRIMARY_BOXED), + Size = get_field_size(Struct), + hipe_rtl:mk_store(Term, Offset, Value, Size). + +get_field_from_pointer(Struct, Term, Dst) -> + Offset = hipe_rtl:mk_imm(get_field_offset(Struct)), + Size = get_field_size(Struct), + hipe_rtl:mk_load(Dst, Term, Offset, Size, unsigned). + +set_field_from_pointer(Struct, Term, Value) -> + Offset = hipe_rtl:mk_imm(get_field_offset(Struct)), + Size = get_field_size(Struct), + hipe_rtl:mk_store(Term, Offset, Value, Size). + +extract_matchbuffer(Mb, Ms) -> + What = {matchstate, matchbuffer}, + Offset = hipe_rtl:mk_imm(get_field_offset(What) - ?TAG_PRIMARY_BOXED), + hipe_rtl:mk_alu(Mb, Ms, add, Offset). + +extract_binary_bytes(Binary, Base) -> + Offset = hipe_rtl:mk_imm(get_field_offset({binary, orig_bytes})), + hipe_rtl:mk_alu(Base, Binary, add, Offset). -- cgit v1.2.3