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_ppc_pp).
16-export([pp/1, pp/2, pp_insn/1]).
17
18-include("hipe_ppc.hrl").
19
20pp(Defun) ->
21  pp(standard_io, Defun).
22
23pp(Dev, #defun{mfa={M,F,A}, code=Code, data=Data}) ->
24  Fname = atom_to_list(M)++"_"++atom_to_list(F)++"_"++integer_to_list(A),
25  io:format(Dev, "\t.text\n", []),
26  io:format(Dev, "\t.align 4\n", []),
27  io:format(Dev, "\t.global ~s\n", [Fname]),
28  io:format(Dev, "~s:\n", [Fname]),
29  pp_insns(Dev, Code, Fname),
30  io:format(Dev, "\t.rodata\n", []),
31  io:format(Dev, "\t.align 4\n", []),
32  hipe_data_pp:pp(Dev, Data, ppc, Fname),
33  io:format(Dev, "\n", []).
34
35pp_insns(Dev, [I|Is], Fname) ->
36  pp_insn(Dev, I, Fname),
37  pp_insns(Dev, Is, Fname);
38pp_insns(_, [], _) ->
39  [].
40
41pp_insn(I) ->
42  pp_insn(standard_io, I, "").
43
44pp_insn(Dev, I, Pre) ->
45  case I of
46    #alu{aluop=AluOp, dst=Dst, src1=Src1, src2=Src2} ->
47      io:format(Dev, "\t~s ", [alu_op_name(AluOp)]),
48      pp_temp(Dev, Dst),
49      io:format(Dev, ", ", []),
50      pp_temp(Dev, Src1),
51      io:format(Dev, ", ", []),
52      pp_src(Dev, Src2),
53      io:format(Dev, "\n", []);
54    #b_fun{'fun'=Fun, linkage=Linkage} ->
55      io:format(Dev, "\tb ", []),
56      pp_fun(Dev, Fun),
57      io:format(Dev, " # ~w\n", [Linkage]);
58    #b_label{label=Label} ->
59      io:format(Dev, "\tb .~s_~w\n", [Pre, Label]);
60    #bc{bcond=BCond, label=Label, pred=Pred} ->
61      io:format(Dev, "\tb~w ~s_~w # ~.2f\n", [bcond_name(BCond), Pre, Label, Pred]);
62    #bctr{labels=Labels} ->
63      io:format(Dev, "\tbctr", []),
64      case Labels of
65	[] -> [];
66	_ ->
67	  io:format(Dev, " #", []),
68	  pp_labels(Dev, Labels, Pre)
69      end,
70      io:format(Dev, "\n", []);
71    #bctrl{sdesc=SDesc} ->
72      io:format(Dev, "\tbctrl #", []),
73      pp_sdesc(Dev, Pre, SDesc),
74      io:format(Dev, "\n", []);
75    #bl{'fun'=Fun, sdesc=SDesc, linkage=Linkage} ->
76      io:format(Dev, "\tbl ", []),
77      pp_fun(Dev, Fun),
78      io:format(Dev, " #", []),
79      pp_sdesc(Dev, Pre, SDesc),
80      io:format(Dev, " ~w\n", [Linkage]);
81    #blr{} ->
82      io:format(Dev, "\tblr\n", []);
83    #comment{term=Term} ->
84      io:format(Dev, "\t# ~p\n", [Term]);
85    #cmp{cmpop=CmpOp, src1=Src1, src2=Src2} ->
86      io:format(Dev, "\t~s ", [cmp_op_name(CmpOp)]),
87      pp_temp(Dev, Src1),
88      io:format(Dev, ", ", []),
89      pp_src(Dev, Src2),
90      io:format(Dev, "\n", []);
91    #label{label=Label} ->
92      io:format(Dev, ".~s_~w:~n", [Pre, Label]);
93    #load{ldop=LdOp, dst=Dst, disp=Disp, base=Base} ->
94      io:format(Dev, "\t~w ", [ldop_name(LdOp)]),
95      pp_temp(Dev, Dst),
96      io:format(Dev, ", ~s(", [to_hex(Disp)]),
97      pp_temp(Dev, Base),
98      io:format(Dev, ")\n", []);
99    #loadx{ldxop=LdxOp, dst=Dst, base1=Base1, base2=Base2} ->
100      io:format(Dev, "\t~w ", [ldxop_name(LdxOp)]),
101      pp_temp(Dev, Dst),
102      io:format(Dev, ", ", []),
103      pp_temp(Dev, Base1),
104      io:format(Dev, ", ", []),
105      pp_temp(Dev, Base2),
106      io:format(Dev, "\n", []);
107    #mfspr{dst=Dst, spr=SPR} ->
108      io:format(Dev, "\tmf~w ", [spr_name(SPR)]),
109      pp_temp(Dev, Dst),
110      io:format(Dev, "\n", []);
111    #mtcr{src=Src} ->
112      io:format(Dev, "\tmtcrf 0x80, ", []),
113      pp_temp(Dev, Src),
114      io:format(Dev, "\n", []);
115    #mtspr{spr=SPR, src=Src} ->
116      io:format(Dev, "\tmt~w ", [spr_name(SPR)]),
117      pp_temp(Dev, Src),
118      io:format(Dev, "\n", []);
119    #pseudo_bc{bcond=BCond, true_label=TrueLab, false_label=FalseLab, pred=Pred} ->
120      io:format(Dev, "\tpseudo_bc ~w, .~s_~w # .~s_~w ~.2f\n",
121		[bcond_name(BCond), Pre, TrueLab, Pre, FalseLab, Pred]);
122    #pseudo_call{func=FunC, sdesc=SDesc, contlab=ContLab, linkage=Linkage} ->
123      io:format(Dev, "\tpseudo_call ", []),
124      pp_func(Dev, FunC),
125      io:format(Dev, " # contlab .~s_~w", [Pre, ContLab]),
126      pp_sdesc(Dev, Pre, SDesc),
127      io:format(Dev, " ~w\n", [Linkage]);
128    #pseudo_call_prepare{nrstkargs=NrStkArgs} ->
129      SP = hipe_ppc_registers:reg_name_gpr(hipe_ppc_registers:stack_pointer()),
130      io:format(Dev, "\taddi ~s, ~s, ~w # pseudo_call_prepare\n",
131		[SP, SP, -(4*NrStkArgs)]);
132    #pseudo_li{dst=Dst, imm=Imm} ->
133      io:format(Dev, "\tpseudo_li ", []),
134      pp_temp(Dev, Dst),
135      io:format(Dev, ", ", []),
136      pp_imm(Dev, Imm),
137      io:format(Dev, "\n", []);
138    #pseudo_move{dst=Dst, src=Src} ->
139      io:format(Dev, "\tpseudo_move ", []),
140      pp_temp(Dev, Dst),
141      io:format(Dev, ", ", []),
142      pp_temp(Dev, Src),
143      io:format(Dev, "\n", []);
144    #pseudo_tailcall{func=FunC, arity=Arity, stkargs=StkArgs, linkage=Linkage} ->
145      io:format(Dev, "\tpseudo_tailcall ", []),
146      pp_func(Dev, FunC),
147      io:format(Dev, "/~w (", [Arity]),
148      pp_args(Dev, StkArgs),
149      io:format(Dev, ") ~w\n", [Linkage]);
150    #pseudo_tailcall_prepare{} ->
151      io:format(Dev, "\tpseudo_tailcall_prepare\n", []);
152    #store{stop=StOp, src=Src, disp=Disp, base=Base} ->
153      io:format(Dev, "\t~s ", [stop_name(StOp)]),
154      pp_temp(Dev, Src),
155      io:format(Dev, ", ~s(", [to_hex(Disp)]),
156      pp_temp(Dev, Base),
157      io:format(Dev, ")\n", []);
158    #storex{stxop=StxOp, src=Src, base1=Base1, base2=Base2} ->
159      io:format(Dev, "\t~s ", [stxop_name(StxOp)]),
160      pp_temp(Dev, Src),
161      io:format(Dev, ", ", []),
162      pp_temp(Dev, Base1),
163      io:format(Dev, ", ", []),
164      pp_temp(Dev, Base2),
165      io:format(Dev, "\n", []);
166    #unary{unop={UnOp,I1,I2,I3}, dst=Dst, src=Src} ->
167      io:format(Dev, "\t~s ", [UnOp]),
168      pp_temp(Dev, Dst),
169      io:format(Dev, ", ", []),
170      pp_temp(Dev, Src),
171      io:format(Dev, ", ~s, ~s, ~s\n", [to_hex(I1),to_hex(I2),to_hex(I3)]);
172    #unary{unop=UnOp, dst=Dst, src=Src} ->
173      io:format(Dev, "\t~w ", [unop_name(UnOp)]),
174      pp_temp(Dev, Dst),
175      io:format(Dev, ", ", []),
176      pp_temp(Dev, Src),
177      io:format(Dev, "\n", []);
178    #lfd{dst=Dst, disp=Disp, base=Base} ->
179      io:format(Dev, "\tlfd ", []),
180      pp_temp(Dev, Dst),
181      io:format(Dev, ", ~s(", [to_hex(Disp)]),
182      pp_temp(Dev, Base),
183      io:format(Dev, ")\n", []);
184    #lfdx{dst=Dst, base1=Base1, base2=Base2} ->
185      io:format(Dev, "\tlfdx ", []),
186      pp_temp(Dev, Dst),
187      io:format(Dev, ", ", []),
188      pp_temp(Dev, Base1),
189      io:format(Dev, ", ", []),
190      pp_temp(Dev, Base2),
191      io:format(Dev, "\n", []);
192    #stfd{src=Src, disp=Disp, base=Base} ->
193      io:format(Dev, "\tstfd ", []),
194      pp_temp(Dev, Src),
195      io:format(Dev, ", ~s(", [to_hex(Disp)]),
196      pp_temp(Dev, Base),
197      io:format(Dev, ")\n", []);
198    #stfdx{src=Src, base1=Base1, base2=Base2} ->
199      io:format(Dev, "\tstfdx ", []),
200      pp_temp(Dev, Src),
201      io:format(Dev, ", ", []),
202      pp_temp(Dev, Base1),
203      io:format(Dev, ", ", []),
204      pp_temp(Dev, Base2),
205      io:format(Dev, "\n", []);
206    #fp_binary{fp_binop=FpBinOp, dst=Dst, src1=Src1, src2=Src2} ->
207      io:format(Dev, "\t~s ", [FpBinOp]),
208      pp_temp(Dev, Dst),
209      io:format(Dev, ", ", []),
210      pp_temp(Dev, Src1),
211      io:format(Dev, ", ", []),
212      pp_temp(Dev, Src2),
213      io:format(Dev, "\n", []);
214    #fp_unary{fp_unop=FpUnOp, dst=Dst, src=Src} ->
215      io:format(Dev, "\t~s ", [FpUnOp]),
216      pp_temp(Dev, Dst),
217      io:format(Dev, ", ", []),
218      pp_temp(Dev, Src),
219      io:format(Dev, "\n", []);
220    #pseudo_fmove{dst=Dst, src=Src} ->
221      io:format(Dev, "\tpseudo_fmove ", []),
222      pp_temp(Dev, Dst),
223      io:format(Dev, ", ", []),
224      pp_temp(Dev, Src),
225      io:format(Dev, "\n", []);
226    _ ->
227      exit({?MODULE, pp_insn, I})
228  end.
229
230to_hex(N) ->
231  io_lib:format("~.16x", [N, "0x"]).
232
233pp_sdesc(Dev, Pre, #ppc_sdesc{exnlab=ExnLab,fsize=FSize,arity=Arity,live=Live}) ->
234  pp_sdesc_exnlab(Dev, Pre, ExnLab),
235  io:format(Dev, " ~s ~w [", [to_hex(FSize), Arity]),
236  pp_sdesc_live(Dev, Live),
237  io:format(Dev, "]", []).
238
239pp_sdesc_exnlab(Dev, _, []) -> io:format(Dev, " []", []);
240pp_sdesc_exnlab(Dev, Pre, ExnLab) -> io:format(Dev, " .~s_~w", [Pre, ExnLab]).
241
242pp_sdesc_live(_, {}) -> [];
243pp_sdesc_live(Dev, Live) -> pp_sdesc_live(Dev, Live, 1).
244
245pp_sdesc_live(Dev, Live, I) ->
246  io:format(Dev, "~s", [to_hex(element(I, Live))]),
247  if I < tuple_size(Live) ->
248      io:format(Dev, ",", []),
249      pp_sdesc_live(Dev, Live, I+1);
250     true -> []
251  end.
252
253pp_labels(Dev, [Label|Labels], Pre) ->
254  io:format(Dev, " .~s_~w", [Pre, Label]),
255  pp_labels(Dev, Labels, Pre);
256pp_labels(_, [], _) ->
257  [].
258
259pp_fun(Dev, Fun) ->
260  case Fun of
261    #ppc_mfa{m=M, f=F, a=A} ->
262      io:format(Dev, "~w:~w/~w", [M, F, A]);
263    #ppc_prim{prim=Prim} ->
264      io:format(Dev, "~w", [Prim])
265  end.
266
267pp_func(Dev, FunC) ->
268  case FunC of
269    'ctr' ->
270      io:format(Dev, "ctr", []);
271    Fun ->
272      pp_fun(Dev, Fun)
273  end.
274
275alu_op_name(Op) -> Op.
276
277bcond_name(BCond) -> BCond.
278
279cmp_op_name(Op) -> Op.
280
281spr_name(SPR) -> SPR.
282
283ldop_name(LdOp) -> LdOp.
284
285ldxop_name(LdxOp) -> LdxOp.
286
287stop_name(StOp) -> StOp.
288
289stxop_name(StxOp) -> StxOp.
290
291unop_name(UnOp) -> UnOp.
292
293pp_temp(Dev, Temp=#ppc_temp{reg=Reg, type=Type}) ->
294  case hipe_ppc:temp_is_precoloured(Temp) of
295    true ->
296      Name =
297	case Type of
298	  'double' -> hipe_ppc_registers:reg_name_fpr(Reg);
299	  _ -> hipe_ppc_registers:reg_name_gpr(Reg)
300	end,
301      io:format(Dev, "~s", [Name]);
302    false ->
303      Tag =
304	case Type of
305	  double -> "f";
306	  tagged -> "t";
307	  untagged -> "u"
308	end,
309      io:format(Dev, "~s~w", [Tag, Reg])
310  end.
311
312pp_hex(Dev, Value) -> io:format(Dev, "~s", [to_hex(Value)]).
313pp_simm16(Dev, #ppc_simm16{value=Value}) -> pp_hex(Dev, Value).
314pp_uimm16(Dev, #ppc_uimm16{value=Value}) -> pp_hex(Dev, Value).
315
316pp_imm(Dev, Value) ->
317  if is_integer(Value) -> pp_hex(Dev, Value);
318     true -> io:format(Dev, "~w", [Value])
319  end.
320
321pp_src(Dev, Src) ->
322  case Src of
323    #ppc_temp{} ->
324      pp_temp(Dev, Src);
325    #ppc_simm16{} ->
326      pp_simm16(Dev, Src);
327    #ppc_uimm16{} ->
328      pp_uimm16(Dev, Src)
329  end.
330
331pp_arg(Dev, Arg) ->
332  case Arg of
333    #ppc_temp{} ->
334      pp_temp(Dev, Arg);
335    _ ->
336      pp_hex(Dev, Arg)
337  end.
338
339pp_args(Dev, [A|As]) ->
340  pp_arg(Dev, A),
341  pp_comma_args(Dev, As);
342pp_args(_, []) ->
343  [].
344
345pp_comma_args(Dev, [A|As]) ->
346  io:format(Dev, ", ", []),
347  pp_arg(Dev, A),
348  pp_comma_args(Dev, As);
349pp_comma_args(_, []) ->
350  [].
351