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 02fd83cd5c
commit 306ef2095b
8 changed files with 132 additions and 6 deletions

View File

@@ -271,6 +271,9 @@ class InstDocumenter(sphinx.ext.autodoc.Documenter):
return False return False
def resolve_name(self, modname, parents, path, base): def resolve_name(self, modname, parents, path, base):
if path:
return path.rstrip('.'), [base]
else:
return 'base.instructions', [base] return 'base.instructions', [base]
def format_signature(self): def format_signature(self):

View File

@@ -775,15 +775,31 @@ the target ISA.
.. autoinst:: isplit .. autoinst:: isplit
.. autoinst:: iconcat .. autoinst:: iconcat
Base instruction group ISA-specific instructions
====================== =========================
Target ISAs can define supplemental instructions that do not make sense to
support generally.
Intel
-----
Instructions that can only be used by the Intel target ISA.
.. autoinst:: isa.intel.instructions.sdivmodx
.. autoinst:: isa.intel.instructions.udivmodx
Instruction groups
==================
All of the shared instructions are part of the :instgroup:`base` instruction All of the shared instructions are part of the :instgroup:`base` instruction
group. group.
.. autoinstgroup:: base.instructions.GROUP .. autoinstgroup:: base.instructions.GROUP
Target ISAs may define further instructions in their own instruction groups. Target ISAs may define further instructions in their own instruction groups:
.. autoinstgroup:: isa.intel.instructions.GROUP
Implementation limits Implementation limits
===================== =====================

View File

@@ -112,6 +112,19 @@ ebb0:
; asm: imull %ecx, %esi ; asm: imull %ecx, %esi
[-,%rsi] v51 = imul v2, v1 ; bin: 0f af f1 [-,%rsi] v51 = imul v2, v1 ; bin: 0f af f1
; asm: movl $1, %eax
[-,%rax] v52 = iconst.i32 1 ; bin: b8 00000001
; asm: movl $2, %edx
[-,%rdx] v53 = iconst.i32 2 ; bin: ba 00000002
; asm: idivl %ecx
[-,%rax,%rdx] v54, v55 = x86_sdivmodx v52, v53, v1 ; bin: f7 f9
; asm: idivl %esi
[-,%rax,%rdx] v56, v57 = x86_sdivmodx v52, v53, v2 ; bin: f7 fe
; asm: divl %ecx
[-,%rax,%rdx] v58, v59 = x86_udivmodx v52, v53, v1 ; bin: f7 f1
; asm: divl %esi
[-,%rax,%rdx] v60, v61 = x86_udivmodx v52, v53, v2 ; bin: f7 f6
; Register copies. ; Register copies.
; asm: movl %esi, %ecx ; asm: movl %esi, %ecx

View File

@@ -154,6 +154,21 @@ ebb0:
; asm: imulq %rcx, %r10 ; asm: imulq %rcx, %r10
[-,%r10] v122 = imul v3, v1 ; bin: 4c 0f af d1 [-,%r10] v122 = imul v3, v1 ; bin: 4c 0f af d1
[-,%rax] v130 = iconst.i64 1
[-,%rdx] v131 = iconst.i64 2
; asm: idivq %rcx
[-,%rax,%rdx] v132, v133 = x86_sdivmodx v130, v131, v1 ; bin: 48 f7 f9
; asm: idivq %rsi
[-,%rax,%rdx] v134, v135 = x86_sdivmodx v130, v131, v2 ; bin: 48 f7 fe
; asm: idivq %r10
[-,%rax,%rdx] v136, v137 = x86_sdivmodx v130, v131, v3 ; bin: 49 f7 fa
; asm: divq %rcx
[-,%rax,%rdx] v138, v139 = x86_udivmodx v130, v131, v1 ; bin: 48 f7 f1
; asm: divq %rsi
[-,%rax,%rdx] v140, v141 = x86_udivmodx v130, v131, v2 ; bin: 48 f7 f6
; asm: divq %r10
[-,%rax,%rdx] v142, v143 = x86_udivmodx v130, v131, v3 ; bin: 49 f7 f2
; Bit-counting instructions. ; Bit-counting instructions.
; asm: popcntq %rsi, %rcx ; asm: popcntq %rsi, %rcx
@@ -331,6 +346,21 @@ ebb0:
; asm: imull %ecx, %r10d ; asm: imull %ecx, %r10d
[-,%r10] v122 = imul v3, v1 ; bin: 44 0f af d1 [-,%r10] v122 = imul v3, v1 ; bin: 44 0f af d1
[-,%rax] v130 = iconst.i32 1
[-,%rdx] v131 = iconst.i32 2
; asm: idivl %rcx
[-,%rax,%rdx] v132, v133 = x86_sdivmodx v130, v131, v1 ; bin: 40 f7 f9
; asm: idivl %rsi
[-,%rax,%rdx] v134, v135 = x86_sdivmodx v130, v131, v2 ; bin: 40 f7 fe
; asm: idivl %r10d
[-,%rax,%rdx] v136, v137 = x86_sdivmodx v130, v131, v3 ; bin: 41 f7 fa
; asm: divl %rcx
[-,%rax,%rdx] v138, v139 = x86_udivmodx v130, v131, v1 ; bin: 40 f7 f1
; asm: divl %rsi
[-,%rax,%rdx] v140, v141 = x86_udivmodx v130, v131, v2 ; bin: 40 f7 f6
; asm: divl %r10d
[-,%rax,%rdx] v142, v143 = x86_udivmodx v130, v131, v3 ; bin: 41 f7 f2
; Bit-counting instructions. ; Bit-counting instructions.
; asm: popcntl %esi, %ecx ; asm: popcntl %esi, %ecx

View File

@@ -6,8 +6,9 @@ Commonly used definitions.
from __future__ import absolute_import from __future__ import absolute_import
from cdsl.isa import TargetISA, CPUMode from cdsl.isa import TargetISA, CPUMode
import base.instructions 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. # CPU modes for 32-bit and 64-bit operation.
I32 = CPUMode('I32', ISA) I32 = CPUMode('I32', ISA)

View File

@@ -8,6 +8,7 @@ from base.formats import UnaryImm
from .defs import I32, I64 from .defs import I32, I64
from . import recipes as r from . import recipes as r
from . import settings as cfg from . import settings as cfg
from . import instructions as x86
for inst, opc in [ for inst, opc in [
(base.iadd, 0x01), (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.rex(0x0f, 0xaf))
I64.enc(base.imul.i32, *r.rrx(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)) I32.enc(base.copy.i32, *r.umr(0x89))
I64.enc(base.copy.i64, *r.umr.rex(0x89, w=1)) I64.enc(base.copy.i64, *r.umr.rex(0x89, w=1))
I64.enc(base.copy.i32, *r.umr.rex(0x89)) 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 cdsl.predicates import IsSignedInt, IsEqual
from base.formats import Unary, UnaryImm, Binary, BinaryImm, MultiAry from base.formats import Unary, UnaryImm, Binary, BinaryImm, MultiAry
from base.formats import Call, IndirectCall, Store, Load from base.formats import Call, IndirectCall, Store, Load
from base.formats import RegMove from base.formats import RegMove, Ternary
from .registers import GPR, ABCD from .registers import GPR, ABCD
try: try:
@@ -239,6 +239,15 @@ rc = TailRecipe(
modrm_r_bits(in_reg0, bits, sink); 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. # XX /n ib with 8-bit immediate sign-extended.
rib = TailRecipe( rib = TailRecipe(
'rib', BinaryImm, size=2, ins=GPR, outs=0, 'rib', BinaryImm, size=2, ins=GPR, outs=0,