X86: Total overhaul of the division instructions and microops.
--HG-- extra : convert_revision : 303ea45f69f7805361ad877fe6bb43fbc3dfd7a6
This commit is contained in:
parent
0f57b407a3
commit
f7b6230d99
|
@ -234,20 +234,70 @@ def macroop IMUL_R_P_I
|
||||||
|
|
||||||
def macroop DIV_B_R
|
def macroop DIV_B_R
|
||||||
{
|
{
|
||||||
div1 rax, rax, reg
|
# Do the initial part of the division
|
||||||
|
div1 rsi, reg, dataSize=1
|
||||||
|
|
||||||
|
#These are split out so we can initialize the number of bits in the
|
||||||
|
#second register
|
||||||
|
div2i t1, rax, 8, dataSize=1
|
||||||
|
div2 t1, rax, t1, dataSize=1
|
||||||
|
|
||||||
|
#Loop until we're out of bits to shift in
|
||||||
|
divLoopTop:
|
||||||
|
div2 t1, rax, t1, dataSize=1
|
||||||
|
div2 t1, rax, t1, flags=(EZF,), dataSize=1
|
||||||
|
bri t0, label("divLoopTop"), flags=(nCEZF,)
|
||||||
|
|
||||||
|
#Unload the answer
|
||||||
|
divq rax, dataSize=1
|
||||||
|
divr rsi, dataSize=1
|
||||||
};
|
};
|
||||||
|
|
||||||
def macroop DIV_B_M
|
def macroop DIV_B_M
|
||||||
{
|
{
|
||||||
ld t1, seg, sib, disp
|
ld t2, seg, sib, disp
|
||||||
div1 rax, rax, t1
|
|
||||||
|
# Do the initial part of the division
|
||||||
|
div1 rsi, t2, dataSize=1
|
||||||
|
|
||||||
|
#These are split out so we can initialize the number of bits in the
|
||||||
|
#second register
|
||||||
|
div2i t1, rax, 8, dataSize=1
|
||||||
|
div2 t1, rax, t1, dataSize=1
|
||||||
|
|
||||||
|
#Loop until we're out of bits to shift in
|
||||||
|
divLoopTop:
|
||||||
|
div2 t1, rax, t1, dataSize=1
|
||||||
|
div2 t1, rax, t1, flags=(EZF,), dataSize=1
|
||||||
|
bri t0, label("divLoopTop"), flags=(nCEZF,)
|
||||||
|
|
||||||
|
#Unload the answer
|
||||||
|
divq rax, dataSize=1
|
||||||
|
divr rsi, dataSize=1
|
||||||
};
|
};
|
||||||
|
|
||||||
def macroop DIV_B_P
|
def macroop DIV_B_P
|
||||||
{
|
{
|
||||||
rdip t7
|
rdip t7
|
||||||
ld t1, seg, riprel, disp
|
ld t2, seg, riprel, disp
|
||||||
div1 rax, rax, t1
|
|
||||||
|
# Do the initial part of the division
|
||||||
|
div1 rsi, t2, dataSize=1
|
||||||
|
|
||||||
|
#These are split out so we can initialize the number of bits in the
|
||||||
|
#second register
|
||||||
|
div2i t1, rax, 8, dataSize=1
|
||||||
|
div2 t1, rax, t1, dataSize=1
|
||||||
|
|
||||||
|
#Loop until we're out of bits to shift in
|
||||||
|
divLoopTop:
|
||||||
|
div2 t1, rax, t1, dataSize=1
|
||||||
|
div2 t1, rax, t1, flags=(EZF,), dataSize=1
|
||||||
|
bri t0, label("divLoopTop"), flags=(nCEZF,)
|
||||||
|
|
||||||
|
#Unload the answer
|
||||||
|
divq rax, dataSize=1
|
||||||
|
divr rsi, dataSize=1
|
||||||
};
|
};
|
||||||
|
|
||||||
#
|
#
|
||||||
|
@ -256,24 +306,301 @@ def macroop DIV_B_P
|
||||||
|
|
||||||
def macroop DIV_R
|
def macroop DIV_R
|
||||||
{
|
{
|
||||||
divr t1, rax, reg
|
# Do the initial part of the division
|
||||||
divq rax, rax, reg
|
div1 rdx, reg
|
||||||
mov rdx, rdx, t1
|
|
||||||
|
#These are split out so we can initialize the number of bits in the
|
||||||
|
#second register
|
||||||
|
div2i t1, rax, "env.dataSize * 8"
|
||||||
|
div2 t1, rax, t1
|
||||||
|
|
||||||
|
#Loop until we're out of bits to shift in
|
||||||
|
#The amount of unrolling here could stand some tuning
|
||||||
|
divLoopTop:
|
||||||
|
div2 t1, rax, t1
|
||||||
|
div2 t1, rax, t1
|
||||||
|
div2 t1, rax, t1
|
||||||
|
div2 t1, rax, t1, flags=(EZF,)
|
||||||
|
bri t0, label("divLoopTop"), flags=(nCEZF,)
|
||||||
|
|
||||||
|
#Unload the answer
|
||||||
|
divq rax
|
||||||
|
divr rdx
|
||||||
};
|
};
|
||||||
|
|
||||||
def macroop DIV_M
|
def macroop DIV_M
|
||||||
{
|
{
|
||||||
ld t1, seg, sib, disp
|
ld t2, seg, sib, disp
|
||||||
divr rdx, rax, t1
|
|
||||||
divq rax, rax, t1
|
# Do the initial part of the division
|
||||||
|
div1 rdx, t2
|
||||||
|
|
||||||
|
#These are split out so we can initialize the number of bits in the
|
||||||
|
#second register
|
||||||
|
div2i t1, rax, "env.dataSize * 8"
|
||||||
|
div2 t1, rax, t1
|
||||||
|
|
||||||
|
#Loop until we're out of bits to shift in
|
||||||
|
#The amount of unrolling here could stand some tuning
|
||||||
|
divLoopTop:
|
||||||
|
div2 t1, rax, t1
|
||||||
|
div2 t1, rax, t1
|
||||||
|
div2 t1, rax, t1
|
||||||
|
div2 t1, rax, t1, flags=(EZF,)
|
||||||
|
bri t0, label("divLoopTop"), flags=(nCEZF,)
|
||||||
|
|
||||||
|
#Unload the answer
|
||||||
|
divq rax
|
||||||
|
divr rdx
|
||||||
};
|
};
|
||||||
|
|
||||||
def macroop DIV_P
|
def macroop DIV_P
|
||||||
{
|
{
|
||||||
rdip t7
|
rdip t7
|
||||||
ld t1, seg, riprel, disp
|
ld t2, seg, riprel, disp
|
||||||
divr rdx, rax, t1
|
|
||||||
divq rax, rax, t1
|
# Do the initial part of the division
|
||||||
|
div1 rdx, t2
|
||||||
|
|
||||||
|
#These are split out so we can initialize the number of bits in the
|
||||||
|
#second register
|
||||||
|
div2i t1, rax, "env.dataSize * 8"
|
||||||
|
div2 t1, rax, t1
|
||||||
|
|
||||||
|
#Loop until we're out of bits to shift in
|
||||||
|
#The amount of unrolling here could stand some tuning
|
||||||
|
divLoopTop:
|
||||||
|
div2 t1, rax, t1
|
||||||
|
div2 t1, rax, t1
|
||||||
|
div2 t1, rax, t1
|
||||||
|
div2 t1, rax, t1, flags=(EZF,)
|
||||||
|
bri t0, label("divLoopTop"), flags=(nCEZF,)
|
||||||
|
|
||||||
|
#Unload the answer
|
||||||
|
divq rax
|
||||||
|
divr rdx
|
||||||
|
};
|
||||||
|
|
||||||
|
#
|
||||||
|
# One byte version of signed division
|
||||||
|
#
|
||||||
|
|
||||||
|
def macroop IDIV_B_R
|
||||||
|
{
|
||||||
|
# Negate dividend
|
||||||
|
sub t1, t0, rax, flags=(ECF,), dataSize=1
|
||||||
|
ruflag t4, 3
|
||||||
|
sub t2, t0, rsi, dataSize=1
|
||||||
|
sub t2, t2, t4
|
||||||
|
|
||||||
|
#Find the sign of the divisor
|
||||||
|
#FIXME!!! This depends on shifts setting the carry flag correctly.
|
||||||
|
slli t0, reg, 1, flags=(ECF,), dataSize=1
|
||||||
|
|
||||||
|
# Negate divisor
|
||||||
|
sub t3, t0, reg, dataSize=1
|
||||||
|
# Put the divisor's absolute value into t3
|
||||||
|
mov t3, t3, reg, flags=(nCECF,), dataSize=1
|
||||||
|
|
||||||
|
#Find the sign of the dividend
|
||||||
|
#FIXME!!! This depends on shifts setting the carry flag correctly.
|
||||||
|
slli t0, rsi, 1, flags=(ECF,), dataSize=1
|
||||||
|
|
||||||
|
# Put the dividend's absolute value into t1 and t2
|
||||||
|
mov t1, t1, rax, flags=(nCECF,), dataSize=1
|
||||||
|
mov t2, t2, rsi, flags=(nCECF,), dataSize=1
|
||||||
|
|
||||||
|
# Do the initial part of the division
|
||||||
|
div1 t2, t3, dataSize=1
|
||||||
|
|
||||||
|
#These are split out so we can initialize the number of bits in the
|
||||||
|
#second register
|
||||||
|
div2i t4, t1, 8, dataSize=1
|
||||||
|
div2 t4, t1, t4, dataSize=1
|
||||||
|
|
||||||
|
#Loop until we're out of bits to shift in
|
||||||
|
divLoopTop:
|
||||||
|
div2 t4, t1, t4, dataSize=1
|
||||||
|
div2 t4, t1, t4, flags=(EZF,), dataSize=1
|
||||||
|
bri t0, label("divLoopTop"), flags=(nCEZF,)
|
||||||
|
|
||||||
|
#Unload the answer
|
||||||
|
divq t5, dataSize=1
|
||||||
|
divr t6, dataSize=1
|
||||||
|
|
||||||
|
# Fix up signs. The sign of the dividend is still lying around in ECF.
|
||||||
|
# The sign of the remainder, ah, is the same as the dividend. The sign
|
||||||
|
# of the quotient is negated if the signs of the divisor and dividend
|
||||||
|
# were different.
|
||||||
|
|
||||||
|
# Negate the remainder
|
||||||
|
sub t4, t0, t6, dataSize=1
|
||||||
|
# If the dividend was negitive, put the negated remainder in rsi.
|
||||||
|
mov rsi, rsi, t4, (CECF,), dataSize=1
|
||||||
|
# Otherwise put the regular remainder in rsi.
|
||||||
|
mov rsi, rsi, t6, (nCECF,), dataSize=1
|
||||||
|
|
||||||
|
# Negate the quotient.
|
||||||
|
sub t4, t0, t5, dataSize=1
|
||||||
|
# If the dividend was negative, start using the negated quotient
|
||||||
|
mov t5, t5, t4, (CECF,), dataSize=1
|
||||||
|
|
||||||
|
# Check the sign of the divisor
|
||||||
|
slli t0, t3, 1, flags=(ECF,), dataSize=1
|
||||||
|
|
||||||
|
# Negate the (possibly already negated) quotient
|
||||||
|
sub t4, t0, t5, dataSize=1
|
||||||
|
# If the divisor was negative, put the negated quotient in rax.
|
||||||
|
mov rax, rax, t4, (CECF,), dataSize=1
|
||||||
|
# Otherwise put the one that wasn't negated (at least here) in rax.
|
||||||
|
mov rax, rax, t5, (nCECF,), dataSize=1
|
||||||
|
};
|
||||||
|
|
||||||
|
def macroop IDIV_B_M
|
||||||
|
{
|
||||||
|
# Negate dividend
|
||||||
|
sub t1, t0, rax, flags=(ECF,), dataSize=1
|
||||||
|
ruflag t4, 3
|
||||||
|
sub t2, t0, rsi, dataSize=1
|
||||||
|
sub t2, t2, t4
|
||||||
|
|
||||||
|
ld t3, seg, sib, disp
|
||||||
|
|
||||||
|
#Find the sign of the divisor
|
||||||
|
#FIXME!!! This depends on shifts setting the carry flag correctly.
|
||||||
|
slli t0, t3, 1, flags=(ECF,), dataSize=1
|
||||||
|
|
||||||
|
# Negate divisor
|
||||||
|
sub t4, t0, t3, dataSize=1
|
||||||
|
# Put the divisor's absolute value into t3
|
||||||
|
mov t3, t3, t4, flags=(CECF,), dataSize=1
|
||||||
|
|
||||||
|
#Find the sign of the dividend
|
||||||
|
#FIXME!!! This depends on shifts setting the carry flag correctly.
|
||||||
|
slli t0, rsi, 1, flags=(ECF,), dataSize=1
|
||||||
|
|
||||||
|
# Put the dividend's absolute value into t1 and t2
|
||||||
|
mov t1, t1, rax, flags=(nCECF,), dataSize=1
|
||||||
|
mov t2, t2, rsi, flags=(nCECF,), dataSize=1
|
||||||
|
|
||||||
|
# Do the initial part of the division
|
||||||
|
div1 t2, t3, dataSize=1
|
||||||
|
|
||||||
|
#These are split out so we can initialize the number of bits in the
|
||||||
|
#second register
|
||||||
|
div2i t4, t1, 8, dataSize=1
|
||||||
|
div2 t4, t1, t4, dataSize=1
|
||||||
|
|
||||||
|
#Loop until we're out of bits to shift in
|
||||||
|
divLoopTop:
|
||||||
|
div2 t4, t1, t4, dataSize=1
|
||||||
|
div2 t4, t1, t4, flags=(EZF,), dataSize=1
|
||||||
|
bri t0, label("divLoopTop"), flags=(nCEZF,)
|
||||||
|
|
||||||
|
#Unload the answer
|
||||||
|
divq t5, dataSize=1
|
||||||
|
divr t6, dataSize=1
|
||||||
|
|
||||||
|
# Fix up signs. The sign of the dividend is still lying around in ECF.
|
||||||
|
# The sign of the remainder, ah, is the same as the dividend. The sign
|
||||||
|
# of the quotient is negated if the signs of the divisor and dividend
|
||||||
|
# were different.
|
||||||
|
|
||||||
|
# Negate the remainder
|
||||||
|
sub t4, t0, t6, dataSize=1
|
||||||
|
# If the dividend was negitive, put the negated remainder in rsi.
|
||||||
|
mov rsi, rsi, t4, (CECF,), dataSize=1
|
||||||
|
# Otherwise put the regular remainder in rsi.
|
||||||
|
mov rsi, rsi, t6, (nCECF,), dataSize=1
|
||||||
|
|
||||||
|
# Negate the quotient.
|
||||||
|
sub t4, t0, t5, dataSize=1
|
||||||
|
# If the dividend was negative, start using the negated quotient
|
||||||
|
mov t5, t5, t4, (CECF,), dataSize=1
|
||||||
|
|
||||||
|
# Check the sign of the divisor
|
||||||
|
slli t0, t3, 1, flags=(ECF,), dataSize=1
|
||||||
|
|
||||||
|
# Negate the (possibly already negated) quotient
|
||||||
|
sub t4, t0, t5, dataSize=1
|
||||||
|
# If the divisor was negative, put the negated quotient in rax.
|
||||||
|
mov rax, rax, t4, (CECF,), dataSize=1
|
||||||
|
# Otherwise put the one that wasn't negated (at least here) in rax.
|
||||||
|
mov rax, rax, t5, (nCECF,), dataSize=1
|
||||||
|
};
|
||||||
|
|
||||||
|
def macroop IDIV_B_P
|
||||||
|
{
|
||||||
|
# Negate dividend
|
||||||
|
sub t1, t0, rax, flags=(ECF,), dataSize=1
|
||||||
|
ruflag t4, 3
|
||||||
|
sub t2, t0, rsi, dataSize=1
|
||||||
|
sub t2, t2, t4
|
||||||
|
|
||||||
|
rdip t7
|
||||||
|
ld t3, seg, riprel, disp
|
||||||
|
|
||||||
|
#Find the sign of the divisor
|
||||||
|
#FIXME!!! This depends on shifts setting the carry flag correctly.
|
||||||
|
slli t0, t3, 1, flags=(ECF,), dataSize=1
|
||||||
|
|
||||||
|
# Negate divisor
|
||||||
|
sub t4, t0, t3, dataSize=1
|
||||||
|
# Put the divisor's absolute value into t3
|
||||||
|
mov t3, t3, t4, flags=(CECF,), dataSize=1
|
||||||
|
|
||||||
|
#Find the sign of the dividend
|
||||||
|
#FIXME!!! This depends on shifts setting the carry flag correctly.
|
||||||
|
slli t0, rsi, 1, flags=(ECF,), dataSize=1
|
||||||
|
|
||||||
|
# Put the dividend's absolute value into t1 and t2
|
||||||
|
mov t1, t1, rax, flags=(nCECF,), dataSize=1
|
||||||
|
mov t2, t2, rsi, flags=(nCECF,), dataSize=1
|
||||||
|
|
||||||
|
# Do the initial part of the division
|
||||||
|
div1 t2, t3, dataSize=1
|
||||||
|
|
||||||
|
#These are split out so we can initialize the number of bits in the
|
||||||
|
#second register
|
||||||
|
div2i t4, t1, 8, dataSize=1
|
||||||
|
div2 t4, t1, t4, dataSize=1
|
||||||
|
|
||||||
|
#Loop until we're out of bits to shift in
|
||||||
|
divLoopTop:
|
||||||
|
div2 t4, t1, t4, dataSize=1
|
||||||
|
div2 t4, t1, t4, flags=(EZF,), dataSize=1
|
||||||
|
bri t0, label("divLoopTop"), flags=(nCEZF,)
|
||||||
|
|
||||||
|
#Unload the answer
|
||||||
|
divq t5, dataSize=1
|
||||||
|
divr t6, dataSize=1
|
||||||
|
|
||||||
|
# Fix up signs. The sign of the dividend is still lying around in ECF.
|
||||||
|
# The sign of the remainder, ah, is the same as the dividend. The sign
|
||||||
|
# of the quotient is negated if the signs of the divisor and dividend
|
||||||
|
# were different.
|
||||||
|
|
||||||
|
# Negate the remainder
|
||||||
|
sub t4, t0, t6, dataSize=1
|
||||||
|
# If the dividend was negitive, put the negated remainder in rsi.
|
||||||
|
mov rsi, rsi, t4, (CECF,), dataSize=1
|
||||||
|
# Otherwise put the regular remainder in rsi.
|
||||||
|
mov rsi, rsi, t6, (nCECF,), dataSize=1
|
||||||
|
|
||||||
|
# Negate the quotient.
|
||||||
|
sub t4, t0, t5, dataSize=1
|
||||||
|
# If the dividend was negative, start using the negated quotient
|
||||||
|
mov t5, t5, t4, (CECF,), dataSize=1
|
||||||
|
|
||||||
|
# Check the sign of the divisor
|
||||||
|
slli t0, t3, 1, flags=(ECF,), dataSize=1
|
||||||
|
|
||||||
|
# Negate the (possibly already negated) quotient
|
||||||
|
sub t4, t0, t5, dataSize=1
|
||||||
|
# If the divisor was negative, put the negated quotient in rax.
|
||||||
|
mov rax, rax, t4, (CECF,), dataSize=1
|
||||||
|
# Otherwise put the one that wasn't negated (at least here) in rax.
|
||||||
|
mov rax, rax, t5, (nCECF,), dataSize=1
|
||||||
};
|
};
|
||||||
|
|
||||||
#
|
#
|
||||||
|
@ -282,27 +609,225 @@ def macroop DIV_P
|
||||||
|
|
||||||
def macroop IDIV_R
|
def macroop IDIV_R
|
||||||
{
|
{
|
||||||
divr t1, rax, reg
|
# Negate dividend
|
||||||
divq rax, rax, reg
|
sub t1, t0, rax, flags=(ECF,)
|
||||||
mov rdx, rdx, t1
|
ruflag t4, 3
|
||||||
|
sub t2, t0, rdx
|
||||||
|
sub t2, t2, t4
|
||||||
|
|
||||||
|
#Find the sign of the divisor
|
||||||
|
#FIXME!!! This depends on shifts setting the carry flag correctly.
|
||||||
|
slli t0, reg, 1, flags=(ECF,)
|
||||||
|
|
||||||
|
# Negate divisor
|
||||||
|
sub t3, t0, reg
|
||||||
|
# Put the divisor's absolute value into t3
|
||||||
|
mov t3, t3, reg, flags=(nCECF,)
|
||||||
|
|
||||||
|
#Find the sign of the dividend
|
||||||
|
#FIXME!!! This depends on shifts setting the carry flag correctly.
|
||||||
|
slli t0, rdx, 1, flags=(ECF,)
|
||||||
|
|
||||||
|
# Put the dividend's absolute value into t1 and t2
|
||||||
|
mov t1, t1, rax, flags=(nCECF,)
|
||||||
|
mov t2, t2, rdx, flags=(nCECF,)
|
||||||
|
|
||||||
|
# Do the initial part of the division
|
||||||
|
div1 t2, t3
|
||||||
|
|
||||||
|
#These are split out so we can initialize the number of bits in the
|
||||||
|
#second register
|
||||||
|
div2i t4, t1, "env.dataSize * 8"
|
||||||
|
div2 t4, t1, t4
|
||||||
|
|
||||||
|
#Loop until we're out of bits to shift in
|
||||||
|
divLoopTop:
|
||||||
|
div2 t4, t1, t4
|
||||||
|
div2 t4, t1, t4
|
||||||
|
div2 t4, t1, t4
|
||||||
|
div2 t4, t1, t4, flags=(EZF,)
|
||||||
|
bri t0, label("divLoopTop"), flags=(nCEZF,)
|
||||||
|
|
||||||
|
#Unload the answer
|
||||||
|
divq t5
|
||||||
|
divr t6
|
||||||
|
|
||||||
|
# Fix up signs. The sign of the dividend is still lying around in ECF.
|
||||||
|
# The sign of the remainder, ah, is the same as the dividend. The sign
|
||||||
|
# of the quotient is negated if the signs of the divisor and dividend
|
||||||
|
# were different.
|
||||||
|
|
||||||
|
# Negate the remainder
|
||||||
|
sub t4, t0, t6
|
||||||
|
# If the dividend was negitive, put the negated remainder in rdx.
|
||||||
|
mov rdx, rdx, t4, (CECF,)
|
||||||
|
# Otherwise put the regular remainder in rdx.
|
||||||
|
mov rdx, rdx, t6, (nCECF,)
|
||||||
|
|
||||||
|
# Negate the quotient.
|
||||||
|
sub t4, t0, t5
|
||||||
|
# If the dividend was negative, start using the negated quotient
|
||||||
|
mov t5, t5, t4, (CECF,)
|
||||||
|
|
||||||
|
# Check the sign of the divisor
|
||||||
|
slli t0, t3, 1, flags=(ECF,)
|
||||||
|
|
||||||
|
# Negate the (possibly already negated) quotient
|
||||||
|
sub t4, t0, t5
|
||||||
|
# If the divisor was negative, put the negated quotient in rax.
|
||||||
|
mov rax, rax, t4, (CECF,)
|
||||||
|
# Otherwise put the one that wasn't negated (at least here) in rax.
|
||||||
|
mov rax, rax, t5, (nCECF,)
|
||||||
};
|
};
|
||||||
|
|
||||||
def macroop IDIV_M
|
def macroop IDIV_M
|
||||||
{
|
{
|
||||||
ld t1, seg, sib, disp
|
# Negate dividend
|
||||||
divr rdx, rax, t1
|
sub t1, t0, rax, flags=(ECF,)
|
||||||
divq rax, rax, t1
|
ruflag t4, 3
|
||||||
|
sub t2, t0, rdx
|
||||||
|
sub t2, t2, t4
|
||||||
|
|
||||||
|
ld t3, seg, sib, disp
|
||||||
|
|
||||||
|
#Find the sign of the divisor
|
||||||
|
#FIXME!!! This depends on shifts setting the carry flag correctly.
|
||||||
|
slli t0, t3, 1, flags=(ECF,)
|
||||||
|
|
||||||
|
# Negate divisor
|
||||||
|
sub t4, t0, t3
|
||||||
|
# Put the divisor's absolute value into t3
|
||||||
|
mov t3, t3, t4, flags=(CECF,)
|
||||||
|
|
||||||
|
#Find the sign of the dividend
|
||||||
|
#FIXME!!! This depends on shifts setting the carry flag correctly.
|
||||||
|
slli t0, rdx, 1, flags=(ECF,)
|
||||||
|
|
||||||
|
# Put the dividend's absolute value into t1 and t2
|
||||||
|
mov t1, t1, rax, flags=(nCECF,)
|
||||||
|
mov t2, t2, rdx, flags=(nCECF,)
|
||||||
|
|
||||||
|
# Do the initial part of the division
|
||||||
|
div1 t2, t3
|
||||||
|
|
||||||
|
#These are split out so we can initialize the number of bits in the
|
||||||
|
#second register
|
||||||
|
div2i t4, t1, "env.dataSize * 8"
|
||||||
|
div2 t4, t1, t4
|
||||||
|
|
||||||
|
#Loop until we're out of bits to shift in
|
||||||
|
divLoopTop:
|
||||||
|
div2 t4, t1, t4
|
||||||
|
div2 t4, t1, t4
|
||||||
|
div2 t4, t1, t4
|
||||||
|
div2 t4, t1, t4, flags=(EZF,)
|
||||||
|
bri t0, label("divLoopTop"), flags=(nCEZF,)
|
||||||
|
|
||||||
|
#Unload the answer
|
||||||
|
divq t5
|
||||||
|
divr t6
|
||||||
|
|
||||||
|
# Fix up signs. The sign of the dividend is still lying around in ECF.
|
||||||
|
# The sign of the remainder, ah, is the same as the dividend. The sign
|
||||||
|
# of the quotient is negated if the signs of the divisor and dividend
|
||||||
|
# were different.
|
||||||
|
|
||||||
|
# Negate the remainder
|
||||||
|
sub t4, t0, t6
|
||||||
|
# If the dividend was negitive, put the negated remainder in rdx.
|
||||||
|
mov rdx, rdx, t4, (CECF,)
|
||||||
|
# Otherwise put the regular remainder in rdx.
|
||||||
|
mov rdx, rdx, t6, (nCECF,)
|
||||||
|
|
||||||
|
# Negate the quotient.
|
||||||
|
sub t4, t0, t5
|
||||||
|
# If the dividend was negative, start using the negated quotient
|
||||||
|
mov t5, t5, t4, (CECF,)
|
||||||
|
|
||||||
|
# Check the sign of the divisor
|
||||||
|
slli t0, t3, 1, flags=(ECF,)
|
||||||
|
|
||||||
|
# Negate the (possibly already negated) quotient
|
||||||
|
sub t4, t0, t5
|
||||||
|
# If the divisor was negative, put the negated quotient in rax.
|
||||||
|
mov rax, rax, t4, (CECF,)
|
||||||
|
# Otherwise put the one that wasn't negated (at least here) in rax.
|
||||||
|
mov rax, rax, t5, (nCECF,)
|
||||||
};
|
};
|
||||||
|
|
||||||
def macroop IDIV_P
|
def macroop IDIV_P
|
||||||
{
|
{
|
||||||
|
# Negate dividend
|
||||||
|
sub t1, t0, rax, flags=(ECF,)
|
||||||
|
ruflag t4, 3
|
||||||
|
sub t2, t0, rdx
|
||||||
|
sub t2, t2, t4
|
||||||
|
|
||||||
rdip t7
|
rdip t7
|
||||||
ld t1, seg, riprel, disp
|
ld t3, seg, riprel, disp
|
||||||
divr rdx, rax, t1
|
|
||||||
divq rax, rax, t1
|
#Find the sign of the divisor
|
||||||
|
#FIXME!!! This depends on shifts setting the carry flag correctly.
|
||||||
|
slli t0, t3, 1, flags=(ECF,)
|
||||||
|
|
||||||
|
# Negate divisor
|
||||||
|
sub t4, t0, t3
|
||||||
|
# Put the divisor's absolute value into t3
|
||||||
|
mov t3, t3, t4, flags=(CECF,)
|
||||||
|
|
||||||
|
#Find the sign of the dividend
|
||||||
|
#FIXME!!! This depends on shifts setting the carry flag correctly.
|
||||||
|
slli t0, rdx, 1, flags=(ECF,)
|
||||||
|
|
||||||
|
# Put the dividend's absolute value into t1 and t2
|
||||||
|
mov t1, t1, rax, flags=(nCECF,)
|
||||||
|
mov t2, t2, rdx, flags=(nCECF,)
|
||||||
|
|
||||||
|
# Do the initial part of the division
|
||||||
|
div1 t2, t3
|
||||||
|
|
||||||
|
#These are split out so we can initialize the number of bits in the
|
||||||
|
#second register
|
||||||
|
div2i t4, t1, "env.dataSize * 8"
|
||||||
|
div2 t4, t1, t4
|
||||||
|
|
||||||
|
#Loop until we're out of bits to shift in
|
||||||
|
divLoopTop:
|
||||||
|
div2 t4, t1, t4
|
||||||
|
div2 t4, t1, t4
|
||||||
|
div2 t4, t1, t4
|
||||||
|
div2 t4, t1, t4, flags=(EZF,)
|
||||||
|
bri t0, label("divLoopTop"), flags=(nCEZF,)
|
||||||
|
|
||||||
|
#Unload the answer
|
||||||
|
divq t5
|
||||||
|
divr t6
|
||||||
|
|
||||||
|
# Fix up signs. The sign of the dividend is still lying around in ECF.
|
||||||
|
# The sign of the remainder, ah, is the same as the dividend. The sign
|
||||||
|
# of the quotient is negated if the signs of the divisor and dividend
|
||||||
|
# were different.
|
||||||
|
|
||||||
|
# Negate the remainder
|
||||||
|
sub t4, t0, t6
|
||||||
|
# If the dividend was negitive, put the negated remainder in rdx.
|
||||||
|
mov rdx, rdx, t4, (CECF,)
|
||||||
|
# Otherwise put the regular remainder in rdx.
|
||||||
|
mov rdx, rdx, t6, (nCECF,)
|
||||||
|
|
||||||
|
# Negate the quotient.
|
||||||
|
sub t4, t0, t5
|
||||||
|
# If the dividend was negative, start using the negated quotient
|
||||||
|
mov t5, t5, t4, (CECF,)
|
||||||
|
|
||||||
|
# Check the sign of the divisor
|
||||||
|
slli t0, t3, 1, flags=(ECF,)
|
||||||
|
|
||||||
|
# Negate the (possibly already negated) quotient
|
||||||
|
sub t4, t0, t5
|
||||||
|
# If the divisor was negative, put the negated quotient in rax.
|
||||||
|
mov rax, rax, t4, (CECF,)
|
||||||
|
# Otherwise put the one that wasn't negated (at least here) in rax.
|
||||||
|
mov rax, rax, t5, (nCECF,)
|
||||||
};
|
};
|
||||||
'''
|
'''
|
||||||
#let {{
|
|
||||||
# class IDIV(Inst):
|
|
||||||
# "GenFault ${new UnimpInstFault}"
|
|
||||||
#}};
|
|
||||||
|
|
|
@ -227,6 +227,45 @@ def template MicroRegOpImmConstructor {{
|
||||||
}
|
}
|
||||||
}};
|
}};
|
||||||
|
|
||||||
|
output header {{
|
||||||
|
void
|
||||||
|
divide(uint64_t dividend, uint64_t divisor,
|
||||||
|
uint64_t "ient, uint64_t &remainder);
|
||||||
|
}};
|
||||||
|
|
||||||
|
output decoder {{
|
||||||
|
void
|
||||||
|
divide(uint64_t dividend, uint64_t divisor,
|
||||||
|
uint64_t "ient, uint64_t &remainder)
|
||||||
|
{
|
||||||
|
//Check for divide by zero.
|
||||||
|
if (divisor == 0)
|
||||||
|
panic("Divide by zero!\\n");
|
||||||
|
//If the divisor is bigger than the dividend, don't do anything.
|
||||||
|
if (divisor <= dividend) {
|
||||||
|
//Shift the divisor so it's msb lines up with the dividend.
|
||||||
|
int dividendMsb = findMsbSet(dividend);
|
||||||
|
int divisorMsb = findMsbSet(divisor);
|
||||||
|
int shift = dividendMsb - divisorMsb;
|
||||||
|
divisor <<= shift;
|
||||||
|
//Compute what we'll add to the quotient if the divisor isn't
|
||||||
|
//now larger than the dividend.
|
||||||
|
uint64_t quotientBit = 1;
|
||||||
|
quotientBit <<= shift;
|
||||||
|
//If we need to step back a bit (no pun intended) because the
|
||||||
|
//divisor got too to large, do that here. This is the "or two"
|
||||||
|
//part of one or two bit division.
|
||||||
|
if (divisor > dividend) {
|
||||||
|
quotientBit >>= 1;
|
||||||
|
divisor >>= 1;
|
||||||
|
}
|
||||||
|
//Decrement the remainder and increment the quotient.
|
||||||
|
quotient += quotientBit;
|
||||||
|
remainder -= divisor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}};
|
||||||
|
|
||||||
let {{
|
let {{
|
||||||
# Make these empty strings so that concatenating onto
|
# Make these empty strings so that concatenating onto
|
||||||
# them will always work.
|
# them will always work.
|
||||||
|
@ -507,20 +546,65 @@ let {{
|
||||||
ccFlagBits = ccFlagBits & ~(ext & (CFBit | OFBit | ECFBit));
|
ccFlagBits = ccFlagBits & ~(ext & (CFBit | OFBit | ECFBit));
|
||||||
'''
|
'''
|
||||||
|
|
||||||
class Div1(FlagRegOp):
|
# One or two bit divide
|
||||||
|
class Div1(WrRegOp):
|
||||||
code = '''
|
code = '''
|
||||||
int halfSize = (dataSize * 8) / 2;
|
//These are temporaries so that modifying them later won't make
|
||||||
IntReg quotient = (psrc1 / op2) & mask(halfSize);
|
//the ISA parser think they're also sources.
|
||||||
IntReg remainder = (psrc1 % op2) & mask(halfSize);
|
uint64_t quotient = 0;
|
||||||
IntReg result = quotient | (remainder << halfSize);
|
uint64_t remainder = psrc1;
|
||||||
DestReg = merge(DestReg, result, dataSize);
|
//Similarly, this is a temporary so changing it doesn't make it
|
||||||
|
//a source.
|
||||||
|
uint64_t divisor = op2;
|
||||||
|
//This is a temporary just for consistency and clarity.
|
||||||
|
uint64_t dividend = remainder;
|
||||||
|
//Do the division.
|
||||||
|
divide(dividend, divisor, quotient, remainder);
|
||||||
|
//Record the final results.
|
||||||
|
Remainder = remainder;
|
||||||
|
Quotient = quotient;
|
||||||
|
Divisor = divisor;
|
||||||
'''
|
'''
|
||||||
|
|
||||||
class Divq(FlagRegOp):
|
# Step divide
|
||||||
code = 'DestReg = merge(DestReg, psrc1 / op2, dataSize);'
|
class Div2(RegOp):
|
||||||
|
code = '''
|
||||||
|
uint64_t dividend = Remainder;
|
||||||
|
uint64_t divisor = Divisor;
|
||||||
|
uint64_t quotient = Quotient;
|
||||||
|
uint64_t remainder = dividend;
|
||||||
|
int remaining = op2;
|
||||||
|
//If we overshot, do nothing. This lets us unrool division loops a
|
||||||
|
//little.
|
||||||
|
if (remaining) {
|
||||||
|
//Shift in bits from the low order portion of the dividend
|
||||||
|
while(dividend < divisor && remaining) {
|
||||||
|
dividend = (dividend << 1) | bits(SrcReg1, remaining - 1);
|
||||||
|
quotient <<= 1;
|
||||||
|
remaining--;
|
||||||
|
}
|
||||||
|
remainder = dividend;
|
||||||
|
//Do the division.
|
||||||
|
divide(dividend, divisor, quotient, remainder);
|
||||||
|
}
|
||||||
|
//Keep track of how many bits there are still to pull in.
|
||||||
|
DestReg = merge(DestReg, remaining, dataSize);
|
||||||
|
//Record the final results
|
||||||
|
Remainder = remainder;
|
||||||
|
Quotient = quotient;
|
||||||
|
'''
|
||||||
|
flag_code = '''
|
||||||
|
if (DestReg == 0)
|
||||||
|
ccFlagBits = ccFlagBits | (ext & EZFBit);
|
||||||
|
else
|
||||||
|
ccFlagBits = ccFlagBits & ~(ext & EZFBit);
|
||||||
|
'''
|
||||||
|
|
||||||
class Divr(FlagRegOp):
|
class Divq(RdRegOp):
|
||||||
code = 'DestReg = merge(DestReg, psrc1 % op2, dataSize);'
|
code = 'DestReg = merge(SrcReg1, Quotient, dataSize);'
|
||||||
|
|
||||||
|
class Divr(RdRegOp):
|
||||||
|
code = 'DestReg = merge(SrcReg1, Remainder, dataSize);'
|
||||||
|
|
||||||
class Mov(CondRegOp):
|
class Mov(CondRegOp):
|
||||||
code = 'DestReg = merge(SrcReg1, op2, dataSize)'
|
code = 'DestReg = merge(SrcReg1, op2, dataSize)'
|
||||||
|
|
|
@ -105,7 +105,8 @@ def operands {{
|
||||||
'ProdHi': ('IntReg', 'uqw', 'INTREG_IMPLICIT(1)', 'IsInteger', 8),
|
'ProdHi': ('IntReg', 'uqw', 'INTREG_IMPLICIT(1)', 'IsInteger', 8),
|
||||||
'Quotient': ('IntReg', 'uqw', 'INTREG_IMPLICIT(2)', 'IsInteger', 9),
|
'Quotient': ('IntReg', 'uqw', 'INTREG_IMPLICIT(2)', 'IsInteger', 9),
|
||||||
'Remainder': ('IntReg', 'uqw', 'INTREG_IMPLICIT(3)', 'IsInteger', 10),
|
'Remainder': ('IntReg', 'uqw', 'INTREG_IMPLICIT(3)', 'IsInteger', 10),
|
||||||
'rax': ('IntReg', 'uqw', '(INTREG_RAX)', 'IsInteger', 11),
|
'Divisor': ('IntReg', 'uqw', 'INTREG_IMPLICIT(4)', 'IsInteger', 11),
|
||||||
|
'rax': ('IntReg', 'uqw', '(INTREG_RAX)', 'IsInteger', 12),
|
||||||
'FpSrcReg1': ('FloatReg', 'df', 'src1', 'IsFloating', 20),
|
'FpSrcReg1': ('FloatReg', 'df', 'src1', 'IsFloating', 20),
|
||||||
'FpSrcReg2': ('FloatReg', 'df', 'src2', 'IsFloating', 21),
|
'FpSrcReg2': ('FloatReg', 'df', 'src2', 'IsFloating', 21),
|
||||||
'FpDestReg': ('FloatReg', 'df', 'dest', 'IsFloating', 22),
|
'FpDestReg': ('FloatReg', 'df', 'dest', 'IsFloating', 22),
|
||||||
|
|
|
@ -64,11 +64,12 @@ namespace X86ISA
|
||||||
|
|
||||||
const int NumPseudoIntRegs = 1;
|
const int NumPseudoIntRegs = 1;
|
||||||
//1. The condition code bits of the rflags register.
|
//1. The condition code bits of the rflags register.
|
||||||
const int NumImplicitIntRegs = 4;
|
const int NumImplicitIntRegs = 5;
|
||||||
//1. The lower part of the result of multiplication.
|
//1. The lower part of the result of multiplication.
|
||||||
//2. The upper part of the result of multiplication.
|
//2. The upper part of the result of multiplication.
|
||||||
//3. The quotient from division
|
//3. The quotient from division
|
||||||
//4. The remainder from division
|
//4. The remainder from division
|
||||||
|
//5. The divisor for division
|
||||||
|
|
||||||
const int NumMMXRegs = 8;
|
const int NumMMXRegs = 8;
|
||||||
const int NumXMMRegs = 16;
|
const int NumXMMRegs = 16;
|
||||||
|
|
Loading…
Reference in a new issue