Adapt intel to be able to correctly choose compressed instruction encodings: create a register class to identify the lower 8 registers, omit unnecessary REX prefixes, and fix the tests
This commit is contained in:
committed by
Jakob Stoklund Olesen
parent
3b66c0be40
commit
b003605132
@@ -15,7 +15,7 @@ runif() {
|
||||
runif flake8 .
|
||||
|
||||
# Type checking.
|
||||
runif mypy --py2 build.py
|
||||
runif python3 -m mypy --py2 build.py
|
||||
|
||||
# Python unit tests.
|
||||
runif python -m unittest discover
|
||||
|
||||
@@ -91,6 +91,12 @@ def enc_flt(inst, recipe, *args, **kwargs):
|
||||
I64.enc(inst, *recipe(*args, **kwargs))
|
||||
|
||||
|
||||
def enc_i64(inst, recipe, *args, **kwargs):
|
||||
# type: (MaybeBoundInst, r.TailRecipe, *int, **int) -> None
|
||||
I64.enc(inst, *recipe.rex(*args, **kwargs))
|
||||
I64.enc(inst, *recipe(*args, **kwargs))
|
||||
|
||||
|
||||
for inst, opc in [
|
||||
(base.iadd, 0x01),
|
||||
(base.isub, 0x29),
|
||||
@@ -175,9 +181,9 @@ 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)
|
||||
|
||||
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_i64(base.istore32.i64.any, r.st, 0x89)
|
||||
enc_i64(base.istore32.i64.any, r.stDisp8, 0x89)
|
||||
enc_i64(base.istore32.i64.any, r.stDisp32, 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)
|
||||
@@ -187,21 +193,24 @@ enc_i32_i64_ld_st(base.istore16, False, r.stDisp32, 0x66, 0x89)
|
||||
# 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_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_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_abcd(0x88))
|
||||
I64.enc(base.istore8.i64.any, *r.stDisp32.rex(0x88))
|
||||
|
||||
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)
|
||||
|
||||
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))
|
||||
enc_i64(base.uload32.i64, r.ld, 0x8b)
|
||||
enc_i64(base.uload32.i64, r.ldDisp8, 0x8b)
|
||||
enc_i64(base.uload32.i64, r.ldDisp32, 0x8b)
|
||||
|
||||
I64.enc(base.sload32.i64, *r.ld.rex(0x63, w=1))
|
||||
I64.enc(base.sload32.i64, *r.ldDisp8.rex(0x63, w=1))
|
||||
@@ -301,7 +310,7 @@ enc_i32_i64(base.icmp, r.icscc, 0x39)
|
||||
# This assumes that b1 is represented as an 8-bit low register with the value 0
|
||||
# or 1.
|
||||
I32.enc(base.bint.i32.b1, *r.urm_abcd(0x0f, 0xb6))
|
||||
I64.enc(base.bint.i64.b1, *r.urm.rex(0x0f, 0xb6, w=1))
|
||||
I64.enc(base.bint.i64.b1, *r.urm.rex(0x0f, 0xb6)) # zext to i64 implicit.
|
||||
I64.enc(base.bint.i64.b1, *r.urm_abcd(0x0f, 0xb6)) # zext to i64 implicit.
|
||||
I64.enc(base.bint.i32.b1, *r.urm.rex(0x0f, 0xb6))
|
||||
I64.enc(base.bint.i32.b1, *r.urm_abcd(0x0f, 0xb6))
|
||||
|
||||
@@ -8,10 +8,10 @@ from base.formats import Unary, UnaryImm, Binary, BinaryImm, MultiAry
|
||||
from base.formats import Trap, Call, IndirectCall, Store, Load
|
||||
from base.formats import IntCompare
|
||||
from base.formats import RegMove, Ternary, Jump, Branch, FuncAddr
|
||||
from .registers import GPR, ABCD, FPR
|
||||
from .registers import GPR, ABCD, FPR, GPR8, FPR8
|
||||
|
||||
try:
|
||||
from typing import Tuple, Dict # noqa
|
||||
from typing import Tuple, Dict, Sequence # noqa
|
||||
from cdsl.instructions import InstructionFormat # noqa
|
||||
from cdsl.isa import ConstraintSeq, BranchRange, PredNode, OperandConstraint # noqa
|
||||
except ImportError:
|
||||
@@ -95,6 +95,15 @@ def replace_put_op(emit, prefix):
|
||||
return emit.replace('PUT_OP', 'put_' + prefix.lower())
|
||||
|
||||
|
||||
def map_regs(
|
||||
regs, # type: Sequence[OperandConstraint]
|
||||
from_class, # type: OperandConstraint
|
||||
to_class # type: OperandConstraint
|
||||
):
|
||||
# type: (...) -> Sequence[OperandConstraint]
|
||||
return tuple(to_class if (reg is from_class) else reg for reg in regs)
|
||||
|
||||
|
||||
class TailRecipe:
|
||||
"""
|
||||
Generate encoding recipes on demand.
|
||||
@@ -150,7 +159,7 @@ class TailRecipe:
|
||||
w = kwargs.get('w', 0)
|
||||
name, bits = decode_ops(ops, rrr, w)
|
||||
if name not in self.recipes:
|
||||
self.recipes[name] = EncRecipe(
|
||||
recipe = EncRecipe(
|
||||
name + self.name,
|
||||
self.format,
|
||||
len(ops) + self.size,
|
||||
@@ -160,6 +169,13 @@ class TailRecipe:
|
||||
instp=self.instp,
|
||||
isap=self.isap,
|
||||
emit=replace_put_op(self.emit, name))
|
||||
|
||||
recipe.ins = map_regs(recipe.ins, GPR, GPR8)
|
||||
recipe.ins = map_regs(recipe.ins, FPR, FPR8)
|
||||
recipe.outs = map_regs(recipe.outs, GPR, GPR8)
|
||||
recipe.outs = map_regs(recipe.outs, FPR, FPR8)
|
||||
|
||||
self.recipes[name] = recipe
|
||||
return (self.recipes[name], bits)
|
||||
|
||||
def rex(self, *ops, **kwargs):
|
||||
|
||||
@@ -39,7 +39,9 @@ FloatRegs = RegBank(
|
||||
units=16, prefix='xmm')
|
||||
|
||||
GPR = RegClass(IntRegs)
|
||||
GPR8 = GPR[0:8]
|
||||
ABCD = GPR[0:4]
|
||||
FPR = RegClass(FloatRegs)
|
||||
FPR8 = FPR[0:8]
|
||||
|
||||
RegClass.extract_names(globals())
|
||||
|
||||
Reference in New Issue
Block a user