OSDN Git Service

866dbf74a7b185ca08f048e44078cd11794264ad
[pf3gnuchains/pf3gnuchains3x.git] / sid / component / bochs / cpu / mult16.cc
1 //  Copyright (C) 2001  MandrakeSoft S.A.
2 //
3 //    MandrakeSoft S.A.
4 //    43, rue d'Aboukir
5 //    75002 Paris - France
6 //    http://www.linux-mandrake.com/
7 //    http://www.mandrakesoft.com/
8 //
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.
13 //
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.
18 //
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
22
23
24
25
26
27
28 #define NEED_CPU_REG_SHORTCUTS 1
29 #include "bochs.h"
30 #define LOG_THIS BX_CPU_THIS_PTR
31
32
33
34
35   void
36 BX_CPU_C::MUL_AXEw(BxInstruction_t *i)
37 {
38     Bit16u op1_16, op2_16, product_16h, product_16l;
39     Bit32u product_32;
40     Boolean temp_flag;
41
42     op1_16 = AX;
43
44     /* op2 is a register or memory reference */
45     if (i->mod == 0xc0) {
46       op2_16 = BX_READ_16BIT_REG(i->rm);
47       }
48     else {
49       /* pointer, segment address pair */
50       read_virtual_word(i->seg, i->rm_addr, &op2_16);
51       }
52
53     product_32 = ((Bit32u) op1_16) * ((Bit32u) op2_16);
54
55     product_16l = (product_32 & 0xFFFF);
56     product_16h = product_32 >> 16;
57
58     /* now write product back to destination */
59
60     AX = product_16l;
61     DX = product_16h;
62
63     /* set eflags:
64      * MUL affects the following flags: C,O
65      */
66
67     temp_flag = (product_16h != 0);
68     SET_FLAGS_OxxxxC(temp_flag, temp_flag);
69 }
70
71
72
73   void
74 BX_CPU_C::IMUL_AXEw(BxInstruction_t *i)
75 {
76     Bit16s op1_16, op2_16;
77     Bit32s product_32;
78     Bit16u product_16h, product_16l;
79
80     op1_16 = AX;
81
82     /* op2 is a register or memory reference */
83     if (i->mod == 0xc0) {
84       op2_16 = BX_READ_16BIT_REG(i->rm);
85       }
86     else {
87       /* pointer, segment address pair */
88       read_virtual_word(i->seg, i->rm_addr, (Bit16u *) &op2_16);
89       }
90
91     product_32 = ((Bit32s) op1_16) * ((Bit32s) op2_16);
92
93     product_16l = (product_32 & 0xFFFF);
94     product_16h = product_32 >> 16;
95
96     /* now write product back to destination */
97
98     AX = product_16l;
99     DX = product_16h;
100
101     /* set eflags:
102      * IMUL affects the following flags: C,O
103      * IMUL r/m16: condition for clearing CF & OF:
104      *   DX:AX = sign-extend of AX
105      */
106
107     if ( (DX==0xffff) && (AX & 0x8000) ) {
108       SET_FLAGS_OxxxxC(0, 0);
109       }
110     else if ( (DX==0x0000) && (AX < 0x8000) ) {
111       SET_FLAGS_OxxxxC(0, 0);
112       }
113     else {
114       SET_FLAGS_OxxxxC(1, 1);
115       }
116 }
117
118
119   void
120 BX_CPU_C::DIV_AXEw(BxInstruction_t *i)
121 {
122     Bit16u op2_16, remainder_16, quotient_16l;
123     Bit32u op1_32, quotient_32;
124
125     op1_32 = (((Bit32u) DX) << 16) | ((Bit32u) AX);
126
127     /* op2 is a register or memory reference */
128     if (i->mod == 0xc0) {
129       op2_16 = BX_READ_16BIT_REG(i->rm);
130       }
131     else {
132       /* pointer, segment address pair */
133       read_virtual_word(i->seg, i->rm_addr, &op2_16);
134       }
135
136     if (op2_16 == 0) {
137       exception(BX_DE_EXCEPTION, 0, 0);
138       }
139     quotient_32 = op1_32 / op2_16;
140     remainder_16 = op1_32 % op2_16;
141     quotient_16l = quotient_32 & 0xFFFF;
142
143     if (quotient_32 != quotient_16l) {
144       exception(BX_DE_EXCEPTION, 0, 0);
145       }
146
147     /* set EFLAGS:
148      * DIV affects the following flags: O,S,Z,A,P,C are undefined
149      */
150
151 #if INTEL_DIV_FLAG_BUG == 1
152     set_CF(1);
153 #endif
154
155     /* now write quotient back to destination */
156
157     AX = quotient_16l;
158     DX = remainder_16;
159 }
160
161
162   void
163 BX_CPU_C::IDIV_AXEw(BxInstruction_t *i)
164 {
165     Bit16s op2_16, remainder_16, quotient_16l;
166     Bit32s op1_32, quotient_32;
167
168     op1_32 = ((((Bit32u) DX) << 16) | ((Bit32u) AX));
169
170     /* op2 is a register or memory reference */
171     if (i->mod == 0xc0) {
172       op2_16 = BX_READ_16BIT_REG(i->rm);
173       }
174     else {
175       /* pointer, segment address pair */
176       read_virtual_word(i->seg, i->rm_addr, (Bit16u *) &op2_16);
177       }
178
179     if (op2_16 == 0) {
180       exception(BX_DE_EXCEPTION, 0, 0);
181       }
182     quotient_32 = op1_32 / op2_16;
183     remainder_16 = op1_32 % op2_16;
184     quotient_16l = quotient_32 & 0xFFFF;
185
186     if (quotient_32 != quotient_16l) {
187       exception(BX_DE_EXCEPTION, 0, 0);
188       }
189
190     /* set EFLAGS:
191      * IDIV affects the following flags: O,S,Z,A,P,C are undefined
192      */
193
194 #if INTEL_DIV_FLAG_BUG == 1
195     set_CF(1);
196 #endif
197
198     /* now write quotient back to destination */
199
200     AX = quotient_16l;
201     DX = remainder_16;
202 }
203
204
205   void
206 BX_CPU_C::IMUL_GwEwIw(BxInstruction_t *i)
207 {
208 #if BX_CPU_LEVEL < 2
209   BX_PANIC(("IMUL_GvEvIv() unsupported on 8086!\n"));
210 #else
211
212
213     Bit16u product_16l;
214     Bit16s op2_16, op3_16;
215     Bit32s product_32;
216
217     op3_16 = i->Iw;
218
219     /* op2 is a register or memory reference */
220     if (i->mod == 0xc0) {
221       op2_16 = BX_READ_16BIT_REG(i->rm);
222       }
223     else {
224       /* pointer, segment address pair */
225       read_virtual_word(i->seg, i->rm_addr, (Bit16u *) &op2_16);
226       }
227
228     product_32 = op2_16 * op3_16;
229
230     product_16l = (product_32 & 0xFFFF);
231
232     /* now write product back to destination */
233     BX_WRITE_16BIT_REG(i->nnn, product_16l);
234
235     /* set eflags:
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
239      */
240
241     if (product_32 > -32768  && product_32 < 32767) {
242       SET_FLAGS_OxxxxC(0, 0);
243       }
244     else {
245       SET_FLAGS_OxxxxC(1, 1);
246       }
247 #endif
248 }
249
250   void
251 BX_CPU_C::IMUL_GwEw(BxInstruction_t *i)
252 {
253 #if BX_CPU_LEVEL < 3
254   BX_PANIC(("IMUL_GvEv() unsupported on 8086!\n"));
255 #else
256
257     Bit16u product_16l;
258     Bit16s op1_16, op2_16;
259     Bit32s product_32;
260
261     /* op2 is a register or memory reference */
262     if (i->mod == 0xc0) {
263       op2_16 = BX_READ_16BIT_REG(i->rm);
264       }
265     else {
266       /* pointer, segment address pair */
267       read_virtual_word(i->seg, i->rm_addr, (Bit16u *) &op2_16);
268       }
269
270     op1_16 = BX_READ_16BIT_REG(i->nnn);
271
272     product_32 = op1_16 * op2_16;
273
274     product_16l = (product_32 & 0xFFFF);
275
276     /* now write product back to destination */
277     BX_WRITE_16BIT_REG(i->nnn, product_16l);
278
279     /* set eflags:
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
283      */
284
285     if (product_32 > -32768  && product_32 < 32767) {
286       SET_FLAGS_OxxxxC(0, 0);
287       }
288     else {
289       SET_FLAGS_OxxxxC(1, 1);
290       }
291 #endif
292 }