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.erl60
1 files changed, 45 insertions, 15 deletions
diff --git a/lib/hipe/x86/hipe_x86_assemble.erl b/lib/hipe/x86/hipe_x86_assemble.erl
index e21223a5b1..ef9c32ef41 100644
--- a/lib/hipe/x86/hipe_x86_assemble.erl
+++ b/lib/hipe/x86/hipe_x86_assemble.erl
@@ -1,9 +1,5 @@
%%% -*- erlang-indent-level: 2 -*-
%%%
-%%% %CopyrightBegin%
-%%%
-%%% Copyright Ericsson AB 2001-2016. All Rights Reserved.
-%%%
%%% Licensed under the Apache License, Version 2.0 (the "License");
%%% you may not use this file except in compliance with the License.
%%% You may obtain a copy of the License at
@@ -15,8 +11,6 @@
%%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
%%% See the License for the specific language governing permissions and
%%% limitations under the License.
-%%%
-%%% %CopyrightEnd%
%%%
%%% HiPE/x86 assembler
%%%
@@ -599,10 +593,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 +882,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 +914,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 =