1
%% -*- erlang-indent-level: 2 -*-
2
%% =====================================================================
3
%% Copyright (c) 1997 by the HiPE group. All Rights Reserved
4
%% =====================================================================
5
%% Filename : hipe_sparc.erl
6
%% Purpose : Provides primitives for handling SPARC instructions.
8
%% =====================================================================
10
%% @doc Provides primitives for handling SPARC instructions.
11
%% <h3>Basic types</h3>
13
%% <li>{@link sparc()}</li>
14
%% <li>{@link sparc_instruction()}</li>
15
%% <li>{@link mfa()}</li>
16
%% <li>{@link fa()}</li>
18
%% <h3>Basic instructions</h3>
20
%% <li>{@link label()}</li>
21
%% <li>{@link nop()}</li>
22
%% <li>{@link comment()}</li>
23
%% <li>{@link move()}</li>
24
%% <li>{@link multimove()}</li>
25
%% <li>{@link alu()}</li>
26
%% <li>{@link alu_cc()}</li>
27
%% <li>{@link sethi()}</li>
28
%% <li>{@link load()}</li>
29
%% <li>{@link store()}</li>
30
%% <li>{@link b()}</li>
31
%% <li>{@link goto()}</li>
32
%% <li>{@link jmp_link()}</li>
33
%% <li>{@link jmp()}</li>
34
%% <li>{@link call_link()}</li>
35
%% <li>{@link load_address()}</li>
36
%% <li>{@link load_atom()}</li>
37
%% <li>{@link load_word_index()}</li>
39
%% <h3>Floating-point instructions</h3>
41
%% <li>{@link load_fp()}</li>
42
%% <li>{@link store_fp()}</li>
43
%% <li>{@link fop()}</li>
44
%% <li>{@link fmove()}</li>
45
%% <li>{@link conv_fp()}</li>
47
%% <h3>Pseudo instructions</h3>
49
%% <li>{@link pseudo_return()}</li>
50
%% <li>{@link pseudo_enter()}</li>
51
%% <li>{@link pseudo_pop()}</li>
52
%% <li>{@link pseudo_spill()}</li>
53
%% <li>{@link pseudo_unspill()}</li>
55
%% <h3>Field types</h3>
57
%% <li>{@link operand()}</li>
58
%% <li>{@link src()}</li>
59
%% <li>{@link reg()}</li>
60
%% <li>{@link fp_reg()}</li>
61
%% <li>{@link imm()}</li>
62
%% <li>{@link aluop()}</li>
63
%% <li>{@link condition_code()}</li>
64
%% <li>{@link label_name()}</li>
65
%% <li>{@link load_type()}</li>
66
%% <li>{@link store_type()}</li>
67
%% <li>{@link prediction()}</li>
68
%% <li>{@link annulbit()}</li>
69
%% <li>{@link call_type()}</li>
70
%% <li>{@link target()}</li>
71
%% <li>{@link la_type()}</li>
72
%% <li>{@link la_addr()}</li>
73
%% <li>{@link fp_type()}</li>
74
%% <li>{@link fp_cond()}</li>
75
%% <li>{@link fp_op()}</li>
78
%% (Not currently used: pseudo_push(), align(), cmov_cc(), cmov_r(),
79
%% br(), fb(), fcmp(), fcc_reg().)
84
%% A datastructure for SPARC code for one function.
85
%% <p>Has the following properties
87
%% <li>{@type FunctionName::mfa()} -- Name of the function.</li>
88
%% <li><code>Arity::integer()</code> -- This is needed since the arity
89
%% in the function name might differ from the real arity. </li>
90
%% <li><code>IsClosure::bool()</code> -- True if this is the code for
92
%% <li><code>IsLeaf::bool()</code> -- True if this is a "leaf
94
%% <li><code>Code::[sparc_instruction()]</code> -- List of sparc
95
%% instructions. </li>
96
%% <li><code>Data::hipe_consttab:const_tab()</code> -- Data
98
%% <li><code>VarRange::{integer(),integer()}</code> -- First and last
99
%% name of reg/fp_reg.</li>
100
%% <li><code>LabelRange::{integer(),integer()}</code> -- First and
101
%% last labelname in the code.</li>
104
%% @type mfa()=hipe:mfa(). Name of a function in any module.
105
%% @type fa()={Function::atom(), Arity::integer()}. Name of a local function.
106
%% @type sparc_instruction() =
124
%% | load_word_index()
134
%% | pseudo_unspill()
135
%% This datatype defines all the different SPARC instructions that
138
%% (Not currently used: pseudo_push(), align(), cmov_cc(), cmov_r(),
139
%% br(), fb(), fcmp().)
141
%% Instruction types:
143
%% @type label(). See {@link label_create/1}.
144
%% @type nop(). See {@link nop_create/0}.
145
%% @type comment(). See {@link comment_create/1}.
146
%% @type move(). See {@link move_create/2}.
147
%% @type multimove(). See {@link multimove_create/2}.
148
%% @type alu(). See {@link alu_create/4}.
149
%% @type alu_cc(). See {@link alu_cc_create/4}.
150
%% @type sethi(). See {@link sethi_create/2}.
151
%% @type load(). See {@link load_create/3}.
152
%% @type store(). See {@link store_create/3}.
153
%% @type b(). See {@link b_create/5}.
154
%% @type goto(). See {@link goto_create/1}.
155
%% @type jmp_link(). See {@link jmp_link_create/4}.
156
%% @type jmp(). See {@link jmp_create/4}.
157
%% @type call_link(). See {@link call_link_create/5}.
158
%% @type load_address(). See {@link load_address_create/3}.
159
%% @type load_atom(). See {@link load_atom_create/2}.
160
%% @type load_word_index(). See {@link load_word_index_create/3}.
162
%% (Not currently used: cmov_r(), cmov_cc(), br().)
164
%% Floating-point instructions:
166
%% @type load_fp(). See {@link load_fp_create/3}.
167
%% @type store_fp(). See {@link store_fp_create/3}.
168
%% @type fop(). See {@link fop_create/4}.
169
%% @type fmove(). See {@link fmove_create/2}.
170
%% @type conv_fp(). See {@link conv_fp_create/2}.
172
%% (Not currently used: fb(), fcmp().)
174
%% Pseudo instructions:
176
%% @type pseudo_return(). See {@link pseudo_return_create/1}.
177
%% @type pseudo_enter(). See {@link pseudo_enter_create/2}.
178
%% @type pseudo_pop(). See {@link pseudo_pop_create/2}.
179
%% @type pseudo_spill(). See {@link pseudo_spill_create/2}.
180
%% @type pseudo_unspill(). See {@link pseudo_unspill_create/2}.
182
%% (Not currently used: pseudo_push().)
186
%% @type operand() = src() | fp_reg()
187
%% @type src() = reg() | imm()
188
%% @type reg() = {sparc_reg, Name::integer()}
189
%% @type fp_reg() = {sparc_fpreg, Name::integer()}
190
%% @end (Not used) @type fcc_reg() = 0 | 1 | 2 | 3
191
%% @type imm() = {sparc_imm, Value::integer()}
193
%% '+' | '-' | '+c' | '-c' | 'and' | 'andn' | 'or'
194
%% | 'xor' | 'xnor' | '>>' | '>>64' | '>>?' | '>>?64'
196
%% @type condition_code() =
197
%% 'a' | 'n' | 'ne' | 'e' | 'g' | 'le' | 'ge' | 'l' | 'gu'
198
%% | 'leu' | 'geu' | 'lu' | 'pos' | 'neg' | 'vc' | 'vs'
199
%% @type label_name(). At the moment it is safe to assume this is an integer...
200
%% @type load_type() = uw | sb | sh | sw | ub | uh | x
201
%% @type store_type() = b | h | w | x
202
%% @type prediction() = float(). The value must be between 0 and 1, inclusive.
203
%% @type annulbit() = a | na
204
%% @type call_type() = closure | c
205
%% @type target() = reg() | mfa() | fa() | atom()
206
%% @type la_type() = function | constant | label | closure
207
%% @type la_addr() = mfa() | fa() | atom() | hipe_consttab:lbl() |
209
%% This type is dependent on la_type().
211
%% <li>la_type == function --
212
%% la_addr() = mfa() | fa() | atom()</li>
213
%% <li>la_type == constant --
214
%% la_addr() = hipe_consttab:lbl()</li>
215
%% <li>la_type == label --
216
%% la_addr() = label_name()</li>
217
%% <li>la_type == closure --
218
%% la_addr() = label_name()</li>
220
%% @type fp_type() = single | double | quad
221
%% @type fp_cond() = 'a' | 'n' | 'u' | 'g' | 'ug' | 'l' | 'ul' | 'lg'
222
%% | 'ne' | 'e' | 'ue' | 'ge' | 'uge'
223
%% | 'le' | 'ule' | 'o'
224
%% @type fp_op() = '+' | '-' | '*'
226
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
229
-export([mk_sparc/8, %% mk_sparc/6,
230
sparc_fun/1, sparc_arity/1, sparc_is_closure/1,
231
sparc_is_leaf/1, sparc_code/1, sparc_code_update/2, sparc_data/1,
232
%% sparc_data_update/2, sparc_var_range/1,
233
sparc_var_range_update/2,
234
%% sparc_label_range/1,
235
sparc_label_range_update/2 %%, sparc_size/1
237
-export([store_create/3, store_create/4, store_dest/1, store_dest_update/2,
238
store_off/1, store_off_update/2, store_src/1, store_src_update/2,
239
store_type/1 %% store_type_update/2
241
-export([jmp_link_create/4,
242
jmp_link_off/1, %% jmp_link_off_update/2,
243
jmp_link_target/1, %% jmp_link_target_update/2,
244
jmp_link_args/1, %% jmp_link_args_update/2,
245
jmp_link_link/1, %% jmp_link_link_update/2,
248
jmp_off/1, %% jmp_off_update/2,
249
jmp_target/1, %% jmp_target_update/2,
250
jmp_args/1, %% jmp_args_update/2,
251
jmp_destinations/1, %% jmp_destinations_update/2,
252
call_link_create/6, call_link_create/7,
253
call_link_target/1, call_link_target_update/2,
254
call_link_link/1, %% call_link_link_update/2,
255
call_link_args/1, %% call_link_args_update/2,
257
call_link_continuation/1, call_link_continuation_update/2,
258
call_link_fail/1, call_link_fail_update/2,
260
call_link_is_known/1,
261
call_link_stack_desc/1, call_link_stack_desc_update/2,
262
label_create/1, label_create_new/0,
263
label_name/1, %% label_name_update/2,
265
load_atom_dest/1, %% load_atom_dest_update/2,
267
load_word_index_create/3,
268
load_word_index_dest/1, %% load_word_index_dest_update/2,
269
load_word_index_index/1, load_word_index_block/1,
270
load_address_create/3,
271
load_address_addr/1, load_address_addr_update/2,
272
load_address_type/1, %% load_address_type_update/2,
273
load_address_dest/1, %% load_address_dest_update/2,
274
load_create/3, load_create/4,
275
load_dest/1, %% load_dest_update/2,
276
load_off/1, load_off_update/2,
277
load_src/1, load_src_update/2,
278
load_type/1, %% load_type_update/2,
279
move_create/2, move_dest/1, move_dest_update/2,
280
move_src/1, %% move_src_update/2,
281
multimove_create/2, multimove_dest/1, %% multimove_dest_update/2,
282
multimove_src/1, %% multimove_src_update/2,
284
rdy_create/1, rdy_dest/1,
285
sethi_const/1, %% sethi_const_update/2,
286
sethi_dest/1, %% sethi_dest_update/2,
288
-export([load_fp_create/3,
290
load_fp_dest/1, %% load_fp_dest_update/2,
292
load_fp_off/1, %% load_fp_off_update/2,
293
load_fp_src/1, %% load_fp_src_update/2,
294
load_fp_type/1 %% load_fp_type_update/2
296
-export([store_fp_create/3,
298
store_fp_dest/1, %% store_fp_dest_update/2,
299
store_fp_off/1, %% store_fp_off_update/2,
301
store_fp_src/1, %% store_fp_src_update/2,
302
store_fp_type/1 %% store_fp_type_update/2
305
-export([%% fb_create/7,
308
%% fb_annul_update/2,
312
%% fb_fcc_reg_update/2,
314
%% fb_label_update/2,
316
%% fb_true_label_update/2,
318
%% fb_false_label_update/2,
324
-export([fop_create/4,
327
%% fop_dest_update/2,
329
%% fop_type_update/2,
331
%% fop_operator_update/2,
333
%% fop_src1_update/2,
338
-export([%% fcmp_create/3,
345
%% fcmp_fcc_reg_update/2,
346
%% fcmp_type_update/2,
347
%% fcmp_src1_update/2,
348
%% fcmp_src2_update/2,
349
%% fcmp_exception_update/2
352
-export([fmove_create/2,
357
%% fmove_type_update/2,
359
%% fmove_src_update/2,
363
-export([conv_fp_create/2,
368
%% conv_fp_dest_update/2,
369
%% conv_fp_dest_type_update/2,
370
%% conv_fp_src_update/2
374
-export([pseudo_return_create/1, %% pseudo_return_create/2,
375
pseudo_return_regs/1, %% pseudo_return_regs_update/2,
376
pseudo_enter_create/3,
377
pseudo_enter_target/1, %% pseudo_enter_target_update/2,
379
pseudo_enter_is_known/1,
380
pseudo_enter_args/1, %% pseudo_enter_args_update/2,
381
pseudo_spill_create/2, %% pseudo_spill_create/3,
384
pseudo_unspill_create/2, %% pseudo_unspill_create/3,
385
pseudo_unspill_reg/1, pseudo_unspill_pos/1,
386
%% pseudo_push_create/1, pseudo_push_create/2,
387
% pseudo_push_reg/1, pseudo_push_reg_update/2,
388
pseudo_pop_create/2, %% pseudo_pop_create/3,
389
pseudo_pop_reg/1, pseudo_pop_index/1 %%, pseudo_pop_reg_update/2
391
-export([%%align_alignment/1, align_alignment_update/2, align_create/2,
392
alu_cc_create/4, alu_cc_dest/1, %% alu_cc_dest_update/2,
393
alu_cc_operator/1, %% alu_cc_operator_update/2,
394
alu_cc_src1/1, alu_cc_src1_update/2,
395
alu_cc_src2/1, alu_cc_src2_update/2,
396
alu_create/4, alu_dest/1, %% alu_dest_update/2,
397
alu_operator/1, %% alu_operator_update/2,
398
alu_src1/1, alu_src1_update/2, alu_src2/1, alu_src2_update/2,
400
b_annul/1, %% b_annul_update/2,
401
b_cond/1, %% b_cond_update/2,
402
b_label/1, b_label_update/2, b_true_label/1, %% b_true_label_update/2,
403
b_false_label/1, b_false_label_update/2, b_pred/1, %% b_pred_update/2,
406
%% br_annul/1, %% br_annul_update/2,
407
%% br_label/1, %% br_label_update/2,
408
%% br_true_label/1, %% br_true_label_update/2,
409
%% br_false_label/1, br_false_label_update/2,
410
%% br_pred/1, %% br_pred_update/2,
412
%% br_reg/1, %% br_reg_update/2,
413
%% br_regcond/1, %% br_regcond_update/2,
414
goto_create/1, goto_label/1, goto_label_update/2, is_goto/1,
415
%% cmov_cc_cond/1, cmov_cc_cond_update/2, cmov_cc_create/4,
416
%% cmov_cc_dest/1, cmov_cc_dest_update/2,
417
%% cmov_cc_src/1, cmov_cc_src_update/2,
419
%% cmov_r_dest/1, cmov_r_dest_update/2, cmov_r_reg/1,
420
%% cmov_r_reg_update/2, cmov_r_regcond/1, cmov_r_regcond_update/2,
421
%% cmov_r_src/1, cmov_r_src_update/2,
423
comment_text/1, %% comment_text_update/2,
424
%% is_align/1, is_alu/1, is_alu_cc/1,
426
is_any_branch/1, has_delayslot/1,
427
%% is_any_cmov/1, is_any_memop/1,
429
is_call_link/1, %% is_cmov_cc/1, is_cmov_r/1,
430
is_comment/1, %% is_jmp/1, is_jmp_link/1,
431
is_label/1, is_load/1, is_move/1,
432
%% is_multimove/1, is_nop/1,
433
%% is_sethi/1, is_load_fp/1,
434
%% is_store_fp/1, is_fb/1, is_fop/1, is_fcmp/1,
435
is_fmove/1, is_conv_fp/1, is_store/1]).
436
-export([redirect_jmp/3, cc_negate/1, %% fcc_negate/1,
437
uses/1, defines/1, def_use/1,
440
fp_reg_uses/1, fp_reg_defines/1,
441
%% fpreg_and_regs_defines/1,
442
%% fpregs_and_regs_def_use/1, fpregs_and_regs_uses/1,
443
subst/2, subst_uses/2, subst_defines/2, keep_registers/1,
444
keep_fp_registers/1 %%, fp_reg_def_use/1
446
-export([mk_reg/1, mk_new_reg/0, is_reg/1, reg_nr/1, mk_fpreg/1,
447
mk_new_fpreg/0, is_fpreg/1, fpreg_nr/1, mk_imm/1,
448
is_imm/1, imm_value/1, %% mk_spill/1,
449
is_spill/1, spill_pos/1]).
451
%%-define(DO_ASSERT,true).
452
-include("../main/hipe.hrl").
453
-include("hipe_sparc_sdesc.hrl").
454
-include("hipe_sparc.hrl").
456
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
461
%% @spec mk_sparc(Fun::mfa(), Arity::integer(), Closure::bool(),
462
%% Leaf::bool(), Code::[sparc_instruction()] ,
463
%% Data::hipe_consttab:const_tab(),
464
%% VarRange::{integer(),integer()} ,
465
%% LabelRange::{integer(),integer()}
467
mk_sparc(Fun, Arity, Closure, Leaf, Code, Data, VarRange, LabelRange) ->
469
arity=Arity, closure=Closure, leaf=Leaf,
470
code=Code, data=Data, var_range=VarRange, label_range=LabelRange}.
471
%% %% @spec mk_sparc(Fun::mfa(), Arity::integer(),
472
%% %% Code::[sparc_instruction()] ,
473
%% %% Data::hipe_consttab:const_tab(),
474
%% %% VarRange::{integer(),integer()} ,
475
%% %% LabelRange::{integer(),integer()}
477
%% mk_sparc(Fun, Arity, Code, Data, VarRange, LabelRange) ->
479
%% arity=Arity, closure=false, leaf=false,
480
%% code=Code, data=Data, var_range=VarRange, label_range=LabelRange}.
482
%% @spec sparc_fun(Sparc::sparc()) -> mfa()
483
sparc_fun(#sparc{'fun'=Fun}) -> Fun.
484
%% @spec sparc_arity(Sparc::sparc()) -> integer()
485
sparc_arity(#sparc{arity=Arity}) when is_integer(Arity), 0 =< Arity -> Arity.
486
%% @spec (Sparc::sparc()) -> bool()
487
sparc_is_closure(#sparc{closure=IsClosure}) -> IsClosure.
488
%% @spec (Sparc::sparc()) -> bool()
489
sparc_is_leaf(#sparc{leaf=IsLeaf}) -> IsLeaf.
490
%% @spec (Sparc::sparc()) -> [sparc_instruction()]
491
sparc_code(#sparc{code=Code}) -> Code.
492
%% @spec (Sparc::sparc(),Code::[sparc_instruction()]) -> sparc()
493
sparc_code_update(Sparc, NewCode) -> Sparc#sparc{code=NewCode}.
494
%% @spec (Sparc::sparc()) -> hipe_consttab:const_tab()
495
sparc_data(#sparc{data=Data}) -> Data.
496
%% %% @spec (Sparc::sparc(),Data::hipe_consttab:const_tab()) -> sparc()
497
%% sparc_data_update(Sparc, NewData) -> Sparc#sparc{data=NewData}.
499
%% @spec (Sparc::sparc()) -> {integer(),integer()}
500
sparc_var_range(#sparc{var_range=VarRange}) -> VarRange.
503
%% @spec (Sparc::sparc(), NewRange::{integer(),integer()}) -> sparc()
504
sparc_var_range_update(Sparc, NewRange) ->
505
NewSparc = Sparc#sparc{var_range=NewRange},
506
?ASSERT(check_var_range(NewSparc)),
508
%% %% @spec (Sparc::sparc()) -> {integer(),integer()}
509
%% sparc_label_range(#sparc{label_range=LabelRange}) -> LabelRange.
510
%% @spec (Sparc::sparc(), NewRange::{integer(),integer()}) -> sparc()
511
sparc_label_range_update(Sparc, NewRange) -> Sparc#sparc{label_range=NewRange}.
512
%% %% @spec (Sparc::sparc()) -> integer()
513
%% %% @doc Returns the number of instructions in the SPARC code.
514
%% %% <strong> Note: This is not guaranteed to correspond to the actual
515
%% %% memory footprint of the SPARC code.</strong>
516
%% sparc_size(Sparc) ->
517
%% RealIns = fun(I) -> not(is_label(I) or is_comment(I)) end,
518
%% length(lists:filter(RealIns, sparc_code(Sparc))).
521
%% Enter - pseudo op %
522
%% @spec (Target::target(), Args::[reg()], Type::atom()) -> pseudo_enter()
523
pseudo_enter_create(Target, Args, Type) ->
528
#pseudo_enter{target=Target, args=Args, type=Type}.
529
pseudo_enter_args(#pseudo_enter{args=Args}) ->
531
pseudo_enter_args_update(I,Args) ->
532
I#pseudo_enter{args=Args}.
533
pseudo_enter_target(#pseudo_enter{target=Target}) ->
535
pseudo_enter_target_update(I,Target) ->
536
I#pseudo_enter{target=Target}.
537
pseudo_enter_type(#pseudo_enter{type=Type}) ->
539
pseudo_enter_is_known(I) ->
540
not is_reg(pseudo_enter_target(I)).
543
%% Return - pseudo op %
544
pseudo_return_create(Regs) ->
545
#pseudo_return{regs=Regs}.
546
pseudo_return_regs(#pseudo_return{regs=Regs}) ->
548
pseudo_return_regs_update(I,Regs) ->
549
I#pseudo_return{regs=Regs}.
552
%% Push - pseudo op %
553
%% pseudo_push_create(Reg) ->
554
%% #pseudo_push{reg=Reg}.
555
%% pseudo_push_reg(#pseudo_push{reg=Reg}) ->
557
%% pseudo_push_reg_update(I,Reg) ->
558
%% I#pseudo_push{reg=Reg}.
561
pseudo_pop_create(Reg, Index) ->
562
#pseudo_pop{reg=Reg, index=Index}.
563
pseudo_pop_reg(#pseudo_pop{reg=Reg}) ->
565
pseudo_pop_index(#pseudo_pop{index=Index}) ->
567
pseudo_pop_reg_update(I,Reg) ->
568
I#pseudo_pop{reg=Reg}.
570
%% spill - pseudo op %
571
pseudo_spill_create(Reg1, Pos) ->
572
#pseudo_spill{source=Reg1, dest=Pos}.
573
pseudo_spill_reg(#pseudo_spill{source=Src}) ->
575
pseudo_spill_pos(#pseudo_spill{dest=Dst}) ->
577
pseudo_spill_reg_update(I,Reg) ->
578
I#pseudo_spill{source=Reg}.
580
%% unspill - pseudo op %
581
pseudo_unspill_create(Reg1, Pos) ->
582
#pseudo_unspill{source=Reg1, dest=Pos}.
583
pseudo_unspill_reg(#pseudo_unspill{source=Src}) ->
585
pseudo_unspill_pos(#pseudo_unspill{dest=Dst}) ->
587
pseudo_unspill_reg_update(I,Reg) ->
588
I#pseudo_unspill{source=Reg}.
592
%% @spec (Dest::reg(),Atom::atom()) -> load_atom()
593
load_atom_create(Dest,Atom) ->
594
?ASSERT(is_reg(Dest)),
595
#load_atom{dst=Dest,atom=Atom}.
596
load_atom_dest(#load_atom{dst=Dst}) -> Dst.
597
load_atom_atom(#load_atom{atom=Atom}) -> Atom.
598
load_atom_dest_update(LA, NewDest) -> LA#load_atom{dst=NewDest}.
600
%% @spec (Dest::reg(),Block::term(),Index::integer()) -> load_word_index()
601
load_word_index_create(Dst,Block,Index) ->
602
?ASSERT(is_reg(Dest)),
603
#load_word_index{dst=Dst, block=Block, index=Index}.
604
load_word_index_dest(#load_word_index{dst=Dst}) -> Dst.
605
load_word_index_dest_update(LA, NewDest) -> LA#load_word_index{dst=NewDest}.
606
load_word_index_block(#load_word_index{block=Block}) -> Block.
607
load_word_index_index(#load_word_index{index=Index}) -> Index.
612
%% @spec (Dst::reg(),Addr::la_addr(), Type::la_type()) -> load_address()
613
load_address_create(Dst, Addr, Type) ->
614
#load_address{dst=Dst, addr=Addr, type=Type}.
615
load_address_dest(#load_address{dst=Dst}) -> Dst.
616
load_address_dest_update(LA, NewDst) -> LA#load_address{dst=NewDst}.
617
load_address_addr(#load_address{addr=Addr}) -> Addr.
618
load_address_addr_update(LoadAddress, NewA) -> LoadAddress#load_address{addr=NewA}.
619
load_address_type(#load_address{type=Type}) -> Type.
620
%% load_address_type_update(LA, NewType) -> LA#load_address{type=NewType}.
626
%% @spec (Name::label_name()) -> label()
627
label_create(Name) -> #label{id=Name}.
628
%% @spec () -> label()
629
label_create_new() -> label_create(hipe_gensym:get_next_label(sparc)).
630
%% @spec (label()) -> label_name()
631
label_name(#label{id=Name}) -> Name.
632
%% %% @spec (label(),label_name()) -> label()
633
%% label_name_update(Label,NewName) -> Label#label{id=NewName}.
634
%% @spec (sparc_instruction()) -> bool()
635
is_label(Insn) -> case Insn of #label{} -> true; _ -> false end.
642
nop_create() -> #nop{}.
643
%% %% @spec (sparc_instruction()) -> bool()
644
%% is_nop(Insn) -> case Insn of #nop{} -> true; _ -> false end.
648
%% %% @spec (integer()) -> align()
649
%% align_create(Number) -> #align{alignment=Number}.
650
%% %% @spec (align()) -> integer()
651
%% align_alignment(#align{alignment=Number}) -> Number.
652
%% %% @spec (align(),integer()) -> align()
653
%% align_alignment_update(Align,NewNumber) -> Align#align{alignment=NewNumber}.
654
%% %% @spec (sparc_instruction()) -> bool()
655
%% is_align(Insn) -> case Insn of #align{} -> true; _ -> false end.
658
%% @spec (Text::string()) -> comment()
659
comment_create(Text) -> #comment{text=Text}.
660
%% @spec (comment()) -> string()
661
comment_text(#comment{text=Text}) -> Text.
662
%% %% @spec (comment(), Text::string()) -> comment()
663
%% comment_text_update(Comment, NewText) -> Comment#comment{text=NewText}.
664
%% @spec (sparc_instruction()) -> bool()
665
is_comment(Insn) -> case Insn of #comment{} -> true; _ -> false end.
668
%% @spec (Dst::reg(), Src::src()) -> move()
669
move_create(Dst, Src) -> #move{dst=Dst, src=Src}.
670
move_src(#move{src=Src}) -> Src.
671
move_src_update(Move, NewSource) -> Move#move{src=NewSource}.
672
move_dest(#move{dst=Dst}) -> Dst.
673
move_dest_update(Move, NewDest) -> Move#move{dst=NewDest}.
674
%% @spec (sparc_instruction()) -> bool()
675
is_move(Insn) -> case Insn of #move{} -> true; _ -> false end.
678
%% @spec (Dsts::[reg()], Srcs::[reg()]) -> multimove()
679
multimove_create(Dest, Source) ->
680
?ASSERT(length(Dest) =:= length(Source)),
681
#multimove{dst=Dest, src=Source}.
682
multimove_dest(#multimove{dst=DstList}) -> DstList.
683
multimove_dest_update(Move, NewDest) -> Move#multimove{dst=NewDest}.
684
multimove_src(#multimove{src=SrcList}) -> SrcList.
685
multimove_src_update(Move, NewSource) -> Move#multimove{src=NewSource}.
686
%% %% @spec (sparc_instruction()) -> bool()
687
%% is_multimove(Insn) -> case Insn of #multimove{} -> true; _ -> false end.
690
%% %% cmov_cc_create(Dest,Source,Cond) ->
691
%% #cmov_cc{dst=Dest,src=Source,cc=Cond}.
692
%% cmov_cc_dest(#cmov_cc{dst=Dst}) -> Dst.
693
%% cmov_cc_src(#cmov_cc{src=Src}) -> Src.
694
%% cmov_cc_cond(#cmov_cc{cc=Cond}) -> Cond.
695
%% cmov_cc_dest_update(CmovCc,NewDest) -> CmovCc#cmov_cc{dst=NewDest}.
696
%% cmov_cc_src_update(CmovCc,NewSource) -> CmovCc#cmov_cc{src=NewSource}.
697
%% cmov_cc_cond_update(CmovCc,NewCond) -> CmovCc#cmov_cc{cc=NewCond}.
700
%% %% cmov_r_create(Dest,Source,Reg,RegCond) ->
701
%% #cmov_r{dst=Dest,src=Source,rcc=RegCond,reg=Reg}.
702
%% cmov_r_dest(#cmov_r{dst=Dst}) -> Dst.
703
%% cmov_r_src(#cmov_r{src=Src}) -> Src.
704
%% cmov_r_reg(#cmov_r{reg=Reg}) -> Reg.
705
%% cmov_r_regcond(#cmov_r{rcc=RegCond}) -> RegCond.
706
%% cmov_r_dest_update(CmovR,NewDest) -> CmovR#cmov_r{dst=NewDest}.
707
%% cmov_r_src_update(CmovR,NewSource) -> CmovR#cmov_r{src=NewSource}.
708
%% cmov_r_reg_update(CmovR,NewReg) -> CmovR#cmov_r{reg=NewReg}.
709
%% cmov_r_regcond_update(CmovR,NewRegCond) -> CmovR#cmov_r{rcc=NewRegCond}.
710
%% %% @spec (sparc_instruction()) -> bool()
711
%% is_cmov_r(Insn) -> case Insn of #cmov_r{} -> true; _ -> false end.
714
alu_create(Dest,Src1,Op,Src2) ->
715
#alu{dst=Dest,src1=Src1,src2=Src2,op=Op}.
716
alu_dest(#alu{dst=Dst}) -> Dst.
717
alu_src1(#alu{src1=Src1}) -> Src1.
718
alu_operator(#alu{op=Op}) -> Op.
719
alu_src2(#alu{src2=Src2}) -> Src2.
720
alu_dest_update(Alu,NewDest) -> Alu#alu{dst=NewDest}.
721
alu_src1_update(Alu,NewSource1) -> Alu#alu{src1=NewSource1}.
722
%% alu_operator_update(Alu,NewOp) -> Alu#alu{op=NewOp}.
723
alu_src2_update(Alu,NewSource2) -> Alu#alu{src2=NewSource2}.
724
%% %% @spec (sparc_instruction()) -> bool()
725
%% is_alu(Insn) -> case Insn of #alu{} -> true; _ -> false end.
728
alu_cc_create(Dest,Src1,Op,Src2) ->
729
#alu_cc{dst=Dest,src1=Src1,src2=Src2,op=Op}.
730
alu_cc_dest(#alu_cc{dst=Dst}) -> Dst.
731
alu_cc_src1(#alu_cc{src1=Src1}) -> Src1.
732
alu_cc_operator(#alu_cc{op=Op}) -> Op.
733
alu_cc_src2(#alu_cc{src2=Src2}) -> Src2.
734
alu_cc_dest_update(Alu,NewDest) -> Alu#alu_cc{dst=NewDest}.
735
alu_cc_src1_update(Alu,NewSource1) -> Alu#alu_cc{src1=NewSource1}.
736
%% alu_cc_operator_update(Alu,NewOp) -> Alu#alu_cc{op=NewOp}.
737
alu_cc_src2_update(Alu,NewSource2) -> Alu#alu_cc{src2=NewSource2}.
738
%% %% @spec (sparc_instruction()) -> bool()
739
%% is_alu_cc(Insn) -> case Insn of #alu_cc{} -> true; _ -> false end.
742
rdy_create(Dest) -> #rdy{dst=Dest}.
743
rdy_dest(#rdy{dst=Dst}) -> Dst.
744
rdy_dest_update(Rdy,NewDest) -> Rdy#rdy{dst=NewDest}.
747
sethi_create(Dest,Const) -> #sethi{dst=Dest,const=Const}.
748
sethi_dest(#sethi{dst=Dst}) -> Dst.
749
sethi_const(#sethi{const=Const}) -> Const.
750
sethi_dest_update(SetHi,NewDest) -> SetHi#sethi{dst=NewDest}.
751
%% sethi_const_update(SetHi,NewConst) -> SetHi#sethi{const=NewConst}.
754
load_create(Dest,Source,Off) ->
755
#load{dst=Dest,type=uw,src=Source,off=Off}.
756
load_create(Dest,Type,Source,Off) ->
757
?ASSERT((Type =:= uw) orelse (Type =:= ub) orelse (Type =:= uh) orelse
758
(Type =:= sw) orelse (Type =:= sb) orelse (Type =:= sh) orelse
760
#load{dst=Dest,type=Type,src=Source,off=Off}.
761
load_dest(#load{dst=Dst}) -> Dst.
762
load_type(#load{type=Type}) -> Type.
763
load_src(#load{src=Src}) -> Src.
764
load_off(#load{off=Offset}) -> Offset.
765
load_dest_update(Load,NewDest) -> Load#load{dst=NewDest}.
766
%% load_type_update(Load,NewType) -> Load#load{type=NewType}.
767
load_src_update(Load,NewSource) -> Load#load{src=NewSource}.
768
load_off_update(Load,NewOff) -> Load#load{off=NewOff}.
769
%% @spec (sparc_instruction()) -> bool()
770
is_load(Insn) -> case Insn of #load{} -> true; _ -> false end.
773
store_create(Target,Off,Source) ->
774
#store{dst=Target,type=w,src=Source,off=Off}.
775
store_create(Target,Off,Type,Source) ->
776
?ASSERT((Type =:= w) orelse (Type =:= b) orelse (Type =:= h) orelse
778
#store{dst=Target,type=Type,src=Source,off=Off}.
779
store_dest(#store{dst=Dst}) -> Dst.
780
store_off(#store{off=Offset}) -> Offset.
781
store_type(#store{type=Type}) -> Type.
782
store_src(#store{src=Src}) -> Src.
783
store_dest_update(Store,NewTarget) -> Store#store{dst=NewTarget}.
784
store_off_update(Store,NewOff) -> Store#store{off=NewOff}.
785
%% store_type_update(Store,NewType) -> Store#store{type=NewType}.
786
store_src_update(Store,NewSource) -> Store#store{src=NewSource}.
787
%% @spec (sparc_instruction()) -> bool()
788
is_store(Insn) -> case Insn of #store{} -> true; _ -> false end.
791
b_create(Cond,TrueLabel,FalseLabel,Pred,Annul) ->
792
#b{cc=Cond,true_label=TrueLabel,false_label=FalseLabel, pred=Pred,
794
b_cond(#b{cc=Cond}) -> Cond.
795
%% b_cond_update(B,NewCond) -> B#b{cc=NewCond}.
796
b_label(B) -> b_true_label(B).
797
b_label_update(B,NewLabel) -> b_true_label_update(B,NewLabel).
798
b_true_label(#b{true_label=TrueLabel}) -> TrueLabel.
799
b_true_label_update(B,NewLabel) -> B#b{true_label=NewLabel}.
800
b_false_label(#b{false_label=FalseLabel}) -> FalseLabel.
801
b_false_label_update(B,NewLabel) -> B#b{false_label=NewLabel}.
802
b_pred(#b{pred=Pred}) -> Pred.
803
%% b_pred_update(B,NewPred) -> B#b{pred=NewPred}.
804
%% b_annul_update(B,NewAnnul) -> B#b{annul=NewAnnul}.
805
b_annul(#b{annul=Annul}) -> Annul.
806
b_taken(B) -> P = b_pred(B), if P > 0.5 -> true; true -> false end.
807
%% %% @spec (sparc_instruction()) -> bool()
808
%% is_b(Insn) -> case Insn of #b{} -> true; _ -> false end.
811
%% br_create(Reg,RegCond,TrueLabel,FalseLabel,Pred,Annul) ->
812
%% #br{reg=Reg,rcc=RegCond,true_label=TrueLabel,false_label=FalseLabel,
813
%% pred=Pred,annul=Annul}.
814
%% br_reg(#br{reg=Reg}) -> Reg.
815
%% br_reg_update(Br,NewReg) -> Br#br{reg=NewReg}.
816
%% br_regcond(#br{rcc=RegCond}) -> RegCond.
817
%% br_regcond_update(Br,NewRegCond) -> Br#br{rcc=NewRegCond}.
818
%% br_label(Br) -> br_true_label(Br).
819
%% br_label_update(Br,NewLabel) -> br_true_label_update(Br,NewLabel).
820
%% br_true_label(#br{true_label=TrueLabel}) -> TrueLabel.
821
%% br_true_label_update(Br,NewLabel) -> Br#br{true_label=NewLabel}.
822
%% br_false_label(#br{false_label=FalseLabel}) -> FalseLabel.
823
%% br_false_label_update(Br,NewLabel) -> Br#br{false_label=NewLabel}.
824
%% br_pred(#br{pred=Pred}) -> Pred.
825
%% br_pred_update(Br,NewPred) -> Br#br{pred=NewPred}.
826
%% br_annul(#br{annul=Annul}) -> Annul.
827
%% br_annul_update(Br,NewAnnul) -> Br#br{annul=NewAnnul}.
828
%% br_taken(Br) -> P = br_pred(Br), if P > 0.5 -> true; true -> false end.
829
%% %% @spec (sparc_instruction()) -> bool()
830
%% is_br(Insn) -> case Insn of #br{} -> true; _ -> false end.
834
goto_create(Label) -> #goto{label=Label}.
835
goto_label(#goto{label=Label}) -> Label.
836
goto_label_update(Goto, NewLabel) -> Goto#goto{label=NewLabel}.
837
%% @spec (sparc_instruction()) -> bool()
838
is_goto(I) -> case I of #goto{} -> true; _ -> false end.
842
jmp_link_create(Target, Offset, Link, Args) ->
843
#jmp_link{target=Target, off=Offset, link=Link, args=Args}.
844
jmp_link_target(#jmp_link{target=Target}) -> Target.
845
jmp_link_target_update(JmpLink,NewTarget) ->
846
JmpLink#jmp_link{target=NewTarget}.
847
jmp_link_off(#jmp_link{off=Offset}) -> Offset.
848
jmp_link_off_update(JmpLink,NewOffset) -> JmpLink#jmp_link{off=NewOffset}.
849
jmp_link_link(#jmp_link{link=Link}) -> Link.
850
jmp_link_link_update(JmpLink,NewLink) -> JmpLink#jmp_link{link=NewLink}.
851
jmp_link_args(#jmp_link{args=Args}) -> Args.
852
%% jmp_link_args_update(JmpLink,NewArgs) -> JmpLink#jmp_link{args=NewArgs}.
853
%% %% @spec (sparc_instruction()) -> bool()
854
%% is_jmp_link(Insn) -> case Insn of #jmp_link{} -> true; _ -> false end.
857
% jmp_create(Target, Offset, Args) ->
858
% #jmp{target=Target, off=Offset, args=Args}.
859
jmp_create(Target, Offset, Args, Destinations) ->
860
#jmp{target=Target, off=Offset, args=Args,
861
destinations=Destinations}.
862
jmp_target(#jmp{target=Target}) -> Target.
863
jmp_target_update(Jmp,NewTarget) -> Jmp#jmp{target=NewTarget}.
864
jmp_off(#jmp{off=Offset}) -> Offset.
865
jmp_off_update(Jmp,NewOffset) -> Jmp#jmp{off=NewOffset}.
866
jmp_args(#jmp{args=Args}) -> Args.
867
%% jmp_args_update(Jmp,NewArgs) -> Jmp#jmp{args=NewArgs}.
868
jmp_destinations(#jmp{destinations=Dests}) -> Dests.
869
jmp_destinations_update(Jmp,NewDests) -> Jmp#jmp{destinations=NewDests}.
872
call_link_create(Target,Link,Args,Cont,Fail,Type) ->
873
call_link_create(Target,Link,
874
%% TODO: Fix this when we have multiple retvals.
875
[mk_reg(hipe_sparc_registers:ret(0))],
876
Args,Cont,Fail,Type).
877
call_link_create(Target,Link,Dests,Args,Cont,Fail,Type) ->
882
#call_link{target=Target, link=Link,
886
continuation_label=Cont, fail_label=Fail,
887
stack_descriptor=sdesc_mk_empty()}.
888
call_link_target(#call_link{target=Target}) -> Target.
889
call_link_target_update(CL,NewTarget) -> CL#call_link{target=NewTarget}.
890
call_link_link(#call_link{link=Link}) -> Link.
891
call_link_link_update(CL,NewLink) -> CL#call_link{link=NewLink}.
892
call_link_args(#call_link{args=Args}) -> Args.
893
call_link_dests(#call_link{dests=Dests}) -> Dests.
894
call_link_args_update(CL,NewArgs) -> CL#call_link{args=NewArgs}.
895
call_link_continuation(#call_link{continuation_label=Cont}) -> Cont.
896
call_link_continuation_update(CL,NewC) -> CL#call_link{continuation_label=NewC}.
897
call_link_fail(#call_link{fail_label=Fail}) -> Fail.
898
call_link_fail_update(CL,NewF) ->
899
CL#call_link{fail_label=NewF}.
900
call_link_type(#call_link{type=Type}) -> Type.
901
call_link_stack_desc(#call_link{stack_descriptor=SDesc}) -> SDesc.
902
call_link_stack_desc_update(I,NewSD) -> I#call_link{stack_descriptor=NewSD}.
903
%% @spec (sparc_instruction()) -> bool()
904
is_call_link(Insn) -> case Insn of #call_link{} -> true; _ -> false end.
905
call_link_is_known(I) ->
906
not is_reg(call_link_target(I)).
908
%%--------------------------------------------------------------------------------
910
%%--------------------------------------------------------------------------------
913
%% Type is one of {single, double, quad}
915
%% Standard use is double with 32 bit alignment...
916
load_fp_create(Dest,Source,Off) ->
917
load_fp_create(Dest,32,double,Source,Off).
918
load_fp_create(Dest,Align,Type,Source,Off) ->
919
?ASSERT(is_fpreg(Dest)),
920
?ASSERT((is_reg(Off) orelse is_imm(Off))),
921
?ASSERT(is_reg(Source)),
922
?ASSERT(is_fptype(Type)),
923
#load_fp{dst=Dest,align=Align,type=Type,src=Source,off=Off}.
924
load_fp_dest(#load_fp{dst=Dst}) -> Dst.
925
load_fp_align(#load_fp{align=Align}) -> Align.
926
load_fp_type(#load_fp{type=Type}) -> Type.
927
load_fp_src(#load_fp{src=Src}) -> Src.
928
load_fp_off(#load_fp{off=Offset}) -> Offset.
929
load_fp_dest_update(Load,NewDest) -> Load#load_fp{dst=NewDest}.
930
%% load_fp_type_update(Load,NewType) -> Load#load_fp{type=NewType}.
931
load_fp_src_update(Load,NewSource) -> Load#load_fp{src=NewSource}.
932
load_fp_off_update(Load,NewOff) -> Load#load_fp{off=NewOff}.
933
%% %% @spec (sparc_instruction()) -> bool()
934
%% is_load_fp(Insn) -> case Insn of #load_fp{} -> true; _ -> false end.
937
%% Type is one of {single, double, quad}
939
%% Standard use is double with 32 bit alignment...
940
store_fp_create(Target,Off,Source) ->
941
store_fp_create(Target,Off,double,32,Source).
942
store_fp_create(Target,Off,Type,Align,Source) ->
943
?ASSERT(is_reg(Target)),
944
?ASSERT((is_reg(Off) orelse is_imm(Off))),
945
?ASSERT(is_fpreg(Source)),
946
?ASSERT(is_fptype(Type)),
947
#store_fp{dst=Target,type=Type,align=Align,src=Source,off=Off}.
948
store_fp_dest(#store_fp{dst=Dst}) -> Dst.
949
store_fp_off(#store_fp{off=Offset}) -> Offset.
950
store_fp_type(#store_fp{type=Type}) -> Type.
951
store_fp_align(#store_fp{align=Align}) -> Align.
952
store_fp_src(#store_fp{src=Src}) -> Src.
953
store_fp_dest_update(Store,NewTarget) -> Store#store_fp{dst=NewTarget}.
954
store_fp_off_update(Store,NewOff) -> Store#store_fp{off=NewOff}.
955
%% store_fp_type_update(Store,NewType) -> Store#store_fp{type=NewType}.
956
store_fp_src_update(Store,NewSource) -> Store#store_fp{src=NewSource}.
957
%% %% @spec (sparc_instruction()) -> bool()
958
%% is_store_fp(Insn) -> case Insn of #store_fp{} -> true; _ -> false end.
962
%% fb_create(Cond,N,TrueLabel,FalseLabel,Pred,Annul) ->
963
%% ?ASSERT(is_fp_cond(Cond)),
964
%% ?ASSERT(is_fcc(N)),
965
%% ?ASSERT(Pred >= 0 andalso Pred =< 1),
966
%% ?ASSERT(Annul =:= a orelse Annul =:= na),
968
%% true_label=TrueLabel,
969
%% false_label=FalseLabel,
972
%% fb_create(Cond,TrueLabel,FalseLabel,Pred,Annul) ->
973
%% fb_create(Cond,0,TrueLabel,FalseLabel,Pred,Annul).
974
%% fb_cond(#fb{fcc=Cond}) -> Cond.
975
%% fb_cond_update(B,NewCond) -> B#fb{fcc=NewCond}.
976
%% fb_fcc_reg(#fb{n=N}) -> N.
977
%% fb_fcc_reg_update(B,NewN) -> B#fb{n=NewN}.
978
%% fb_label(B) -> fb_true_label(B).
979
%% fb_label_update(B,NewLabel) -> fb_true_label_update(B,NewLabel).
980
%% fb_true_label(#fb{true_label=TrueLabel}) -> TrueLabel.
981
%% fb_true_label_update(B,NewLabel) -> B#fb{true_label=NewLabel}.
982
%% fb_false_label(#fb{false_label=FalseLabel}) -> FalseLabel.
983
%% fb_false_label_update(B,NewLabel) -> B#fb{false_label=NewLabel}.
984
%% fb_pred(#fb{pred=Pred}) -> Pred.
985
%% fb_pred_update(B,NewPred) -> B#fb{pred=NewPred}.
986
%% fb_annul_update(B,NewAnnul) -> B#fb{annul=NewAnnul}.
987
%% fb_annul(#fb{annul=Annul}) -> Annul.
988
%% fb_taken(B) -> P = b_pred(B), if P > 0.5 -> true; true -> false end.
989
%% %% @spec (sparc_instruction()) -> bool()
990
%% is_fb(Insn) -> case Insn of #fb{} -> true; _ -> false end.
993
%% Floating point op %%
994
fop_create(Dest,Src1,Op,Src2) ->
995
fop_create(Dest,double,Src1,Op,Src2).
996
fop_create(Dest,Type,Src1,Op,Src2) ->
997
?ASSERT(is_fpreg(Dest)),
998
?ASSERT(is_fpreg(Src1)),
999
?ASSERT(is_fpreg(Src2)),
1000
?ASSERT(is_fptype(Type)),
1001
?ASSERT(is_fop_op(Op)),
1002
#fop{dst=Dest,type=Type,src1=Src1,src2=Src2,fop=Op}.
1003
fop_dest(#fop{dst=Dst}) -> Dst.
1004
fop_type(#fop{type=Type}) -> Type.
1005
fop_src1(#fop{src1=Src1}) -> Src1.
1006
fop_operator(#fop{fop=Op}) -> Op.
1007
fop_src2(#fop{src2=Src2}) -> Src2.
1008
fop_dest_update(Fop,NewDest) -> Fop#fop{dst=NewDest}.
1009
%% fop_type_update(Fop,NewType) -> Fop#fop{type=NewType}.
1010
fop_src1_update(Fop,NewSource1) -> Fop#fop{src1=NewSource1}.
1011
%% fop_operator_update(Fop,NewOp) -> Fop#fop{fop=NewOp}.
1012
fop_src2_update(Fop,NewSource2) -> Fop#fop{src2=NewSource2}.
1013
%% %% @spec (sparc_instruction()) -> bool()
1014
%% is_fop(Insn) -> case Insn of #fop{} -> true; _ -> false end.
1017
%% Floating point compare %%
1018
%% fcmp_create(Fcc,Src1,Src2) ->
1019
%% fcmp_create(Fcc,double,Src1,Src2,false,[]).
1020
%% fcmp_create(Fcc,Type,Src1,Src2,Exception) ->
1021
%% ?ASSERT(is_fcc(Fcc)),
1022
%% ?ASSERT(is_fpreg(Src1)),
1023
%% ?ASSERT(is_fpreg(Src2)),
1024
%% ?ASSERT(is_fptype(Type)),
1025
%% ?ASSERT(is_bool(Exception)),
1026
%% #fcmp{fccn=Fcc,type=Type,src1=Src1,src2=Src2,exception=Exception}.
1027
%% fcmp_fcc_reg(#fcmp{fccn=Fcc}) -> Fcc.
1028
%% fcmp_type(#fcmp{type=Type}) -> Type.
1029
%% fcmp_src1(#fcmp{src1=Src1}) -> Src1.
1030
%% fcmp_src2(#fcmp{src2=Src2}) -> Src2.
1031
%% fcmp_exception(#fcmp{exception=Exception}) -> Exception.
1032
%% fcmp_fcc_reg_update(Fcmp,NewN) -> Fcmp#fcmp{fccn=NewN}.
1033
%% fcmp_type_update(Fcmp,NewType) -> Fcmp#fcmp{type=NewType}.
1034
%% fcmp_src1_update(Fcmp,NewSource1) -> Fcmp#fcmp{src1=NewSource1}.
1035
%% fcmp_src2_update(Fcmp,NewSource2) -> Fcmp#fcmp{src2=NewSource2}.
1036
%% fcmp_exception_update(Fcmp,NewOp) -> Fcmp#fcmp{exception=NewOp}.
1037
%% %% @spec (sparc_instruction()) -> bool()
1038
%% is_fcmp(Insn) -> case Insn of #fcmp{} -> true; _ -> false end.
1041
%% Floating point move %%
1042
fmove_create(Dest,Source) ->
1043
fmove_create(Dest,double,Source,false,false).
1044
fmove_create(Dest,Type,Source,Negate,Abs) ->
1045
?ASSERT(is_fpreg(Dest)),
1046
?ASSERT(is_fpreg(Source) orelse is_spill(Source)),
1047
?ASSERT(is_fptype(Type)),
1048
?ASSERT(Negate=true orelse Negate=false),
1049
?ASSERT(Abs=true orelse Abs=false),
1050
#fmove{dst=Dest,type=Type,src=Source,negate=Negate,abs=Abs}.
1051
fmove_dest(#fmove{dst=Dst}) -> Dst.
1052
fmove_type(#fmove{type=Type}) -> Type.
1053
fmove_src(#fmove{src=Src}) -> Src.
1054
fmove_negate(#fmove{negate=Negate}) -> Negate.
1055
fmove_abs(#fmove{abs=Abs}) -> Abs.
1056
fmove_dest_update(FM,NewDest) -> FM#fmove{dst=NewDest}.
1057
%% fmove_type_update(FM,NewType) -> FM#fmove{type=NewType}.
1058
fmove_src_update(FM,NewSource) -> FM#fmove{src=NewSource}.
1059
%% @spec (sparc_instruction()) -> bool()
1060
is_fmove(Insn) -> case Insn of #fmove{} -> true; _ -> false end.
1062
%% Convert from fixnum to float %%
1063
%% Standard use is double
1064
conv_fp_create(Target,Source) ->
1065
conv_fp_create(Target,double,Source).
1066
conv_fp_create(Target,DstType,Source) ->
1067
?ASSERT(is_fpreg(Target)),
1068
?ASSERT(is_fpreg(Source) orelse is_reg(Source)),
1069
?ASSERT(is_fptype(DstType)),
1070
#conv_fp{dst=Target,dst_type=DstType,src=Source}.
1071
conv_fp_dest(#conv_fp{dst=Dst}) -> Dst.
1072
conv_fp_dest_type(#conv_fp{dst_type=DstType}) -> DstType.
1073
conv_fp_src(#conv_fp{src=Src}) -> Src.
1074
conv_fp_dest_update(Conv,NewTarget) -> Conv#conv_fp{dst=NewTarget}.
1075
%% conv_fp_dest_type_update(Conv,NewType) -> Conv#conv_fp{dst_type=NewType}.
1076
conv_fp_src_update(Conv,NewSource) -> Conv#conv_fp{src=NewSource}.
1077
%% @spec (sparc_instruction()) -> bool()
1078
is_conv_fp(Insn) -> case Insn of #conv_fp{} -> true; _ -> false end.
1082
%% ____________________________________________________________________
1095
(is_integer(N) andalso N >= 0 andalso N =< 3).
1127
is_bool(true) -> true;
1128
is_bool(false) -> true;
1129
is_bool(_) -> false.
1131
check_var_range(Sparc) ->
1132
Code = sparc_code(Sparc),
1133
RMax = highest_reg(Code),
1134
{Low, High} = sparc_var_range(Sparc),
1137
%% ---------------------------------------------
1139
highest_reg(Code) ->
1140
highest_reg(Code,0).
1142
highest_reg([I|Is],Max) ->
1145
highest_reg(Is,new_max(Defs++Uses,Max));
1146
highest_reg([],Max) ->
1149
new_max([V|Vs],Max) ->
1156
new_max([],Max) -> Max.
1158
-endif. %% DO_ASSERT
1160
%% ____________________________________________________________________
1164
%% @spec (Name::integer) -> reg()
1165
mk_reg(RegNr) when is_integer(RegNr) -> {sparc_reg, RegNr}.
1166
%% @spec () -> reg()
1167
mk_new_reg() -> mk_reg(hipe_gensym:get_next_var(sparc)).
1168
%% @spec (operand()) -> bool()
1169
is_reg(I) -> case I of {sparc_reg, _} -> true ; _ -> false end.
1170
%% @spec (reg(RegNr)) -> RegNr
1171
%% RegNr = integer()
1172
reg_nr({sparc_reg, RegNr}) when is_integer(RegNr) -> RegNr.
1175
%% @spec (Name::integer) -> fp_reg()
1176
mk_fpreg(RegNr) when is_integer(RegNr) -> {sparc_fpreg, RegNr}.
1177
%% @spec () -> fp_reg()
1178
mk_new_fpreg() -> mk_fpreg(hipe_gensym:get_next_var(sparc)).
1179
%% @spec (operand()) -> bool()
1180
is_fpreg(I) -> case I of {sparc_fpreg, _} -> true; _ -> false end.
1181
%% @spec (fp_reg(Name)) -> Name
1183
fpreg_nr({sparc_fpreg, RegNr}) when is_integer(RegNr) -> RegNr.
1186
%% @spec (Value::integer()) -> imm()
1187
mk_imm(Value) when is_integer(Value) -> {sparc_imm, Value}.
1188
%% @spec (operand()) -> bool()
1189
is_imm(I) -> case I of {sparc_imm, _} -> true; _ -> false end.
1190
%% @spec (imm(Value)) -> Value
1191
%% Value = integer()
1192
imm_value({sparc_imm, Value}) when is_integer(Value) -> Value.
1195
%% mk_spill(Pos) -> {spill, Pos}.
1196
is_spill({spill,_}) -> true;
1197
is_spill(_) -> false.
1198
spill_pos({spill, Pos}) -> Pos.
1201
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1206
%% %% @spec (sparc_instruction()) -> bool()
1207
%% is_cmov_cc(Insn) -> case Insn of #cmov_cc{} -> true; _ -> false end.
1208
%% %% @spec (sparc_instruction()) -> bool()
1209
%% is_sethi(Insn) -> case Insn of #sethi{} -> true; _ -> false end.
1210
%% %% @spec (sparc_instruction()) -> bool()
1211
%% is_jmp(Insn) -> case Insn of #jmp{} -> true; _ -> false end.
1212
%% is_load_atom(Insn) -> case Insn of #load_atom{} -> true; _ -> false end.
1213
%% is_load_address(Insn) -> case Insn of #load_address{} -> true; _ -> false end.
1215
%% %% @spec (sparc_instruction()) -> bool()
1216
%% is_any_alu(Insn) ->
1219
%% #alu_cc{} ->true;
1223
%% %% @spec (sparc_instruction()) -> bool()
1224
%% is_any_cmov(Insn) ->
1226
%% #cmov_cc{} -> true;
1227
%% #cmov_r{} -> true;
1231
%% %% @spec (sparc_instruction()) -> bool()
1232
%% is_any_memop(Insn) ->
1235
%% #store{} -> true;
1236
%% #load_fp{} -> true;
1237
%% #store_fp{} -> true;
1241
%% These instrs are branches that need delayslot filling.
1242
%% @spec (sparc_instruction()) -> bool()
1243
is_any_branch(Insn) ->
1249
#jmp_link{} -> true;
1250
#call_link{} -> case call_link_continuation(Insn) of
1254
#pseudo_return{} -> true;
1255
#pseudo_enter{} -> true;
1260
%% These instrs are branches that need delayslot filling.
1261
%% @spec (sparc_instruction()) -> bool()
1262
has_delayslot(Insn) ->
1268
#jmp_link{} -> true;
1269
#call_link{} -> true;
1270
#pseudo_return{} -> true;
1271
#pseudo_enter{} -> true;
1276
%% @spec (I::sparc_instruction(), Old::label_name(), New::label_name()) -> sparc_instruction()
1277
%% @doc Changes the target of a jump.
1278
%% Replaces any references to the target label Old by the label New.
1279
redirect_jmp(Jmp, ToOld, ToNew) ->
1282
%% case br_true_label(Jmp) of
1284
%% br_true_label_update(Jmp, ToNew);
1286
%% case br_false_label(Jmp) of
1288
%% br_false_label_update(Jmp, ToNew);
1294
case b_true_label(Jmp) of
1296
b_true_label_update(Jmp, ToNew);
1298
case b_false_label(Jmp) of
1300
b_false_label_update(Jmp, ToNew);
1306
case goto_label(Jmp) of
1308
goto_label_update(Jmp, ToNew);
1313
NewDests = replace(ToOld, ToNew, jmp_destinations(Jmp)),
1314
jmp_destinations_update(Jmp, NewDests);
1316
case call_link_continuation(Jmp) of
1318
call_link_continuation_update(Jmp, ToNew);
1320
case call_link_fail(Jmp) of
1322
call_link_fail_update(Jmp, ToNew);
1328
%% case fb_true_label(Jmp) of
1330
%% fb_true_label_update(Jmp, ToNew);
1332
%% case fb_false_label(Jmp) of
1334
%% fb_false_label_update(Jmp, ToNew);
1343
replace(Old, New, List) ->
1349
%% @spec (condition_code()) -> condition_code()
1350
%% @doc Returns the negation of an integer condition code.
1372
%% %% @spec (fp_cond()) -> fp_cond()
1373
%% %% @doc Returns the negation of an fp condition code.
1374
%% fcc_negate(Cond) ->
1394
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1396
%% Def/Use by instruction.
1398
%% The condition code registers is read and written like any other.
1399
%% We define a _virtual_ for icc and xcc.
1401
%% @spec () -> reg()
1402
icc_reg() -> mk_reg(hipe_sparc_registers:icc()).
1403
%% @spec () -> reg()
1404
xcc_reg() -> mk_reg(hipe_sparc_registers:xcc()).
1405
%% %% @spec (N::fcc_reg()) -> reg()
1406
%% fcc_reg(N) -> mk_reg(hipe_sparc_registers:fcc(N)).
1407
y_reg() -> mk_reg(hipe_sparc_registers:y()).
1410
%% %% @spec (sparc_instruction()) -> [reg()]
1411
%% %% @doc Returns a list of both floating point and integer registers
1412
%% %% that are used by an instruction.
1413
%% fpregs_and_regs_uses(Instr) ->
1414
%% remove_immediates(all_uses(Instr)).
1417
%% @spec (sparc_instruction()) -> [reg()]
1418
%% @doc Returns a list of integer registers that are used by an instruction.
1420
%% keep_registers(all_uses(Instr)).
1421
remove_immediates(all_uses(Instr)).
1423
%% @spec (sparc_instruction()) -> [operand()]
1424
%% @doc Returns a list of operands that are used by an instruction
1431
#move{} -> [move_src(Ins)];
1432
#multimove{} -> multimove_src(Ins);
1433
%% #cmov_cc{} -> [icc_reg(), xcc_reg(), cmov_cc_src(Ins)];
1434
%% #cmov_r{} -> [cmov_r_src(Ins), cmov_r_reg(Ins)];
1435
#alu{} -> [alu_src1(Ins), alu_src2(Ins)];
1436
#alu_cc{} -> [alu_cc_src1(Ins), alu_cc_src2(Ins)];
1437
#rdy{} -> [y_reg()];
1438
#sethi{} -> [sethi_const(Ins)];
1439
#load{} -> [load_src(Ins), load_off(Ins)];
1440
#store{} -> [store_dest(Ins), store_src(Ins), store_off(Ins)];
1441
#b{} -> [icc_reg(), xcc_reg()];
1442
%% #br{} -> [br_reg(Ins)];
1445
[jmp_link_target(Ins), jmp_link_off(Ins) | jmp_link_args(Ins)];
1446
#jmp{} -> [jmp_target(Ins), jmp_off(Ins) | jmp_args(Ins)];
1448
case call_link_is_known(Ins) of
1450
[call_link_target(Ins)|call_link_args(Ins)];
1455
#load_word_index{} -> [];
1456
#pseudo_return{} -> pseudo_return_regs(Ins);
1458
case pseudo_enter_is_known(Ins) of
1460
[pseudo_enter_target(Ins)|
1461
pseudo_enter_args(Ins)];
1463
pseudo_enter_args(Ins)
1465
#pseudo_spill{} -> [pseudo_spill_reg(Ins)];
1466
#pseudo_unspill{} -> [];
1467
%% #pseudo_push{} -> [pseudo_push_reg(Ins)];
1468
#pseudo_pop{} -> [];
1470
#load_fp{} -> [load_fp_off(Ins), load_fp_src(Ins)];
1472
case store_fp_type(Ins) of
1473
single -> [store_fp_dest(Ins), store_fp_off(Ins),store_fp_src(Ins)];
1474
_ -> [store_fp_dest(Ins), store_fp_off(Ins)|
1475
format_fpreg([store_fp_src(Ins)])]
1477
%% #fb{} -> [fcc_reg(fb_fcc_reg(Ins))];
1478
#fop{} -> format_fpreg([fop_src1(Ins), fop_src2(Ins)]);
1479
%% #fcmp{} -> format_fpreg([fcmp_src1(Ins), fcmp_src2(Ins)]);
1480
#fmove{} -> format_fpreg([fmove_src(Ins)]);
1481
#conv_fp{} -> format_fpreg([conv_fp_src(Ins)]);
1482
#load_address{} -> []
1485
%% @spec (sparc_instruction()) -> [imm()]
1486
%% @doc Returns a list of immediates that are used by an instruction
1488
keep_imms(all_uses(Instr)).
1490
%% @spec (sparc_instruction()) -> [fp_reg()]
1491
%% @doc Returns a list of fp-registers that are used by an instruction
1492
fp_reg_uses(Instr) ->
1493
keep_fp_registers(all_uses(Instr)).
1496
%% @spec (sparc_instruction()) -> [reg()]
1497
%% @doc Returns a list of registers that are defined by an instruction
1499
%% keep_registers(all_defines(Ins)).
1500
remove_immediates(all_defines(Ins)).
1501
%% @spec (sparc_instruction()) -> [fp_reg()]
1502
%% @doc Returns a list of fp-registers that are defined by an instruction
1503
fp_reg_defines(Ins) ->
1504
keep_fp_registers(all_defines(Ins)).
1506
%% fpregs_and_regs_defines(Ins) ->
1507
%% keep_imms(all_defines(Ins)).
1509
%% @spec (sparc_instruction()) -> [operand()]
1510
%% @doc Returns a list of operands that are defined by an instruction
1517
#move{} -> [move_dest(Ins)];
1518
#multimove{} -> multimove_dest(Ins);
1519
%% #cmov_cc{} -> [cmov_cc_dest(Ins)];
1520
%% #cmov_r{} -> [cmov_r_dest(Ins)];
1521
#alu{} -> [alu_dest(Ins)];
1522
#alu_cc{} -> [icc_reg(), xcc_reg(), alu_cc_dest(Ins)];
1523
#rdy{} -> [rdy_dest(Ins)];
1524
#sethi{} -> [sethi_dest(Ins)];
1525
#load{} -> [load_dest(Ins)];
1530
#jmp_link{} -> [jmp_link_link(Ins)];
1533
[mk_reg(hipe_sparc_registers:ret(0)), %% For exceptions.
1534
call_link_link(Ins)|
1535
call_link_dests(Ins)];
1536
#load_atom{} -> [load_atom_dest(Ins)];
1537
#load_word_index{} -> [load_word_index_dest(Ins)];
1538
#pseudo_return{} -> [];
1539
#pseudo_enter{} -> [];
1540
%% #pseudo_push{} -> [];
1541
#pseudo_pop{} -> [pseudo_pop_reg(Ins)];
1542
#pseudo_spill{} -> [];
1543
#pseudo_unspill{} -> [pseudo_unspill_reg(Ins)];
1545
case load_fp_type(Ins) of
1546
single ->[load_fp_dest(Ins)];
1547
_ -> format_fpreg([load_fp_dest(Ins)])
1551
#fop{} -> format_fpreg([fop_dest(Ins)]);
1552
%% #fcmp{} -> [fcc_reg(fcmp_fcc_reg(Ins))];
1553
#fmove{} -> format_fpreg([fmove_dest(Ins)]);
1554
#conv_fp{} -> format_fpreg([conv_fp_dest(Ins)]);
1555
#load_address{} -> [load_address_dest(Ins)]
1559
%% @spec (sparc_instruction()) -> {[operand()],[operand()]}
1560
%% @doc Returns a tuple of defs and uses in instruction.
1561
%% Totally redundant, but we need it for speed.
1565
#label{} -> {[],[]};
1567
%% #align{} -> {[],[]};
1568
#comment{} -> {[],[]};
1576
%% {[cmov_cc_dest(I)],
1577
%% [icc_reg(), xcc_reg(), cmov_cc_src(I)]};
1579
%% {[cmov_r_dest(I)],
1580
%% [cmov_r_src(I), cmov_r_reg(I)]};
1583
[alu_src1(I), alu_src2(I)]};
1585
{[icc_reg(), xcc_reg(), alu_cc_dest(I)],
1586
[alu_cc_src1(I), alu_cc_src2(I)]};
1595
[load_src(I), load_off(I)]};
1598
[store_dest(I), store_src(I), store_off(I)]};
1601
[icc_reg(), xcc_reg()]};
1607
{[jmp_link_link(I)],
1608
[jmp_link_target(I), jmp_link_off(I) | jmp_link_args(I)]};
1611
[jmp_target(I), jmp_off(I) | jmp_args(I)]};
1613
{[call_link_link(I)|call_link_dests(I)],
1614
case call_link_is_known(I) of
1616
[call_link_target(I)|call_link_args(I)];
1617
true -> call_link_args(I)
1620
{[load_atom_dest(I)],
1622
#load_word_index{} ->
1623
{[load_word_index_dest(I)],
1627
pseudo_return_regs(I)};
1630
case pseudo_enter_is_known(I) of
1632
[pseudo_enter_target(I)|
1633
pseudo_enter_args(I)];
1635
pseudo_enter_args(I)
1639
[pseudo_spill_reg(I)]};
1640
#pseudo_unspill{} ->
1641
{[pseudo_unspill_reg(I)],
1645
% [pseudo_push_reg(I)]};
1647
{[pseudo_pop_reg(I)],
1650
case load_fp_type(I) of
1653
[load_fp_src(I), load_fp_off(I)]};
1655
{format_fpreg([load_fp_dest(I)]),
1656
[load_fp_src(I), load_fp_off(I)]}
1659
case store_fp_type(I) of
1662
[store_fp_src(I), store_fp_off(I), store_fp_dest(I)]};
1665
[store_fp_off(I), store_fp_dest(I) |
1666
format_fpreg([store_fp_src(I)])]}
1670
%% [fcc_reg(fb_fcc_reg(I))]};
1672
{format_fpreg([fop_dest(I)]),
1673
format_fpreg([fop_src1(I), fop_src2(I)])};
1675
%% {[fcc_reg(fcmp_fcc_reg(I))],
1676
%% format_fpreg([fcmp_src1(I), fcmp_src2(I)])};
1678
{format_fpreg([fmove_dest(I)]),
1679
format_fpreg([fmove_src(I)])};
1681
{format_fpreg([conv_fp_dest(I)]),
1684
{[load_address_dest(I)],
1688
%% @spec (sparc_instruction()) -> {[reg()],[reg()]}
1689
%% @doc Returns a tuple of reg-defs and reg-uses in instruction.
1690
%% Totally redundant, but we need it for speed.
1692
{Def,Use} = all_def_uses(I),
1693
{keep_registers(Def), keep_registers(Use)}.
1695
%% %% @spec (sparc_instruction()) -> {[fp_reg()],[fp_reg()]}
1696
%% %% @doc Returns a tuple of fp-reg-defs and fp-reg-uses in instruction.
1697
%% %% Totally redundant, but we need it for speed.
1698
%% fp_reg_def_use(I) ->
1699
%% {Def,Use} = all_def_uses(I),
1700
%% {keep_fp_registers(Def), keep_fp_registers(Use)}.
1702
%% fpregs_and_regs_def_use(I) ->
1703
%% {Def,Use} = all_def_uses(I),
1704
%% {remove_immediates(Def), remove_immediates(Use)}.
1707
%% Makes sure the single precision registers that makes up a double
1708
%% precision one is marked as defines and uses.
1712
format_fpreg(Reg, []).
1714
format_fpreg([H|T], Acc)->
1717
RegNr = fpreg_nr(H),
1718
case hipe_sparc_specific_fp:is_precoloured(RegNr) of
1720
format_fpreg(T, [H, mk_fpreg(RegNr+1)|Acc]);
1722
format_fpreg(T, [H|Acc])
1725
format_fpreg(T, [H|Acc])
1727
format_fpreg([], Acc) ->
1731
%% Remove immediates from a list
1734
remove_immediates([]) ->
1736
remove_immediates([I|Is]) ->
1738
true -> remove_immediates(Is);
1739
false -> [I | remove_immediates(Is)]
1744
%% Remove registers from a list
1747
%% remove_registers([]) ->
1749
%% remove_registers([I|Is]) ->
1750
%% case is_reg(I) of
1751
%% true -> remove_registers(Is);
1753
%% case is_fpreg(I) of
1754
%% true -> remove_registers(Is);
1755
%% false -> [I | remove_registers(Is)]
1761
%% Keep registers in a list
1764
keep_registers([]) ->
1766
keep_registers([I|Is]) ->
1768
true -> [I | keep_registers(Is)];
1769
false -> keep_registers(Is)
1773
%% Keep float registers in a list
1776
keep_fp_registers([]) ->
1778
keep_fp_registers([I|Is]) ->
1780
true -> [I | keep_fp_registers(Is)];
1781
false -> keep_fp_registers(Is)
1785
%% Keep immediates in a list
1790
keep_imms([I|Is]) ->
1792
true -> [I | keep_imms(Is)];
1793
false -> keep_imms(Is)
1797
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1798
%% @spec (Ins::sparc_instruction(), Subst) -> sparc_instruction()
1799
%% Subst = [{Old, New}]
1802
%% @doc Substitution -- replace occurrences of the operator Old by New if {Old,New} is in Subst.
1803
subst(Ins, Subst) ->
1812
NewDst = subst1(Subst, rdy_dest(Ins)),
1813
rdy_dest_update(Ins, NewDst);
1815
NewDst = subst1(Subst, sethi_dest(Ins)),
1816
sethi_dest_update(Ins, NewDst);
1818
%% NewReg = subst1(Subst, br_reg(Ins)),
1819
%% br_reg_update(Ins, NewReg);
1822
case call_link_is_known(Ins) of
1824
NewTarget = subst1(Subst, call_link_target(Ins)),
1825
call_link_target_update(Ins, NewTarget);
1828
NewArgs = subst_list(Subst, call_link_args(Ins1)),
1829
Ins2 = call_link_args_update(Ins1,NewArgs),
1830
NewLink = subst1(Subst, call_link_link(Ins2)),
1831
call_link_link_update(Ins2, NewLink);
1833
NewDst = subst1(Subst, load_atom_dest(Ins)),
1834
load_atom_dest_update(Ins, NewDst);
1835
#load_word_index{} ->
1836
NewDst = subst1(Subst, load_word_index_dest(Ins)),
1837
load_word_index_dest_update(Ins, NewDst);
1839
NewDst = subst1(Subst, load_address_dest(Ins)),
1840
load_address_dest_update(Ins, NewDst);
1842
NewSrc = subst1(Subst, move_src(Ins)),
1843
NewDst = subst1(Subst, move_dest(Ins)),
1844
I0 = move_dest_update(Ins, NewDst),
1845
move_src_update(I0, NewSrc);
1847
NewSrc = subst_list(Subst, multimove_src(Ins)),
1848
NewDst = subst_list(Subst, multimove_dest(Ins)),
1849
I0 = multimove_dest_update(Ins, NewDst),
1850
multimove_src_update(I0, NewSrc);
1852
%% NewSrc = subst1(Subst, cmov_cc_src(Ins)),
1853
%% NewDst = subst1(Subst, cmov_cc_dest(Ins)),
1854
%% I0 = cmov_cc_dest_update(Ins, NewDst),
1855
%% cmov_cc_src_update(I0, NewSrc);
1857
%% NewSrc = subst1(Subst, cmov_r_src(Ins)),
1858
%% NewReg = subst1(Subst, cmov_r_reg(Ins)),
1859
%% NewDst = subst1(Subst, cmov_r_dest(Ins)),
1860
%% I0 = cmov_r_dest_update(Ins, NewDst),
1861
%% I1 = cmov_r_src_update(I0, NewSrc),
1862
%% cmov_r_reg_update(I1, NewReg);
1864
NewSrc1 = subst1(Subst, alu_src1(Ins)),
1865
NewSrc2 = subst1(Subst, alu_src2(Ins)),
1866
NewDst = subst1(Subst, alu_dest(Ins)),
1867
I0 = alu_dest_update(Ins, NewDst),
1868
I1 = alu_src1_update(I0, NewSrc1),
1869
alu_src2_update(I1, NewSrc2);
1871
NewSrc1 = subst1(Subst, alu_cc_src1(Ins)),
1872
NewSrc2 = subst1(Subst, alu_cc_src2(Ins)),
1873
NewDst = subst1(Subst, alu_cc_dest(Ins)),
1874
I0 = alu_cc_dest_update(Ins, NewDst),
1875
I1 = alu_cc_src1_update(I0, NewSrc1),
1876
alu_cc_src2_update(I1, NewSrc2);
1878
NewSrc = subst1(Subst, load_src(Ins)),
1879
NewOff = subst1(Subst, load_off(Ins)),
1880
NewDst = subst1(Subst, load_dest(Ins)),
1881
I0 = load_dest_update(Ins, NewDst),
1882
I1 = load_src_update(I0, NewSrc),
1883
load_off_update(I1, NewOff);
1885
NewSrc = subst1(Subst, store_src(Ins)),
1886
NewOff = subst1(Subst, store_off(Ins)),
1887
NewDst = subst1(Subst, store_dest(Ins)),
1888
I0 = store_dest_update(Ins, NewDst),
1889
I1 = store_src_update(I0, NewSrc),
1890
store_off_update(I1, NewOff);
1892
NewTarget = subst1(Subst, jmp_link_target(Ins)),
1893
NewOff = subst1(Subst, jmp_link_off(Ins)),
1894
NewLink = subst1(Subst, jmp_link_link(Ins)),
1895
I0 = jmp_link_link_update(Ins, NewLink),
1896
I1 = jmp_link_target_update(I0, NewTarget),
1897
jmp_link_off_update(I1, NewOff);
1899
NewRegs = subst_list(Subst, pseudo_return_regs(Ins)),
1900
pseudo_return_regs_update(Ins, NewRegs);
1903
case pseudo_enter_is_known(Ins) of
1905
pseudo_enter_target_update(Ins,
1906
subst1(Subst,pseudo_enter_target(Ins)));
1910
NewRegs = subst_list(Subst, pseudo_enter_args(NewI)),
1911
pseudo_enter_args_update(NewI, NewRegs);
1913
NewReg = subst1(Subst, pseudo_spill_reg(Ins)),
1914
pseudo_spill_reg_update(Ins, NewReg);
1915
#pseudo_unspill{} ->
1916
NewReg = subst1(Subst, pseudo_unspill_reg(Ins)),
1917
pseudo_unspill_reg_update(Ins, NewReg);
1919
% NewReg = subst1(Subst, pseudo_push_reg(Ins)),
1920
% pseudo_push_reg_update(Ins, NewReg);
1922
NewReg = subst1(Subst, pseudo_pop_reg(Ins)),
1923
pseudo_pop_reg_update(Ins, NewReg);
1926
NewSrc = subst1(Subst, load_fp_src(Ins)),
1927
NewOff = subst1(Subst, load_fp_off(Ins)),
1928
NewDst = subst1(Subst, load_fp_dest(Ins)),
1929
I0 = load_fp_dest_update(Ins, NewDst),
1930
I1 = load_fp_src_update(I0, NewSrc),
1931
load_fp_off_update(I1, NewOff);
1933
NewSrc = subst1(Subst, store_fp_src(Ins)),
1934
NewOff = subst1(Subst, store_fp_off(Ins)),
1935
NewDst = subst1(Subst, store_fp_dest(Ins)),
1936
I0 = store_fp_dest_update(Ins, NewDst),
1937
I1 = store_fp_src_update(I0, NewSrc),
1938
store_fp_off_update(I1, NewOff);
1941
NewSrc1 = subst1(Subst, fop_src1(Ins)),
1942
NewSrc2 = subst1(Subst, fop_src2(Ins)),
1943
NewDst = subst1(Subst, fop_dest(Ins)),
1944
I0 = fop_dest_update(Ins, NewDst),
1945
I1 = fop_src1_update(I0, NewSrc1),
1946
fop_src2_update(I1, NewSrc2);
1948
%% NewSrc1 = subst1(Subst, fcmp_src1(Ins)),
1949
%% NewSrc2 = subst1(Subst, fcmp_src2(Ins)),
1950
%% I1 = fcmp_src1_update(Ins, NewSrc1),
1951
%% #fcmp_src2_update(I1, NewSrc2);
1953
NewSrc = subst1(Subst, fmove_src(Ins)),
1954
NewDst = subst1(Subst, fmove_dest(Ins)),
1955
I0 = fmove_dest_update(Ins, NewDst),
1956
fmove_src_update(I0, NewSrc);
1958
NewSrc = subst1(Subst, conv_fp_src(Ins)),
1959
NewDst = subst1(Subst, conv_fp_dest(Ins)),
1960
I0 = conv_fp_dest_update(Ins, NewDst),
1961
conv_fp_src_update(I0, NewSrc);
1963
NewTarget = subst1(Subst, jmp_target(Ins)),
1964
NewOff = subst1(Subst, jmp_off(Ins)),
1965
I0 = jmp_target_update(Ins, NewTarget),
1966
jmp_off_update(I0, NewOff)
1969
%% @spec (Ins::sparc_instruction(), Subst) -> sparc_instruction()
1970
%% Subst = [{Old, New}]
1973
%% @doc Substitution --
1974
%% replace defined occurrences of the operator Old by New if {Old,New} is in Subst.
1975
subst_defines(Ins, Subst) ->
1986
NewDst = subst1(Subst, rdy_dest(Ins)),
1987
rdy_dest_update(Ins, NewDst);
1989
NewDst = subst1(Subst, sethi_dest(Ins)),
1990
sethi_dest_update(Ins, NewDst);
1992
NewLink = subst1(Subst, call_link_link(Ins)),
1993
call_link_link_update(Ins, NewLink);
1995
NewDst = subst1(Subst, load_atom_dest(Ins)),
1996
load_atom_dest_update(Ins, NewDst);
1997
#load_word_index{} ->
1998
NewDst = subst1(Subst, load_word_index_dest(Ins)),
1999
load_word_index_dest_update(Ins, NewDst);
2001
NewDst = subst1(Subst, load_address_dest(Ins)),
2002
load_address_dest_update(Ins, NewDst);
2004
NewDst = subst1(Subst, move_dest(Ins)),
2005
move_dest_update(Ins, NewDst);
2007
NewDst = subst_list(Subst, multimove_dest(Ins)),
2008
multimove_dest_update(Ins, NewDst);
2010
%% NewDst = subst1(Subst, cmov_cc_dest(Ins)),
2011
%% cmov_cc_dest_update(Ins, NewDst);
2013
%% NewDst = subst1(Subst, cmov_r_dest(Ins)),
2014
%% cmov_r_dest_update(Ins, NewDst);
2016
NewDst = subst1(Subst, alu_dest(Ins)),
2017
alu_dest_update(Ins, NewDst);
2019
NewDst = subst1(Subst, alu_cc_dest(Ins)),
2020
alu_cc_dest_update(Ins, NewDst);
2022
NewDst = subst1(Subst, load_dest(Ins)),
2023
load_dest_update(Ins, NewDst);
2025
#pseudo_return{} -> Ins;
2026
#pseudo_enter{} -> Ins;
2027
#pseudo_spill{} -> Ins;
2028
#pseudo_unspill{} ->
2029
NewReg = subst1(Subst, pseudo_unspill_reg(Ins)),
2030
pseudo_unspill_reg_update(Ins, NewReg);
2031
% #pseudo_push{} -> Ins;
2033
NewReg = subst1(Subst, pseudo_pop_reg(Ins)),
2034
pseudo_pop_reg_update(Ins, NewReg);
2036
NewDst = subst1(Subst, load_fp_dest(Ins)),
2037
load_fp_dest_update(Ins, NewDst);
2041
NewDst = subst1(Subst, fop_dest(Ins)),
2042
fop_dest_update(Ins, NewDst);
2043
%% #fcmp{} -> Ins; %% XXX: Should handle fccn updates.
2045
NewDst = subst1(Subst, fmove_dest(Ins)),
2046
fmove_dest_update(Ins, NewDst);
2048
NewDst = subst1(Subst, conv_fp_dest(Ins)),
2049
conv_fp_dest_update(Ins, NewDst);
2051
NewLink = subst1(Subst, jmp_link_link(Ins)),
2052
jmp_link_link_update(Ins, NewLink)
2056
%% @spec (Ins::sparc_instruction(), Subst) -> sparc_instruction()
2057
%% Subst = [{Old, New}]
2060
%% @doc Substitution --
2061
%% replace used occurrences of the operator Old by New if {Old,New} is in Subst.
2062
subst_uses(Ins, Subst) ->
2073
case call_link_is_known(Ins) of
2075
NewTarget = subst1(Subst, call_link_target(Ins)),
2076
call_link_target_update(Ins, NewTarget);
2079
#load_atom{} -> Ins;
2080
#load_word_index{} -> Ins;
2081
#load_address{} -> Ins;
2083
%% NewReg = subst1(Subst, br_reg(Ins)),
2084
%% br_reg_update(Ins, NewReg);
2086
NewSrc = subst1(Subst, move_src(Ins)),
2087
move_src_update(Ins, NewSrc);
2089
NewSrc = subst_list(Subst, multimove_src(Ins)),
2090
multimove_src_update(Ins, NewSrc);
2092
%% NewSrc = subst1(Subst, cmov_cc_src(Ins)),
2093
%% cmov_cc_src_update(Ins, NewSrc);
2095
%% NewSrc = subst1(Subst, cmov_r_src(Ins)),
2096
%% NewReg = subst1(Subst, cmov_r_reg(Ins)),
2097
%% I1 = cmov_r_src_update(Ins, NewSrc),
2098
%% cmov_r_reg_update(I1, NewReg);
2100
NewSrc1 = subst1(Subst, alu_src1(Ins)),
2101
NewSrc2 = subst1(Subst, alu_src2(Ins)),
2102
I1 = alu_src1_update(Ins, NewSrc1),
2103
alu_src2_update(I1, NewSrc2);
2105
NewSrc1 = subst1(Subst, alu_cc_src1(Ins)),
2106
NewSrc2 = subst1(Subst, alu_cc_src2(Ins)),
2107
I1 = alu_cc_src1_update(Ins, NewSrc1),
2108
alu_cc_src2_update(I1, NewSrc2);
2110
NewSrc = subst1(Subst, load_src(Ins)),
2111
NewOff = subst1(Subst, load_off(Ins)),
2112
I1 = load_src_update(Ins, NewSrc),
2113
load_off_update(I1, NewOff);
2115
NewSrc = subst1(Subst, store_src(Ins)),
2116
NewOff = subst1(Subst, store_off(Ins)),
2117
NewDst = subst1(Subst, store_dest(Ins)),
2118
I0 = store_dest_update(Ins, NewDst),
2119
I1 = store_src_update(I0, NewSrc),
2120
store_off_update(I1, NewOff);
2122
NewTarget = subst1(Subst, jmp_link_target(Ins)),
2123
NewOff = subst1(Subst, jmp_link_off(Ins)),
2124
I1 = jmp_link_target_update(Ins, NewTarget),
2125
jmp_link_off_update(I1, NewOff);
2127
NewRegs = subst_list(Subst, pseudo_return_regs(Ins)),
2128
pseudo_return_regs_update(Ins, NewRegs);
2131
case pseudo_enter_is_known(Ins) of
2133
pseudo_enter_target_update(Ins,
2134
subst1(Subst,pseudo_enter_target(Ins)));
2138
NewRegs = subst_list(Subst, pseudo_enter_args(NewI)),
2139
pseudo_enter_args_update(NewI, NewRegs);
2141
NewReg = subst1(Subst, pseudo_spill_reg(Ins)),
2142
pseudo_spill_reg_update(Ins, NewReg);
2143
#pseudo_unspill{} ->
2146
% NewReg = subst1(Subst, pseudo_push_reg(Ins)),
2147
% pseudo_push_reg_update(Ins, NewReg);
2151
NewSrc = subst1(Subst, load_fp_src(Ins)),
2152
NewOff = subst1(Subst, load_fp_off(Ins)),
2153
I1 = load_fp_src_update(Ins, NewSrc),
2154
load_fp_off_update(I1, NewOff);
2156
NewSrc = subst1(Subst, store_fp_src(Ins)),
2157
NewOff = subst1(Subst, store_fp_off(Ins)),
2158
NewDst = subst1(Subst, store_fp_dest(Ins)),
2159
I0 = store_fp_dest_update(Ins, NewDst),
2160
I1 = store_fp_src_update(I0, NewSrc),
2161
store_fp_off_update(I1, NewOff);
2162
%% #fb{} -> Ins; %% XXX: Should realy handle subst of fcc-regs.
2164
NewSrc1 = subst1(Subst, fop_src1(Ins)),
2165
NewSrc2 = subst1(Subst, fop_src2(Ins)),
2166
I1 = fop_src1_update(Ins, NewSrc1),
2167
fop_src2_update(I1, NewSrc2);
2169
%% NewSrc1 = subst1(Subst, fcmp_src1(Ins)),
2170
%% NewSrc2 = subst1(Subst, fcmp_src2(Ins)),
2171
%% I1 = fcmp_src1_update(Ins, NewSrc1),
2172
%% fcmp_src2_update(I1, NewSrc2);
2174
NewSrc = subst1(Subst, fmove_src(Ins)),
2175
fmove_src_update(Ins, NewSrc);
2177
NewSrc = subst1(Subst, conv_fp_src(Ins)),
2178
conv_fp_src_update(Ins, NewSrc);
2180
NewTarget = subst1(Subst, jmp_target(Ins)),
2181
NewOff = subst1(Subst, jmp_off(Ins)),
2182
I0 = jmp_target_update(Ins, NewTarget),
2183
jmp_off_update(I0, NewOff)
2187
[subst1(S,X) || X <- Xs].
2191
subst1([{X,Y}|_],X) ->
2196
%% ----------------------------------------------