1%% -*- erlang-indent-level: 2 -*-
2%%
3%% Licensed under the Apache License, Version 2.0 (the "License");
4%% you may not use this file except in compliance with the License.
5%% You may obtain a copy of the License at
6%%
7%%     http://www.apache.org/licenses/LICENSE-2.0
8%%
9%% Unless required by applicable law or agreed to in writing, software
10%% distributed under the License is distributed on an "AS IS" BASIS,
11%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12%% See the License for the specific language governing permissions and
13%% limitations under the License.
14
15-module(hipe_sparc_pp).
16-export([pp/1, pp/2, pp_insn/1]).
17-include("hipe_sparc.hrl").
18
19pp(Defun) ->
20  pp(standard_io, Defun).
21
22pp(Dev, #defun{mfa={M,F,A}, code=Code, data=Data}) ->
23  Fname = atom_to_list(M)++"_"++atom_to_list(F)++"_"++integer_to_list(A),
24  io:format(Dev, "\t.text\n", []),
25  io:format(Dev, "\t.align 4\n", []),
26  io:format(Dev, "\t.global ~s\n", [Fname]),
27  io:format(Dev, "~s:\n", [Fname]),
28  pp_insns(Dev, Code, Fname),
29  io:format(Dev, "\t.rodata\n", []),
30  io:format(Dev, "\t.align 4\n", []),
31  hipe_data_pp:pp(Dev, Data, sparc, Fname),
32  io:format(Dev, "\n", []).
33
34pp_insns(Dev, [I|Is], Fname) ->
35  pp_insn(Dev, I, Fname),
36  pp_insns(Dev, Is, Fname);
37pp_insns(_, [], _) ->
38  [].
39
40pp_insn(I) ->
41  pp_insn(standard_io, I, "").
42
43pp_insn(Dev, I, Pre) ->
44  case I of
45    #alu{aluop=AluOp, dst=Dst, src1=Src1, src2=Src2} ->
46      io:format(Dev, "\t~s ", [alu_op_name(AluOp)]),
47      case aluop_is_ldop(AluOp) of
48	true ->
49	  io:format(Dev, "[", []),
50	  pp_temp(Dev, Src1),
51	  io:format(Dev, " + ", []),
52	  pp_src(Dev, Src2),
53	  io:format(Dev, "]", []);
54	false ->
55	  pp_temp(Dev, Src1),
56	  io:format(Dev, ", ", []),
57	  pp_src(Dev, Src2)
58      end,
59      io:format(Dev, ", ", []),
60      pp_temp(Dev, Dst),
61      io:format(Dev, "\n", []);
62    #bp{'cond'=Cond, label=Label, pred=Pred} ->
63      io:format(Dev, "\tb~w,~w .~s_~w\n",
64		[cond_name(Cond), pred_name(Pred), Pre, Label]);
65    %% #br{} -> pp_br(Dev, I, Pre);
66    #call_rec{'fun'=Fun, sdesc=SDesc, linkage=Linkage} ->
67      io:format(Dev, "\tcall ", []),
68      pp_fun(Dev, Fun),
69      io:format(Dev, " #", []),
70      pp_sdesc(Dev, Pre, SDesc),
71      io:format(Dev, " ~w\n", [Linkage]);
72    #call_tail{'fun'=Fun, linkage=Linkage} ->
73      io:format(Dev, "\tb ", []),
74      pp_fun(Dev, Fun),
75      io:format(Dev, " # ~w\n", [Linkage]);
76    #comment{term=Term} ->
77      io:format(Dev, "\t# ~p\n", [Term]);
78    #jmp{src1=Src1, src2=Src2, labels=Labels} ->
79      io:format(Dev, "\tjmp [", []),
80      pp_temp(Dev, Src1),
81      io:format(Dev, " + ", []),
82      pp_src(Dev, Src2),
83      io:format(Dev, "]", []),
84      case Labels of
85	[] -> [];
86	_ ->
87	  io:format(Dev, " #", []),
88	  pp_labels(Dev, Labels, Pre)
89      end,
90      io:format(Dev, "\n", []);
91    #jmpl{src=Src, sdesc=SDesc} ->
92      io:format(Dev, "\tjmpl [", []),
93      pp_temp(Dev, Src),
94      io:format(Dev, " + 0], %o7 # ", []),
95      pp_sdesc(Dev, Pre, SDesc),
96      io:format(Dev, "\n", []);
97    #label{label=Label} ->
98      io:format(Dev, ".~s_~w:~n", [Pre, Label]);
99    #pseudo_bp{'cond'=Cond, true_label=TrueLab, false_label=FalseLab, pred=Pred} ->
100      io:format(Dev, "\tpseudo_b~w,~w .~s_~w # .~s_~w\n",
101		[cond_name(Cond), pred_name(Pred), Pre, TrueLab, Pre, FalseLab]);
102    %% #pseudo_br{} -> pp_pseudo_br(Dev, I, Pre);
103    #pseudo_call{funv=FunV, sdesc=SDesc, contlab=ContLab, linkage=Linkage} ->
104      io:format(Dev, "\tpseudo_call ", []),
105      pp_funv(Dev, FunV),
106      io:format(Dev, " # contlab .~s_~w", [Pre, ContLab]),
107      pp_sdesc(Dev, Pre, SDesc),
108      io:format(Dev, " ~w\n", [Linkage]);
109    #pseudo_call_prepare{nrstkargs=NrStkArgs} ->
110      SP = hipe_sparc_registers:reg_name_gpr(hipe_sparc_registers:stack_pointer()),
111      io:format(Dev, "\tsub ~s, ~w, ~s # pseudo_call_prepare\n",
112		[SP, 4*NrStkArgs, SP]);
113    #pseudo_move{src=Src, dst=Dst} ->
114      io:format(Dev, "\tpseudo_move ", []),
115      pp_temp(Dev, Src),
116      io:format(Dev, ", ", []),
117      pp_temp(Dev, Dst),
118      io:format(Dev, "\n", []);
119    #pseudo_ret{} ->
120      io:format(Dev, "\tpseudo_ret\n", []);
121    #pseudo_set{imm=Imm, dst=Dst} ->
122      io:format(Dev, "\tpseudo_set ", []),
123      pp_imm(Dev, Imm),
124      io:format(Dev, ", ", []),
125      pp_temp(Dev, Dst),
126      io:format(Dev, "\n", []);
127    #pseudo_tailcall{funv=FunV, arity=Arity, stkargs=StkArgs, linkage=Linkage} ->
128      io:format(Dev, "\tpseudo_tailcall ", []),
129      pp_funv(Dev, FunV),
130      io:format(Dev, "/~w (", [Arity]),
131      pp_args(Dev, StkArgs),
132      io:format(Dev, ") ~w\n", [Linkage]);
133    #pseudo_tailcall_prepare{} ->
134      io:format(Dev, "\tpseudo_tailcall_prepare\n", []);
135    #rdy{dst=Dst} ->
136      io:format(Dev, "\trd %y, ", []),
137      pp_temp(Dev, Dst),
138      io:format(Dev, "\n", []);
139    #sethi{dst=Dst, uimm22=#sparc_uimm22{value=Value}} ->
140      io:format(Dev, "\tsethi ", []),
141      pp_hex(Dev, Value),
142      io:format(Dev, ", ", []),
143      pp_temp(Dev, Dst),
144      io:format(Dev, "\n", []);
145    #store{stop=StOp, src=Src, base=Base, disp=Disp} ->
146      io:format(Dev, "\t~s ", [stop_name(StOp)]),
147      pp_temp(Dev, Src),
148      io:format(Dev, ", [", []),
149      pp_temp(Dev, Base),
150      io:format(Dev, " + ", []),
151      pp_src(Dev, Disp),
152      io:format(Dev, "]\n", []);
153    #fp_binary{fp_binop=FpBinOp, src1=Src1, src2=Src2, dst=Dst} ->
154      io:format(Dev, "\t~s ", [FpBinOp]),
155      pp_temp(Dev, Src1),
156      io:format(Dev, ", ", []),
157      pp_temp(Dev, Src2),
158      io:format(Dev, ", ", []),
159      pp_temp(Dev, Dst),
160      io:format(Dev, "\n", []);
161    #fp_unary{fp_unop=FpUnOp, src=Src, dst=Dst} ->
162      io:format(Dev, "\t~s ", [FpUnOp]),
163      pp_temp(Dev, Src),
164      io:format(Dev, ", ", []),
165      pp_temp(Dev, Dst),
166      io:format(Dev, "\n", []);
167    #pseudo_fload{base=Base, disp=Disp, dst=Dst, is_single=IsSingle} ->
168      io:format(Dev, "\t~s [",
169		[case IsSingle of
170		   true -> 'ldf';
171		   _ -> 'pseudo_fload' end]),
172      pp_temp(Dev, Base),
173      io:format(Dev, " + ", []),
174      pp_simm13(Dev, Disp),
175      io:format(Dev, "], ", []),
176      pp_temp(Dev, Dst),
177      io:format(Dev, "\n", []);
178    #pseudo_fmove{src=Src, dst=Dst} ->
179      io:format(Dev, "\tpseudo_fmove ", []),
180      pp_temp(Dev, Src),
181      io:format(Dev, ", ", []),
182      pp_temp(Dev, Dst),
183      io:format(Dev, "\n", []);
184    #pseudo_fstore{src=Src, base=Base, disp=Disp} ->
185      io:format(Dev, "\tpseudo_fstore ", []),
186      pp_temp(Dev, Src),
187      io:format(Dev, ", [", []),
188      pp_temp(Dev, Base),
189      io:format(Dev, " + ", []),
190      pp_simm13(Dev, Disp),
191      io:format(Dev, "]\n", []);
192    _ ->
193      exit({?MODULE, pp_insn, I})
194  end.
195
196-ifdef(notdef).	% XXX: only for sparc64, alas
197pp_br(Dev, I, Pre) ->
198  #br{rcond=RCond, src=Src, label=Label, pred=Pred} = I,
199  io:format(Dev, "\tbr~w,~w ", [rcond_name(RCond), pred_name(Pred)]),
200  pp_temp(Dev, Src),
201  io:format(Dev, ", .~s_~w\n", [Pre, Label]).
202
203pp_pseudo_br(Dev, I, Pre) ->
204  #pseudo_br{rcond=RCond, src=Src, true_label=TrueLab, false_label=FalseLab, pred=Pred} = I,
205  io:format(Dev, "\tpseudo_br~w,~w ", [rcond_name(RCond), pred_name(Pred)]),
206  pp_src(Dev, Src),
207  io:format(Dev, ", .~s_~w # .~s_~w\n", [Pre, TrueLab, Pre, FalseLab]).
208-endif.
209
210to_hex(N) ->
211  io_lib:format("~.16x", [N, "0x"]).
212
213pp_sdesc(Dev, Pre, #sparc_sdesc{exnlab=ExnLab,fsize=FSize,arity=Arity,live=Live}) ->
214  pp_sdesc_exnlab(Dev, Pre, ExnLab),
215  io:format(Dev, " ~s ~w [", [to_hex(FSize), Arity]),
216  pp_sdesc_live(Dev, Live),
217  io:format(Dev, "]", []).
218
219pp_sdesc_exnlab(Dev, _, []) -> io:format(Dev, " []", []);
220pp_sdesc_exnlab(Dev, Pre, ExnLab) -> io:format(Dev, " .~s_~w", [Pre, ExnLab]).
221
222pp_sdesc_live(_, {}) -> [];
223pp_sdesc_live(Dev, Live) -> pp_sdesc_live(Dev, Live, 1).
224
225pp_sdesc_live(Dev, Live, I) ->
226  io:format(Dev, "~s", [to_hex(element(I, Live))]),
227  if I < tuple_size(Live) ->
228      io:format(Dev, ",", []),
229      pp_sdesc_live(Dev, Live, I+1);
230     true -> []
231  end.
232
233pp_labels(Dev, [Label|Labels], Pre) ->
234  io:format(Dev, " .~s_~w", [Pre, Label]),
235  pp_labels(Dev, Labels, Pre);
236pp_labels(_, [], _) ->
237  [].
238
239pp_fun(Dev, Fun) ->
240  case Fun of
241    #sparc_mfa{m=M, f=F, a=A} ->
242      io:format(Dev, "~w:~w/~w", [M, F, A]);
243    #sparc_prim{prim=Prim} ->
244      io:format(Dev, "~w", [Prim])
245  end.
246
247pp_funv(Dev, FunV) ->
248  case FunV of
249    #sparc_temp{} ->
250      pp_temp(Dev, FunV);
251    Fun ->
252      pp_fun(Dev, Fun)
253  end.
254
255alu_op_name(Op) -> Op.
256
257aluop_is_ldop(AluOp) ->
258  case AluOp of
259    'ldsb' -> true;
260    'ldsh' -> true;
261    'ldsw' -> true;
262    'ldub' -> true;
263    'lduh' -> true;
264    'lduw' -> true;
265    'ldx' -> true;
266    _ -> false
267  end.
268
269cond_name(Cond) -> Cond.
270%%rcond_name(RCond) -> RCond.
271
272pred_name(Pred) ->
273  if Pred >= 0.5 -> 'pt';
274     true -> 'pn'
275  end.
276
277stop_name(StOp) -> StOp.
278
279pp_temp(Dev, Temp=#sparc_temp{reg=Reg, type=Type}) ->
280  case hipe_sparc:temp_is_precoloured(Temp) of
281    true ->
282      Name =
283	case Type of
284	  double -> hipe_sparc_registers:reg_name_fpr(Reg);
285	  _ -> hipe_sparc_registers:reg_name_gpr(Reg)
286	end,
287      io:format(Dev, "~s", [Name]);
288    false ->
289      Tag =
290	case Type of
291	  double -> "f";
292	  tagged -> "t";
293	  untagged -> "u"
294	end,
295      io:format(Dev, "~s~w", [Tag, Reg])
296  end.
297
298pp_hex(Dev, Value) -> io:format(Dev, "~s", [to_hex(Value)]).
299pp_simm13(Dev, #sparc_simm13{value=Value}) -> pp_hex(Dev, Value).
300pp_uimm5(Dev, #sparc_uimm5{value=Value}) -> pp_hex(Dev, Value).
301
302pp_imm(Dev, Value) ->
303  if is_integer(Value) -> pp_hex(Dev, Value);
304     true -> io:format(Dev, "~w", [Value])
305  end.
306
307pp_src(Dev, Src) ->
308  case Src of
309    #sparc_temp{} ->
310      pp_temp(Dev, Src);
311    #sparc_simm13{} ->
312      pp_simm13(Dev, Src);
313    #sparc_uimm5{} ->	% XXX: sparc64: uimm6
314      pp_uimm5(Dev, Src)
315  end.
316
317pp_arg(Dev, Arg) ->
318  case Arg of
319    #sparc_temp{} ->
320      pp_temp(Dev, Arg);
321    _ ->
322      pp_hex(Dev, Arg)
323  end.
324
325pp_args(Dev, [A|As]) ->
326  pp_arg(Dev, A),
327  pp_comma_args(Dev, As);
328pp_args(_, []) ->
329  [].
330
331pp_comma_args(Dev, [A|As]) ->
332  io:format(Dev, ", ", []),
333  pp_arg(Dev, A),
334  pp_comma_args(Dev, As);
335pp_comma_args(_, []) ->
336  [].
337