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