Add support for type variable wildcards in bound instructions.
Instructions will multiple type variables can now use `any` to indicate
encodings that don't care about the value of a secondary type variable:
ishl.i32.any instead of ishl.i32.i32
This is only allowed for secondary type variables (which are converted
to instruction predicates). The controlling type variable must still be
fully specified because it is used to key the encoding tables.
This commit is contained in:
@@ -314,6 +314,7 @@ class Instruction(object):
|
||||
|
||||
>>> iadd.i32
|
||||
"""
|
||||
assert name != 'any', 'Wildcard not allowed for ctrl_typevar'
|
||||
return self.bind(ValueType.by_name(name))
|
||||
|
||||
def fully_bound(self):
|
||||
@@ -386,6 +387,10 @@ class BoundInstruction(object):
|
||||
|
||||
>>> uext.i32.i8
|
||||
"""
|
||||
if name == 'any':
|
||||
# This is a wild card bind represented as a None type variable.
|
||||
return self.bind(None)
|
||||
|
||||
return self.bind(ValueType.by_name(name))
|
||||
|
||||
def fully_bound(self):
|
||||
|
||||
@@ -424,6 +424,9 @@ class Encoding(object):
|
||||
# Add secondary type variables to the instruction predicate.
|
||||
if len(self.typevars) > 1:
|
||||
for tv, vt in zip(self.inst.other_typevars, self.typevars[1:]):
|
||||
# A None tv is an 'any' wild card: `ishl.i32.any`.
|
||||
if vt is None:
|
||||
continue
|
||||
typred = TypePredicate.typevar_check(self.inst, tv, vt)
|
||||
instp = And.combine(instp, typred)
|
||||
|
||||
|
||||
@@ -104,10 +104,10 @@ for inst, rrr in [
|
||||
(base.ishl, 4),
|
||||
(base.ushr, 5),
|
||||
(base.sshr, 7)]:
|
||||
I32.enc(inst.i32.i32, *r.rc(0xd3, rrr=rrr))
|
||||
I64.enc(inst.i64.i64, *r.rc.rex(0xd3, rrr=rrr, w=1))
|
||||
I64.enc(inst.i32.i32, *r.rc.rex(0xd3, rrr=rrr))
|
||||
I64.enc(inst.i32.i32, *r.rc(0xd3, rrr=rrr))
|
||||
I32.enc(inst.i32.any, *r.rc(0xd3, rrr=rrr))
|
||||
I64.enc(inst.i64.any, *r.rc.rex(0xd3, rrr=rrr, w=1))
|
||||
I64.enc(inst.i32.any, *r.rc.rex(0xd3, rrr=rrr))
|
||||
I64.enc(inst.i32.any, *r.rc(0xd3, rrr=rrr))
|
||||
|
||||
# Population count.
|
||||
I32.enc(base.popcnt.i32, *r.urm(0xf3, 0x0f, 0xb8), isap=cfg.use_popcnt)
|
||||
@@ -131,37 +131,37 @@ 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.i32, *r.st(0x89))
|
||||
I32.enc(base.store.i32.i32, *r.stDisp8(0x89))
|
||||
I32.enc(base.store.i32.i32, *r.stDisp32(0x89))
|
||||
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))
|
||||
|
||||
I32.enc(base.istore16.i32.i32, *r.st(0x66, 0x89))
|
||||
I32.enc(base.istore16.i32.i32, *r.stDisp8(0x66, 0x89))
|
||||
I32.enc(base.istore16.i32.i32, *r.stDisp32(0x66, 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))
|
||||
|
||||
I32.enc(base.istore8.i32.i32, *r.st_abcd(0x88))
|
||||
I32.enc(base.istore8.i32.i32, *r.stDisp8_abcd(0x88))
|
||||
I32.enc(base.istore8.i32.i32, *r.stDisp32_abcd(0x88))
|
||||
I32.enc(base.istore8.i32.any, *r.st_abcd(0x88))
|
||||
I32.enc(base.istore8.i32.any, *r.stDisp8_abcd(0x88))
|
||||
I32.enc(base.istore8.i32.any, *r.stDisp32_abcd(0x88))
|
||||
|
||||
I32.enc(base.load.i32.i32, *r.ld(0x8b))
|
||||
I32.enc(base.load.i32.i32, *r.ldDisp8(0x8b))
|
||||
I32.enc(base.load.i32.i32, *r.ldDisp32(0x8b))
|
||||
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))
|
||||
|
||||
I32.enc(base.uload16.i32.i32, *r.ld(0x0f, 0xb7))
|
||||
I32.enc(base.uload16.i32.i32, *r.ldDisp8(0x0f, 0xb7))
|
||||
I32.enc(base.uload16.i32.i32, *r.ldDisp32(0x0f, 0xb7))
|
||||
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))
|
||||
|
||||
I32.enc(base.sload16.i32.i32, *r.ld(0x0f, 0xbf))
|
||||
I32.enc(base.sload16.i32.i32, *r.ldDisp8(0x0f, 0xbf))
|
||||
I32.enc(base.sload16.i32.i32, *r.ldDisp32(0x0f, 0xbf))
|
||||
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))
|
||||
|
||||
I32.enc(base.uload8.i32.i32, *r.ld(0x0f, 0xb6))
|
||||
I32.enc(base.uload8.i32.i32, *r.ldDisp8(0x0f, 0xb6))
|
||||
I32.enc(base.uload8.i32.i32, *r.ldDisp32(0x0f, 0xb6))
|
||||
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))
|
||||
|
||||
I32.enc(base.sload8.i32.i32, *r.ld(0x0f, 0xbe))
|
||||
I32.enc(base.sload8.i32.i32, *r.ldDisp8(0x0f, 0xbe))
|
||||
I32.enc(base.sload8.i32.i32, *r.ldDisp32(0x0f, 0xbe))
|
||||
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))
|
||||
|
||||
#
|
||||
# Call/return
|
||||
|
||||
Reference in New Issue
Block a user