- added instructions how to update the online documentation
[bochs-mirror.git] / cpu / mult64.cc
bloba2aebf6211d50530f46d842ee6ac7315fd187211
1 /////////////////////////////////////////////////////////////////////////
2 // $Id: mult64.cc,v 1.33 2008/08/10 21:16:12 sshwarts Exp $
3 /////////////////////////////////////////////////////////////////////////
4 //
5 // Copyright (C) 2001 MandrakeSoft S.A.
6 //
7 // MandrakeSoft S.A.
8 // 43, rue d'Aboukir
9 // 75002 Paris - France
10 // http://www.linux-mandrake.com/
11 // http://www.mandrakesoft.com/
13 // This library is free software; you can redistribute it and/or
14 // modify it under the terms of the GNU Lesser General Public
15 // License as published by the Free Software Foundation; either
16 // version 2 of the License, or (at your option) any later version.
18 // This library is distributed in the hope that it will be useful,
19 // but WITHOUT ANY WARRANTY; without even the implied warranty of
20 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 // Lesser General Public License for more details.
23 // You should have received a copy of the GNU Lesser General Public
24 // License along with this library; if not, write to the Free Software
25 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26 /////////////////////////////////////////////////////////////////////////
28 #define NEED_CPU_REG_SHORTCUTS 1
29 #include "bochs.h"
30 #include "cpu.h"
31 #define LOG_THIS BX_CPU_THIS_PTR
33 #if BX_SUPPORT_X86_64
35 static unsigned partial_add(Bit32u *sum,Bit32u b)
37 Bit32u t = *sum;
38 *sum += b;
39 return (*sum < t);
42 void long_mul(Bit128u *product, Bit64u op1, Bit64u op2)
44 Bit32u op_1[2],op_2[2];
45 Bit32u result[5];
46 Bit64u nn;
47 unsigned c;
49 int i,j,k;
51 op_1[0] = (Bit32u)(op1 & 0xffffffff);
52 op_1[1] = (Bit32u)(op1 >> 32);
53 op_2[0] = (Bit32u)(op2 & 0xffffffff);
54 op_2[1] = (Bit32u)(op2 >> 32);
56 for (i = 0; i < 4; i++) result[i] = 0;
58 for (i = 0; i < 2; i++) {
59 for (j = 0; j < 2; j++) {
60 nn = (Bit64u) op_1[i] * (Bit64u) op_2[j];
61 k = i + j;
62 c = partial_add(&result[k++], (Bit32u)(nn & 0xffffffff));
63 c = partial_add(&result[k++], (Bit32u)(nn >> 32) + c);
64 while (k < 4 && c != 0) {
65 c = partial_add(&result[k++], c);
70 product->lo = result[0] + ((Bit64u) result[1] << 32);
71 product->hi = result[2] + ((Bit64u) result[3] << 32);
74 void long_neg(Bit128s *n)
76 Bit64u t = n->lo;
77 n->lo = - (Bit64s)(n->lo);
78 if (t - 1 > t) --n->hi;
79 n->hi = ~n->hi;
82 void long_imul(Bit128s *product, Bit64s op1, Bit64s op2)
84 unsigned s1,s2;
86 if ((s1 = (op1 < 0))) op1 = -op1;
87 if ((s2 = (op2 < 0))) op2 = -op2;
88 long_mul((Bit128u*)product,(Bit64u)op1,(Bit64u)op2);
89 if (s1 ^ s2)
90 long_neg(product);
93 void long_shl(Bit128u *a)
95 Bit64u c;
96 c = a->lo >> 63;
97 a->lo <<= 1;
98 a->hi <<= 1;
99 a->hi |= c;
102 void long_shr(Bit128u *a)
104 Bit64u c;
105 c = a->hi << 63;
106 a->hi >>= 1;
107 a->lo >>= 1;
108 a->lo |= c;
111 unsigned long_sub(Bit128u *a,Bit128u *b)
113 Bit64u t = a->lo;
114 a->lo -= b->lo;
115 int c = (a->lo > t);
116 t = a -> hi;
117 a->hi -= b->hi + c;
118 return(a->hi > t);
121 int long_le(Bit128u *a,Bit128u *b)
123 if (a->hi == b->hi) {
124 return(a->lo <= b->lo);
125 } else {
126 return(a->hi <= b->hi);
130 void long_div(Bit128u *quotient,Bit64u *remainder,Bit128u *dividend,Bit64u divisor)
133 n := 0;
134 while (divisor <= dividend) do
135 inc(n);
136 divisor := divisor * 2;
137 end;
138 quotient := 0;
139 while n > 0 do
140 divisor := divisor div 2;
141 quotient := quotient * 2;
142 temp := dividend;
143 dividend := dividend - divisor;
144 if temp > dividend then
145 dividend := temp;
146 else
147 inc(quotient);
148 end;
149 dec(n);
150 end;
151 remainder := dividend;
154 Bit128u d,acc,q,temp;
155 int n,c;
157 d.lo = divisor;
158 d.hi = 0;
159 acc.lo = dividend->lo;
160 acc.hi = dividend->hi;
161 q.lo = 0;
162 q.hi = 0;
163 n = 0;
165 while (long_le(&d,&acc) && n < 128) {
166 long_shl(&d);
167 n++;
170 while (n > 0) {
171 long_shr(&d);
172 long_shl(&q);
173 temp.lo = acc.lo;
174 temp.hi = acc.hi;
175 c = long_sub(&acc,&d);
176 if (c) {
177 acc.lo = temp.lo;
178 acc.hi = temp.hi;
179 } else {
180 q.lo++;
182 n--;
185 *remainder = acc.lo;
186 quotient->lo = q.lo;
187 quotient->hi = q.hi;
190 void long_idiv(Bit128s *quotient,Bit64s *remainder,Bit128s *dividend,Bit64s divisor)
192 unsigned s1,s2;
193 Bit128s temp;
195 temp = *dividend;
196 if ((s1 = (temp.hi < 0))) {
197 long_neg(&temp);
199 if ((s2 = (divisor < 0))) divisor = -divisor;
200 long_div((Bit128u*)quotient,(Bit64u*)remainder,(Bit128u*)&temp,divisor);
201 if (s1 ^ s2) {
202 long_neg(quotient);
204 if (s2) {
205 *remainder = -*remainder;
209 void BX_CPP_AttrRegparmN(1) BX_CPU_C::MUL_RAXEqR(bxInstruction_c *i)
211 Bit128u product_128;
213 Bit64u op1_64 = RAX;
214 Bit64u op2_64 = BX_READ_64BIT_REG(i->rm());
216 // product_128 = ((Bit128u) op1_64) * ((Bit128u) op2_64);
217 // product_64l = (Bit64u) (product_128 & 0xFFFFFFFFFFFFFFFF);
218 // product_64h = (Bit64u) (product_128 >> 64);
220 long_mul(&product_128,op1_64,op2_64);
222 /* now write product back to destination */
223 RAX = product_128.lo;
224 RDX = product_128.hi;
226 /* set EFLAGS */
227 SET_FLAGS_OSZAPC_LOGIC_64(product_128.lo);
228 if(product_128.hi != 0)
230 ASSERT_FLAGS_OxxxxC();
234 void BX_CPP_AttrRegparmN(1) BX_CPU_C::IMUL_RAXEqR(bxInstruction_c *i)
236 Bit128s product_128;
238 Bit64s op1_64 = RAX;
239 Bit64s op2_64 = BX_READ_64BIT_REG(i->rm());
241 // product_128 = ((Bit128s) op1_64) * ((Bit128s) op2_64);
242 // product_64l = (Bit64u) (product_128 & 0xFFFFFFFFFFFFFFFF);
243 // product_64h = (Bit64u) (product_128 >> 64);
245 long_imul(&product_128,op1_64,op2_64);
247 /* now write product back to destination */
248 RAX = product_128.lo;
249 RDX = product_128.hi;
251 /* set eflags:
252 * IMUL r/m64: condition for clearing CF & OF:
253 * RDX:RAX = sign-extend of RAX
256 SET_FLAGS_OSZAPC_LOGIC_64(product_128.lo);
257 if (((Bit64s)(product_128.lo) >= 0 && product_128.hi == 0) ||
258 ((Bit64s)(product_128.lo) < 0 && product_128.hi == (Bit64s) BX_CONST64(0xffffffffffffffff)))
260 ASSERT_FLAGS_OxxxxC();
264 void BX_CPP_AttrRegparmN(1) BX_CPU_C::DIV_RAXEqR(bxInstruction_c *i)
266 Bit64u remainder_64, quotient_64l;
267 Bit128u op1_128, quotient_128;
269 Bit64u op2_64 = BX_READ_64BIT_REG(i->rm());
270 if (op2_64 == 0) {
271 exception(BX_DE_EXCEPTION, 0, 0);
274 op1_128.lo = RAX;
275 op1_128.hi = RDX;
277 // quotient_128 = op1_128 / op2_64;
278 // remainder_64 = (Bit64u) (op1_128 % op2_64);
279 // quotient_64l = (Bit64u) (quotient_128 & 0xFFFFFFFFFFFFFFFF);
281 long_div(&quotient_128,&remainder_64,&op1_128,op2_64);
282 quotient_64l = quotient_128.lo;
284 if (quotient_128.hi != 0)
285 exception(BX_DE_EXCEPTION, 0, 0);
287 /* set EFLAGS:
288 * DIV affects the following flags: O,S,Z,A,P,C are undefined
291 /* now write quotient back to destination */
292 RAX = quotient_64l;
293 RDX = remainder_64;
296 void BX_CPP_AttrRegparmN(1) BX_CPU_C::IDIV_RAXEqR(bxInstruction_c *i)
298 Bit64s remainder_64, quotient_64l;
299 Bit128s op1_128, quotient_128;
301 op1_128.lo = RAX;
302 op1_128.hi = RDX;
304 /* check MIN_INT case */
305 if ((op1_128.hi == (Bit64s) BX_CONST64(0x8000000000000000)) && (!op1_128.lo))
306 exception(BX_DE_EXCEPTION, 0, 0);
308 Bit64s op2_64 = BX_READ_64BIT_REG(i->rm());
310 if (op2_64 == 0) {
311 exception(BX_DE_EXCEPTION, 0, 0);
314 // quotient_128 = op1_128 / op2_64;
315 // remainder_64 = (Bit64s) (op1_128 % op2_64);
316 // quotient_64l = (Bit64s) (quotient_128 & 0xFFFFFFFFFFFFFFFF);
318 long_idiv(&quotient_128,&remainder_64,&op1_128,op2_64);
319 quotient_64l = quotient_128.lo;
321 if ((!(quotient_128.lo & BX_CONST64(0x8000000000000000)) && quotient_128.hi != (Bit64s) 0) ||
322 (quotient_128.lo & BX_CONST64(0x8000000000000000)) && quotient_128.hi != (Bit64s) BX_CONST64(0xffffffffffffffff))
324 exception(BX_DE_EXCEPTION, 0, 0);
327 /* set EFLAGS:
328 * IDIV affects the following flags: O,S,Z,A,P,C are undefined
331 /* now write quotient back to destination */
332 RAX = quotient_64l;
333 RDX = remainder_64;
336 void BX_CPP_AttrRegparmN(1) BX_CPU_C::IMUL_GqEqIdR(bxInstruction_c *i)
338 Bit128s product_128;
340 Bit64s op2_64 = BX_READ_64BIT_REG(i->rm());
341 Bit64s op3_64 = (Bit32s) i->Id();
343 long_imul(&product_128,op2_64,op3_64);
345 /* now write product back to destination */
346 BX_WRITE_64BIT_REG(i->nnn(), product_128.lo);
348 SET_FLAGS_OSZAPC_LOGIC_64(product_128.lo);
349 if (((Bit64s)(product_128.lo) >= 0 && product_128.hi == 0) ||
350 ((Bit64s)(product_128.lo) < 0 && product_128.hi == (Bit64s) BX_CONST64(0xffffffffffffffff)))
352 ASSERT_FLAGS_OxxxxC();
356 void BX_CPP_AttrRegparmN(1) BX_CPU_C::IMUL_GqEqR(bxInstruction_c *i)
358 Bit128s product_128;
360 Bit64s op1_64 = BX_READ_64BIT_REG(i->nnn());
361 Bit64s op2_64 = BX_READ_64BIT_REG(i->rm());
363 long_imul(&product_128,op1_64,op2_64);
365 /* now write product back to destination */
366 BX_WRITE_64BIT_REG(i->nnn(), product_128.lo);
368 SET_FLAGS_OSZAPC_LOGIC_64(product_128.lo);
369 if (((Bit64s)(product_128.lo) >= 0 && product_128.hi == 0) ||
370 ((Bit64s)(product_128.lo) < 0 && product_128.hi == (Bit64s) BX_CONST64(0xffffffffffffffff)))
372 ASSERT_FLAGS_OxxxxC();
376 #endif /* if BX_SUPPORT_X86_64 */