aboutsummaryrefslogtreecommitdiffstats
path: root/lib/hipe/x86/hipe_x86_assemble.erl
diff options
context:
space:
mode:
Diffstat (limited to 'lib/hipe/x86/hipe_x86_assemble.erl')
-rw-r--r--lib/hipe/x86/hipe_x86_assemble.erl54
1 files changed, 45 insertions, 9 deletions
diff --git a/lib/hipe/x86/hipe_x86_assemble.erl b/lib/hipe/x86/hipe_x86_assemble.erl
index e21223a5b1..e692ff0ebb 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,29 @@ 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}};
+ %% Since we're using an 8-bit instruction, the immediate is not sign
+ %% extended. Thus, we can use immediates up to 255.
+ #x86_imm{value=ImmVal}
+ when is_integer(ImmVal), ImmVal >= 0, ImmVal =< 255 ->
+ Imm = {imm8, ImmVal},
+ 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;
+ #x86_imm{value=ImmVal} when is_integer(ImmVal), ImmVal >= 0 ->
+ {case Dst of
+ #x86_temp{reg=0} -> eax;
+ #x86_temp{} -> temp_to_rm32(Dst);
+ #x86_mem{} -> mem_to_rm32(Dst)
+ end, {imm32, ImmVal}};
+ #x86_imm{} -> % Negative ImmVal; use word-sized instr, imm32
+ {_, ImmVal} = translate_imm(Src, Context, false),
+ {case Dst of
+ #x86_temp{reg=0} -> ?EAX;
+ #x86_temp{} -> temp_to_rmArch(Dst);
+ #x86_mem{} -> mem_to_rmArch(Dst)
+ end, {imm32, ImmVal}};
#x86_temp{} ->
NewDst =
case Dst of
@@ -896,6 +920,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 =