X86: Make signed multiplication do something different from unsigned.
authorGabe Black <gblack@eecs.umich.edu>
Thu, 6 Sep 2007 23:25:29 +0000 (16:25 -0700)
committerGabe Black <gblack@eecs.umich.edu>
Thu, 6 Sep 2007 23:25:29 +0000 (16:25 -0700)
--HG--
extra : convert_revision : 333c4a3464d708d4d8cea88931259ab96c2f75ed

src/arch/x86/isa/insts/arithmetic/multiply_and_divide.py
src/arch/x86/isa/microops/regop.isa

index f498a10e06b4ce216b13babdc088888dd1aa59ee..5f75b886833f8ca1a9c380ff1727f4c3639e5f18 100644 (file)
@@ -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
 };
 
index 6d68f4fe9a27535467c44523931bb3d366368e43..28689c84b1a04fbeb49010e92f6963accb046d6c 100644 (file)
@@ -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;