summaryrefslogtreecommitdiff
path: root/lib/hipe/x86
diff options
context:
space:
mode:
authorMagnus Lång <margnus1@telia.com>2016-11-16 18:29:16 +0100
committerMagnus Lång <margnus1@telia.com>2016-11-16 19:48:24 +0100
commitfda3c9575d77bed0250f76f17e92d18836e15d0c (patch)
treeff0e90f7353c7dfb668364070986f619478f305c /lib/hipe/x86
parent053e54e5a937deb685dc71e3873074cb8efc96ea (diff)
downloaderlang-fda3c9575d77bed0250f76f17e92d18836e15d0c.tar.gz
hipe_x86: Fix encoding of test instr w/ neg imm
Also, use byte form for immediates up to 255, since there's no sign extension in byte form. HiPE seems to never generate negative test immediates currently, but we should at least not output incorrect encodings.
Diffstat (limited to 'lib/hipe/x86')
-rw-r--r--lib/hipe/x86/hipe_x86_assemble.erl37
1 files changed, 22 insertions, 15 deletions
diff --git a/lib/hipe/x86/hipe_x86_assemble.erl b/lib/hipe/x86/hipe_x86_assemble.erl
index 4986933f50..e692ff0ebb 100644
--- a/lib/hipe/x86/hipe_x86_assemble.erl
+++ b/lib/hipe/x86/hipe_x86_assemble.erl
@@ -888,22 +888,29 @@ resolve_alu_args(Src, Dst, Context) ->
%%% test
resolve_test_args(Src, Dst, Context) ->
case Src of
- #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}
+ %% 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