aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lib/hipe/amd64/hipe_amd64_encode.erl38
-rw-r--r--lib/hipe/x86/hipe_x86_assemble.erl47
-rw-r--r--lib/hipe/x86/hipe_x86_defuse.erl3
-rw-r--r--lib/hipe/x86/hipe_x86_encode.erl23
-rw-r--r--lib/hipe/x86/hipe_x86_frame.erl8
-rw-r--r--lib/hipe/x86/hipe_x86_pp.erl6
-rw-r--r--lib/hipe/x86/hipe_x86_ra_finalise.erl4
-rw-r--r--lib/hipe/x86/hipe_x86_ra_naive.erl7
-rw-r--r--lib/hipe/x86/hipe_x86_ra_postconditions.erl10
9 files changed, 125 insertions, 21 deletions
diff --git a/lib/hipe/amd64/hipe_amd64_encode.erl b/lib/hipe/amd64/hipe_amd64_encode.erl
index df15732cea..c41eaa3c6a 100644
--- a/lib/hipe/amd64/hipe_amd64_encode.erl
+++ b/lib/hipe/amd64/hipe_amd64_encode.erl
@@ -63,7 +63,7 @@
-export([% condition codes
cc/1,
% 8-bit registers
- %% al/0, cl/0, dl/0, bl/0, ah/0, ch/0, dh/0, bh/0,
+ %% al/0, cl/0, dl/0, bl/0,
% 32-bit registers
%% eax/0, ecx/0, edx/0, ebx/0, esp/0, ebp/0, esi/0, edi/0,
% operands
@@ -127,19 +127,15 @@ cc(g) -> ?CC_G.
-define(CL, 2#001).
-define(DL, 2#010).
-define(BL, 2#011).
--define(AH, 2#100).
--define(CH, 2#101).
--define(DH, 2#110).
--define(BH, 2#111).
+-define(SPL, 2#100).
+-define(BPL, 2#101).
+-define(SIL, 2#110).
+-define(DIL, 2#111).
%% al() -> ?AL.
%% cl() -> ?CL.
%% dl() -> ?DL.
%% bl() -> ?BL.
-%% ah() -> ?AH.
-%% ch() -> ?CH.
-%% dh() -> ?DH.
-%% bh() -> ?BH.
%%% 32-bit registers
@@ -208,6 +204,7 @@ rex_([]) -> 0;
rex_([{r8, Reg8}| Rest]) -> % 8 bit registers
case Reg8 of
{rm_mem, _} -> rex_(Rest);
+ {rm_reg, R} -> rex_([{r8, R} | Rest]);
4 -> (1 bsl 8) bor rex_(Rest);
5 -> (1 bsl 8) bor rex_(Rest);
6 -> (1 bsl 8) bor rex_(Rest);
@@ -825,12 +822,22 @@ shd_op_encode(Opcode, Opnds) ->
test_encode(Opnds) ->
case Opnds of
+ {al, {imm8,Imm8}} ->
+ [16#A8, Imm8];
+ {ax, {imm16,Imm16}} ->
+ [?PFX_OPND_16BITS, 16#A9 | le16(Imm16, [])];
{eax, {imm32,Imm32}} ->
[16#A9 | le32(Imm32, [])];
+ {{rm8,RM8}, {imm8,Imm8}} ->
+ [rex([{r8,RM8}]), 16#F6 | encode_rm(RM8, 2#000, [Imm8])];
+ {{rm16,RM16}, {imm16,Imm16}} ->
+ [?PFX_OPND_16BITS, 16#F7 | encode_rm(RM16, 2#000, le16(Imm16, []))];
{{rm32,RM32}, {imm32,Imm32}} ->
[16#F7 | encode_rm(RM32, 2#000, le32(Imm32, []))];
{{rm32,RM32}, {reg32,Reg32}} ->
- [16#85 | encode_rm(RM32, Reg32, [])]
+ [16#85 | encode_rm(RM32, Reg32, [])];
+ {{rm64,RM64}, {reg64,Reg64}} ->
+ [rex([{w,1}]), 16#85 | encode_rm(RM64, Reg64, [])]
end.
%% test_sizeof(Opnds) ->
@@ -1309,18 +1316,21 @@ dotest1(OS) ->
Imm32 = {imm32,Word32},
Imm16 = {imm16,Word16},
Imm8 = {imm8,Word8},
+ RM64 = {rm64,rm_reg(?EDX)},
RM32 = {rm32,rm_reg(?EDX)},
RM16 = {rm16,rm_reg(?EDX)},
RM8 = {rm8,rm_reg(?EDX)},
+ RM8REX = {rm8,rm_reg(?SIL)},
Rel32 = {rel32,Word32},
Rel8 = {rel8,Word8},
Moffs32 = {moffs32,Word32},
Moffs16 = {moffs16,Word32},
Moffs8 = {moffs8,Word32},
CC = {cc,?CC_G},
+ Reg64 = {reg64,?EAX},
Reg32 = {reg32,?EAX},
Reg16 = {reg16,?EAX},
- Reg8 = {reg8,?AH},
+ Reg8 = {reg8,?SPL},
EA = {ea,ea_base(?ECX)},
% exercise each instruction definition
t(OS,'adc',{eax,Imm32}),
@@ -1465,9 +1475,15 @@ dotest1(OS) ->
t(OS,'sub',{RM32,Imm8}),
t(OS,'sub',{RM32,Reg32}),
t(OS,'sub',{Reg32,RM32}),
+ t(OS,'test',{al,Imm8}),
+ t(OS,'test',{ax,Imm16}),
t(OS,'test',{eax,Imm32}),
+ t(OS,'test',{RM8,Imm8}),
+ t(OS,'test',{RM8REX,Imm8}),
+ t(OS,'test',{RM16,Imm16}),
t(OS,'test',{RM32,Imm32}),
t(OS,'test',{RM32,Reg32}),
+ t(OS,'test',{RM64,Reg64}),
t(OS,'xor',{eax,Imm32}),
t(OS,'xor',{RM32,Imm32}),
t(OS,'xor',{RM32,Imm8}),
diff --git a/lib/hipe/x86/hipe_x86_assemble.erl b/lib/hipe/x86/hipe_x86_assemble.erl
index e21223a5b1..4986933f50 100644
--- a/lib/hipe/x86/hipe_x86_assemble.erl
+++ b/lib/hipe/x86/hipe_x86_assemble.erl
@@ -599,10 +599,20 @@ temp_to_xmm(#x86_temp{reg=Reg}) ->
{xmm, Reg}.
-ifdef(HIPE_AMD64).
+temp_to_rm8(#x86_temp{reg=Reg}) ->
+ {rm8, ?HIPE_X86_ENCODE:rm_reg(Reg)}.
temp_to_rm64(#x86_temp{reg=Reg}) ->
{rm64, hipe_amd64_encode:rm_reg(Reg)}.
+-else.
+temp_to_rm8(#x86_temp{reg=Reg}) ->
+ true = ?HIPE_X86_ENCODE:reg_has_8bit(Reg),
+ {rm8, ?HIPE_X86_ENCODE:rm_reg(Reg)}.
+temp_to_rm16(#x86_temp{reg=Reg}) ->
+ {rm16, ?HIPE_X86_ENCODE:rm_reg(Reg)}.
-endif.
+temp_to_rm32(#x86_temp{reg=Reg}) ->
+ {rm32, ?HIPE_X86_ENCODE:rm_reg(Reg)}.
temp_to_rmArch(#x86_temp{reg=Reg}) ->
{?RMArch, ?HIPE_X86_ENCODE:rm_reg(Reg)}.
temp_to_rm64fp(#x86_temp{reg=Reg}) ->
@@ -878,15 +888,22 @@ resolve_alu_args(Src, Dst, Context) ->
%%% test
resolve_test_args(Src, Dst, Context) ->
case Src of
- #x86_imm{} -> % imm8 not allowed
- {_ImmSize,ImmValue} = translate_imm(Src, Context, false),
- NewDst =
- case Dst of
- #x86_temp{reg=0} -> ?EAX;
- #x86_temp{} -> temp_to_rmArch(Dst);
- #x86_mem{} -> mem_to_rmArch(Dst)
- end,
- {NewDst, {imm32,ImmValue}};
+ #x86_imm{} ->
+ Imm = translate_imm(Src, Context, false),
+ case Imm of
+ {imm8,_} ->
+ case Dst of
+ #x86_temp{reg=0} -> {al, Imm};
+ #x86_temp{} -> resolve_test_imm8_reg(Imm, Dst);
+ #x86_mem{} -> {mem_to_rm8(Dst), Imm}
+ end;
+ {imm32,_} ->
+ {case Dst of
+ #x86_temp{reg=0} -> eax;
+ #x86_temp{} -> temp_to_rm32(Dst);
+ #x86_mem{} -> mem_to_rm32(Dst)
+ end, Imm}
+ end;
#x86_temp{} ->
NewDst =
case Dst of
@@ -896,6 +913,18 @@ resolve_test_args(Src, Dst, Context) ->
{NewDst, temp_to_regArch(Src)}
end.
+-ifdef(HIPE_AMD64).
+resolve_test_imm8_reg(Imm, Dst) -> {temp_to_rm8(Dst), Imm}.
+-else.
+resolve_test_imm8_reg(Imm = {imm8, ImmVal}, Dst = #x86_temp{reg=Reg}) ->
+ case ?HIPE_X86_ENCODE:reg_has_8bit(Reg) of
+ true -> {temp_to_rm8(Dst), Imm};
+ false ->
+ %% Register does not exist in 8-bit version; use 16-bit instead
+ {temp_to_rm16(Dst), {imm16, ImmVal}}
+ end.
+-endif.
+
%%% shifts
resolve_shift_args(Src, Dst, Context) ->
RM32 =
diff --git a/lib/hipe/x86/hipe_x86_defuse.erl b/lib/hipe/x86/hipe_x86_defuse.erl
index 4455def74e..ab26370a80 100644
--- a/lib/hipe/x86/hipe_x86_defuse.erl
+++ b/lib/hipe/x86/hipe_x86_defuse.erl
@@ -60,7 +60,7 @@ insn_def(I) ->
#pseudo_tailcall_prepare{} -> tailcall_clobbered();
#shift{dst=Dst} -> dst_def(Dst);
%% call, cmp, comment, jcc, jmp_fun, jmp_label, jmp_switch, label
- %% pseudo_jcc, pseudo_tailcall, push, ret
+ %% pseudo_jcc, pseudo_tailcall, push, ret, test
_ -> []
end.
@@ -120,6 +120,7 @@ insn_use(I) ->
#push{src=Src} -> addtemp(Src, []);
#ret{} -> [hipe_x86:mk_temp(?HIPE_X86_REGISTERS:?RV(), 'tagged')];
#shift{src=Src,dst=Dst} -> addtemp(Src, addtemp(Dst, []));
+ #test{src=Src, dst=Dst} -> addtemp(Src, addtemp(Dst, []));
%% comment, jcc, jmp_label, label, pseudo_jcc, pseudo_tailcall_prepare
_ -> []
end.
diff --git a/lib/hipe/x86/hipe_x86_encode.erl b/lib/hipe/x86/hipe_x86_encode.erl
index 3b7be86608..2d1663d0d6 100644
--- a/lib/hipe/x86/hipe_x86_encode.erl
+++ b/lib/hipe/x86/hipe_x86_encode.erl
@@ -65,6 +65,7 @@
cc/1,
% 8-bit registers
%% al/0, cl/0, dl/0, bl/0, ah/0, ch/0, dh/0, bh/0,
+ reg_has_8bit/1,
% 32-bit registers
%% eax/0, ecx/0, edx/0, ebx/0, esp/0, ebp/0, esi/0, edi/0,
% operands
@@ -143,6 +144,8 @@ cc(g) -> ?CC_G.
%% dh() -> ?DH.
%% bh() -> ?BH.
+reg_has_8bit(Reg) -> Reg =< ?BL.
+
%%% 32-bit registers
-define(EAX, 2#000).
@@ -700,8 +703,16 @@ shd_op_sizeof(Opnds) ->
test_encode(Opnds) ->
case Opnds of
+ {al, {imm8,Imm8}} ->
+ [16#A8, Imm8];
+ {ax, {imm16,Imm16}} ->
+ [?PFX_OPND, 16#A9 | le16(Imm16, [])];
{eax, {imm32,Imm32}} ->
[16#A9 | le32(Imm32, [])];
+ {{rm8,RM8}, {imm8,Imm8}} ->
+ [16#F6 | encode_rm(RM8, 2#000, [Imm8])];
+ {{rm16,RM16}, {imm16,Imm16}} ->
+ [?PFX_OPND, 16#F7 | encode_rm(RM16, 2#000, le16(Imm16, []))];
{{rm32,RM32}, {imm32,Imm32}} ->
[16#F7 | encode_rm(RM32, 2#000, le32(Imm32, []))];
{{rm32,RM32}, {reg32,Reg32}} ->
@@ -710,8 +721,16 @@ test_encode(Opnds) ->
test_sizeof(Opnds) ->
case Opnds of
+ {al, {imm8,_}} ->
+ 1 + 1;
+ {ax, {imm16,_}} ->
+ 2 + 2;
{eax, {imm32,_}} ->
1 + 4;
+ {{rm8,RM8}, {imm8,_}} ->
+ 1 + sizeof_rm(RM8) + 1;
+ {{rm16,RM16}, {imm16,_}} ->
+ 2 + sizeof_rm(RM16) + 2;
{{rm32,RM32}, {imm32,_}} ->
1 + sizeof_rm(RM32) + 4;
{{rm32,RM32}, {reg32,_}} ->
@@ -1283,7 +1302,11 @@ dotest1(OS) ->
t(OS,'sub',{RM32,Imm8}),
t(OS,'sub',{RM32,Reg32}),
t(OS,'sub',{Reg32,RM32}),
+ t(OS,'test',{al,Imm8}),
+ t(OS,'test',{ax,Imm16}),
t(OS,'test',{eax,Imm32}),
+ t(OS,'test',{RM8,Imm8}),
+ t(OS,'test',{RM16,Imm16}),
t(OS,'test',{RM32,Imm32}),
t(OS,'test',{RM32,Reg32}),
t(OS,'xor',{eax,Imm32}),
diff --git a/lib/hipe/x86/hipe_x86_frame.erl b/lib/hipe/x86/hipe_x86_frame.erl
index fc782571bf..17253ad46f 100644
--- a/lib/hipe/x86/hipe_x86_frame.erl
+++ b/lib/hipe/x86/hipe_x86_frame.erl
@@ -116,6 +116,8 @@ do_insn(I, LiveOut, Context, FPoff) ->
{do_ret(I, Context, FPoff), context_framesize(Context)};
#shift{} ->
{[do_shift(I, Context, FPoff)], FPoff};
+ #test{} ->
+ {[do_test(I, Context, FPoff)], FPoff};
_ -> % comment, jmp, label, pseudo_jcc, pseudo_tailcall_prepare
{[I], FPoff}
end.
@@ -188,6 +190,12 @@ do_shift(I, Context, FPoff) ->
Dst = conv_opnd(Dst0, FPoff, Context),
I#shift{src=Src,dst=Dst}.
+do_test(I, Context, FPoff) ->
+ #test{src=Src0,dst=Dst0} = I,
+ Src = conv_opnd(Src0, FPoff, Context),
+ Dst = conv_opnd(Dst0, FPoff, Context),
+ I#test{src=Src,dst=Dst}.
+
conv_opnd(Opnd, FPoff, Context) ->
case opnd_is_pseudo(Opnd) of
false ->
diff --git a/lib/hipe/x86/hipe_x86_pp.erl b/lib/hipe/x86/hipe_x86_pp.erl
index ff26a31877..942201a051 100644
--- a/lib/hipe/x86/hipe_x86_pp.erl
+++ b/lib/hipe/x86/hipe_x86_pp.erl
@@ -188,6 +188,12 @@ pp_insn(Dev, I, Pre) ->
io:format(Dev, ", ", []),
pp_dst(Dev, Dst),
io:format(Dev, "\n", []);
+ #test{src=Src, dst=Dst} ->
+ io:format(Dev, "\ttest ", []),
+ pp_src(Dev, Src),
+ io:format(Dev, ", ", []),
+ pp_dst(Dev, Dst),
+ io:format(Dev, "\n", []);
#fp_binop{src=Src, dst=Dst, op=Op} ->
io:format(Dev, "\t~s ", [Op]),
pp_dst(Dev, Dst),
diff --git a/lib/hipe/x86/hipe_x86_ra_finalise.erl b/lib/hipe/x86/hipe_x86_ra_finalise.erl
index edfd7b332c..1fd617570a 100644
--- a/lib/hipe/x86/hipe_x86_ra_finalise.erl
+++ b/lib/hipe/x86/hipe_x86_ra_finalise.erl
@@ -162,6 +162,10 @@ ra_insn(I, Map, FpMap) ->
Src = ra_opnd(Src0, Map),
Dst = ra_opnd(Dst0, Map),
I#shift{src=Src,dst=Dst};
+ #test{src=Src0,dst=Dst0} ->
+ Src = ra_opnd(Src0, Map),
+ Dst = ra_opnd(Dst0, Map),
+ I#test{src=Src,dst=Dst};
_ ->
exit({?MODULE,ra_insn,I})
end.
diff --git a/lib/hipe/x86/hipe_x86_ra_naive.erl b/lib/hipe/x86/hipe_x86_ra_naive.erl
index 35de692e07..9371e4b1a5 100644
--- a/lib/hipe/x86/hipe_x86_ra_naive.erl
+++ b/lib/hipe/x86/hipe_x86_ra_naive.erl
@@ -100,6 +100,8 @@ do_insn(I) -> % Insn -> Insn list
do_fp_binop(I);
#shift{} ->
do_shift(I);
+ #test{} ->
+ do_test(I);
#label{} ->
[I];
#pseudo_jcc{} ->
@@ -310,6 +312,11 @@ do_shift(I) ->
FixDst ++ [I#shift{dst=Dst}]
end.
+do_test(I) ->
+ #test{src=Src0,dst=Dst0} = I,
+ {FixSrc, Src, FixDst, Dst} = do_binary(Src0, Dst0),
+ FixSrc ++ FixDst ++ [I#test{src=Src,dst=Dst}].
+
%%% Fix the operands of a binary op.
%%% 1. remove pseudos from any explicit memory operands
%%% 2. if both operands are (implicit or explicit) memory operands,
diff --git a/lib/hipe/x86/hipe_x86_ra_postconditions.erl b/lib/hipe/x86/hipe_x86_ra_postconditions.erl
index f496b71828..e7c397b5b7 100644
--- a/lib/hipe/x86/hipe_x86_ra_postconditions.erl
+++ b/lib/hipe/x86/hipe_x86_ra_postconditions.erl
@@ -83,6 +83,8 @@ do_insn(I, TempMap, Strategy) -> % Insn -> {Insn list, DidSpill}
do_fmove(I, TempMap, Strategy);
#shift{} ->
do_shift(I, TempMap, Strategy);
+ #test{} ->
+ do_test(I, TempMap, Strategy);
_ ->
%% comment, jmp*, label, pseudo_call, pseudo_jcc, pseudo_tailcall,
%% pseudo_tailcall_prepare, push, ret
@@ -308,6 +310,14 @@ do_shift(I, TempMap, Strategy) ->
{FixDst ++ [I#shift{dst=Dst}], DidSpill}
end.
+%%% Fix a test op.
+
+do_test(I, TempMap, Strategy) ->
+ #test{src=Src0,dst=Dst0} = I,
+ {FixSrc, Src, FixDst, Dst, DidSpill} =
+ do_binary(Src0, Dst0, TempMap, Strategy),
+ {FixSrc ++ FixDst ++ [I#test{src=Src,dst=Dst}], DidSpill}.
+
%%% Fix the operands of a binary op.
%%% 1. remove pseudos from any explicit memory operands
%%% 2. if both operands are (implicit or explicit) memory operands,