Eliminate the ABCD register class constaint in REX encodings.

Some REX-less encodings require an ABCD input because they are looking
at 8-bit registers. This constraint doesn't apply with a REX prefix
where the low 8 bits of all registers are addressable.
This commit is contained in:
Jakob Stoklund Olesen
2017-09-29 15:29:25 -07:00
parent 51a6901a7f
commit c82e68efea
2 changed files with 59 additions and 11 deletions

View File

@@ -104,4 +104,37 @@ ebb1(v31: i64):
return v31 return v31
} }
function #0000001a(i64 vmctx [%r14]) -> i64 [%rax] spiderwasm {
gv0 = vmctx+48
sig0 = (i32 [%rdi], i64 [%rsi], i64 vmctx [%r14], i64 sigid [%rbx]) -> i64 [%rax] spiderwasm
ebb0(v0: i64):
v1 = iconst.i32 32
v2 = iconst.i64 64
v3 = iconst.i32 9
v4 = iconst.i64 1063
v5 = iadd_imm v0, 48
v6 = load.i32 v5
v7 = icmp uge v3, v6
; If we're unlucky, there are no ABCD registers available for v7 at this branch.
brz v7, ebb2
trap oob
ebb2:
v8 = load.i64 v5+8
v9 = uextend.i64 v3
v16 = iconst.i64 16
v10 = imul v9, v16
v11 = iadd v8, v10
v12 = load.i64 v11
brnz v12, ebb3
trap icall_null
ebb3:
v13 = load.i64 v11+8
v14 = call_indirect.i64 sig0, v12(v1, v2, v13, v4)
jump ebb1(v14)
ebb1(v15: i64):
return v15
}

View File

@@ -4,6 +4,7 @@ Intel Encoding recipes.
from __future__ import absolute_import from __future__ import absolute_import
from cdsl.isa import EncRecipe from cdsl.isa import EncRecipe
from cdsl.predicates import IsSignedInt, IsEqual, Or from cdsl.predicates import IsSignedInt, IsEqual, Or
from cdsl.registers import RegClass
from base.formats import Unary, UnaryImm, Binary, BinaryImm, MultiAry from base.formats import Unary, UnaryImm, Binary, BinaryImm, MultiAry
from base.formats import Trap, Call, IndirectCall, Store, Load from base.formats import Trap, Call, IndirectCall, Store, Load
from base.formats import IntCompare, FloatCompare from base.formats import IntCompare, FloatCompare
@@ -96,13 +97,26 @@ def replace_put_op(emit, prefix):
return emit.replace('PUT_OP', 'put_' + prefix.lower()) return emit.replace('PUT_OP', 'put_' + prefix.lower())
# Register class mapping for no-REX instructions.
NOREX_MAP = {
GPR: GPR8,
FPR: FPR8
}
# Register class mapping for REX instructions. The ABCD constraint no longer
# applies.
REX_MAP = {
ABCD: GPR
}
def map_regs( def map_regs(
regs, # type: Sequence[OperandConstraint] regs, # type: Sequence[OperandConstraint]
from_class, # type: OperandConstraint mapping # type: Dict[RegClass, RegClass]
to_class # type: OperandConstraint
): ):
# type: (...) -> Sequence[OperandConstraint] # type: (...) -> Sequence[OperandConstraint]
return tuple(to_class if (reg is from_class) else reg for reg in regs) return tuple(mapping.get(rc, rc) if isinstance(rc, RegClass) else rc
for rc in regs)
class TailRecipe: class TailRecipe:
@@ -178,11 +192,8 @@ class TailRecipe:
isap=self.isap, isap=self.isap,
emit=replace_put_op(self.emit, name)) emit=replace_put_op(self.emit, name))
recipe.ins = map_regs(recipe.ins, GPR, GPR8) recipe.ins = map_regs(recipe.ins, NOREX_MAP)
recipe.ins = map_regs(recipe.ins, FPR, FPR8) recipe.outs = map_regs(recipe.outs, NOREX_MAP)
recipe.outs = map_regs(recipe.outs, GPR, GPR8)
recipe.outs = map_regs(recipe.outs, FPR, FPR8)
self.recipes[name] = recipe self.recipes[name] = recipe
return (self.recipes[name], bits) return (self.recipes[name], bits)
@@ -208,7 +219,7 @@ class TailRecipe:
branch_range = (size, self.branch_range) branch_range = (size, self.branch_range)
if name not in self.recipes: if name not in self.recipes:
self.recipes[name] = EncRecipe( recipe = EncRecipe(
name + self.name, name + self.name,
self.format, self.format,
size, size,
@@ -218,6 +229,10 @@ class TailRecipe:
instp=self.instp, instp=self.instp,
isap=self.isap, isap=self.isap,
emit=replace_put_op(self.emit, name)) emit=replace_put_op(self.emit, name))
recipe.ins = map_regs(recipe.ins, REX_MAP)
recipe.outs = map_regs(recipe.outs, REX_MAP)
self.recipes[name] = recipe
return (self.recipes[name], bits) return (self.recipes[name], bits)
@staticmethod @staticmethod
@@ -731,7 +746,7 @@ t8jccb_abcd = TailRecipe(
branch_range=8, branch_range=8,
emit=''' emit='''
// test8 r, r. // test8 r, r.
PUT_OP(0x84, rex2(in_reg0, in_reg0), sink); PUT_OP((bits & 0xff00) | 0x84, rex2(in_reg0, in_reg0), sink);
modrm_rr(in_reg0, in_reg0, sink); modrm_rr(in_reg0, in_reg0, sink);
// Jcc instruction. // Jcc instruction.
sink.put1(bits as u8); sink.put1(bits as u8);
@@ -743,7 +758,7 @@ t8jccd_abcd = TailRecipe(
branch_range=32, branch_range=32,
emit=''' emit='''
// test8 r, r. // test8 r, r.
PUT_OP(0x84, rex2(in_reg0, in_reg0), sink); PUT_OP((bits & 0xff00) | 0x84, rex2(in_reg0, in_reg0), sink);
modrm_rr(in_reg0, in_reg0, sink); modrm_rr(in_reg0, in_reg0, sink);
// Jcc instruction. // Jcc instruction.
sink.put1(0x0f); sink.put1(0x0f);