1 /////////////////////////////////////////////////////////////////////////
2 // $Id: mult16.cc,v 1.21 2006/03/06 22:03:01 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
28 #define NEED_CPU_REG_SHORTCUTS 1
31 #define LOG_THIS BX_CPU_THIS_PTR
34 void BX_CPU_C::MUL_AXEw(bxInstruction_c
*i
)
36 Bit16u op1_16
, op2_16
;
40 /* op2 is a register or memory reference */
42 op2_16
= BX_READ_16BIT_REG(i
->rm());
45 /* pointer, segment address pair */
46 read_virtual_word(i
->seg(), RMAddr(i
), &op2_16
);
49 Bit32u product_32
= ((Bit32u
) op1_16
) * ((Bit32u
) op2_16
);
50 Bit16u product_16l
= (product_32
& 0xFFFF);
51 Bit16u product_16h
= product_32
>> 16;
54 SET_FLAGS_OSZAPC_S1S2_16(product_16l
, product_16h
, BX_INSTR_MUL16
);
56 /* now write product back to destination */
61 void BX_CPU_C::IMUL_AXEw(bxInstruction_c
*i
)
63 Bit16s op1_16
, op2_16
;
67 /* op2 is a register or memory reference */
69 op2_16
= BX_READ_16BIT_REG(i
->rm());
72 /* pointer, segment address pair */
73 read_virtual_word(i
->seg(), RMAddr(i
), (Bit16u
*) &op2_16
);
76 Bit32s product_32
= ((Bit32s
) op1_16
) * ((Bit32s
) op2_16
);
77 Bit16u product_16l
= (product_32
& 0xFFFF);
78 Bit16u product_16h
= product_32
>> 16;
80 /* now write product back to destination */
85 * IMUL r/m16: condition for clearing CF & OF:
86 * DX:AX = sign-extend of AX
88 SET_FLAGS_OSZAPC_S1S2_16(product_16l
, product_16h
, BX_INSTR_IMUL16
);
91 void BX_CPU_C::DIV_AXEw(bxInstruction_c
*i
)
93 Bit16u op2_16
, remainder_16
, quotient_16l
;
94 Bit32u op1_32
, quotient_32
;
96 op1_32
= (((Bit32u
) DX
) << 16) | ((Bit32u
) AX
);
98 /* op2 is a register or memory reference */
100 op2_16
= BX_READ_16BIT_REG(i
->rm());
103 /* pointer, segment address pair */
104 read_virtual_word(i
->seg(), RMAddr(i
), &op2_16
);
108 exception(BX_DE_EXCEPTION
, 0, 0);
110 quotient_32
= op1_32
/ op2_16
;
111 remainder_16
= op1_32
% op2_16
;
112 quotient_16l
= quotient_32
& 0xFFFF;
114 if (quotient_32
!= quotient_16l
)
115 exception(BX_DE_EXCEPTION
, 0, 0);
118 * DIV affects the following flags: O,S,Z,A,P,C are undefined
121 #if INTEL_DIV_FLAG_BUG == 1
125 /* now write quotient back to destination */
130 void BX_CPU_C::IDIV_AXEw(bxInstruction_c
*i
)
132 Bit16s op2_16
, remainder_16
, quotient_16l
;
133 Bit32s op1_32
, quotient_32
;
135 op1_32
= ((((Bit32u
) DX
) << 16) | ((Bit32u
) AX
));
137 /* op2 is a register or memory reference */
139 op2_16
= BX_READ_16BIT_REG(i
->rm());
142 /* pointer, segment address pair */
143 read_virtual_word(i
->seg(), RMAddr(i
), (Bit16u
*) &op2_16
);
147 exception(BX_DE_EXCEPTION
, 0, 0);
149 /* check MIN_INT divided by -1 case */
150 if ((op1_32
== ((Bit32s
)0x80000000)) && (op2_16
== -1))
151 exception(BX_DE_EXCEPTION
, 0, 0);
153 quotient_32
= op1_32
/ op2_16
;
154 remainder_16
= op1_32
% op2_16
;
155 quotient_16l
= quotient_32
& 0xFFFF;
157 if (quotient_32
!= quotient_16l
)
158 exception(BX_DE_EXCEPTION
, 0, 0);
161 * IDIV affects the following flags: O,S,Z,A,P,C are undefined
164 #if INTEL_DIV_FLAG_BUG == 1
168 /* now write quotient back to destination */
173 void BX_CPU_C::IMUL_GwEwIw(bxInstruction_c
*i
)
175 Bit16s op2_16
, op3_16
;
179 /* op2 is a register or memory reference */
181 op2_16
= BX_READ_16BIT_REG(i
->rm());
184 /* pointer, segment address pair */
185 read_virtual_word(i
->seg(), RMAddr(i
), (Bit16u
*) &op2_16
);
188 Bit32s product_32
= op2_16
* op3_16
;
189 Bit16u product_16l
= (product_32
& 0xFFFF);
190 Bit16u product_16h
= (product_32
>> 16);
192 /* now write product back to destination */
193 BX_WRITE_16BIT_REG(i
->nnn(), product_16l
);
196 * IMUL r16,r/m16,imm16: condition for clearing CF & OF:
197 * result exactly fits within r16
199 SET_FLAGS_OSZAPC_S1S2_16(product_16l
, product_16h
, BX_INSTR_IMUL16
);
202 void BX_CPU_C::IMUL_GwEw(bxInstruction_c
*i
)
204 Bit16s op1_16
, op2_16
;
206 /* op2 is a register or memory reference */
208 op2_16
= BX_READ_16BIT_REG(i
->rm());
211 /* pointer, segment address pair */
212 read_virtual_word(i
->seg(), RMAddr(i
), (Bit16u
*) &op2_16
);
215 op1_16
= BX_READ_16BIT_REG(i
->nnn());
217 Bit32s product_32
= op1_16
* op2_16
;
218 Bit16u product_16l
= (product_32
& 0xFFFF);
219 Bit16u product_16h
= (product_32
>> 16);
221 /* now write product back to destination */
222 BX_WRITE_16BIT_REG(i
->nnn(), product_16l
);
225 * IMUL r16,r/m16,imm16: condition for clearing CF & OF:
226 * result exactly fits within r16
228 SET_FLAGS_OSZAPC_S1S2_16(product_16l
, product_16h
, BX_INSTR_IMUL16
);