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%% Copyright (c) 2001 by Erik Johansson. 17%%===================================================================== 18%% Filename : hipe_rtl_arch.erl 19%% History : * 2001-04-10 Erik Johansson (happi@it.uu.se): Created. 20%%===================================================================== 21%% @doc 22%% 23%% This module contains interface functions whose semantics and 24%% implementation depend on the target architecture. 25%% 26%% @end 27%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 28 29-module(hipe_rtl_arch). 30 31-export([first_virtual_reg/0, 32 heap_pointer/0, 33 heap_limit/0, 34 fcalls/0, 35 reg_name/1, 36 is_precoloured/1, 37 call_defined/0, 38 call_used/0, 39 tailcall_used/0, 40 return_used/0, 41 live_at_return/0, 42 endianess/0, 43 load_big_2/4, 44 load_little_2/4, 45 load_big_4/4, 46 load_little_4/4, 47 %% store_4/3, 48 eval_alu/3, 49 %% eval_alub/4, 50 eval_cond/3, 51 eval_cond_bits/5, 52 fwait/0, 53 handle_fp_exception/0, 54 pcb_load/2, 55 pcb_load/3, 56 pcb_store/2, 57 pcb_store/3, 58 pcb_address/2, 59 call_bif/5, 60 %% alignment/0, 61 nr_of_return_regs/0, 62 log2_word_size/0, 63 word_size/0, 64 mk_fp_check_result/1 65 ]). 66 67-include("hipe_literals.hrl"). 68 69%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 70%% ____________________________________________________________________ 71%% 72%% ARCH-specific stuff 73%% ____________________________________________________________________ 74%% 75%% 76%% XXX: x86 might not _have_ real registers for some of these things 77%% 78 79first_virtual_reg() -> 80 case get(hipe_target_arch) of 81 ultrasparc -> 82 hipe_sparc_registers:first_virtual(); 83 powerpc -> 84 hipe_ppc_registers:first_virtual(); 85 ppc64 -> 86 hipe_ppc_registers:first_virtual(); 87 arm -> 88 hipe_arm_registers:first_virtual(); 89 x86 -> 90 hipe_x86_registers:first_virtual(); 91 amd64 -> 92 hipe_amd64_registers:first_virtual() 93 end. 94 95heap_pointer() -> % {GetHPInsn, HPReg, PutHPInsn} 96 case get(hipe_target_arch) of 97 ultrasparc -> 98 heap_pointer_from_reg(hipe_sparc_registers:heap_pointer()); 99 powerpc -> 100 heap_pointer_from_reg(hipe_ppc_registers:heap_pointer()); 101 ppc64 -> 102 heap_pointer_from_reg(hipe_ppc_registers:heap_pointer()); 103 arm -> 104 heap_pointer_from_reg(hipe_arm_registers:heap_pointer()); 105 x86 -> 106 x86_heap_pointer(); 107 amd64 -> 108 amd64_heap_pointer() 109 end. 110 111heap_pointer_from_reg(Reg) -> 112 {hipe_rtl:mk_comment('get_heap_pointer'), 113 hipe_rtl:mk_reg(Reg), 114 hipe_rtl:mk_comment('put_heap_pointer')}. 115 116-ifdef(AMD64_HP_IN_REGISTER). 117amd64_heap_pointer() -> 118 heap_pointer_from_reg(hipe_amd64_registers:heap_pointer()). 119-else. 120-define(HEAP_POINTER_FROM_PCB_NEEDED,1). 121amd64_heap_pointer() -> 122 heap_pointer_from_pcb(). 123-endif. 124 125-ifdef(X86_HP_IN_ESI). 126x86_heap_pointer() -> 127 heap_pointer_from_reg(hipe_x86_registers:heap_pointer()). 128-else. 129-define(HEAP_POINTER_FROM_PCB_NEEDED,1). 130x86_heap_pointer() -> 131 heap_pointer_from_pcb(). 132-endif. 133 134-ifdef(HEAP_POINTER_FROM_PCB_NEEDED). 135heap_pointer_from_pcb() -> 136 Reg = hipe_rtl:mk_new_reg(), 137 {pcb_load(Reg, ?P_HP), Reg, pcb_store(?P_HP, Reg)}. 138-endif. 139 140heap_limit() -> % {GetHLIMITInsn, HLIMITReg} 141 case get(hipe_target_arch) of 142 ultrasparc -> 143 heap_limit_from_pcb(); 144 powerpc -> 145 heap_limit_from_pcb(); 146 ppc64 -> 147 heap_limit_from_pcb(); 148 arm -> 149 heap_limit_from_pcb(); 150 x86 -> 151 heap_limit_from_reg(hipe_x86_registers:heap_limit()); 152 amd64 -> 153 heap_limit_from_reg(hipe_amd64_registers:heap_limit()) 154 end. 155 156heap_limit_from_reg(Reg) -> 157 {hipe_rtl:mk_comment('get_heap_limit'), 158 hipe_rtl:mk_reg(Reg)}. 159 160heap_limit_from_pcb() -> 161 Reg = hipe_rtl:mk_new_reg(), 162 {pcb_load(Reg, ?P_HP_LIMIT), Reg}. 163 164fcalls() -> % {GetFCallsInsn, FCallsReg, PutFCallsInsn} 165 case get(hipe_target_arch) of 166 ultrasparc -> 167 fcalls_from_pcb(); 168 powerpc -> 169 fcalls_from_pcb(); 170 ppc64 -> 171 fcalls_from_pcb(); 172 arm -> 173 fcalls_from_pcb(); 174 x86 -> 175 fcalls_from_reg(hipe_x86_registers:fcalls()); 176 amd64 -> 177 fcalls_from_reg(hipe_amd64_registers:fcalls()) 178 end. 179 180fcalls_from_reg(Reg) -> 181 {hipe_rtl:mk_comment('get_fcalls'), 182 hipe_rtl:mk_reg(Reg), 183 hipe_rtl:mk_comment('put_fcalls')}. 184 185fcalls_from_pcb() -> 186 Reg = hipe_rtl:mk_new_reg(), 187 {pcb_load(Reg, ?P_FCALLS), Reg, pcb_store(?P_FCALLS, Reg)}. 188 189reg_name(Reg) -> 190 case get(hipe_target_arch) of 191 ultrasparc -> 192 hipe_sparc_registers:reg_name_gpr(Reg); 193 powerpc -> 194 hipe_ppc_registers:reg_name_gpr(Reg); 195 ppc64 -> 196 hipe_ppc_registers:reg_name_gpr(Reg); 197 arm -> 198 hipe_arm_registers:reg_name_gpr(Reg); 199 x86 -> 200 hipe_x86_registers:reg_name(Reg); 201 amd64 -> 202 hipe_amd64_registers:reg_name(Reg) 203 end. 204 205%% @spec is_precoloured(rtl_arg()) -> boolean() 206%% 207%% @doc Succeeds if Arg is mapped to a precoloured register in the target. 208%% 209is_precoloured(Arg) -> 210 case hipe_rtl:is_reg(Arg) of 211 true -> 212 is_precolored_regnum(hipe_rtl:reg_index(Arg)); 213 false -> 214 hipe_rtl:is_var(Arg) andalso 215 is_precolored_regnum(hipe_rtl:var_index(Arg)) 216 end. 217 218is_precolored_regnum(RegNum) -> 219 case get(hipe_target_arch) of 220 ultrasparc -> 221 hipe_sparc_registers:is_precoloured_gpr(RegNum); 222 powerpc -> 223 hipe_ppc_registers:is_precoloured_gpr(RegNum); 224 ppc64 -> 225 hipe_ppc_registers:is_precoloured_gpr(RegNum); 226 arm -> 227 hipe_arm_registers:is_precoloured_gpr(RegNum); 228 x86 -> 229 hipe_x86_registers:is_precoloured(RegNum); 230 amd64 -> 231 hipe_amd64_registers:is_precoloured(RegNum) 232 end. 233 234call_defined() -> 235 call_used(). 236 237call_used() -> 238 live_at_return(). 239 240tailcall_used() -> 241 call_used(). 242 243return_used() -> 244 tailcall_used(). 245 246live_at_return() -> 247 case get(hipe_target_arch) of 248 ultrasparc -> 249 ordsets:from_list([hipe_rtl:mk_reg(R) 250 || {R,_} <- hipe_sparc_registers:live_at_return()]); 251 powerpc -> 252 ordsets:from_list([hipe_rtl:mk_reg(R) 253 || {R,_} <- hipe_ppc_registers:live_at_return()]); 254 ppc64 -> 255 ordsets:from_list([hipe_rtl:mk_reg(R) 256 || {R,_} <- hipe_ppc_registers:live_at_return()]); 257 arm -> 258 ordsets:from_list([hipe_rtl:mk_reg(R) 259 || {R,_} <- hipe_arm_registers:live_at_return()]); 260 x86 -> 261 ordsets:from_list([hipe_rtl:mk_reg(R) 262 || {R,_} <- hipe_x86_registers:live_at_return()]); 263 amd64 -> 264 ordsets:from_list([hipe_rtl:mk_reg(R) 265 || {R,_} <- hipe_amd64_registers:live_at_return()]) 266 end. 267 268%% @spec word_size() -> integer() 269%% 270%% @doc Returns the target's word size. 271%% 272word_size() -> 273 case get(hipe_target_arch) of 274 ultrasparc -> 4; 275 powerpc -> 4; 276 ppc64 -> 8; 277 arm -> 4; 278 x86 -> 4; 279 amd64 -> 8 280 end. 281 282%% alignment() -> 283%% case get(hipe_target_arch) of 284%% ultrasparc -> 4; 285%% powerpc -> 4; 286%% arm -> 4; 287%% x86 -> 4; 288%% amd64 -> 8 289%% end. 290 291%% @spec log2_word_size() -> integer() 292%% 293%% @doc Returns log2 of the target's word size. 294%% 295log2_word_size() -> 296 case get(hipe_target_arch) of 297 ultrasparc -> 2; 298 powerpc -> 2; 299 ppc64 -> 3; 300 arm -> 2; 301 x86 -> 2; 302 amd64 -> 3 303 end. 304 305%% @spec endianess() -> big | little 306%% 307%% @doc Returns the target's endianess. 308%% 309endianess() -> 310 case get(hipe_target_arch) of 311 ultrasparc -> big; 312 powerpc -> big; 313 ppc64 -> big; 314 x86 -> little; 315 amd64 -> little; 316 arm -> ?ARM_ENDIANESS 317 end. 318 319%%%------------------------------------------------------------------------ 320%%% Reading integers from binaries, in various sizes and endianesses. 321%%% Operand-sized alignment is NOT guaranteed, only byte alignment. 322%%%------------------------------------------------------------------------ 323 324%%% Load a 2-byte big-endian integer from a binary. 325%%% Increment Offset by 2. 326load_big_2(Dst, Base, Offset, Signedness) -> 327 case get(hipe_target_arch) of 328 powerpc -> 329 load_2_directly(Dst, Base, Offset, Signedness); 330 ppc64 -> 331 load_2_directly(Dst, Base, Offset, Signedness); 332 %% Note: x86 could use a "load;xchgb" or "load;rol $8,<16-bit reg>" 333 %% sequence here. This has been implemented, but unfortunately didn't 334 %% make consistent improvements to our benchmarks. 335 _ -> 336 load_big_2_in_pieces(Dst, Base, Offset, Signedness) 337 end. 338 339%%% Load a 2-byte little-endian integer from a binary. 340%%% Increment Offset by 2. 341load_little_2(Dst, Base, Offset, Signedness) -> 342 case get(hipe_target_arch) of 343 x86 -> 344 load_2_directly(Dst, Base, Offset, Signedness); 345 powerpc -> 346 [hipe_rtl:mk_call([Dst], 'lhbrx', [Base,Offset], [], [], not_remote), 347 hipe_rtl:mk_alu(Offset, Offset, add, hipe_rtl:mk_imm(2)) | 348 case Signedness of 349 unsigned -> []; 350 signed -> [hipe_rtl:mk_call([Dst], 'extsh', [Dst], [], [], not_remote)] 351 end]; 352 ppc64 -> 353 [hipe_rtl:mk_call([Dst], 'lhbrx', [Base,Offset], [], [], not_remote), 354 hipe_rtl:mk_alu(Offset, Offset, add, hipe_rtl:mk_imm(2)) | 355 case Signedness of 356 unsigned -> []; 357 signed -> [hipe_rtl:mk_call([Dst], 'extsh', [Dst], [], [], not_remote)] 358 end]; 359 _ -> 360 load_little_2_in_pieces(Dst, Base, Offset, Signedness) 361 end. 362 363load_2_directly(Dst, Base, Offset, Signedness) -> 364 [hipe_rtl:mk_load(Dst, Base, Offset, int16, Signedness), 365 hipe_rtl:mk_alu(Offset, Offset, add, hipe_rtl:mk_imm(2))]. 366 367load_big_2_in_pieces(Dst, Base, Offset, Signedness) -> 368 Tmp1 = hipe_rtl:mk_new_reg(), 369 [hipe_rtl:mk_load(Dst, Base, Offset, byte, Signedness), 370 hipe_rtl:mk_alu(Offset, Offset, add, hipe_rtl:mk_imm(1)), 371 hipe_rtl:mk_alu(Dst, Dst, sll, hipe_rtl:mk_imm(8)), 372 hipe_rtl:mk_load(Tmp1, Base, Offset, byte, unsigned), 373 hipe_rtl:mk_alu(Dst, Dst, 'or', Tmp1), 374 hipe_rtl:mk_alu(Offset, Offset, add, hipe_rtl:mk_imm(1))]. 375 376load_little_2_in_pieces(Dst, Base, Offset, Signedness) -> 377 Tmp1 = hipe_rtl:mk_new_reg(), 378 [hipe_rtl:mk_load(Dst, Base, Offset, byte, unsigned), 379 hipe_rtl:mk_alu(Offset, Offset, add, hipe_rtl:mk_imm(1)), 380 hipe_rtl:mk_load(Tmp1, Base, Offset, byte, Signedness), 381 hipe_rtl:mk_alu(Tmp1, Tmp1, sll, hipe_rtl:mk_imm(8)), 382 hipe_rtl:mk_alu(Dst, Dst, 'or', Tmp1), 383 hipe_rtl:mk_alu(Offset, Offset, add, hipe_rtl:mk_imm(1))]. 384 385%%% Load a 4-byte big-endian integer from a binary. 386%%% Increment Offset by 4. 387load_big_4(Dst, Base, Offset, Signedness) -> 388 case get(hipe_target_arch) of 389 powerpc -> 390 load_4_directly(Dst, Base, Offset, Signedness); 391 ppc64 -> 392 load_4_directly(Dst, Base, Offset, Signedness); 393 %% Note: x86 could use a "load;bswap" sequence here. 394 %% This has been implemented, but unfortunately didn't 395 %% make any noticeable improvements in our benchmarks. 396 arm -> 397 %% When loading 4 bytes into a 32-bit register, the 398 %% signedness of the high-order byte doesn't matter. 399 %% ARM prefers unsigned byte loads so we'll use that. 400 load_big_4_in_pieces(Dst, Base, Offset, unsigned); 401 _ -> 402 load_big_4_in_pieces(Dst, Base, Offset, Signedness) 403 end. 404 405%%% Load a 4-byte little-endian integer from a binary. 406%%% Increment Offset by 4. 407load_little_4(Dst, Base, Offset, Signedness) -> 408 case get(hipe_target_arch) of 409 x86 -> 410 load_4_directly(Dst, Base, Offset, Signedness); 411 powerpc -> 412 [hipe_rtl:mk_call([Dst], 'lwbrx', [Base,Offset], [], [], not_remote), 413 hipe_rtl:mk_alu(Offset, Offset, add, hipe_rtl:mk_imm(4))]; 414 ppc64 -> 415 [hipe_rtl:mk_call([Dst], 'lwbrx', [Base,Offset], [], [], not_remote), 416 hipe_rtl:mk_alu(Offset, Offset, add, hipe_rtl:mk_imm(4)) | 417 case Signedness of 418 unsigned -> []; 419 signed -> [hipe_rtl:mk_call([Dst], 'extsw', [Dst], [], [], not_remote)] 420 end]; 421 arm -> 422 %% When loading 4 bytes into a 32-bit register, the 423 %% signedness of the high-order byte doesn't matter. 424 %% ARM prefers unsigned byte loads so we'll use that. 425 load_little_4_in_pieces(Dst, Base, Offset, unsigned); 426 _ -> 427 load_little_4_in_pieces(Dst, Base, Offset, Signedness) 428 end. 429 430load_4_directly(Dst, Base, Offset, Signedness) -> 431 [hipe_rtl:mk_load(Dst, Base, Offset, int32, Signedness), 432 hipe_rtl:mk_alu(Offset, Offset, add, hipe_rtl:mk_imm(4))]. 433 434load_big_4_in_pieces(Dst, Base, Offset, Signedness) -> 435 Tmp1 = hipe_rtl:mk_new_reg(), 436 [hipe_rtl:mk_load(Dst, Base, Offset, byte, Signedness), 437 hipe_rtl:mk_alu(Offset, Offset, add, hipe_rtl:mk_imm(1)), 438 hipe_rtl:mk_alu(Dst, Dst, sll, hipe_rtl:mk_imm(8)), 439 hipe_rtl:mk_load(Tmp1, Base, Offset, byte, unsigned), 440 hipe_rtl:mk_alu(Dst, Dst, 'or', Tmp1), 441 hipe_rtl:mk_alu(Offset, Offset, add, hipe_rtl:mk_imm(1)), 442 hipe_rtl:mk_alu(Dst, Dst, sll, hipe_rtl:mk_imm(8)), 443 hipe_rtl:mk_load(Tmp1, Base, Offset, byte, unsigned), 444 hipe_rtl:mk_alu(Dst, Dst, 'or', Tmp1), 445 hipe_rtl:mk_alu(Offset, Offset, add, hipe_rtl:mk_imm(1)), 446 hipe_rtl:mk_alu(Dst, Dst, sll, hipe_rtl:mk_imm(8)), 447 hipe_rtl:mk_load(Tmp1, Base, Offset, byte, unsigned), 448 hipe_rtl:mk_alu(Dst, Dst, 'or', Tmp1), 449 hipe_rtl:mk_alu(Offset, Offset, add, hipe_rtl:mk_imm(1))]. 450 451load_little_4_in_pieces(Dst, Base, Offset, Signedness) -> 452 Tmp1 = hipe_rtl:mk_new_reg(), 453 [hipe_rtl:mk_load(Dst, Base, Offset, byte, unsigned), 454 hipe_rtl:mk_alu(Offset, Offset, add, hipe_rtl:mk_imm(1)), 455 hipe_rtl:mk_load(Tmp1, Base, Offset, byte, unsigned), 456 hipe_rtl:mk_alu(Tmp1, Tmp1, sll, hipe_rtl:mk_imm(8)), 457 hipe_rtl:mk_alu(Dst, Dst, 'or', Tmp1), 458 hipe_rtl:mk_alu(Offset, Offset, add, hipe_rtl:mk_imm(1)), 459 hipe_rtl:mk_load(Tmp1, Base, Offset, byte, unsigned), 460 hipe_rtl:mk_alu(Tmp1, Tmp1, sll, hipe_rtl:mk_imm(16)), 461 hipe_rtl:mk_alu(Dst, Dst, 'or', Tmp1), 462 hipe_rtl:mk_alu(Offset, Offset, add, hipe_rtl:mk_imm(1)), 463 hipe_rtl:mk_load(Tmp1, Base, Offset, byte, Signedness), 464 hipe_rtl:mk_alu(Tmp1, Tmp1, sll, hipe_rtl:mk_imm(24)), 465 hipe_rtl:mk_alu(Dst, Dst, 'or', Tmp1), 466 hipe_rtl:mk_alu(Offset, Offset, add, hipe_rtl:mk_imm(1))]. 467 468-ifdef(STORE_4_NEEDED). 469store_4(Base, Offset, Src) -> 470 case get(hipe_target_arch) of 471 x86 -> 472 store_4_directly(Base, Offset, Src); 473 powerpc -> 474 store_4_directly(Base, Offset, Src); 475 ppc64 -> 476 store_4_directly(Base, Offset, Src); 477 arm -> 478 store_big_4_in_pieces(Base, Offset, Src); 479 ultrasparc -> 480 store_big_4_in_pieces(Base, Offset, Src); 481 amd64 -> 482 store_4_directly(Base, Offset, Src) 483 end. 484 485store_4_directly(Base, Offset, Src) -> 486 [hipe_rtl:mk_store(Base, Offset, Src, int32), 487 hipe_rtl:mk_alu(Offset, Offset, add, hipe_rtl:mk_imm(4))]. 488 489store_big_4_in_pieces(Base, Offset, Src) -> 490 [hipe_rtl:mk_alu(Offset, Offset, add, hipe_rtl:mk_imm(3)), 491 hipe_rtl:mk_store(Base, Offset, Src, byte), 492 hipe_rtl:mk_alu(Offset, Offset, sub, hipe_rtl:mk_imm(1)), 493 hipe_rtl:mk_alu(Src, Src, srl, hipe_rtl:mk_imm(8)), 494 hipe_rtl:mk_store(Base, Offset, Src, byte), 495 hipe_rtl:mk_alu(Offset, Offset, sub, hipe_rtl:mk_imm(1)), 496 hipe_rtl:mk_alu(Src, Src, srl, hipe_rtl:mk_imm(8)), 497 hipe_rtl:mk_store(Base, Offset, Src, byte), 498 hipe_rtl:mk_alu(Offset, Offset, sub, hipe_rtl:mk_imm(1)), 499 hipe_rtl:mk_alu(Src, Src, srl, hipe_rtl:mk_imm(8)), 500 hipe_rtl:mk_store(Base, Offset, Src, byte), 501 hipe_rtl:mk_alu(Offset, Offset, add, hipe_rtl:mk_imm(4))]. 502-endif. 503 504%%---------------------------------------------------------------------- 505%% Handling of arithmetic -- depends on the size of word. 506%%---------------------------------------------------------------------- 507 508eval_alu(Op, Arg1, Arg2) -> 509 %% io:format("Evaluated alu: ~w ~w ~w = ",[Arg1, Op, Arg2]), 510 Res = case word_size() of 511 4 -> 512 hipe_rtl_arith_32:eval_alu(Op, Arg1, Arg2); 513 8 -> 514 hipe_rtl_arith_64:eval_alu(Op, Arg1, Arg2) 515 end, 516 %% io:format("~w~n ",[Res]), 517 Res. 518 519-ifdef(EVAL_ALUB_NEEDED). 520eval_alub(Op, Cond, Arg1, Arg2) -> 521 %% io:format("Evaluated alub: ~w ~w ~w cond ~w = ",[Arg1, Op, Arg2, Cond]), 522 Res = case word_size() of 523 4 -> 524 hipe_rtl_arith_32:eval_alub(Op, Cond, Arg1, Arg2); 525 8 -> 526 hipe_rtl_arith_64:eval_alub(Op, Cond, Arg1, Arg2) 527 end, 528 %% io:format("~w~n ",[Res]), 529 Res. 530-endif. 531 532eval_cond(Cond, Arg1, Arg2) -> 533 %% io:format("Evaluated cond: ~w ~w ~w = ",[Arg1, Cond, Arg2]), 534 Res = case word_size() of 535 4 -> 536 hipe_rtl_arith_32:eval_cond(Cond, Arg1, Arg2); 537 8 -> 538 hipe_rtl_arith_64:eval_cond(Cond, Arg1, Arg2) 539 end, 540 %% io:format("~w~n ",[Res]), 541 Res. 542 543eval_cond_bits(Cond, N, Z, V, C) -> 544 %% io:format("Evaluated cond: ~w ~w ~w = ",[Arg1, Cond, Arg2]), 545 Res = case word_size() of 546 4 -> 547 hipe_rtl_arith_32:eval_cond_bits(Cond, N, Z, V, C); 548 8 -> 549 hipe_rtl_arith_64:eval_cond_bits(Cond, N, Z, V, C) 550 end, 551 %% io:format("~w~n ",[Res]), 552 Res. 553 554%%---------------------------------------------------------------------- 555 556fwait() -> 557 case ?ERTS_NO_FPE_SIGNALS of 558 1 -> []; 559 0 -> fwait_real() 560 end. 561 562fwait_real() -> 563 case get(hipe_target_arch) of 564 x86 -> [hipe_rtl:mk_call([], 'fwait', [], [], [], not_remote)]; 565 amd64 -> [hipe_rtl:mk_call([], 'fwait', [], [], [], not_remote)]; 566 arm -> []; 567 powerpc -> []; 568 ppc64 -> []; 569 ultrasparc -> [] 570 end. 571 572%% @spec handle_fp_exception() -> [term()] 573%% 574%% @doc 575%% Returns RTL code to restore the FPU after a floating-point exception. 576%% @end 577handle_fp_exception() -> 578 case ?ERTS_NO_FPE_SIGNALS of 579 1 -> []; 580 0 -> handle_real_fp_exception() 581 end. 582 583handle_real_fp_exception() -> 584 case get(hipe_target_arch) of 585 x86 -> 586 ContLbl = hipe_rtl:mk_new_label(), 587 [hipe_rtl:mk_call([], handle_fp_exception, [], 588 hipe_rtl:label_name(ContLbl), [], not_remote), 589 ContLbl]; 590 amd64 -> 591 ContLbl = hipe_rtl:mk_new_label(), 592 [hipe_rtl:mk_call([], handle_fp_exception, [], 593 hipe_rtl:label_name(ContLbl), [], not_remote), 594 ContLbl]; 595 arm -> 596 []; 597 powerpc -> 598 []; 599 ppc64 -> 600 []; 601 ultrasparc -> 602 [] 603 end. 604 605%% 606%% PCB accesses. 607%% Wrapped to avoid leaking the PCB pointer to the wrong places. 608%% 609 610pcb_load(Dst, Off) -> pcb_load(Dst, Off, word). 611 612pcb_load(Dst, Off, Size) -> 613 hipe_rtl:mk_load(Dst, proc_pointer(), hipe_rtl:mk_imm(Off), Size, unsigned). 614 615pcb_store(Off, Src) -> pcb_store(Off, Src, word). 616 617pcb_store(Off, Src, Size) -> 618 hipe_rtl:mk_store(proc_pointer(), hipe_rtl:mk_imm(Off), Src, Size). 619 620pcb_address(Dst, Off) -> 621 hipe_rtl:mk_alu(Dst, proc_pointer(), 'add', hipe_rtl:mk_imm(Off)). 622 623proc_pointer() -> % must not be exported 624 case get(hipe_target_arch) of 625 ultrasparc -> 626 hipe_rtl:mk_reg_gcsafe(hipe_sparc_registers:proc_pointer()); 627 powerpc -> 628 hipe_rtl:mk_reg_gcsafe(hipe_ppc_registers:proc_pointer()); 629 ppc64 -> 630 hipe_rtl:mk_reg_gcsafe(hipe_ppc_registers:proc_pointer()); 631 arm -> 632 hipe_rtl:mk_reg_gcsafe(hipe_arm_registers:proc_pointer()); 633 x86 -> 634 hipe_rtl:mk_reg_gcsafe(hipe_x86_registers:proc_pointer()); 635 amd64 -> 636 hipe_rtl:mk_reg_gcsafe(hipe_amd64_registers:proc_pointer()) 637 end. 638 639%% 640%% Special BIF calls. 641%% Wrapped to avoid leaking the PCB pointer to the wrong places, 642%% and to allow ARCH-specific expansion. 643%% 644 645call_bif(Dst, Name, Args, Cont, Fail) -> 646 hipe_rtl:mk_call(Dst, Name, Args, Cont, Fail, not_remote). 647 648nr_of_return_regs() -> 649 case get(hipe_target_arch) of 650 ultrasparc -> 651 1; 652 %% hipe_sparc_registers:nr_rets(); 653 powerpc -> 654 1; 655 ppc64 -> 656 1; 657 %% hipe_ppc_registers:nr_rets(); 658 arm -> 659 1; 660 x86 -> 661 hipe_x86_registers:nr_rets(); 662 amd64 -> 663 1 664 %% hipe_amd64_registers:nr_rets(); 665 end. 666 667 668mk_fp_check_result(Result) -> 669 case ?ERTS_NO_FPE_SIGNALS of 670 0 -> 671 []; 672 1 -> 673 [hipe_rtl:mk_fstore(proc_pointer(), 674 hipe_rtl:mk_imm(?P_FLOAT_RESULT), 675 Result), 676 hipe_rtl:mk_call([], emulate_fpe, [], [], [], not_remote)] 677 end. 678