|
|
1.1 root 1: .file "reg_u_mul.S"
2: /*---------------------------------------------------------------------------+
3: | reg_u_mul.S |
4: | |
5: | Core multiplication routine |
6: | |
7: | Copyright (C) 1992 W. Metzenthen, 22 Parker St, Ormond, Vic 3163, |
8: | Australia. E-mail [email protected] |
9: | |
10: | |
11: +---------------------------------------------------------------------------*/
12:
13: /*---------------------------------------------------------------------------+
14: | Basic multiplication routine. |
15: | Does not check the resulting exponent for overflow/underflow |
16: | |
17: | Internal working is at approx 96 bits. |
18: | Result is rounded to nearest 64 bits, using "nearest or even". |
19: +---------------------------------------------------------------------------*/
20:
21: #include "exception.h"
22: #include "fpu_asm.h"
23:
24:
25:
26: .data
27: .align 2,0
28: accum_1:
29: .long 0
30:
31:
32: .text
33: .align 2,144
34:
35: .globl reg_u_mul
36: reg_u_mul:
37: pushl %ebp
38: movl %esp,%ebp
39: pushl %esi
40: pushl %edi
41: pushl %ebx
42:
43: movl PARAM1,%esi
44: movl PARAM2,%ecx
45:
46: #ifdef PARANOID
47: testl $0x80000000,SIGH(%esi)
48: jz xL_bugged
49: testl $0x80000000,SIGH(%ecx)
50: jz xL_bugged
51: #endif PARANOID
52:
53: xorl %edi,%edi
54: xorl %ebx,%ebx
55:
56: movl SIGL(%esi),%eax
57: mull SIGL(%ecx)
58: // movl %eax,accum_0
59: movl %edx,accum_1
60:
61: movl SIGL(%esi),%eax
62: mull SIGH(%ecx)
63: addl %eax,accum_1
64: adcl %edx,%ebx
65: // adcl $0,%edi // overflow here is not possible
66:
67: movl SIGH(%esi),%eax
68: mull SIGL(%ecx)
69: addl %eax,accum_1
70: adcl %edx,%ebx
71: adcl $0,%edi
72:
73: movl SIGH(%esi),%eax
74: mull SIGH(%ecx)
75: addl %eax,%ebx
76: adcl %edx,%edi
77:
78: movl EXP(%esi),%eax /* Compute the exponent */
79: addl EXP(%ecx),%eax
80: // Have now finished with the sources
81: movl PARAM3,%esi // Point to the destination
82: movl %eax,EXP(%esi)
83:
84: // Now make sure that the result is normalized
85: testl $0x80000000,%edi
86: jnz L20
87:
88: /* Normalize by shifting left one bit */
89: // shll $1,accum_0 // If using this, change next to rcll
90: shll $1,accum_1
91: rcll $1,%ebx
92: rcll $1,%edi
93: decl EXP(%esi)
94:
95: L20:
96: /* Do the rounding */
97: cmpl $0x80000000,accum_1
98: jc L40
99:
100: jne L30
101:
102: /* 0x80000000, round up only if previous bit is 1 */
103: testl $1,%ebx
104: jz L40
105:
106: L30:
107: addl $1,%ebx
108: adcl $0,%edi
109:
110: /* An overflow can occur here (rare!) */
111: jc xL_overflow_adjust
112:
113: L40:
114: /* Copy the result to the destination register */
115: movl %ebx,SIGL(%esi)
116: movl %edi,SIGH(%esi)
117:
118: xL_exit:
119: popl %ebx
120: popl %edi
121: popl %esi
122: leave
123: ret
124:
125:
126: xL_overflow_adjust:
127: rcrl $1, %edi
128: incl EXP(%esi)
129: jmp L40
130:
131: #ifdef PARANOID
132: xL_bugged:
133: pushl EX_INTERNAL|0x205
134: call EXCEPTION
135: pop %ebx
136: jmp xL_exit
137: #endif PARANOID
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.