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_finalise). 16-export([finalise/1]). 17-include("hipe_sparc.hrl"). 18 19finalise(Defun) -> 20 #defun{code=Code0} = Defun, 21 Code1 = peep(expand(Code0)), 22 Defun#defun{code=Code1}. 23 24expand(Insns) -> 25 expand_list(Insns, []). 26 27expand_list([I|Insns], Accum) -> 28 expand_list(Insns, expand_insn(I, Accum)); 29expand_list([], Accum) -> 30 lists:reverse(Accum). 31 32expand_insn(I, Accum) -> 33 case I of 34 #bp{'cond'='a'} -> 35 [hipe_sparc:mk_nop(), 36 I | 37 Accum]; 38 #call_rec{} -> 39 [hipe_sparc:mk_nop(), 40 I | 41 Accum]; 42 #call_tail{} -> 43 RA = hipe_sparc:mk_ra(), 44 TempRA = hipe_sparc:mk_temp1(), 45 [hipe_sparc:mk_mov(TempRA, RA), 46 I, % becomes a call, which clobbers RA 47 hipe_sparc:mk_mov(RA, TempRA) | 48 Accum]; 49 #jmp{} -> 50 [hipe_sparc:mk_nop(), 51 I | 52 Accum]; 53 #pseudo_bp{'cond'=Cond,true_label=TrueLab,false_label=FalseLab, pred=Pred} -> 54 [hipe_sparc:mk_nop(), 55 hipe_sparc:mk_b_label(FalseLab), 56 hipe_sparc:mk_nop(), 57 hipe_sparc:mk_bp(Cond, TrueLab, Pred) | 58 Accum]; 59 %% #pseudo_br{} -> expand_pseudo_br(I, Accum); 60 #pseudo_call{funv=FunV,sdesc=SDesc,contlab=ContLab,linkage=Linkage} -> 61 [hipe_sparc:mk_nop(), 62 hipe_sparc:mk_b_label(ContLab), 63 hipe_sparc:mk_nop(), 64 case FunV of 65 #sparc_temp{} -> 66 hipe_sparc:mk_jmpl(FunV, SDesc); 67 _ -> 68 hipe_sparc:mk_call_rec(FunV, SDesc, Linkage) 69 end | 70 Accum]; 71 #pseudo_ret{} -> 72 RA = hipe_sparc:mk_ra(), 73 [hipe_sparc:mk_nop(), 74 hipe_sparc:mk_jmp(RA, hipe_sparc:mk_simm13(8), []) | 75 Accum]; 76 #pseudo_tailcall_prepare{} -> 77 Accum; 78 _ -> 79 XXX = 80 case I of 81 #alu{} -> true; 82 #comment{} -> true; 83 #label{} -> true; 84 #pseudo_set{} -> true; 85 #rdy{} -> true; 86 #sethi{} -> true; 87 #store{} -> true; 88 #bp{} -> false; 89 %% #br{} -> false; 90 #call_rec{} -> false; 91 #call_tail{} -> false; 92 #jmp{} -> false; 93 #jmpl{} -> false; 94 #pseudo_bp{} -> false; 95 %% #pseudo_br{} -> false; 96 #pseudo_call{} -> false; 97 #pseudo_call_prepare{} -> false; 98 #pseudo_move{} -> false; 99 #pseudo_ret{} -> false; 100 #pseudo_tailcall{} -> false; 101 #pseudo_tailcall_prepare{} -> false; 102 #fp_binary{} -> true; 103 #fp_unary{} -> true; 104 #pseudo_fload{} -> true; 105 #pseudo_fstore{} -> true 106 end, 107 case XXX of 108 true -> []; 109 false -> exit({?MODULE,expand_insn,I}) 110 end, 111 [I|Accum] 112 end. 113 114-ifdef(notdef). % XXX: only for sparc64, alas 115expand_pseudo_br(I, Accum) -> 116 #pseudo_br{rcond=RCond,src=Src,true_label=TrueLab,false_label=FalseLab, pred=Pred} = I, 117 [hipe_sparc:mk_nop(), 118 hipe_sparc:mk_b_label(FalseLab), 119 hipe_sparc:mk_nop(), 120 hipe_sparc:mk_br(RCond, Src, TrueLab, Pred) | 121 Accum]. 122-endif. 123 124peep(Insns) -> 125 peep_list(Insns, []). 126 127peep_list([#bp{'cond'='a',label=Label}, #sethi{uimm22=#sparc_uimm22{value=0},dst=#sparc_temp{reg=0}} | (Insns = [#label{label=Label}|_])], Accum) -> 128 peep_list(Insns, Accum); 129peep_list([I|Insns], Accum) -> 130 peep_list(Insns, [I|Accum]); 131peep_list([], Accum) -> 132 lists:reverse(Accum). 133