Add encodings for CPU flags instructions.

Branch on flags: brif, brff,
Compare integers to flags: ifcmp
Compare floats to flags: ffcmp
Convert flags to b1: trueif, trueff
This commit is contained in:
Jakob Stoklund Olesen
2017-10-13 16:44:34 -07:00
parent 0f4f663584
commit 5d065c4d8f
7 changed files with 430 additions and 9 deletions

View File

@@ -7,10 +7,11 @@ 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 Trap, Call, IndirectCall, Store, Load
from base.formats import IntCompare, FloatCompare
from base.formats import Ternary, Jump, Branch, FuncAddr
from base.formats import IntCompare, FloatCompare, IntCond, FloatCond
from base.formats import Jump, Branch, BranchInt, BranchFloat
from base.formats import Ternary, FuncAddr
from base.formats import RegMove, RegSpill, RegFill
from .registers import GPR, ABCD, FPR, GPR8, FPR8, StackGPR32, StackFPR32
from .registers import GPR, ABCD, FPR, GPR8, FPR8, FLAG, StackGPR32, StackFPR32
from .defs import supported_floatccs
try:
@@ -250,6 +251,15 @@ class TailRecipe:
assert name == obj.name, "Mismatched TailRecipe name: " + name
def floatccs(iform):
# type: (InstructionFormat) -> PredNode
"""
Return an instruction predicate that checks in `iform.cond` is one of the
directly supported floating point condition codes.
"""
return Or(*(IsEqual(iform.cond, cc) for cc in supported_floatccs))
# A null unary instruction that takes a GPR register. Can be used for identity
# copies and no-op conversions.
null = EncRecipe('null', Unary, size=0, ins=GPR, outs=0, emit='')
@@ -754,6 +764,100 @@ jmpd = TailRecipe(
disp4(destination, func, sink);
''')
brib = TailRecipe(
'brib', BranchInt, size=1, ins=FLAG.eflags, outs=(),
branch_range=8,
emit='''
PUT_OP(bits | icc2opc(cond), BASE_REX, sink);
disp1(destination, func, sink);
''')
brid = TailRecipe(
'brid', BranchInt, size=4, ins=FLAG.eflags, outs=(),
branch_range=32,
emit='''
PUT_OP(bits | icc2opc(cond), BASE_REX, sink);
disp4(destination, func, sink);
''')
brfb = TailRecipe(
'brfb', BranchFloat, size=1, ins=FLAG.eflags, outs=(),
branch_range=8,
instp=floatccs(BranchFloat),
emit='''
PUT_OP(bits | fcc2opc(cond), BASE_REX, sink);
disp1(destination, func, sink);
''')
brfd = TailRecipe(
'brfd', BranchFloat, size=4, ins=FLAG.eflags, outs=(),
branch_range=32,
instp=floatccs(BranchFloat),
emit='''
PUT_OP(bits | fcc2opc(cond), BASE_REX, sink);
disp4(destination, func, sink);
''')
#
# Test flags and set a register.
#
# These setCC instructions only set the low 8 bits, and they can only write
# ABCD registers without a REX prefix.
#
# Other instruction encodings accepting `b1` inputs have the same constraints
# and only look at the low 8 bits of the input register.
#
seti = TailRecipe(
'seti', IntCond, size=1, ins=FLAG.eflags, outs=GPR,
requires_prefix=True,
emit='''
PUT_OP(bits | icc2opc(cond), rex1(out_reg0), sink);
modrm_r_bits(out_reg0, bits, sink);
''')
seti_abcd = TailRecipe(
'seti_abcd', IntCond, size=1, ins=FLAG.eflags, outs=ABCD,
when_prefixed=seti,
emit='''
PUT_OP(bits | icc2opc(cond), rex1(out_reg0), sink);
modrm_r_bits(out_reg0, bits, sink);
''')
setf = TailRecipe(
'setf', FloatCond, size=1, ins=FLAG.eflags, outs=GPR,
requires_prefix=True,
emit='''
PUT_OP(bits | fcc2opc(cond), rex1(out_reg0), sink);
modrm_r_bits(out_reg0, bits, sink);
''')
setf_abcd = TailRecipe(
'setf_abcd', FloatCond, size=1, ins=FLAG.eflags, outs=ABCD,
when_prefixed=setf,
emit='''
PUT_OP(bits | fcc2opc(cond), rex1(out_reg0), sink);
modrm_r_bits(out_reg0, bits, sink);
''')
#
# Compare and set flags.
#
# XX /r, MR form. Compare two GPR registers and set flags.
rcmp = TailRecipe(
'rcmp', Binary, size=1, ins=(GPR, GPR), outs=FLAG.eflags,
emit='''
PUT_OP(bits, rex2(in_reg0, in_reg1), sink);
modrm_rr(in_reg0, in_reg1, sink);
''')
# XX /r, RM form. Compare two FPR registers and set flags.
fcmp = TailRecipe(
'fcmp', Binary, size=1, ins=(FPR, FPR), outs=FLAG.eflags,
emit='''
PUT_OP(bits, rex2(in_reg1, in_reg0), sink);
modrm_rr(in_reg1, in_reg0, sink);
''')
# Test-and-branch.
#
# This recipe represents the macro fusion of a test and a conditional branch.
@@ -926,8 +1030,7 @@ icscc = TailRecipe(
# The omission of a `when_prefixed` alternative is deliberate here.
fcscc = TailRecipe(
'fcscc', FloatCompare, size=1 + 3, ins=(FPR, FPR), outs=ABCD,
instp=Or(*(IsEqual(FloatCompare.cond, cc)
for cc in supported_floatccs)),
instp=floatccs(FloatCompare),
emit='''
// Comparison instruction.
PUT_OP(bits, rex2(in_reg1, in_reg0), sink);