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%% Module : hipe_rtl_binary_construct 17%% Purpose : 18%% Notes : 19%% History : Written mostly by Per Gustafsson 20%% ==================================================================== 21%% Exports : 22%% 23%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 24 25-module(hipe_rtl_binary_construct). 26 27-export([gen_rtl/7]). 28 29-import(hipe_rtl_binary, [get_word_integer/4]). 30 31%%------------------------------------------------------------------------- 32 33-include("../main/hipe.hrl"). 34-include("hipe_rtl.hrl"). 35-include("hipe_literals.hrl"). 36 37-define(BYTE_SHIFT, hipe_rtl:mk_imm(3)). %% Turn bits into bytes or vice versa 38-define(LOW_BITS, hipe_rtl:mk_imm(7)). %% Three lowest bits set 39-define(LOW_BITS_INT, 7). 40-define(BYTE_SIZE, 8). 41-define(MAX_BINSIZE, ((1 bsl ((hipe_rtl_arch:word_size()*?BYTE_SIZE)-3)) - 1)). 42 43%% ------------------------------------------------------------------------- 44%% The code is generated as a list of lists, it will be flattened later. 45%% 46 47gen_rtl(BsOP, Dst, Args, TrueLblName, FalseLblName, SystemLimitLblName, ConstTab) -> 48 %%io:format("~w, ~w, ~w~n", [BsOP, Args, Dst]), 49 case BsOP of 50 {bs_put_string, String, SizeInBytes} -> 51 [NewOffset] = get_real(Dst), 52 [Base, Offset] = Args, 53 put_string(NewOffset, ConstTab, String, SizeInBytes, Base, Offset, 54 TrueLblName); 55 _ -> 56 Code = 57 case BsOP of 58 {bs_init, Size, _Flags} -> 59 [] = Args, 60 [Dst0, Base, Offset] = Dst, 61 case is_illegal_const(Size bsl 3) of 62 true -> 63 hipe_rtl:mk_goto(SystemLimitLblName); 64 false -> 65 const_init2(Size, Dst0, Base, Offset, TrueLblName) 66 end; 67 68 {bs_init, _Flags} -> 69 [Size] = Args, 70 [Dst0, Base, Offset] = Dst, 71 var_init2(Size, Dst0, Base, Offset, TrueLblName, 72 SystemLimitLblName, FalseLblName); 73 74 {bs_init_bits, Size, _Flags} -> 75 [] = Args, 76 [Dst0, Base, Offset] = Dst, 77 case is_illegal_const(Size) of 78 true -> 79 hipe_rtl:mk_goto(SystemLimitLblName); 80 false -> 81 const_init_bits(Size, Dst0, Base, Offset, TrueLblName) 82 end; 83 84 {bs_init_bits, _Flags} -> 85 [Size] = Args, 86 [Dst0, Base, Offset] = Dst, 87 var_init_bits(Size, Dst0, Base, Offset, TrueLblName, 88 SystemLimitLblName, FalseLblName); 89 90 {bs_put_binary_all, Unit, _Flags} -> 91 [Src, Base, Offset] = Args, 92 [NewOffset] = get_real(Dst), 93 put_binary_all(NewOffset, Src, Base, Offset, Unit, 94 TrueLblName, FalseLblName); 95 96 {bs_put_binary, Size, _Flags} -> 97 case is_illegal_const(Size) of 98 true -> 99 [hipe_rtl:mk_goto(FalseLblName)]; 100 false -> 101 [NewOffset] = get_real(Dst), 102 case Args of 103 [Src, Base, Offset] -> 104 put_static_binary(NewOffset, Src, Size, Base, Offset, 105 TrueLblName, FalseLblName); 106 [Src, Bits, Base, Offset] -> 107 {SizeCode, SizeReg} = 108 hipe_rtl_binary:make_size(Size, Bits, SystemLimitLblName, 109 FalseLblName), 110 InCode = put_dynamic_binary(NewOffset, Src, SizeReg, Base, 111 Offset, TrueLblName, FalseLblName), 112 SizeCode ++ InCode 113 end 114 end; 115 116 {bs_put_float, Size, Flags, ConstInfo} -> 117 [NewOffset] = get_real(Dst), 118 Aligned = aligned(Flags), 119 LittleEndian = littleendian(Flags), 120 case is_illegal_const(Size) of 121 true -> 122 [hipe_rtl:mk_goto(FalseLblName)]; 123 false -> 124 case Args of 125 [Src, Base, Offset] -> 126 CCode = static_float_c_code(NewOffset, Src, Base, Offset, Size, Flags, 127 TrueLblName, FalseLblName), 128 put_float(NewOffset, Src, Base, Offset, Size, CCode, Aligned, 129 LittleEndian, ConstInfo, TrueLblName); 130 [Src, Bits, Base, Offset] -> 131 {SizeCode, SizeReg} = 132 hipe_rtl_binary:make_size(Size, Bits, SystemLimitLblName, 133 FalseLblName), 134 InCode = float_c_code(NewOffset, Src, Base, Offset, SizeReg, 135 Flags, TrueLblName, FalseLblName), 136 SizeCode ++ InCode 137 end 138 end; 139 140 {unsafe_bs_put_integer, 0, _Flags, _ConstInfo} -> 141 [NewOffset] = get_real(Dst), 142 case Args of 143 [_Src, _Base, Offset] -> 144 [hipe_rtl:mk_move(NewOffset,Offset), 145 hipe_rtl:mk_goto(TrueLblName)]; 146 [_Src, _Bits, _Base, Offset] -> 147 [hipe_rtl:mk_move(NewOffset,Offset), 148 hipe_rtl:mk_goto(TrueLblName)] 149 end; 150 151 {unsafe_bs_put_integer, Size, Flags, ConstInfo} -> 152 do_bs_put_integer(Dst, Args, Size, Flags, ConstInfo, true, 153 TrueLblName, FalseLblName, SystemLimitLblName); 154 155 {bs_put_integer, Size, Flags, ConstInfo} -> 156 do_bs_put_integer(Dst, Args, Size, Flags, ConstInfo, false, 157 TrueLblName, FalseLblName, SystemLimitLblName); 158 159 bs_utf8_size -> 160 case Dst of 161 [_DstVar] -> 162 [_Arg] = Args, 163 [hipe_rtl:mk_call(Dst, bs_utf8_size, Args, 164 TrueLblName, [], not_remote)]; 165 [] -> 166 [hipe_rtl:mk_goto(TrueLblName)] 167 end; 168 169 bs_put_utf8 -> 170 [_Src, _Base, _Offset] = Args, 171 [NewOffs] = get_real(Dst), 172 RetLbl = hipe_rtl:mk_new_label(), 173 [hipe_rtl:mk_call([NewOffs], bs_put_utf8, Args, 174 hipe_rtl:label_name(RetLbl), [], not_remote), 175 RetLbl, 176 hipe_rtl:mk_branch(NewOffs, ne, hipe_rtl:mk_imm(0), 177 TrueLblName, FalseLblName, 0.99)]; 178 179 bs_utf16_size -> 180 case Dst of 181 [_DstVar] -> 182 [_Arg] = Args, 183 [hipe_rtl:mk_call(Dst, bs_utf16_size, Args, 184 TrueLblName, [], not_remote)]; 185 [] -> 186 [hipe_rtl:mk_goto(TrueLblName)] 187 end; 188 189 {bs_put_utf16, Flags} -> 190 [_Src, _Base, _Offset] = Args, 191 NewDsts = get_real(Dst), 192 PrimOp = % workaround for bif/primop arity restrictions 193 case littleendian(Flags) of 194 false -> bs_put_utf16be; 195 true -> bs_put_utf16le 196 end, 197 [hipe_rtl:mk_call(NewDsts, PrimOp, Args, 198 TrueLblName, FalseLblName, not_remote)]; 199 200 bs_validate_unicode -> 201 [_Arg] = Args, 202 [IsUnicode] = create_regs(1), 203 RetLbl = hipe_rtl:mk_new_label(), 204 [hipe_rtl:mk_call([IsUnicode], is_unicode, Args, 205 hipe_rtl:label_name(RetLbl), [], not_remote), 206 RetLbl, 207 hipe_rtl:mk_branch(IsUnicode, ne, hipe_rtl:mk_imm(0), 208 TrueLblName, FalseLblName, 0.99)]; 209 210 bs_final -> 211 Zero = hipe_rtl:mk_imm(0), 212 [Src, Offset] = Args, 213 [BitSize, ByteSize] = create_regs(2), 214 [ShortLbl, LongLbl] = create_lbls(2), 215 case Dst of 216 [DstVar] -> 217 [hipe_rtl:mk_alub(BitSize, Offset, 'and', ?LOW_BITS, eq, 218 hipe_rtl:label_name(ShortLbl), 219 hipe_rtl:label_name(LongLbl)), ShortLbl, 220 hipe_rtl:mk_move(DstVar, Src), 221 hipe_rtl:mk_goto(TrueLblName), 222 LongLbl, 223 hipe_rtl:mk_alu(ByteSize, Offset, 'srl', ?BYTE_SHIFT), 224 hipe_tagscheme:mk_sub_binary(DstVar, ByteSize, 225 Zero, BitSize, Zero, Src), 226 hipe_rtl:mk_goto(TrueLblName)]; 227 [] -> 228 [hipe_rtl:mk_goto(TrueLblName)] 229 end; 230 231 bs_init_writable -> 232 Zero = hipe_rtl:mk_imm(0), 233 [Size] = Args, 234 [DstVar] = Dst, 235 [SizeReg] = create_regs(1), 236 [Base] = create_unsafe_regs(1), 237 [hipe_rtl:mk_gctest(?PROC_BIN_WORDSIZE + ?SUB_BIN_WORDSIZE), 238 get_word_integer(Size, SizeReg, SystemLimitLblName, FalseLblName), 239 allocate_writable(DstVar, Base, SizeReg, Zero, Zero), 240 hipe_rtl:mk_goto(TrueLblName)]; 241 242 {bs_private_append, _U, _F} -> 243 [Size, Bin] = Args, 244 [DstVar, Base, Offset] = Dst, 245 [ProcBin] = create_vars(1), 246 [SubSize, SizeReg, EndSubSize, EndSubBitSize] = create_regs(4), 247 SubBinSize = {sub_binary, binsize}, 248 [hipe_tagscheme:get_field_from_term({sub_binary, orig}, Bin, ProcBin), 249 hipe_tagscheme:get_field_from_term(SubBinSize, Bin, SubSize), 250 get_word_integer(Size, SizeReg, SystemLimitLblName, FalseLblName), 251 realloc_binary(SizeReg, ProcBin, Base), 252 calculate_sizes(Bin, SizeReg, Offset, EndSubSize, EndSubBitSize), 253 hipe_tagscheme:set_field_from_term(SubBinSize, Bin, EndSubSize), 254 hipe_tagscheme:set_field_from_term({sub_binary, bitsize}, Bin, EndSubBitSize), 255 hipe_rtl:mk_move(DstVar, Bin), 256 hipe_rtl:mk_goto(TrueLblName)]; 257 258 {bs_append, _U, _F, Unit, _Bla} -> 259 [Size, Bin] = Args, 260 [DstVar, Base, Offset] = Dst, 261 [ProcBin] = create_vars(1), 262 [Flags, SizeReg, IsWritable, EndSubSize, EndSubBitSize] = 263 create_regs(5), 264 [ContLbl,ContLbl2,ContLbl3,ContLbl4,WritableLbl,NotWritableLbl] = 265 Lbls = create_lbls(6), 266 [ContLblName, ContLbl2Name, ContLbl3Name, ContLbl4Name, 267 Writable, NotWritable] = 268 [hipe_rtl:label_name(Lbl) || Lbl <- Lbls], 269 Zero = hipe_rtl:mk_imm(0), 270 SubIsWritable = {sub_binary, is_writable}, 271 [hipe_rtl:mk_gctest(?SUB_BIN_WORDSIZE + ?PROC_BIN_WORDSIZE), 272 get_word_integer(Size, SizeReg, SystemLimitLblName, FalseLblName), 273 hipe_tagscheme:test_bitstr(Bin, ContLblName, FalseLblName, 0.99), 274 ContLbl, 275 hipe_tagscheme:test_subbinary(Bin,ContLbl2Name, NotWritable), 276 ContLbl2, 277 hipe_tagscheme:get_field_from_term(SubIsWritable, Bin, IsWritable), 278 hipe_rtl:mk_branch(IsWritable, 'ne', Zero, 279 ContLbl3Name, NotWritable), 280 ContLbl3, 281 hipe_tagscheme:get_field_from_term({sub_binary, orig}, Bin, ProcBin), 282 hipe_tagscheme:get_field_from_term({proc_bin, flags}, ProcBin, Flags), 283 hipe_rtl:mk_alub(Flags, Flags, 'and', 284 hipe_rtl:mk_imm(?PB_IS_WRITABLE), 285 eq, NotWritable, ContLbl4Name, 0.01), 286 ContLbl4, 287 calculate_sizes(Bin, SizeReg, Offset, EndSubSize, EndSubBitSize), 288 is_divisible(Offset, Unit, Writable, FalseLblName), 289 WritableLbl, 290 hipe_tagscheme:set_field_from_term(SubIsWritable, Bin, Zero), 291 realloc_binary(SizeReg, ProcBin, Base), 292 hipe_tagscheme:mk_sub_binary(DstVar, EndSubSize, Zero, 293 EndSubBitSize, Zero, 294 hipe_rtl:mk_imm(1), ProcBin), 295 hipe_rtl:mk_goto(TrueLblName), 296 NotWritableLbl, 297 not_writable_code(Bin, SizeReg, DstVar, Base, Offset, Unit, 298 TrueLblName, FalseLblName)] 299 end, 300 {Code, ConstTab} 301 end. 302 303%% Common implementation of bs_put_integer and unsafe_bs_put_integer 304do_bs_put_integer(Dst, Args, Size, Flags, ConstInfo, SrcUnsafe, 305 TrueLblName, FalseLblName, SystemLimitLblName) -> 306 case is_illegal_const(Size) of 307 true -> 308 [hipe_rtl:mk_goto(FalseLblName)]; 309 false -> 310 Aligned = aligned(Flags), 311 LittleEndian = littleendian(Flags), 312 [NewOffset] = get_real(Dst), 313 case ConstInfo of 314 fail -> 315 [hipe_rtl:mk_goto(FalseLblName)]; 316 _ -> 317 case Args of 318 [Src, Base, Offset] -> 319 CCode = static_int_c_code(NewOffset, Src, Base, Offset, Size, 320 Flags, TrueLblName, FalseLblName), 321 put_static_int(NewOffset, Src, Base, Offset, Size, CCode, Aligned, 322 LittleEndian, SrcUnsafe, TrueLblName); 323 [Src, Bits, Base, Offset] -> 324 {SizeCode, SizeReg} = 325 hipe_rtl_binary:make_size(Size, Bits, SystemLimitLblName, 326 FalseLblName), 327 CCode = int_c_code(NewOffset, Src, Base, Offset, SizeReg, Flags, 328 TrueLblName, FalseLblName), 329 InCode = put_dynamic_int(NewOffset, Src, Base, Offset, SizeReg, 330 CCode, Aligned, LittleEndian, SrcUnsafe, 331 TrueLblName), 332 SizeCode ++ InCode 333 end 334 end 335 end. 336 337%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 338%% 339%% Code that is used in the append and init writeable functions 340%% 341%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 342 343not_writable_code(Bin, SizeReg, Dst, Base, Offset, Unit, 344 TrueLblName, FalseLblName) -> 345 [SrcBase] = create_unsafe_regs(1), 346 [SrcOffset, SrcSize, TotSize, TotBytes, UsedBytes] = create_regs(5), 347 [IncLbl,AllLbl] = Lbls = create_lbls(2), 348 [IncLblName,AllLblName] = get_label_names(Lbls), 349 [get_base_offset_size(Bin, SrcBase, SrcOffset, SrcSize, FalseLblName), 350 hipe_rtl:mk_alu(TotSize, SrcSize, add, SizeReg), 351 hipe_rtl:mk_alu(TotBytes, TotSize, add, ?LOW_BITS), 352 hipe_rtl:mk_alu(TotBytes, TotBytes, srl, ?BYTE_SHIFT), 353 hipe_rtl:mk_alu(UsedBytes, TotBytes, sll, hipe_rtl:mk_imm(1)), 354 hipe_rtl:mk_branch(UsedBytes, geu, hipe_rtl:mk_imm(256), 355 AllLblName, IncLblName), 356 IncLbl, 357 hipe_rtl:mk_move(UsedBytes, hipe_rtl:mk_imm(256)), 358 AllLbl, 359 allocate_writable(Dst, Base, UsedBytes, TotBytes, TotSize), 360 put_binary_all(Offset, Bin, Base, hipe_rtl:mk_imm(0), Unit, 361 TrueLblName, FalseLblName)]. 362 363allocate_writable(Dst, Base, UsedBytes, TotBytes, TotSize) -> 364 Zero = hipe_rtl:mk_imm(0), 365 [NextLbl] = create_lbls(1), 366 [EndSubSize, EndSubBitSize] = create_regs(2), 367 [ProcBin] = create_unsafe_regs(1), 368 [hipe_rtl:mk_call([Base], bs_allocate, [UsedBytes], 369 hipe_rtl:label_name(NextLbl), [], not_remote), 370 NextLbl, 371 hipe_tagscheme:create_refc_binary(Base, TotBytes, 372 hipe_rtl:mk_imm(?PB_IS_WRITABLE bor 373 ?PB_ACTIVE_WRITER), 374 ProcBin), 375 hipe_rtl:mk_alu(EndSubSize, TotSize, srl, ?BYTE_SHIFT), 376 hipe_rtl:mk_alu(EndSubBitSize, TotSize, 'and', ?LOW_BITS), 377 hipe_tagscheme:mk_sub_binary(Dst, EndSubSize, Zero, EndSubBitSize, 378 Zero, hipe_rtl:mk_imm(1), ProcBin)]. 379 380realloc_binary(SizeReg, ProcBin, Base) -> 381 [NoReallocLbl, ReallocLbl, NextLbl, ContLbl] = Lbls = create_lbls(4), 382 [NoReallocLblName, ReallocLblName, NextLblName, ContLblName] = 383 [hipe_rtl:label_name(Lbl) || Lbl <- Lbls], 384 [PBSize, Tmp, ByteSize, NewSize, Flags, ResultingSize, OrigSize, 385 BinPointer] = create_regs(8), 386 ProcBinSizeTag = {proc_bin, binsize}, 387 ProcBinFlagsTag = {proc_bin, flags}, 388 ProcBinValTag = {proc_bin, val}, 389 ProcBinBytesTag = {proc_bin, bytes}, 390 BinOrigSizeTag = {binary, orig_size}, 391 [hipe_tagscheme:get_field_from_term(ProcBinSizeTag, ProcBin, PBSize), 392 hipe_rtl:mk_alu(Tmp, SizeReg, 'add', ?LOW_BITS), 393 hipe_rtl:mk_alu(ByteSize, Tmp, 'srl', ?BYTE_SHIFT), 394 hipe_rtl:mk_alu(ResultingSize, ByteSize, 'add', PBSize), 395 hipe_tagscheme:set_field_from_term(ProcBinSizeTag, ProcBin, ResultingSize), 396 hipe_tagscheme:get_field_from_term(ProcBinFlagsTag, ProcBin, Flags), 397 hipe_rtl:mk_alu(Flags, Flags, 'or', hipe_rtl:mk_imm(?PB_ACTIVE_WRITER)), 398 hipe_tagscheme:set_field_from_term(ProcBinFlagsTag, ProcBin, Flags), 399 hipe_tagscheme:get_field_from_term(ProcBinValTag, ProcBin, BinPointer), 400 hipe_tagscheme:get_field_from_pointer(BinOrigSizeTag, BinPointer, OrigSize), 401 hipe_rtl:mk_branch(OrigSize, 'geu', ResultingSize, NoReallocLblName, 402 ReallocLblName), 403 NoReallocLbl, 404 hipe_tagscheme:get_field_from_term(ProcBinBytesTag, ProcBin, Base), 405 hipe_rtl:mk_goto(ContLblName), 406 ReallocLbl, 407 hipe_rtl:mk_alu(NewSize, ResultingSize, 'sll', hipe_rtl:mk_imm(1)), 408 hipe_rtl:mk_call([BinPointer], bs_reallocate, [BinPointer, NewSize], 409 NextLblName, [], not_remote), 410 NextLbl, 411 hipe_tagscheme:set_field_from_pointer(BinOrigSizeTag, BinPointer, NewSize), 412 hipe_tagscheme:set_field_from_term(ProcBinValTag, ProcBin, BinPointer), 413 hipe_tagscheme:extract_binary_bytes(BinPointer, Base), 414 hipe_tagscheme:set_field_from_term(ProcBinBytesTag, ProcBin, Base), 415 ContLbl]. 416 417calculate_sizes(Bin, SizeReg, Offset, EndSubSize, EndSubBitSize) -> 418 [SubSize, SubBitSize, EndSize] = create_regs(3), 419 [hipe_tagscheme:get_field_from_term({sub_binary, binsize}, Bin, SubSize), 420 hipe_tagscheme:get_field_from_term({sub_binary, bitsize}, Bin, SubBitSize), 421 hipe_rtl:mk_alu(Offset, SubSize, 'sll', ?BYTE_SHIFT), 422 hipe_rtl:mk_alu(Offset, Offset, 'add', SubBitSize), 423 hipe_rtl:mk_alu(EndSize, Offset, 'add', SizeReg), 424 hipe_rtl:mk_alu(EndSubSize, EndSize, srl, ?BYTE_SHIFT), 425 hipe_rtl:mk_alu(EndSubBitSize, EndSize, 'and', ?LOW_BITS)]. 426 427%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 428%% 429%% Code that is used to create calls to beam functions 430%% 431%% X_c_code/8, used for putting terms into binaries 432%% 433%% X_get_c_code/10, used for getting terms from binaries 434%% 435%% - gen_test_sideffect_bs_call/4 is used to make a C-call that might 436%% fail but doesn't return an erlang value. 437%% 438%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 439 440static_float_c_code(NewOffset, Src, Base, Offset, Size, Flags, 441 TrueLblName, FalseLblName) -> 442 [SizeReg] = create_regs(1), 443 [hipe_rtl:mk_move(SizeReg, hipe_rtl:mk_imm(Size))| 444 float_c_code(NewOffset, Src, Base, Offset, SizeReg, Flags, 445 TrueLblName, FalseLblName)]. 446 447float_c_code(NewOffset, Src, Base, Offset, SizeReg, Flags, 448 TrueLblName, FalseLblName) -> 449 put_c_code(bs_put_small_float, NewOffset, Src, Base, Offset, SizeReg, 450 Flags, TrueLblName, FalseLblName). 451 452static_int_c_code(NewOffset, Src, Base, Offset, Size, Flags, 453 TrueLblName, FalseLblName) -> 454 [SizeReg] = create_regs(1), 455 [hipe_rtl:mk_move(SizeReg, hipe_rtl:mk_imm(Size))| 456 int_c_code(NewOffset, Src, Base, Offset, SizeReg, Flags, 457 TrueLblName, FalseLblName)]. 458 459int_c_code(NewOffset, Src, Base, Offset, SizeReg, Flags, 460 TrueLblName, FalseLblName) -> 461 put_c_code(bs_put_big_integer, NewOffset, Src, Base, Offset, SizeReg, 462 Flags, TrueLblName, FalseLblName). 463 464binary_c_code(NewOffset, Src, Base, Offset, Size, TrueLblName) -> 465 PassedLbl = hipe_rtl:mk_new_label(), 466 [SizeReg, FlagsReg] = create_regs(2), 467 [hipe_rtl:mk_move(FlagsReg, hipe_rtl:mk_imm(0)), 468 hipe_rtl:mk_move(SizeReg, Size), 469 hipe_rtl:mk_call([], bs_put_bits, [Src, SizeReg, Base, Offset, FlagsReg], 470 hipe_rtl:label_name(PassedLbl), [], not_remote), 471 PassedLbl, 472 hipe_rtl:mk_alu(NewOffset, Offset, add, SizeReg), 473 hipe_rtl:mk_goto(TrueLblName)]. 474 475put_c_code(Func, NewOffset, Src, Base, Offset, SizeReg, Flags, 476 TrueLblName, FalseLblName) -> 477 PassedLbl = hipe_rtl:mk_new_label(), 478 [FlagsReg] = create_regs(1), 479 [hipe_rtl:mk_move(FlagsReg, hipe_rtl:mk_imm(Flags)), 480 gen_test_sideffect_bs_call(Func, [Src, SizeReg, Base, Offset, FlagsReg], 481 hipe_rtl:label_name(PassedLbl), FalseLblName), 482 PassedLbl, 483 hipe_rtl:mk_alu(NewOffset, Offset, add, SizeReg), 484 hipe_rtl:mk_goto(TrueLblName)]. 485 486gen_test_sideffect_bs_call(Name, Args, TrueLblName, FalseLblName) -> 487 [Tmp1] = create_regs(1), 488 RetLbl = hipe_rtl:mk_new_label(), 489 [hipe_rtl:mk_call([Tmp1], Name, Args, 490 hipe_rtl:label_name(RetLbl), [], not_remote), 491 RetLbl, 492 hipe_rtl:mk_branch(Tmp1, eq, hipe_rtl:mk_imm(0), 493 FalseLblName, TrueLblName, 0.01)]. 494 495%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 496%% 497%% Small utility functions: 498%% 499%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 500 501create_regs(X) when X > 0 -> 502 [hipe_rtl:mk_new_reg_gcsafe()|create_regs(X-1)]; 503create_regs(0) -> 504 []. 505 506create_unsafe_regs(X) when X > 0 -> 507 [hipe_rtl:mk_new_reg()|create_unsafe_regs(X-1)]; 508create_unsafe_regs(0) -> 509 []. 510 511create_vars(X) when X > 0 -> 512 [hipe_rtl:mk_new_var()|create_vars(X-1)]; 513create_vars(0) -> 514 []. 515 516create_lbls(X) when X > 0 -> 517 [hipe_rtl:mk_new_label()|create_lbls(X-1)]; 518create_lbls(0) -> 519 []. 520 521get_label_names(Lbls) -> 522 [hipe_rtl:label_name(Lbl) || Lbl <- Lbls]. 523 524aligned(Flags) -> 525 case Flags band ?BSF_ALIGNED of 526 1 -> true; 527 0 -> false 528 end. 529 530littleendian(Flags) -> 531 case Flags band 2 of 532 2 -> true; 533 0 -> false 534 end. 535 536is_illegal_const(Const) -> 537 Const >= (1 bsl (hipe_rtl_arch:word_size() * ?BYTE_SIZE)) orelse Const < 0. 538 539get_real(Dst) -> 540 case Dst of 541 [_NewOffset] -> Dst; 542 [] -> create_regs(1) 543 end. 544 545%%----------------------------------------------------------------------------- 546%% Help functions implementing the bs operations in rtl code. 547%% 548%% The following functions are called from the translation switch: 549%% 550%% - put_string/7 creates code to copy a string to a binary 551%% starting at base+offset and ending at base+newoffset 552%% 553%% - const_init2/6 initializes the creation of a binary of constant size 554%% 555%% - var_init2/6 initializes the creation of a binary of variable size 556%% 557%% - get_int_from_unaligned_bin/11 creates code to extract a fixed 558%% size integer from a binary or makes a c-call if it does not 559%% conform to some certain rules. 560%% 561%% - get_unknown_size_int/11 creates code to extract a variable size 562%% byte-aligned integer from a binary or makes a c-call if it 563%% does not conform to some certain rules. 564%% 565%% - skip_no_of_bits/5 creates code to skip a variable amount of bits 566%% in a binary. 567%% 568%% - load_match_buffer/7 reloads the C-matchbuffer to RTL registers. 569%% 570%% - expand_runtime/4 creates code that calculates a maximal heap need 571%% before a binary match 572%%----------------------------------------------------------------------------- 573 574put_string(NewOffset, ConstTab, String, SizeInBytes, Base, Offset, TLName) -> 575 [StringBase] = create_regs(1), 576 {NewTab, Lbl} = hipe_consttab:insert_block(ConstTab, byte, String), 577 {[hipe_rtl:mk_load_address(StringBase, Lbl, constant)| 578 copy_string(StringBase, SizeInBytes, Base, Offset, NewOffset, TLName)], 579 NewTab}. 580 581const_init2(Size, Dst, Base, Offset, TrueLblName) -> 582 Log2WordSize = hipe_rtl_arch:log2_word_size(), 583 WordSize = hipe_rtl_arch:word_size(), 584 NextLbl = hipe_rtl:mk_new_label(), 585 case Size =< ?MAX_HEAP_BIN_SIZE of 586 true -> 587 [hipe_rtl:mk_gctest(((Size + 3*WordSize-1) bsr Log2WordSize)+?SUB_BIN_WORDSIZE), 588 hipe_tagscheme:create_heap_binary(Base, Size, Dst), 589 hipe_rtl:mk_move(Offset, hipe_rtl:mk_imm(0)), 590 hipe_rtl:mk_goto(TrueLblName)]; 591 false -> 592 ByteSize = hipe_rtl:mk_new_reg(), 593 [hipe_rtl:mk_gctest(?PROC_BIN_WORDSIZE+?SUB_BIN_WORDSIZE), 594 hipe_rtl:mk_move(ByteSize, hipe_rtl:mk_imm(Size)), 595 hipe_rtl:mk_call([Base], bs_allocate, [ByteSize], 596 hipe_rtl:label_name(NextLbl), [], not_remote), 597 NextLbl, 598 hipe_tagscheme:create_refc_binary(Base, ByteSize, Dst), 599 hipe_rtl:mk_move(Offset, hipe_rtl:mk_imm(0)), 600 hipe_rtl:mk_goto(TrueLblName)] 601 end. 602 603const_init_bits(Size, Dst, Base, Offset, TrueLblName) -> 604 Log2WordSize = hipe_rtl_arch:log2_word_size(), 605 WordSize = hipe_rtl_arch:word_size(), 606 [NextLbl] = create_lbls(1), 607 TmpDst = hipe_rtl:mk_new_var(), 608 Zero = hipe_rtl:mk_imm(0), 609 {ExtraSpace, SubBinCode} = 610 case (Size rem ?BYTE_SIZE) =:= 0 of 611 true -> 612 {0, [hipe_rtl:mk_move(Dst, TmpDst)]}; 613 false -> 614 {?SUB_BIN_WORDSIZE, 615 hipe_tagscheme:mk_sub_binary(Dst, hipe_rtl:mk_imm(Size bsr 3), Zero, 616 hipe_rtl:mk_imm(Size band ?LOW_BITS_INT), 617 Zero, TmpDst)} 618 end, 619 BaseBinCode = 620 case Size =< (?MAX_HEAP_BIN_SIZE * 8) of 621 true -> 622 ByteSize = (Size + 7) div 8, 623 [hipe_rtl:mk_gctest(((ByteSize + 3*WordSize-1) bsr Log2WordSize) + ExtraSpace), 624 hipe_tagscheme:create_heap_binary(Base, ByteSize, TmpDst), 625 hipe_rtl:mk_move(Offset, Zero)]; 626 false -> 627 ByteSize = hipe_rtl:mk_new_reg(), 628 [hipe_rtl:mk_gctest(?PROC_BIN_WORDSIZE+ExtraSpace), 629 hipe_rtl:mk_move(Offset, Zero), 630 hipe_rtl:mk_move(ByteSize, hipe_rtl:mk_imm((Size+7) bsr 3)), 631 hipe_rtl:mk_call([Base], bs_allocate, [ByteSize], 632 hipe_rtl:label_name(NextLbl), [], not_remote), 633 NextLbl, 634 hipe_tagscheme:create_refc_binary(Base, ByteSize, TmpDst)] 635 end, 636 [BaseBinCode, SubBinCode, hipe_rtl:mk_goto(TrueLblName)]. 637 638var_init2(Size, Dst, Base, Offset, TrueLblName, SystemLimitLblName, FalseLblName) -> 639 Log2WordSize = hipe_rtl_arch:log2_word_size(), 640 WordSize = hipe_rtl_arch:word_size(), 641 [ContLbl, HeapLbl, REFCLbl, NextLbl] = create_lbls(4), 642 [USize, Tmp] = create_regs(2), 643 [get_word_integer(Size, USize, SystemLimitLblName, FalseLblName), 644 hipe_rtl:mk_branch(USize, leu, hipe_rtl:mk_imm(?MAX_BINSIZE), 645 hipe_rtl:label_name(ContLbl), 646 SystemLimitLblName), 647 ContLbl, 648 hipe_rtl:mk_branch(USize, leu, hipe_rtl:mk_imm(?MAX_HEAP_BIN_SIZE), 649 hipe_rtl:label_name(HeapLbl), 650 hipe_rtl:label_name(REFCLbl)), 651 HeapLbl, 652 hipe_rtl:mk_alu(Tmp, USize, add, hipe_rtl:mk_imm(3*WordSize-1)), 653 hipe_rtl:mk_alu(Tmp, Tmp, srl, hipe_rtl:mk_imm(Log2WordSize)), 654 hipe_rtl:mk_alu(Tmp, Tmp, add, hipe_rtl:mk_imm(?SUB_BIN_WORDSIZE)), 655 hipe_rtl:mk_gctest(Tmp), 656 hipe_tagscheme:create_heap_binary(Base, USize, Dst), 657 hipe_rtl:mk_move(Offset, hipe_rtl:mk_imm(0)), 658 hipe_rtl:mk_goto(TrueLblName), 659 REFCLbl, 660 hipe_rtl:mk_gctest(?PROC_BIN_WORDSIZE+?SUB_BIN_WORDSIZE), 661 hipe_rtl:mk_call([Base], bs_allocate, [USize], 662 hipe_rtl:label_name(NextLbl), [], not_remote), 663 NextLbl, 664 hipe_tagscheme:create_refc_binary(Base, USize, Dst), 665 hipe_rtl:mk_move(Offset, hipe_rtl:mk_imm(0)), 666 hipe_rtl:mk_goto(TrueLblName)]. 667 668var_init_bits(Size, Dst, Base, Offset, TrueLblName, SystemLimitLblName, FalseLblName) -> 669 [HeapLbl, REFCLbl, NextLbl, NoSubLbl, SubLbl, 670 NoCreateSubBin, CreateSubBin, JoinLbl, JoinLbl2] = create_lbls(9), 671 [USize, ByteSize, TotByteSize, OffsetBits] = create_regs(4), 672 [TmpDst] = create_unsafe_regs(1), 673 Log2WordSize = hipe_rtl_arch:log2_word_size(), 674 WordSize = hipe_rtl_arch:word_size(), 675 MaximumWords = 676 erlang:max((?MAX_HEAP_BIN_SIZE + 3*WordSize) bsr Log2WordSize, 677 ?PROC_BIN_WORDSIZE) + ?SUB_BIN_WORDSIZE, 678 Zero = hipe_rtl:mk_imm(0), 679 [hipe_rtl:mk_gctest(MaximumWords), 680 get_word_integer(Size, USize, SystemLimitLblName, FalseLblName), 681 hipe_rtl:mk_alu(ByteSize, USize, srl, ?BYTE_SHIFT), 682 hipe_rtl:mk_alub(OffsetBits, USize, 'and', ?LOW_BITS, eq, 683 hipe_rtl:label_name(NoSubLbl), 684 hipe_rtl:label_name(SubLbl)), 685 NoSubLbl, 686 hipe_rtl:mk_move(TotByteSize, ByteSize), 687 hipe_rtl:mk_goto(hipe_rtl:label_name(JoinLbl)), 688 SubLbl, 689 hipe_rtl:mk_alu(TotByteSize, ByteSize, 'add', hipe_rtl:mk_imm(1)), 690 JoinLbl, 691 hipe_rtl:mk_branch(TotByteSize, 'leu', hipe_rtl:mk_imm(?MAX_HEAP_BIN_SIZE), 692 hipe_rtl:label_name(HeapLbl), 693 hipe_rtl:label_name(REFCLbl)), 694 HeapLbl, 695 hipe_tagscheme:create_heap_binary(Base, TotByteSize, TmpDst), 696 hipe_rtl:mk_goto(hipe_rtl:label_name(JoinLbl2)), 697 REFCLbl, 698 hipe_rtl:mk_call([Base], bs_allocate, [TotByteSize], 699 hipe_rtl:label_name(NextLbl), [], not_remote), 700 NextLbl, 701 hipe_tagscheme:create_refc_binary(Base, TotByteSize, TmpDst), 702 JoinLbl2, 703 hipe_rtl:mk_move(Offset, Zero), 704 hipe_rtl:mk_branch(OffsetBits, 'eq', Zero, 705 hipe_rtl:label_name(NoCreateSubBin), 706 hipe_rtl:label_name(CreateSubBin)), 707 CreateSubBin, 708 hipe_tagscheme:mk_sub_binary(Dst, ByteSize, Zero, OffsetBits, Zero, TmpDst), 709 hipe_rtl:mk_goto(TrueLblName), 710 NoCreateSubBin, 711 hipe_rtl:mk_move(Dst, TmpDst), 712 hipe_rtl:mk_goto(TrueLblName)]. 713 714put_binary_all(NewOffset, Src, Base, Offset, Unit, TLName, FLName) -> 715 [SrcBase, SrcOffset, NumBits] = create_regs(3), 716 [ContLbl] = create_lbls(1), 717 CCode = binary_c_code(NewOffset, Src, Base, Offset, NumBits, TLName), 718 AlignedCode = copy_aligned_bytes(SrcBase, SrcOffset, NumBits, Base, Offset, 719 NewOffset, TLName), 720 [get_base_offset_size(Src, SrcBase, SrcOffset, NumBits,FLName), 721 is_divisible(NumBits, Unit, hipe_rtl:label_name(ContLbl), FLName), 722 ContLbl 723 |test_alignment(SrcOffset, NumBits, Offset, AlignedCode, CCode)]. 724 725test_alignment(SrcOffset, NumBits, Offset, AlignedCode, CCode) -> 726 [Tmp] = create_regs(1), 727 [AlignedLbl, CLbl] = create_lbls(2), 728 [hipe_rtl:mk_alu(Tmp, SrcOffset, 'or', NumBits), 729 hipe_rtl:mk_alu(Tmp, Tmp, 'or', Offset), 730 hipe_rtl:mk_branch(Tmp, 'and', ?LOW_BITS, 'eq', 731 hipe_rtl:label_name(AlignedLbl), 732 hipe_rtl:label_name(CLbl), 0.5), 733 AlignedLbl, 734 AlignedCode, 735 CLbl, 736 CCode]. 737 738put_static_binary(NewOffset, Src, Size, Base, Offset, TLName, FLName) -> 739 [SrcBase] = create_unsafe_regs(1), 740 [SrcOffset, SrcSize] = create_regs(2), 741 case Size of 742 0 -> 743 get_base_offset_size(Src, SrcBase, SrcOffset, SrcSize, FLName) ++ 744 [hipe_rtl:mk_move(NewOffset, Offset), 745 hipe_rtl:mk_goto(TLName)]; 746 _ -> 747 SizeImm = hipe_rtl:mk_imm(Size), 748 CCode = binary_c_code(NewOffset, Src, Base, Offset, SizeImm, TLName), 749 AlignedCode = copy_aligned_bytes(SrcBase, SrcOffset, SizeImm, Base, 750 Offset, NewOffset, TLName), 751 get_base_offset_size(Src, SrcBase, SrcOffset, SrcSize, FLName) ++ 752 small_check(SizeImm, SrcSize, FLName) ++ 753 test_alignment(SrcOffset, SizeImm, Offset, AlignedCode, CCode) 754 end. 755 756put_dynamic_binary(NewOffset, Src, SizeReg, Base, Offset, TLName, FLName) -> 757 [SrcBase] = create_unsafe_regs(1), 758 [SrcOffset, SrcSize] = create_regs(2), 759 CCode = binary_c_code(NewOffset, Src, Base, Offset, SizeReg, TLName), 760 AlignedCode = copy_aligned_bytes(SrcBase, SrcOffset, SizeReg, Base, Offset, 761 NewOffset, TLName), 762 get_base_offset_size(Src, SrcBase, SrcOffset, SrcSize, FLName) ++ 763 small_check(SizeReg, SrcSize, FLName) ++ 764 test_alignment(SrcOffset, SizeReg, Offset, AlignedCode, CCode). 765 766put_float(NewOffset, Src, Base, Offset, 64, CCode, Aligned, LittleEndian, 767 ConstInfo, TrueLblName) -> 768 [CLbl] = create_lbls(1), 769 case {Aligned, LittleEndian} of 770 {true, false} -> 771 copy_float_big(Base, Offset, NewOffset, Src, 772 hipe_rtl:label_name(CLbl), TrueLblName, ConstInfo) ++ 773 [CLbl|CCode]; 774 {true, true} -> 775 copy_float_little(Base, Offset, NewOffset, Src, 776 hipe_rtl:label_name(CLbl), TrueLblName, ConstInfo) ++ 777 [CLbl|CCode]; 778 {false, _} -> 779 CCode 780 end; 781put_float(_NewOffset, _Src, _Base, _Offset, _Size, CCode, _Aligned, 782 _LittleEndian, _ConstInfo, _TrueLblName) -> 783 CCode. 784 785put_static_int(NewOffset, Src, Base, Offset, Size, CCode, Aligned, 786 LittleEndian, SrcUnsafe, TrueLblName) -> 787 {Init, End, UntaggedSrc} = make_init_end(Src, CCode, SrcUnsafe, TrueLblName), 788 case {Aligned, LittleEndian} of 789 {true, true} -> 790 Init ++ 791 copy_int_little(Base, Offset, NewOffset, Size, UntaggedSrc) ++ 792 End; 793 {true, false} -> 794 Init ++ 795 copy_int_big(Base, Offset, NewOffset, Size, UntaggedSrc) ++ 796 End; 797 {false, true} -> 798 CCode; 799 {false, false} -> 800 Init ++ 801 copy_offset_int_big(Base, Offset, NewOffset, Size, UntaggedSrc) ++ 802 End 803 end. 804 805put_dynamic_int(NewOffset, Src, Base, Offset, SizeReg, CCode, Aligned, 806 LittleEndian, SrcUnsafe, TrueLblName) -> 807 {Init, End, UntaggedSrc} = make_init_end(Src, CCode, SrcUnsafe, TrueLblName), 808 case Aligned of 809 true -> 810 case LittleEndian of 811 true -> 812 Init ++ 813 copy_int_little(Base, Offset, NewOffset, SizeReg, UntaggedSrc) ++ 814 End; 815 false -> 816 Init ++ 817 copy_int_big(Base, Offset, NewOffset, SizeReg, UntaggedSrc) ++ 818 End 819 end; 820 false -> 821 CCode 822 end. 823 824%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 825%% 826%% Help functions used by the above 827%% 828%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 829 830make_init_end(Src, CCode, false, TrueLblName) -> 831 [CLbl, SuccessLbl] = create_lbls(2), 832 [UntaggedSrc] = create_regs(1), 833 Init = [hipe_tagscheme:test_fixnum(Src, hipe_rtl:label_name(SuccessLbl), 834 hipe_rtl:label_name(CLbl), 0.99), 835 SuccessLbl, 836 hipe_tagscheme:untag_fixnum(UntaggedSrc,Src)], 837 End = [hipe_rtl:mk_goto(TrueLblName), CLbl| CCode], 838 {Init, End, UntaggedSrc}; 839make_init_end(Src, _CCode, true, TrueLblName) -> 840 [UntaggedSrc] = create_regs(1), 841 Init = [hipe_tagscheme:untag_fixnum(UntaggedSrc,Src)], 842 End = [hipe_rtl:mk_goto(TrueLblName)], 843 {Init, End, UntaggedSrc}. 844 845get_base_offset_size(Binary, SrcBase, SrcOffset, SrcSize, FLName) -> 846 [JoinLbl, EndLbl, SuccessLbl, SubLbl, OtherLbl, HeapLbl, REFCLbl] = 847 Lbls = create_lbls(7), 848 [JoinLblName, EndLblName, SuccessLblName, SubLblName, 849 OtherLblName, HeapLblName, REFCLblName] = get_label_names(Lbls), 850 [BitSize, BitOffset] = create_regs(2), 851 [Orig] = create_vars(1), 852 [hipe_tagscheme:test_bitstr(Binary, SuccessLblName, FLName, 0.99), 853 SuccessLbl, 854 hipe_tagscheme:get_field_from_term({sub_binary,binsize}, Binary, SrcSize), 855 hipe_rtl:mk_alu(SrcSize, SrcSize, sll, ?BYTE_SHIFT), 856 hipe_tagscheme:test_subbinary(Binary, SubLblName, OtherLblName), 857 SubLbl, 858 hipe_tagscheme:get_field_from_term({sub_binary,bitsize}, Binary, BitSize), 859 hipe_tagscheme:get_field_from_term({sub_binary,offset}, Binary, SrcOffset), 860 hipe_rtl:mk_alu(SrcSize, SrcSize, add, BitSize), 861 hipe_tagscheme:get_field_from_term({sub_binary,bitoffset}, Binary, BitOffset), 862 hipe_rtl:mk_alu(SrcOffset, SrcOffset, sll, ?BYTE_SHIFT), 863 hipe_rtl:mk_alu(SrcOffset, SrcOffset, add, BitOffset), 864 hipe_tagscheme:get_field_from_term({sub_binary,orig}, Binary, Orig), 865 hipe_rtl:mk_goto(JoinLblName), 866 OtherLbl, 867 hipe_rtl:mk_move(SrcOffset, hipe_rtl:mk_imm(0)), 868 hipe_rtl:mk_move(Orig, Binary), 869 JoinLbl, 870 hipe_tagscheme:test_heap_binary(Orig, HeapLblName, REFCLblName), 871 HeapLbl, 872 hipe_tagscheme:get_field_addr_from_term({heap_bin, {data, 0}}, Orig, SrcBase), 873 hipe_rtl:mk_goto(EndLblName), 874 REFCLbl, 875 hipe_tagscheme:get_field_from_term({proc_bin,bytes}, Orig, SrcBase), 876 EndLbl]. 877 878copy_aligned_bytes(CopyBase, CopyOffset, Size, Base, Offset, NewOffset, TrueLblName) -> 879 [BaseDst, BaseSrc] = create_unsafe_regs(2), 880 [Iter, Extra, BothOffset] = create_regs(3), 881 initializations(BaseSrc, BaseDst, BothOffset, CopyOffset, Offset, CopyBase, Base) ++ 882 [hipe_rtl:mk_alu(Extra, Size, 'and', ?LOW_BITS), 883 hipe_rtl:mk_alu(Iter, Size, srl, ?BYTE_SHIFT), 884 hipe_rtl:mk_alu(NewOffset, Offset, 'add', Size)] ++ 885 easy_loop(BaseSrc, BaseDst, BothOffset, Iter, Extra, TrueLblName). 886 887copy_string(StringBase, StringSize, BinBase, BinOffset, NewOffset, TrueLblName) -> 888 [TmpOffset,BothOffset,InitOffs] = create_regs(3), 889 [NewBinBase] = create_unsafe_regs(1), 890 [EasyLbl, HardLbl] = create_lbls(2), 891 [hipe_rtl:mk_alu(TmpOffset, BinOffset, srl, ?BYTE_SHIFT), 892 hipe_rtl:mk_alu(NewBinBase, BinBase, add, TmpOffset), 893 hipe_rtl:mk_move(BothOffset, hipe_rtl:mk_imm(0)), 894 hipe_rtl:mk_alub(InitOffs, BinOffset, 'and', ?LOW_BITS, eq, 895 hipe_rtl:label_name(EasyLbl), hipe_rtl:label_name(HardLbl)), 896 EasyLbl, 897 hipe_rtl:mk_alu(NewOffset, BinOffset, add, 898 hipe_rtl:mk_imm(?bytes_to_bits(StringSize)))] ++ 899 easy_loop(StringBase, NewBinBase, BothOffset, 900 hipe_rtl:mk_imm(StringSize), hipe_rtl:mk_imm(0), TrueLblName) ++ 901 [HardLbl, 902 hipe_rtl:mk_alu(NewOffset, BinOffset, add, 903 hipe_rtl:mk_imm(?bytes_to_bits(StringSize)))] ++ 904 hard_loop(StringBase, NewBinBase, BothOffset, hipe_rtl:mk_imm(StringSize), 905 InitOffs, TrueLblName). 906 907small_check(SizeVar, CopySize, FalseLblName) -> 908 SuccessLbl = hipe_rtl:mk_new_label(), 909 [hipe_rtl:mk_branch(SizeVar, leu, CopySize, 910 hipe_rtl:label_name(SuccessLbl), FalseLblName), 911 SuccessLbl]. 912 913easy_loop(BaseSrc, BaseDst, BothOffset, Iterations, Extra, TrueLblName) -> 914 [Tmp1, Shift] = create_regs(2), 915 [LoopLbl, TopLbl, EndLbl, ExtraLbl] = create_lbls(4), 916 [TopLbl, 917 hipe_rtl:mk_branch(BothOffset, ne, Iterations, hipe_rtl:label_name(LoopLbl), 918 hipe_rtl:label_name(EndLbl), 0.99), 919 LoopLbl, 920 hipe_rtl:mk_load(Tmp1, BaseSrc, BothOffset, byte, unsigned), 921 hipe_rtl:mk_store(BaseDst, BothOffset, Tmp1, byte), 922 hipe_rtl:mk_alu(BothOffset, BothOffset, add, hipe_rtl:mk_imm(1)), 923 hipe_rtl:mk_goto(hipe_rtl:label_name(TopLbl)), 924 EndLbl, 925 hipe_rtl:mk_branch(Extra, eq, hipe_rtl:mk_imm(0), TrueLblName, 926 hipe_rtl:label_name(ExtraLbl)), 927 ExtraLbl, 928 hipe_rtl:mk_load(Tmp1, BaseSrc, BothOffset, byte, unsigned), 929 hipe_rtl:mk_alu(Shift, hipe_rtl:mk_imm(?BYTE_SIZE), sub, Extra), 930 hipe_rtl:mk_alu(Tmp1, Tmp1, srl, Shift), 931 hipe_rtl:mk_alu(Tmp1, Tmp1, sll, Shift), 932 hipe_rtl:mk_store(BaseDst, BothOffset, Tmp1, byte), 933 hipe_rtl:mk_goto(TrueLblName)]. 934 935hard_loop(BaseSrc, BaseDst, BothOffset, Iterations, 936 InitOffset, TrueLblName) -> 937 [Tmp1, Tmp2, OldByte, NewByte, SaveByte] = create_regs(5), 938 [LoopLbl, EndLbl, TopLbl] = create_lbls(3), 939 [hipe_rtl:mk_load(OldByte, BaseDst, BothOffset, byte, unsigned), 940 hipe_rtl:mk_alu(Tmp1, hipe_rtl:mk_imm(?BYTE_SIZE), sub, InitOffset), 941 TopLbl, 942 hipe_rtl:mk_branch(BothOffset, ne, Iterations, 943 hipe_rtl:label_name(LoopLbl), 944 hipe_rtl:label_name(EndLbl)), 945 LoopLbl, 946 hipe_rtl:mk_load(NewByte, BaseSrc, BothOffset, byte, unsigned), 947 hipe_rtl:mk_alu(Tmp2, NewByte, srl, InitOffset), 948 hipe_rtl:mk_alu(SaveByte, OldByte, 'or', Tmp2), 949 hipe_rtl:mk_store(BaseDst, BothOffset, SaveByte, byte), 950 hipe_rtl:mk_alu(OldByte, NewByte, sll, Tmp1), 951 hipe_rtl:mk_alu(BothOffset, BothOffset, 'add', hipe_rtl:mk_imm(1)), 952 hipe_rtl:mk_goto(hipe_rtl:label_name(TopLbl)), 953 EndLbl, 954 hipe_rtl:mk_store(BaseDst, BothOffset, OldByte, byte), 955 hipe_rtl:mk_goto(TrueLblName)]. 956 957initializations(BaseTmp1, BaseTmp2, BothOffset, CopyOffset, Offset, CopyBase, Base) -> 958 [OffsetTmp1,OffsetTmp2] = create_regs(2), 959 [hipe_rtl:mk_alu(OffsetTmp1, CopyOffset, srl, ?BYTE_SHIFT), 960 hipe_rtl:mk_alu(OffsetTmp2, Offset, srl, ?BYTE_SHIFT), 961 hipe_rtl:mk_alu(BaseTmp1, CopyBase, add, OffsetTmp1), 962 hipe_rtl:mk_alu(BaseTmp2, Base, add, OffsetTmp2), 963 hipe_rtl:mk_move(BothOffset, hipe_rtl:mk_imm(0))]. 964 965copy_int_little(Base, Offset, NewOffset, Size, Tmp1) when is_integer(Size) -> 966 [Tmp2,TmpOffset] = create_regs(2), 967 ByteSize = Size div ?BYTE_SIZE, 968 [hipe_rtl:mk_alu(TmpOffset, Offset, srl, ?BYTE_SHIFT), 969 hipe_rtl:mk_alu(Tmp2, hipe_rtl:mk_imm(ByteSize), 'add', TmpOffset)] ++ 970 971 little_loop(Tmp1, Tmp2, TmpOffset, Base) ++ 972 973 case Size band 7 of 974 0 -> 975 [hipe_rtl:mk_alu(NewOffset, Offset, 'add', hipe_rtl:mk_imm(Size))]; 976 Bits -> 977 [hipe_rtl:mk_alu(Tmp1, Tmp1, sll, hipe_rtl:mk_imm(?BYTE_SIZE-Bits)), 978 hipe_rtl:mk_store(Base, TmpOffset, Tmp1, byte), 979 hipe_rtl:mk_alu(NewOffset, Offset, 'add', hipe_rtl:mk_imm(Size))] 980 end; 981copy_int_little(Base, Offset, NewOffset, Size, Tmp1) -> 982 [Tmp2, Tmp3, Tmp4, TmpOffset] = create_regs(4), 983 [hipe_rtl:mk_alu(Tmp2, Size, srl, ?BYTE_SHIFT), 984 hipe_rtl:mk_alu(TmpOffset, Offset, srl, ?BYTE_SHIFT), 985 hipe_rtl:mk_alu(Tmp3, Tmp2, 'add', TmpOffset)] ++ 986 987 little_loop(Tmp1, Tmp3, TmpOffset, Base) ++ 988 989 [hipe_rtl:mk_alu(Tmp4, Size, 'and', ?LOW_BITS), 990 hipe_rtl:mk_alu(Tmp4, hipe_rtl:mk_imm(?BYTE_SIZE), 'sub', Tmp4), 991 hipe_rtl:mk_alu(Tmp1, Tmp1, sll, Tmp4), 992 hipe_rtl:mk_store(Base, TmpOffset, Tmp1, byte), 993 hipe_rtl:mk_alu(NewOffset, Offset, 'add', Size)]. 994 995little_loop(Tmp1, Tmp3, TmpOffset, Base) -> 996 [BranchLbl, BodyLbl, EndLbl] = create_lbls(3), 997 [BranchLbl, 998 hipe_rtl:mk_branch(TmpOffset, 'ne', Tmp3, 999 hipe_rtl:label_name(BodyLbl), 1000 hipe_rtl:label_name(EndLbl)), 1001 BodyLbl, 1002 hipe_rtl:mk_store(Base, TmpOffset, Tmp1, byte), 1003 hipe_rtl:mk_alu(Tmp1, Tmp1, 'sra', hipe_rtl:mk_imm(?BYTE_SIZE)), 1004 hipe_rtl:mk_alu(TmpOffset, TmpOffset, 'add', hipe_rtl:mk_imm(1)), 1005 hipe_rtl:mk_goto(hipe_rtl:label_name(BranchLbl)), 1006 EndLbl]. 1007 1008big_loop(Tmp1, Tmp3, TmpOffset, Base) -> 1009 [BranchLbl, BodyLbl, EndLbl] = create_lbls(3), 1010 [BranchLbl, 1011 hipe_rtl:mk_branch(TmpOffset, 'ne', Tmp3, 1012 hipe_rtl:label_name(BodyLbl), 1013 hipe_rtl:label_name(EndLbl)), 1014 BodyLbl, 1015 hipe_rtl:mk_alu(TmpOffset, TmpOffset, 'sub', hipe_rtl:mk_imm(1)), 1016 hipe_rtl:mk_store(Base, TmpOffset, Tmp1, byte), 1017 hipe_rtl:mk_alu(Tmp1, Tmp1, 'sra', hipe_rtl:mk_imm(?BYTE_SIZE)), 1018 hipe_rtl:mk_goto(hipe_rtl:label_name(BranchLbl)), 1019 EndLbl]. 1020 1021copy_int_big(_Base, Offset, NewOffset, 0, _Tmp1) -> 1022 [hipe_rtl:mk_move(NewOffset, Offset)]; 1023copy_int_big(Base, Offset, NewOffset, ?BYTE_SIZE, Tmp1) -> 1024 TmpOffset = hipe_rtl:mk_new_reg(), 1025 [hipe_rtl:mk_alu(TmpOffset, Offset, 'srl', hipe_rtl:mk_imm(3)), 1026 hipe_rtl:mk_store(Base, TmpOffset, Tmp1, byte), 1027 hipe_rtl:mk_alu(NewOffset, Offset, 'add', hipe_rtl:mk_imm(8))]; 1028copy_int_big(Base, Offset, NewOffset, 2*?BYTE_SIZE, Tmp1) -> 1029 TmpOffset = hipe_rtl:mk_new_reg(), 1030 [hipe_rtl:mk_alu(TmpOffset, Offset, 'srl', hipe_rtl:mk_imm(3)), 1031 hipe_rtl:mk_alu(TmpOffset, TmpOffset, 'add', hipe_rtl:mk_imm(1)), 1032 hipe_rtl:mk_store(Base, TmpOffset, Tmp1, byte), 1033 hipe_rtl:mk_alu(TmpOffset, TmpOffset, sub, hipe_rtl:mk_imm(1)), 1034 hipe_rtl:mk_alu(Tmp1, Tmp1, 'sra', hipe_rtl:mk_imm(8)), 1035 hipe_rtl:mk_store(Base, TmpOffset, Tmp1, byte), 1036 hipe_rtl:mk_alu(NewOffset, Offset, 'add', hipe_rtl:mk_imm(16))]; 1037copy_int_big(Base, Offset, NewOffset, 3*?BYTE_SIZE, Tmp1) -> 1038 TmpOffset = hipe_rtl:mk_new_reg(), 1039 [hipe_rtl:mk_alu(TmpOffset, Offset, srl, hipe_rtl:mk_imm(3)), 1040 hipe_rtl:mk_alu(TmpOffset, TmpOffset, add, hipe_rtl:mk_imm(2)), 1041 hipe_rtl:mk_store(Base, TmpOffset, Tmp1, byte), 1042 hipe_rtl:mk_alu(TmpOffset, TmpOffset, sub, hipe_rtl:mk_imm(1)), 1043 hipe_rtl:mk_alu(Tmp1, Tmp1, sra, hipe_rtl:mk_imm(8)), 1044 hipe_rtl:mk_store(Base, TmpOffset, Tmp1, byte), 1045 hipe_rtl:mk_alu(TmpOffset, TmpOffset, sub, hipe_rtl:mk_imm(1)), 1046 hipe_rtl:mk_alu(Tmp1, Tmp1, sra, hipe_rtl:mk_imm(8)), 1047 hipe_rtl:mk_store(Base, TmpOffset, Tmp1, byte), 1048 hipe_rtl:mk_alu(NewOffset, Offset, add, hipe_rtl:mk_imm(24))]; 1049copy_int_big(Base, Offset,NewOffset, 4*?BYTE_SIZE, Tmp1) -> 1050 copy_big_word(Base, Offset, NewOffset, Tmp1); 1051copy_int_big(Base, Offset, NewOffset, Size, Tmp1) when is_integer(Size) -> 1052 [OldOffset, TmpOffset, Bits] = create_regs(3), 1053 ByteSize = (Size + 7) div ?BYTE_SIZE, 1054 case Size band 7 of 1055 0 -> 1056 [hipe_rtl:mk_alu(OldOffset, Offset, sra, hipe_rtl:mk_imm(3)), 1057 hipe_rtl:mk_alu(TmpOffset, OldOffset, add, hipe_rtl:mk_imm(ByteSize))]; 1058 Rest -> 1059 [hipe_rtl:mk_alu(OldOffset, Offset, sra, hipe_rtl:mk_imm(3)), 1060 hipe_rtl:mk_alu(TmpOffset, OldOffset, add, hipe_rtl:mk_imm(ByteSize-1)), 1061 hipe_rtl:mk_alu(Bits, Tmp1, sll, hipe_rtl:mk_imm(?BYTE_SIZE-Rest)), 1062 hipe_rtl:mk_store(Base, TmpOffset, Bits, byte), 1063 hipe_rtl:mk_alu(Tmp1, Tmp1, sra, hipe_rtl:mk_imm(Rest))] 1064 end ++ 1065 big_loop(Tmp1, OldOffset, TmpOffset, Base) ++ 1066 [hipe_rtl:mk_alu(NewOffset, Offset, 'add', hipe_rtl:mk_imm(Size))]; 1067copy_int_big(Base, Offset, NewOffset, Size, Tmp1) -> 1068 Tmp2 = hipe_rtl:mk_new_reg(), 1069 Tmp3 = hipe_rtl:mk_new_reg(), 1070 Tmp4 = hipe_rtl:mk_new_reg(), 1071 Tmp5 = hipe_rtl:mk_new_reg(), 1072 Tmp6 = hipe_rtl:mk_new_reg(), 1073 TmpOffset = hipe_rtl:mk_new_reg(), 1074 EvenLbl = hipe_rtl:mk_new_label(), 1075 OddLbl = hipe_rtl:mk_new_label(), 1076 [hipe_rtl:mk_alu(Tmp2, Size, 'srl', hipe_rtl:mk_imm(3)), 1077 hipe_rtl:mk_alu(Tmp3, Offset, 'srl', hipe_rtl:mk_imm(3)), 1078 hipe_rtl:mk_alu(TmpOffset, Tmp2, 'add', Tmp3), 1079 hipe_rtl:mk_alub(Tmp4, Size, 'and', hipe_rtl:mk_imm(7), 'eq', 1080 hipe_rtl:label_name(EvenLbl), hipe_rtl:label_name(OddLbl)), 1081 OddLbl, 1082 hipe_rtl:mk_alu(Tmp6, hipe_rtl:mk_imm(8), 'sub', Tmp4), 1083 hipe_rtl:mk_alu(Tmp5, Tmp1, 'sll', Tmp6), 1084 hipe_rtl:mk_store(Base, TmpOffset, Tmp5, byte), 1085 EvenLbl, 1086 hipe_rtl:mk_alu(Tmp1, Tmp1, srl, Tmp4)] ++ 1087 big_loop(Tmp1, Tmp3, TmpOffset, Base) ++ 1088 [hipe_rtl:mk_alu(NewOffset, Offset, 'add', Size)]. 1089 1090copy_big_word(Base, Offset, NewOffset, Word) -> 1091 TmpOffset = hipe_rtl:mk_new_reg(), 1092 [hipe_rtl:mk_alu(TmpOffset, Offset, 'srl', hipe_rtl:mk_imm(3)), 1093 hipe_rtl:mk_alu(TmpOffset, TmpOffset, 'add', hipe_rtl:mk_imm(3)), 1094 hipe_rtl:mk_store(Base, TmpOffset, Word, byte), 1095 hipe_rtl:mk_alu(TmpOffset, TmpOffset, 'sub', hipe_rtl:mk_imm(1)), 1096 hipe_rtl:mk_alu(Word, Word, 'sra', hipe_rtl:mk_imm(8)), 1097 hipe_rtl:mk_store(Base, TmpOffset, Word, byte), 1098 hipe_rtl:mk_alu(TmpOffset, TmpOffset, 'sub', hipe_rtl:mk_imm(1)), 1099 hipe_rtl:mk_alu(Word, Word, 'sra', hipe_rtl:mk_imm(8)), 1100 hipe_rtl:mk_store(Base, TmpOffset, Word, byte), 1101 hipe_rtl:mk_alu(TmpOffset, TmpOffset, 'sub', hipe_rtl:mk_imm(1)), 1102 hipe_rtl:mk_alu(Word, Word, 'sra', hipe_rtl:mk_imm(8)), 1103 hipe_rtl:mk_store(Base, TmpOffset, Word, byte), 1104 hipe_rtl:mk_alu(NewOffset, Offset, 'add', hipe_rtl:mk_imm(32))]. 1105 1106copy_little_word(Base, Offset, NewOffset, Word) -> 1107 TmpOffset = hipe_rtl:mk_new_reg(), 1108 [hipe_rtl:mk_alu(TmpOffset, Offset, 'srl', ?BYTE_SHIFT), 1109 hipe_rtl:mk_store(Base, TmpOffset, Word, byte), 1110 hipe_rtl:mk_alu(TmpOffset, TmpOffset, 'add', hipe_rtl:mk_imm(1)), 1111 hipe_rtl:mk_alu(Word, Word, 'sra', hipe_rtl:mk_imm(?BYTE_SIZE)), 1112 hipe_rtl:mk_store(Base, TmpOffset, Word, byte), 1113 hipe_rtl:mk_alu(TmpOffset, TmpOffset, 'add', hipe_rtl:mk_imm(1)), 1114 hipe_rtl:mk_alu(Word, Word, 'sra', hipe_rtl:mk_imm(?BYTE_SIZE)), 1115 hipe_rtl:mk_store(Base, TmpOffset, Word, byte), 1116 hipe_rtl:mk_alu(TmpOffset, TmpOffset, 'add', hipe_rtl:mk_imm(1)), 1117 hipe_rtl:mk_alu(Word, Word, 'sra', hipe_rtl:mk_imm(?BYTE_SIZE)), 1118 hipe_rtl:mk_store(Base, TmpOffset, Word, byte), 1119 hipe_rtl:mk_alu(NewOffset, Offset, 'add', hipe_rtl:mk_imm(32))]. 1120 1121copy_offset_int_big(_Base, Offset, NewOffset, 0, _Tmp1) -> 1122 [hipe_rtl:mk_move(NewOffset, Offset)]; 1123copy_offset_int_big(Base, Offset, NewOffset, Size, Tmp1) 1124 when is_integer(Size), Size > 0 -> 1125 Tmp2 = hipe_rtl:mk_new_reg(), 1126 Tmp3 = hipe_rtl:mk_new_reg(), 1127 Tmp4 = hipe_rtl:mk_new_reg(), 1128 Tmp5 = hipe_rtl:mk_new_reg(), 1129 Tmp6 = hipe_rtl:mk_new_reg(), 1130 Tmp7 = hipe_rtl:mk_new_reg(), 1131 Tmp8 = hipe_rtl:mk_new_reg(), 1132 Tmp9 = hipe_rtl:mk_new_reg(), 1133 OldByte = hipe_rtl:mk_new_reg(), 1134 TmpOffset = hipe_rtl:mk_new_reg(), 1135 BranchLbl = hipe_rtl:mk_new_label(), 1136 BodyLbl = hipe_rtl:mk_new_label(), 1137 EndLbl = hipe_rtl:mk_new_label(), 1138 NextLbl = hipe_rtl:mk_new_label(), 1139 WordSize = hipe_rtl_arch:word_size(), 1140 [hipe_rtl:mk_alu(Tmp2, Offset, 'and', ?LOW_BITS), 1141 hipe_rtl:mk_alu(Tmp3, Offset, srl, ?BYTE_SHIFT), 1142 hipe_rtl:mk_alu(NewOffset, Offset, 'add', hipe_rtl:mk_imm(Size)), 1143 hipe_rtl:mk_alu(Tmp9, NewOffset, 'sub', hipe_rtl:mk_imm(1)), 1144 hipe_rtl:mk_alu(TmpOffset, Tmp9, srl, ?BYTE_SHIFT), 1145 hipe_rtl:mk_alu(Tmp4, NewOffset, 'and', ?LOW_BITS), 1146 hipe_rtl:mk_alu(Tmp6, hipe_rtl:mk_imm(?BYTE_SIZE), 'sub', Tmp4), 1147 hipe_rtl:mk_alu(Tmp6, Tmp6, 'and', ?LOW_BITS), 1148 hipe_rtl:mk_alu(Tmp4, hipe_rtl:mk_imm(?BYTE_SIZE), 'sub', Tmp6), 1149 hipe_rtl:mk_move(Tmp5, Tmp1), 1150 hipe_rtl:mk_alu(Tmp1, Tmp1, 'sll', Tmp6), 1151 hipe_rtl:mk_branch(TmpOffset, 'ne', Tmp3, hipe_rtl:label_name(NextLbl), 1152 hipe_rtl:label_name(EndLbl)), 1153 NextLbl, 1154 hipe_rtl:mk_store(Base, TmpOffset, Tmp1, byte), 1155 hipe_rtl:mk_move(Tmp1, Tmp5), 1156 hipe_rtl:mk_alu(Tmp1, Tmp1, 'sra', Tmp4), 1157 hipe_rtl:mk_alu(TmpOffset, TmpOffset, 'sub', hipe_rtl:mk_imm(1)), 1158 BranchLbl, 1159 hipe_rtl:mk_branch(TmpOffset, 'ne', Tmp3, hipe_rtl:label_name(BodyLbl), 1160 hipe_rtl:label_name(EndLbl)), 1161 BodyLbl, 1162 hipe_rtl:mk_store(Base, TmpOffset, Tmp1, byte), 1163 hipe_rtl:mk_alu(Tmp1, Tmp1, 'sra', hipe_rtl:mk_imm(?BYTE_SIZE)), 1164 hipe_rtl:mk_alu(TmpOffset, TmpOffset, 'sub', hipe_rtl:mk_imm(1)), 1165 hipe_rtl:mk_goto(hipe_rtl:label_name(BranchLbl)), 1166 EndLbl, 1167 hipe_rtl:mk_load(OldByte, Base, TmpOffset, byte, unsigned), 1168 hipe_rtl:mk_alu(Tmp8, hipe_rtl:mk_imm(?BYTE_SIZE), 'sub', Tmp2), 1169 hipe_rtl:mk_alu(OldByte, OldByte, 'srl', Tmp8), 1170 hipe_rtl:mk_alu(OldByte, OldByte, 'sll', Tmp8), 1171 hipe_rtl:mk_alu(Tmp7, Tmp2, 'add', 1172 hipe_rtl:mk_imm(?bytes_to_bits(WordSize-1))), 1173 hipe_rtl:mk_alu(Tmp1, Tmp1, 'sll', Tmp7), 1174 hipe_rtl:mk_alu(Tmp1, Tmp1, 'srl', Tmp7), 1175 hipe_rtl:mk_alu(Tmp1, Tmp1, 'or', OldByte), 1176 hipe_rtl:mk_store(Base, TmpOffset, Tmp1, byte)]. 1177 1178copy_float_little(_Base, _Offset, _NewOffset, _Src, FalseLblName, _TrueLblName, fail) -> 1179 [hipe_rtl:mk_goto(FalseLblName)]; 1180copy_float_little(Base, Offset, NewOffset, Src, _FalseLblName, TrueLblName, pass) -> 1181 FloatLo = hipe_rtl:mk_new_reg(), 1182 FloatHi = hipe_rtl:mk_new_reg(), 1183 TmpOffset = hipe_rtl:mk_new_reg(), 1184 hipe_tagscheme:unsafe_load_float(FloatLo, FloatHi, Src) ++ 1185 copy_little_word(Base, Offset, TmpOffset, FloatLo) ++ 1186 copy_little_word(Base, TmpOffset, NewOffset, FloatHi) ++ 1187 [hipe_rtl:mk_goto(TrueLblName)]; 1188copy_float_little(Base, Offset, NewOffset, Src, FalseLblName, TrueLblName, var) -> 1189 SuccessLbl = hipe_rtl:mk_new_label(), 1190 hipe_tagscheme:test_flonum(Src, hipe_rtl:label_name(SuccessLbl), FalseLblName, 0.99) ++ 1191 [SuccessLbl|copy_float_little(Base, Offset, NewOffset, Src, FalseLblName, TrueLblName, pass)]. 1192 1193copy_float_big(_Base, _Offset, _NewOffset, _Src, FalseLblName, _TrueLblName, fail) -> 1194 [hipe_rtl:mk_goto(FalseLblName)]; 1195copy_float_big(Base, Offset, NewOffset, Src, _FalseLblName, TrueLblName,pass) -> 1196 FloatLo = hipe_rtl:mk_new_reg(), 1197 FloatHi = hipe_rtl:mk_new_reg(), 1198 TmpOffset = hipe_rtl:mk_new_reg(), 1199 hipe_tagscheme:unsafe_load_float(FloatLo, FloatHi, Src) ++ 1200 copy_big_word(Base, Offset, TmpOffset, FloatHi) ++ 1201 copy_big_word(Base, TmpOffset, NewOffset, FloatLo) ++ 1202 [hipe_rtl:mk_goto(TrueLblName)]; 1203copy_float_big(Base, Offset, NewOffset, Src, FalseLblName, TrueLblName, var) -> 1204 SuccessLbl = hipe_rtl:mk_new_label(), 1205 hipe_tagscheme:test_flonum(Src, hipe_rtl:label_name(SuccessLbl), FalseLblName, 0.99) ++ 1206 [SuccessLbl|copy_float_big(Base, Offset, NewOffset, Src, FalseLblName, TrueLblName, pass)]. 1207 1208is_divisible(_Dividend, 1, SuccLbl, _FailLbl) -> 1209 [hipe_rtl:mk_goto(SuccLbl)]; 1210is_divisible(Dividend, Divisor, SuccLbl, FailLbl) -> 1211 Log2 = hipe_rtl_binary:floorlog2(Divisor), 1212 case Divisor =:= 1 bsl Log2 of 1213 true -> %% Divisor is a power of 2 1214 %% Test that the Log2-1 lowest bits are clear 1215 Mask = hipe_rtl:mk_imm(Divisor - 1), 1216 [hipe_rtl:mk_branch(Dividend, 'and', Mask, eq, SuccLbl, FailLbl, 0.99)]; 1217 false -> 1218 %% We need division, fall back to a primop 1219 [Tmp] = create_regs(1), 1220 RetLbl = hipe_rtl:mk_new_label(), 1221 [hipe_rtl:mk_call([Tmp], is_divisible, 1222 [Dividend, hipe_rtl:mk_imm(Divisor)], 1223 hipe_rtl:label_name(RetLbl), [], not_remote), 1224 RetLbl, 1225 hipe_rtl:mk_branch(Tmp, ne, hipe_rtl:mk_imm(0), 1226 SuccLbl, FailLbl, 0.99)] 1227 end. 1228