~statik/ubuntu/maverick/erlang/erlang-merge-testing

« back to all changes in this revision

Viewing changes to lib/hipe/sparc/0OLD/hipe_sparc_frame.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_frame.erl
4
 
%%  Module   :  hipe_sparc_frame
5
 
%%  Purpose  :  
6
 
%%  Notes    :  
7
 
%%              The code may only have spilled registers in
8
 
%%              the pseudo instructions: 
9
 
%%
10
 
%%                pseudo_spill   t1, t2 ; spills t1 to spillpos of t2
11
 
%%                pseudo_unspill t1, t2 ; loads t1 from spillpos of t2 
12
 
%% 
13
 
%%              The TempMap must contain mappings from all used temps
14
 
%%              to physical registers or spill positions.   
15
 
%%
16
 
%%              XXX: New immediates are introduced as stack offsets.
17
 
%%                   If more than 1024 stack slots are needed,
18
 
%%                   the immediate offsets will be to big for a
19
 
%%                   sparc instruction.
20
 
%%                   This can happen with the naive allocator.
21
 
%%                   A special pass called from hipe_main 
22
 
%%                   rectifies this situation.
23
 
%% 
24
 
%%  History  :  * 2001-10-25 Erik Johansson (happi@csd.uu.se): 
25
 
%%               Created.
26
 
%%  CVS      :
27
 
%%              $Author: mikpe $
28
 
%%              $Date: 2007/12/18 09:18:21 $
29
 
%%              $Revision: 1.1 $
30
 
%% ====================================================================
31
 
%%  Exports  :
32
 
%%
33
 
%% TODO:
34
 
%%  Optimize 
35
 
%%  Handle multiple return values
36
 
%%
37
 
%% Testcases:
38
 
%% hipe:c({len,len,2},[pp_rtl,{regalloc,naive}]).
39
 
%% hipe:c({len,len,2},[pp_sparc,{regalloc,lfls}]).
40
 
%% hipe:c({late,t,0},[pp_sparc,{regalloc,lfls}]).
41
 
%% hipe:c({late,seven,7},[pp_sparc,{regalloc,lfls}]).
42
 
%% hipe:c({late,test_enter,7},[pp_sparc,{regalloc,lfls}]).
43
 
%% hipe:c({trivial_19,test,0},[pp_sparc,{regalloc,lfls}]).
44
 
%%
45
 
 
46
 
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
47
 
 
48
 
-module(hipe_sparc_frame).
49
 
-export([frame/5]).
50
 
 
51
 
%% -define(DO_ASSERT,true).
52
 
-include("../main/hipe.hrl").
53
 
-include("hipe_sparc.hrl").
54
 
-include("../rtl/hipe_literals.hrl").
55
 
 
56
 
-define(MK_CP_REG(),(hipe_sparc:mk_reg(hipe_sparc_registers:return_address()))).
57
 
-define(MK_SP_REG(),(hipe_sparc:mk_reg(hipe_sparc_registers:stack_pointer()))).
58
 
-define(MK_TEMP_REG(),(hipe_sparc:mk_reg(hipe_sparc_registers:temp0()))).
59
 
-define(MK_TEMP_FPREG(),(hipe_sparc:mk_fpreg(0))).
60
 
-define(IS_SPILLED(Reg,Map),hipe_temp_map:is_spilled(hipe_sparc:reg_nr(Reg),Map)).
61
 
 
62
 
frame(Cfg, TempMap, FpMap, NextSpillPos, _Options) ->
63
 
  %% io:format("~p\n",[TempMap]),
64
 
  rewrite(Cfg, TempMap, FpMap, NextSpillPos).
65
 
 
66
 
rewrite(Cfg, TempMap, FpMap, NextSpillPos) ->
67
 
  %% hipe_sparc_cfg:pp(Cfg),
68
 
  Sparc = hipe_sparc_cfg:linearize(Cfg),
69
 
  Arity = hipe_sparc:sparc_arity(Sparc),
70
 
  Code = hipe_sparc:sparc_code(Sparc),
71
 
  %% ConvNeed is added if there are any conv_fp instructions.
72
 
  ConvNeed = 
73
 
    case get(hipe_inline_fp) of
74
 
      true ->  
75
 
        lists:foldl(fun(I, Acc) -> 
76
 
                        case hipe_sparc:is_conv_fp(I) of true -> 1; _ -> Acc end
77
 
                    end, 0, Code);
78
 
      _ ->
79
 
        0
80
 
    end,
81
 
  
82
 
  %% Need is stack positions for spills
83
 
  Need = NextSpillPos + 1 + ConvNeed, 
84
 
  %% +1 for CP, not realy needed for leaf functions... 
85
 
  
86
 
  %% ExtraNeed is room for arguments in calls. 
87
 
  ExtraNeed = extra_stack_need(Code, Need, Arity),
88
 
  StackNeed = Need + ExtraNeed,
89
 
 
90
 
  SP = ?MK_SP_REG(),
91
 
  CP = ?MK_CP_REG(),
92
 
  NewStart = hipe_sparc:label_create_new(),
93
 
 
94
 
  {StackTestCode, StackIncCode} =
95
 
    gen_stack_test(StackNeed, SP, CP, Arity, Cfg),
96
 
  NeedInBytes = Need bsl ?log2_wordsize,
97
 
  AllocCode = gen_alloc_code(NeedInBytes, SP),
98
 
 
99
 
  EntryCode = 
100
 
    [NewStart,
101
 
     StackTestCode,  %% (We will flatten the list later.)
102
 
     AllocCode,
103
 
     gen_save_cp(Need)],
104
 
 
105
 
  {RetCode,RetLabel} = gen_ret(Need, Arity),
106
 
  
107
 
  NewCode = 
108
 
    [EntryCode,
109
 
     %% Rewrite instructions to use physical registers 
110
 
     %% instead of temps.
111
 
     %% Also, handle pseudo instructions.
112
 
     if is_tuple(TempMap) -> % XXX: can someone please explain the logic here?
113
 
         [rewrite_instr(I, TempMap, FpMap, Need, Arity, RetLabel) || I <- Code];
114
 
        true ->
115
 
         rewrite_instrs(Code, [], TempMap, FpMap, Need, Arity, RetLabel)
116
 
     end,
117
 
     RetCode,
118
 
     %% code to call increment stack.
119
 
     StackIncCode],
120
 
 
121
 
  %% Create a new CFG
122
 
  NewSparc = hipe_sparc:sparc_code_update(Sparc, lists:flatten(NewCode)),
123
 
  CFG0 = hipe_sparc_cfg:init(NewSparc),
124
 
  %% io:format("\n\n\n\n\n\n\n\nAfter frame\n"),
125
 
  %% hipe_sparc_cfg:pp(CFG1),
126
 
  CFG0.
127
 
 
128
 
rewrite_instrs([I|Is], TempMap, TempMaps, FpMap, Need, Arity, RetLabel) ->
129
 
  NewMap = 
130
 
    case hipe_sparc:is_label(I) of
131
 
      true ->
132
 
%%      io:format("~w\n",[hipe_vectors:get(TempMaps, hipe_sparc:label_name(I)-1)]),
133
 
        hipe_vectors:get(TempMaps, hipe_sparc:label_name(I)-1);
134
 
      false ->
135
 
        TempMap
136
 
    end,
137
 
  [rewrite_instr(I, NewMap, FpMap, Need, Arity, RetLabel) |
138
 
   rewrite_instrs(Is, NewMap, TempMaps, FpMap, Need, Arity, RetLabel)];
139
 
rewrite_instrs([], _, _, _, _, _, _) ->
140
 
  [].
141
 
 
142
 
rewrite_instr(I, TempMap, FpMap, Need, Arity, RetLabel) ->
143
 
  %% io:format("\n\n~w -> \n",[I]),
144
 
  I1 = remap_fp_regs(I, FpMap),
145
 
  I2 = rewrite_instr2(I1, TempMap, FpMap,Need, Arity, RetLabel),
146
 
  %% io:format("~w\n",[I2]),
147
 
  I2.
148
 
 
149
 
remap_fp_regs(I, FpMap) ->
150
 
  case I of
151
 
    %% These instructions handle their own remapping.
152
 
    #fmove{} -> I;
153
 
    #pseudo_spill{} -> I;
154
 
    #pseudo_unspill{} -> I;
155
 
    _ ->
156
 
      Defs = hipe_sparc:fp_reg_defines(I),
157
 
      NewI = remap_fp(remap_fp(I, Defs, FpMap),
158
 
                      hipe_sparc:fp_reg_uses(I),
159
 
                      FpMap),
160
 
      NewI
161
 
  end.
162
 
 
163
 
rewrite_instr2(I, TempMap, FpMap, Need, Arity, RetLabel) ->
164
 
  case I of
165
 
    %% #pseudo_push{} ->
166
 
    %%   ?EXIT({pseudo_push, not_supported_any_more, I});
167
 
    #pseudo_pop{} ->
168
 
      Temp = hipe_sparc:pseudo_pop_reg(I),
169
 
      Reg = map(Temp,TempMap),
170
 
      %% Arg position on stack = -(arg index + need)*4
171
 
      ArgIndex = hipe_sparc:imm_value(hipe_sparc:pseudo_pop_index(I)),
172
 
      Pos = - ((ArgIndex + Need) bsl ?log2_wordsize),
173
 
      gen_stack_load(Pos, Reg);
174
 
    #move{} ->
175
 
      rewrite_move(I, TempMap);
176
 
    #pseudo_spill{} ->
177
 
      rewrite_spill(I, TempMap, FpMap);
178
 
    #pseudo_unspill{} ->
179
 
      rewrite_unspill(I, TempMap, FpMap);
180
 
    #call_link{} ->
181
 
      rewrite_call(I, TempMap, Need, Arity);
182
 
    #pseudo_return{} ->
183
 
      %% Note we assume that the arguments to return have been 
184
 
      %% mapped to physical register in the translation RTL->SPARC.
185
 
 
186
 
      %% XXX: Fix if we start using multiple return values
187
 
      %%      Acctually just fix gen_ret/2 to annotate the
188
 
      %%      jmp with the live registers...
189
 
      case length(hipe_sparc:pseudo_return_regs(I)) =:= 1 of
190
 
        true -> %% Just one retval all is ok
191
 
          hipe_sparc:goto_create(RetLabel);
192
 
        false ->
193
 
          %% Number of retvalues not 1.
194
 
          ?EXIT({multiple_retvals_not_handled,I})
195
 
      end;
196
 
    #pseudo_enter{} ->
197
 
      rewrite_enter(I, TempMap, Need, Arity);
198
 
    #fmove{} ->
199
 
      rewrite_fmove(I, TempMap, FpMap);
200
 
    #load_fp{} -> 
201
 
      rewrite_load_fp(I, TempMap);
202
 
    #store_fp{} -> 
203
 
      rewrite_store_fp(I, TempMap);
204
 
    #conv_fp{} ->
205
 
      NewI = map_temps(I, TempMap),
206
 
      Source = hipe_sparc:conv_fp_src(NewI),
207
 
      Dest = hipe_sparc:conv_fp_dest(NewI),
208
 
      Off = hipe_sparc:mk_imm(get_offset(Need - 1)),
209
 
      SP = hipe_sparc:mk_reg(hipe_sparc_registers:stack_pointer()),
210
 
      [hipe_sparc:store_create(SP, Off, w, Source),
211
 
       hipe_sparc:load_fp_create(Dest, 32, single, SP, Off),
212
 
       hipe_sparc:conv_fp_create(Dest, Dest)];
213
 
    _ -> 
214
 
      %% All other instructions.
215
 
      %% No special handling, just map the temps to regs or spill positions.
216
 
      map_temps(I, TempMap)
217
 
  end.
218
 
 
219
 
 
220
 
rewrite_enter(I, TempMap, Need, Arity) ->
221
 
  %% Calculate number of args (to current fun) on stack
222
 
  %% Consider moving this out of the loop.
223
 
  NoRegArgs = hipe_sparc_registers:register_args(),
224
 
  ArgsOnStack = 
225
 
    if Arity > NoRegArgs -> Arity - NoRegArgs; 
226
 
       true -> 0 
227
 
    end,
228
 
 
229
 
  %% Get arguments to enter.
230
 
  Args = hipe_sparc:pseudo_enter_args(I), 
231
 
  RegArgs = lists:sublist(Args, 1, NoRegArgs),
232
 
  %% Get target (closure or address).
233
 
  T = hipe_sparc:pseudo_enter_target(I),
234
 
  {Target,GetTInstr} =
235
 
    case hipe_sparc:pseudo_enter_is_known(I) of
236
 
      false ->
237
 
        {map(T, TempMap),[]};
238
 
      true ->
239
 
        TR = ?MK_TEMP_REG(),
240
 
        TT = case hipe_sparc:pseudo_enter_type(I) of
241
 
               remote -> remote_function;
242
 
               not_remote -> local_function
243
 
             end,
244
 
        TI = hipe_sparc:load_address_create(TR, T, TT),
245
 
        {TR,TI}
246
 
    end,
247
 
  CP = ?MK_CP_REG(),
248
 
 
249
 
  %% The code for enter.
250
 
  [
251
 
   %% Restore CP from stack
252
 
   %% TODO: Do this only in non-leaf functions.
253
 
   gen_stack_load(-(Need bsl ?log2_wordsize), CP),
254
 
   
255
 
   %% If arguments to the called function spill over to the 
256
 
   %% stack, do some shuffling.
257
 
   %% Otherwise just adjust the stackpointer.
258
 
   case length(Args) > NoRegArgs of
259
 
     true ->
260
 
       enter_stack_args(Args, Need, TempMap, ArgsOnStack);
261
 
     false ->
262
 
       gen_dealloc_code((ArgsOnStack+Need) bsl ?log2_wordsize)
263
 
   end,
264
 
   
265
 
   %% Jump to the target function.
266
 
   GetTInstr,
267
 
   hipe_sparc:jmp_create(Target, hipe_sparc:mk_imm(0), 
268
 
                         [map(R,TempMap)||R <- RegArgs] , [])].
269
 
 
270
 
map_temps(I, TempMap) ->
271
 
  Defs = hipe_sparc:keep_registers(hipe_sparc:defines(I)),
272
 
  Uses = hipe_sparc:keep_registers(hipe_sparc:uses(I)),
273
 
  remap(remap(I, Defs, TempMap), Uses, TempMap).
274
 
 
275
 
rewrite_call(Call, TempMap, Need, Arity) ->
276
 
  I = set_stack_size(Call,Need, Arity),
277
 
  Args = hipe_sparc:call_link_args(I),
278
 
  PushCode = push_call_args(Args, TempMap),
279
 
  NewI = remap_call_regs(I, TempMap),
280
 
  [PushCode,NewI].
281
 
 
282
 
 
283
 
remap_call_regs(I, TempMap) ->
284
 
  Defs = hipe_sparc:keep_registers(hipe_sparc:defines(I)),
285
 
  ArgsInRegs = lists:sublist(hipe_sparc:call_link_args(I), 
286
 
                             hipe_sparc_registers:register_args()),
287
 
  case hipe_sparc:call_link_is_known(I) of
288
 
    false ->
289
 
      Target = hipe_sparc:call_link_target(I),
290
 
      case ?IS_SPILLED(Target,TempMap) of
291
 
        true ->
292
 
          RemappedCall = remap(I, Defs ++ ArgsInRegs, TempMap),
293
 
          Temp = ?MK_TEMP_REG(),
294
 
          Pos = get_spill_offset(hipe_temp_map:find(hipe_sparc:reg_nr(Target), TempMap)),
295
 
          [gen_stack_load(Pos, Temp),
296
 
           hipe_sparc:call_link_target_update(RemappedCall, Temp)];
297
 
        false ->
298
 
          remap(I, [Target | (Defs ++ ArgsInRegs)], TempMap)
299
 
      end;
300
 
    true ->
301
 
      remap(I, Defs ++ ArgsInRegs, TempMap)
302
 
  end.
303
 
 
304
 
 
305
 
%% ____________________________________________________________________
306
 
%%
307
 
%% Returns:     
308
 
%% Arguments:   
309
 
%% Description:  
310
 
%% ____________________________________________________________________
311
 
rewrite_move(I, TempMap) ->
312
 
  Src = hipe_sparc:move_src(I),
313
 
  Dest = hipe_sparc:move_dest(I),
314
 
  DestReg = hipe_sparc:reg_nr(Dest),
315
 
 
316
 
  case hipe_sparc:is_reg(Src) of
317
 
    false ->
318
 
      case hipe_temp_map:is_spilled(DestReg,TempMap) of
319
 
        true ->
320
 
          Pos = get_spill_offset(hipe_temp_map:find(DestReg, TempMap)),
321
 
          Reg = ?MK_TEMP_REG(),
322
 
          [hipe_sparc:move_dest_update(I,Reg)|
323
 
           gen_stack_store(Pos, Reg)];
324
 
        false ->
325
 
          remap(I, [Dest], TempMap)
326
 
      end;
327
 
    true ->
328
 
      SrcReg = hipe_sparc:reg_nr(Src),
329
 
      case {hipe_temp_map:is_spilled(SrcReg,TempMap),
330
 
            hipe_temp_map:is_spilled(DestReg,TempMap)} of
331
 
        {false,true} -> %% spill
332
 
          Pos = get_spill_offset(hipe_temp_map:find(DestReg, TempMap)),
333
 
          Reg = map(Src,TempMap),
334
 
          gen_stack_store(Pos, Reg);
335
 
        {true,false} -> %% unspill
336
 
          Pos = get_spill_offset(hipe_temp_map:find(SrcReg, TempMap)),
337
 
          Reg = map(Dest,TempMap),
338
 
          gen_stack_load(Pos, Reg);
339
 
        {false,false} ->
340
 
          remap(I, [Src,Dest], TempMap);
341
 
        {true,true} ->
342
 
          Pos1 = get_spill_offset(hipe_temp_map:find(SrcReg, TempMap)),
343
 
          Pos2 = get_spill_offset(hipe_temp_map:find(DestReg, TempMap)),
344
 
          Reg = ?MK_TEMP_REG(),
345
 
          [gen_stack_load(Pos1, Reg),
346
 
           gen_stack_store(Pos2, Reg)]
347
 
      end
348
 
  end.
349
 
 
350
 
%% ____________________________________________________________________
351
 
%%      
352
 
%% Returns:     
353
 
%% Arguments:   
354
 
%% Description:  
355
 
%% ____________________________________________________________________
356
 
rewrite_spill(I, TempMap, FpMap) ->
357
 
  SrcReg = hipe_sparc:pseudo_spill_reg(I),
358
 
  Pos = get_spill_offset(hipe_sparc:pseudo_spill_pos(I)),
359
 
 
360
 
  case hipe_sparc:is_fpreg(SrcReg) of
361
 
    true ->
362
 
      SrcFpRegNr = hipe_sparc:fpreg_nr(SrcReg),
363
 
      case hipe_temp_map:in_fp_reg(SrcFpRegNr,FpMap) of
364
 
        false ->
365
 
          %% Spilling a spilled reg...
366
 
          ?ASSERT(check_spill(SrcFpRegNr,FpMap,Pos,I)),
367
 
          hipe_sparc:comment_create({already_spilled,I});
368
 
        true -> %% Not spilled...
369
 
          Reg = map_fp(SrcReg, FpMap),
370
 
          gen_stack_store_fp(Pos, Reg)
371
 
      end;
372
 
    false ->
373
 
      SrcRegNr = hipe_sparc:reg_nr(SrcReg),
374
 
      case hipe_temp_map:in_reg(SrcRegNr,TempMap) of
375
 
        false ->
376
 
          %% Spilling a spilled reg...
377
 
          ?ASSERT(check_spill(SrcRegNr,TempMap,Pos,I)),
378
 
          hipe_sparc:comment_create({already_spilled,I});
379
 
        true -> %% Not spilled...
380
 
          Reg = map(SrcReg,TempMap),
381
 
          gen_stack_store(Pos, Reg)
382
 
      end
383
 
  end.
384
 
 
385
 
%% --------------------------------------------------------------------
386
 
%% Returns:     
387
 
%% Arguments:   
388
 
%% Description: 
389
 
%% --------------------------------------------------------------------
390
 
 
391
 
rewrite_unspill(I, TempMap, FpMap) ->
392
 
  DstReg = hipe_sparc:pseudo_unspill_reg(I),
393
 
  Pos = get_spill_offset(hipe_sparc:pseudo_unspill_pos(I)),
394
 
  case hipe_sparc:is_fpreg(DstReg) of
395
 
    true ->
396
 
      DstFpRegNr = hipe_sparc:fpreg_nr(DstReg),
397
 
      case hipe_temp_map:in_fp_reg(DstFpRegNr,FpMap) of
398
 
        false ->
399
 
          %% Unspilling to a spilled fpreg...
400
 
          ?ASSERT(check_spill(DstFpRegNr,FpMap,Pos,I)),
401
 
          hipe_sparc:comment_create({already_unspilled,I});
402
 
        true -> %% Not spilled...
403
 
          Reg = map_fp(DstReg, FpMap),
404
 
          gen_stack_load_fp(Pos, Reg)
405
 
      end;
406
 
    false ->
407
 
      DstRegNr = hipe_sparc:reg_nr(DstReg),
408
 
      case hipe_temp_map:in_reg(DstRegNr,TempMap) of
409
 
        false -> %% Unspilling to a spilled reg.
410
 
          ?ASSERT(check_spill(DstRegNr,TempMap,Pos,I)),
411
 
          hipe_sparc:comment_create({already_unspilled,I});
412
 
        true -> %% Not spilled.
413
 
          Reg = map(DstReg,TempMap),
414
 
          gen_stack_load(Pos,Reg)
415
 
      end
416
 
  end.
417
 
 
418
 
-ifdef(DO_ASSERT).
419
 
check_spill(RegNr,TempMap,Pos,I) ->
420
 
  case (catch hipe_temp_map:find(RegNr, TempMap)) of
421
 
    unknown -> true;
422
 
    DPos -> (get_spill_offset(DPos) =:= Pos)
423
 
  end.
424
 
-endif.
425
 
 
426
 
rewrite_fmove(I0, TempMap, FpMap)->
427
 
  I = map_temps(I0, TempMap),
428
 
  Src = hipe_sparc:fmove_src(I),
429
 
  Dest = hipe_sparc:fmove_dest(I),
430
 
  DestReg = hipe_sparc:fpreg_nr(Dest),
431
 
 
432
 
  case hipe_sparc:is_fpreg(Src) of
433
 
    false -> %% Can this happen?
434
 
      case hipe_temp_map:is_spilled(DestReg,FpMap) of
435
 
        true ->
436
 
          Pos = get_spill_offset(hipe_temp_map:find(DestReg, FpMap)),
437
 
          Reg = ?MK_TEMP_FPREG(),
438
 
          [hipe_sparc:fmove_dest_update(I,Reg)|
439
 
           gen_stack_store_fp(Pos, Reg)];
440
 
        false ->
441
 
          remap_fp(I, [Dest], FpMap)
442
 
      end;
443
 
    true ->
444
 
      SrcReg = hipe_sparc:fpreg_nr(Src),
445
 
 
446
 
      case {hipe_temp_map:is_spilled(SrcReg,FpMap),
447
 
            hipe_temp_map:is_spilled(DestReg,FpMap)} of
448
 
        {false,true} -> %% spill
449
 
          Pos = get_spill_offset(hipe_temp_map:find(DestReg, FpMap)),
450
 
          Reg = map_fp(Src,FpMap),
451
 
          gen_stack_store_fp(Pos, Reg);
452
 
        {true,false} -> %% unspill
453
 
          Pos = get_spill_offset(hipe_temp_map:find(SrcReg, FpMap)),
454
 
          Reg = map_fp(Dest,FpMap),
455
 
          gen_stack_load_fp(Pos, Reg);
456
 
        {false,false} ->
457
 
          remap_fp(I, [Src,Dest], FpMap);
458
 
        {true,true} ->
459
 
          Pos1 = get_spill_offset(hipe_temp_map:find(SrcReg, FpMap)),
460
 
          Pos2 = get_spill_offset(hipe_temp_map:find(DestReg, FpMap)),
461
 
          Reg = ?MK_TEMP_FPREG(),
462
 
          [gen_stack_load_fp(Pos1, Reg),
463
 
           gen_stack_store_fp(Pos2, Reg)]
464
 
      end
465
 
  end.  
466
 
 
467
 
rewrite_load_fp(I, TempMap)->
468
 
  NewI = map_temps(I, TempMap),
469
 
  Source = hipe_sparc:load_fp_src(NewI),
470
 
  Dest = hipe_sparc:load_fp_dest(NewI),
471
 
  Off = hipe_sparc:load_fp_off(NewI),
472
 
  Align = hipe_sparc:load_fp_align(NewI),
473
 
  case hipe_sparc:load_fp_type(NewI) of
474
 
    double ->
475
 
      Dest2 = hipe_sparc:mk_fpreg(hipe_sparc:fpreg_nr(Dest) + 1),
476
 
      case hipe_sparc:is_imm(Off) of
477
 
        true ->
478
 
          Off2 = hipe_sparc:mk_imm(hipe_sparc:imm_value(Off) + 4),
479
 
          [hipe_sparc:load_fp_create(Dest, Align, single, Source, Off),
480
 
           hipe_sparc:load_fp_create(Dest2, Align, single, Source, Off2)];
481
 
        _ -> %% The offset is a register
482
 
          [hipe_sparc:load_fp_create(Dest, Align, single, Source, Off),
483
 
           hipe_sparc:alu_create(Off, Off, '+', hipe_sparc:mk_imm(4)),
484
 
           hipe_sparc:load_fp_create(Dest2, Align, single, Source, Off),
485
 
           hipe_sparc:alu_create(Off, Off, '-', hipe_sparc:mk_imm(4))]
486
 
      end;
487
 
    _ ->
488
 
      NewI
489
 
  end.
490
 
 
491
 
rewrite_store_fp(I, TempMap)->
492
 
  NewI = map_temps(I, TempMap),
493
 
  Source = hipe_sparc:store_fp_src(NewI),
494
 
  Dest = hipe_sparc:store_fp_dest(NewI),
495
 
  Off = hipe_sparc:store_fp_off(NewI),
496
 
  Align = hipe_sparc:store_fp_align(NewI),
497
 
  case hipe_sparc:store_fp_type(NewI) of
498
 
    double ->
499
 
      Source2 = hipe_sparc:mk_fpreg(hipe_sparc:fpreg_nr(Source) + 1),
500
 
      case hipe_sparc:is_imm(Off) of
501
 
        true ->
502
 
          Off2 = hipe_sparc:mk_imm(hipe_sparc:imm_value(Off) + 4),
503
 
          [hipe_sparc:store_fp_create(Dest, Off, single, Align, Source),
504
 
           hipe_sparc:store_fp_create(Dest, Off2, single, Align, Source2)];
505
 
        _ ->
506
 
          [hipe_sparc:store_fp_create(Dest, Off, single, Align, Source),
507
 
           hipe_sparc:alu_create(Off, Off, '+', hipe_sparc:mk_imm(4)),
508
 
           hipe_sparc:store_fp_create(Dest, Off, single, Align, Source2),
509
 
           hipe_sparc:alu_create(Off, Off, '-', hipe_sparc:mk_imm(4))]
510
 
      end;
511
 
    _ ->
512
 
      NewI
513
 
  end.
514
 
 
515
 
get_offset(O) when is_integer(O) ->
516
 
  -4 * O.
517
 
 
518
 
get_spill_pos(P) ->
519
 
  get_offset(P+1).
520
 
 
521
 
get_spill_offset(T) ->
522
 
 get_spill_pos(element(2,T)).
523
 
 
524
 
enter_stack_args(Args, Need, TempMap, ArgsOnStack) ->
525
 
  enter_stack_args(0, hipe_sparc_registers:register_args(), Args,
526
 
                   Need, TempMap, ArgsOnStack).
527
 
 
528
 
%%
529
 
%% The stack on SPARC grows uppwards (At least now...)
530
 
%%
531
 
%% Assume a function f with Arity = j is doing a tail-call to
532
 
%% a function g with arity k. 
533
 
%% Also assume the current function has spilled i temps.
534
 
%%
535
 
%%  Current stack frame:
536
 
%%
537
 
%%        |         |
538
 
%% SP ->  |         |
539
 
%%        | Spill 0 |
540
 
%%        |  ...    |
541
 
%%        | Spill i |
542
 
%%        | Dead CP |  (Read to %o7)    
543
 
%%        | Arg j   |
544
 
%%        | ...     |
545
 
%%        | Arg 6   |  (Currently 5 args in reg)
546
 
%%        |OLD FRAME|
547
 
%%
548
 
%%  Stack just before call to target:
549
 
%%        |         |
550
 
%% sp ->  |         |
551
 
%%        |         |
552
 
%% SP ->  |         |                   
553
 
%%        | Arg' k  |
554
 
%%        | ...     |
555
 
%%        | ...     |
556
 
%%        | ...     |
557
 
%%        | Arg' 6  |  (Currently 5 args in reg)
558
 
%%        |OLD FRAME|
559
 
%%
560
 
%% The arguments to g might be on the stack
561
 
%% If they are in the dangezone (the area overwritten by the arguments)
562
 
%% They have to be moved.
563
 
%% e.g. ( d marks the dangerzone)
564
 
%%           f/7               g/10
565
 
%%        |         |
566
 
%% SP ->  |         |
567
 
%%        | Spill 1 |   SP ->|         |
568
 
%%   d    | Spill 2 |        | Spill 1 |
569
 
%%   d    | Spill 3 |        | Spill 2 |
570
 
%%   d    | Dead CP |        | Spill 3 |
571
 
%%   d    | Arg 7   |        | Arg 6   |
572
 
%%   d    | Arg 6   |        | t1      |
573
 
%%        |OLD FRAME|        |OLD FRAME|
574
 
%%
575
 
%%   The DangerZone is SP - 2 to SP - 6
576
 
%%  We go through the arguments to g bottom up:
577
 
%%
578
 
%%   DZ     ARG      POSITION       SAVE  
579
 
%%
580
 
%%    < -6, t1     : in reg -> OK
581
 
%%    < -5, Arg 6  : SP-6 -> in DZ, Save = [SP-6]  
582
 
%%    < -4, Spill 2: SP-2 -> OK
583
 
%%    < -3, Spill 3: SP-1 -> OK
584
 
%%    < -2, Spill 1: SP-3 -> in DZ, Save = [SP-3, SP-6]
585
 
%%
586
 
%%  Then we copy the positions in Save to the top of the stack.
587
 
%%        | Arg 6   |
588
 
%% SP ->  | Spill 1 |
589
 
%%        | Spill 3 |
590
 
%%   d    | Spill 2 |
591
 
%%   d    | Spill 1 |
592
 
%%   d    | Dead CP |
593
 
%%   d    | Arg 7   |
594
 
%%   d    | Arg 6   |
595
 
%%        |OLD FRAME|
596
 
%%
597
 
%%  Now we can rewrite the stack safely:
598
 
%%        | A g 6   |
599
 
%% sp ->  | S i l 1 |
600
 
%% SP ->  | s i l 2 |
601
 
%%        | Spill 1 |
602
 
%%        | Spill 2 |
603
 
%%        | Spill 3 |
604
 
%%        | Arg 6   |
605
 
%%        | t1      |
606
 
%%        |OLD FRAME|
607
 
 
608
 
%% TODO: Verify that this really is correct.
609
 
 
610
 
enter_stack_args(ArgNo, ArgNo, Args, Need, TempMap, ArgsOnStack) ->
611
 
  %% How many args has to be spilled to the stack?
612
 
  NoNewArgsOnStack = length(Args),
613
 
 
614
 
  %% Where does the first arg end up?
615
 
  %% SP - (Need + ArgsOnStack)*4
616
 
  Base = -(Need + ArgsOnStack),
617
 
 
618
 
  {ToSave,RealArgs} = args_in_danger(Args, Base-1, [], 0, [], TempMap),
619
 
 
620
 
  TempReg = ?MK_TEMP_REG(),
621
 
  SaveCode = save(ToSave,0, TempReg),
622
 
  PushCode = pushem(RealArgs, Base, TempReg),
623
 
 
624
 
  AdjustOffset = (ArgsOnStack + Need - NoNewArgsOnStack) bsl ?log2_wordsize,
625
 
  AdjustSP = gen_dealloc_code(AdjustOffset),
626
 
  [SaveCode, PushCode, AdjustSP];
627
 
enter_stack_args(No, NoRegArgs, [_Arg|Args], Need, TempMap, ArgsOnStack) ->
628
 
  enter_stack_args(No+1, NoRegArgs, Args, Need, TempMap, ArgsOnStack).
629
 
 
630
 
args_in_danger([Arg|Args], DangerZone, ToSave, SavePos, MappedArgs, TempMap) ->
631
 
  case hipe_sparc:is_reg(Arg) of
632
 
    true ->
633
 
      case hipe_temp_map:find(hipe_sparc:reg_nr(Arg), TempMap) of
634
 
        {reg, Reg} -> %% Arg in reg all cool.
635
 
          args_in_danger(Args, DangerZone+1, ToSave, SavePos, 
636
 
                         [{reg, Reg}|MappedArgs], TempMap);
637
 
        {spill, Pos} when is_integer(Pos) ->
638
 
          if -Pos < DangerZone -> %% Spill in dangerzone
639
 
              args_in_danger(Args, DangerZone+1, [-Pos|ToSave], SavePos+1,
640
 
                             [{spill, SavePos}|MappedArgs], TempMap);
641
 
             true ->
642
 
              args_in_danger(Args, DangerZone+1, ToSave, SavePos,
643
 
                             [{spill, -(Pos+1)}|MappedArgs], TempMap)
644
 
          end
645
 
      end;
646
 
    false ->
647
 
      case hipe_sparc:is_imm(Arg) of 
648
 
        true ->
649
 
          args_in_danger(Args, DangerZone+1, ToSave, SavePos, 
650
 
                         [{imm, hipe_sparc:imm_value(Arg)}|MappedArgs],
651
 
                         TempMap);
652
 
        false ->
653
 
          %% TODO: XXX: Dont handle fpreg ...
654
 
          ?EXIT({do_no_handle,Arg})
655
 
      end
656
 
  end;
657
 
args_in_danger([],_,ToSave,_,Args,_) ->
658
 
  {lists:reverse(ToSave),lists:reverse(Args)}.
659
 
 
660
 
save([Pos|Poses], Offset, TempReg) ->
661
 
  ToPos = Offset bsl ?log2_wordsize,
662
 
  FromPos = get_offset(Pos+1),
663
 
  [gen_stack_load(FromPos, TempReg),
664
 
   gen_stack_store(ToPos, TempReg)
665
 
   | save(Poses, Offset+1, TempReg)];
666
 
save([],_,_) -> [].
667
 
 
668
 
pushem([{reg,R}|Args], Pos, Temp) ->
669
 
  ToPos = Pos bsl ?log2_wordsize,
670
 
  [gen_stack_store(ToPos, hipe_sparc:mk_reg(R)) | pushem(Args,Pos+1, Temp)];
671
 
pushem([{spill,P}|Args], Pos, Temp) ->
672
 
  FromPos = P bsl ?log2_wordsize, 
673
 
  ToPos = Pos bsl ?log2_wordsize,
674
 
  [gen_stack_load(FromPos, Temp),
675
 
   gen_stack_store(ToPos, Temp) |
676
 
   pushem(Args,Pos+1, Temp)];
677
 
pushem([{imm,I}|Args], Pos, Temp) ->
678
 
  ToPos = Pos bsl ?log2_wordsize,
679
 
  [hipe_sparc:move_create(Temp, hipe_sparc:mk_imm(I)),
680
 
   gen_stack_store(ToPos, Temp) |
681
 
   pushem(Args, Pos+1, Temp)];
682
 
pushem([], _, _) -> [].
683
 
 
684
 
find_reg(Temp,Map) ->
685
 
  case hipe_temp_map:find(hipe_sparc:reg_nr(Temp), Map) of 
686
 
    {reg, Pos} ->
687
 
      Pos;
688
 
    Where -> ?EXIT({temp_assumed_in_reg,Temp,Where})
689
 
  end.
690
 
 
691
 
find_fpreg(Temp,Map) ->
692
 
  case hipe_temp_map:find(hipe_sparc:fpreg_nr(Temp), Map) of 
693
 
    {fp_reg, Pos} ->
694
 
      Pos;
695
 
    Where -> ?EXIT({temp_assumed_in_fpreg,Temp,Where})
696
 
  end.
697
 
 
698
 
%%find_pos(Temp,Map) ->
699
 
%%    case hipe_temp_map:find(hipe_sparc:reg_nr(Temp), Map) of
700
 
%%    {spill, Pos} ->
701
 
%%      Pos;
702
 
%%    Where -> ?EXIT({temp_assumed_on_stack,Temp,Where})
703
 
%%  end.
704
 
 
705
 
remap(I, Temps, Map) ->
706
 
  %% io:format("\n\n~w~w\n~w\n",[I,Temps,Map]),
707
 
  Substs = [{Temp, hipe_sparc:mk_reg(find_reg(Temp,Map))} || Temp <- Temps],
708
 
  hipe_sparc:subst(I, Substs).
709
 
 
710
 
remap_fp(I, Temps, Map) ->
711
 
  %% io:format("\n\n~w~w\n~w\n",[I,Temps,Map]),
712
 
  Substs = 
713
 
    [{Temp, hipe_sparc:mk_fpreg(find_fpreg(Temp,Map))} || Temp <- Temps],
714
 
  hipe_sparc:subst(I, Substs).
715
 
 
716
 
map_fp(Temp, Map) ->
717
 
  case hipe_sparc:is_fpreg(Temp) of
718
 
    true ->
719
 
      hipe_sparc:mk_fpreg(find_fpreg(Temp, Map));
720
 
    false ->
721
 
      Temp
722
 
  end.
723
 
 
724
 
map(Temp, Map) ->
725
 
  case hipe_sparc:is_reg(Temp) of
726
 
    true ->
727
 
      hipe_sparc:mk_reg(find_reg(Temp, Map));
728
 
    false ->
729
 
      Temp
730
 
  end.
731
 
 
732
 
max(P, A) when is_integer(P), is_integer(A) ->
733
 
  if P > A -> P;
734
 
     true -> A
735
 
  end.
736
 
 
737
 
min(P, A) when is_integer(P), is_integer(A) ->
738
 
  if P < A -> P;
739
 
     true -> A
740
 
  end.
741
 
 
742
 
push_call_args(Args, TempMap) ->
743
 
  ArgsOnStack = args_on_stack(hipe_sparc_registers:register_args(), Args),
744
 
  NoArgs = length(ArgsOnStack),      
745
 
  if NoArgs > 0 ->
746
 
      MappedArgs = 
747
 
        [
748
 
         case hipe_sparc:is_reg(Arg) of
749
 
           true ->
750
 
             case hipe_temp_map:find(hipe_sparc:reg_nr(Arg), TempMap) of
751
 
               {reg, Reg} -> {reg,Reg};
752
 
               {spill, Pos} -> {spill, -(1+Pos+NoArgs)}
753
 
             end;
754
 
           false ->
755
 
             case hipe_sparc:is_imm(Arg) of 
756
 
               true ->
757
 
                 {imm,hipe_sparc:imm_value(Arg)};
758
 
               false ->
759
 
                 %% TODO: XXX: Dont handle fpreg ...
760
 
                 ?EXIT({do_no_handle,Arg})
761
 
             end
762
 
         end
763
 
         || Arg <- ArgsOnStack],
764
 
      SP = ?MK_SP_REG(),
765
 
      TempReg = ?MK_TEMP_REG(),
766
 
      AdjustSP = hipe_sparc:alu_create(SP,SP,'+',hipe_sparc:mk_imm(4*NoArgs)),
767
 
      PushCode = pushem(MappedArgs,-NoArgs,TempReg),
768
 
      [AdjustSP|PushCode];
769
 
    true ->
770
 
      [] %% No args on the stack.
771
 
  end.
772
 
 
773
 
args_on_stack(0, [_|_] = Args) ->
774
 
  Args;
775
 
args_on_stack(N, [_Arg|Args]) ->
776
 
  args_on_stack(N-1, Args);
777
 
args_on_stack(_N, []) -> 
778
 
  [].
779
 
 
780
 
extra_stack_need(Code, Need, Arity) when is_integer(Need) ->
781
 
  %% Calculate number of args (to current fun) on stack
782
 
  NoRegArgs = hipe_sparc_registers:register_args(),
783
 
  ArgsOnStack = 
784
 
    if Arity > NoRegArgs -> Arity - NoRegArgs; 
785
 
       true -> 0 
786
 
    end,
787
 
  PrevSPLevel = ArgsOnStack + Need,  
788
 
  lists:foldl(fun (I, Max) ->
789
 
                  max(stack_need(I, PrevSPLevel), Max)
790
 
              end, 
791
 
              0,
792
 
              Code).
793
 
 
794
 
stack_need(I, PrevSPLevel) ->
795
 
  %% io:format("\n\n~w\n~w\n",[I,TempMap]),
796
 
  case I of
797
 
    #call_link{} ->
798
 
      Argneed = call_args_need(hipe_sparc:call_link_args(I)),
799
 
      Argneed;
800
 
    #pseudo_enter{} ->
801
 
      NoArgs = length(hipe_sparc:pseudo_enter_args(I)),
802
 
      NoRegArgs = hipe_sparc_registers:register_args(),
803
 
      %% stack, do some shuffling.
804
 
      %% Otherwise just adjust the stack pointer.
805
 
      case NoArgs > NoRegArgs of
806
 
        true ->        
807
 
          %% Arguments to the called function spill 
808
 
          NewOnStack = NoArgs - NoRegArgs,
809
 
          case NewOnStack > PrevSPLevel of
810
 
            true -> NewOnStack - PrevSPLevel;
811
 
            false -> 0
812
 
          end;
813
 
        false -> %% All arguments on stack...
814
 
          0
815
 
      end;
816
 
    _ -> 
817
 
      %% All other instructions no extra need.
818
 
      0
819
 
  end.
820
 
 
821
 
call_args_need(Args) ->
822
 
  length(args_on_stack(hipe_sparc_registers:register_args(), Args)).
823
 
 
824
 
set_stack_size(Call, Size, Arity) ->
825
 
  SD = hipe_sparc:call_link_stack_desc(Call),
826
 
  NewSD = hipe_sparc:sdesc_size_update(SD, Size),
827
 
  NewSD2 = hipe_sparc:sdesc_arity_update(NewSD, Arity),
828
 
  hipe_sparc:call_link_stack_desc_update(Call, NewSD2).
829
 
 
830
 
gen_stack_test(StackNeed, SP, CP, Arity, Cfg) when is_integer(StackNeed) ->
831
 
  Leaf = hipe_sparc_cfg:is_leaf(Cfg),
832
 
  TempReg = ?MK_TEMP_REG(),
833
 
  TempReg1 = hipe_sparc:mk_reg(hipe_sparc_registers:temp1()),
834
 
  if StackNeed =:= 0 ->
835
 
      {[],[]};
836
 
     StackNeed < ?SPARC_LEAF_WORDS, Leaf =:= true ->
837
 
      {[],[]};
838
 
     true -> 
839
 
      Zero = hipe_sparc:mk_reg(hipe_sparc_registers:zero()),
840
 
      SL = hipe_sparc:mk_reg(hipe_sparc_registers:stack_limit()),
841
 
      Pred = 0.01,
842
 
      OverflowLbl = hipe_sparc:label_create_new(),
843
 
      StartLbl = hipe_sparc:label_create_new(),
844
 
      TestLbl = hipe_sparc:label_create_new(),
845
 
      RetLbl = hipe_sparc:label_create_new(),
846
 
      OverflowName = hipe_rtl:label_name(OverflowLbl), 
847
 
      StartName = hipe_rtl:label_name(StartLbl),
848
 
      TestName = hipe_rtl:label_name(TestLbl),
849
 
      ByteNeed = (?SPARC_LEAF_WORDS+StackNeed) bsl ?log2_wordsize, 
850
 
      TestCode = 
851
 
        if ByteNeed > 16#fff -> %% Max in simm13.
852
 
            [
853
 
             hipe_sparc:alu_create(TempReg, SL, '-', SP),
854
 
             hipe_sparc:sethi_create(TempReg1,
855
 
                                     hipe_sparc:mk_imm(high22(ByteNeed))),
856
 
             hipe_sparc:alu_create(TempReg1, TempReg1, 'or', 
857
 
                                   hipe_sparc:mk_imm(low10(ByteNeed))),
858
 
             hipe_sparc:alu_cc_create(Zero, TempReg, '-', TempReg1),
859
 
             hipe_sparc:b_create(l, OverflowName, StartName, Pred, na),
860
 
             StartLbl];
861
 
           true ->
862
 
            [hipe_sparc:alu_create(TempReg, SL, '-', SP),
863
 
             hipe_sparc:alu_cc_create(Zero, TempReg, '-', 
864
 
                                      hipe_sparc:mk_imm(ByteNeed)),
865
 
             hipe_sparc:b_create(l, OverflowName, StartName, Pred, na),
866
 
             StartLbl]
867
 
        end,
868
 
      CPSAVE = hipe_sparc:mk_reg(hipe_sparc_registers:cpsave()),
869
 
      {[hipe_sparc:goto_create(TestName),
870
 
        TestLbl|TestCode],
871
 
       [OverflowLbl,
872
 
        hipe_sparc:move_create(CPSAVE, CP),
873
 
        hipe_sparc:call_link_create(inc_stack_fun(Arity),
874
 
                                    CP,
875
 
                                    [CPSAVE],
876
 
                                    hipe_rtl:label_name(RetLbl), [], not_remote),
877
 
        RetLbl,
878
 
        hipe_sparc:move_create(CP, CPSAVE),
879
 
        hipe_sparc:goto_create(TestName)]
880
 
      }
881
 
  end.
882
 
 
883
 
inc_stack_fun(Arity) ->
884
 
  ArgsInRegs = min(Arity, hipe_sparc_registers:register_args()), 
885
 
  list_to_atom("inc_stack_" ++ integer_to_list(ArgsInRegs) ++ "args_0").
886
 
 
887
 
gen_alloc_code(NeededBytes,SP) ->
888
 
  TempReg = ?MK_TEMP_REG(),
889
 
  %% Alloc space on stack for spills
890
 
  if NeededBytes > 4092 -> %% Too big for imm
891
 
      [hipe_sparc:sethi_create(TempReg,
892
 
                               hipe_sparc:mk_imm(high22(NeededBytes))),
893
 
       hipe_sparc:alu_create(TempReg, TempReg, 'or', 
894
 
                             hipe_sparc:mk_imm(low10(NeededBytes))),
895
 
       hipe_sparc:alu_create(SP,SP,'+',TempReg)];
896
 
     true ->
897
 
      [hipe_sparc:alu_create(SP,SP,'+',hipe_sparc:mk_imm(NeededBytes))]
898
 
  end.
899
 
 
900
 
gen_dealloc_code(Bytes) ->
901
 
  TempReg = ?MK_TEMP_REG(),
902
 
  SP = ?MK_SP_REG(),
903
 
  %% dealloc space on stack.
904
 
  if Bytes > 4092 -> %% Too big for imm
905
 
      [hipe_sparc:sethi_create(TempReg,
906
 
                               hipe_sparc:mk_imm(high22(Bytes))),
907
 
       hipe_sparc:alu_create(TempReg, TempReg, 'or', 
908
 
                             hipe_sparc:mk_imm(low10(Bytes))),
909
 
       hipe_sparc:alu_create(SP,SP,'-',TempReg)];
910
 
     true ->
911
 
      [hipe_sparc:alu_create(SP,SP,'-',hipe_sparc:mk_imm(Bytes))]
912
 
  end.
913
 
                                        
914
 
gen_save_cp(Need) ->
915
 
  CP = ?MK_CP_REG(),
916
 
  Offset = get_offset(Need),
917
 
  gen_stack_store(Offset,CP).
918
 
 
919
 
gen_ret(Need, Arity) ->
920
 
  %% Generate code for stack cleanup and return.
921
 
 
922
 
  %% XXX: Fix if we start using multiple return values
923
 
  RegArgs = [hipe_sparc:mk_reg(hipe_sparc_registers:ret(0))], 
924
 
  CP = ?MK_CP_REG(),
925
 
  %% Calculate number of args (to current fun) on stack
926
 
  %% Consider moving this out of the loop.
927
 
  NoRegArgs = hipe_sparc_registers:register_rets(),
928
 
  ArgsOnStack = 
929
 
    if Arity > NoRegArgs -> Arity - NoRegArgs; 
930
 
       true -> 0 
931
 
    end,
932
 
  RetLabel = hipe_sparc:label_create_new(),
933
 
  
934
 
  StackAdjust = (ArgsOnStack+Need) bsl ?log2_wordsize,
935
 
  {[RetLabel,
936
 
    gen_stack_load(get_offset(Need),CP),
937
 
    gen_dealloc_code(StackAdjust),
938
 
    hipe_sparc:jmp_create(CP, hipe_sparc:mk_imm(8), RegArgs, [])
939
 
   ],
940
 
   hipe_sparc:label_name(RetLabel)}.
941
 
 
942
 
high22(X) -> X bsr 10.
943
 
 
944
 
low10(X) -> X band 16#3ff.
945
 
 
946
 
gen_stack_load(Offset, DestReg) ->
947
 
  if Offset < -4092 ->
948
 
      load_huge_spillpos(Offset,DestReg);
949
 
     true ->
950
 
      SP = ?MK_SP_REG(),
951
 
      ImmOffset = hipe_sparc:mk_imm(Offset),
952
 
      [hipe_sparc:load_create(DestReg, uw, SP, ImmOffset)]
953
 
  end.
954
 
 
955
 
gen_stack_store(Offset, Reg) ->
956
 
  if Offset < -4092 ->
957
 
      store_huge_spillpos(Offset,Reg);
958
 
     true ->
959
 
      SP = ?MK_SP_REG(),
960
 
      ImmOffset = hipe_sparc:mk_imm(Offset),
961
 
      [hipe_sparc:store_create(SP,ImmOffset, w, Reg)]
962
 
  end.
963
 
 
964
 
store_huge_spillpos(Offset, RegToSave) ->
965
 
  SP = ?MK_SP_REG(),
966
 
  {DecCode, IncCode, NewOffset} = adjust(Offset,SP),
967
 
  [DecCode, 
968
 
   hipe_sparc:store_create(SP, hipe_sparc:mk_imm(NewOffset), RegToSave),
969
 
   IncCode].
970
 
 
971
 
load_huge_spillpos(Offset, RegToLoad) ->
972
 
  SP = ?MK_SP_REG(),
973
 
  {DecCode, _IncCode, NewOffset} = adjust(Offset, RegToLoad),
974
 
  [hipe_sparc:move_create(RegToLoad, SP),
975
 
   DecCode, 
976
 
   hipe_sparc:load_create(RegToLoad, RegToLoad,
977
 
                          hipe_sparc:mk_imm(NewOffset))].
978
 
 
979
 
gen_stack_load_fp(Offset, DestReg) ->
980
 
  Offset2 = Offset - 4,
981
 
  if Offset2 < -4092 ->
982
 
      load_huge_spillpos_fp(Offset2, DestReg);
983
 
     true ->
984
 
      DestRegNr = hipe_sparc:fpreg_nr(DestReg),
985
 
      DestReg2 = hipe_sparc:mk_fpreg(DestRegNr + 1),
986
 
      SP = ?MK_SP_REG(),
987
 
      [hipe_sparc:load_fp_create(DestReg, 32, single, SP, 
988
 
                                 hipe_sparc:mk_imm(Offset)),
989
 
       hipe_sparc:load_fp_create(DestReg2, 32, single, SP,
990
 
                                 hipe_sparc:mk_imm(Offset2))]
991
 
  end.
992
 
 
993
 
gen_stack_store_fp(Offset, SrcReg) ->
994
 
  Offset2 = Offset - 4,
995
 
  if Offset2 < -4092 ->
996
 
      store_huge_spillpos_fp(Offset2, SrcReg);
997
 
     true ->  
998
 
      SrcRegNr = hipe_sparc:fpreg_nr(SrcReg),
999
 
      SrcReg2 = hipe_sparc:mk_fpreg(SrcRegNr + 1),
1000
 
      SP = ?MK_SP_REG(),
1001
 
      [hipe_sparc:store_fp_create(SP, hipe_sparc:mk_imm(Offset), 
1002
 
                                  single, 32, SrcReg),
1003
 
       hipe_sparc:store_fp_create(SP, hipe_sparc:mk_imm(Offset2), 
1004
 
                                  single, 32, SrcReg2)]
1005
 
  end.
1006
 
 
1007
 
store_huge_spillpos_fp(Offset2, RegToSave) ->
1008
 
  RegNr = hipe_sparc:fpreg_nr(RegToSave),
1009
 
  RegToSave2 = hipe_sparc:mk_fpreg(RegNr+ 1),
1010
 
  SP = ?MK_SP_REG(),
1011
 
  {DecCode, IncCode, NewOffset2} = adjust(Offset2,SP),
1012
 
  [DecCode,
1013
 
   hipe_sparc:store_fp_create(SP, hipe_sparc:mk_imm(NewOffset2+4), 
1014
 
                              single, 32, RegToSave),
1015
 
   hipe_sparc:store_fp_create(SP, hipe_sparc:mk_imm(NewOffset2), 
1016
 
                              single, 32, RegToSave2),
1017
 
   IncCode].
1018
 
 
1019
 
load_huge_spillpos_fp(Offset2, RegToLoad) ->
1020
 
  RegNr = hipe_sparc:fpreg_nr(RegToLoad),
1021
 
  RegToLoad2 = hipe_sparc:mk_fpreg(RegNr + 1),
1022
 
  SP = ?MK_SP_REG(),
1023
 
  {DecCode, IncCode, NewOffset2} = adjust(Offset2,SP),
1024
 
  [DecCode,
1025
 
   hipe_sparc:load_fp_create(RegToLoad, 32, single, SP, 
1026
 
                             hipe_sparc:mk_imm(NewOffset2+4)),
1027
 
   hipe_sparc:load_fp_create(RegToLoad2, 32, single, SP, 
1028
 
                             hipe_sparc:mk_imm(NewOffset2)),
1029
 
   IncCode].
1030
 
 
1031
 
adjust(Offset, Reg) ->
1032
 
  adjust(Offset, Reg, [], []).
1033
 
 
1034
 
adjust(Offset, _Reg, Dec,Inc) when Offset > -4092 ->
1035
 
  {Dec,Inc,Offset};
1036
 
adjust(Offset, Reg, Dec,Inc) ->
1037
 
  NewOffset = Offset + 4092,
1038
 
  Step = hipe_sparc:mk_imm(4092),
1039
 
  adjust(NewOffset, Reg,
1040
 
         [hipe_sparc:alu_create(Reg,Reg,'-',Step)| Dec],
1041
 
         [hipe_sparc:alu_create(Reg,Reg,'+',Step)| Inc]).