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