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:
@@ -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
|
||||||
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
Reference in New Issue
Block a user