diff options
author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
commit | 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch) | |
tree | 0bba044c4ce775e45a88a51686b5d9f90697ea9d /arch/i386/math-emu/reg_u_add.S |
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.
Let it rip!
Diffstat (limited to 'arch/i386/math-emu/reg_u_add.S')
-rw-r--r-- | arch/i386/math-emu/reg_u_add.S | 167 |
1 files changed, 167 insertions, 0 deletions
diff --git a/arch/i386/math-emu/reg_u_add.S b/arch/i386/math-emu/reg_u_add.S new file mode 100644 index 000000000000..47c4c2434d85 --- /dev/null +++ b/arch/i386/math-emu/reg_u_add.S | |||
@@ -0,0 +1,167 @@ | |||
1 | .file "reg_u_add.S" | ||
2 | /*---------------------------------------------------------------------------+ | ||
3 | | reg_u_add.S | | ||
4 | | | | ||
5 | | Add two valid (TAG_Valid) FPU_REG numbers, of the same sign, and put the | | ||
6 | | result in a destination FPU_REG. | | ||
7 | | | | ||
8 | | Copyright (C) 1992,1993,1995,1997 | | ||
9 | | W. Metzenthen, 22 Parker St, Ormond, Vic 3163, Australia | | ||
10 | | E-mail billm@suburbia.net | | ||
11 | | | | ||
12 | | Call from C as: | | ||
13 | | int FPU_u_add(FPU_REG *arg1, FPU_REG *arg2, FPU_REG *answ, | | ||
14 | | int control_w) | | ||
15 | | Return value is the tag of the answer, or-ed with FPU_Exception if | | ||
16 | | one was raised, or -1 on internal error. | | ||
17 | | | | ||
18 | +---------------------------------------------------------------------------*/ | ||
19 | |||
20 | /* | ||
21 | | Kernel addition routine FPU_u_add(reg *arg1, reg *arg2, reg *answ). | ||
22 | | Takes two valid reg f.p. numbers (TAG_Valid), which are | ||
23 | | treated as unsigned numbers, | ||
24 | | and returns their sum as a TAG_Valid or TAG_Special f.p. number. | ||
25 | | The returned number is normalized. | ||
26 | | Basic checks are performed if PARANOID is defined. | ||
27 | */ | ||
28 | |||
29 | #include "exception.h" | ||
30 | #include "fpu_emu.h" | ||
31 | #include "control_w.h" | ||
32 | |||
33 | .text | ||
34 | ENTRY(FPU_u_add) | ||
35 | pushl %ebp | ||
36 | movl %esp,%ebp | ||
37 | pushl %esi | ||
38 | pushl %edi | ||
39 | pushl %ebx | ||
40 | |||
41 | movl PARAM1,%esi /* source 1 */ | ||
42 | movl PARAM2,%edi /* source 2 */ | ||
43 | |||
44 | movl PARAM6,%ecx | ||
45 | movl %ecx,%edx | ||
46 | subl PARAM7,%ecx /* exp1 - exp2 */ | ||
47 | jge L_arg1_larger | ||
48 | |||
49 | /* num1 is smaller */ | ||
50 | movl SIGL(%esi),%ebx | ||
51 | movl SIGH(%esi),%eax | ||
52 | |||
53 | movl %edi,%esi | ||
54 | movl PARAM7,%edx | ||
55 | negw %cx | ||
56 | jmp L_accum_loaded | ||
57 | |||
58 | L_arg1_larger: | ||
59 | /* num1 has larger or equal exponent */ | ||
60 | movl SIGL(%edi),%ebx | ||
61 | movl SIGH(%edi),%eax | ||
62 | |||
63 | L_accum_loaded: | ||
64 | movl PARAM3,%edi /* destination */ | ||
65 | movw %dx,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 | /* The number to be shifted is in %eax:%ebx:%edx */ | ||
78 | cmpw $32,%cx /* shrd only works for 0..31 bits */ | ||
79 | jnc L_more_than_31 | ||
80 | |||
81 | /* less than 32 bits */ | ||
82 | shrd %cl,%ebx,%edx | ||
83 | shrd %cl,%eax,%ebx | ||
84 | shr %cl,%eax | ||
85 | jmp L_shift_done | ||
86 | |||
87 | L_more_than_31: | ||
88 | cmpw $64,%cx | ||
89 | jnc L_more_than_63 | ||
90 | |||
91 | subb $32,%cl | ||
92 | jz L_exactly_32 | ||
93 | |||
94 | shrd %cl,%eax,%edx | ||
95 | shr %cl,%eax | ||
96 | orl %ebx,%ebx | ||
97 | jz L_more_31_no_low /* none of the lowest bits is set */ | ||
98 | |||
99 | orl $1,%edx /* record the fact in the extension */ | ||
100 | |||
101 | L_more_31_no_low: | ||
102 | movl %eax,%ebx | ||
103 | xorl %eax,%eax | ||
104 | jmp L_shift_done | ||
105 | |||
106 | L_exactly_32: | ||
107 | movl %ebx,%edx | ||
108 | movl %eax,%ebx | ||
109 | xorl %eax,%eax | ||
110 | jmp L_shift_done | ||
111 | |||
112 | L_more_than_63: | ||
113 | cmpw $65,%cx | ||
114 | jnc L_more_than_64 | ||
115 | |||
116 | movl %eax,%edx | ||
117 | orl %ebx,%ebx | ||
118 | jz L_more_63_no_low | ||
119 | |||
120 | orl $1,%edx | ||
121 | jmp L_more_63_no_low | ||
122 | |||
123 | L_more_than_64: | ||
124 | movl $1,%edx /* The shifted nr always at least one '1' */ | ||
125 | |||
126 | L_more_63_no_low: | ||
127 | xorl %ebx,%ebx | ||
128 | xorl %eax,%eax | ||
129 | |||
130 | L_shift_done: | ||
131 | /* Now do the addition */ | ||
132 | addl SIGL(%esi),%ebx | ||
133 | adcl SIGH(%esi),%eax | ||
134 | jnc L_round_the_result | ||
135 | |||
136 | /* Overflow, adjust the result */ | ||
137 | rcrl $1,%eax | ||
138 | rcrl $1,%ebx | ||
139 | rcrl $1,%edx | ||
140 | jnc L_no_bit_lost | ||
141 | |||
142 | orl $1,%edx | ||
143 | |||
144 | L_no_bit_lost: | ||
145 | incw EXP(%edi) | ||
146 | |||
147 | L_round_the_result: | ||
148 | jmp fpu_reg_round /* Round the result */ | ||
149 | |||
150 | |||
151 | |||
152 | #ifdef PARANOID | ||
153 | /* If we ever get here then we have problems! */ | ||
154 | L_bugged: | ||
155 | pushl EX_INTERNAL|0x201 | ||
156 | call EXCEPTION | ||
157 | pop %ebx | ||
158 | movl $-1,%eax | ||
159 | jmp L_exit | ||
160 | |||
161 | L_exit: | ||
162 | popl %ebx | ||
163 | popl %edi | ||
164 | popl %esi | ||
165 | leave | ||
166 | ret | ||
167 | #endif /* PARANOID */ | ||