aboutsummaryrefslogtreecommitdiffstats
path: root/lib/hipe/ppc
diff options
context:
space:
mode:
authorHenrik Nord <[email protected]>2011-04-05 16:27:36 +0200
committerHenrik Nord <[email protected]>2011-04-05 16:28:18 +0200
commit79698f6f214283e34f8e0893c90716f503a723f2 (patch)
tree495077fa13b9445e590ff1042cac53414f6d92c6 /lib/hipe/ppc
parent645d19ca2e96ec53b4b4834b312cfa869084d107 (diff)
parent577a6282d6b090c0727038df0bc163b3baa02534 (diff)
downloadotp-79698f6f214283e34f8e0893c90716f503a723f2.tar.gz
otp-79698f6f214283e34f8e0893c90716f503a723f2.tar.bz2
otp-79698f6f214283e34f8e0893c90716f503a723f2.zip
Merge branch 'ks/hipe-ppc64' into dev
* ks/hipe-ppc64: Enable HiPE by default when compiling for PPC64 Translate RTL to PPC code on PPC64 too Changes in ppc files for PPC64 Additions for the PPC64 backend Changes for the PPC64 backend Added loader for ppc64 New files for the 64-bit backends Cleanup tags OTP-9198
Diffstat (limited to 'lib/hipe/ppc')
-rw-r--r--lib/hipe/ppc/hipe_ppc.erl172
-rw-r--r--lib/hipe/ppc/hipe_ppc_assemble.erl76
-rw-r--r--lib/hipe/ppc/hipe_ppc_frame.erl30
-rw-r--r--lib/hipe/ppc/hipe_rtl_to_ppc.erl260
4 files changed, 375 insertions, 163 deletions
diff --git a/lib/hipe/ppc/hipe_ppc.erl b/lib/hipe/ppc/hipe_ppc.erl
index 047e86c45b..4014fc1561 100644
--- a/lib/hipe/ppc/hipe_ppc.erl
+++ b/lib/hipe/ppc/hipe_ppc.erl
@@ -1,20 +1,20 @@
%% -*- erlang-indent-level: 2 -*-
%%
%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2004-2009. All Rights Reserved.
-%%
+%%
+%% Copyright Ericsson AB 2004-2011. All Rights Reserved.
+%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
%% compliance with the License. You should have received a copy of the
%% Erlang Public License along with this software. If not, it can be
%% retrieved online at http://www.erlang.org/.
-%%
+%%
%% Software distributed under the License is distributed on an "AS IS"
%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
%% the License for the specific language governing rights and limitations
%% under the License.
-%%
+%%
%% %CopyrightEnd%
%%
@@ -58,6 +58,10 @@
mk_blr/0,
mk_cmp/3,
+ cmpop_word/0,
+ cmpiop_word/0,
+ cmplop_word/0,
+ cmpliop_word/0,
mk_comment/1,
@@ -73,6 +77,8 @@
mk_loadx/4,
mk_load/6,
ldop_to_ldxop/1,
+ ldop_word/0,
+ ldop_wordx/0,
mk_mfspr/2,
@@ -110,6 +116,8 @@
mk_storex/4,
mk_store/6,
stop_to_stxop/1,
+ stop_word/0,
+ stop_wordx/0,
mk_unary/3,
@@ -189,6 +197,31 @@ mk_blr() -> #blr{}.
mk_cmp(CmpOp, Src1, Src2) -> #cmp{cmpop=CmpOp, src1=Src1, src2=Src2}.
+cmpop_word() ->
+ case get(hipe_target_arch) of
+ powerpc -> 'cmp';
+ ppc64 -> 'cmpd'
+ end.
+
+cmpiop_word() ->
+ case get(hipe_target_arch) of
+ powerpc -> 'cmpi';
+ ppc64 -> 'cmpdi'
+ end.
+
+cmplop_word() ->
+ case get(hipe_target_arch) of
+ powerpc -> 'cmpl';
+ ppc64 -> 'cmpld'
+ end.
+
+cmpliop_word() ->
+ case get(hipe_target_arch) of
+ powerpc -> 'cmpli';
+ ppc64 -> 'cmpldi'
+ end.
+
+
mk_comment(Term) -> #comment{term=Term}.
mk_label(Label) -> #label{label=Label}.
@@ -198,9 +231,50 @@ label_label(#label{label=Label}) -> Label.
%%% Load an integer constant into a register.
mk_li(Dst, Value) -> mk_li(Dst, Value, []).
-mk_li(Dst, Value, Tail) ->
+mk_li(Dst, Value, Tail) -> % Dst can be R0
R0 = mk_temp(0, 'untagged'),
- mk_addi(Dst, R0, Value, Tail).
+ %% Check if immediate can fit in the 32 bits, this is obviously a
+ %% sufficient check for PPC32
+ if Value >= -16#80000000,
+ Value =< 16#7FFFFFFF ->
+ mk_li32(Dst, R0, Value, Tail);
+ true ->
+ Highest = (Value bsr 48), % Value@highest
+ Higher = (Value bsr 32) band 16#FFFF, % Value@higher
+ High = (Value bsr 16) band 16#FFFF, % Value@h
+ Low = Value band 16#FFFF, % Value@l
+ LdLo =
+ case Low of
+ 0 -> Tail;
+ _ -> [mk_alu('ori', Dst, Dst, mk_uimm16(Low)) | Tail]
+ end,
+ Ld32bits =
+ case High of
+ 0 -> LdLo;
+ _ -> [mk_alu('oris', Dst, Dst, mk_uimm16(High)) | LdLo]
+ end,
+ [mk_alu('addis', Dst, R0, mk_simm16(Highest)),
+ mk_alu('ori', Dst, Dst, mk_uimm16(Higher)),
+ mk_alu('sldi', Dst, Dst, mk_uimm16(32)) |
+ Ld32bits]
+ end.
+
+mk_li32(Dst, R0, Value, Tail) ->
+ case at_ha(Value) of
+ 0 ->
+ %% Value[31:16] are the sign-extension of Value[15].
+ %% Use a single addi to load and sign-extend 16 bits.
+ [mk_alu('addi', Dst, R0, mk_simm16(at_l(Value))) | Tail];
+ _ ->
+ %% Use addis to load the high 16 bits, followed by an
+ %% optional ori to load non sign-extended low 16 bits.
+ High = simm16sext((Value bsr 16) band 16#FFFF),
+ [mk_alu('addis', Dst, R0, mk_simm16(High)) |
+ case (Value band 16#FFFF) of
+ 0 -> Tail;
+ Low -> [mk_alu('ori', Dst, Dst, mk_uimm16(Low)) | Tail]
+ end]
+ end.
mk_addi(Dst, R0, Value, Tail) ->
Low = at_l(Value),
@@ -232,27 +306,6 @@ simm16sext(Value) ->
true -> Value
end.
-mk_li_new(Dst, Value, Tail) -> % Dst may be R0
- R0 = mk_temp(0, 'untagged'),
- case at_ha(Value) of
- 0 ->
- %% Value[31:16] are the sign-extension of Value[15].
- %% Use a single addi to load and sign-extend 16 bits.
- [mk_alu('addi', Dst, R0, mk_simm16(at_l(Value))) |
- Tail];
- _ ->
- %% Use addis to load the high 16 bits, followed by an
- %% optional ori to load non sign-extended low 16 bits.
- High = simm16sext((Value bsr 16) band 16#FFFF),
- [mk_alu('addis', Dst, R0, mk_simm16(High)) |
- case (Value band 16#FFFF) of
- 0 -> Tail;
- Low ->
- [mk_alu('ori', Dst, Dst, mk_uimm16(Low)) |
- Tail]
- end]
- end.
-
mk_load(LDop, Dst, Disp, Base) ->
#load{ldop=LDop, dst=Dst, disp=Disp, base=Base}.
@@ -260,8 +313,15 @@ mk_loadx(LdxOp, Dst, Base1, Base2) ->
#loadx{ldxop=LdxOp, dst=Dst, base1=Base1, base2=Base2}.
mk_load(LdOp, Dst, Offset, Base, Scratch, Rest) when is_integer(Offset) ->
- if Offset >= -32768, Offset =< 32767 ->
- [mk_load(LdOp, Dst, Offset, Base) | Rest];
+ RequireAlignment =
+ case LdOp of
+ 'ld' -> true;
+ 'ldx' -> true;
+ _ -> false
+ end,
+ if Offset >= -32768, Offset =< 32767,
+ not RequireAlignment orelse Offset band 3 =:= 0 ->
+ [mk_load(LdOp, Dst, Offset, Base) | Rest];
true ->
LdxOp = ldop_to_ldxop(LdOp),
Index =
@@ -272,8 +332,8 @@ mk_load(LdOp, Dst, Offset, Base, Scratch, Rest) when is_integer(Offset) ->
true -> mk_scratch(Scratch)
end
end,
- mk_li_new(Index, Offset,
- [mk_loadx(LdxOp, Dst, Base, Index) | Rest])
+ mk_li(Index, Offset,
+ [mk_loadx(LdxOp, Dst, Base, Index) | Rest])
end.
ldop_to_ldxop(LdOp) ->
@@ -281,7 +341,21 @@ ldop_to_ldxop(LdOp) ->
'lbz' -> 'lbzx';
'lha' -> 'lhax';
'lhz' -> 'lhzx';
- 'lwz' -> 'lwzx'
+ 'lwa' -> 'lwax';
+ 'lwz' -> 'lwzx';
+ 'ld' -> 'ldx'
+ end.
+
+ldop_word() ->
+ case get(hipe_target_arch) of
+ powerpc -> 'lwz';
+ ppc64 -> 'ld'
+ end.
+
+ldop_wordx() ->
+ case get(hipe_target_arch) of
+ powerpc -> 'lwzx';
+ ppc64 -> 'ldx'
end.
mk_scratch(Scratch) ->
@@ -354,20 +428,40 @@ mk_storex(StxOp, Src, Base1, Base2) ->
#storex{stxop=StxOp, src=Src, base1=Base1, base2=Base2}.
mk_store(StOp, Src, Offset, Base, Scratch, Rest)when is_integer(Offset) ->
- if Offset >= -32768, Offset =< 32767 ->
+ RequireAlignment =
+ case StOp of
+ 'std' -> true;
+ 'stdx' -> true;
+ _ -> false
+ end,
+ if Offset >= -32768, Offset =< 32767,
+ not RequireAlignment orelse Offset band 3 =:= 0 ->
[mk_store(StOp, Src, Offset, Base) | Rest];
true ->
StxOp = stop_to_stxop(StOp),
Index = mk_scratch(Scratch),
- mk_li_new(Index, Offset,
- [mk_storex(StxOp, Src, Base, Index) | Rest])
+ mk_li(Index, Offset,
+ [mk_storex(StxOp, Src, Base, Index) | Rest])
end.
stop_to_stxop(StOp) ->
case StOp of
'stb' -> 'stbx';
'sth' -> 'sthx';
- 'stw' -> 'stwx'
+ 'stw' -> 'stwx';
+ 'std' -> 'stdx'
+ end.
+
+stop_word() ->
+ case get(hipe_target_arch) of
+ powerpc -> 'stw';
+ ppc64 -> 'std'
+ end.
+
+stop_wordx() ->
+ case get(hipe_target_arch) of
+ powerpc -> 'stwx';
+ ppc64 -> 'stdx'
end.
mk_unary(UnOp, Dst, Src) -> #unary{unop=UnOp, dst=Dst, src=Src}.
@@ -379,7 +473,7 @@ mk_fload(Dst, Offset, Base, Scratch) when is_integer(Offset) ->
[mk_lfd(Dst, Offset, Base)];
true ->
Index = mk_scratch(Scratch),
- mk_li_new(Index, Offset, [mk_lfdx(Dst, Base, Index)])
+ mk_li(Index, Offset, [mk_lfdx(Dst, Base, Index)])
end.
mk_stfd(Src, Disp, Base) -> #stfd{src=Src, disp=Disp, base=Base}.
@@ -389,7 +483,7 @@ mk_fstore(Src, Offset, Base, Scratch) when is_integer(Offset) ->
[mk_stfd(Src, Offset, Base)];
true ->
Index = mk_scratch(Scratch),
- mk_li_new(Index, Offset, [mk_stfdx(Src, Base, Index)])
+ mk_li(Index, Offset, [mk_stfdx(Src, Base, Index)])
end.
mk_fp_binary(FpBinOp, Dst, Src1, Src2) ->
diff --git a/lib/hipe/ppc/hipe_ppc_assemble.erl b/lib/hipe/ppc/hipe_ppc_assemble.erl
index 6f06f8b841..b2fd50517b 100644
--- a/lib/hipe/ppc/hipe_ppc_assemble.erl
+++ b/lib/hipe/ppc/hipe_ppc_assemble.erl
@@ -1,20 +1,20 @@
%% -*- erlang-indent-level: 2 -*-
%%
%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2004-2009. All Rights Reserved.
-%%
+%%
+%% Copyright Ericsson AB 2004-2011. All Rights Reserved.
+%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
%% compliance with the License. You should have received a copy of the
%% Erlang Public License along with this software. If not, it can be
%% retrieved online at http://www.erlang.org/.
-%%
+%%
%% Software distributed under the License is distributed on an "AS IS"
%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
%% the License for the specific language governing rights and limitations
%% under the License.
-%%
+%%
%% %CopyrightEnd%
%%
@@ -39,7 +39,7 @@ assemble(CompiledCode, Closures, Exports, Options) ->
|| {MFA, Defun} <- CompiledCode],
%%
{ConstAlign,ConstSize,ConstMap,RefsFromConsts} =
- hipe_pack_constants:pack_constants(Code, 4),
+ hipe_pack_constants:pack_constants(Code, hipe_rtl_arch:word_size()),
%%
{CodeSize,CodeBinary,AccRefs,LabelMap,ExportMap} =
encode(translate(Code, ConstMap), Options),
@@ -159,6 +159,13 @@ do_alu(I) ->
'srwi.' -> {'rlwinm.', do_srwi_opnds(NewDst, NewSrc1, NewSrc2)};
'srawi' -> {'srawi', {NewDst,NewSrc1,do_srawi_src2(NewSrc2)}};
'srawi.' -> {'srawi.', {NewDst,NewSrc1,do_srawi_src2(NewSrc2)}};
+ %ppc64 extension
+ 'sldi' -> {'rldicr', do_sldi_opnds(NewDst, NewSrc1, NewSrc2)};
+ 'sldi.' -> {'rldicr.', do_sldi_opnds(NewDst, NewSrc1, NewSrc2)};
+ 'srdi' -> {'rldicl', do_srdi_opnds(NewDst, NewSrc1, NewSrc2)};
+ 'srdi.' -> {'rldicl.', do_srdi_opnds(NewDst, NewSrc1, NewSrc2)};
+ 'sradi' -> {'sradi', {NewDst,NewSrc1,do_sradi_src2(NewSrc2)}};
+ 'sradi.' -> {'sradi.', {NewDst,NewSrc1,do_sradi_src2(NewSrc2)}};
_ -> {AluOp, {NewDst,NewSrc1,NewSrc2}}
end,
[{NewI, NewOpnds, I}].
@@ -171,6 +178,15 @@ do_srwi_opnds(Dst, Src1, {uimm,N}) when is_integer(N), 0 =< N, N < 32 ->
do_srawi_src2({uimm,N}) when is_integer(N), 0 =< N, N < 32 -> {sh,N}.
+%% ppc64 extension
+do_sldi_opnds(Dst, Src1, {uimm,N}) when is_integer(N), 0 =< N, N < 64 ->
+ {Dst, Src1, {sh6,N}, {me6,63-N}}.
+
+do_srdi_opnds(Dst, Src1, {uimm,N}) when is_integer(N), 0 =< N, N < 64 ->
+ {Dst, Src1, {sh6,64-N}, {mb6,N}}.
+
+do_sradi_src2({uimm,N}) when is_integer(N), 0 =< N, N < 64 -> {sh6,N}.
+
do_b_fun(I) ->
#b_fun{'fun'=Fun,linkage=Linkage} = I,
[{'.reloc', {b_fun,Fun,Linkage}, #comment{term='fun'}},
@@ -205,7 +221,18 @@ do_cmp(I) ->
#cmp{cmpop=CmpOp,src1=Src1,src2=Src2} = I,
NewSrc1 = do_reg(Src1),
NewSrc2 = do_reg_or_imm(Src2),
- [{CmpOp, {{crf,0},0,NewSrc1,NewSrc2}, I}].
+ {RealOp,L} =
+ case CmpOp of
+ 'cmpd' -> {'cmp',1};
+ 'cmpdi' -> {'cmpi',1};
+ 'cmpld' -> {'cmpl',1};
+ 'cmpldi' -> {'cmpli',1};
+ 'cmp' -> {CmpOp,0};
+ 'cmpi' -> {CmpOp,0};
+ 'cmpl' -> {CmpOp,0};
+ 'cmpli' -> {CmpOp,0}
+ end,
+ [{RealOp, {{crf,0},L,NewSrc1,NewSrc2}, I}].
do_label(I) ->
#label{label=Label} = I,
@@ -214,7 +241,12 @@ do_label(I) ->
do_load(I) ->
#load{ldop=LdOp,dst=Dst,disp=Disp,base=Base} = I,
NewDst = do_reg(Dst),
- NewDisp = do_disp(Disp),
+ NewDisp =
+ case LdOp of
+ 'ld' -> do_disp_ds(Disp);
+ 'ldu' -> do_disp_ds(Disp);
+ _ -> do_disp(Disp)
+ end,
NewBase = do_reg(Base),
[{LdOp, {NewDst,NewDisp,NewBase}, I}].
@@ -265,14 +297,30 @@ do_pseudo_li(I, MFA, ConstMap) ->
end,
NewDst = do_reg(Dst),
Simm0 = {simm,0},
- [{'.reloc', RelocData, #comment{term=reloc}},
- {addi, {NewDst,{r,0},Simm0}, I},
- {addis, {NewDst,NewDst,Simm0}, I}].
+ Uimm0 = {uimm,0},
+ case get(hipe_target_arch) of
+ powerpc ->
+ [{'.reloc', RelocData, #comment{term=reloc}},
+ {addi, {NewDst,{r,0},Simm0}, I},
+ {addis, {NewDst,NewDst,Simm0}, I}];
+ ppc64 ->
+ [{'.reloc', RelocData, #comment{term=reloc}},
+ {addis, {NewDst,{r,0},Simm0}, I}, % @highest
+ {ori, {NewDst,NewDst,Uimm0}, I}, % @higher
+ {rldicr, {NewDst,NewDst,{sh6,32},{me6,31}}, I},
+ {oris, {NewDst,NewDst,Uimm0}, I}, % @h
+ {ori, {NewDst,NewDst,Uimm0}, I}] % @l
+ end.
do_store(I) ->
#store{stop=StOp,src=Src,disp=Disp,base=Base} = I,
NewSrc = do_reg(Src),
- NewDisp = do_disp(Disp),
+ NewDisp =
+ case StOp of
+ 'std' -> do_disp_ds(Disp);
+ 'stdu' -> do_disp_ds(Disp);
+ _ -> do_disp(Disp)
+ end,
NewBase = do_reg(Base),
[{StOp, {NewSrc,NewDisp,NewBase}, I}].
@@ -344,6 +392,10 @@ do_reg_or_imm(Src) ->
do_disp(Disp) when is_integer(Disp), -32768 =< Disp, Disp =< 32767 ->
{d, Disp band 16#ffff}.
+do_disp_ds(Disp) when is_integer(Disp),
+ -32768 =< Disp, Disp =< 32767, Disp band 3 =:= 0 ->
+ {ds, (Disp band 16#ffff) bsr 2}.
+
do_spr(SPR) ->
SPR_NR =
case SPR of
diff --git a/lib/hipe/ppc/hipe_ppc_frame.erl b/lib/hipe/ppc/hipe_ppc_frame.erl
index 158009872f..8a4d1906c0 100644
--- a/lib/hipe/ppc/hipe_ppc_frame.erl
+++ b/lib/hipe/ppc/hipe_ppc_frame.erl
@@ -1,20 +1,20 @@
%% -*- erlang-indent-level: 2 -*-
%%
%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2004-2009. All Rights Reserved.
-%%
+%%
+%% Copyright Ericsson AB 2004-2011. All Rights Reserved.
+%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
%% compliance with the License. You should have received a copy of the
%% Erlang Public License along with this software. If not, it can be
%% retrieved online at http://www.erlang.org/.
-%%
+%%
%% Software distributed under the License is distributed on an "AS IS"
%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
%% the License for the specific language governing rights and limitations
%% under the License.
-%%
+%%
%% %CopyrightEnd%
%%
@@ -103,12 +103,12 @@ do_pseudo_move(I, Context, FPoff) ->
case temp_is_pseudo(Dst) of
true ->
Offset = pseudo_offset(Dst, FPoff, Context),
- mk_store('stw', Src, Offset, mk_sp(), []);
+ mk_store(hipe_ppc:stop_word(), Src, Offset, mk_sp(), []);
_ ->
case temp_is_pseudo(Src) of
true ->
Offset = pseudo_offset(Src, FPoff, Context),
- mk_load('lwz', Dst, Offset, mk_sp(), []);
+ mk_load(hipe_ppc:ldop_word(), Dst, Offset, mk_sp(), []);
_ ->
[hipe_ppc:mk_alu('or', Dst, Src, Src)]
end
@@ -152,7 +152,7 @@ restore_lr(FPoff, Context, Rest) ->
false -> Rest;
true ->
Temp = mk_temp1(),
- mk_load('lwz', Temp, FPoff - word_size(), mk_sp(),
+ mk_load(hipe_ppc:ldop_word(), Temp, FPoff - word_size(), mk_sp(),
[hipe_ppc:mk_mtspr('lr', Temp) |
Rest])
end.
@@ -324,8 +324,8 @@ simple_moves([{SrcOff,DstOff,Type}|Moves], FPoff, TempReg, Rest) ->
LoadOff = FPoff+SrcOff,
StoreOff = FPoff+DstOff,
simple_moves(Moves, FPoff, TempReg,
- mk_load('lwz', Temp, LoadOff, SP,
- mk_store('stw', Temp, StoreOff, SP,
+ mk_load(hipe_ppc:ldop_word(), Temp, LoadOff, SP,
+ mk_store(hipe_ppc:stop_word(), Temp, StoreOff, SP,
Rest)));
simple_moves([], _, _, Rest) ->
Rest.
@@ -343,7 +343,8 @@ store_moves([{Src,DstOff}|Moves], FPoff, TempReg, Rest) ->
{Temp, hipe_ppc:mk_li(Temp, Src)}
end,
store_moves(Moves, FPoff, TempReg,
- FixSrc ++ mk_store('stw', NewSrc, StoreOff, SP, Rest));
+ FixSrc ++ mk_store(hipe_ppc:stop_word(), NewSrc,
+ StoreOff, SP, Rest));
store_moves([], _, _, Rest) ->
Rest.
@@ -400,7 +401,7 @@ mk_temp_map(Formals, ClobbersLR, Temps) ->
enter_vars([V|Vs], PrevOff, Map) ->
Off =
case hipe_ppc:temp_type(V) of
- 'double' -> PrevOff - 2*word_size();
+ 'double' -> PrevOff - 8;
_ -> PrevOff - word_size()
end,
enter_vars(Vs, Off, tmap_bind(Map, V, Off));
@@ -454,7 +455,8 @@ do_prologue(CFG, Context) ->
AllocFrameCodeTail =
case ClobbersLR of
false -> GotoOldStartCode;
- true -> mk_store('stw', Temp1, FrameSize-word_size(), SP, GotoOldStartCode)
+ true -> mk_store(hipe_ppc:stop_word(), Temp1,
+ FrameSize-word_size(), SP, GotoOldStartCode)
end,
%%
Arity = context_arity(Context),
@@ -484,7 +486,7 @@ do_prologue(CFG, Context) ->
true -> [hipe_ppc:mk_mfspr(Temp1, 'lr') | NewStartCodeTail2]
end,
NewStartCode0 =
- [hipe_ppc:mk_load('lwz', Temp1, ?P_NSP_LIMIT, P) |
+ [hipe_ppc:mk_load(hipe_ppc:ldop_word(), Temp1, ?P_NSP_LIMIT, P) |
hipe_ppc:mk_addi(Temp2, SP, -MaxStack,
[hipe_ppc:mk_cmp('cmpl', Temp2, Temp1) |
NewStartCodeTail1])],
diff --git a/lib/hipe/ppc/hipe_rtl_to_ppc.erl b/lib/hipe/ppc/hipe_rtl_to_ppc.erl
index 458af250de..7dfa56df29 100644
--- a/lib/hipe/ppc/hipe_rtl_to_ppc.erl
+++ b/lib/hipe/ppc/hipe_rtl_to_ppc.erl
@@ -1,20 +1,20 @@
%%% -*- erlang-indent-level: 2 -*-
%%%
%%% %CopyrightBegin%
-%%%
-%%% Copyright Ericsson AB 2004-2009. All Rights Reserved.
-%%%
+%%%
+%%% Copyright Ericsson AB 2004-2011. All Rights Reserved.
+%%%
%%% The contents of this file are subject to the Erlang Public License,
%%% Version 1.1, (the "License"); you may not use this file except in
%%% compliance with the License. You should have received a copy of the
%%% Erlang Public License along with this software. If not, it can be
%%% retrieved online at http://www.erlang.org/.
-%%%
+%%%
%%% Software distributed under the License is distributed on an "AS IS"
%%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
%%% the License for the specific language governing rights and limitations
%%% under the License.
-%%%
+%%%
%%% %CopyrightEnd%
%%%
%%% The PowerPC instruction set is quite irregular.
@@ -110,20 +110,27 @@ conv_fconv(I, Map, Data) ->
mk_fconv(Dst, Src) ->
CSP = hipe_ppc:mk_temp(1, 'untagged'),
- R0 = hipe_ppc:mk_temp(0, 'untagged'),
- RTmp1 = hipe_ppc:mk_new_temp('untagged'),
- RTmp2 = hipe_ppc:mk_new_temp('untagged'),
- RTmp3 = hipe_ppc:mk_new_temp('untagged'),
- FTmp1 = hipe_ppc:mk_new_temp('double'),
- FTmp2 = hipe_ppc:mk_new_temp('double'),
- [hipe_ppc:mk_pseudo_li(RTmp1, {fconv_constant,c_const}),
- hipe_ppc:mk_lfd(FTmp1, 0, RTmp1),
- hipe_ppc:mk_alu('xoris', RTmp2, Src, hipe_ppc:mk_uimm16(16#8000)),
- hipe_ppc:mk_store('stw', RTmp2, 28, CSP),
- hipe_ppc:mk_alu('addis', RTmp3, R0, hipe_ppc:mk_simm16(16#4330)),
- hipe_ppc:mk_store('stw', RTmp3, 24, CSP),
- hipe_ppc:mk_lfd(FTmp2, 24, CSP),
- hipe_ppc:mk_fp_binary('fsub', Dst, FTmp2, FTmp1)].
+ case get(hipe_target_arch) of
+ powerpc ->
+ R0 = hipe_ppc:mk_temp(0, 'untagged'),
+ RTmp1 = hipe_ppc:mk_new_temp('untagged'),
+ RTmp2 = hipe_ppc:mk_new_temp('untagged'),
+ RTmp3 = hipe_ppc:mk_new_temp('untagged'),
+ FTmp1 = hipe_ppc:mk_new_temp('double'),
+ FTmp2 = hipe_ppc:mk_new_temp('double'),
+ [hipe_ppc:mk_pseudo_li(RTmp1, {fconv_constant,c_const}),
+ hipe_ppc:mk_lfd(FTmp1, 0, RTmp1),
+ hipe_ppc:mk_alu('xoris', RTmp2, Src, hipe_ppc:mk_uimm16(16#8000)),
+ hipe_ppc:mk_store('stw', RTmp2, 28, CSP),
+ hipe_ppc:mk_alu('addis', RTmp3, R0, hipe_ppc:mk_simm16(16#4330)),
+ hipe_ppc:mk_store('stw', RTmp3, 24, CSP),
+ hipe_ppc:mk_lfd(FTmp2, 24, CSP),
+ hipe_ppc:mk_fp_binary('fsub', Dst, FTmp2, FTmp1)];
+ ppc64 ->
+ [hipe_ppc:mk_store('std', Src, 24, CSP),
+ hipe_ppc:mk_lfd(Dst, 24, CSP),
+ hipe_ppc:mk_fp_unary('fcfid', Dst, Dst)]
+ end.
conv_fmove(I, Map, Data) ->
%% Dst := Src, where both Dst and Src are FP regs
@@ -280,10 +287,14 @@ mk_alu_ri(Dst, Src1, RtlAluOp, Src2) ->
'mul' -> % 'mulli' has a 16-bit simm operand
mk_alu_ri_simm16(Dst, Src1, RtlAluOp, 'mulli', Src2);
'and' -> % 'andi.' has a 16-bit uimm operand
- case rlwinm_mask(Src2) of
- {MB,ME} ->
- [hipe_ppc:mk_unary({'rlwinm',0,MB,ME}, Dst, Src1)];
- _ ->
+ if Src2 band (bnot 16#ffffffff) =:= 0 ->
+ case rlwinm_mask(Src2) of
+ {MB,ME} ->
+ [hipe_ppc:mk_unary({'rlwinm',0,MB,ME}, Dst, Src1)];
+ _ ->
+ mk_alu_ri_bitop(Dst, Src1, RtlAluOp, 'andi.', Src2)
+ end;
+ true ->
mk_alu_ri_bitop(Dst, Src1, RtlAluOp, 'andi.', Src2)
end;
'or' -> % 'ori' has a 16-bit uimm operand
@@ -360,17 +371,33 @@ mk_alu_ri_bitop(Dst, Src1, RtlAluOp, AluOp, Src2) ->
end.
mk_alu_ri_shift(Dst, Src1, RtlAluOp, Src2) ->
- if Src2 < 32, Src2 >= 0 ->
- AluOp =
- case RtlAluOp of
- 'sll' -> 'slwi'; % alias for rlwinm
- 'srl' -> 'srwi'; % alias for rlwinm
- 'sra' -> 'srawi'
- end,
- [hipe_ppc:mk_alu(AluOp, Dst, Src1,
- hipe_ppc:mk_uimm16(Src2))];
- true ->
- mk_alu_ri_rr(Dst, Src1, RtlAluOp, Src2)
+ case get(hipe_target_arch) of
+ ppc64 ->
+ if Src2 < 64, Src2 >= 0 ->
+ AluOp =
+ case RtlAluOp of
+ 'sll' -> 'sldi'; % alias for rldimi %%% buggy
+ 'srl' -> 'srdi'; % alias for rldimi %%% buggy
+ 'sra' -> 'sradi' %%% buggy
+ end,
+ [hipe_ppc:mk_alu(AluOp, Dst, Src1,
+ hipe_ppc:mk_uimm16(Src2))];
+ true ->
+ mk_alu_ri_rr(Dst, Src1, RtlAluOp, Src2)
+ end;
+ powerpc ->
+ if Src2 < 32, Src2 >= 0 ->
+ AluOp =
+ case RtlAluOp of
+ 'sll' -> 'slwi'; % alias for rlwinm
+ 'srl' -> 'srwi'; % alias for rlwinm
+ 'sra' -> 'srawi'
+ end,
+ [hipe_ppc:mk_alu(AluOp, Dst, Src1,
+ hipe_ppc:mk_uimm16(Src2))];
+ true ->
+ mk_alu_ri_rr(Dst, Src1, RtlAluOp, Src2)
+ end
end.
mk_alu_ri_rr(Dst, Src1, RtlAluOp, Src2) ->
@@ -384,15 +411,21 @@ mk_alu_rr(Dst, Src1, RtlAluOp, Src2) ->
[hipe_ppc:mk_alu('subf', Dst, Src2, Src1)];
_ ->
AluOp =
- case RtlAluOp of
- 'add' -> 'add';
- 'mul' -> 'mullw';
- 'or' -> 'or';
- 'and' -> 'and';
- 'xor' -> 'xor';
- 'sll' -> 'slw';
- 'srl' -> 'srw';
- 'sra' -> 'sraw'
+ case {get(hipe_target_arch), RtlAluOp} of
+ {_, 'add'} -> 'add';
+ {_, 'or'} -> 'or';
+ {_, 'and'} -> 'and';
+ {_, 'xor'} -> 'xor';
+
+ {powerpc, 'mul'} -> 'mullw';
+ {powerpc, 'sll'} -> 'slw';
+ {powerpc, 'srl'} -> 'srw';
+ {powerpc, 'sra'} -> 'sraw';
+
+ {ppc64, 'mul'} -> 'mulld';
+ {ppc64, 'sll'} -> 'sld';
+ {ppc64, 'srl'} -> 'srd';
+ {ppc64, 'sra'} -> 'srad'
end,
[hipe_ppc:mk_alu(AluOp, Dst, Src1, Src2)]
end.
@@ -431,16 +464,22 @@ conv_alub(I, Map, Data) ->
{I1 ++ I2, Map2, Data}.
conv_alub_op(RtlAluOp) ->
- case RtlAluOp of
- 'add' -> 'add';
- 'sub' -> 'subf'; % XXX: must swap operands
- 'mul' -> 'mullw';
- 'or' -> 'or';
- 'and' -> 'and';
- 'xor' -> 'xor';
- 'sll' -> 'slw';
- 'srl' -> 'srw';
- 'sra' -> 'sraw'
+ case {get(hipe_target_arch), RtlAluOp} of
+ {_, 'add'} -> 'add';
+ {_, 'sub'} -> 'subf'; % XXX: must swap operands
+ {_, 'or'} -> 'or';
+ {_, 'and'} -> 'and';
+ {_, 'xor'} -> 'xor';
+
+ {powerpc, 'mul'} -> 'mullw';
+ {powerpc, 'sll'} -> 'slw';
+ {powerpc, 'srl'} -> 'srw';
+ {powerpc, 'sra'} -> 'sraw';
+
+ {ppc64, 'mul'} -> 'mulld';
+ {ppc64, 'sll'} -> 'sld';
+ {ppc64, 'srl'} -> 'srd';
+ {ppc64, 'sra'} -> 'srad'
end.
aluop_commutes(AluOp) ->
@@ -454,7 +493,11 @@ aluop_commutes(AluOp) ->
'xor' -> true;
'slw' -> false;
'srw' -> false;
- 'sraw' -> false
+ 'sraw' -> false;
+ 'mulld' -> true; % ppc64
+ 'sld' -> false; % ppc64
+ 'srd' -> false; % ppc64
+ 'srad' -> false % ppc64
end.
conv_alub_cond(Cond) -> % only signed
@@ -528,17 +571,24 @@ mk_alub_ri_Rc(Dst, Src1, AluOp, Src2) ->
mk_alub_ri_Rc_addi(Dst, Src1, Src2, 'addic.', 'add.');
'addc' -> % 'addic' has a 16-bit simm operand
mk_alub_ri_Rc_addi(Dst, Src1, Src2, 'addic', 'addc');
- 'mullw' -> % there is no 'mulli.'
+ 'mullw' -> % there is no 'mulli.'
mk_alub_ri_Rc_rr(Dst, Src1, 'mullw.', Src2);
+ 'mulld' -> % there is no 'mulli.'
+ mk_alub_ri_Rc_rr(Dst, Src1, 'mulld.', Src2);
'or' -> % there is no 'ori.'
mk_alub_ri_Rc_rr(Dst, Src1, 'or.', Src2);
'xor' -> % there is no 'xori.'
mk_alub_ri_Rc_rr(Dst, Src1, 'xor.', Src2);
'and' -> % 'andi.' has a 16-bit uimm operand
- case rlwinm_mask(Src2) of
- {MB,ME} ->
- [hipe_ppc:mk_unary({'rlwinm.',0,MB,ME}, Dst, Src1)];
- _ ->
+ if
+ Src2 band (bnot 16#ffffffff) =:= 0 ->
+ case rlwinm_mask(Src2) of
+ {MB,ME} ->
+ [hipe_ppc:mk_unary({'rlwinm.',0,MB,ME}, Dst, Src1)];
+ _ ->
+ mk_alub_ri_Rc_andi(Dst, Src1, Src2)
+ end;
+ true ->
mk_alub_ri_Rc_andi(Dst, Src1, Src2)
end;
_ -> % shift ops have 5-bit uimm operands
@@ -562,13 +612,16 @@ mk_alub_ri_Rc_andi(Dst, Src1, Src2) ->
end.
mk_alub_ri_Rc_shift(Dst, Src1, AluOp, Src2) ->
- if Src2 < 32, Src2 >= 0 ->
- AluOpIDot =
- case AluOp of
- 'slw' -> 'slwi.'; % alias for rlwinm.
- 'srw' -> 'srwi.'; % alias for rlwinm.
- 'sraw' -> 'srawi.'
- end,
+ {AluOpIDot, MaxIShift} =
+ case AluOp of
+ 'slw' -> {'slwi.', 32}; % alias for rlwinm.
+ 'srw' -> {'srwi.', 32}; % alias for rlwinm.
+ 'sraw' -> {'srawi.', 32};
+ 'sld' -> {'sldi.', 64};
+ 'srd' -> {'srdi.', 64};
+ 'srad' -> {'sradi.', 64}
+ end,
+ if Src2 < MaxIShift, Src2 >= 0 ->
[hipe_ppc:mk_alu(AluOpIDot, Dst, Src1,
hipe_ppc:mk_uimm16(Src2))];
true ->
@@ -576,7 +629,10 @@ mk_alub_ri_Rc_shift(Dst, Src1, AluOp, Src2) ->
case AluOp of
'slw' -> 'slw.';
'srw' -> 'srw.';
- 'sraw' -> 'sraw.'
+ 'sraw' -> 'sraw.';
+ 'sld' -> 'sld.';
+ 'srd' -> 'srd.';
+ 'srad' -> 'srad.'
end,
mk_alub_ri_Rc_rr(Dst, Src1, AluOpDot, Src2)
end.
@@ -598,8 +654,9 @@ mk_alub_rr_OE(Dst, Src1, AluOp, Src2) ->
case AluOp of
'subf' -> 'subfo.';
'add' -> 'addo.';
- 'mullw' -> 'mullwo.'
- %% fail for addc, or, and, xor, slw, srw, sraw
+ 'mullw' -> 'mullwo.';
+ 'mulld' -> 'mulldo.'
+ %% fail for addc, or, and, xor, slw, srw, sraw
end,
[hipe_ppc:mk_alu(AluOpODot, Dst, Src1, Src2)].
@@ -610,12 +667,16 @@ mk_alub_rr_Rc(Dst, Src1, AluOp, Src2) ->
'add' -> 'add.';
'addc' -> 'addc'; % only interested in CA, no Rc needed
'mullw' -> 'mullw.';
+ 'mulld' -> 'mulld.';
'or' -> 'or.';
'and' -> 'and.';
'xor' -> 'xor.';
'slw' -> 'slw.';
+ 'sld' -> 'sld.';
'srw' -> 'srw.';
- 'sraw' -> 'sraw.'
+ 'srd' -> 'srd.';
+ 'sraw' -> 'sraw.';
+ 'srad' -> 'srad.'
end,
[hipe_ppc:mk_alu(AluOpDot, Dst, Src1, Src2)].
@@ -682,17 +743,17 @@ mk_branch_ri(Src1, BCond, Sign, Src2, TrueLab, FalseLab, Pred) ->
case Sign of
'signed' ->
if is_integer(Src2), -32768 =< Src2, Src2 < 32768 ->
- {[], hipe_ppc:mk_simm16(Src2), 'cmpi'};
+ {[], hipe_ppc:mk_simm16(Src2), hipe_ppc:cmpiop_word()};
true ->
Tmp = new_untagged_temp(),
- {mk_li(Tmp, Src2), Tmp, 'cmp'}
+ {mk_li(Tmp, Src2), Tmp, hipe_ppc:cmpop_word()}
end;
'unsigned' ->
if is_integer(Src2), 0 =< Src2, Src2 < 65536 ->
- {[], hipe_ppc:mk_uimm16(Src2), 'cmpli'};
+ {[], hipe_ppc:mk_uimm16(Src2), hipe_ppc:cmpliop_word()};
true ->
Tmp = new_untagged_temp(),
- {mk_li(Tmp, Src2), Tmp, 'cmpl'}
+ {mk_li(Tmp, Src2), Tmp, hipe_ppc:cmplop_word()}
end
end,
FixSrc2 ++
@@ -701,8 +762,8 @@ mk_branch_ri(Src1, BCond, Sign, Src2, TrueLab, FalseLab, Pred) ->
mk_branch_rr(Src1, BCond, Sign, Src2, TrueLab, FalseLab, Pred) ->
CmpOp =
case Sign of
- 'signed' -> 'cmp';
- 'unsigned' -> 'cmpl'
+ 'signed' -> hipe_ppc:cmpop_word();
+ 'unsigned' -> hipe_ppc:cmplop_word()
end,
mk_cmp_bc(CmpOp, Src1, Src2, BCond, TrueLab, FalseLab, Pred).
@@ -841,7 +902,7 @@ mk_store_args([Arg|Args], PrevOffset, Tail) ->
Tmp = new_tagged_temp(),
{Tmp, mk_li(Tmp, Arg)}
end,
- Store = hipe_ppc:mk_store('stw', Src, Offset, mk_sp()),
+ Store = hipe_ppc:mk_store(hipe_ppc:stop_word(), Src, Offset, mk_sp()),
mk_store_args(Args, Offset, FixSrc ++ [Store | Tail]);
mk_store_args([], _, Tail) ->
Tail.
@@ -883,25 +944,19 @@ conv_load(I, Map, Data) ->
{I2, Map2, Data}.
mk_load(Dst, Base1, Base2, LoadSize, LoadSign) ->
- Rest =
- case LoadSize of
- byte ->
- case LoadSign of
- signed -> [hipe_ppc:mk_unary('extsb', Dst, Dst)];
- _ -> []
+ {LdOp, Rest} =
+ case {LoadSize, LoadSign} of
+ {byte, signed} -> {'lbz', [hipe_ppc:mk_unary('extsb', Dst, Dst)]};
+ {byte, unsigned} -> {'lbz', []};
+ {int16, signed} -> {'lha', []};
+ {int16, unsigned} -> {'lhz', []};
+ {int32, signed} ->
+ case get(hipe_target_arch) of
+ powerpc -> {'lwz', []};
+ ppc64 -> {'lwa', []}
end;
- _ -> []
- end,
- LdOp =
- case LoadSize of
- byte -> 'lbz';
- int32 -> 'lwz';
- word -> 'lwz';
- int16 ->
- case LoadSign of
- signed -> 'lha';
- unsigned -> 'lhz'
- end
+ {int32, unsigned} -> {'lwz', []};
+ {word, _} -> {hipe_ppc:ldop_word(), []}
end,
case hipe_ppc:is_temp(Base1) of
true ->
@@ -980,7 +1035,7 @@ mk_store(Src, Base1, Base2, StoreSize) ->
byte -> 'stb';
int16 -> 'sth';
int32 -> 'stw';
- word -> 'stw'
+ word -> hipe_ppc:stop_word()
end,
case hipe_ppc:is_temp(Src) of
true ->
@@ -1022,10 +1077,16 @@ conv_switch(I, Map, Data) ->
JTabR = new_untagged_temp(),
OffsetR = new_untagged_temp(),
DestR = new_untagged_temp(),
+ ShiftInstruction =
+ case get(hipe_target_arch) of
+ powerpc -> 'slwi';
+ ppc64 -> 'sldi'
+ end,
I2 =
[hipe_ppc:mk_pseudo_li(JTabR, {JTabLab,constant}),
- hipe_ppc:mk_alu('slwi', OffsetR, IndexR, hipe_ppc:mk_uimm16(2)),
- hipe_ppc:mk_loadx('lwzx', DestR, JTabR, OffsetR),
+ hipe_ppc:mk_alu(ShiftInstruction, OffsetR, IndexR,
+ hipe_ppc:mk_uimm16(log2_word_size())),
+ hipe_ppc:mk_loadx(hipe_ppc:ldop_wordx(), DestR, JTabR, OffsetR),
hipe_ppc:mk_mtspr('ctr', DestR),
hipe_ppc:mk_bctr(Labels)],
{I2, Map1, NewData}.
@@ -1247,3 +1308,6 @@ vmap_bind(Map, Key, Val) ->
word_size() ->
hipe_rtl_arch:word_size().
+
+log2_word_size() ->
+ hipe_rtl_arch:log2_word_size().