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:
committed by
Jakob Stoklund Olesen
parent
54534e2147
commit
07e1f682d0
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user