Begin an Intel-specific instruction group.

Add instructions representing Intel's division instructions which use a
numerator that is twice as wide as the denominator and produce both the
quotient and remainder.

Add encodings for the x86_[su]divmodx instructions.
This commit is contained in:
Jakob Stoklund Olesen
2017-07-18 10:09:02 -07:00
parent cf876e492a
commit c4db4c124b
8 changed files with 132 additions and 6 deletions

View File

@@ -6,8 +6,9 @@ Commonly used definitions.
from __future__ import absolute_import
from cdsl.isa import TargetISA, CPUMode
import base.instructions
from . import instructions as x86
ISA = TargetISA('intel', [base.instructions.GROUP])
ISA = TargetISA('intel', [base.instructions.GROUP, x86.GROUP])
# CPU modes for 32-bit and 64-bit operation.
I32 = CPUMode('I32', ISA)

View File

@@ -8,6 +8,7 @@ from base.formats import UnaryImm
from .defs import I32, I64
from . import recipes as r
from . import settings as cfg
from . import instructions as x86
for inst, opc in [
(base.iadd, 0x01),
@@ -28,6 +29,14 @@ I64.enc(base.imul.i64, *r.rrx.rex(0x0f, 0xaf, w=1))
I64.enc(base.imul.i32, *r.rrx.rex(0x0f, 0xaf))
I64.enc(base.imul.i32, *r.rrx(0x0f, 0xaf))
for inst, rrr in [
(x86.sdivmodx, 7),
(x86.udivmodx, 6)]:
I32.enc(inst.i32, *r.div(0xf7, rrr=rrr))
I64.enc(inst.i64, *r.div.rex(0xf7, rrr=rrr, w=1))
I64.enc(inst.i32, *r.div.rex(0xf7, rrr=rrr))
I64.enc(inst.i32, *r.div(0xf7, rrr=rrr))
I32.enc(base.copy.i32, *r.umr(0x89))
I64.enc(base.copy.i64, *r.umr.rex(0x89, w=1))
I64.enc(base.copy.i32, *r.umr.rex(0x89))

View File

@@ -0,0 +1,45 @@
"""
Supplementary instruction definitions for Intel.
This module defines additional instructions that are useful only to the Intel
target ISA.
"""
from cdsl.operands import Operand
from cdsl.instructions import Instruction, InstructionGroup
from base.instructions import iB
GROUP = InstructionGroup("x86", "Intel-specific instruction set")
nlo = Operand('nlo', iB, doc='Low part of numerator')
nhi = Operand('nhi', iB, doc='High part of numerator')
d = Operand('d', iB, doc='Denominator')
q = Operand('q', iB, doc='Quotient')
r = Operand('r', iB, doc='Remainder')
udivmodx = Instruction(
'x86_udivmodx', r"""
Extended unsigned division.
Concatenate the bits in `nhi` and `nlo` to form the numerator.
Interpret the bits as an unsigned number and divide by the unsigned
denominator `d`. Trap when `d` is zero or if the quotient is larger
than the range of the output.
Return both quotient and remainder.
""",
ins=(nlo, nhi, d), outs=(q, r), can_trap=True)
sdivmodx = Instruction(
'x86_sdivmodx', r"""
Extended signed division.
Concatenate the bits in `nhi` and `nlo` to form the numerator.
Interpret the bits as a signed number and divide by the signed
denominator `d`. Trap when `d` is zero or if the quotient is outside
the range of the output.
Return both quotient and remainder.
""",
ins=(nlo, nhi, d), outs=(q, r), can_trap=True)

View File

@@ -6,7 +6,7 @@ from cdsl.isa import EncRecipe
from cdsl.predicates import IsSignedInt, IsEqual
from base.formats import Unary, UnaryImm, Binary, BinaryImm, MultiAry
from base.formats import Call, IndirectCall, Store, Load
from base.formats import RegMove
from base.formats import RegMove, Ternary
from .registers import GPR, ABCD
try:
@@ -239,6 +239,15 @@ rc = TailRecipe(
modrm_r_bits(in_reg0, bits, sink);
''')
# XX /n for division: inputs in %rax, %rdx, r. Outputs in %rax, %rdx.
div = TailRecipe(
'div', Ternary, size=1,
ins=(GPR.rax, GPR.rdx, GPR), outs=(GPR.rax, GPR.rdx),
emit='''
PUT_OP(bits, rex1(in_reg2), sink);
modrm_r_bits(in_reg2, bits, sink);
''')
# XX /n ib with 8-bit immediate sign-extended.
rib = TailRecipe(
'rib', BinaryImm, size=2, ins=GPR, outs=0,