1%%% -*- erlang-indent-level: 2 -*- 2%%% 3%%% Licensed under the Apache License, Version 2.0 (the "License"); 4%%% you may not use this file except in compliance with the License. 5%%% You may obtain a copy of the License at 6%%% 7%%% http://www.apache.org/licenses/LICENSE-2.0 8%%% 9%%% Unless required by applicable law or agreed to in writing, software 10%%% distributed under the License is distributed on an "AS IS" BASIS, 11%%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12%%% See the License for the specific language governing permissions and 13%%% limitations under the License. 14%%% 15%%%------------------------------------------------------------------- 16%%% File : hipe_rtl_binary_match.erl 17%%% Author : Per Gustafsson <pergu@it.uu.se> 18%%% Description : 19%%% 20%%% Created : 5 Mar 2007 by Per Gustafsson <pergu@it.uu.se> 21%%%------------------------------------------------------------------- 22-module(hipe_rtl_binary_match). 23 24-export([gen_rtl/5]). 25 26-import(hipe_tagscheme, [set_field_from_term/3, get_field_from_term/3]). 27 28-import(hipe_rtl_binary, [make_size/3]). 29 30-include("hipe_literals.hrl"). 31 32%%-------------------------------------------------------------------- 33 34-define(BYTE_SHIFT, 3). %% Turn bits into bytes or vice versa 35-define(LOW_BITS, 7). %% Three lowest bits set 36-define(BYTE_SIZE, 8). 37-define(MAX_SMALL_BITS, (hipe_rtl_arch:word_size() * ?BYTE_SIZE - 5)). 38 39%%-------------------------------------------------------------------- 40 41%% ----- bs_start_match ----- 42gen_rtl({bs_start_match, 0}, [Ms], [Binary], TrueLblName, FalseLblName) -> 43 ReInitLbl = hipe_rtl:mk_new_label(), 44 BinaryLbl = hipe_rtl:mk_new_label(), 45 TestCode = 46 [hipe_rtl:mk_move(Ms,Binary), 47 hipe_tagscheme:test_matchstate(Binary, 48 hipe_rtl:label_name(ReInitLbl), 49 hipe_rtl:label_name(BinaryLbl), 50 0.99)], 51 ReInitCode = reinit_matchstate(Ms, TrueLblName), 52 OrdinaryCode = make_matchstate(Binary, 0, Ms, TrueLblName, FalseLblName), 53 [TestCode,[ReInitLbl|ReInitCode],[BinaryLbl|OrdinaryCode]]; 54gen_rtl({bs_start_match, Max}, [Ms], [Binary], TrueLblName, FalseLblName) -> 55 MatchStateLbl = hipe_rtl:mk_new_label(), 56 BinaryLbl = hipe_rtl:mk_new_label(), 57 ReSizeLbl = hipe_rtl:mk_new_label(), 58 ReInitLbl = hipe_rtl:mk_new_label(), 59 TestCode = 60 [hipe_rtl:mk_move(Ms,Binary), 61 hipe_tagscheme:test_matchstate(Binary, 62 hipe_rtl:label_name(MatchStateLbl), 63 hipe_rtl:label_name(BinaryLbl), 64 0.99)], 65 MatchStateTestCode = 66 [hipe_tagscheme:compare_matchstate(Max, Ms, 67 hipe_rtl:label_name(ReInitLbl), 68 hipe_rtl:label_name(ReSizeLbl))], 69 ReSizeCode = resize_matchstate(Ms, Max, TrueLblName), 70 ReInitCode = reinit_matchstate(Ms, TrueLblName), 71 OrdinaryCode = make_matchstate(Binary, Max, Ms, TrueLblName, FalseLblName), 72 [TestCode, [MatchStateLbl|MatchStateTestCode], [ReSizeLbl|ReSizeCode], 73 [ReInitLbl|ReInitCode], [BinaryLbl|OrdinaryCode]]; 74gen_rtl({bs_start_match, _Max}, [], [Binary], TrueLblName, FalseLblName) -> 75 MatchStateLbl = hipe_rtl:mk_new_label(), 76 [hipe_tagscheme:test_bitstr(Binary, TrueLblName, 77 hipe_rtl:label_name(MatchStateLbl), 0.99), 78 MatchStateLbl, 79 hipe_tagscheme:test_matchstate(Binary, TrueLblName, FalseLblName, 0.99)]; 80gen_rtl({{bs_start_match, bitstr}, Max}, [Ms], [Binary], 81 TrueLblName, FalseLblName) -> 82 make_matchstate(Binary, Max, Ms, TrueLblName, FalseLblName); 83gen_rtl({{bs_start_match, bitstr}, _Max}, [], [_Binary], 84 TrueLblName, _FalseLblName) -> 85 [hipe_rtl:mk_goto(TrueLblName)]; 86gen_rtl({{bs_start_match, ok_matchstate}, Max}, [Ms], [Binary], 87 TrueLblName, FalseLblName) -> 88 MatchStateLbl = hipe_rtl:mk_new_label(), 89 BinaryLbl = hipe_rtl:mk_new_label(), 90 TestCode = 91 [hipe_rtl:mk_move(Ms,Binary), 92 hipe_tagscheme:test_matchstate(Binary, 93 hipe_rtl:label_name(MatchStateLbl), 94 hipe_rtl:label_name(BinaryLbl), 95 0.99)], 96 MatchStateCode = reinit_matchstate(Ms, TrueLblName), 97 OrdinaryCode = make_matchstate(Binary, Max, Ms, TrueLblName, FalseLblName), 98 TestCode ++ [MatchStateLbl|MatchStateCode] ++ [BinaryLbl|OrdinaryCode]; 99gen_rtl({{bs_start_match, ok_matchstate}, _Max}, [], [Binary], 100 TrueLblName, FalseLblName) -> 101 MatchStateLbl = hipe_rtl:mk_new_label(), 102 [hipe_tagscheme:test_bitstr(Binary, TrueLblName, 103 hipe_rtl:label_name(MatchStateLbl), 0.99), 104 MatchStateLbl, 105 hipe_tagscheme:test_matchstate(Binary, TrueLblName, FalseLblName, 0.99)]; 106%% ----- bs_get_integer ----- 107gen_rtl({bs_get_integer, 0, _Flags}, [Dst, NewMs], [Ms], 108 TrueLblName, _FalseLblName) -> 109 update_ms(NewMs, Ms) ++ 110 [hipe_rtl:mk_move(Dst, hipe_rtl:mk_imm(15)), 111 hipe_rtl:mk_goto(TrueLblName)]; 112gen_rtl({bs_get_integer, Size, Flags}, [Dst, NewMs], Args, 113 TrueLblName, FalseLblName) -> 114 case is_illegal_const(Size) of 115 true -> 116 [hipe_rtl:mk_goto(FalseLblName)]; 117 false -> 118 Signed = signed(Flags), 119 LittleEndian = littleendian(Flags), 120 Aligned = aligned(Flags), 121 UnSafe = unsafe(Flags), 122 case Args of 123 [Ms] -> 124 CCode = int_get_c_code(Dst, Ms, hipe_rtl:mk_imm(Size), 125 Flags, TrueLblName, FalseLblName), 126 update_ms(NewMs, Ms) ++ 127 get_static_int(Dst, Ms, Size, CCode, 128 Signed, LittleEndian, Aligned, UnSafe, 129 TrueLblName, FalseLblName); 130 [Ms, Arg] -> 131 {SizeCode1, SizeReg1} = make_size(Size, Arg, FalseLblName), 132 CCode = int_get_c_code(Dst, Ms, SizeReg1, Flags, 133 TrueLblName, FalseLblName), 134 InCode = get_dynamic_int(Dst, Ms, SizeReg1, CCode, 135 Signed, LittleEndian, Aligned, 136 TrueLblName, FalseLblName), 137 update_ms(NewMs, Ms) ++ SizeCode1 ++ InCode 138 end 139 end; 140%% ----- bs_get_float ----- 141gen_rtl({bs_get_float,Size,Flags}, [Dst1, NewMs], Args, 142 TrueLblName, FalseLblName) -> 143 case is_illegal_const(Size) of 144 true -> 145 [hipe_rtl:mk_goto(FalseLblName)]; 146 false -> 147 [hipe_rtl:mk_gctest(3)] ++ 148 case Args of 149 [Ms] -> 150 CCode = float_get_c_code(Dst1, Ms, hipe_rtl:mk_imm(Size), Flags, 151 TrueLblName, FalseLblName), 152 update_ms(NewMs, Ms) ++ CCode; 153 [Ms, Arg] -> 154 {SizeCode, SizeReg} = make_size(Size, Arg, FalseLblName), 155 CCode = float_get_c_code(Dst1, Ms, SizeReg, Flags, 156 TrueLblName, FalseLblName), 157 update_ms(NewMs, Ms) ++ SizeCode ++ CCode 158 end 159 end; 160%% ----- bs_get_binary_all ----- 161gen_rtl({bs_get_binary_all, Unit, _Flags}, [Dst], [Ms], 162 TrueLblName, FalseLblName) -> 163 [hipe_rtl:mk_gctest(?SUB_BIN_WORDSIZE)] ++ 164 get_binary_all(Dst, Unit, Ms, TrueLblName,FalseLblName); 165%% ----- bs_get_binary_all_2 ----- 166gen_rtl({bs_get_binary_all_2, Unit, _Flags}, [Dst, NewMs], [Ms], 167 TrueLblName, FalseLblName) -> 168 [hipe_rtl:mk_gctest(?SUB_BIN_WORDSIZE)] ++ 169 update_ms(NewMs, Ms) ++ 170 get_binary_all(Dst, Unit, Ms, TrueLblName, FalseLblName); 171%% ----- bs_get_binary ----- 172gen_rtl({bs_get_binary, Size, Flags}, [Dst, NewMs], Args, 173 TrueLblName, FalseLblName) -> 174 case is_illegal_const(Size) of 175 true -> 176 [hipe_rtl:mk_goto(FalseLblName)]; 177 false -> 178 Unsafe = unsafe(Flags), 179 {OldMs, SizeReg, SizeCode} = 180 case Args of 181 [Ms] -> 182 SzReg = hipe_rtl:mk_new_reg(), 183 SzCode = [hipe_rtl:mk_move(SzReg, hipe_rtl:mk_imm(Size))], 184 {Ms, SzReg, SzCode}; 185 [Ms, BitsVar] -> 186 {SzCode, SzReg} = make_size(Size, BitsVar, FalseLblName), 187 {Ms, SzReg, SzCode} 188 end, 189 InCode = get_binary(Dst, OldMs, SizeReg, Unsafe, 190 TrueLblName, FalseLblName), 191 [hipe_rtl:mk_gctest(?SUB_BIN_WORDSIZE)] ++ 192 update_ms(NewMs, OldMs) ++ SizeCode ++ InCode 193 end; 194%% ----- bs_get_utf8 ----- 195gen_rtl(bs_get_utf8, [Dst, NewMs], [Ms], TrueLblName, FalseLblName) -> 196 update_ms(NewMs, Ms) ++ utf8_get_c_code(Dst, Ms, TrueLblName, FalseLblName); 197%% ----- bs_get_utf16 ----- 198gen_rtl({bs_get_utf16, Flags}, [Dst, NewMs], [Ms], TrueLblName, FalseLblName) -> 199 update_ms(NewMs, Ms) ++ 200 utf16_get_c_code(Flags, Dst, Ms, TrueLblName, FalseLblName); 201%% ----- bs_validate_unicode_retract ----- 202gen_rtl(bs_validate_unicode_retract, [NewMs], [Src, Ms], 203 TrueLblName, FalseLblName) -> 204 update_ms(NewMs, Ms) ++ 205 validate_unicode_retract_c_code(Src, Ms, TrueLblName, FalseLblName); 206%% ----- bs_test_tail ----- 207gen_rtl({bs_test_tail, NumBits}, [NewMs], [Ms], TrueLblName, FalseLblName) -> 208 {[Offset,BinSize], ExCode} = extract_matchstate_vars([offset,binsize], Ms), 209 update_ms(NewMs, Ms) ++ ExCode ++ 210 [add_to_offset(Offset, Offset, hipe_rtl:mk_imm(NumBits), FalseLblName), 211 hipe_rtl:mk_branch(Offset, eq, BinSize, TrueLblName, FalseLblName)]; 212%% ----- bs_test_unit ----- 213gen_rtl({bs_test_unit, Unit}, [], [Ms], TrueLblName, FalseLblName) -> 214 {[Offset, BinSize], ExCode} = extract_matchstate_vars([offset, binsize], Ms), 215 SizeReg = hipe_rtl:mk_new_reg(), 216 ExCode ++ 217 [hipe_rtl:mk_alu(SizeReg, BinSize, sub, Offset)| 218 test_alignment_code(SizeReg, Unit, TrueLblName, FalseLblName)]; 219gen_rtl({bs_test_tail, NumBits}, [], [Ms], TrueLblName, FalseLblName) -> 220 {[Offset, BinSize], ExCode} = extract_matchstate_vars([offset, binsize], Ms), 221 ExCode ++ 222 [add_to_offset(Offset, Offset, hipe_rtl:mk_imm(NumBits), FalseLblName), 223 hipe_rtl:mk_branch(Offset, eq, BinSize, TrueLblName, FalseLblName)]; 224%% ----- bs_skip_bits_all ----- 225gen_rtl({bs_skip_bits_all, Unit, _Flags}, Dst, [Ms], 226 TrueLblName, FalseLblName) -> 227 opt_update_ms(Dst, Ms) ++ 228 skip_bits_all(Unit, Ms, TrueLblName, FalseLblName); 229%% ----- bs_skip_bits ----- 230gen_rtl({bs_skip_bits, Bits}, Dst, [Ms|Args], TrueLblName, FalseLblName) -> 231 MaxValue = (1 bsl (hipe_rtl_arch:word_size() * ?BYTE_SIZE)), 232 opt_update_ms(Dst, Ms) ++ 233 case Bits < MaxValue of 234 true -> 235 case Args of 236 [] -> 237 skip_bits2(Ms, hipe_rtl:mk_imm(Bits), TrueLblName, FalseLblName); 238 [Arg] -> 239 {SizeCode, SizeReg} = make_size(Bits, Arg, FalseLblName), 240 InCode = skip_bits2(Ms, SizeReg, TrueLblName, FalseLblName), 241 SizeCode ++ InCode 242 end; 243 false -> % handle overflow case 244 case Args of 245 [] -> 246 [hipe_rtl:mk_goto(FalseLblName)]; 247 [Arg] -> 248 [hipe_rtl:mk_branch(Arg, 'eq', hipe_tagscheme:mk_fixnum(0), 249 TrueLblName, FalseLblName, 0.5)] 250 end 251 end; 252%% ----- bs_restore ----- 253gen_rtl({bs_restore, Slot}, [NewMs], [Ms], TrueLblName, _FalseLblName) -> 254 Tmp1 = hipe_rtl:mk_new_reg_gcsafe(), 255 update_ms(NewMs, Ms) ++ 256 [get_field_from_term({matchstate, {saveoffset, Slot}}, Ms, Tmp1), 257 set_field_from_term({matchstate, {matchbuffer, offset}}, Ms, Tmp1), 258 hipe_rtl:mk_goto(TrueLblName)]; 259%% ----- bs_save ----- 260gen_rtl({bs_save, Slot}, [NewMs], [Ms], TrueLblName, _FalseLblName) -> 261 {Offset, Instr} = extract_matchstate_var(offset, Ms), 262 update_ms(NewMs, Ms) ++ 263 [Instr, 264 set_field_from_term({matchstate, {saveoffset, Slot}}, Ms, Offset), 265 hipe_rtl:mk_goto(TrueLblName)]; 266%% ----- bs_match_string ----- 267gen_rtl({bs_match_string, String, BitSize}, Dst, [Ms], 268 TrueLblName, FalseLblName) -> 269 {[Offset, BinSize, Base], Instrs} = 270 extract_matchstate_vars([offset, binsize, base], Ms), 271 [SuccessLbl, ALbl, ULbl] = create_lbls(3), 272 [NewOffset, BitOffset] = create_gcsafe_regs(2), 273 Unit = (hipe_rtl_arch:word_size() - 1) * ?BYTE_SIZE, 274 Init = 275 [Instrs, 276 opt_update_ms(Dst, Ms), 277 check_size(Offset, hipe_rtl:mk_imm(BitSize), BinSize, 278 NewOffset, hipe_rtl:label_name(SuccessLbl), FalseLblName), 279 SuccessLbl], 280 SplitCode = 281 [hipe_rtl:mk_alub(BitOffset, Offset, 'and', hipe_rtl:mk_imm(?LOW_BITS), eq, 282 hipe_rtl:label_name(ALbl), hipe_rtl:label_name(ULbl))], 283 Loops = BitSize div Unit, 284 SkipSize = Loops * Unit, 285 {ACode1, UCode1} = 286 case Loops of 287 0 -> 288 {[], []}; 289 _ -> 290 create_loops(Loops, Unit, String, Base, 291 Offset, BitOffset, FalseLblName) 292 end, 293 <<_:SkipSize/bits, RestString/bits>> = String, 294 {ACode2, UCode2} = 295 case BitSize rem Unit of 296 0 -> 297 {[], []}; 298 Rem -> 299 create_rests(Rem, RestString, Base, Offset, BitOffset, FalseLblName) 300 end, 301 GoTo = hipe_rtl:mk_goto(TrueLblName), 302 End = case Dst of 303 [] -> [GoTo]; 304 [NewMs] -> [update_offset(NewOffset, NewMs), GoTo] 305 end, 306 [Init, SplitCode, ALbl, ACode1, ACode2, End, ULbl, UCode1, UCode2, End]; 307%% ----- bs_context_to_binary ----- 308gen_rtl(bs_context_to_binary, [Bin], [Var], TrueLblName, _FalseLblName) -> 309 MSLabel = hipe_rtl:mk_new_label(), 310 [hipe_rtl:mk_move(Bin, Var), 311 hipe_tagscheme:test_matchstate(Var, hipe_rtl:label_name(MSLabel), 312 TrueLblName, 0.5), 313 MSLabel, 314 hipe_tagscheme:convert_matchstate(Bin), 315 hipe_rtl:mk_goto(TrueLblName)]. 316 317%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Calls to C %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 318 319int_get_c_code(Dst1, Ms, Size, Flags, TrueLblName, FalseLblName) -> 320 make_int_gc_code(Size) ++ 321 get_c_code(bs_get_integer_2, Dst1, Ms, Size, Flags, 322 TrueLblName, FalseLblName). 323 324float_get_c_code(Dst1, Ms, Size, Flags, TrueLblName, FalseLblName) -> 325 get_c_code(bs_get_float_2, Dst1, Ms, Size, Flags, TrueLblName, FalseLblName). 326 327get_c_code(Func, Dst1, Ms, Size, Flags, TrueLblName, FalseLblName) -> 328 SizeReg = hipe_rtl:mk_new_reg_gcsafe(), 329 FlagsReg = hipe_rtl:mk_new_reg_gcsafe(), 330 RetReg = hipe_rtl:mk_new_reg_gcsafe(), 331 MatchBuf = hipe_rtl:mk_new_reg(), 332 RetLabel = hipe_rtl:mk_new_label(), 333 OkLabel = hipe_rtl:mk_new_label(), 334 NonVal = hipe_rtl:mk_imm(hipe_tagscheme:mk_non_value()), 335 [hipe_rtl:mk_move(SizeReg, Size), 336 hipe_rtl:mk_move(FlagsReg, hipe_rtl:mk_imm(Flags)), 337 hipe_tagscheme:extract_matchbuffer(MatchBuf, Ms), 338 hipe_rtl_arch:call_bif([RetReg], Func, [SizeReg, FlagsReg, MatchBuf], 339 hipe_rtl:label_name(RetLabel), FalseLblName), 340 RetLabel, 341 hipe_rtl:mk_branch(RetReg, eq, NonVal, FalseLblName, 342 hipe_rtl:label_name(OkLabel), 0.01), 343 OkLabel, 344 hipe_rtl:mk_move(Dst1, RetReg), 345 hipe_rtl:mk_goto(TrueLblName)]. 346 347utf8_get_c_code(Dst, Ms, TrueLblName, FalseLblName) -> 348 RetReg = hipe_rtl:mk_new_reg_gcsafe(), 349 OkLabel = hipe_rtl:mk_new_label(), 350 MatchBuf = hipe_rtl:mk_new_reg(), 351 NonVal = hipe_rtl:mk_imm(hipe_tagscheme:mk_non_value()), 352 [hipe_tagscheme:extract_matchbuffer(MatchBuf, Ms), 353 hipe_rtl_arch:call_bif([RetReg], bs_get_utf8, [MatchBuf], [], []), 354 hipe_rtl:mk_branch(RetReg, eq, NonVal, FalseLblName, 355 hipe_rtl:label_name(OkLabel), 0.01), 356 OkLabel, 357 hipe_rtl:mk_move(Dst, RetReg), 358 hipe_rtl:mk_goto(TrueLblName)]. 359 360utf16_get_c_code(Flags, Dst, Ms, TrueLblName, FalseLblName) -> 361 RetReg = hipe_rtl:mk_new_reg_gcsafe(), 362 OkLabel = hipe_rtl:mk_new_label(), 363 MatchBuf = hipe_rtl:mk_new_reg(), 364 NonVal = hipe_rtl:mk_imm(hipe_tagscheme:mk_non_value()), 365 FlagsReg = hipe_rtl:mk_new_reg_gcsafe(), 366 [hipe_tagscheme:extract_matchbuffer(MatchBuf, Ms), 367 hipe_rtl:mk_move(FlagsReg, hipe_rtl:mk_imm(Flags)), 368 hipe_rtl_arch:call_bif([RetReg], bs_get_utf16, [MatchBuf, FlagsReg], [], []), 369 hipe_rtl:mk_branch(RetReg, eq, NonVal, FalseLblName, 370 hipe_rtl:label_name(OkLabel), 0.01), 371 OkLabel, 372 hipe_rtl:mk_move(Dst, RetReg), 373 hipe_rtl:mk_goto(TrueLblName)]. 374 375validate_unicode_retract_c_code(Src, Ms, TrueLblName, FalseLblName) -> 376 MatchBuf = hipe_rtl:mk_new_reg(), 377 Zero = hipe_rtl:mk_imm(0), 378 Tmp = hipe_rtl:mk_new_reg(), 379 [hipe_tagscheme:extract_matchbuffer(MatchBuf, Ms), 380 hipe_rtl_arch:call_bif([Tmp], bs_validate_unicode_retract, 381 [MatchBuf, Src], [], []), 382 hipe_rtl:mk_branch(Tmp, eq, Zero, FalseLblName, TrueLblName, 0.01)]. 383 384%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Int Code %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 385 386create_loops(Loops, Unit, String, Base, Offset, BitOffset, FalseLblName) -> 387 [Reg] = create_gcsafe_regs(1), 388 AlignedFun = fun(Value) -> 389 [get_int_to_reg(Reg, Unit, Base, Offset, 'srl', 390 {unsigned, big}), 391 update_and_test(Reg, Unit, Offset, Value, FalseLblName)] 392 end, 393 UnAlignedFun = fun(Value) -> 394 [get_unaligned_int_to_reg(Reg, Unit, 395 Base, Offset, BitOffset, 396 'srl', {unsigned, big})| 397 update_and_test(Reg, Unit, Offset, Value, FalseLblName)] 398 end, 399 {create_loops(Loops, Unit, String, AlignedFun), 400 create_loops(Loops, Unit, String, UnAlignedFun)}. 401 402create_rests(RemBits, String, Base, Offset, BitOffset, FalseLblName) -> 403 [Reg] = create_gcsafe_regs(1), 404 AlignedFun = fun(Value) -> 405 [get_int_to_reg(Reg, RemBits, Base, Offset, 'srl', 406 {unsigned, big})| 407 just_test(Reg, Value, FalseLblName)] 408 end, 409 UnAlignedFun = fun(Value) -> 410 [get_unaligned_int_to_reg(Reg, RemBits, 411 Base, Offset, BitOffset, 412 'srl', {unsigned, big})| 413 just_test(Reg, Value, FalseLblName)] 414 end, 415 {create_loops(1, RemBits, String, AlignedFun), 416 create_loops(1, RemBits, String, UnAlignedFun)}. 417 418create_loops(0, _Unit, _String, _IntFun) -> 419 []; 420create_loops(N, Unit, String, IntFun) -> 421 {Value, RestString} = get_value(Unit, String), 422 [IntFun(Value), 423 create_loops(N-1, Unit, RestString, IntFun)]. 424 425update_and_test(Reg, Unit, Offset, Value, FalseLblName) -> 426 [add_to_offset(Offset, Offset, hipe_rtl:mk_imm(Unit), FalseLblName), 427 just_test(Reg, Value, FalseLblName)]. 428 429just_test(Reg, Value, FalseLblName) -> 430 [ContLbl] = create_lbls(1), 431 [hipe_rtl:mk_branch(Reg, eq, hipe_rtl:mk_imm(Value), 432 hipe_rtl:label_name(ContLbl), FalseLblName), 433 ContLbl]. 434 435get_value(N, String) -> 436 <<I:N, Rest/bits>> = String, 437 {I, Rest}. 438 439make_int_gc_code(I) when is_integer(I) -> 440 case hipe_tagscheme:bignum_sizeneed(I) of 441 0 -> []; 442 X when is_integer(X) -> [hipe_rtl:mk_gctest(X)] 443 end; 444make_int_gc_code(SReg) -> 445 FixNumLbl = hipe_rtl:mk_new_label(), 446 FixNumLblName = hipe_rtl:label_name(FixNumLbl), 447 {ResReg,Code} = hipe_tagscheme:bignum_sizeneed_code(SReg, FixNumLblName), 448 Code ++ 449 [hipe_rtl:mk_gctest(ResReg), 450 hipe_rtl:mk_goto(FixNumLblName), 451 FixNumLbl]. 452 453get_static_int(Dst1, Ms, Size, CCode, Signed, LittleEndian, Aligned, 454 Unsafe, TrueLblName, FalseLblName) -> 455 WordSize = hipe_rtl_arch:word_size(), 456 case Size =< WordSize*?BYTE_SIZE of 457 true -> 458 case {Aligned, LittleEndian} of 459 {true, false} -> 460 get_int_from_bin(Ms, Size, Dst1,Signed, LittleEndian, 461 Unsafe, FalseLblName, TrueLblName); 462 {true, true} -> 463 case Size rem ?BYTE_SIZE of 464 0 -> 465 get_int_from_bin(Ms, Size, Dst1, Signed, LittleEndian, 466 Unsafe, FalseLblName, TrueLblName); 467 _ -> 468 CCode 469 end; 470 {false, false} -> 471 get_int_from_unaligned_bin(Ms, Size, Dst1, Signed, 472 Unsafe, FalseLblName, TrueLblName); 473 {false, true} -> 474 CCode 475 end; 476 false -> 477 CCode 478 end. 479 480get_dynamic_int(Dst1, Ms, SizeReg, CCode, Signed, LittleEndian, true, 481 TrueLblName, FalseLblName) -> 482 {Init, End} = make_dyn_prep(SizeReg, CCode), 483 Init ++ 484 get_unknown_size_int(SizeReg, Ms, Dst1, Signed, LittleEndian, 485 FalseLblName, TrueLblName) ++ 486 End; 487get_dynamic_int(_Dst1, _Ms, _SizeReg, CCode, _Signed, _LittleEndian, false, 488 _TrueLblName, _FalseLblName) -> 489 CCode. 490 491get_int_from_bin(Ms, Size, Dst1, Signed, LittleEndian, 492 Unsafe, FalseLblName, TrueLblName) -> 493 Shiftr = shift_type(Signed), 494 Type = get_type(Signed, LittleEndian), 495 NewOffset = hipe_rtl:mk_new_reg_gcsafe(), 496 [SuccessLbl] = create_lbls(1), 497 {[Base,Offset,BinSize], ExCode} = 498 extract_matchstate_vars([base,offset,binsize], Ms), 499 ExCode ++ 500 [check_size(Offset, hipe_rtl:mk_imm(Size), BinSize, NewOffset, 501 Unsafe, hipe_rtl:label_name(SuccessLbl), FalseLblName), 502 SuccessLbl] ++ 503 [update_offset(NewOffset, Ms)] ++ 504 get_int(Dst1, Size, Base, Offset, Shiftr, Type, TrueLblName). 505 506get_int_from_unaligned_bin(Ms, Size, Dst1, Signed, 507 UnSafe, FalseLblName, TrueLblName) -> 508 Shiftr = shift_type(Signed), 509 Type = get_type(Signed, false), 510 NewOffset = hipe_rtl:mk_new_reg_gcsafe(), 511 [SuccessLbl] = create_lbls(1), 512 {[Base,Offset,BinSize], ExCode} = 513 extract_matchstate_vars([base,offset,binsize], Ms), 514 ExCode ++ 515 [check_size(Offset, hipe_rtl:mk_imm(Size), BinSize, NewOffset, 516 UnSafe, hipe_rtl:label_name(SuccessLbl), FalseLblName), 517 SuccessLbl] ++ 518 [update_offset(NewOffset, Ms)] ++ 519 get_unaligned_int(Dst1, Size, Base, Offset, Shiftr, Type, TrueLblName). 520 521get_unknown_size_int(SizeReg, Ms, Dst1, Signed, Little, 522 FalseLblName, TrueLblName) -> 523 Shiftr = shift_type(Signed), 524 Type = get_type(Signed, false), 525 [NewOffset] = create_gcsafe_regs(1), 526 [SuccessLbl] = create_lbls(1), 527 {[Base,Offset,BinSize], ExCode} = 528 extract_matchstate_vars([base,offset,binsize], Ms), 529 ExCode ++ 530 [check_size(Offset, SizeReg, BinSize, NewOffset, 531 hipe_rtl:label_name(SuccessLbl), FalseLblName), 532 SuccessLbl, 533 update_offset(NewOffset, Ms)] ++ 534 case Little of 535 true -> 536 get_little_unknown_int(Dst1, Base, Offset, NewOffset, 537 Shiftr, Type, TrueLblName); 538 false -> 539 get_big_unknown_int(Dst1, Base, Offset, NewOffset, 540 Shiftr, Type, TrueLblName) 541 end. 542 543make_matchstate(Binary, Max, Ms, TrueLblName, FalseLblName) -> 544 Base = hipe_rtl:mk_new_reg(), 545 Orig = hipe_rtl:mk_new_var(), 546 BinSize = hipe_rtl:mk_new_reg_gcsafe(), 547 Offset = hipe_rtl:mk_new_reg_gcsafe(), 548 Lbl = hipe_rtl:mk_new_label(), 549 [hipe_rtl:mk_gctest(?MS_MIN_SIZE+Max), 550 get_binary_bytes(Binary, BinSize, Base, Offset, 551 Orig, hipe_rtl:label_name(Lbl), FalseLblName), 552 Lbl, 553 hipe_tagscheme:create_matchstate(Max, BinSize, Base, Offset, Orig, Ms), 554 hipe_rtl:mk_goto(TrueLblName)]. 555 556resize_matchstate(Ms, Max, TrueLblName) -> 557 Base = hipe_rtl:mk_new_reg(), 558 Orig = hipe_rtl:mk_new_var(), 559 BinSize = hipe_rtl:mk_new_reg_gcsafe(), 560 Offset = hipe_rtl:mk_new_reg_gcsafe(), 561 [hipe_rtl:mk_gctest(?MS_MIN_SIZE+Max), 562 get_field_from_term({matchstate, {matchbuffer, binsize}}, Ms, BinSize), 563 get_field_from_term({matchstate, {matchbuffer, base}}, Ms, Base), 564 get_field_from_term({matchstate, {matchbuffer, orig}}, Ms, Orig), 565 get_field_from_term({matchstate, {matchbuffer, offset}}, Ms, Offset), 566 hipe_tagscheme:create_matchstate(Max, BinSize, Base, Offset, Orig, Ms), 567 hipe_rtl:mk_goto(TrueLblName)]. 568 569reinit_matchstate(Ms, TrueLblName) -> 570 Tmp = hipe_rtl:mk_new_reg_gcsafe(), 571 [get_field_from_term({matchstate, {matchbuffer, offset}}, Ms, Tmp), 572 set_field_from_term({matchstate, {saveoffset, 0}}, Ms, Tmp), 573 hipe_rtl:mk_goto(TrueLblName)]. 574 575%%%%%%%%%%%%%%%%%%%%%%%%%%%% Binary Code %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 576 577get_binary_all(Dst1, 1, Ms, TrueLblName, _FalseLblName) -> 578 [SizeReg] = create_gcsafe_regs(1), 579 {[Offset,BinSize,Orig], ExCode} = 580 extract_matchstate_vars([offset,binsize,orig], Ms), 581 MakeCode = 582 [hipe_rtl:mk_alu(SizeReg, BinSize, sub, Offset)| 583 construct_subbin(Dst1,SizeReg,Offset,Orig)] ++ 584 [update_offset(BinSize, Ms), 585 hipe_rtl:mk_goto(TrueLblName)], 586 ExCode ++ MakeCode; 587get_binary_all(Dst1, Unit, Ms, TrueLblName, FalseLblName) -> 588 [SizeReg] = create_gcsafe_regs(1), 589 [SuccessLbl] = create_lbls(1), 590 SLblName = hipe_rtl:label_name(SuccessLbl), 591 {[Offset,BinSize,Orig], ExCode} = 592 extract_matchstate_vars([offset,binsize,orig], Ms), 593 MakeCode = 594 [hipe_rtl:mk_alu(SizeReg, BinSize, sub, Offset)| 595 test_alignment_code(SizeReg,Unit,SLblName,FalseLblName)] ++ 596 [SuccessLbl| 597 construct_subbin(Dst1,SizeReg,Offset,Orig)] ++ 598 [update_offset(BinSize, Ms), 599 hipe_rtl:mk_goto(TrueLblName)], 600 ExCode ++ MakeCode. 601 602get_binary(Dst1, Ms, SizeReg, UnSafe, TrueLblName, FalseLblName) -> 603 [SuccessLbl] = create_lbls(1), 604 [EndOffset] = create_gcsafe_regs(1), 605 {[Offset,BinSize,Orig], ExCode} = 606 extract_matchstate_vars([offset,binsize,orig], Ms), 607 CheckCode = 608 [check_size(Offset, SizeReg, BinSize, EndOffset, UnSafe, 609 hipe_rtl:label_name(SuccessLbl), FalseLblName), 610 SuccessLbl], 611 MakeCode = 612 construct_subbin(Dst1, SizeReg, Offset, Orig) 613 ++ [update_offset(EndOffset, Ms), 614 hipe_rtl:mk_goto(TrueLblName)], 615 ExCode ++ CheckCode ++ MakeCode. 616 617construct_subbin(Dst, Size, Offset, Orig) -> 618 [BitOffset, ByteOffset, BitSize, ByteSize] = create_gcsafe_regs(4), 619 [hipe_rtl:mk_alu(ByteSize, Size, srl, hipe_rtl:mk_imm(?BYTE_SHIFT)), 620 hipe_rtl:mk_alu(BitSize, Size, 'and', hipe_rtl:mk_imm(?LOW_BITS)), 621 hipe_rtl:mk_alu(ByteOffset, Offset, srl, hipe_rtl:mk_imm(?BYTE_SHIFT)), 622 hipe_rtl:mk_alu(BitOffset, Offset, 'and', hipe_rtl:mk_imm(?LOW_BITS)), 623 hipe_tagscheme:mk_sub_binary(Dst, ByteSize, ByteOffset, 624 BitSize, BitOffset, Orig)]. 625 626%%%%%%%%%%%%%%%%%%%%%%%%% Skip Bits %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 627 628skip_bits_all(1, Ms, TrueLblName, _FalseLblName) -> 629 {[BinSize], ExCode} = extract_matchstate_vars([binsize], Ms), 630 ExCode ++ [update_offset(BinSize,Ms), hipe_rtl:mk_goto(TrueLblName)]; 631skip_bits_all(Unit,Ms, TrueLblName, FalseLblName) -> 632 [Size] = create_gcsafe_regs(1), 633 [SuccessLbl] = create_lbls(1), 634 SLblName = hipe_rtl:label_name(SuccessLbl), 635 {[Offset,BinSize], ExCode} = extract_matchstate_vars([offset,binsize], Ms), 636 ExCode ++ 637 [hipe_rtl:mk_alu(Size,BinSize,sub,Offset)] 638 ++ 639 test_alignment_code(Size,Unit,SLblName,FalseLblName) ++ 640 [SuccessLbl, 641 update_offset(BinSize,Ms), 642 hipe_rtl:mk_goto(TrueLblName)]. 643 644test_alignment_code(Size, Unit, SLblName, FalseLblName) -> 645 case Unit of 646 1 -> [hipe_rtl:mk_goto(SLblName)]; 647 2 -> get_fast_test_code(Size,1,SLblName,FalseLblName); 648 4 -> get_fast_test_code(Size,3,SLblName,FalseLblName); 649 8 -> get_fast_test_code(Size,7,SLblName,FalseLblName); 650 16 -> get_fast_test_code(Size,15,SLblName,FalseLblName); 651 32 -> get_fast_test_code(Size,31,SLblName,FalseLblName); 652 _ -> get_slow_test_code(Size,Unit,SLblName,FalseLblName) 653 end. 654 655get_fast_test_code(Size, AndTest, SLblName, FalseLblName) -> 656 [hipe_rtl:mk_branch(Size, 'and', hipe_rtl:mk_imm(AndTest), 'eq', 657 SLblName, FalseLblName, 0.5)]. 658 659%% This is really slow 660get_slow_test_code(Size, Unit, SLblName, FalseLblName) -> 661 [Tmp] = create_gcsafe_regs(1), 662 [LoopLbl,Lbl1,Lbl2] = create_lbls(3), 663 LoopLblName = hipe_rtl:label_name(LoopLbl), 664 Lbl1Name = hipe_rtl:label_name(Lbl1), 665 Lbl2Name = hipe_rtl:label_name(Lbl2), 666 [hipe_rtl:mk_move(Tmp,Size), 667 LoopLbl, 668 hipe_rtl:mk_branch(Tmp, eq, hipe_rtl:mk_imm(0), SLblName, Lbl1Name), 669 Lbl1, 670 hipe_rtl:mk_branch(Tmp, lt, hipe_rtl:mk_imm(0), FalseLblName, Lbl2Name), 671 Lbl2, 672 hipe_rtl:mk_alu(Tmp,Tmp,sub,hipe_rtl:mk_imm(Unit)), 673 hipe_rtl:mk_goto(LoopLblName)]. 674 675skip_bits2(Ms, NoOfBits, TrueLblName, FalseLblName) -> 676 [NewOffset] = create_gcsafe_regs(1), 677 [TempLbl] = create_lbls(1), 678 {[Offset,BinSize], ExCode} = extract_matchstate_vars([offset,binsize], Ms), 679 ExCode ++ 680 add_to_offset(NewOffset, NoOfBits, Offset, FalseLblName) ++ 681 [hipe_rtl:mk_branch(BinSize, 'ltu', NewOffset, FalseLblName, 682 hipe_rtl:label_name(TempLbl), 0.01), 683 TempLbl, 684 update_offset(NewOffset, Ms), 685 hipe_rtl:mk_goto(TrueLblName)]. 686 687add_to_offset(Result, Extra, Original, FalseLblName) -> 688 TrueLbl = hipe_rtl:mk_new_label(), 689 %% Note: 'ltu' means 'unsigned overflow'. 690 [hipe_rtl:mk_alub(Result, Extra, 'add', Original, 'ltu', 691 FalseLblName, hipe_rtl:label_name(TrueLbl)), 692 TrueLbl]. 693 694%%%%%%%%%%%%%%%%%%%%%%% Code for start match %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 695 696get_binary_bytes(Binary, BinSize, Base, Offset, Orig, 697 TrueLblName, FalseLblName) -> 698 [OrigOffset,BitSize,BitOffset] = create_gcsafe_regs(3), 699 [SuccessLbl,SubLbl,OtherLbl,JoinLbl] = create_lbls(4), 700 [hipe_tagscheme:test_bitstr(Binary, hipe_rtl:label_name(SuccessLbl), 701 FalseLblName, 0.99), 702 SuccessLbl, 703 get_field_from_term({sub_binary, binsize}, Binary, BinSize), 704 hipe_rtl:mk_alu(BinSize, BinSize, sll, hipe_rtl:mk_imm(?BYTE_SHIFT)), 705 hipe_tagscheme:test_subbinary(Binary, hipe_rtl:label_name(SubLbl), 706 hipe_rtl:label_name(OtherLbl)), 707 SubLbl, 708 get_field_from_term({sub_binary, offset}, Binary, OrigOffset), 709 hipe_rtl:mk_alu(Offset, OrigOffset, sll, hipe_rtl:mk_imm(?BYTE_SHIFT)), 710 get_field_from_term({sub_binary, bitoffset}, Binary, BitOffset), 711 hipe_rtl:mk_alu(Offset, Offset, add, BitOffset), 712 get_field_from_term({sub_binary, bitsize}, Binary, BitSize), 713 hipe_rtl:mk_alu(BinSize, BinSize, add, Offset), 714 hipe_rtl:mk_alu(BinSize, BinSize, add, BitSize), 715 get_field_from_term({sub_binary, orig}, Binary, Orig), 716 hipe_rtl:mk_goto(hipe_rtl:label_name(JoinLbl)), 717 OtherLbl, 718 hipe_rtl:mk_move(Offset, hipe_rtl:mk_imm(0)), 719 hipe_rtl:mk_move(Orig, Binary), 720 JoinLbl] ++ 721 get_base(Orig,Base) ++ 722 [hipe_rtl:mk_goto(TrueLblName)]. 723 724%%%%%%%%%%%%%%%%%%%%%%%%% UTILS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 725 726get_base(Orig,Base) -> 727 [HeapLbl,REFCLbl,WritableLbl,NotWritableLbl,EndLbl] = create_lbls(5), 728 Flags = hipe_rtl:mk_new_reg_gcsafe(), 729 730 [hipe_tagscheme:test_heap_binary(Orig, hipe_rtl:label_name(HeapLbl), 731 hipe_rtl:label_name(REFCLbl)), 732 HeapLbl, 733 hipe_tagscheme:get_field_addr_from_term({heap_bin, {data, 0}}, Orig, Base), 734 hipe_rtl:mk_goto(hipe_rtl:label_name(EndLbl)), 735 REFCLbl, 736 get_field_from_term({proc_bin, flags}, Orig, Flags), 737 hipe_rtl:mk_branch(Flags, 'ne', hipe_rtl:mk_imm(0), 738 hipe_rtl:label_name(WritableLbl), 739 hipe_rtl:label_name(NotWritableLbl)), 740 WritableLbl, 741 hipe_rtl:mk_call([], emasculate_binary, [Orig], [], [], 'not_remote'), 742 NotWritableLbl, 743 get_field_from_term({proc_bin, bytes}, Orig, Base), 744 EndLbl]. 745 746extract_matchstate_var(binsize, Ms) -> 747 BinSize = hipe_rtl:mk_new_reg_gcsafe(), 748 {BinSize, 749 get_field_from_term({matchstate, {matchbuffer, binsize}}, Ms, BinSize)}; 750extract_matchstate_var(offset, Ms) -> 751 Offset = hipe_rtl:mk_new_reg_gcsafe(), 752 {Offset, 753 get_field_from_term({matchstate, {matchbuffer, offset}}, Ms, Offset)}; 754extract_matchstate_var(base, Ms) -> 755 Base = hipe_rtl:mk_new_reg(), 756 {Base, 757 get_field_from_term({matchstate, {matchbuffer, base}}, Ms, Base)}; 758extract_matchstate_var(orig, Ms) -> 759 Orig = hipe_rtl:mk_new_var(), 760 {Orig, 761 get_field_from_term({matchstate, {matchbuffer, orig}}, Ms, Orig)}. 762 763extract_matchstate_vars(List, Ms) -> 764 lists:unzip([extract_matchstate_var(Name, Ms) || Name <- List]). 765 766check_size(Offset, Size, BinSize, Tmp1, ContLblName, FalseLblName) -> 767 [add_to_offset(Tmp1, Offset, Size, FalseLblName), 768 hipe_rtl:mk_branch(Tmp1, leu, BinSize, ContLblName, FalseLblName, 0.99)]. 769 770check_size(Offset, Size, _BinSize, Tmp1, true, ContLblName, _FalseLblName) -> 771 [hipe_rtl:mk_alu(Tmp1, Offset, add, Size), 772 hipe_rtl:mk_goto(ContLblName)]; 773check_size(Offset, Size, BinSize, Tmp1, false, ContLblName, FalseLblName) -> 774 check_size(Offset, Size, BinSize, Tmp1, ContLblName, FalseLblName). 775 776shift_type(true) -> 777 sra; 778shift_type(false) -> 779 srl. 780 781get_type(true, LittleEndian) -> 782 {signed, endianess(LittleEndian)}; 783get_type(false, LittleEndian) -> 784 {unsigned, endianess(LittleEndian)}. 785 786endianess(true) -> 787 little; 788endianess(false) -> 789 big. 790 791aligned(Flags) -> 792 case Flags band ?BSF_ALIGNED of 793 1 -> true; 794 0 -> false 795 end. 796 797littleendian(Flags) -> 798 case Flags band 2 of 799 2 -> true; 800 0 -> false 801 end. 802 803signed(Flags) -> 804 case Flags band 4 of 805 4 -> true; 806 0 -> false 807 end. 808 809unsafe(Flags) -> 810 case Flags band 16 of 811 16 -> true; 812 0 -> false 813 end. 814 815update_offset(NewOffset, Ms) -> 816 set_field_from_term({matchstate, {matchbuffer, offset}}, Ms, NewOffset). 817 818opt_update_ms([NewMs], OldMs) -> 819 [hipe_rtl:mk_move(NewMs, OldMs)]; 820opt_update_ms([], _OldMs) -> 821 []. 822 823update_ms(NewMs, OldMs) -> 824 [hipe_rtl:mk_move(NewMs, OldMs)]. 825 826create_lbls(0) -> 827 []; 828create_lbls(X) when X > 0 -> 829 [hipe_rtl:mk_new_label()|create_lbls(X-1)]. 830 831make_dyn_prep(SizeReg, CCode) -> 832 [CLbl, SuccessLbl] = create_lbls(2), 833 Init = [hipe_rtl:mk_branch(SizeReg, leu, hipe_rtl:mk_imm(?MAX_SMALL_BITS), 834 hipe_rtl:label_name(SuccessLbl), 835 hipe_rtl:label_name(CLbl)), 836 SuccessLbl], 837 End = [CLbl|CCode], 838 {Init, End}. 839 840%%------------------------------------------------------------------------ 841%% From hipe_rtl_binutil.erl 842%%------------------------------------------------------------------------ 843 844get_unaligned_int(Dst1, Size, Base, Offset, Shiftr, Type, TrueLblName) -> 845 [Reg] = create_gcsafe_regs(1), 846 [get_maybe_unaligned_int_to_reg(Reg, Size, Base, Offset, Shiftr, Type), 847 do_bignum_code(Size, Type, Reg, Dst1, TrueLblName)]. 848 849get_maybe_unaligned_int_to_reg(Reg, Size, Base, Offset, Shiftr, Type) -> 850 [LowBits] = create_gcsafe_regs(1), 851 [AlignedLbl, UnAlignedLbl, EndLbl] = create_lbls(3), 852 [hipe_rtl:mk_alub(LowBits, Offset, 'and', hipe_rtl:mk_imm(?LOW_BITS), 853 eq, hipe_rtl:label_name(AlignedLbl), 854 hipe_rtl:label_name(UnAlignedLbl)), 855 AlignedLbl, 856 get_int_to_reg(Reg, Size, Base, Offset, Shiftr, Type), 857 hipe_rtl:mk_goto(hipe_rtl:label_name(EndLbl)), 858 UnAlignedLbl, 859 get_unaligned_int_to_reg(Reg, Size, Base, Offset, LowBits, Shiftr, Type), 860 EndLbl]. 861 862get_unaligned_int_to_reg(Reg, Size, Base, Offset, LowBits, Shiftr, Type) -> 863 [ByteOffset, ShiftBits, LoadDst, Tmp, TotBits] = create_gcsafe_regs(5), 864 [MoreLbl, LessLbl, JoinLbl] = create_lbls(3), 865 WordSize = hipe_rtl_arch:word_size(), 866 MinLoad = (Size-1) div ?BYTE_SIZE +1, 867 MaxLoad = MinLoad + 1, 868 Code1 = 869 [hipe_rtl:mk_alu(TotBits, LowBits, 'add', hipe_rtl:mk_imm(Size)), 870 hipe_rtl:mk_alu(ByteOffset, Offset, 'srl', hipe_rtl:mk_imm(?BYTE_SHIFT))], 871 Code2 = 872 case {Size rem ?BYTE_SIZE, MinLoad} of 873 {1, _} -> 874 [load_bytes(LoadDst, Base, ByteOffset, Type, MinLoad), 875 hipe_rtl:mk_alu(ShiftBits, LowBits, 'add', 876 hipe_rtl:mk_imm((WordSize-MinLoad)*?BYTE_SIZE))]; 877 {_, WordSize} -> 878 UnsignedBig = {unsigned, big}, 879 [hipe_rtl:mk_branch(TotBits, leu, hipe_rtl:mk_imm(MinLoad*?BYTE_SIZE), 880 hipe_rtl:label_name(LessLbl), 881 hipe_rtl:label_name(MoreLbl)), 882 LessLbl, 883 load_bytes(LoadDst, Base, ByteOffset, Type, MinLoad), 884 hipe_rtl:mk_alu(ShiftBits, LowBits, 'add', 885 hipe_rtl:mk_imm((WordSize-MinLoad)*?BYTE_SIZE)), 886 hipe_rtl:mk_goto(hipe_rtl:label_name(JoinLbl)), 887 MoreLbl, 888 load_bytes(LoadDst, Base, ByteOffset, UnsignedBig, MinLoad), 889 hipe_rtl:mk_alu(LoadDst, LoadDst, 'sll', LowBits), 890 load_bytes(Tmp, Base, ByteOffset, UnsignedBig, 1), 891 hipe_rtl:mk_alu(LowBits, hipe_rtl:mk_imm(?BYTE_SIZE), 'sub', LowBits), 892 hipe_rtl:mk_alu(Tmp, Tmp, 'srl', LowBits), 893 hipe_rtl:mk_alu(LoadDst, LoadDst, 'or', Tmp), 894 hipe_rtl:mk_move(ShiftBits, hipe_rtl:mk_imm(0)), 895 JoinLbl]; 896 {_, _} -> 897 [load_bytes(LoadDst, Base, ByteOffset, Type, MaxLoad), 898 hipe_rtl:mk_alu(ShiftBits, LowBits, 'add', 899 hipe_rtl:mk_imm((WordSize-MaxLoad)*?BYTE_SIZE))] 900 end, 901 Code3 = 902 [hipe_rtl:mk_alu(Tmp, LoadDst, sll, ShiftBits), 903 hipe_rtl:mk_alu(Reg, Tmp, Shiftr, 904 hipe_rtl:mk_imm(WordSize*?BYTE_SIZE-Size))], 905 Code1 ++ Code2 ++ Code3. 906 907get_int(Dst1, Size, Base, Offset, Shiftr, Type, TrueLblName) -> 908 [Reg] = create_gcsafe_regs(1), 909 [get_int_to_reg(Reg, Size, Base, Offset, Shiftr, Type), 910 do_bignum_code(Size, Type, Reg, Dst1, TrueLblName)]. 911 912get_int_to_reg(Reg, Size, Base, Offset, Shiftr, Type) -> 913 [ByteOffset] = create_gcsafe_regs(1), 914 Code1 = 915 [hipe_rtl:mk_alu(ByteOffset, Offset, srl, hipe_rtl:mk_imm(?BYTE_SHIFT)), 916 load_bytes(Reg, Base, ByteOffset, Type, ((Size-1) div ?BYTE_SIZE +1))], 917 Code2 = 918 case Size rem ?BYTE_SIZE of 919 0 -> 920 []; 921 _ -> 922 [hipe_rtl:mk_alu(Reg, Reg, Shiftr, 923 hipe_rtl:mk_imm(?BYTE_SIZE -Size rem ?BYTE_SIZE))] 924 end, 925 Code1 ++ Code2. 926 927get_big_unknown_int(Dst1, Base, Offset, NewOffset, 928 Shiftr, Type, TrueLblName) -> 929 [LoadDst, ByteOffset, Limit, Tmp, LowBits] = create_gcsafe_regs(5), 930 [ContLbl, BackLbl, LoopLbl, TagLbl, LastLbl, EndLbl] = create_lbls(6), 931 [hipe_rtl:mk_move(LoadDst, hipe_rtl:mk_imm(0)), 932 hipe_rtl:mk_branch(NewOffset, ne, Offset, hipe_rtl:label_name(ContLbl), 933 hipe_rtl:label_name(TagLbl), 0.99), 934 ContLbl, 935 hipe_rtl:mk_alu(Limit, NewOffset, sub, hipe_rtl:mk_imm(1)), 936 hipe_rtl:mk_alu(Limit, Limit, srl, hipe_rtl:mk_imm(?BYTE_SHIFT)), 937 hipe_rtl:mk_alu(ByteOffset, Offset, srl, hipe_rtl:mk_imm(?BYTE_SHIFT)), 938 load_bytes(LoadDst, Base, ByteOffset, Type, 1), 939 BackLbl, 940 hipe_rtl:mk_branch(ByteOffset, leu, Limit, hipe_rtl:label_name(LoopLbl), 941 hipe_rtl:label_name(EndLbl)), 942 LoopLbl, 943 load_bytes(Tmp, Base, ByteOffset, {unsigned, big}, 1), 944 hipe_rtl:mk_alu(LoadDst, LoadDst, sll, hipe_rtl:mk_imm(?BYTE_SIZE)), 945 hipe_rtl:mk_alu(LoadDst, LoadDst, 'or', Tmp), 946 hipe_rtl:mk_goto(hipe_rtl:label_name(BackLbl)), 947 EndLbl, 948 hipe_rtl:mk_alub(LowBits, NewOffset, 'and', hipe_rtl:mk_imm(?LOW_BITS), eq, 949 hipe_rtl:label_name(TagLbl), hipe_rtl:label_name(LastLbl)), 950 LastLbl, 951 hipe_rtl:mk_alu(LowBits, hipe_rtl:mk_imm(?BYTE_SIZE), 'sub', LowBits), 952 hipe_rtl:mk_alu(LoadDst, LoadDst, Shiftr, LowBits), 953 TagLbl] ++ 954 do_bignum_code(64, Type, LoadDst, Dst1, TrueLblName). 955 956get_little_unknown_int(Dst1, Base, Offset, NewOffset, 957 Shiftr, Type, TrueLblName) -> 958 [LoadDst, ByteOffset, Limit, ShiftReg, LowBits, Tmp] = create_gcsafe_regs(6), 959 [ContLbl, BackLbl, LoopLbl, DoneLbl, TagLbl] = create_lbls(5), 960 [hipe_rtl:mk_move(LoadDst, hipe_rtl:mk_imm(0)), 961 hipe_rtl:mk_branch(NewOffset, ne, Offset, hipe_rtl:label_name(ContLbl), 962 hipe_rtl:label_name(TagLbl), 0.99), 963 ContLbl, 964 hipe_rtl:mk_alu(Tmp, NewOffset, sub, hipe_rtl:mk_imm(1)), 965 hipe_rtl:mk_alu(ByteOffset, Offset, srl, hipe_rtl:mk_imm(?BYTE_SHIFT)), 966 hipe_rtl:mk_alu(Limit, Tmp, srl, hipe_rtl:mk_imm(?BYTE_SHIFT)), 967 hipe_rtl:mk_move(ShiftReg, hipe_rtl:mk_imm(0)), 968 BackLbl, 969 hipe_rtl:mk_branch(ByteOffset, ltu, Limit, 970 hipe_rtl:label_name(LoopLbl), 971 hipe_rtl:label_name(DoneLbl)), 972 LoopLbl, 973 load_bytes(Tmp, Base, ByteOffset, {unsigned, big}, 1), 974 hipe_rtl:mk_alu(Tmp, Tmp, sll, ShiftReg), 975 hipe_rtl:mk_alu(ShiftReg, ShiftReg, add, hipe_rtl:mk_imm(?BYTE_SIZE)), 976 hipe_rtl:mk_alu(LoadDst, LoadDst, 'or', Tmp), 977 hipe_rtl:mk_goto(hipe_rtl:label_name(BackLbl)), 978 DoneLbl, 979 hipe_rtl:mk_alu(LowBits, NewOffset, 'and', hipe_rtl:mk_imm(?LOW_BITS)), 980 hipe_rtl:mk_alu(LowBits, hipe_rtl:mk_imm(?BYTE_SIZE), sub, LowBits), 981 hipe_rtl:mk_alu(LowBits, LowBits, 'and', hipe_rtl:mk_imm(?LOW_BITS)), 982 load_bytes(Tmp, Base, ByteOffset, Type, 1), 983 hipe_rtl:mk_alu(Tmp, Tmp, Shiftr, LowBits), 984 hipe_rtl:mk_alu(Tmp, Tmp, sll, ShiftReg), 985 hipe_rtl:mk_alu(LoadDst, LoadDst, 'or', Tmp), 986 TagLbl] ++ 987 do_bignum_code(64, Type, LoadDst, Dst1, TrueLblName). 988 989do_bignum_code(Size, {Signedness,_}, Src, Dst1, TrueLblName) 990 when is_integer(Size) -> 991 case {Size > ?MAX_SMALL_BITS, Signedness} of 992 {false, _} -> 993 [hipe_tagscheme:tag_fixnum(Dst1, Src), 994 hipe_rtl:mk_goto(TrueLblName)]; 995 {true, signed} -> 996 make_int_gc_code(Size) ++ 997 signed_bignum(Dst1, Src, TrueLblName); 998 {true, unsigned} -> 999 make_int_gc_code(Size) ++ 1000 unsigned_bignum(Dst1, Src, TrueLblName) 1001 end. 1002 1003signed_bignum(Dst1, Src, TrueLblName) -> 1004 Tmp1 = hipe_rtl:mk_new_reg_gcsafe(), 1005 BignumLabel = hipe_rtl:mk_new_label(), 1006 [hipe_tagscheme:realtag_fixnum(Dst1, Src), 1007 hipe_tagscheme:realuntag_fixnum(Tmp1, Dst1), 1008 hipe_rtl:mk_branch(Tmp1, eq, Src, TrueLblName, 1009 hipe_rtl:label_name(BignumLabel)), 1010 BignumLabel, 1011 hipe_tagscheme:unsafe_mk_big(Dst1, Src, signed), 1012 hipe_rtl:mk_goto(TrueLblName)]. 1013 1014unsigned_bignum(Dst1, Src, TrueLblName) -> 1015 Tmp1 = hipe_rtl:mk_new_reg_gcsafe(), 1016 BignumLbl = hipe_rtl:mk_new_label(), 1017 BignumLblName = hipe_rtl:label_name(BignumLbl), 1018 NxtLbl = hipe_rtl:mk_new_label(), 1019 NxtLblName = hipe_rtl:label_name(NxtLbl), 1020 [hipe_rtl:mk_branch(Src, lt, hipe_rtl:mk_imm(0), BignumLblName, NxtLblName), 1021 NxtLbl, 1022 hipe_tagscheme:realtag_fixnum(Dst1, Src), 1023 hipe_tagscheme:realuntag_fixnum(Tmp1, Dst1), 1024 hipe_rtl:mk_branch(Tmp1, eq, Src, TrueLblName, BignumLblName), 1025 BignumLbl, 1026 hipe_tagscheme:unsafe_mk_big(Dst1, Src, unsigned), 1027 hipe_rtl:mk_goto(TrueLblName)]. 1028 1029load_bytes(Dst, Base, Offset, {Signedness, _Endianness},1) -> 1030 [hipe_rtl:mk_load(Dst, Base, Offset, byte, Signedness), 1031 hipe_rtl:mk_alu(Offset, Offset, add, hipe_rtl:mk_imm(1))]; 1032load_bytes(Dst, Base, Offset, {Signedness, Endianness},2) -> 1033 case Endianness of 1034 big -> 1035 hipe_rtl_arch:load_big_2(Dst, Base, Offset, Signedness); 1036 little -> 1037 hipe_rtl_arch:load_little_2(Dst, Base, Offset, Signedness) 1038 end; 1039load_bytes(Dst, Base, Offset, {Signedness, Endianness},3) -> 1040 Tmp1 = hipe_rtl:mk_new_reg(), 1041 case Endianness of 1042 big -> 1043 [hipe_rtl:mk_load(Dst, Base, Offset, byte, Signedness), 1044 hipe_rtl:mk_alu(Offset, Offset, add, hipe_rtl:mk_imm(1)), 1045 hipe_rtl:mk_alu(Dst, Dst, sll, hipe_rtl:mk_imm(8)), 1046 hipe_rtl:mk_load(Tmp1, Base, Offset, byte, unsigned), 1047 hipe_rtl:mk_alu(Dst, Dst, 'or', Tmp1), 1048 hipe_rtl:mk_alu(Offset, Offset, add, hipe_rtl:mk_imm(1)), 1049 hipe_rtl:mk_alu(Dst, Dst, sll, hipe_rtl:mk_imm(8)), 1050 hipe_rtl:mk_load(Tmp1, Base, Offset, byte, unsigned), 1051 hipe_rtl:mk_alu(Dst, Dst, 'or', Tmp1), 1052 hipe_rtl:mk_alu(Offset, Offset, add, hipe_rtl:mk_imm(1))]; 1053 little -> 1054 [hipe_rtl:mk_load(Dst, Base, Offset, byte, unsigned), 1055 hipe_rtl:mk_alu(Offset, Offset, add, hipe_rtl:mk_imm(1)), 1056 hipe_rtl:mk_load(Tmp1, Base, Offset, byte,unsigned), 1057 hipe_rtl:mk_alu(Tmp1, Tmp1, sll, hipe_rtl:mk_imm(8)), 1058 hipe_rtl:mk_alu(Dst, Dst, 'or', Tmp1), 1059 hipe_rtl:mk_alu(Offset, Offset, add, hipe_rtl:mk_imm(1)), 1060 hipe_rtl:mk_load(Tmp1, Base, Offset, byte,Signedness), 1061 hipe_rtl:mk_alu(Tmp1, Tmp1, sll, hipe_rtl:mk_imm(16)), 1062 hipe_rtl:mk_alu(Dst, Dst, 'or', Tmp1), 1063 hipe_rtl:mk_alu(Offset, Offset, add, hipe_rtl:mk_imm(1))] 1064 end; 1065load_bytes(Dst, Base, Offset, {Signedness, Endianness}, 4) -> 1066 case Endianness of 1067 big -> 1068 hipe_rtl_arch:load_big_4(Dst, Base, Offset, Signedness); 1069 little -> 1070 hipe_rtl_arch:load_little_4(Dst, Base, Offset, Signedness) 1071 end; 1072 1073load_bytes(Dst, Base, Offset, {Signedness, Endianness}, X) when X > 1 -> 1074 [LoopLbl, EndLbl] = create_lbls(2), 1075 [Tmp1, Limit, TmpOffset] = create_regs(3), 1076 case Endianness of 1077 big -> 1078 [hipe_rtl:mk_alu(Limit, Offset, add, hipe_rtl:mk_imm(X)), 1079 hipe_rtl:mk_load(Dst, Base, Offset, byte, Signedness), 1080 hipe_rtl:mk_alu(Offset, Offset, add, hipe_rtl:mk_imm(1)), 1081 LoopLbl, 1082 hipe_rtl:mk_load(Tmp1, Base, Offset, byte, unsigned), 1083 hipe_rtl:mk_alu(Offset, Offset, add, hipe_rtl:mk_imm(1)), 1084 hipe_rtl:mk_alu(Dst, Dst, sll, hipe_rtl:mk_imm(8)), 1085 hipe_rtl:mk_alu(Dst, Dst, 'or', Tmp1), 1086 hipe_rtl:mk_branch(Offset, ltu, Limit, hipe_rtl:label_name(LoopLbl), 1087 hipe_rtl:label_name(EndLbl)), 1088 EndLbl]; 1089 little -> 1090 [hipe_rtl:mk_alu(Limit, Offset, add, hipe_rtl:mk_imm(X)), 1091 hipe_rtl:mk_alu(TmpOffset, Limit, sub, hipe_rtl:mk_imm(1)), 1092 hipe_rtl:mk_load(Dst, Base, TmpOffset, byte, Signedness), 1093 LoopLbl, 1094 hipe_rtl:mk_alu(TmpOffset, TmpOffset, sub, hipe_rtl:mk_imm(1)), 1095 hipe_rtl:mk_load(Tmp1, Base, TmpOffset, byte, Signedness), 1096 hipe_rtl:mk_alu(Dst, Dst, sll, hipe_rtl:mk_imm(8)), 1097 hipe_rtl:mk_alu(Dst, Dst, 'or', Tmp1), 1098 hipe_rtl:mk_branch(Offset, ltu, TmpOffset, hipe_rtl:label_name(LoopLbl), 1099 hipe_rtl:label_name(EndLbl)), 1100 EndLbl, 1101 hipe_rtl:mk_move(Offset, Limit)] 1102 end. 1103 1104create_regs(X) when X > 0 -> 1105 [hipe_rtl:mk_new_reg()|create_regs(X-1)]; 1106create_regs(0) -> 1107 []. 1108 1109create_gcsafe_regs(X) when X > 0 -> 1110 [hipe_rtl:mk_new_reg_gcsafe()|create_gcsafe_regs(X-1)]; 1111create_gcsafe_regs(0) -> 1112 []. 1113 1114is_illegal_const(Const) -> 1115 Const >= 1 bsl (hipe_rtl_arch:word_size() * ?BYTE_SIZE) orelse Const < 0. 1116