diff options
author | Magnus Lång <[email protected]> | 2016-11-16 18:29:16 +0100 |
---|---|---|
committer | Magnus Lång <[email protected]> | 2016-11-16 19:48:24 +0100 |
commit | fda3c9575d77bed0250f76f17e92d18836e15d0c (patch) | |
tree | ff0e90f7353c7dfb668364070986f619478f305c /lib | |
parent | 053e54e5a937deb685dc71e3873074cb8efc96ea (diff) | |
download | otp-fda3c9575d77bed0250f76f17e92d18836e15d0c.tar.gz otp-fda3c9575d77bed0250f76f17e92d18836e15d0c.tar.bz2 otp-fda3c9575d77bed0250f76f17e92d18836e15d0c.zip |
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')
-rw-r--r-- | lib/hipe/amd64/hipe_amd64_encode.erl | 6 | ||||
-rw-r--r-- | lib/hipe/x86/hipe_x86_assemble.erl | 37 |
2 files changed, 28 insertions, 15 deletions
diff --git a/lib/hipe/amd64/hipe_amd64_encode.erl b/lib/hipe/amd64/hipe_amd64_encode.erl index c41eaa3c6a..16bd705055 100644 --- a/lib/hipe/amd64/hipe_amd64_encode.erl +++ b/lib/hipe/amd64/hipe_amd64_encode.erl @@ -828,12 +828,16 @@ test_encode(Opnds) -> [?PFX_OPND_16BITS, 16#A9 | le16(Imm16, [])]; {eax, {imm32,Imm32}} -> [16#A9 | le32(Imm32, [])]; + {rax, {imm32,Imm32}} -> + [rex([{w,1}]), 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, []))]; + {{rm64,RM64}, {imm32,Imm32}} -> + [rex([{w,1}]), 16#F7 | encode_rm(RM64, 2#000, le32(Imm32, []))]; {{rm32,RM32}, {reg32,Reg32}} -> [16#85 | encode_rm(RM32, Reg32, [])]; {{rm64,RM64}, {reg64,Reg64}} -> @@ -1478,10 +1482,12 @@ dotest1(OS) -> t(OS,'test',{al,Imm8}), t(OS,'test',{ax,Imm16}), t(OS,'test',{eax,Imm32}), + t(OS,'test',{rax,Imm32}), t(OS,'test',{RM8,Imm8}), t(OS,'test',{RM8REX,Imm8}), t(OS,'test',{RM16,Imm16}), t(OS,'test',{RM32,Imm32}), + t(OS,'test',{RM64,Imm32}), t(OS,'test',{RM32,Reg32}), t(OS,'test',{RM64,Reg64}), t(OS,'xor',{eax,Imm32}), 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 |