~ubuntu-branches/ubuntu/karmic/erlang/karmic

« back to all changes in this revision

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

  • Committer: Bazaar Package Importer
  • Author(s): Sergei Golovan
  • Date: 2009-05-01 10:14:38 UTC
  • mfrom: (3.1.4 sid)
  • Revision ID: james.westby@ubuntu.com-20090501101438-6qlr6rsdxgyzrg2z
Tags: 1:13.b-dfsg-2
* Cleaned up patches: removed unneeded patch which helped to support
  different SCTP library versions, made sure that changes for m68k
  architecture applied only when building on this architecture.
* Removed duplicated information from binary packages descriptions.
* Don't require libsctp-dev build-dependency on solaris-i386 architecture
  which allows to build Erlang on Nexenta (thanks to Tim Spriggs for
  the suggestion).

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
%% -*- erlang-indent-level: 2 -*-
2
 
%% ====================================================================
3
 
%%  Filename :  hipe_sparc_assemble.erl
4
 
%%  Module   :  hipe_sparc_assemble
5
 
%%  Purpose  :  Writes SPARC-code to memory. 
6
 
%%  Notes    :  Not all SPARC instructions are handled.
7
 
%%  History  :  * 1998-06-18 Erik Johansson (happi@csd.uu.se): Created.
8
 
%% CVS:
9
 
%%     $Id$
10
 
%% ====================================================================
11
 
%% @doc
12
 
%%
13
 
%% Module that assembles SPARC code and returns it in the form of
14
 
%% HiPE's external format.
15
 
%%
16
 
%% The external format for SPARC code is a binary representation of an
17
 
%% Erlang list of the form:
18
 
%% <pre>
19
 
%%    [Version::version(),
20
 
%%     ConstSize::size(), ConstMap::constmap(), LabelMap::labelmap(),
21
 
%%     ExportMap::exportmap(),
22
 
%%     HotSize::size(),   HotCode::code(),   HotRefs::refs(),
23
 
%%     ColdSize::size(),  ColdCode::code(),  ColdRefs::refs()
24
 
%%    ]
25
 
%% </pre>
26
 
%% where
27
 
%% <ul>
28
 
%%   <li><code> version():   {VERSION::string(), SYSTEM-CHECKSUM} </code></li>
29
 
%%   <li><code> size():      non_neg_integer() </code></li>
30
 
%%   <li><code> constmap():  [ConstNo::integer(), Offset::integer(),
31
 
%%                            Need::integer(), Type::consttype(),
32
 
%%                            Exported::bool(), Data::term()
33
 
%%                            | constmap] </code></li>
34
 
%%   <li><code> labelmap():  [{DataOffset:integer, CodeOffset:integer}
35
 
%%                            | labelmap] </code></li>
36
 
%%   <li><code> exportmap(): [Offset::integer(), Module::atom(),
37
 
%%                            Function::atom(), Arity::integer()
38
 
%%                            | exportmap()] </code>
39
 
%%                                A list sorted on <code>Offset</code>. </li>
40
 
%%   <li><code> code():      [B4::byte(), B3::byte(), B2::byte(), B1::byte()
41
 
%%                            | code()] </code></li>
42
 
%%   <li><code> refs():      [{RefType:integer, Reflist:reflist}
43
 
%%                            | refs()] </code></li>
44
 
%%
45
 
%%   <li><code> reflist():   [{Data::term(),Offsets::offests()}
46
 
%%                            | reflist()] </code></li>
47
 
%%   <li><code> offsets():   [Offset::integer() | offsets()] </code></li>
48
 
%%
49
 
%%   <li><code> constype():  0 | 1 </code> (0 -> term (arbitrary erlang term), 
50
 
%%                                          1 -> block (a list of bytes)) </li>
51
 
%%   <li><code> bool():      0 | 1 </code> (false, true) </li>
52
 
%%   <li><code> mode():      hot | cold</code></li>
53
 
%% </ul>
54
 
%%
55
 
%% @end
56
 
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
57
 
 
58
 
-module(hipe_sparc_assemble).
59
 
-export([assemble/4]).
60
 
 
61
 
%-ifndef(DEBUG).
62
 
%-define(DEBUG,true).
63
 
%-endif.
64
 
-define(DO_ASSERT,true).
65
 
 
66
 
-include("../../kernel/src/hipe_ext_format.hrl").
67
 
-include("../main/hipe.hrl").
68
 
-include("hipe_sparc.hrl").
69
 
-include("../rtl/hipe_literals.hrl").
70
 
 
71
 
%%---------------------------------------------------------------------
72
 
%% @spec assemble(term(), term(), [terms()], [Option]) -> binary()
73
 
%%     Option = term()
74
 
%% @doc  Assembles the compiled code in a SPARC-specific way and
75
 
%%       returns a binary according to HiPE's external format.
76
 
%% @end
77
 
%%---------------------------------------------------------------------
78
 
 
79
 
assemble(CompiledCode, Closures, Exports, Options) ->
80
 
  ?when_option(time, Options, ?start_timer("SPARC assembler")),
81
 
  {ConstAlign,ConstSize,ConstMap,RefsFromConsts} =
82
 
    hipe_pack_constants:pack_constants(CompiledCode,
83
 
                                       hipe_sparc_registers:alignment()),
84
 
  %% io:format("Const Size ~w\n",[ConstSize]),
85
 
  {CodeSize,ExportMap,Code} = get_code(CompiledCode),
86
 
  {AccHCode,AccHRefs} = linker(Code,ExportMap,ConstMap),
87
 
  CodeBinary = mk_code_binary(AccHCode),
88
 
  Bin = term_to_binary([{?VERSION_STRING(),?HIPE_SYSTEM_CRC},
89
 
                        ConstAlign, ConstSize,
90
 
                        hipe_pack_constants:slim_constmap(ConstMap),
91
 
                        mk_labelmap(RefsFromConsts, ExportMap),
92
 
                        slim_exportmap(ExportMap, Closures, Exports),
93
 
                        CodeSize,CodeBinary,
94
 
                        hipe_pack_constants:slim_refs(AccHRefs),
95
 
                        0,[] % ColdCodeSize, SlimColdRefs
96
 
                       ]),
97
 
  ?when_option(time, Options, ?stop_timer("SPARC assembler")),
98
 
  Bin.
99
 
 
100
 
mk_code_binary(AccHCode) ->
101
 
  list_to_binary(words32towords8(AccHCode)).
102
 
 
103
 
words32towords8(List) ->
104
 
  lists:foldr(fun word32towords8/2, [], List).
105
 
 
106
 
word32towords8(X1, Acc) ->
107
 
  X2 = X1 bsr 8,
108
 
  X3 = X2 bsr 8, 
109
 
  X4 = X3 bsr 8,
110
 
  [X4, (X3 band 16#ff), X2 band 16#ff, X1 band 16#ff | Acc].
111
 
 
112
 
mk_labelmap(Map, ExportMap) ->
113
 
  %% msg("Map: ~w Map\n",[Map]),
114
 
  LblMap = lists:flatten(mk_labelmap(Map, ExportMap, [])),
115
 
  %% msg("LblMap: ~w Map\n",[LblMap]),
116
 
  LblMap.
117
 
 
118
 
mk_labelmap([{MFA, Labels}| Rest], ExportMap, Acc) ->
119
 
  Map = [case Label of
120
 
           {L,Pos} ->
121
 
             {Pos, find_offset({MFA,L}, ExportMap)};
122
 
           {sorted,Base,OrderedLabels} ->
123
 
             {sorted, Base, [{Order, find_offset({MFA,L}, ExportMap)}
124
 
                             || {L,Order} <- OrderedLabels]}
125
 
         end || Label <- Labels],
126
 
  %% msg("Map: ~w Map\n",[Map]),
127
 
  mk_labelmap(Rest, ExportMap, [Map,Acc]);
128
 
mk_labelmap([], _, Acc) -> Acc.
129
 
 
130
 
find_offset({MFA,L},[{{MFA,L},hot,Adr}|_Rest]) ->
131
 
  Adr;
132
 
find_offset(L,[_|Rest]) ->
133
 
  find_offset(L,Rest);
134
 
find_offset(L,[]) ->
135
 
  ?EXIT({label_not_found,L}).
136
 
 
137
 
slim_exportmap(Map, Closures, Exports) ->
138
 
  SortedMap = lists:sort(slim_exportmap1(Map, [])),
139
 
  slim_sorted_exportmap(SortedMap, Closures, Exports).
140
 
 
141
 
slim_exportmap1([{{{M,F,A},entry},hot,Adr}|Rest], Acc) ->
142
 
  slim_exportmap1(Rest, [{Adr,M,F,A}|Acc]);
143
 
slim_exportmap1([_|Rest], Acc) ->
144
 
  slim_exportmap1(Rest, Acc);
145
 
slim_exportmap1([], Acc) ->
146
 
  Acc.
147
 
 
148
 
slim_sorted_exportmap([{Addr,M,F,A}|Rest], Closures, Exports) ->
149
 
  IsClosure = lists:member({M,F,A}, Closures),
150
 
  IsExported = is_exported(F, A, Exports),
151
 
  [Addr,M,F,A,IsClosure,IsExported | slim_sorted_exportmap(Rest, Closures, Exports)];
152
 
slim_sorted_exportmap([],_,_) -> [].
153
 
 
154
 
is_exported(F, A, Exports) -> lists:member({F,A}, Exports).
155
 
 
156
 
%%---------------------------------------------------------------------
157
 
%% assemble_instr(Instr)
158
 
%%     Returns:         
159
 
%%   Arguments: Instr - The complete instruction.
160
 
%% Description: Returns the 32-bit SPARC code for the instruction Instr. 
161
 
%%---------------------------------------------------------------------
162
 
 
163
 
assemble_instr(I) ->
164
 
  case I of 
165
 
%%  #move{} ->
166
 
%%    assemble_move(I);
167
 
    #alu{} ->     
168
 
      assemble_alu(I);
169
 
%%  #alu_cc{} ->
170
 
%%    assemble_alu_cc(I);
171
 
%%  #store{} ->
172
 
%%     assemble_store(I);
173
 
%%  #load{} ->
174
 
%%    assemble_load(I);
175
 
    #goto{} ->
176
 
      assemble_goto(I);
177
 
    #b{} ->
178
 
      assemble_b(I);
179
 
%%  #br{} ->
180
 
%%    assemble_br(I);
181
 
    #call_link{} ->
182
 
      assemble_call_link(I);
183
 
    #jmp_link{} ->
184
 
      assemble_jmp_link(I);
185
 
%%  #jmp{} ->
186
 
%%    assemble_jmp(I);
187
 
    #sethi{} ->
188
 
      assemble_sethi(I)
189
 
%%  #load_fp{} ->
190
 
%%    assemble_load_fp(I);
191
 
%%  #store_fp{} ->
192
 
%%    assemble_store_fp(I);
193
 
%%  #fb{} ->
194
 
%%    assemble_fb(I);
195
 
%%  #fop{} ->
196
 
%%    assemble_fop(I);
197
 
%%  #fcmp{} ->
198
 
%%    assemble_fcmp(I);
199
 
%%  #fmove{} ->
200
 
%%    assemble_fmove(I);
201
 
%%  #conv_fp{} ->
202
 
%%    assemble_conv_fp(I);
203
 
%%  #nop{} ->
204
 
%%    assemble_nop(I)
205
 
  end.
206
 
 
207
 
check_simm13(Val,I) ->
208
 
  case hipe_sparc:is_imm(Val) of
209
 
    true -> 
210
 
      V = hipe_sparc:imm_value(Val),
211
 
      if 
212
 
        V > 4095 -> %% 12 bits
213
 
          exit([{problem,{too_big_imm,Val}},{at,I}]);
214
 
        V < -4096 ->
215
 
          exit([{problem,{too_small_imm,Val}},{at,I}]);
216
 
        true ->
217
 
          true
218
 
      end;
219
 
    _ -> true
220
 
  end.
221
 
 
222
 
check_imm22(Val,I) ->
223
 
  case hipe_sparc:is_imm(Val) of
224
 
    true -> 
225
 
      V = hipe_sparc:imm_value(Val),
226
 
      if 
227
 
        V > 4194303 ->  %% 22 bits
228
 
          exit([{problem,{too_big_imm,Val}},{at,I}]);
229
 
        V < -4194303 ->
230
 
          exit([{problem,{too_small_imm,Val}},{at,I}]);
231
 
        true ->
232
 
          true
233
 
      end;
234
 
    _ -> true
235
 
  end.
236
 
 
237
 
%%     Src Dst
238
 
%% mov reg reg  
239
 
%% mov imm reg
240
 
assemble_move(Instr) ->
241
 
  % move is a syntetic instruction, implemented with 'or'.
242
 
  Dst = hipe_sparc:reg_nr(hipe_sparc:move_dest(Instr)),
243
 
  Src = hipe_sparc:move_src(Instr),
244
 
 
245
 
  %% Check if the source is a register.
246
 
  case hipe_sparc:is_reg(Src) of
247
 
    false ->
248
 
      %% Check if source is an immediate.
249
 
      case hipe_sparc:is_imm(Src) of
250
 
        true -> 
251
 
          check_simm13(Src,Instr), %% Throws exception...
252
 
          hipe_sparc_op:ori(0,hipe_sparc:imm_value(Src),Dst);
253
 
        _ -> exit([{problem,{not_handled_operand,Src}},{at,Instr}])
254
 
      end;
255
 
    true ->
256
 
      hipe_sparc_op:or_op(0,hipe_sparc:reg_nr(Src),Dst)
257
 
  end.
258
 
 
259
 
%%     Dst Src1 AluOp Src2
260
 
%% alu reg reg  op    reg
261
 
%% alu reg reg  op    imm
262
 
assemble_alu(Instr) ->
263
 
  Dst = hipe_sparc:reg_nr(hipe_sparc:alu_dest(Instr)),
264
 
  Src1 = hipe_sparc:reg_nr(hipe_sparc:alu_src1(Instr)),
265
 
  SymSrc2 = hipe_sparc:alu_src2(Instr),
266
 
  AluOp = hipe_sparc:alu_operator(Instr),
267
 
  case hipe_sparc:is_reg(SymSrc2) of
268
 
    false -> 
269
 
      case hipe_sparc:is_imm(SymSrc2) of
270
 
        true -> 
271
 
          check_simm13(SymSrc2,Instr), %% Throws exception...
272
 
          Src2 = hipe_sparc:imm_value(SymSrc2),
273
 
          case AluOp of
274
 
            '+' -> hipe_sparc_op:addi(Src1,Src2,Dst);
275
 
            '-' -> hipe_sparc_op:subi(Src1,Src2,Dst);
276
 
            '+c' -> hipe_sparc_op:addci(Src1,Src2,Dst);
277
 
            '-c' -> hipe_sparc_op:subci(Src1,Src2,Dst);
278
 
            'and' -> hipe_sparc_op:andi(Src1,Src2,Dst);
279
 
            'andn' -> hipe_sparc_op:andni(Src1,Src2,Dst);
280
 
            'or' -> hipe_sparc_op:ori(Src1,Src2,Dst);
281
 
            'xor' -> hipe_sparc_op:xori(Src1,Src2,Dst);
282
 
            'xnor' -> hipe_sparc_op:xnori(Src1,Src2,Dst);
283
 
            '>>' -> hipe_sparc_op:srli(Src1,Src2,Dst);
284
 
            '>>64' -> hipe_sparc_op:srlix(Src1,Src2,Dst);
285
 
            '>>?' -> hipe_sparc_op:srai(Src1,Src2,Dst);
286
 
            '>>?64' -> hipe_sparc_op:sraix(Src1,Src2,Dst);
287
 
            '<<' -> hipe_sparc_op:slli(Src1,Src2,Dst);
288
 
            '<<64' -> hipe_sparc_op:sllix(Src1,Src2,Dst);
289
 
            'smul' -> hipe_sparc_op:smuli(Src1,Src2,Dst);
290
 
            _ -> exit([{problem,{not_handled,{aluop,AluOp}}},{at,Instr}])
291
 
          end;
292
 
        false -> %% Not reg or imm
293
 
          exit([{problem,{not_handled_operand,SymSrc2}},{at,Instr}])
294
 
      end;
295
 
              
296
 
    true -> %% Reg2
297
 
      Src2 = hipe_sparc:reg_nr(SymSrc2),
298
 
      case AluOp of
299
 
        '+' -> hipe_sparc_op:add(Src1,Src2,Dst);
300
 
        '-' -> hipe_sparc_op:sub(Src1,Src2,Dst);
301
 
        '+c' -> hipe_sparc_op:addc(Src1,Src2,Dst);
302
 
        '-c' -> hipe_sparc_op:subc(Src1,Src2,Dst);
303
 
        'and' -> hipe_sparc_op:and_op(Src1,Src2,Dst);
304
 
        'andn' -> hipe_sparc_op:andn(Src1,Src2,Dst);
305
 
        'or' -> hipe_sparc_op:or_op(Src1,Src2,Dst);
306
 
        'xor' -> hipe_sparc_op:xor_op(Src1,Src2,Dst);
307
 
        'xnor' -> hipe_sparc_op:xnor_op(Src1,Src2,Dst);
308
 
        '>>' -> hipe_sparc_op:srl(Src1,Src2,Dst);
309
 
        '>>?' -> hipe_sparc_op:sra(Src1,Src2,Dst);
310
 
        '<<' -> hipe_sparc_op:sll(Src1,Src2,Dst);
311
 
        '>>64' -> hipe_sparc_op:srlx(Src1,Src2,Dst);
312
 
        '>>?64' -> hipe_sparc_op:srax(Src1,Src2,Dst);
313
 
        '<<64' -> hipe_sparc_op:sllx(Src1,Src2,Dst);
314
 
        'smul' -> hipe_sparc_op:smul(Src1,Src2,Dst);
315
 
        _ -> exit([{problem,{not_handled,{aluop,AluOp}}},{at,Instr}])
316
 
      end
317
 
  end.
318
 
 
319
 
%%     Dst Src1 AluOp Src2
320
 
%% alu reg reg  op    reg
321
 
%% alu reg reg  op    imm
322
 
assemble_alu_cc(Instr) ->
323
 
  Dst = hipe_sparc:reg_nr(hipe_sparc:alu_cc_dest(Instr)),
324
 
  Src1 = hipe_sparc:reg_nr(hipe_sparc:alu_cc_src1(Instr)),
325
 
  SymSrc2 = hipe_sparc:alu_cc_src2(Instr),
326
 
  AluOp = hipe_sparc:alu_cc_operator(Instr),
327
 
  case hipe_sparc:is_reg(hipe_sparc:alu_cc_src2(Instr)) of
328
 
    false ->
329
 
      case hipe_sparc:is_imm(SymSrc2) of
330
 
        true -> 
331
 
          check_simm13(SymSrc2,Instr), %% Throws exception...
332
 
          Src2 = hipe_sparc:imm_value(SymSrc2),
333
 
          case AluOp of
334
 
            '+' -> hipe_sparc_op:addicc(Src1,Src2,Dst);
335
 
            '-' -> hipe_sparc_op:subicc(Src1,Src2,Dst);
336
 
            'and' -> hipe_sparc_op:andicc(Src1,Src2,Dst);
337
 
            'andn' -> hipe_sparc_op:andnicc(Src1,Src2,Dst);
338
 
            'or' -> hipe_sparc_op:oricc(Src1,Src2,Dst);
339
 
            'xor' -> hipe_sparc_op:xoricc(Src1,Src2,Dst);
340
 
            _ -> exit([{problem,{not_handled,{aluccop,AluOp}}},
341
 
                       {at,Instr}])
342
 
          end;
343
 
        false -> %% Not reg or imm
344
 
          exit([{problem,{not_handled_operand,SymSrc2}},{at,Instr}])
345
 
      end;
346
 
 
347
 
    true ->
348
 
      Src2 = hipe_sparc:reg_nr(SymSrc2),
349
 
      case AluOp of
350
 
        '+' -> hipe_sparc_op:addcc(Src1,Src2,Dst);
351
 
        '-' -> hipe_sparc_op:subcc(Src1,Src2,Dst);
352
 
        'and' -> hipe_sparc_op:andcc(Src1,Src2,Dst);
353
 
        'andn' -> hipe_sparc_op:andncc(Src1,Src2,Dst);
354
 
        'or' -> hipe_sparc_op:orcc(Src1,Src2,Dst);
355
 
        'xor' -> hipe_sparc_op:xorcc(Src1,Src2,Dst);
356
 
        _ -> exit([{problem,{not_handled,{aluccop,AluOp}}},{at,Instr}])
357
 
      end
358
 
  end.
359
 
 
360
 
%%       Src Off Dst
361
 
%% store reg reg reg
362
 
%% store reg imm reg
363
 
assemble_store(Store) ->
364
 
  Dst = hipe_sparc:reg_nr(hipe_sparc:store_dest(Store)),
365
 
  Off = hipe_sparc:store_off(Store),
366
 
  Type = hipe_sparc:store_type(Store),
367
 
  Src = hipe_sparc:reg_nr(hipe_sparc:store_src(Store)),
368
 
  case hipe_sparc:is_reg(Off) of 
369
 
    false -> 
370
 
      case hipe_sparc:is_imm(Off) of
371
 
        true -> 
372
 
          check_simm13(Off,Store), %% Throws exception...
373
 
          ImmOff = hipe_sparc:imm_value(Off),
374
 
          case Type of
375
 
            w -> hipe_sparc_op:stwi(Src,Dst,ImmOff);
376
 
            b -> hipe_sparc_op:stbi(Src,Dst,ImmOff);
377
 
            h -> hipe_sparc_op:sthi(Src,Dst,ImmOff);
378
 
            x -> hipe_sparc_op:stxi(Src,Dst,ImmOff)
379
 
          end;
380
 
        false -> %% Not register or immediate
381
 
          exit([{problem,{not_handled_offset,Off}},{at,Store}])
382
 
      end;
383
 
    true -> 
384
 
      case Type of
385
 
        w -> hipe_sparc_op:stw(Src,Dst,hipe_sparc:reg_nr(Off));
386
 
        b -> hipe_sparc_op:stb(Src,Dst,hipe_sparc:reg_nr(Off));
387
 
        h -> hipe_sparc_op:sth(Src,Dst,hipe_sparc:reg_nr(Off));
388
 
        x -> hipe_sparc_op:stx(Src,Dst,hipe_sparc:reg_nr(Off))
389
 
      end
390
 
  end.
391
 
 
392
 
%%       Src Off Dst
393
 
%% load  reg reg reg
394
 
%% load  reg imm reg
395
 
assemble_load(Load) ->
396
 
  case hipe_sparc:is_reg(hipe_sparc:load_dest(Load)) of
397
 
    true ->
398
 
      case hipe_sparc:is_reg(hipe_sparc:load_src(Load)) of
399
 
        true ->
400
 
          Dst = hipe_sparc:reg_nr(hipe_sparc:load_dest(Load)),
401
 
          Src = hipe_sparc:reg_nr(hipe_sparc:load_src(Load)),
402
 
          Off = hipe_sparc:load_off(Load),
403
 
          Type = hipe_sparc:load_type(Load),
404
 
          case hipe_sparc:is_reg(Off) of 
405
 
            false -> 
406
 
              case hipe_sparc:is_imm(Off) of
407
 
                true -> 
408
 
                  check_simm13(Off,Load), %% Throws exception...
409
 
                  ImmOff = hipe_sparc:imm_value(Off),
410
 
                  case Type of
411
 
                    uw -> hipe_sparc_op:ldi(Src,ImmOff,Dst);
412
 
                    sb -> hipe_sparc_op:ldsbi(Src,ImmOff,Dst);
413
 
                    sh -> hipe_sparc_op:ldshi(Src,ImmOff,Dst);
414
 
                    sw -> hipe_sparc_op:ldswi(Src,ImmOff,Dst);
415
 
                    ub -> hipe_sparc_op:ldubi(Src,ImmOff,Dst);
416
 
                    uh -> hipe_sparc_op:lduhi(Src,ImmOff,Dst);
417
 
                    x -> hipe_sparc_op:ldxi(Src,ImmOff,Dst)
418
 
                  end;
419
 
                false -> %% Not register or immediate
420
 
                  exit([{problem,{not_handled_offset,Off}},{at,Load}])
421
 
              end;
422
 
            true -> 
423
 
              OffReg = hipe_sparc:reg_nr(Off),
424
 
              case Type of
425
 
                uw -> hipe_sparc_op:ld(Src,OffReg,Dst);
426
 
                sb -> hipe_sparc_op:ldsb(Src,OffReg,Dst);
427
 
                sh -> hipe_sparc_op:ldsh(Src,OffReg,Dst);
428
 
                sw -> hipe_sparc_op:ldsw(Src,OffReg,Dst);
429
 
                ub -> hipe_sparc_op:ldub(Src,OffReg,Dst);
430
 
                uh -> hipe_sparc_op:lduh(Src,OffReg,Dst);
431
 
                x ->  hipe_sparc_op:ldx(Src,OffReg,Dst)
432
 
              end
433
 
          end;
434
 
        false ->
435
 
          exit([{problem,load_src_not_reg},{at,Load}])
436
 
      end;
437
 
    false ->
438
 
      exit([{problem,load_dst_not_reg},{at,Load}])
439
 
  end.
440
 
 
441
 
%% goto is a synthetic instruction implemented with ba
442
 
%% we're only doing SPARC V9 now, so replace "ba" with "ba,pt"
443
 
assemble_goto(Goto) ->
444
 
  Disp = hipe_sparc:goto_label(Goto),
445
 
  Cond = hipe_sparc_op:cc_bits('a'),
446
 
  Pred = hipe_sparc_op:predicate_bit(true),
447
 
  Annul = hipe_sparc_op:annul_bit('na'),
448
 
  hipe_sparc_op:bpcc(Cond, Annul, Pred, Disp).
449
 
 
450
 
%%
451
 
%%
452
 
assemble_b(B) ->
453
 
  Disp = hipe_sparc:b_label(B),
454
 
  Cond = hipe_sparc_op:cc_bits(hipe_sparc:b_cond(B)),
455
 
  Pred = hipe_sparc_op:predicate_bit(hipe_sparc:b_taken(B)),
456
 
  Annul = hipe_sparc_op:annul_bit(hipe_sparc:b_annul(B)),
457
 
  hipe_sparc_op:bpcc(Cond, Annul, Pred, Disp).
458
 
 
459
 
%% assemble_br(BR) -> 
460
 
%%   Disp = hipe_sparc:br_label(BR),
461
 
%%   Reg = hipe_sparc:reg_nr(hipe_sparc:br_reg(BR)),
462
 
%%   RCond = hipe_sparc_op:rcc_bits(hipe_sparc:br_regcond(BR)),
463
 
%%   Pred = hipe_sparc_op:predicate_bit(hipe_sparc:br_taken(BR)),
464
 
%%   Annul = hipe_sparc_op:annul_bit(hipe_sparc:br_annul(BR)),
465
 
%%   hipe_sparc_op:bpr(RCond, Annul, Pred, Reg, Disp).
466
 
 
467
 
assemble_call_link(Call_link) ->
468
 
  case 
469
 
    hipe_sparc:reg_nr(hipe_sparc:call_link_link(Call_link)) =/= 
470
 
    hipe_sparc_registers:return_address() of
471
 
    true ->
472
 
      exit([{problem,{call_link_not_to_CP}},{at,Call_link}]);
473
 
    false ->
474
 
      hipe_sparc_op:call(hipe_sparc:call_link_target(Call_link))
475
 
  end.
476
 
 
477
 
assemble_jmp_link(Jmp_link) ->
478
 
  Target = hipe_sparc:reg_nr(hipe_sparc:jmp_link_target(Jmp_link)),
479
 
  Off = hipe_sparc:jmp_link_off(Jmp_link),
480
 
  Link = hipe_sparc:reg_nr(hipe_sparc:jmp_link_link(Jmp_link)),
481
 
  assemble_jlink(Jmp_link, Target, Off, Link).
482
 
 
483
 
assemble_jlink(I, Target, Off, Link) ->
484
 
  case hipe_sparc:is_reg(Off) of 
485
 
    true -> 
486
 
      exit([{problem,{not_handled,{jmp_link,reg_reg_reg}}},{at,I}]);
487
 
    false -> 
488
 
      case hipe_sparc:is_imm(Off) of
489
 
        true -> 
490
 
          check_simm13(Off,I), %% Throws exception...
491
 
          ImmOff = hipe_sparc:imm_value(Off),
492
 
          hipe_sparc_op:jumpli(Target,ImmOff,Link);
493
 
        false -> %% Not reg or imm
494
 
          exit([{problem,{not_handled_offset,Off}},{at,I}])
495
 
      end
496
 
  end.  
497
 
 
498
 
assemble_jmp(Jmp)->
499
 
  Target = hipe_sparc:reg_nr(hipe_sparc:jmp_target(Jmp)),
500
 
  Link = hipe_sparc_registers:zero(),
501
 
  Off = hipe_sparc:jmp_off(Jmp),
502
 
  assemble_jlink(Jmp, Target, Off, Link).
503
 
 
504
 
assemble_rdy(Instr) ->
505
 
  Dest = hipe_sparc:reg_nr(hipe_sparc:rdy_dest(Instr)),
506
 
  hipe_sparc_op:rdy(Dest).
507
 
 
508
 
assemble_sethi(Instr)->
509
 
  Dest = hipe_sparc:reg_nr(hipe_sparc:sethi_dest(Instr)),
510
 
  Val = hipe_sparc:sethi_const(Instr),
511
 
  case hipe_sparc:is_imm(Val) of
512
 
    true -> 
513
 
      check_imm22(Val,Instr), %% Throws exception...
514
 
      ImmVal = hipe_sparc:imm_value(Val),
515
 
      hipe_sparc_op:sethi(ImmVal,Dest);
516
 
    false -> 
517
 
      exit([{problem,{not_an_integer,Val}},{at,Instr}])
518
 
  end.
519
 
 
520
 
assemble_nop(_Instr) ->
521
 
  hipe_sparc_op:nop().
522
 
 
523
 
%%---------------------------------------------------------------------
524
 
%% FP - ops
525
 
%%---------------------------------------------------------------------
526
 
 
527
 
%%          Src Off Dst
528
 
%% load_fp  reg reg fpreg
529
 
%% load_fp  reg imm fpreg
530
 
assemble_load_fp(Load) ->
531
 
  case hipe_sparc:is_fpreg(hipe_sparc:load_fp_dest(Load)) of
532
 
    true ->
533
 
      case hipe_sparc:is_reg(hipe_sparc:load_fp_src(Load)) of
534
 
        true ->
535
 
          Type = hipe_sparc:load_fp_type(Load),
536
 
          Dst = encode_5bit_fpreg(hipe_sparc:fpreg_nr(hipe_sparc:load_fp_dest(Load)),
537
 
                                  Type),
538
 
          Src = hipe_sparc:reg_nr(hipe_sparc:load_fp_src(Load)),
539
 
          Off = hipe_sparc:load_fp_off(Load),
540
 
          case hipe_sparc:is_reg(Off) of 
541
 
            false -> 
542
 
              case hipe_sparc:is_imm(Off) of
543
 
                true -> 
544
 
                  check_simm13(Off,Load), %% Throws exception...
545
 
                  ImmOff = hipe_sparc:imm_value(Off),
546
 
                  case Type of
547
 
                    single ->  hipe_sparc_op:ldfi(Dst,Src,ImmOff);
548
 
                    double ->  hipe_sparc_op:lddfi(Dst,Src,ImmOff);
549
 
                    quad ->  hipe_sparc_op:ldqfi(Dst,Src,ImmOff)
550
 
                  end;
551
 
                false -> %% Not reg or imm
552
 
                  exit([{problem,{not_handled_offset,Off}},{at,Load}])
553
 
              end;
554
 
            true ->
555
 
              case Type of
556
 
                single -> hipe_sparc_op:ldf(Dst,Src,hipe_sparc:reg_nr(Off));
557
 
                double -> hipe_sparc_op:lddf(Dst,Src,hipe_sparc:reg_nr(Off));
558
 
                  quad -> hipe_sparc_op:ldqf(Dst,Src,hipe_sparc:reg_nr(Off))
559
 
              end
560
 
          end;
561
 
        false ->
562
 
          exit([{problem,load_fp_src_not_reg},{at,Load}])
563
 
      end;
564
 
    false ->
565
 
      exit([{problem,load_fp_dst_not_fpreg},{at,Load}])
566
 
  end.
567
 
 
568
 
%%          Src   Off Dst
569
 
%% store_fp fpreg reg reg
570
 
%% store_fp reg   imm reg
571
 
assemble_store_fp(Store) ->
572
 
  Dst = hipe_sparc:reg_nr(hipe_sparc:store_fp_dest(Store)),
573
 
  Off = hipe_sparc:store_fp_off(Store),
574
 
  Type = hipe_sparc:store_fp_type(Store),
575
 
  Src = encode_5bit_fpreg(hipe_sparc:fpreg_nr(hipe_sparc:store_fp_src(Store)), 
576
 
                          Type),
577
 
  case hipe_sparc:is_reg(Off) of 
578
 
    false -> 
579
 
      case hipe_sparc:is_imm(Off) of
580
 
        true -> 
581
 
          check_simm13(Off,Store), %% Throws exception...
582
 
          ImmOff = hipe_sparc:imm_value(Off),
583
 
          case Type of
584
 
            single -> hipe_sparc_op:stfi(Src,Dst,ImmOff);
585
 
            double -> hipe_sparc_op:stdfi(Src,Dst,ImmOff);
586
 
            quad ->   hipe_sparc_op:stqfi(Src,Dst,ImmOff)
587
 
          end;
588
 
        false -> %% Not reg or imm
589
 
          exit([{problem,{not_handled_offset,Off}},{at,Store}])
590
 
      end;
591
 
    true -> 
592
 
      case Type of
593
 
        single -> hipe_sparc_op:stf(Src,Dst,hipe_sparc:reg_nr(Off));
594
 
        double -> hipe_sparc_op:stdf(Src,Dst,hipe_sparc:reg_nr(Off));
595
 
        quad ->   hipe_sparc_op:stqf(Src,Dst,hipe_sparc:reg_nr(Off))
596
 
      end
597
 
  end.
598
 
 
599
 
%% %% fb<Cond>[,a][,pt] <%fccN>,<L>
600
 
%% %%
601
 
%% assemble_fb(B) ->
602
 
%%   Disp = hipe_sparc:fb_label(B),
603
 
%%   Cond = hipe_sparc_op:fcc_bits(hipe_sparc:fb_cond(B)),
604
 
%%   Pred = hipe_sparc_op:predicate_bit(hipe_sparc:fb_taken(B)),
605
 
%%   Annul = hipe_sparc_op:annul_bit(hipe_sparc:fb_annul(B)),
606
 
%%   Fcc = hipe_sparc:fb_fcc_reg(B),
607
 
%%   hipe_sparc_op:fbpfcc(Fcc, Cond, Annul, Pred, Disp).
608
 
 
609
 
 
610
 
%%     Dst   Src1   FOp Src2
611
 
%%     fpreg fpreg  op  fpreg
612
 
assemble_fop(Instr) ->
613
 
  D = hipe_sparc:fpreg_nr(hipe_sparc:fop_dest(Instr)),
614
 
  S1 = hipe_sparc:fpreg_nr(hipe_sparc:fop_src1(Instr)),
615
 
  S2 = hipe_sparc:fpreg_nr(hipe_sparc:fop_src2(Instr)),
616
 
  Type = hipe_sparc:fop_type(Instr),
617
 
  Src1 = encode_5bit_fpreg(S1, Type),
618
 
  Src2 = encode_5bit_fpreg(S2, Type),
619
 
  Dst = encode_5bit_fpreg(D, Type),
620
 
  
621
 
  FOp = hipe_sparc:fop_operator(Instr),
622
 
 
623
 
  case Type of
624
 
    double ->
625
 
      case FOp of
626
 
        '+' -> hipe_sparc_op:faddd(Src1,Src2,Dst);
627
 
        '-' -> hipe_sparc_op:fsubd(Src1,Src2,Dst);
628
 
        '*' -> hipe_sparc_op:fmuld(Src1,Src2,Dst);
629
 
        '/' -> hipe_sparc_op:fdivd(Src1,Src2,Dst);
630
 
        _ -> ?EXIT([{problem,{not_handled,{fop,FOp}}},
631
 
                    {at,Instr}])
632
 
      end;
633
 
    single ->
634
 
      case FOp of
635
 
        '+' -> hipe_sparc_op:fadds(Src1,Src2,Dst);
636
 
        '-' -> hipe_sparc_op:fsubs(Src1,Src2,Dst);
637
 
        '*' -> hipe_sparc_op:fmuls(Src1,Src2,Dst);
638
 
        '/' -> hipe_sparc_op:fdivs(Src1,Src2,Dst);
639
 
        _ -> ?EXIT([{problem,{not_handled,{fop,FOp}}},
640
 
                    {at,Instr}])
641
 
      end;
642
 
    quad ->
643
 
      case FOp of
644
 
        '+' -> hipe_sparc_op:faddq(Src1,Src2,Dst);
645
 
        '-' -> hipe_sparc_op:fsubq(Src1,Src2,Dst);
646
 
        '*' -> hipe_sparc_op:fmulq(Src1,Src2,Dst);
647
 
        '/' -> hipe_sparc_op:fdivq(Src1,Src2,Dst);
648
 
        _ -> ?EXIT([{problem,{not_handled,{fop,FOp}}},
649
 
                    {at,Instr}])
650
 
      end
651
 
  end.
652
 
      
653
 
%% %%     Dst   Src1   Src2
654
 
%% %%     fccN  fpreg  fpreg
655
 
%% assemble_fcmp(Instr) ->
656
 
%%   Fcc = hipe_sparc:fcmp_fcc_reg(Instr),
657
 
%%   Src1 = hipe_sparc:fpreg_nr(hipe_sparc:fcmp_src1(Instr)),
658
 
%%   Src2 = hipe_sparc:fpreg_nr(hipe_sparc:fcmp_src2(Instr)),
659
 
%%   Exception = hipe_sparc:fcmp_exception(Instr),
660
 
%%   Type = hipe_sparc:fcmp_type(Instr),
661
 
%%   %% XXX: Is this the right way to code the regs?
662
 
%%   RS1 = encode_5bit_fpreg(Src1, Type),
663
 
%%   RS2 = encode_5bit_fpreg(Src2, Type),
664
 
%%   case Type of
665
 
%%     double ->
666
 
%%       case Exception of
667
 
%%      true -> hipe_sparc_op:fcmped(Fcc,RS1,RS2);
668
 
%%      false -> hipe_sparc_op:fcmpd(Fcc,RS1,RS2)
669
 
%%       end;
670
 
%%     single ->
671
 
%%       case Exception of
672
 
%%      true -> hipe_sparc_op:fcmpes(Fcc,RS1,RS2);
673
 
%%      false -> hipe_sparc_op:fcmps(Fcc,RS1,RS2)
674
 
%%       end;
675
 
%%     quad ->
676
 
%%       case Exception of
677
 
%%      true -> hipe_sparc_op:fcmpeq(Fcc,RS1,RS2);
678
 
%%      false -> hipe_sparc_op:fcmpq(Fcc,RS1,RS2)
679
 
%%       end
680
 
%%   end.
681
 
 
682
 
%%     Dst   Src
683
 
%%     fpreg fpreg
684
 
assemble_fmove(Instr) ->
685
 
  D = hipe_sparc:fpreg_nr(hipe_sparc:fmove_dest(Instr)),
686
 
  S = hipe_sparc:fpreg_nr(hipe_sparc:fmove_src(Instr)),
687
 
  Type = hipe_sparc:fmove_type(Instr),
688
 
  Neg = hipe_sparc:fmove_negate(Instr),
689
 
  Abs = hipe_sparc:fmove_abs(Instr),
690
 
  Src = encode_5bit_fpreg(S, Type),
691
 
  Dst = encode_5bit_fpreg(D, Type),
692
 
  
693
 
  case Type of
694
 
    double ->
695
 
      case {Abs, Neg} of
696
 
        {true, false} -> hipe_sparc_op:fabsd(Src,Dst);
697
 
        {false, true} -> hipe_sparc_op:fnegd(Src,Dst);
698
 
        {false, false} -> hipe_sparc_op:fmovd(Src,Dst);
699
 
        _ -> ?EXIT([{problem,{not_handled,{negate, absolute_value}}},
700
 
                    {at,Instr}])
701
 
      end;
702
 
    single ->
703
 
      case {Abs, Neg} of
704
 
        {true, false} -> hipe_sparc_op:fabss(Src,Dst);
705
 
        {false, true} -> hipe_sparc_op:fnegs(Src,Dst);
706
 
        {false, false} -> hipe_sparc_op:fmovs(Src,Dst);
707
 
        _ -> ?EXIT([{problem,{not_handled,{negate,Neg,absolute_value,Abs}}},
708
 
                    {at,Instr}])
709
 
      end;
710
 
    quad ->
711
 
      case {Abs, Neg} of
712
 
        {true, false} -> hipe_sparc_op:fabsq(Src,Dst);
713
 
        {false, true} -> hipe_sparc_op:fnegq(Src,Dst);
714
 
        {false, false} -> hipe_sparc_op:fmovq(Src,Dst);
715
 
        _ -> ?EXIT([{problem,{not_handled,{negate, absolute_value}}},
716
 
                    {at,Instr}])
717
 
      end
718
 
  end.
719
 
 
720
 
%%     Dst   Src
721
 
%%     fpreg reg
722
 
assemble_conv_fp(Instr) ->
723
 
  D = hipe_sparc:fpreg_nr(hipe_sparc:conv_fp_dest(Instr)),
724
 
  S = hipe_sparc:fpreg_nr(hipe_sparc:conv_fp_src(Instr)),
725
 
  DestType = hipe_sparc:conv_fp_dest_type(Instr),
726
 
  Dst = encode_5bit_fpreg(D, DestType),
727
 
  Src = encode_5bit_fpreg(S, single),
728
 
  
729
 
  case DestType of
730
 
    single ->
731
 
      hipe_sparc_op:fitos(Src, Dst);
732
 
    double ->
733
 
      hipe_sparc_op:fitod(Src, Dst);
734
 
    quad ->
735
 
      hipe_sparc_op:fitoq(Src, Dst)
736
 
  end.
737
 
 
738
 
%%---------------------------------------------------------------------
739
 
%% 
740
 
encode_5bit_fpreg(Reg, Type) ->
741
 
  case Type of
742
 
    single -> 
743
 
      ?ASSERT(Reg < 32),
744
 
      Reg;
745
 
    double -> 
746
 
      ?ASSERT(Reg < 63),
747
 
      ?ASSERT(Reg band 2#1 =:= 0),
748
 
      ((Reg bsr 5) bor (Reg band 2#11110));
749
 
    quad ->
750
 
      ?ASSERT(Reg < 63),
751
 
      ?ASSERT(Reg band 2#11 =:= 0),
752
 
      ((Reg bsr 5) bor (Reg band 2#11110))
753
 
  end.
754
 
 
755
 
%% TODO: implement if needed:
756
 
%% encode_6bit_fpreg(Reg, Type)
757
 
 
758
 
%%=====================================================================
759
 
%% A linker for SPARC code appears below
760
 
%%=====================================================================
761
 
 
762
 
linker(Code, Map, ConstMap) ->
763
 
  link9(Code,0,
764
 
        init_export_map(Map),      %% Convert to more efficient
765
 
        init_const_map(ConstMap),  %% data structures.
766
 
        [],[]).
767
 
 
768
 
link9([{MFA,Hot}|Rest], HAddr, Map, ConstMap,
769
 
      AccHCode, AccHRefs) ->
770
 
  %% io:format("Assembling ~w\n",[MFA]),
771
 
  {HCode,NewHAddr,HRefs} =
772
 
    link8(Hot , MFA, HAddr, local_labels(MFA,Map), ConstMap, AccHRefs, []),
773
 
  link9(Rest, NewHAddr, Map, ConstMap, AccHCode++HCode, HRefs);
774
 
link9([],_HAddr,_Map,_ConstMap,AccHCode,AccHRefs) ->
775
 
  {AccHCode,AccHRefs}.
776
 
 
777
 
link8([I|Is],MFA,Addr,Map,ConstMap,Refs,Code) ->
778
 
  case  
779
 
    case I of
780
 
      #call_link{} -> resolve_call_link(I,Addr,Refs,Map);
781
 
      #b{} -> resolve_b(I,Addr,Refs,Map);
782
 
      #goto{} -> resolve_goto(I,Addr,Refs,Map);
783
 
      #load_address{} -> resolve_load_address(I,Addr,Refs,MFA,Map,ConstMap);
784
 
      #load_atom{} -> resolve_load_atom(I,Addr,Refs);
785
 
%%    #load_word_index{} -> resolve_load_word_index(I,Addr,Refs,MFA,Map,ConstMap);
786
 
      #alu{} -> {assemble_alu(I),Addr+4,Refs};
787
 
      #alu_cc{} -> {assemble_alu_cc(I),Addr+4,Refs};
788
 
      #store{} -> {assemble_store(I),Addr+4,Refs};
789
 
      #move{} -> {assemble_move(I),Addr+4,Refs};
790
 
      #load{} -> {assemble_load(I),Addr+4,Refs};
791
 
      #store_fp{} -> {assemble_store_fp(I),Addr+4,Refs};
792
 
      #load_fp{} -> {assemble_load_fp(I),Addr+4,Refs};
793
 
%%    #fb{} -> {assemble_fb(I),Addr+4,Refs};
794
 
      #fop{} -> {assemble_fop(I),Addr+4,Refs};
795
 
%%    #fcmp{} -> {assemble_fcmp(I),Addr+4,Refs};
796
 
      #fmove{} -> {assemble_fmove(I),Addr+4,Refs};
797
 
      #conv_fp{} -> {assemble_conv_fp(I),Addr+4,Refs};
798
 
      #jmp{} -> {assemble_jmp(I),Addr+4,Refs};
799
 
      #nop{} -> {assemble_nop(I),Addr+4,Refs};
800
 
      #rdy{} -> {assemble_rdy(I),Addr+4,Refs};
801
 
      #sethi{} -> {assemble_sethi(I),Addr+4,Refs};
802
 
      Other -> exit({bad_sparc_instruction,Other})
803
 
    end of
804
 
    {[I1,I2],NewAddr,NewRefs} ->
805
 
      link8(Is,MFA,NewAddr,Map,ConstMap,NewRefs,[I1,I2|Code]);
806
 
    {C,NewAddr,NewRefs}  ->
807
 
      link8(Is,MFA,NewAddr,Map,ConstMap,NewRefs,[C|Code])
808
 
  end;
809
 
link8([],_MFA,Addr,_Map,_ConstMap,Refs,Code) ->
810
 
  {lists:reverse(Code),Addr,Refs}.
811
 
 
812
 
resolve_load_address(Instr,Addr,Refs,MFA,_Map,ConstMap)->
813
 
  Dest = hipe_sparc:load_address_dest(Instr),
814
 
  Address = hipe_sparc:load_address_addr(Instr),
815
 
  Ref = 
816
 
    case hipe_sparc:load_address_type(Instr) of
817
 
%%      label ->
818
 
%%      {hot,Offset} = find(Address, Map),
819
 
%%      [{?LOAD_ADDRESS,Addr,{label,Offset}}];
820
 
      local_function -> 
821
 
        [{?LOAD_ADDRESS,Addr,{local_function,Address}}];
822
 
      remote_function -> 
823
 
        [{?LOAD_ADDRESS,Addr,{remote_function,Address}}];
824
 
      constant ->
825
 
        ConstNo = find_const({MFA,Address},ConstMap),
826
 
        [{?LOAD_ADDRESS,Addr,{constant,ConstNo}}];
827
 
      closure ->
828
 
        [{?LOAD_ADDRESS,Addr,{closure,Address}}];
829
 
      c_const ->
830
 
        [{?LOAD_ADDRESS,Addr,{c_const,Address}}];
831
 
      Type ->     
832
 
        exit([{problem,{not_handled,{address,Type}}},{at,Instr}])
833
 
    end,
834
 
  Hi = hipe_sparc:mk_imm(0),
835
 
  Lo = hipe_sparc:mk_imm(0),
836
 
  I1 = hipe_sparc:sethi_create(Dest,Hi),
837
 
  I2 = hipe_sparc:alu_create(Dest,Dest,'or',Lo),
838
 
  {[assemble_instr(I2),assemble_instr(I1)],Addr+8,Ref++Refs}.
839
 
 
840
 
resolve_goto(I,Addr,Refs,Map) ->
841
 
  Dest = hipe_sparc:goto_label(I),
842
 
  {hot,Address} = find(Dest,Map),
843
 
  RelDest = (Address - Addr) div 4,
844
 
  case valid_branch_length(RelDest) of
845
 
    true -> true;
846
 
    false -> exit({too_long_branch,{address,Addr}})
847
 
  end,
848
 
  NewI = hipe_sparc:goto_label_update(I,RelDest),
849
 
  Code = assemble_instr(NewI),
850
 
  {Code,Addr+4,Refs}.
851
 
 
852
 
resolve_b(I,Addr,Refs,Map) ->
853
 
  Dest = hipe_sparc:b_label(I),
854
 
  {hot,Address} = find(Dest,Map),
855
 
  RelDest = (Address - Addr) div 4,
856
 
  case valid_branch_length(RelDest) of
857
 
    true -> true;
858
 
    false -> exit({too_long_branch,{address,Addr}})
859
 
  end,
860
 
  NewI = hipe_sparc:b_label_update(I,RelDest),
861
 
  Code = assemble_instr(NewI),
862
 
  {Code,Addr+4,Refs}.
863
 
 
864
 
resolve_load_atom(Instr,Addr,Refs)->
865
 
  Atom = hipe_sparc:load_atom_atom(Instr),
866
 
  Dest = hipe_sparc:load_atom_dest(Instr),
867
 
  I1 = hipe_sparc:sethi_create(Dest, hipe_sparc:mk_imm(0)),
868
 
  I2 = hipe_sparc:alu_create(Dest, Dest, 'or', hipe_sparc:mk_imm(0)),
869
 
  {[assemble_instr(I2),assemble_instr(I1)],
870
 
   Addr+8,[{?LOAD_ATOM, Addr, Atom}|Refs]}.
871
 
 
872
 
%%resolve_load_word_index(_Instr,_Addr,_Refs,_MFA,_Map,_ConstMap) ->
873
 
%%  ?EXIT({nyi,resolve_load_word_index}).
874
 
%%  Index =hipe_sparc:load_word_index_index(Instr),
875
 
%%  Block =hipe_sparc:load_word_index_block(Instr),
876
 
%%  Dest = hipe_sparc:load_word_index_dest(Instr),
877
 
%%  ConstNo = find_const({MFA,Block},ConstMap),
878
 
%%  I1 = hipe_sparc:sethi_create(Dest, hipe_sparc:mk_imm(0)),
879
 
%%  I2 = hipe_sparc:alu_create(Dest,Dest, 'or', hipe_sparc:mk_imm(0)),
880
 
%%  {[assemble_instr(I2),assemble_instr(I1)],
881
 
%%   Addr+8,[{?PATCH_TYPE2EXT(load_word_index),Addr, {word_index, ConstNo, Index}}|Refs]}.
882
 
 
883
 
resolve_call_link(Instr,Addr,OldRefs,Map)->
884
 
  Target = hipe_sparc:call_link_target(Instr),
885
 
  ExnLab = hipe_sparc:call_link_fail(Instr),
886
 
  %% Get the stack descriptor information
887
 
  SD = hipe_sparc:call_link_stack_desc(Instr),
888
 
  FSize = hipe_sparc:sdesc_size(SD),
889
 
  Live = list_to_tuple(hipe_sparc:sdesc_live_slots(SD)),
890
 
  Arity = case hipe_sparc:sdesc_arity(SD) of
891
 
            N when N > ?SPARC_NR_ARG_REGS -> N - ?SPARC_NR_ARG_REGS;
892
 
            _ -> 0
893
 
          end,
894
 
  ExnRA = case ExnLab of
895
 
            [] -> [];   % don't cons up a new one
896
 
            _ -> {hot,V} = find(ExnLab,Map), V
897
 
          end,
898
 
  %% The stack descriptor needs to be inserted into the system at load-time.
899
 
  Refs = [{?SDESC,
900
 
           Addr,
901
 
           ?STACK_DESC(ExnRA, FSize, Arity, Live)} | OldRefs],
902
 
  case hipe_sparc:call_link_is_known(Instr) of
903
 
    false -> 
904
 
      NewI = hipe_sparc:jmp_link_create(
905
 
               hipe_sparc:call_link_target(Instr),
906
 
               hipe_sparc:mk_imm(0), 
907
 
               hipe_sparc:mk_reg(hipe_sparc_registers:return_address()),
908
 
               hipe_sparc:call_link_args(Instr)),
909
 
      Code = assemble_instr(NewI),
910
 
      {Code,Addr+4, Refs};
911
 
    true -> 
912
 
      Patch =
913
 
        case hipe_sparc:call_link_type(Instr) of
914
 
          remote -> ?CALL_REMOTE;
915
 
          not_remote -> ?CALL_LOCAL
916
 
        end,
917
 
      NewRefs = [{Patch,Addr,Target} | Refs],
918
 
      NewI = hipe_sparc:call_link_target_update(Instr,0),
919
 
      Code = assemble_instr(NewI),
920
 
      {Code,Addr+4,NewRefs}
921
 
  end.
922
 
 
923
 
%% ------------------------------------------------------------------
924
 
  
925
 
get_code(CompiledCode) -> % -> {CodeSize,ExportMap,NewCode}
926
 
  get_code(CompiledCode, 0, [], []).
927
 
 
928
 
get_code([{MFA,Insns,_Data}|Rest], Address, Map, AccCode) ->
929
 
  {NewInsns,NewAddress,NewMap} = preprocess(Insns,MFA,Address,Map),
930
 
  get_code(Rest, NewAddress, NewMap, [{MFA,NewInsns}|AccCode]);
931
 
get_code([], Address, Map, AccCode) ->
932
 
  {Address,Map,lists:reverse(AccCode)}.
933
 
 
934
 
preprocess(Entry, MFA, Address, Map) ->
935
 
  %% io:format("~w at ~w ~w\n",[MFA,Address]),
936
 
  process_instr(Entry, Address,
937
 
                [{{MFA,entry},hot,Address}|Map],
938
 
                MFA, []).
939
 
 
940
 
process_instr([I|Is], Address, Map, MFA, AccCode) ->
941
 
  case I of
942
 
    #label{} ->
943
 
      process_instr(Is, Address,
944
 
                    [{{MFA,hipe_sparc:label_name(I)},hot,Address}|Map],
945
 
                    MFA, AccCode);
946
 
    #comment{} ->
947
 
      process_instr(Is, Address, Map, MFA, AccCode);
948
 
    #load_address{} ->
949
 
      process_instr(Is, Address+8, Map, MFA, [I|AccCode]);
950
 
    #load_atom{} ->
951
 
      process_instr(Is, Address+8, Map, MFA, [I|AccCode]);
952
 
    #load_word_index{} ->
953
 
      process_instr(Is, Address+8, Map, MFA, [I|AccCode]);
954
 
    _Other ->
955
 
      process_instr(Is, Address+4, Map, MFA, [I|AccCode])
956
 
  end;
957
 
process_instr([], Address, Map, _MFA, AccCode) ->
958
 
  {lists:reverse(AccCode),Address,Map}.
959
 
 
960
 
%% ------------------------------------------------------------------
961
 
%%
962
 
%% Constant map
963
 
%%
964
 
 
965
 
find_const(Name, Tree) ->
966
 
  case gb_trees:lookup(Name,Tree) of
967
 
    {value,V} -> V;
968
 
    none -> ?EXIT({could_not_find_constant, Name, Tree})
969
 
  end.
970
 
 
971
 
init_const_map(List) ->
972
 
  init_const_map(List, gb_trees:empty()).
973
 
init_const_map([{pcm_entry,MFA,Label,ConstNo,_,_,_} | List], Tree) ->
974
 
  init_const_map(List,gb_trees:insert({MFA,Label}, ConstNo ,Tree));
975
 
init_const_map([], Tree) ->
976
 
  Tree.
977
 
 
978
 
%% ------------------------------------------------------------------
979
 
%%
980
 
%% Label map: represented with double gbtrees.
981
 
%%
982
 
 
983
 
local_labels(MFA, Map) ->
984
 
  case gb_trees:lookup(MFA, Map) of
985
 
    {value,T} -> T;
986
 
    none -> ?EXIT({mfa_not_in_map,MFA,Map})
987
 
  end.
988
 
  
989
 
find(L, Tree) ->
990
 
  case gb_trees:lookup(L, Tree) of
991
 
    {value,V} -> V;
992
 
    none -> ?EXIT({label_not_in_map,L,Tree})
993
 
  end.
994
 
 
995
 
init_export_map(List) ->
996
 
  init_export_map(List, gb_trees:empty()).
997
 
 
998
 
init_export_map([{{M,L},Seg,Addr}|List], Tree) ->
999
 
  init_export_map(List, init_m(M, L, {Seg,Addr}, Tree));
1000
 
init_export_map([], Tree) -> Tree.
1001
 
 
1002
 
init_m(M, L, Data, Tree) ->
1003
 
  case gb_trees:lookup(M, Tree) of
1004
 
    {value,T2} ->
1005
 
      gb_trees:update(M, gb_trees:insert(L, Data, T2), Tree);
1006
 
    none ->
1007
 
      gb_trees:insert(M, gb_trees:insert(L, Data, gb_trees:empty()), Tree)
1008
 
  end.
1009
 
 
1010
 
%% %%--------------------------------------------------------------------
1011
 
%% %%
1012
 
%% %% check_immediates asserts that all immediates are less than 13 bits
1013
 
%% %% Returns true if the code is ok.
1014
 
%% %% Exception: {'EXIT',{immediate_too_large, [{Instr1,[Imm1,Imm2]},{Instr2,[Imm3|...]}|...]}}
1015
 
%% %%  if Imm1 and Imm2 are too large.
1016
 
%% %%
1017
 
%% check_immediates(Instrs) -> check_immediates(Instrs,[]).
1018
 
%% 
1019
 
%% check_immediates([],[]) -> true;
1020
 
%% check_immediates([],Problems) -> exit({immediate_too_large,Problems});
1021
 
%% check_immediates([Instr|Rest],Problems) ->
1022
 
%%   case hipe_sparc:is_sethi(Instr) of
1023
 
%%     true -> check_immediates(Rest,Problems);
1024
 
%%     _ -> 
1025
 
%%       case check_imm(hipe_sparc:imm_uses(Instr),[]) of
1026
 
%%      true ->
1027
 
%%        check_immediates(Rest,Problems);
1028
 
%%      MoreProblems -> 
1029
 
%%        check_immediates(Rest,[{Instr,MoreProblems}|Problems])
1030
 
%%       end
1031
 
%%   end.
1032
 
%% 
1033
 
%% check_imm([],[]) -> true;
1034
 
%% check_imm([],Problems) -> Problems;
1035
 
%% check_imm([Use|Rest],Problems) ->
1036
 
%%   case hipe_sparc:is_imm(Use) of 
1037
 
%%     true -> 
1038
 
%%       Val = hipe_sparc:imm_value(Use),
1039
 
%%       if 
1040
 
%%      Val > 4095 -> %% Largest possible immediate.
1041
 
%%        check_imm(Rest,[Val|Problems]);
1042
 
%%      true -> 
1043
 
%%        check_imm(Rest,Problems)
1044
 
%%       end;
1045
 
%%     _ ->     
1046
 
%%       check_imm(Rest,Problems)
1047
 
%%   end.
1048
 
 
1049
 
%% ------------------------------------------------------------------
1050
 
%% valid_branch_length(relativeDestination) 
1051
 
%%  Validates that the destination is within reach.
1052
 
%%
1053
 
%% XXX: this only works for disp19-type branches.
1054
 
%% XXX: update for disp16 (BPr) and disp22 (Bicc) type branches
1055
 
%%
1056
 
 
1057
 
valid_branch_length(Dest) ->
1058
 
  if (abs(Dest) band (16#FFF80000)) > 0 ->
1059
 
      false;
1060
 
    true -> true
1061
 
  end.
1062