Fix i386 and x86-64 generic multiplication hooks on fixnums.
authorTaylor R Campbell <campbell@mumble.net>
Thu, 12 Nov 2009 21:44:58 +0000 (16:44 -0500)
committerTaylor R Campbell <campbell@mumble.net>
Thu, 12 Nov 2009 21:44:58 +0000 (16:44 -0500)
Before multiplying, both tags must be cleared, and one of the
operands must be shifted to include a factor of 2^6.  Shifting both
operands, so that there is an extra factor of 2^12, or not clearing
the tag on both operands, is wrong.  However, this didn't affect any
real code, since the fixnum case of generic multiplication is always
open-coded by the compiler unless you futz with compiler switches.

src/microcode/cmpauxmd/i386.m4
src/microcode/cmpauxmd/x86-64.m4

index 4b4f23e99d246d0dac7dab9fc3f1b4cfdeac7526..fda7aa75019c2c23584d5be55e9152ced333a256 100644 (file)
@@ -862,6 +862,10 @@ asm_generic_$1_fail:
        jmp     scheme_to_interface')
 \f
 define(define_binary_operation,
+`define_binary_operation_with_setup($1,$2,$3,$4,
+       `OP(shl,l)      TW(IMM(TC_LENGTH),REG(eax))')')
+
+define(define_binary_operation_with_setup,
 `declare_alignment(2)
 define_hook_label(generic_$1)
        OP(pop,l)       REG(edx)
@@ -886,7 +890,7 @@ asm_generic_$1_fail:
 asm_generic_$1_fix:
        OP(mov,l)       TW(REG(edx),REG(eax))
        OP(mov,l)       TW(REG(ebx),REG(ecx))
-       OP(shl,l)       TW(IMM(TC_LENGTH),REG(eax))
+       $5                                              # Set up eax.
        OP(shl,l)       TW(IMM(TC_LENGTH),REG(ecx))
        OP($3,l)        TW(REG(ecx),REG(eax))           # subl
        jo      asm_generic_$1_fail
@@ -996,7 +1000,13 @@ define_unary_predicate(zero,2d,je,je)
 # define_binary_operation(  $1,   $2,     $3,     $4)
 define_binary_operation(add,2b,add,fadd)
 define_binary_operation(subtract,28,sub,fsub)
-define_binary_operation(multiply,29,imul,fmul)
+
+# To set up eax, kill its tag, but leave it unshifted; the other
+# operand will be shifted already, so that it will already include the
+# factor of 2^6 desired in the product.
+define_binary_operation_with_setup(multiply,29,imul,fmul,
+       `OP(and,l)      TW(rmask,REG(eax))')
+
 # Divide needs to check for 0, so we cant really use the following
 # define_binary_operation(divide,23,NONE,fdiv)
 
index 52cf079953a29ff6b167b7aca34e4d66a02a174f..7c4f8ac6c0daaca4738e69419d5f100cdd2c4e76 100644 (file)
@@ -657,10 +657,10 @@ asm_generic_$1_fail:
        jmp     scheme_to_interface')
 \f
 define(define_binary_operation,
-`define_binary_operation_with_fixup($1,$2,$3,$4,
+`define_binary_operation_with_setup($1,$2,$3,$4,
        `OP(shl,q)      TW(IMM(TC_LENGTH),REG(rax))')')
 
-define(define_binary_operation_with_fixup,
+define(define_binary_operation_with_setup,
 `declare_alignment(2)
 define_hook_label(generic_$1)
        OP(pop,q)       REG(rdx)
@@ -829,8 +829,11 @@ define_unary_predicate(zero,2d,je)
 define_binary_operation(add,2b,add,addsd)
 define_binary_operation(subtract,28,sub,subsd)
 
-# No fixup -- leave it unshifted.
-define_binary_operation_with_fixup(multiply,29,imul,mulsd)
+# To set up rax, kill its tag, but leave it unshifted; the other
+# operand will be shifted already, so that it will already include the
+# factor of 2^6 desired in the product.
+define_binary_operation_with_setup(multiply,29,imul,mulsd,
+       `OP(and,q)      TW(rmask,REG(rax))')
 
 # define_binary_predicate(name,index,jcc)
 # define_binary_predicate(  $1,   $2, $3)