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_assemble). 16-export([assemble/4]). 17 18-include("../main/hipe.hrl"). % for VERSION_STRING, when_option 19-include("hipe_sparc.hrl"). 20-include("../../kernel/src/hipe_ext_format.hrl"). 21-include("../rtl/hipe_literals.hrl"). 22-include("../misc/hipe_sdi.hrl"). 23-undef(ASSERT). 24-define(ASSERT(G), if G -> [] ; true -> exit({assertion_failed,?MODULE,?LINE,??G}) end). 25 26assemble(CompiledCode, Closures, Exports, Options) -> 27 print("****************** Assembling *******************\n", [], Options), 28 %% 29 Code = [{MFA, 30 hipe_sparc:defun_code(Defun), 31 hipe_sparc:defun_data(Defun)} 32 || {MFA, Defun} <- CompiledCode], 33 %% 34 {ConstAlign,ConstSize,ConstMap,RefsFromConsts} = 35 hipe_pack_constants:pack_constants(Code), 36 %% 37 {CodeSize,CodeBinary,AccRefs,LabelMap,ExportMap} = 38 encode(translate(Code, ConstMap), Options), 39 print("Total num bytes=~w\n", [CodeSize], Options), 40 %% 41 SC = hipe_pack_constants:slim_constmap(ConstMap), 42 DataRelocs = hipe_pack_constants:mk_data_relocs(RefsFromConsts, LabelMap), 43 SSE = hipe_pack_constants:slim_sorted_exportmap(ExportMap,Closures,Exports), 44 SlimRefs = hipe_pack_constants:slim_refs(AccRefs), 45 Bin = term_to_binary([{?VERSION_STRING(),?HIPE_ERTS_CHECKSUM}, 46 ConstAlign, ConstSize, 47 SC, 48 DataRelocs, % nee LM, LabelMap 49 SSE, 50 CodeSize,CodeBinary,SlimRefs, 51 0,[] % ColdCodeSize, SlimColdRefs 52 ]), 53 %% 54 Bin. 55 56%%% 57%%% Assembly Pass 1. 58%%% Process initial {MFA,Code,Data} list. 59%%% Translate each MFA's body, choosing operand & instruction kinds. 60%%% 61%%% Assembly Pass 2. 62%%% Perform short/long form optimisation for jumps. 63%%% 64%%% Result is {MFA,NewCode,CodeSize,LabelMap} list. 65%%% 66 67translate(Code, ConstMap) -> 68 translate_mfas(Code, ConstMap, []). 69 70translate_mfas([{MFA,Insns,_Data}|Code], ConstMap, NewCode) -> 71 {NewInsns,CodeSize,LabelMap} = 72 translate_insns(Insns, MFA, ConstMap, hipe_sdi:pass1_init(), 0, []), 73 translate_mfas(Code, ConstMap, [{MFA,NewInsns,CodeSize,LabelMap}|NewCode]); 74translate_mfas([], _ConstMap, NewCode) -> 75 lists:reverse(NewCode). 76 77translate_insns([I|Insns], MFA, ConstMap, SdiPass1, Address, NewInsns) -> 78 NewIs = translate_insn(I, MFA, ConstMap), 79 add_insns(NewIs, Insns, MFA, ConstMap, SdiPass1, Address, NewInsns); 80translate_insns([], _MFA, _ConstMap, SdiPass1, Address, NewInsns) -> 81 {LabelMap,CodeSizeIncr} = hipe_sdi:pass2(SdiPass1), 82 {lists:reverse(NewInsns), Address+CodeSizeIncr, LabelMap}. 83 84add_insns([I|Is], Insns, MFA, ConstMap, SdiPass1, Address, NewInsns) -> 85 NewSdiPass1 = 86 case I of 87 {'.label',L,_} -> 88 hipe_sdi:pass1_add_label(SdiPass1, Address, L); 89 {bp_sdi,{_,_,{label,L}},_} -> % BP has 19-bit offset 90 SdiInfo = #sdi_info{incr=(12-4),lb=-16#40000*4,ub=16#3FFFF*4}, 91 hipe_sdi:pass1_add_sdi(SdiPass1, Address, L, SdiInfo); 92 %% {br_sdi,_,_} -> add_insns_br(I, SdiPass1, Address); 93 _ -> 94 SdiPass1 95 end, 96 Address1 = Address + insn_size(I), 97 add_insns(Is, Insns, MFA, ConstMap, NewSdiPass1, Address1, [I|NewInsns]); 98add_insns([], Insns, MFA, ConstMap, SdiPass1, Address, NewInsns) -> 99 translate_insns(Insns, MFA, ConstMap, SdiPass1, Address, NewInsns). 100 101-ifdef(notdef). % XXX: only for sparc64, alas 102add_insns_br(I, SdiPass1, Address) -> % BR has 16-bit offset 103 {br_sdi,{_,_,_,{label,L}},_} = I, 104 SdiInfo = #sdi_info{incr=(12-4),lb=-16#8000*4,ub=16#7FFF*4}, 105 hipe_sdi:pass1_add_sdi(SdiPass1, Address, L, SdiInfo). 106-endif. 107 108insn_size(I) -> 109 case I of 110 {'.label',_,_} -> 0; 111 {'.reloc',_,_} -> 0; 112 _ -> 4 % b{p,r}_sdi included in this case 113 end. 114 115translate_insn(I, MFA, ConstMap) -> % -> [{Op,Opnd,OrigI}] 116 case I of 117 #alu{} -> do_alu(I); 118 #bp{} -> do_bp(I); 119 %% #br{} -> do_br(I); 120 #call_rec{} -> do_call_rec(I); 121 #call_tail{} -> do_call_tail(I); 122 #comment{} -> []; 123 #jmp{} -> do_jmp(I); 124 #jmpl{} -> do_jmpl(I); 125 #label{} -> do_label(I); 126 %% pseudo_bp: eliminated before assembly 127 %% pseudo_br: eliminated before assembly 128 %% pseudo_call: eliminated before assembly 129 %% pseudo_call_prepare: eliminated before assembly 130 %% pseudo_move: eliminated before assembly 131 %% pseudo_ret: eliminated before assembly 132 #pseudo_set{} -> do_pseudo_set(I, MFA, ConstMap); 133 %% pseudo_tailcall: eliminated before assembly 134 %% pseudo_tailcall_prepare: eliminated before assembly 135 #rdy{} -> do_rdy(I); 136 #sethi{} -> do_sethi(I); 137 #store{} -> do_store(I); 138 #fp_binary{} -> do_fp_binary(I); 139 #fp_unary{} -> do_fp_unary(I); 140 #pseudo_fload{} -> do_pseudo_fload(I); 141 %% #pseudo_fmove: eliminated before assembly 142 #pseudo_fstore{} -> do_pseudo_fstore(I); 143 _ -> exit({?MODULE,translate_insn,I}) 144 end. 145 146do_alu(I) -> 147 #alu{aluop=AluOp,src1=Src1,src2=Src2,dst=Dst} = I, 148 NewDst = do_reg(Dst), 149 NewSrc1 = do_reg(Src1), 150 NewSrc2 = do_reg_or_imm(Src2), 151 [{AluOp, {NewSrc1,NewSrc2,NewDst}, I}]. 152 153do_bp(I) -> 154 #bp{'cond'=Cond,pred=Pred,label=Label} = I, 155 NewLabel = {label,Label}, 156 case Cond of 157 'a' -> 158 [{ba, NewLabel, I}]; % 3 more offset bits 159 _ -> 160 NewCond = {'cond',Cond}, 161 NewPred = {pred,Pred}, 162 [{bp_sdi, {NewCond,NewPred,NewLabel}, I}] 163 end. 164 165-ifdef(notdef). % XXX: only for sparc64, alas 166do_br(I) -> 167 #br{rcond=RCond,pred=Pred,src=Src,label=Label} = I, 168 NewRCond = {rcond,RCond}, 169 NewPred = {pred,Pred}, 170 NewSrc = do_reg(Src), 171 NewLabel = {label,Label}, 172 [{br_sdi, {NewRCond,NewPred,NewSrc,NewLabel}, I}]. 173-endif. 174 175do_call_rec(I) -> 176 #call_rec{'fun'=Fun,sdesc=SDesc,linkage=Linkage} = I, 177 [{'.reloc', {call,Fun,Linkage}, #comment{term='fun'}}, 178 {'.reloc', {sdesc,SDesc}, #comment{term=sdesc}}, 179 {call, {disp30,0}, I}]. 180 181do_call_tail(I) -> 182 #call_tail{'fun'=Fun,linkage=Linkage} = I, 183 [{'.reloc', {call,Fun,Linkage}, #comment{term='fun'}}, 184 {call, {disp30,0}, I}]. 185 186do_jmp(I) -> 187 #jmp{src1=Src1,src2=Src2} = I, 188 NewSrc1 = do_reg(Src1), 189 NewSrc2 = do_reg_or_imm(Src2), 190 NewDst = {r,0}, 191 [{jmpl, {NewSrc1,NewSrc2,NewDst}, I}]. 192 193do_jmpl(I) -> 194 #jmpl{src=Src,sdesc=SDesc} = I, 195 NewSrc1 = do_reg(Src), 196 NewSrc2 = {simm13,0}, 197 NewDst = {r,15}, % %o7 198 [{'.reloc', {sdesc,SDesc}, #comment{term=sdesc}}, 199 {jmpl, {NewSrc1,NewSrc2,NewDst}, I}]. 200 201do_label(I) -> 202 #label{label=Label} = I, 203 [{'.label', Label, I}]. 204 205do_pseudo_set(I, MFA, ConstMap) -> 206 #pseudo_set{imm=Imm,dst=Dst} = I, 207 RelocData = 208 case Imm of 209 Atom when is_atom(Atom) -> 210 {load_atom, Atom}; 211%%% {mfa,MFAorPrim,Linkage} -> 212%%% Tag = 213%%% case Linkage of 214%%% remote -> remote_function; 215%%% not_remote -> local_function 216%%% end, 217%%% {load_address, {Tag,untag_mfa_or_prim(MFAorPrim)}}; 218 {Label,constant} -> 219 ConstNo = hipe_pack_constants:find_const({MFA,Label}, ConstMap), 220 {load_address, {constant,ConstNo}}; 221 {Label,closure} -> 222 {load_address, {closure,Label}}; 223 {Label,c_const} -> 224 {load_address, {c_const,Label}} 225 end, 226 NewDst = do_reg(Dst), 227 [{'.reloc', RelocData, #comment{term=reloc}}, 228 {sethi, {{uimm22,0},NewDst}, I}, 229 {'or', {NewDst,{simm13,0},NewDst}, I}]. 230 231do_rdy(I) -> 232 #rdy{dst=Dst} = I, 233 NewDst = do_reg(Dst), 234 [{rd, {y,NewDst}, I}]. 235 236do_sethi(I) -> 237 #sethi{uimm22=#sparc_uimm22{value=UImm22},dst=Dst} = I, 238 NewUImm22 = {uimm22,UImm22}, 239 NewDst = do_reg(Dst), 240 [{sethi, {NewUImm22,NewDst}, I}]. 241 242do_store(I) -> 243 #store{stop=StOp,src=Src,base=Base,disp=Disp} = I, 244 NewSrc = do_reg(Src), 245 NewBase = do_reg(Base), 246 NewDisp = do_reg_or_imm(Disp), 247 [{StOp, {NewSrc,NewBase,NewDisp}, I}]. 248 249do_fp_binary(I) -> 250 #fp_binary{fp_binop=FpBinOp,src1=Src1,src2=Src2,dst=Dst} = I, 251 NewSrc1 = do_fpreg(Src1), 252 NewSrc2 = do_fpreg(Src2), 253 NewDst = do_fpreg(Dst), 254 [{FpBinOp, {NewSrc1,NewSrc2,NewDst}, I}]. 255 256do_fp_unary(I) -> 257 #fp_unary{fp_unop=FpUnOp,src=Src,dst=Dst} = I, 258 NewSrc = do_fpreg(Src), 259 NewDst = do_fpreg(Dst), 260 [{FpUnOp, {NewSrc,NewDst}, I}]. 261 262do_pseudo_fload(I) -> 263 #pseudo_fload{base=Base,disp=Disp,dst=Dst,is_single=IsSingle} = I, 264 NewBase = do_reg(Base), 265 #sparc_simm13{value=RawDisp} = Disp, 266 {fr,RawDst} = FrRawDst = do_fpreg(Dst), 267 case IsSingle of 268 true -> 269 [{'ldf', {NewBase,{simm13,RawDisp},FrRawDst}, I}]; 270 _ -> 271 [{'ldf', {NewBase,{simm13,RawDisp},FrRawDst}, I}, 272 {'ldf', {NewBase,{simm13,RawDisp+4},{fr,RawDst+1}}, I}] 273 end. 274 275do_pseudo_fstore(I) -> 276 #pseudo_fstore{src=Src,base=Base,disp=Disp} = I, 277 {fr,RawSrc} = FrRawSrc = do_fpreg(Src), 278 NewBase = do_reg(Base), 279 #sparc_simm13{value=RawDisp} = Disp, 280 [{'stf', {FrRawSrc,NewBase,{simm13,RawDisp}}, I}, 281 {'stf', {{fr,RawSrc+1},NewBase,{simm13,RawDisp+4}}, I}]. 282 283%% map a virtual double-precision fp reg in [0,15] to its 284%% corresponding single-precision fp reg in [0,2,4,...,28,30] 285do_fpreg(#sparc_temp{reg=Reg,type='double'}) 286 when is_integer(Reg), 0 =< Reg, Reg < 16 -> 287 {fr,2*Reg}. 288 289do_reg(#sparc_temp{reg=Reg,type=Type}) 290 when is_integer(Reg), 0 =< Reg, Reg < 32, Type =/= 'double' -> 291 {r,Reg}. 292 293do_reg_or_imm(Src) -> 294 case Src of 295 #sparc_temp{} -> 296 do_reg(Src); 297 #sparc_simm13{value=Value} when is_integer(Value), -4096 =< Value, Value =< 4095 -> 298 {simm13, Value band 16#1fff}; 299 #sparc_uimm5{value=Value} when is_integer(Value), 0 =< Value, Value =< 31 -> 300 {uimm5, Value}; 301 #sparc_uimm6{value=Value} when is_integer(Value), 0 =< Value, Value =< 63 -> 302 {uimm6, Value} 303 end. 304 305%%% 306%%% Assembly Pass 3. 307%%% Process final {MFA,Code,CodeSize,LabelMap} list from pass 2. 308%%% Translate to a single binary code segment. 309%%% Collect relocation patches. 310%%% Build ExportMap (MFA-to-address mapping). 311%%% Combine LabelMaps to a single one (for mk_data_relocs/2 compatibility). 312%%% Return {CombinedCodeSize,BinaryCode,Relocs,CombinedLabelMap,ExportMap}. 313%%% 314 315encode(Code, Options) -> 316 CodeSize = compute_code_size(Code, 0), 317 ExportMap = build_export_map(Code, 0, []), 318 {AccCode,Relocs} = encode_mfas(Code, 0, [], [], Options), 319 CodeBinary = list_to_binary(lists:reverse(AccCode)), 320 ?ASSERT(CodeSize =:= byte_size(CodeBinary)), 321 CombinedLabelMap = combine_label_maps(Code, 0, gb_trees:empty()), 322 {CodeSize,CodeBinary,Relocs,CombinedLabelMap,ExportMap}. 323 324compute_code_size([{_MFA,_Insns,CodeSize,_LabelMap}|Code], Size) -> 325 compute_code_size(Code, Size+CodeSize); 326compute_code_size([], Size) -> Size. 327 328build_export_map([{{M,F,A},_Insns,CodeSize,_LabelMap}|Code], Address, ExportMap) -> 329 build_export_map(Code, Address+CodeSize, [{Address,M,F,A}|ExportMap]); 330build_export_map([], _Address, ExportMap) -> ExportMap. 331 332combine_label_maps([{MFA,_Insns,CodeSize,LabelMap}|Code], Address, CLM) -> 333 NewCLM = merge_label_map(gb_trees:to_list(LabelMap), MFA, Address, CLM), 334 combine_label_maps(Code, Address+CodeSize, NewCLM); 335combine_label_maps([], _Address, CLM) -> CLM. 336 337merge_label_map([{Label,Offset}|Rest], MFA, Address, CLM) -> 338 NewCLM = gb_trees:insert({MFA,Label}, Address+Offset, CLM), 339 merge_label_map(Rest, MFA, Address, NewCLM); 340merge_label_map([], _MFA, _Address, CLM) -> CLM. 341 342encode_mfas([{MFA,Insns,CodeSize,LabelMap}|Code], Address, AccCode, Relocs, Options) -> 343 print("Generating code for: ~w\n", [MFA], Options), 344 print("Offset | Opcode | Instruction\n", [], Options), 345 {Address1,Relocs1,AccCode1} = 346 encode_insns(Insns, Address, Address, LabelMap, Relocs, AccCode, Options), 347 ExpectedAddress = Address + CodeSize, 348 ?ASSERT(Address1 =:= ExpectedAddress), 349 print("Finished.\n", [], Options), 350 encode_mfas(Code, Address1, AccCode1, Relocs1, Options); 351encode_mfas([], _Address, AccCode, Relocs, _Options) -> 352 {AccCode,Relocs}. 353 354encode_insns([I|Insns], Address, FunAddress, LabelMap, Relocs, AccCode, Options) -> 355 case I of 356 {'.label',L,_} -> 357 LabelAddress = gb_trees:get(L, LabelMap) + FunAddress, 358 ?ASSERT(Address =:= LabelAddress), % sanity check 359 print_insn(Address, [], I, Options), 360 encode_insns(Insns, Address, FunAddress, LabelMap, Relocs, AccCode, Options); 361 {'.reloc',Data,_} -> 362 Reloc = encode_reloc(Data, Address, FunAddress, LabelMap), 363 encode_insns(Insns, Address, FunAddress, LabelMap, [Reloc|Relocs], AccCode, Options); 364 {bp_sdi,_,_} -> 365 encode_insns(fix_bp_sdi(I, Insns, Address, FunAddress, LabelMap), 366 Address, FunAddress, LabelMap, Relocs, AccCode, Options); 367 %% {br_sdi,_,_} -> 368 %% encode_insns(fix_br_sdi(I, Insns, Address, FunAddress, LabelMap), 369 %% Address, FunAddress, LabelMap, Relocs, AccCode, Options); 370 _ -> 371 {Op,Arg,_} = fix_jumps(I, Address, FunAddress, LabelMap), 372 Word = hipe_sparc_encode:insn_encode(Op, Arg), 373 print_insn(Address, Word, I, Options), 374 Segment = <<Word:32/integer-big>>, 375 NewAccCode = [Segment|AccCode], 376 encode_insns(Insns, Address+4, FunAddress, LabelMap, Relocs, NewAccCode, Options) 377 end; 378encode_insns([], Address, _FunAddress, _LabelMap, Relocs, AccCode, _Options) -> 379 {Address,Relocs,AccCode}. 380 381encode_reloc(Data, Address, FunAddress, LabelMap) -> 382 case Data of 383 {call,MFAorPrim,Linkage} -> 384 %% call_rec and call_tail are patched the same, so no need to distinguish 385 %% call from tailcall 386 PatchTypeExt = 387 case Linkage of 388 remote -> ?CALL_REMOTE; 389 not_remote -> ?CALL_LOCAL 390 end, 391 {PatchTypeExt, Address, untag_mfa_or_prim(MFAorPrim)}; 392 {load_atom,Atom} -> 393 {?LOAD_ATOM, Address, Atom}; 394 {load_address,X} -> 395 {?LOAD_ADDRESS, Address, X}; 396 {sdesc,SDesc} -> 397 #sparc_sdesc{exnlab=ExnLab,fsize=FSize,arity=Arity,live=Live} = SDesc, 398 ExnRA = 399 case ExnLab of 400 [] -> []; % don't cons up a new one 401 ExnLab -> gb_trees:get(ExnLab, LabelMap) + FunAddress 402 end, 403 {?SDESC, Address, 404 ?STACK_DESC(ExnRA, FSize, Arity, Live)} 405 end. 406 407untag_mfa_or_prim(#sparc_mfa{m=M,f=F,a=A}) -> {M,F,A}; 408untag_mfa_or_prim(#sparc_prim{prim=Prim}) -> Prim. 409 410fix_bp_sdi(I, Insns, InsnAddress, FunAddress, LabelMap) -> 411 {bp_sdi,Opnds,OrigI} = I, 412 {{'cond',Cond},{pred,Pred},Label} = Opnds, 413 {label,L} = Label, 414 LabelAddress = gb_trees:get(L, LabelMap) + FunAddress, 415 BD = (LabelAddress - InsnAddress) div 4, 416 if BD >= -16#40000, BD =< 16#3FFFF -> 417 [{bp, Opnds, OrigI} | Insns]; 418 true -> 419 %% bp<cond>,<pred> L; Delay 420 %% --> 421 %% bp<!cond>,<!pred> 1f; Delay; ba L; nop; 1: 422 [Delay|Rest] = Insns, 423 NewCond = hipe_sparc:negate_cond(Cond), 424 NewPred = 1.0 - Pred, 425 [{bp, 426 {{'cond',NewCond},{pred,NewPred},'.+16'}, 427 #bp{'cond'=NewCond,pred=NewPred,label='.+16'}}, % pp will be ugly 428 Delay, % should be a NOP 429 {ba, Label, #bp{'cond'='a',pred=1.0,label=L}}, 430 {sethi, {{uimm22,0},{r,0}}, #comment{term=nop}} | 431 Rest] 432 end. 433 434-ifdef(notdef). % XXX: only for sparc64, alas 435fix_br_sdi(I, Insns, InsnAddress, FunAddress, LabelMap) -> 436 {br_sdi,Opnds,OrigI} = I, 437 {{rcond,RCond},{pred,Pred},Src,{label,L}} = Opnds, 438 LabelAddress = gb_trees:get(L, LabelMap) + FunAddress, 439 BD = (LabelAddress - InsnAddress) div 4, 440 if BD >= -16#8000, BD =< 16#7FFF -> 441 [{br, Opnds, OrigI} | Insns]; 442 true -> 443 %% br<rcond>,<pred> reg, L; Delay 444 %% --> 445 %% br<!rcond>,<!pred> reg, 1f; Delay; ba L; nop; 1: 446 [Delay|Rest] = Insns, 447 {reg,SrcReg} = Src, 448 NewRCond = hipe_sparc:negate_rcond(RCond), 449 NewPred = 1.0 - Pred, 450 [{br, 451 {{rcond,NewRCond},{pred,NewPred},Src,'.+16'}, 452 #br{rcond=NewRCond,pred=NewPred,src=SrcReg,label='.+16'}}, % pp will be ugly 453 Delay, % should be a NOP 454 {ba, {label,L}, #bp{'cond'='a',pred=1.0,label=L}}, 455 {sethi, {{uimm22,0},{r,0}}, #comment{term=nop}} | 456 Rest] 457 end. 458-endif. 459 460fix_jumps(I, InsnAddress, FunAddress, LabelMap) -> 461 case I of 462 {ba, {label,L}, OrigI} -> 463 LabelAddress = gb_trees:get(L, LabelMap) + FunAddress, 464 BD = (LabelAddress - InsnAddress) div 4, 465 %% ensure BD fits in a 22 bit sign-extended field 466 ?ASSERT(BD =< 16#1FFFFF), 467 ?ASSERT(BD >= -16#200000), 468 {ba, {disp22,BD band 16#3FFFFF}, OrigI}; 469 {bp, {Cond,Pred,Target}, OrigI} -> 470 LabelAddress = 471 case Target of 472 {label,L} -> gb_trees:get(L, LabelMap) + FunAddress; 473 '.+16' -> InsnAddress + 16 474 end, 475 BD = (LabelAddress - InsnAddress) div 4, 476 %% ensure BD fits in a 19 bit sign-extended field 477 ?ASSERT(BD =< 16#3FFFF), 478 ?ASSERT(BD >= -16#40000), 479 {bp, {Cond,px(Pred),{disp19,BD band 16#7FFFF}}, OrigI}; 480 %% {br, _, _} -> fix_br(I, InsnAddress, FunAddress, LabelMap); 481 _ -> I 482 end. 483 484-ifdef(notdef). % XXX: only for sparc64, alas 485fix_br(I, InsnAddress, FunAddress, LabelMap) -> 486 {br, {RCond,Pred,Src,Target}, OrigI} = I, 487 LabelAddress = 488 case Target of 489 {label,L} -> gb_trees:get(L, LabelMap) + FunAddress; 490 '.+16' -> InsnAddress + 16 491 end, 492 BD = (LabelAddress - InsnAddress) div 4, 493 %% ensure BD fits in a 16 bit sign-extended field 494 ?ASSERT(BD =< 16#7FFF), 495 ?ASSERT(BD >= -16#8000), 496 {br, {RCond,px(Pred),Src,{disp16,BD band 16#FFFF}}, OrigI}. 497-endif. 498 499px({pred,Pred}) -> % XXX: use pt/pn throughout entire backend 500 {pred, if Pred >= 0.5 -> 'pt'; true -> 'pn' end}. 501 502%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 503 504%%% 505%%% Assembly listing support (pp_asm option). 506%%% 507 508print(String, Arglist, Options) -> 509 ?when_option(pp_asm, Options, io:format(String, Arglist)). 510 511print_insn(Address, Word, I, Options) -> 512 ?when_option(pp_asm, Options, print_insn_2(Address, Word, I)). 513 514print_insn_2(Address, Word, {_,_,OrigI}) -> 515 io:format("~8.16.0b | ", [Address]), 516 print_code_list(word_to_bytes(Word), 0), 517 hipe_sparc_pp:pp_insn(OrigI). 518 519word_to_bytes(W) -> 520 case W of 521 [] -> []; % label or other pseudo instruction 522 _ -> [(W bsr 24) band 16#FF, (W bsr 16) band 16#FF, 523 (W bsr 8) band 16#FF, W band 16#FF] 524 end. 525 526print_code_list([Byte|Rest], Len) -> 527 print_byte(Byte), 528 print_code_list(Rest, Len+1); 529print_code_list([], Len) -> 530 fill_spaces(8-(Len*2)), 531 io:format(" | "). 532 533print_byte(Byte) -> 534 io:format("~2.16.0b", [Byte band 16#FF]). 535 536fill_spaces(N) when N > 0 -> 537 io:format(" "), 538 fill_spaces(N-1); 539fill_spaces(0) -> 540 []. 541