Added Intel x86-64 encodings for 64bit loads and store instructions (#127)

* Added Intel x86-64 encodings for 64bit loads and store instructions

* Using GPR registers instead of ABCD for istore8 with REX prefix
Fixed testing of 64bit intel encoding

* Emit REX and REX-less encodings for optional REX prefix
Value renumbering in binary64.cton
This commit is contained in:
Denis Merigoux
2017-07-31 14:52:39 -07:00
committed by Jakob Stoklund Olesen
parent 54534e2147
commit 07e1f682d0
4 changed files with 373 additions and 102 deletions

View File

@@ -55,6 +55,28 @@ def enc_i32_i64(inst, recipe, *args, **kwargs):
I64.enc(inst.i64, *recipe.rex(*args, w=1, **kwargs))
def enc_i32_i64_ld_st(inst, w_bit, recipe, *args, **kwargs):
# type: (MaybeBoundInst, bool, r.TailRecipe, *int, **int) -> None
"""
Add encodings for `inst.i32` to I32.
Add encodings for `inst.i32` to I64 with and without REX.
Add encodings for `inst.i64` to I64 with a REX prefix, using the `w_bit`
argument to determine wheter or not to set the REX.W bit.
"""
I32.enc(inst.i32.any, *recipe(*args, **kwargs))
# REX-less encoding must come after REX encoding so we don't use it by
# default. Otherwise reg-alloc would never use r8 and up.
I64.enc(inst.i32.any, *recipe.rex(*args, **kwargs))
I64.enc(inst.i32.any, *recipe(*args, **kwargs))
if w_bit:
I64.enc(inst.i64.any, *recipe.rex(*args, w=1, **kwargs))
else:
I64.enc(inst.i64.any, *recipe.rex(*args, **kwargs))
I64.enc(inst.i64.any, *recipe(*args, **kwargs))
def enc_flt(inst, recipe, *args, **kwargs):
# type: (MaybeBoundInst, r.TailRecipe, *int, **int) -> None
"""
@@ -142,38 +164,60 @@ I64.enc(base.ctz.i64, *r.urm.rex(0xf3, 0x0f, 0xbc, w=1),
I64.enc(base.ctz.i32, *r.urm.rex(0xf3, 0x0f, 0xbc), isap=cfg.use_bmi1)
I64.enc(base.ctz.i32, *r.urm(0xf3, 0x0f, 0xbc), isap=cfg.use_bmi1)
#
# Loads and stores.
I32.enc(base.store.i32.any, *r.st(0x89))
I32.enc(base.store.i32.any, *r.stDisp8(0x89))
I32.enc(base.store.i32.any, *r.stDisp32(0x89))
#
enc_i32_i64_ld_st(base.store, True, r.st, 0x89)
enc_i32_i64_ld_st(base.store, True, r.stDisp8, 0x89)
enc_i32_i64_ld_st(base.store, True, r.stDisp32, 0x89)
I32.enc(base.istore16.i32.any, *r.st(0x66, 0x89))
I32.enc(base.istore16.i32.any, *r.stDisp8(0x66, 0x89))
I32.enc(base.istore16.i32.any, *r.stDisp32(0x66, 0x89))
I64.enc(base.istore32.i64.any, *r.st.rex(0x89))
I64.enc(base.istore32.i64.any, *r.stDisp8.rex(0x89))
I64.enc(base.istore32.i64.any, *r.stDisp32.rex(0x89))
enc_i32_i64_ld_st(base.istore16, False, r.st, 0x66, 0x89)
enc_i32_i64_ld_st(base.istore16, False, r.stDisp8, 0x66, 0x89)
enc_i32_i64_ld_st(base.istore16, False, r.stDisp32, 0x66, 0x89)
# Byte stores are more complicated because the registers they can address
# depends of the presence of a REX prefix
I32.enc(base.istore8.i32.any, *r.st_abcd(0x88))
I64.enc(base.istore8.i32.any, *r.st_abcd(0x88))
I64.enc(base.istore8.i64.any, *r.st.rex(0x88))
I32.enc(base.istore8.i32.any, *r.stDisp8_abcd(0x88))
I64.enc(base.istore8.i32.any, *r.stDisp8_abcd(0x88))
I64.enc(base.istore8.i64.any, *r.stDisp8.rex(0x88))
I32.enc(base.istore8.i32.any, *r.stDisp32_abcd(0x88))
I64.enc(base.istore8.i32.any, *r.stDisp32_abcd(0x88))
I64.enc(base.istore8.i64.any, *r.stDisp32.rex(0x88))
I32.enc(base.load.i32.any, *r.ld(0x8b))
I32.enc(base.load.i32.any, *r.ldDisp8(0x8b))
I32.enc(base.load.i32.any, *r.ldDisp32(0x8b))
enc_i32_i64_ld_st(base.load, True, r.ld, 0x8b)
enc_i32_i64_ld_st(base.load, True, r.ldDisp8, 0x8b)
enc_i32_i64_ld_st(base.load, True, r.ldDisp32, 0x8b)
I32.enc(base.uload16.i32.any, *r.ld(0x0f, 0xb7))
I32.enc(base.uload16.i32.any, *r.ldDisp8(0x0f, 0xb7))
I32.enc(base.uload16.i32.any, *r.ldDisp32(0x0f, 0xb7))
I64.enc(base.uload32.i64, *r.ld.rex(0x8b))
I64.enc(base.uload32.i64, *r.ldDisp8.rex(0x8b))
I64.enc(base.uload32.i64, *r.ldDisp32.rex(0x8b))
I32.enc(base.sload16.i32.any, *r.ld(0x0f, 0xbf))
I32.enc(base.sload16.i32.any, *r.ldDisp8(0x0f, 0xbf))
I32.enc(base.sload16.i32.any, *r.ldDisp32(0x0f, 0xbf))
I64.enc(base.sload32.i64, *r.ld.rex(0x63, w=1))
I64.enc(base.sload32.i64, *r.ldDisp8.rex(0x63, w=1))
I64.enc(base.sload32.i64, *r.ldDisp32.rex(0x63, w=1))
I32.enc(base.uload8.i32.any, *r.ld(0x0f, 0xb6))
I32.enc(base.uload8.i32.any, *r.ldDisp8(0x0f, 0xb6))
I32.enc(base.uload8.i32.any, *r.ldDisp32(0x0f, 0xb6))
enc_i32_i64_ld_st(base.uload16, True, r.ld, 0x0f, 0xb7)
enc_i32_i64_ld_st(base.uload16, True, r.ldDisp8, 0x0f, 0xb7)
enc_i32_i64_ld_st(base.uload16, True, r.ldDisp32, 0x0f, 0xb7)
I32.enc(base.sload8.i32.any, *r.ld(0x0f, 0xbe))
I32.enc(base.sload8.i32.any, *r.ldDisp8(0x0f, 0xbe))
I32.enc(base.sload8.i32.any, *r.ldDisp32(0x0f, 0xbe))
enc_i32_i64_ld_st(base.sload16, True, r.ld, 0x0f, 0xbf)
enc_i32_i64_ld_st(base.sload16, True, r.ldDisp8, 0x0f, 0xbf)
enc_i32_i64_ld_st(base.sload16, True, r.ldDisp32, 0x0f, 0xbf)
enc_i32_i64_ld_st(base.uload8, True, r.ld, 0x0f, 0xb6)
enc_i32_i64_ld_st(base.uload8, True, r.ldDisp8, 0x0f, 0xb6)
enc_i32_i64_ld_st(base.uload8, True, r.ldDisp32, 0x0f, 0xb6)
enc_i32_i64_ld_st(base.sload8, True, r.ld, 0x0f, 0xbe)
enc_i32_i64_ld_st(base.sload8, True, r.ldDisp8, 0x0f, 0xbe)
enc_i32_i64_ld_st(base.sload8, True, r.ldDisp32, 0x0f, 0xbe)
#
# Call/return