~ubuntu-branches/debian/squeeze/erlang/squeeze

« back to all changes in this revision

Viewing changes to lib/hipe/sparc/0OLD/hipe_sparc.erl

  • Committer: Bazaar Package Importer
  • Author(s): Sergei Golovan
  • Date: 2009-05-07 15:07:37 UTC
  • mfrom: (1.2.1 upstream) (5.1.2 sid)
  • Revision ID: james.westby@ubuntu.com-20090507150737-i4yb5elwinm7r0hc
Tags: 1:13.b-dfsg1-1
* Removed another bunch of non-free RFCs from original tarball
  (closes: #527053).
* Fixed build-dependencies list by adding missing comma. This requires
  libsctp-dev again. Also, added libsctp1 dependency to erlang-base and
  erlang-base-hipe packages because the shared library is loaded via
  dlopen now and cannot be added using dh_slibdeps (closes: #526682).
* Weakened dependency of erlang-webtool on erlang-observer to recommends
  to avoid circular dependencies (closes: #526627).
* Added solaris-i386 to HiPE enabled architectures.
* Made script sources in /usr/lib/erlang/erts-*/bin directory executable,
  which is more convenient if a user wants to create a target Erlang system.
* Shortened extended description line for erlang-dev package to make it
  fit 80x25 terminals.

Show diffs side-by-side

added added

removed removed

Lines of Context:
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.
7
 
%%  Notes    : 
8
 
%% =====================================================================
9
 
%%
10
 
%% @doc Provides primitives for handling SPARC instructions.
11
 
%% <h3>Basic types</h3>
12
 
%% <ul> 
13
 
%%   <li>{@link sparc()}</li>
14
 
%%   <li>{@link sparc_instruction()}</li>
15
 
%%   <li>{@link mfa()}</li>
16
 
%%   <li>{@link fa()}</li>
17
 
%% </ul>
18
 
%% <h3>Basic instructions</h3>
19
 
%% <ul> 
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>
38
 
%% </ul>
39
 
%% <h3>Floating-point instructions</h3>
40
 
%% <ul> 
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>
46
 
%% </ul>
47
 
%% <h3>Pseudo instructions</h3>
48
 
%% <ul> 
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>
54
 
%% </ul>
55
 
%% <h3>Field types</h3>
56
 
%% <ul> 
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>
76
 
%% </ul>
77
 
%% @end
78
 
%% (Not currently used: pseudo_push(), align(), cmov_cc(), cmov_r(),
79
 
%% br(), fb(), fcmp(), fcc_reg().)
80
 
%%
81
 
%% Basic types:
82
 
%%
83
 
%% @type sparc().
84
 
%% A datastructure for SPARC code for one function. 
85
 
%% <p>Has the following properties
86
 
%% <ul> 
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
91
 
%%   a closure.</li>
92
 
%%   <li><code>IsLeaf::bool()</code> -- True if this is a "leaf
93
 
%%   function". </li>
94
 
%%   <li><code>Code::[sparc_instruction()]</code> -- List of sparc
95
 
%%   instructions. </li>
96
 
%%   <li><code>Data::hipe_consttab:const_tab()</code> -- Data
97
 
%%   segment.</li>
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>
102
 
%% </ul>
103
 
%% </p> 
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() =
107
 
%%               label()
108
 
%%            |  nop()
109
 
%%            |  comment() 
110
 
%%            |  move() 
111
 
%%            |  multimove() 
112
 
%%            |  alu()
113
 
%%            |  alu_cc()
114
 
%%            |  sethi()
115
 
%%            |  load()
116
 
%%            |  store()
117
 
%%            |  b()
118
 
%%            |  goto()
119
 
%%            |  jmp_link()
120
 
%%            |  jmp()
121
 
%%            |  call_link()
122
 
%%            |  load_address().
123
 
%%            |  load_atom()
124
 
%%            |  load_word_index()
125
 
%%            |  load_fp()
126
 
%%            |  store_fp()
127
 
%%            |  fop()
128
 
%%            |  fmove()
129
 
%%            |  conv_fp()
130
 
%%            |  pseudo_return()
131
 
%%            |  pseudo_enter() 
132
 
%%            |  pseudo_pop() 
133
 
%%            |  pseudo_spill() 
134
 
%%            |  pseudo_unspill() 
135
 
%% This datatype defines all the different SPARC instructions that
136
 
%% HiPE handles.
137
 
%% @end
138
 
%% (Not currently used: pseudo_push(), align(), cmov_cc(), cmov_r(),
139
 
%% br(), fb(), fcmp().)
140
 
%%
141
 
%% Instruction types:
142
 
%%
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}.
161
 
%% @end
162
 
%% (Not currently used: cmov_r(), cmov_cc(), br().)
163
 
%%
164
 
%% Floating-point instructions:
165
 
%%
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}.
171
 
%% @end
172
 
%% (Not currently used: fb(), fcmp().)
173
 
%%
174
 
%% Pseudo instructions:
175
 
%%
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}.
181
 
%% @end
182
 
%% (Not currently used: pseudo_push().)
183
 
%%
184
 
%% Field types:
185
 
%%
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()}
192
 
%% @type aluop() = 
193
 
%%               '+' | '-' |  '+c' | '-c' | 'and' | 'andn' |  'or' 
194
 
%%             | 'xor' | 'xnor' | '>>' |  '>>64' |  '>>?' |  '>>?64'
195
 
%%             | '<<' | '<<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() |
208
 
%%                                 label_name().
209
 
%%                                 This type is dependent on la_type().
210
 
%%                                 <ul>
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>
219
 
%%                                 </ul>
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() = '+' | '-' | '*' 
225
 
%% @end
226
 
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
227
 
-module(hipe_sparc).
228
 
 
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
236
 
        ]).
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
240
 
        ]).
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,
246
 
         %% jmp_create/3,
247
 
         jmp_create/4,
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,
256
 
         call_link_dests/1,
257
 
         call_link_continuation/1, call_link_continuation_update/2,
258
 
         call_link_fail/1, call_link_fail_update/2,
259
 
         call_link_type/1,
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,
264
 
         load_atom_create/2,
265
 
         load_atom_dest/1, %% load_atom_dest_update/2,
266
 
         load_atom_atom/1,
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,
283
 
         nop_create/0,
284
 
         rdy_create/1, rdy_dest/1,
285
 
         sethi_const/1, %% sethi_const_update/2,
286
 
         sethi_dest/1, %% sethi_dest_update/2,
287
 
         sethi_create/2]).
288
 
-export([load_fp_create/3,
289
 
         load_fp_create/5,
290
 
         load_fp_dest/1, %% load_fp_dest_update/2,
291
 
         load_fp_align/1,
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
295
 
        ]).
296
 
-export([store_fp_create/3,
297
 
         store_fp_create/5,
298
 
         store_fp_dest/1, %% store_fp_dest_update/2,
299
 
         store_fp_off/1,  %% store_fp_off_update/2,
300
 
         store_fp_align/1,
301
 
         store_fp_src/1,  %% store_fp_src_update/2,
302
 
         store_fp_type/1  %% store_fp_type_update/2
303
 
        ]).
304
 
 
305
 
-export([%% fb_create/7,
306
 
         %% fb_create/6,
307
 
         %% fb_annul/1,
308
 
         %% fb_annul_update/2,
309
 
         %% fb_cond/1,
310
 
         %% fb_cond_update/2,
311
 
         %% fb_fcc_reg/1,
312
 
         %% fb_fcc_reg_update/2,
313
 
         %% fb_label/1,
314
 
         %% fb_label_update/2,
315
 
         %% fb_true_label/1,
316
 
         %% fb_true_label_update/2,
317
 
         %% fb_false_label/1,
318
 
         %% fb_false_label_update/2,
319
 
         %% fb_pred/1,
320
 
         %% fb_pred_update/2,
321
 
         %% fb_taken/1
322
 
        ]).
323
 
 
324
 
-export([fop_create/4,
325
 
         %% fop_create/5,
326
 
         fop_dest/1,
327
 
         %% fop_dest_update/2,
328
 
         fop_type/1,
329
 
         %% fop_type_update/2,
330
 
         fop_operator/1,
331
 
         %% fop_operator_update/2,
332
 
         fop_src1/1,
333
 
         %% fop_src1_update/2,
334
 
         fop_src2/1
335
 
         %% fop_src2_update/2
336
 
        ]).
337
 
 
338
 
-export([%% fcmp_create/3,
339
 
         %% fcmp_create/6,
340
 
         %% fcmp_fcc_reg/1,
341
 
         %% fcmp_type/1,
342
 
         %% fcmp_src1/1,
343
 
         %% fcmp_src2/1,
344
 
         %% fcmp_exception/1
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
350
 
        ]).
351
 
 
352
 
-export([fmove_create/2,
353
 
         fmove_create/5,
354
 
         fmove_dest/1,
355
 
         fmove_dest_update/2,
356
 
         fmove_type/1,
357
 
         %% fmove_type_update/2,
358
 
         fmove_src/1,
359
 
         %% fmove_src_update/2,
360
 
         fmove_negate/1,         
361
 
         fmove_abs/1]).
362
 
 
363
 
-export([conv_fp_create/2,
364
 
         %% conv_fp_create/3,
365
 
         conv_fp_dest/1,
366
 
         conv_fp_dest_type/1,
367
 
         conv_fp_src/1
368
 
         %% conv_fp_dest_update/2,
369
 
         %% conv_fp_dest_type_update/2,
370
 
         %% conv_fp_src_update/2
371
 
        ]).
372
 
 
373
 
 
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,
378
 
         pseudo_enter_type/1,
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,
382
 
         pseudo_spill_reg/1,
383
 
         pseudo_spill_pos/1,
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
390
 
        ]).
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, 
399
 
         b_create/5,
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,
404
 
         b_taken/1,
405
 
         %% br_create/7,
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,
411
 
         %% br_taken/1,
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,
418
 
         %% cmov_r_create/4,
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,
422
 
         comment_create/1,
423
 
         comment_text/1, %% comment_text_update/2,
424
 
         %% is_align/1, is_alu/1, is_alu_cc/1,
425
 
         %% is_any_alu/1,
426
 
         is_any_branch/1, has_delayslot/1,
427
 
         %% is_any_cmov/1, is_any_memop/1,
428
 
         %% is_b/1, is_br/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,
438
 
         %% all_uses/1,
439
 
         imm_uses/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
445
 
        ]).
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]).
450
 
 
451
 
%%-define(DO_ASSERT,true).
452
 
-include("../main/hipe.hrl").
453
 
-include("hipe_sparc_sdesc.hrl").
454
 
-include("hipe_sparc.hrl").
455
 
 
456
 
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
457
 
%%
458
 
%% Constructors
459
 
%%
460
 
 
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()} 
466
 
%%                               ) -> sparc()
467
 
mk_sparc(Fun, Arity, Closure, Leaf, Code, Data, VarRange, LabelRange) ->
468
 
  #sparc{'fun'=Fun, 
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()} 
476
 
%% %%                               ) -> sparc()
477
 
%% mk_sparc(Fun, Arity, Code, Data, VarRange, LabelRange) ->
478
 
%%   #sparc{'fun'=Fun, 
479
 
%%       arity=Arity, closure=false, leaf=false,
480
 
%%       code=Code, data=Data, var_range=VarRange, label_range=LabelRange}.
481
 
 
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}.
498
 
-ifdef(DO_ASSERT).
499
 
%% @spec (Sparc::sparc()) -> {integer(),integer()} 
500
 
sparc_var_range(#sparc{var_range=VarRange}) -> VarRange.
501
 
-endif.
502
 
%% @clear
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)),
507
 
  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))).
519
 
 
520
 
 
521
 
%% Enter - pseudo op %
522
 
%% @spec  (Target::target(), Args::[reg()], Type::atom()) -> pseudo_enter()
523
 
pseudo_enter_create(Target, Args, Type) ->
524
 
  case Type of
525
 
    remote -> ok;
526
 
    not_remote -> ok
527
 
  end,
528
 
  #pseudo_enter{target=Target, args=Args, type=Type}.
529
 
pseudo_enter_args(#pseudo_enter{args=Args}) ->
530
 
  Args.
531
 
pseudo_enter_args_update(I,Args) ->
532
 
  I#pseudo_enter{args=Args}.
533
 
pseudo_enter_target(#pseudo_enter{target=Target}) ->
534
 
  Target.
535
 
pseudo_enter_target_update(I,Target) ->
536
 
  I#pseudo_enter{target=Target}.
537
 
pseudo_enter_type(#pseudo_enter{type=Type}) ->
538
 
  Type.
539
 
pseudo_enter_is_known(I) ->
540
 
  not is_reg(pseudo_enter_target(I)).
541
 
 
542
 
 
543
 
%% Return - pseudo op %
544
 
pseudo_return_create(Regs) ->
545
 
  #pseudo_return{regs=Regs}.
546
 
pseudo_return_regs(#pseudo_return{regs=Regs}) ->
547
 
  Regs.
548
 
pseudo_return_regs_update(I,Regs) ->
549
 
  I#pseudo_return{regs=Regs}.
550
 
 
551
 
 
552
 
%% Push - pseudo op %
553
 
%% pseudo_push_create(Reg) ->
554
 
%%   #pseudo_push{reg=Reg}.
555
 
%% pseudo_push_reg(#pseudo_push{reg=Reg}) ->
556
 
%%   Reg.
557
 
%% pseudo_push_reg_update(I,Reg) ->
558
 
%%   I#pseudo_push{reg=Reg}.
559
 
 
560
 
%% Pop - pseudo op %
561
 
pseudo_pop_create(Reg, Index) ->
562
 
  #pseudo_pop{reg=Reg, index=Index}.
563
 
pseudo_pop_reg(#pseudo_pop{reg=Reg}) ->
564
 
  Reg.
565
 
pseudo_pop_index(#pseudo_pop{index=Index}) ->
566
 
  Index.
567
 
pseudo_pop_reg_update(I,Reg) ->
568
 
  I#pseudo_pop{reg=Reg}.
569
 
 
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}) ->
574
 
  Src.
575
 
pseudo_spill_pos(#pseudo_spill{dest=Dst}) ->
576
 
  Dst.
577
 
pseudo_spill_reg_update(I,Reg) ->
578
 
  I#pseudo_spill{source=Reg}.
579
 
 
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}) ->
584
 
  Src.
585
 
pseudo_unspill_pos(#pseudo_unspill{dest=Dst}) ->
586
 
  Dst.
587
 
pseudo_unspill_reg_update(I,Reg) ->
588
 
  I#pseudo_unspill{source=Reg}.
589
 
 
590
 
 
591
 
%% Load atom %%
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}.
599
 
 
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.
608
 
 
609
 
%%
610
 
%% Load address
611
 
%%
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}.
621
 
 
622
 
 
623
 
%% 
624
 
%% label
625
 
%%
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.
636
 
 
637
 
 
638
 
%%
639
 
%% nop
640
 
%%
641
 
%% @spec () -> nop()
642
 
nop_create() -> #nop{}.
643
 
%% %% @spec (sparc_instruction()) -> bool()
644
 
%% is_nop(Insn) -> case Insn of #nop{} -> true; _ -> false end.
645
 
 
646
 
 
647
 
%% %% Align %%
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.
656
 
 
657
 
%% Comment %%
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.
666
 
 
667
 
%% Move %%
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.
676
 
 
677
 
%% MultiMove %%
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.
688
 
 
689
 
%% %% Cmov_cc %%
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}.
698
 
 
699
 
%% %% Cmov_r %%
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.
712
 
 
713
 
%% Alu %%
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.
726
 
 
727
 
%% Alu_cc %%
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.
740
 
 
741
 
%% rd %y,Rd %%
742
 
rdy_create(Dest) -> #rdy{dst=Dest}.
743
 
rdy_dest(#rdy{dst=Dst}) -> Dst.
744
 
rdy_dest_update(Rdy,NewDest) -> Rdy#rdy{dst=NewDest}.
745
 
 
746
 
%% Sethi %%
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}.
752
 
 
753
 
%% Load %%
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
759
 
          (Type =:= x)),
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.
771
 
 
772
 
%% Store %%
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
777
 
          (Type =:= x)),
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.
789
 
 
790
 
%% B %%
791
 
b_create(Cond,TrueLabel,FalseLabel,Pred,Annul) -> 
792
 
  #b{cc=Cond,true_label=TrueLabel,false_label=FalseLabel, pred=Pred,
793
 
     annul=Annul}.
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.
809
 
 
810
 
%% Br %%
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.
831
 
 
832
 
 
833
 
%% Goto %%
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.
839
 
 
840
 
 
841
 
%% Jmp_link %%
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.
855
 
 
856
 
%% Jmp %%
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}.
870
 
 
871
 
%% Call_link %%
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) ->
878
 
  case Type of
879
 
    remote -> ok;
880
 
    not_remote -> ok
881
 
  end,
882
 
  #call_link{target=Target, link=Link, 
883
 
             dests=Dests,
884
 
             args=Args, 
885
 
             type=Type,
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)).
907
 
 
908
 
%%--------------------------------------------------------------------------------
909
 
%% FP - instructions
910
 
%%--------------------------------------------------------------------------------
911
 
 
912
 
%% Load float
913
 
%% Type is one of {single, double, quad}
914
 
 
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.
935
 
 
936
 
%% Store %%
937
 
%% Type is one of {single, double, quad}
938
 
 
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.
959
 
 
960
 
 
961
 
%% fb %%
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),
967
 
%%   #fb{fcc=Cond,n=N,
968
 
%%       true_label=TrueLabel,
969
 
%%       false_label=FalseLabel, 
970
 
%%       pred=Pred,
971
 
%%       annul=Annul}.
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.
991
 
 
992
 
 
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.
1015
 
 
1016
 
  
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.
1039
 
      
1040
 
 
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.
1061
 
 
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.
1079
 
 
1080
 
 
1081
 
 
1082
 
%% ____________________________________________________________________
1083
 
%% 
1084
 
 
1085
 
%% ASSERTS
1086
 
-ifdef(DO_ASSERT).
1087
 
is_fptype(Type) ->
1088
 
  (Type =:= single) 
1089
 
    orelse 
1090
 
      (Type =:= double) 
1091
 
    orelse 
1092
 
      (Type =:= quad).
1093
 
 
1094
 
is_fcc(N) ->
1095
 
  (is_integer(N) andalso N >= 0 andalso N =< 3).
1096
 
 
1097
 
is_fop_op(Op) ->
1098
 
  case Op of
1099
 
    '+' -> true;
1100
 
    '-' -> true;
1101
 
    '*' -> true;
1102
 
    '/' -> true;
1103
 
    _   -> false
1104
 
  end.
1105
 
 
1106
 
is_fp_cond(FCC) ->
1107
 
  case FCC of 
1108
 
    'a' ->  true;
1109
 
    'n' ->  true;
1110
 
    'u' ->  true;
1111
 
    'g' ->  true;
1112
 
    'ug' -> true;
1113
 
    'l' ->  true;
1114
 
    'ul' -> true;
1115
 
    'lg' -> true;
1116
 
    'ne' -> true;
1117
 
    'e' ->  true;
1118
 
    'ue' -> true;
1119
 
    'ge' -> true;
1120
 
    'uge'-> true;
1121
 
    'le' -> true;
1122
 
    'ule'-> true;
1123
 
    'o' ->  true;
1124
 
    _  -> false
1125
 
  end.
1126
 
 
1127
 
is_bool(true) ->  true;
1128
 
is_bool(false) -> true;
1129
 
is_bool(_) ->     false.
1130
 
 
1131
 
check_var_range(Sparc) ->
1132
 
  Code = sparc_code(Sparc),
1133
 
  RMax = highest_reg(Code),
1134
 
  {Low, High} = sparc_var_range(Sparc),
1135
 
  RMax =< High.
1136
 
 
1137
 
%% ---------------------------------------------
1138
 
 
1139
 
highest_reg(Code) ->
1140
 
  highest_reg(Code,0).
1141
 
 
1142
 
highest_reg([I|Is],Max) ->
1143
 
  Defs = defines(I),
1144
 
  Uses = uses(I),
1145
 
  highest_reg(Is,new_max(Defs++Uses,Max));
1146
 
highest_reg([],Max) ->
1147
 
  Max.
1148
 
 
1149
 
new_max([V|Vs],Max) ->
1150
 
  VName = reg_nr(V),
1151
 
  if VName > Max ->
1152
 
      new_max(Vs, VName);
1153
 
     true ->
1154
 
      new_max(Vs, Max)
1155
 
  end;
1156
 
new_max([],Max) -> Max.
1157
 
 
1158
 
-endif. %% DO_ASSERT
1159
 
 
1160
 
%% ____________________________________________________________________
1161
 
%% 
1162
 
 
1163
 
%% Integer regs %%
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.
1173
 
 
1174
 
%% FP regs %%
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
1182
 
%%  Name = integer() 
1183
 
fpreg_nr({sparc_fpreg, RegNr}) when is_integer(RegNr) -> RegNr.
1184
 
 
1185
 
%% Immediates %%
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.
1193
 
 
1194
 
%% Spill locations
1195
 
%% mk_spill(Pos) -> {spill, Pos}.
1196
 
is_spill({spill,_}) -> true;
1197
 
is_spill(_) -> false.
1198
 
spill_pos({spill, Pos}) -> Pos.
1199
 
  
1200
 
  
1201
 
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1202
 
%%
1203
 
%% Predicates
1204
 
%%
1205
 
 
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.
1214
 
 
1215
 
%% %% @spec (sparc_instruction()) -> bool()
1216
 
%% is_any_alu(Insn) ->
1217
 
%%   case Insn of
1218
 
%%     #alu{} -> true;
1219
 
%%     #alu_cc{} ->true;
1220
 
%%     _ -> false
1221
 
%%   end.
1222
 
 
1223
 
%% %% @spec (sparc_instruction()) -> bool()
1224
 
%% is_any_cmov(Insn) ->
1225
 
%%   case Insn of
1226
 
%%     #cmov_cc{} -> true;
1227
 
%%     #cmov_r{} -> true;
1228
 
%%     _ -> false
1229
 
%%   end.
1230
 
 
1231
 
%% %% @spec (sparc_instruction()) -> bool()
1232
 
%% is_any_memop(Insn) -> 
1233
 
%%   case Insn of
1234
 
%%     #load{} -> true;
1235
 
%%     #store{} -> true;
1236
 
%%     #load_fp{} -> true;
1237
 
%%     #store_fp{} -> true;
1238
 
%%     _ -> false
1239
 
%%   end.
1240
 
 
1241
 
%% These instrs are branches that need delayslot filling.
1242
 
%% @spec (sparc_instruction()) -> bool()
1243
 
is_any_branch(Insn) -> 
1244
 
  case Insn of
1245
 
    #b{} -> true;
1246
 
%%  #br{} -> true;
1247
 
    #goto{} -> true;
1248
 
    #jmp{} -> true;
1249
 
    #jmp_link{} -> true;
1250
 
    #call_link{} -> case call_link_continuation(Insn) of
1251
 
                      [] -> false;
1252
 
                      _ -> true
1253
 
                    end;
1254
 
    #pseudo_return{} -> true;
1255
 
    #pseudo_enter{} -> true;
1256
 
%%  #fb{} -> true;
1257
 
    _ -> false
1258
 
  end.
1259
 
 
1260
 
%% These instrs are branches that need delayslot filling.
1261
 
%% @spec (sparc_instruction()) -> bool()
1262
 
has_delayslot(Insn) -> 
1263
 
  case Insn of
1264
 
    #b{} -> true;
1265
 
%%  #br -> true;
1266
 
    #goto{} -> true;
1267
 
    #jmp{} -> true;
1268
 
    #jmp_link{} -> true;
1269
 
    #call_link{} -> true;
1270
 
    #pseudo_return{} -> true;
1271
 
    #pseudo_enter{} -> true;
1272
 
%%  #fb{} -> true;
1273
 
    _ -> false
1274
 
  end.
1275
 
 
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) ->
1280
 
  case Jmp of
1281
 
%%  #br{} ->
1282
 
%%       case br_true_label(Jmp) of
1283
 
%%      ToOld ->
1284
 
%%        br_true_label_update(Jmp, ToNew);
1285
 
%%      _ ->
1286
 
%%        case br_false_label(Jmp) of
1287
 
%%          ToOld ->
1288
 
%%            br_false_label_update(Jmp, ToNew);
1289
 
%%          _ ->
1290
 
%%            Jmp
1291
 
%%        end
1292
 
%%       end;
1293
 
    #b{} ->
1294
 
      case b_true_label(Jmp) of
1295
 
        ToOld ->
1296
 
          b_true_label_update(Jmp, ToNew);
1297
 
        _ ->
1298
 
          case b_false_label(Jmp) of
1299
 
            ToOld ->
1300
 
              b_false_label_update(Jmp, ToNew);
1301
 
            _ ->
1302
 
              Jmp
1303
 
          end
1304
 
      end;
1305
 
    #goto{} ->
1306
 
      case goto_label(Jmp) of
1307
 
        ToOld ->
1308
 
          goto_label_update(Jmp, ToNew);
1309
 
        _ ->
1310
 
          Jmp
1311
 
      end;
1312
 
    #jmp{} -> 
1313
 
      NewDests = replace(ToOld, ToNew, jmp_destinations(Jmp)),
1314
 
      jmp_destinations_update(Jmp, NewDests);
1315
 
    #call_link{} ->
1316
 
      case call_link_continuation(Jmp) of
1317
 
        ToOld ->
1318
 
          call_link_continuation_update(Jmp, ToNew);
1319
 
        _ ->
1320
 
          case call_link_fail(Jmp) of
1321
 
            ToOld ->
1322
 
              call_link_fail_update(Jmp, ToNew);
1323
 
            _ ->
1324
 
              Jmp
1325
 
          end
1326
 
      end;
1327
 
%%  #fb{} ->
1328
 
%%       case fb_true_label(Jmp) of
1329
 
%%      ToOld ->
1330
 
%%        fb_true_label_update(Jmp, ToNew);
1331
 
%%      _ ->
1332
 
%%        case fb_false_label(Jmp) of
1333
 
%%          ToOld ->
1334
 
%%            fb_false_label_update(Jmp, ToNew);
1335
 
%%          _ ->
1336
 
%%            Jmp
1337
 
%%        end
1338
 
%%       end;
1339
 
    _ ->
1340
 
      Jmp
1341
 
  end.
1342
 
 
1343
 
replace(Old, New, List) ->
1344
 
  [if X =:= Old ->
1345
 
       New; 
1346
 
      true -> X
1347
 
   end || X <- List].
1348
 
                    
1349
 
%% @spec (condition_code()) -> condition_code()
1350
 
%% @doc Returns the negation of an integer condition code.
1351
 
cc_negate(Cond) ->
1352
 
  case Cond of
1353
 
    'a' -> 'n';
1354
 
    'n' -> 'a';
1355
 
    'ne'-> 'e';
1356
 
    'e' -> 'ne';
1357
 
    'g' -> 'le';
1358
 
    'le' -> 'g';
1359
 
    'ge' -> 'l';
1360
 
    'l' -> 'ge';
1361
 
    'gu' -> 'leu';
1362
 
    'leu' -> 'gu';
1363
 
    'geu' -> 'lu';
1364
 
    'lu'  -> 'geu';
1365
 
    'pos' -> 'neg';
1366
 
    'neg' -> 'pos';
1367
 
    'vc' ->  'vs';
1368
 
    'vs' ->  'vc'
1369
 
  end.
1370
 
 
1371
 
 
1372
 
%% %% @spec (fp_cond()) -> fp_cond()
1373
 
%% %% @doc Returns the negation of an fp condition code.
1374
 
%% fcc_negate(Cond) ->
1375
 
%%  case Cond of
1376
 
%%    'a'       ->  'n';
1377
 
%%    'n'       ->  'a';
1378
 
%%    'u'       ->  'o';
1379
 
%%    'g'       ->  'ule';
1380
 
%%    'ug' -> 'le';
1381
 
%%    'l'       ->  'uge';
1382
 
%%    'ul' -> 'ge';
1383
 
%%    'lg' -> 'ue';
1384
 
%%    'ne' -> 'e';
1385
 
%%    'e'       ->  'ne';
1386
 
%%    'ue' -> 'lg';
1387
 
%%    'ge' -> 'ul';
1388
 
%%    'uge'-> 'l';
1389
 
%%    'le' -> 'ug';
1390
 
%%    'ule'-> 'g';
1391
 
%%    'o'       ->  'u'
1392
 
%%   end.
1393
 
 
1394
 
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1395
 
%%
1396
 
%% Def/Use by instruction.
1397
 
%%
1398
 
%% The condition code registers is read and written like any other. 
1399
 
%% We define a _virtual_ for icc and xcc.
1400
 
%%
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()).
1408
 
 
1409
 
 
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)).
1415
 
 
1416
 
 
1417
 
%% @spec (sparc_instruction()) -> [reg()]
1418
 
%% @doc Returns a list of integer registers that are used by an instruction.
1419
 
uses(Instr) -> 
1420
 
  %% keep_registers(all_uses(Instr)).
1421
 
  remove_immediates(all_uses(Instr)).
1422
 
 
1423
 
%% @spec (sparc_instruction()) -> [operand()]
1424
 
%% @doc Returns a list of operands that are used by an instruction
1425
 
all_uses(Ins) ->
1426
 
  case Ins of
1427
 
    #label{} -> [];
1428
 
    #nop{} -> [];
1429
 
%%  #align{} -> [];
1430
 
    #comment{} -> [];
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)];
1443
 
    #goto{} -> [];
1444
 
    #jmp_link{} ->
1445
 
      [jmp_link_target(Ins), jmp_link_off(Ins) | jmp_link_args(Ins)];
1446
 
    #jmp{} -> [jmp_target(Ins), jmp_off(Ins) | jmp_args(Ins)];
1447
 
    #call_link{} -> 
1448
 
      case call_link_is_known(Ins) of
1449
 
        false ->
1450
 
          [call_link_target(Ins)|call_link_args(Ins)];
1451
 
        true ->
1452
 
          call_link_args(Ins)
1453
 
      end;
1454
 
    #load_atom{} -> [];
1455
 
    #load_word_index{} -> [];
1456
 
    #pseudo_return{} -> pseudo_return_regs(Ins);
1457
 
    #pseudo_enter{} -> 
1458
 
      case pseudo_enter_is_known(Ins) of
1459
 
        false ->
1460
 
          [pseudo_enter_target(Ins)|
1461
 
           pseudo_enter_args(Ins)];
1462
 
        true ->
1463
 
          pseudo_enter_args(Ins)
1464
 
      end;
1465
 
    #pseudo_spill{} -> [pseudo_spill_reg(Ins)];
1466
 
    #pseudo_unspill{} -> [];
1467
 
%%  #pseudo_push{} -> [pseudo_push_reg(Ins)];
1468
 
    #pseudo_pop{} -> [];
1469
 
 
1470
 
    #load_fp{} -> [load_fp_off(Ins), load_fp_src(Ins)];
1471
 
    #store_fp{} ->
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)])]
1476
 
      end;
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{} -> []
1483
 
  end.
1484
 
 
1485
 
%% @spec (sparc_instruction()) -> [imm()]
1486
 
%% @doc Returns a list of immediates that are used by an instruction
1487
 
imm_uses(Instr) ->
1488
 
  keep_imms(all_uses(Instr)).
1489
 
 
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)).
1494
 
 
1495
 
 
1496
 
%% @spec (sparc_instruction()) -> [reg()]
1497
 
%% @doc Returns a list of registers that are defined by an instruction
1498
 
defines(Ins) ->
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)).
1505
 
 
1506
 
%% fpregs_and_regs_defines(Ins) ->
1507
 
%%   keep_imms(all_defines(Ins)).
1508
 
 
1509
 
%% @spec (sparc_instruction()) -> [operand()]
1510
 
%% @doc Returns a list of operands that are defined by an instruction
1511
 
all_defines(Ins)->
1512
 
  case Ins of
1513
 
    #label{} -> [];
1514
 
    #nop{} -> [];
1515
 
%%  #align{} -> [];
1516
 
    #comment{} -> [];
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)];
1526
 
    #store{} -> [];
1527
 
    #b{} -> [];
1528
 
%%  #br{} -> [];
1529
 
    #goto{} -> [];
1530
 
    #jmp_link{} -> [jmp_link_link(Ins)];
1531
 
    #jmp{} -> [];
1532
 
    #call_link{} -> 
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)];
1544
 
    #load_fp{} -> 
1545
 
      case load_fp_type(Ins) of
1546
 
        single ->[load_fp_dest(Ins)];
1547
 
        _ -> format_fpreg([load_fp_dest(Ins)])
1548
 
      end;
1549
 
    #store_fp{} -> [];
1550
 
%%  #fb{} -> [];
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)]
1556
 
  end.
1557
 
 
1558
 
 
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.
1562
 
%%
1563
 
all_def_uses(I) ->
1564
 
  case I of
1565
 
    #label{} -> {[],[]};
1566
 
    #nop{} -> {[],[]};
1567
 
%%  #align{} -> {[],[]};
1568
 
    #comment{} ->  {[],[]};
1569
 
    #move{} -> 
1570
 
        {[move_dest(I)],
1571
 
         [move_src(I)]};
1572
 
    #multimove{} -> 
1573
 
        {multimove_dest(I),
1574
 
         multimove_src(I)};
1575
 
%%  #cmov_cc{} ->
1576
 
%%      {[cmov_cc_dest(I)],
1577
 
%%       [icc_reg(), xcc_reg(), cmov_cc_src(I)]};
1578
 
%%       cmov_r ->
1579
 
%%      {[cmov_r_dest(I)],
1580
 
%%       [cmov_r_src(I), cmov_r_reg(I)]};
1581
 
    #alu{} ->
1582
 
        {[alu_dest(I)],
1583
 
         [alu_src1(I), alu_src2(I)]};
1584
 
    #alu_cc{} ->
1585
 
        {[icc_reg(), xcc_reg(), alu_cc_dest(I)],
1586
 
         [alu_cc_src1(I), alu_cc_src2(I)]};
1587
 
    #rdy{} ->
1588
 
        {[rdy_dest(I)],
1589
 
         [y_reg()]};
1590
 
    #sethi{} ->
1591
 
        {[sethi_dest(I)], 
1592
 
         [sethi_const(I)]};
1593
 
    #load{} -> 
1594
 
        {[load_dest(I)],
1595
 
         [load_src(I), load_off(I)]};
1596
 
    #store{} ->
1597
 
        {[],
1598
 
         [store_dest(I), store_src(I), store_off(I)]};
1599
 
    #b{} ->
1600
 
        {[],
1601
 
         [icc_reg(), xcc_reg()]};
1602
 
%%  #br{} ->
1603
 
%%      {[],
1604
 
%%       [br_reg(I)]};
1605
 
    #goto{} -> {[],[]};
1606
 
    #jmp_link{} ->
1607
 
        {[jmp_link_link(I)],
1608
 
         [jmp_link_target(I), jmp_link_off(I) | jmp_link_args(I)]};
1609
 
    #jmp{} ->
1610
 
        {[],
1611
 
         [jmp_target(I), jmp_off(I) | jmp_args(I)]};
1612
 
    #call_link{} ->
1613
 
        {[call_link_link(I)|call_link_dests(I)],
1614
 
         case call_link_is_known(I) of
1615
 
           false -> 
1616
 
             [call_link_target(I)|call_link_args(I)];
1617
 
           true -> call_link_args(I)
1618
 
         end};
1619
 
    #load_atom{} ->
1620
 
        {[load_atom_dest(I)],
1621
 
         []};
1622
 
    #load_word_index{} ->
1623
 
        {[load_word_index_dest(I)],
1624
 
         []};
1625
 
    #pseudo_return{} ->
1626
 
        {[],
1627
 
         pseudo_return_regs(I)};
1628
 
    #pseudo_enter{} ->
1629
 
        {[],
1630
 
         case pseudo_enter_is_known(I) of
1631
 
           false ->
1632
 
             [pseudo_enter_target(I)|
1633
 
              pseudo_enter_args(I)];
1634
 
           true ->
1635
 
             pseudo_enter_args(I)
1636
 
         end};
1637
 
    #pseudo_spill{} ->
1638
 
        {[],
1639
 
         [pseudo_spill_reg(I)]};
1640
 
    #pseudo_unspill{} ->
1641
 
        {[pseudo_unspill_reg(I)],
1642
 
         []};
1643
 
%   #pseudo_push{} ->
1644
 
%       {[],
1645
 
%        [pseudo_push_reg(I)]};
1646
 
    #pseudo_pop{} ->
1647
 
        {[pseudo_pop_reg(I)],
1648
 
         []};
1649
 
    #load_fp{} ->
1650
 
        case load_fp_type(I) of
1651
 
          single ->
1652
 
            {[load_fp_dest(I)],
1653
 
             [load_fp_src(I), load_fp_off(I)]};
1654
 
          _ ->
1655
 
            {format_fpreg([load_fp_dest(I)]),
1656
 
             [load_fp_src(I), load_fp_off(I)]}
1657
 
        end;
1658
 
    #store_fp{} ->
1659
 
        case store_fp_type(I) of
1660
 
          single ->
1661
 
            {[],
1662
 
             [store_fp_src(I), store_fp_off(I), store_fp_dest(I)]};
1663
 
          _ ->
1664
 
            {[],
1665
 
             [store_fp_off(I), store_fp_dest(I) |
1666
 
              format_fpreg([store_fp_src(I)])]}
1667
 
        end;
1668
 
%%  #fb{} ->
1669
 
%%      {[],
1670
 
%%       [fcc_reg(fb_fcc_reg(I))]};
1671
 
    #fop{} ->
1672
 
        {format_fpreg([fop_dest(I)]),
1673
 
         format_fpreg([fop_src1(I), fop_src2(I)])}; 
1674
 
%%  fcmp{} -> 
1675
 
%%      {[fcc_reg(fcmp_fcc_reg(I))],
1676
 
%%       format_fpreg([fcmp_src1(I), fcmp_src2(I)])};
1677
 
    #fmove{} -> 
1678
 
        {format_fpreg([fmove_dest(I)]),
1679
 
         format_fpreg([fmove_src(I)])};
1680
 
    #conv_fp{} -> 
1681
 
        {format_fpreg([conv_fp_dest(I)]),
1682
 
         [conv_fp_src(I)]};
1683
 
    #load_address{} -> 
1684
 
        {[load_address_dest(I)],
1685
 
         []}
1686
 
  end.
1687
 
 
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.
1691
 
def_use(I) ->
1692
 
  {Def,Use} = all_def_uses(I),
1693
 
  {keep_registers(Def), keep_registers(Use)}.
1694
 
 
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)}.
1701
 
 
1702
 
%% fpregs_and_regs_def_use(I) ->
1703
 
%%   {Def,Use} = all_def_uses(I),
1704
 
%%   {remove_immediates(Def), remove_immediates(Use)}.
1705
 
 
1706
 
%%
1707
 
%% Makes sure the single precision registers that makes up a double 
1708
 
%% precision one is marked as defines and uses.
1709
 
%%
1710
 
 
1711
 
format_fpreg(Reg)->
1712
 
  format_fpreg(Reg, []).
1713
 
 
1714
 
format_fpreg([H|T], Acc)->
1715
 
  case is_fpreg(H) of
1716
 
    true ->
1717
 
      RegNr = fpreg_nr(H),
1718
 
      case hipe_sparc_specific_fp:is_precoloured(RegNr) of
1719
 
        true ->
1720
 
          format_fpreg(T, [H, mk_fpreg(RegNr+1)|Acc]);
1721
 
        _ ->
1722
 
          format_fpreg(T, [H|Acc])
1723
 
      end;
1724
 
    _ ->
1725
 
      format_fpreg(T, [H|Acc])
1726
 
  end;
1727
 
format_fpreg([], Acc) ->
1728
 
  Acc.
1729
 
 
1730
 
%%
1731
 
%% Remove immediates from a list
1732
 
%%
1733
 
 
1734
 
remove_immediates([]) -> 
1735
 
  [];
1736
 
remove_immediates([I|Is]) ->
1737
 
  case is_imm(I) of
1738
 
    true -> remove_immediates(Is);
1739
 
    false -> [I | remove_immediates(Is)]
1740
 
  end.
1741
 
 
1742
 
 
1743
 
%%
1744
 
%% Remove registers from a list
1745
 
%%
1746
 
 
1747
 
%% remove_registers([]) -> 
1748
 
%%   [];
1749
 
%% remove_registers([I|Is]) ->
1750
 
%%   case is_reg(I) of
1751
 
%%     true -> remove_registers(Is);
1752
 
%%     false -> 
1753
 
%%       case is_fpreg(I) of
1754
 
%%      true -> remove_registers(Is);
1755
 
%%      false -> [I | remove_registers(Is)]
1756
 
%%       end
1757
 
%%   end.
1758
 
 
1759
 
 
1760
 
%%
1761
 
%% Keep registers in a list
1762
 
%%
1763
 
 
1764
 
keep_registers([]) -> 
1765
 
  [];
1766
 
keep_registers([I|Is]) ->
1767
 
  case is_reg(I) of
1768
 
    true -> [I | keep_registers(Is)];
1769
 
    false -> keep_registers(Is)
1770
 
  end.
1771
 
 
1772
 
%%
1773
 
%% Keep float registers in a list
1774
 
%%
1775
 
 
1776
 
keep_fp_registers([]) -> 
1777
 
  [];
1778
 
keep_fp_registers([I|Is]) ->
1779
 
  case is_fpreg(I) of
1780
 
    true -> [I | keep_fp_registers(Is)];
1781
 
    false -> keep_fp_registers(Is)
1782
 
  end.
1783
 
 
1784
 
%%
1785
 
%% Keep immediates in a list
1786
 
%%
1787
 
 
1788
 
keep_imms([]) -> 
1789
 
  [];
1790
 
keep_imms([I|Is]) ->
1791
 
  case is_imm(I) of
1792
 
    true -> [I | keep_imms(Is)];
1793
 
    false -> keep_imms(Is)
1794
 
  end.
1795
 
 
1796
 
 
1797
 
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1798
 
%% @spec (Ins::sparc_instruction(), Subst) -> sparc_instruction()
1799
 
%%            Subst = [{Old, New}]
1800
 
%%            Old = operand()
1801
 
%%            New = operand()
1802
 
%% @doc Substitution -- replace occurrences of the operator Old by New if {Old,New} is in Subst.
1803
 
subst(Ins, Subst) ->
1804
 
  case Ins of
1805
 
    #label{} -> Ins;
1806
 
    #nop{} -> Ins;
1807
 
%%  #align{} -> Ins;
1808
 
    #comment{} -> Ins;
1809
 
    #b{} -> Ins;
1810
 
    #goto{} -> Ins;
1811
 
    #rdy{} ->
1812
 
      NewDst = subst1(Subst, rdy_dest(Ins)),
1813
 
      rdy_dest_update(Ins, NewDst);
1814
 
    #sethi{} ->
1815
 
      NewDst = subst1(Subst, sethi_dest(Ins)),
1816
 
      sethi_dest_update(Ins, NewDst);
1817
 
%%  #br{} ->
1818
 
%%    NewReg = subst1(Subst, br_reg(Ins)),
1819
 
%%    br_reg_update(Ins, NewReg);
1820
 
    #call_link{} ->
1821
 
      Ins1 =
1822
 
        case call_link_is_known(Ins) of
1823
 
          false ->
1824
 
            NewTarget = subst1(Subst, call_link_target(Ins)),
1825
 
            call_link_target_update(Ins, NewTarget);
1826
 
          true -> Ins
1827
 
        end,
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);
1832
 
    #load_atom{} ->
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);
1838
 
    #load_address{} ->
1839
 
      NewDst = subst1(Subst, load_address_dest(Ins)),
1840
 
      load_address_dest_update(Ins, NewDst);
1841
 
    #move{} ->
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);
1846
 
    #multimove{} ->
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);
1851
 
%%  #cmov_cc{} ->
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);
1856
 
%%  #cmov_r{} ->
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);
1863
 
    #alu{} ->
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);
1870
 
    #alu_cc{} ->
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);
1877
 
    #load{} ->
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);
1884
 
    #store{} ->
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);
1891
 
    #jmp_link{} ->
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);
1898
 
    #pseudo_return{} ->
1899
 
      NewRegs = subst_list(Subst, pseudo_return_regs(Ins)),
1900
 
      pseudo_return_regs_update(Ins, NewRegs);
1901
 
    #pseudo_enter{} ->
1902
 
      NewI = 
1903
 
        case pseudo_enter_is_known(Ins) of
1904
 
          false ->
1905
 
            pseudo_enter_target_update(Ins,
1906
 
                                       subst1(Subst,pseudo_enter_target(Ins)));
1907
 
          true ->
1908
 
            Ins
1909
 
        end,
1910
 
      NewRegs = subst_list(Subst, pseudo_enter_args(NewI)),
1911
 
      pseudo_enter_args_update(NewI, NewRegs);
1912
 
    #pseudo_spill{} ->
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);
1918
 
%   #pseudo_push{} ->
1919
 
%     NewReg = subst1(Subst, pseudo_push_reg(Ins)),
1920
 
%     pseudo_push_reg_update(Ins, NewReg);
1921
 
    #pseudo_pop{} ->
1922
 
      NewReg = subst1(Subst, pseudo_pop_reg(Ins)),
1923
 
      pseudo_pop_reg_update(Ins, NewReg);
1924
 
 
1925
 
    #load_fp{} ->
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);
1932
 
    #store_fp{} ->
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);
1939
 
%%  #fb{} -> Ins;
1940
 
    #fop{} ->
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);
1947
 
%%  #fcmp{} ->
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);
1952
 
    #fmove{} ->
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);
1957
 
    #conv_fp{} ->
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);
1962
 
    #jmp{} ->
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)
1967
 
  end.
1968
 
 
1969
 
%% @spec (Ins::sparc_instruction(), Subst) -> sparc_instruction()
1970
 
%%            Subst = [{Old, New}]
1971
 
%%            Old = operand()
1972
 
%%            New = operand()
1973
 
%% @doc Substitution -- 
1974
 
%% replace defined occurrences of the operator Old by New if {Old,New} is in Subst.
1975
 
subst_defines(Ins, Subst) ->
1976
 
  case Ins of
1977
 
    #label{} -> Ins;
1978
 
    #nop{} -> Ins;
1979
 
%%  #align{} -> Ins;
1980
 
    #comment{} -> Ins;
1981
 
    #b{} -> Ins;
1982
 
    #goto{} -> Ins;
1983
 
    #jmp{} -> Ins;
1984
 
%%  #br{} -> Ins;
1985
 
    #rdy{} ->
1986
 
      NewDst = subst1(Subst, rdy_dest(Ins)),
1987
 
      rdy_dest_update(Ins, NewDst);
1988
 
    #sethi{} ->
1989
 
      NewDst = subst1(Subst, sethi_dest(Ins)),
1990
 
      sethi_dest_update(Ins, NewDst);
1991
 
    #call_link{} ->
1992
 
      NewLink = subst1(Subst, call_link_link(Ins)),
1993
 
      call_link_link_update(Ins, NewLink);
1994
 
    #load_atom{} ->
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);
2000
 
    #load_address{} ->
2001
 
      NewDst = subst1(Subst, load_address_dest(Ins)),
2002
 
      load_address_dest_update(Ins, NewDst);
2003
 
    #move{} ->
2004
 
      NewDst = subst1(Subst, move_dest(Ins)),
2005
 
      move_dest_update(Ins, NewDst);
2006
 
    #multimove{} ->
2007
 
      NewDst = subst_list(Subst, multimove_dest(Ins)),
2008
 
      multimove_dest_update(Ins, NewDst);
2009
 
%%  #cmov_cc{} ->
2010
 
%%       NewDst = subst1(Subst, cmov_cc_dest(Ins)),
2011
 
%%       cmov_cc_dest_update(Ins, NewDst);
2012
 
%%  #cmov_r{} ->
2013
 
%%       NewDst = subst1(Subst, cmov_r_dest(Ins)),
2014
 
%%       cmov_r_dest_update(Ins, NewDst);
2015
 
    #alu{} ->
2016
 
      NewDst = subst1(Subst, alu_dest(Ins)),
2017
 
      alu_dest_update(Ins, NewDst);
2018
 
    #alu_cc{} ->
2019
 
      NewDst = subst1(Subst, alu_cc_dest(Ins)),
2020
 
      alu_cc_dest_update(Ins, NewDst);
2021
 
    #load{} ->
2022
 
      NewDst = subst1(Subst, load_dest(Ins)),
2023
 
      load_dest_update(Ins, NewDst);
2024
 
    #store{} -> Ins;
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;
2032
 
    #pseudo_pop{} ->
2033
 
      NewReg = subst1(Subst, pseudo_pop_reg(Ins)),
2034
 
      pseudo_pop_reg_update(Ins, NewReg);
2035
 
    #load_fp{} ->
2036
 
      NewDst = subst1(Subst, load_fp_dest(Ins)),
2037
 
      load_fp_dest_update(Ins, NewDst);
2038
 
    #store_fp{} -> Ins;
2039
 
%%  #fb{} -> Ins;
2040
 
    #fop{} ->
2041
 
      NewDst = subst1(Subst, fop_dest(Ins)),
2042
 
      fop_dest_update(Ins, NewDst);
2043
 
%%  #fcmp{} -> Ins; %% XXX: Should handle fccn updates.
2044
 
    #fmove{} ->
2045
 
      NewDst = subst1(Subst, fmove_dest(Ins)),
2046
 
      fmove_dest_update(Ins, NewDst);
2047
 
    #conv_fp{} ->
2048
 
      NewDst = subst1(Subst, conv_fp_dest(Ins)),
2049
 
      conv_fp_dest_update(Ins, NewDst);
2050
 
    #jmp_link{} ->
2051
 
      NewLink = subst1(Subst, jmp_link_link(Ins)),
2052
 
      jmp_link_link_update(Ins, NewLink)
2053
 
  end.
2054
 
 
2055
 
 
2056
 
%% @spec (Ins::sparc_instruction(), Subst) -> sparc_instruction()
2057
 
%%            Subst = [{Old, New}]
2058
 
%%            Old = operand()
2059
 
%%            New = operand()
2060
 
%% @doc Substitution -- 
2061
 
%% replace used occurrences of the operator Old by New if {Old,New} is in Subst.
2062
 
subst_uses(Ins, Subst) ->
2063
 
  case Ins of
2064
 
    #label{} -> Ins;
2065
 
    #nop{} -> Ins;
2066
 
%%  #align{} -> Ins;
2067
 
    #comment{} -> Ins;
2068
 
    #b{} -> Ins;
2069
 
    #goto{} -> Ins;
2070
 
    #rdy{} -> Ins;
2071
 
    #sethi{} -> Ins;
2072
 
    #call_link{} -> 
2073
 
      case call_link_is_known(Ins) of
2074
 
        false ->
2075
 
          NewTarget = subst1(Subst, call_link_target(Ins)),
2076
 
          call_link_target_update(Ins, NewTarget);
2077
 
        true -> Ins
2078
 
      end;
2079
 
    #load_atom{} -> Ins;
2080
 
    #load_word_index{} -> Ins;
2081
 
    #load_address{} -> Ins;
2082
 
%%  #br{} ->
2083
 
%%    NewReg = subst1(Subst, br_reg(Ins)),
2084
 
%%    br_reg_update(Ins, NewReg);
2085
 
    #move{} ->
2086
 
      NewSrc = subst1(Subst, move_src(Ins)),
2087
 
      move_src_update(Ins, NewSrc);
2088
 
    #multimove{} ->
2089
 
      NewSrc = subst_list(Subst, multimove_src(Ins)),
2090
 
      multimove_src_update(Ins, NewSrc);
2091
 
%%  #cmov_cc{} ->
2092
 
%%    NewSrc = subst1(Subst, cmov_cc_src(Ins)),
2093
 
%%    cmov_cc_src_update(Ins, NewSrc);
2094
 
%%  #cmov_r{} ->
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);
2099
 
    #alu{} ->
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);
2104
 
    #alu_cc{} ->
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);
2109
 
    #load{} ->
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);
2114
 
    #store{} ->
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);
2121
 
    #jmp_link{} ->
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);
2126
 
    #pseudo_return{} ->
2127
 
      NewRegs = subst_list(Subst, pseudo_return_regs(Ins)),
2128
 
      pseudo_return_regs_update(Ins, NewRegs);
2129
 
    #pseudo_enter{} ->
2130
 
      NewI = 
2131
 
        case pseudo_enter_is_known(Ins) of
2132
 
          false ->
2133
 
            pseudo_enter_target_update(Ins,
2134
 
                                       subst1(Subst,pseudo_enter_target(Ins)));
2135
 
          true ->
2136
 
            Ins
2137
 
        end,
2138
 
      NewRegs = subst_list(Subst, pseudo_enter_args(NewI)),
2139
 
      pseudo_enter_args_update(NewI, NewRegs);
2140
 
    #pseudo_spill{} ->
2141
 
      NewReg = subst1(Subst, pseudo_spill_reg(Ins)),
2142
 
      pseudo_spill_reg_update(Ins, NewReg);
2143
 
    #pseudo_unspill{} ->
2144
 
      Ins;
2145
 
%   #pseudo_push{} ->
2146
 
%     NewReg = subst1(Subst, pseudo_push_reg(Ins)),
2147
 
%     pseudo_push_reg_update(Ins, NewReg);
2148
 
    #pseudo_pop{} ->
2149
 
      Ins;
2150
 
    #load_fp{} ->
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);
2155
 
    #store_fp{} ->
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.
2163
 
    #fop{} ->
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);
2168
 
%%  #fcmp{} ->
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);
2173
 
    #fmove{} ->
2174
 
      NewSrc = subst1(Subst, fmove_src(Ins)),
2175
 
      fmove_src_update(Ins, NewSrc);
2176
 
    #conv_fp{} ->
2177
 
      NewSrc = subst1(Subst, conv_fp_src(Ins)),
2178
 
      conv_fp_src_update(Ins, NewSrc);
2179
 
    #jmp{} ->
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)
2184
 
  end.
2185
 
 
2186
 
subst_list(S,Xs) ->
2187
 
  [subst1(S,X) || X <- Xs].
2188
 
 
2189
 
subst1([],X) -> 
2190
 
  X;
2191
 
subst1([{X,Y}|_],X) -> 
2192
 
  Y;
2193
 
subst1([_|Xs],X) -> 
2194
 
  subst1(Xs,X).
2195
 
 
2196
 
%% ----------------------------------------------