1 /////////////////////////////////////////////////////////////////////////
2 // $Id: mult64.cc,v 1.33 2008/08/10 21:16:12 sshwarts Exp $
3 /////////////////////////////////////////////////////////////////////////
5 // Copyright (C) 2001 MandrakeSoft S.A.
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
31 #define LOG_THIS BX_CPU_THIS_PTR
35 static unsigned partial_add(Bit32u
*sum
,Bit32u b
)
42 void long_mul(Bit128u
*product
, Bit64u op1
, Bit64u op2
)
44 Bit32u op_1
[2],op_2
[2];
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
];
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
)
77 n
->lo
= - (Bit64s
)(n
->lo
);
78 if (t
- 1 > t
) --n
->hi
;
82 void long_imul(Bit128s
*product
, Bit64s op1
, Bit64s op2
)
86 if ((s1
= (op1
< 0))) op1
= -op1
;
87 if ((s2
= (op2
< 0))) op2
= -op2
;
88 long_mul((Bit128u
*)product
,(Bit64u
)op1
,(Bit64u
)op2
);
93 void long_shl(Bit128u
*a
)
102 void long_shr(Bit128u
*a
)
111 unsigned long_sub(Bit128u
*a
,Bit128u
*b
)
121 int long_le(Bit128u
*a
,Bit128u
*b
)
123 if (a
->hi
== b
->hi
) {
124 return(a
->lo
<= b
->lo
);
126 return(a
->hi
<= b
->hi
);
130 void long_div(Bit128u
*quotient
,Bit64u
*remainder
,Bit128u
*dividend
,Bit64u divisor
)
134 while (divisor <= dividend) do
136 divisor := divisor * 2;
140 divisor := divisor div 2;
141 quotient := quotient * 2;
143 dividend := dividend - divisor;
144 if temp > dividend then
151 remainder := dividend;
154 Bit128u d
,acc
,q
,temp
;
159 acc
.lo
= dividend
->lo
;
160 acc
.hi
= dividend
->hi
;
165 while (long_le(&d
,&acc
) && n
< 128) {
175 c
= long_sub(&acc
,&d
);
190 void long_idiv(Bit128s
*quotient
,Bit64s
*remainder
,Bit128s
*dividend
,Bit64s divisor
)
196 if ((s1
= (temp
.hi
< 0))) {
199 if ((s2
= (divisor
< 0))) divisor
= -divisor
;
200 long_div((Bit128u
*)quotient
,(Bit64u
*)remainder
,(Bit128u
*)&temp
,divisor
);
205 *remainder
= -*remainder
;
209 void BX_CPP_AttrRegparmN(1) BX_CPU_C::MUL_RAXEqR(bxInstruction_c
*i
)
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
;
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
)
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
;
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());
271 exception(BX_DE_EXCEPTION
, 0, 0);
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("ient_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);
288 * DIV affects the following flags: O,S,Z,A,P,C are undefined
291 /* now write quotient back to destination */
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
;
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());
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("ient_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);
328 * IDIV affects the following flags: O,S,Z,A,P,C are undefined
331 /* now write quotient back to destination */
336 void BX_CPP_AttrRegparmN(1) BX_CPU_C::IMUL_GqEqIdR(bxInstruction_c
*i
)
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
)
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 */