summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGabe Black <gblack@eecs.umich.edu>2007-09-06 16:25:29 -0700
committerGabe Black <gblack@eecs.umich.edu>2007-09-06 16:25:29 -0700
commit7f079149f147107070f518fc0a86c45c6c62b2a5 (patch)
tree5657c1be30b11f740be1bc2b15dc59d4e92458a2
parent5052e2cb10b78da55ddef2b1deb67ab2e2aa3255 (diff)
downloadgem5-7f079149f147107070f518fc0a86c45c6c62b2a5.tar.xz
X86: Make signed multiplication do something different from unsigned.
--HG-- extra : convert_revision : 333c4a3464d708d4d8cea88931259ab96c2f75ed
-rw-r--r--src/arch/x86/isa/insts/arithmetic/multiply_and_divide.py6
-rw-r--r--src/arch/x86/isa/microops/regop.isa36
2 files changed, 33 insertions, 9 deletions
diff --git a/src/arch/x86/isa/insts/arithmetic/multiply_and_divide.py b/src/arch/x86/isa/insts/arithmetic/multiply_and_divide.py
index f498a10e0..5f75b8868 100644
--- a/src/arch/x86/isa/insts/arithmetic/multiply_and_divide.py
+++ b/src/arch/x86/isa/insts/arithmetic/multiply_and_divide.py
@@ -134,7 +134,7 @@ def macroop IMUL_B_P
def macroop IMUL_R
{
- muleh t1, rax, reg
+ mulehs t1, rax, reg
mulel rax, rax, reg
mov rdx, rdx, t1
};
@@ -142,7 +142,7 @@ def macroop IMUL_R
def macroop IMUL_M
{
ld t1, seg, sib, disp
- muleh rdx, rax, t1
+ mulehs rdx, rax, t1
mulel rax, rax, t1
};
@@ -150,7 +150,7 @@ def macroop IMUL_P
{
rdip t7
ld t1, seg, riprel, disp
- muleh rdx, rax, t1
+ mulehs rdx, rax, t1
mulel rax, rax, t1
};
diff --git a/src/arch/x86/isa/microops/regop.isa b/src/arch/x86/isa/microops/regop.isa
index 6d68f4fe9..28689c84b 100644
--- a/src/arch/x86/isa/microops/regop.isa
+++ b/src/arch/x86/isa/microops/regop.isa
@@ -258,13 +258,18 @@ let {{
# If op2 is used anywhere, make register and immediate versions
# of this code.
- matcher = re.compile("op2(?P<typeQual>\\.\\w+)?")
- if matcher.search(allCode):
+ matcher = re.compile("(?<!\\w)(?P<prefix>s?)op2(?P<typeQual>\\.\\w+)?")
+ match = matcher.search(allCode)
+ if match:
+ typeQual = ""
+ if match.group("typeQual"):
+ typeQual = match.group("typeQual")
+ src2_name = "%spsrc2%s" % (match.group("prefix"), typeQual)
self.buildCppClasses(name, Name, suffix,
- matcher.sub("psrc2", code),
- matcher.sub("psrc2", flag_code),
- matcher.sub("psrc2", cond_check),
- matcher.sub("psrc2", else_code))
+ matcher.sub(src2_name, code),
+ matcher.sub(src2_name, flag_code),
+ matcher.sub(src2_name, cond_check),
+ matcher.sub(src2_name, else_code))
self.buildCppClasses(name + "i", Name, suffix + "Imm",
matcher.sub("imm8", code),
matcher.sub("imm8", flag_code),
@@ -462,6 +467,11 @@ let {{
class Mulel(FlagRegOp):
code = 'DestReg = merge(DestReg, psrc1 * op2, dataSize);'
+ # Neither of these is quite correct because it assumes that right shifting
+ # a signed or unsigned value does sign or zero extension respectively.
+ # The C standard says that what happens on a right shift with a 1 in the
+ # MSB position is undefined. On x86 and under likely most compilers the
+ # "right thing" happens, but this isn't a guarantee.
class Muleh(FlagRegOp):
code = '''
int halfSize = (dataSize * 8) / 2;
@@ -476,6 +486,20 @@ let {{
DestReg = merge(DestReg, result, dataSize);
'''
+ class Mulehs(FlagRegOp):
+ code = '''
+ int halfSize = (dataSize * 8) / 2;
+ int64_t spsrc1_h = spsrc1 >> halfSize;
+ int64_t spsrc1_l = spsrc1 & mask(halfSize);
+ int64_t spsrc2_h = sop2 >> halfSize;
+ int64_t spsrc2_l = sop2 & mask(halfSize);
+ int64_t result =
+ ((spsrc1_l * spsrc2_h + spsrc1_h * spsrc2_l +
+ ((spsrc1_l * spsrc2_l) >> halfSize)) >> halfSize) +
+ spsrc1_h * spsrc2_h;
+ DestReg = merge(DestReg, result, dataSize);
+ '''
+
class Div1(FlagRegOp):
code = '''
int halfSize = (dataSize * 8) / 2;