|
|
1.1 root 1: .file "reg_u_add.S"
2: /*---------------------------------------------------------------------------+
3: | reg_u_add.S |
4: | |
5: | Add two valid (TW_Valid) FPU_REG numbers, of the same sign, and put the |
6: | result in a destination FPU_REG. |
7: | |
8: | Copyright (C) 1992 W. Metzenthen, 22 Parker St, Ormond, Vic 3163, |
9: | Australia. E-mail [email protected] |
10: | |
11: | Call from C as: |
12: | void reg_u_add(reg *arg1, reg *arg2, reg *answ) |
13: | |
14: +---------------------------------------------------------------------------*/
15:
16: /*
17: | Kernel addition routine reg_u_add(reg *arg1, reg *arg2, reg *answ).
18: | Takes two valid reg f.p. numbers (TW_Valid), which are
19: | treated as unsigned numbers,
20: | and returns their sum as a TW_Valid or TW_S f.p. number.
21: | The returned number is normalized.
22: | Basic checks are performed if PARANOID is defined.
23: */
24:
25: #include "exception.h"
26: #include "fpu_asm.h"
27:
28: .text
29: .align 2,144
30: .globl reg_u_add
31: reg_u_add:
32: pushl %ebp
33: movl %esp,%ebp
34: // subl $16,%esp
35: pushl %esi
36: pushl %edi
37: pushl %ebx
38:
39: movl PARAM1,%esi /* source 1 */
40: movl PARAM2,%edi /* source 2 */
41:
42: xorl %ecx,%ecx
43: movl EXP(%esi),%ecx
44: subl EXP(%edi),%ecx /* exp1 - exp2 */
45: // jnc L_arg1_larger
46: jge L_arg1_larger
47:
48: /* num1 is smaller */
49: movl SIGL(%esi),%ebx
50: movl SIGH(%esi),%eax
51:
52: movl %edi,%esi
53: negw %cx
54: jmp L_accum_loaded
55:
56: L_arg1_larger:
57: /* num1 has larger or equal exponent */
58: movl SIGL(%edi),%ebx
59: movl SIGH(%edi),%eax
60:
61: L_accum_loaded:
62: movl 16(%ebp),%edi /* destination */
63:
64: movl EXP(%esi),%edx
65: movl %edx,EXP(%edi) /* Copy exponent to destination */
66:
67: xorl %edx,%edx /* clear the extension */
68:
69: #ifdef PARANOID
70: testl $0x80000000,%eax
71: je L_bugged
72:
73: testl $0x80000000,SIGH(%esi)
74: je L_bugged
75: #endif PARANOID
76:
77: cmpw $32,%cx /* shrd only works for 0..31 bits */
78: jnc L_more_than_31
79:
80: /* less than 32 bits */
81: shrd %cl,%ebx,%edx
82: shrd %cl,%eax,%ebx
83: shr %cl,%eax
84: jmp L_shift_done
85:
86: L_more_than_31:
87: cmpw $64,%cx
88: jnc L_more_than_63
89:
90: subb $32,%cl
91: shrd %cl,%eax,%edx
92: shr %cl,%eax
93: movl %eax,%ebx
94: xorl %eax,%eax
95: jmp L_shift_done
96:
97: L_more_than_63:
98: cmpw $66,%cx
99: jnc L_more_than_65
100:
101: subb $64,%cl
102: movl %eax,%edx
103: shr %cl,%edx
104: xorl %ebx,%ebx
105: xorl %eax,%eax
106: jmp L_shift_done
107:
108: L_more_than_65:
109: /* just copy the larger reg to dest */
110: movw SIGN(%esi),%ax
111: movw %ax,SIGN(%edi)
112: movl SIGL(%esi),%eax
113: movl %eax,SIGL(%edi)
114: movl SIGH(%esi),%eax
115: movl %eax,SIGH(%edi)
116: jmp L_exit // Does not overflow
117:
118: L_shift_done:
119: /* Now do the addition */
120: addl SIGL(%esi),%ebx
121: adcl SIGH(%esi),%eax
122: jnc L_round_the_result
123:
124: /* Overflow, adjust the result */
125: rcrl $1,%eax
126: rcrl $1,%ebx
127: rcrl $1,%edx
128:
129: incl EXP(%edi)
130:
131: L_round_the_result:
132: /* Round the result */
133: cmpl $0x80000000,%edx
134: jc L_no_round_up
135:
136: jne L_do_round_up
137:
138: /* Now test for round-to-even */
139: test $1,%ebx
140: jz L_no_round_up
141:
142: L_do_round_up:
143: addl $1,%ebx
144: adcl $0,%eax
145: jnc L_no_round_up /* Rounding done, no overflow */
146:
147: /* Overflow, adjust the result */
148: rcrl $1,%eax
149: rcrl $1,%ebx
150: incl EXP(%edi)
151:
152: L_no_round_up:
153: /* store the result */
154: movl %eax,SIGH(%edi)
155: movl %ebx,SIGL(%edi)
156:
157: movb TW_Valid,TAG(%edi) /* Set the tags to TW_Valid */
158: movb SIGN(%esi),%al
159: movb %al,SIGN(%edi) /* Copy the sign from the first arg */
160:
161: // The number may have overflowed
162: cmpl EXP_OVER,EXP(%edi)
163: jge L_overflow
164:
165: L_exit:
166: popl %ebx
167: popl %edi
168: popl %esi
169: leave
170: ret
171:
172: /* The addition resulted in a number too large to represent */
173: L_overflow:
174: push %edi
175: call arith_overflow
176: pop %ebx
177: jmp L_exit
178:
179:
180: #ifdef PARANOID
181: /* If we ever get here then we have problems! */
182: L_bugged:
183: pushl EX_INTERNAL|0x201
184: call EXCEPTION
185: pop %ebx
186: jmp L_exit
187: #endif PARANOID
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.