1 // Copyright (C) 2001 MandrakeSoft S.A.
5 // 75002 Paris - France
6 // http://www.linux-mandrake.com/
7 // http://www.mandrakesoft.com/
9 // This library is free software; you can redistribute it and/or
10 // modify it under the terms of the GNU Lesser General Public
11 // License as published by the Free Software Foundation; either
12 // version 2 of the License, or (at your option) any later version.
14 // This library is distributed in the hope that it will be useful,
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 // Lesser General Public License for more details.
19 // You should have received a copy of the GNU Lesser General Public
20 // License along with this library; if not, write to the Free Software
21 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 #define NEED_CPU_REG_SHORTCUTS 1
30 #define LOG_THIS BX_CPU_THIS_PTR
36 BX_CPU_C::MUL_AXEw(BxInstruction_t *i)
38 Bit16u op1_16, op2_16, product_16h, product_16l;
44 /* op2 is a register or memory reference */
46 op2_16 = BX_READ_16BIT_REG(i->rm);
49 /* pointer, segment address pair */
50 read_virtual_word(i->seg, i->rm_addr, &op2_16);
53 product_32 = ((Bit32u) op1_16) * ((Bit32u) op2_16);
55 product_16l = (product_32 & 0xFFFF);
56 product_16h = product_32 >> 16;
58 /* now write product back to destination */
64 * MUL affects the following flags: C,O
67 temp_flag = (product_16h != 0);
68 SET_FLAGS_OxxxxC(temp_flag, temp_flag);
74 BX_CPU_C::IMUL_AXEw(BxInstruction_t *i)
76 Bit16s op1_16, op2_16;
78 Bit16u product_16h, product_16l;
82 /* op2 is a register or memory reference */
84 op2_16 = BX_READ_16BIT_REG(i->rm);
87 /* pointer, segment address pair */
88 read_virtual_word(i->seg, i->rm_addr, (Bit16u *) &op2_16);
91 product_32 = ((Bit32s) op1_16) * ((Bit32s) op2_16);
93 product_16l = (product_32 & 0xFFFF);
94 product_16h = product_32 >> 16;
96 /* now write product back to destination */
102 * IMUL affects the following flags: C,O
103 * IMUL r/m16: condition for clearing CF & OF:
104 * DX:AX = sign-extend of AX
107 if ( (DX==0xffff) && (AX & 0x8000) ) {
108 SET_FLAGS_OxxxxC(0, 0);
110 else if ( (DX==0x0000) && (AX < 0x8000) ) {
111 SET_FLAGS_OxxxxC(0, 0);
114 SET_FLAGS_OxxxxC(1, 1);
120 BX_CPU_C::DIV_AXEw(BxInstruction_t *i)
122 Bit16u op2_16, remainder_16, quotient_16l;
123 Bit32u op1_32, quotient_32;
125 op1_32 = (((Bit32u) DX) << 16) | ((Bit32u) AX);
127 /* op2 is a register or memory reference */
128 if (i->mod == 0xc0) {
129 op2_16 = BX_READ_16BIT_REG(i->rm);
132 /* pointer, segment address pair */
133 read_virtual_word(i->seg, i->rm_addr, &op2_16);
137 exception(BX_DE_EXCEPTION, 0, 0);
139 quotient_32 = op1_32 / op2_16;
140 remainder_16 = op1_32 % op2_16;
141 quotient_16l = quotient_32 & 0xFFFF;
143 if (quotient_32 != quotient_16l) {
144 exception(BX_DE_EXCEPTION, 0, 0);
148 * DIV affects the following flags: O,S,Z,A,P,C are undefined
151 #if INTEL_DIV_FLAG_BUG == 1
155 /* now write quotient back to destination */
163 BX_CPU_C::IDIV_AXEw(BxInstruction_t *i)
165 Bit16s op2_16, remainder_16, quotient_16l;
166 Bit32s op1_32, quotient_32;
168 op1_32 = ((((Bit32u) DX) << 16) | ((Bit32u) AX));
170 /* op2 is a register or memory reference */
171 if (i->mod == 0xc0) {
172 op2_16 = BX_READ_16BIT_REG(i->rm);
175 /* pointer, segment address pair */
176 read_virtual_word(i->seg, i->rm_addr, (Bit16u *) &op2_16);
180 exception(BX_DE_EXCEPTION, 0, 0);
182 quotient_32 = op1_32 / op2_16;
183 remainder_16 = op1_32 % op2_16;
184 quotient_16l = quotient_32 & 0xFFFF;
186 if (quotient_32 != quotient_16l) {
187 exception(BX_DE_EXCEPTION, 0, 0);
191 * IDIV affects the following flags: O,S,Z,A,P,C are undefined
194 #if INTEL_DIV_FLAG_BUG == 1
198 /* now write quotient back to destination */
206 BX_CPU_C::IMUL_GwEwIw(BxInstruction_t *i)
209 BX_PANIC(("IMUL_GvEvIv() unsupported on 8086!\n"));
214 Bit16s op2_16, op3_16;
219 /* op2 is a register or memory reference */
220 if (i->mod == 0xc0) {
221 op2_16 = BX_READ_16BIT_REG(i->rm);
224 /* pointer, segment address pair */
225 read_virtual_word(i->seg, i->rm_addr, (Bit16u *) &op2_16);
228 product_32 = op2_16 * op3_16;
230 product_16l = (product_32 & 0xFFFF);
232 /* now write product back to destination */
233 BX_WRITE_16BIT_REG(i->nnn, product_16l);
236 * IMUL affects the following flags: C,O
237 * IMUL r16,r/m16,imm16: condition for clearing CF & OF:
238 * result exactly fits within r16
241 if (product_32 > -32768 && product_32 < 32767) {
242 SET_FLAGS_OxxxxC(0, 0);
245 SET_FLAGS_OxxxxC(1, 1);
251 BX_CPU_C::IMUL_GwEw(BxInstruction_t *i)
254 BX_PANIC(("IMUL_GvEv() unsupported on 8086!\n"));
258 Bit16s op1_16, op2_16;
261 /* op2 is a register or memory reference */
262 if (i->mod == 0xc0) {
263 op2_16 = BX_READ_16BIT_REG(i->rm);
266 /* pointer, segment address pair */
267 read_virtual_word(i->seg, i->rm_addr, (Bit16u *) &op2_16);
270 op1_16 = BX_READ_16BIT_REG(i->nnn);
272 product_32 = op1_16 * op2_16;
274 product_16l = (product_32 & 0xFFFF);
276 /* now write product back to destination */
277 BX_WRITE_16BIT_REG(i->nnn, product_16l);
280 * IMUL affects the following flags: C,O
281 * IMUL r16,r/m16,imm16: condition for clearing CF & OF:
282 * result exactly fits within r16
285 if (product_32 > -32768 && product_32 < 32767) {
286 SET_FLAGS_OxxxxC(0, 0);
289 SET_FLAGS_OxxxxC(1, 1);