finished simplifying string operations
[qemu/qemu_0_9_1_stable.git] / ops_template_mem.h
blobeacaabba5ca20e5301a0c4f605d58789495b200f
1 /*
2 * i386 micro operations (included several times to generate
3 * different operand sizes)
4 *
5 * Copyright (c) 2003 Fabrice Bellard
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 #ifdef MEM_WRITE
23 #if DATA_BITS == 8
24 #define MEM_SUFFIX b_mem
25 #elif DATA_BITS == 16
26 #define MEM_SUFFIX w_mem
27 #elif DATA_BITS == 32
28 #define MEM_SUFFIX l_mem
29 #endif
31 #else
33 #define MEM_SUFFIX SUFFIX
35 #endif
37 void OPPROTO glue(glue(op_rol, MEM_SUFFIX), _T0_T1_cc)(void)
39 int count, src;
40 count = T1 & SHIFT_MASK;
41 if (count) {
42 src = T0;
43 T0 &= DATA_MASK;
44 T0 = (T0 << count) | (T0 >> (DATA_BITS - count));
45 #ifdef MEM_WRITE
46 glue(st, SUFFIX)((uint8_t *)A0, T0);
47 #else
48 /* gcc 3.2 workaround. This is really a bug in gcc. */
49 asm volatile("" : : "r" (T0));
50 #endif
51 CC_SRC = (cc_table[CC_OP].compute_all() & ~(CC_O | CC_C)) |
52 (lshift(src ^ T0, 11 - (DATA_BITS - 1)) & CC_O) |
53 (T0 & CC_C);
54 CC_OP = CC_OP_EFLAGS;
56 FORCE_RET();
59 void OPPROTO glue(glue(op_ror, MEM_SUFFIX), _T0_T1_cc)(void)
61 int count, src;
62 count = T1 & SHIFT_MASK;
63 if (count) {
64 src = T0;
65 T0 &= DATA_MASK;
66 T0 = (T0 >> count) | (T0 << (DATA_BITS - count));
67 #ifdef MEM_WRITE
68 glue(st, SUFFIX)((uint8_t *)A0, T0);
69 #else
70 /* gcc 3.2 workaround. This is really a bug in gcc. */
71 asm volatile("" : : "r" (T0));
72 #endif
73 CC_SRC = (cc_table[CC_OP].compute_all() & ~(CC_O | CC_C)) |
74 (lshift(src ^ T0, 11 - (DATA_BITS - 1)) & CC_O) |
75 ((T0 >> (DATA_BITS - 1)) & CC_C);
76 CC_OP = CC_OP_EFLAGS;
78 FORCE_RET();
81 void OPPROTO glue(glue(op_rol, MEM_SUFFIX), _T0_T1)(void)
83 int count;
84 count = T1 & SHIFT_MASK;
85 if (count) {
86 T0 &= DATA_MASK;
87 T0 = (T0 << count) | (T0 >> (DATA_BITS - count));
88 #ifdef MEM_WRITE
89 glue(st, SUFFIX)((uint8_t *)A0, T0);
90 #endif
92 FORCE_RET();
95 void OPPROTO glue(glue(op_ror, MEM_SUFFIX), _T0_T1)(void)
97 int count;
98 count = T1 & SHIFT_MASK;
99 if (count) {
100 T0 &= DATA_MASK;
101 T0 = (T0 >> count) | (T0 << (DATA_BITS - count));
102 #ifdef MEM_WRITE
103 glue(st, SUFFIX)((uint8_t *)A0, T0);
104 #endif
106 FORCE_RET();
109 void OPPROTO glue(glue(op_rcl, MEM_SUFFIX), _T0_T1_cc)(void)
111 int count, res, eflags;
112 unsigned int src;
114 count = T1 & 0x1f;
115 #if DATA_BITS == 16
116 count = rclw_table[count];
117 #elif DATA_BITS == 8
118 count = rclb_table[count];
119 #endif
120 if (count) {
121 eflags = cc_table[CC_OP].compute_all();
122 T0 &= DATA_MASK;
123 src = T0;
124 res = (T0 << count) | ((eflags & CC_C) << (count - 1));
125 if (count > 1)
126 res |= T0 >> (DATA_BITS + 1 - count);
127 T0 = res;
128 #ifdef MEM_WRITE
129 glue(st, SUFFIX)((uint8_t *)A0, T0);
130 #endif
131 CC_SRC = (eflags & ~(CC_C | CC_O)) |
132 (lshift(src ^ T0, 11 - (DATA_BITS - 1)) & CC_O) |
133 ((src >> (DATA_BITS - count)) & CC_C);
134 CC_OP = CC_OP_EFLAGS;
136 FORCE_RET();
139 void OPPROTO glue(glue(op_rcr, MEM_SUFFIX), _T0_T1_cc)(void)
141 int count, res, eflags;
142 unsigned int src;
144 count = T1 & 0x1f;
145 #if DATA_BITS == 16
146 count = rclw_table[count];
147 #elif DATA_BITS == 8
148 count = rclb_table[count];
149 #endif
150 if (count) {
151 eflags = cc_table[CC_OP].compute_all();
152 T0 &= DATA_MASK;
153 src = T0;
154 res = (T0 >> count) | ((eflags & CC_C) << (DATA_BITS - count));
155 if (count > 1)
156 res |= T0 << (DATA_BITS + 1 - count);
157 T0 = res;
158 #ifdef MEM_WRITE
159 glue(st, SUFFIX)((uint8_t *)A0, T0);
160 #endif
161 CC_SRC = (eflags & ~(CC_C | CC_O)) |
162 (lshift(src ^ T0, 11 - (DATA_BITS - 1)) & CC_O) |
163 ((src >> (count - 1)) & CC_C);
164 CC_OP = CC_OP_EFLAGS;
166 FORCE_RET();
169 void OPPROTO glue(glue(op_shl, MEM_SUFFIX), _T0_T1_cc)(void)
171 int count, src;
172 count = T1 & 0x1f;
173 if (count) {
174 src = (DATA_TYPE)T0 << (count - 1);
175 T0 = T0 << count;
176 #ifdef MEM_WRITE
177 glue(st, SUFFIX)((uint8_t *)A0, T0);
178 #endif
179 CC_SRC = src;
180 CC_DST = T0;
181 CC_OP = CC_OP_SHLB + SHIFT;
183 FORCE_RET();
186 void OPPROTO glue(glue(op_shr, MEM_SUFFIX), _T0_T1_cc)(void)
188 int count, src;
189 count = T1 & 0x1f;
190 if (count) {
191 T0 &= DATA_MASK;
192 src = T0 >> (count - 1);
193 T0 = T0 >> count;
194 #ifdef MEM_WRITE
195 glue(st, SUFFIX)((uint8_t *)A0, T0);
196 #endif
197 CC_SRC = src;
198 CC_DST = T0;
199 CC_OP = CC_OP_SARB + SHIFT;
201 FORCE_RET();
204 void OPPROTO glue(glue(op_sar, MEM_SUFFIX), _T0_T1_cc)(void)
206 int count, src;
207 count = T1 & 0x1f;
208 if (count) {
209 src = (DATA_STYPE)T0;
210 T0 = src >> count;
211 src = src >> (count - 1);
212 #ifdef MEM_WRITE
213 glue(st, SUFFIX)((uint8_t *)A0, T0);
214 #endif
215 CC_SRC = src;
216 CC_DST = T0;
217 CC_OP = CC_OP_SARB + SHIFT;
219 FORCE_RET();
222 #if DATA_BITS == 16
223 /* XXX: overflow flag might be incorrect in some cases in shldw */
224 void OPPROTO glue(glue(op_shld, MEM_SUFFIX), _T0_T1_im_cc)(void)
226 int count;
227 unsigned int res, tmp;
228 count = PARAM1;
229 T1 &= 0xffff;
230 res = T1 | (T0 << 16);
231 tmp = res >> (32 - count);
232 res <<= count;
233 if (count > 16)
234 res |= T1 << (count - 16);
235 T0 = res >> 16;
236 #ifdef MEM_WRITE
237 glue(st, SUFFIX)((uint8_t *)A0, T0);
238 #endif
239 CC_SRC = tmp;
240 CC_DST = T0;
243 void OPPROTO glue(glue(op_shld, MEM_SUFFIX), _T0_T1_ECX_cc)(void)
245 int count;
246 unsigned int res, tmp;
247 count = ECX & 0x1f;
248 if (count) {
249 T1 &= 0xffff;
250 res = T1 | (T0 << 16);
251 tmp = res >> (32 - count);
252 res <<= count;
253 if (count > 16)
254 res |= T1 << (count - 16);
255 T0 = res >> 16;
256 #ifdef MEM_WRITE
257 glue(st, SUFFIX)((uint8_t *)A0, T0);
258 #endif
259 CC_SRC = tmp;
260 CC_DST = T0;
261 CC_OP = CC_OP_SARB + SHIFT;
263 FORCE_RET();
266 void OPPROTO glue(glue(op_shrd, MEM_SUFFIX), _T0_T1_im_cc)(void)
268 int count;
269 unsigned int res, tmp;
271 count = PARAM1;
272 res = (T0 & 0xffff) | (T1 << 16);
273 tmp = res >> (count - 1);
274 res >>= count;
275 if (count > 16)
276 res |= T1 << (32 - count);
277 T0 = res;
278 #ifdef MEM_WRITE
279 glue(st, SUFFIX)((uint8_t *)A0, T0);
280 #endif
281 CC_SRC = tmp;
282 CC_DST = T0;
286 void OPPROTO glue(glue(op_shrd, MEM_SUFFIX), _T0_T1_ECX_cc)(void)
288 int count;
289 unsigned int res, tmp;
291 count = ECX & 0x1f;
292 if (count) {
293 res = (T0 & 0xffff) | (T1 << 16);
294 tmp = res >> (count - 1);
295 res >>= count;
296 if (count > 16)
297 res |= T1 << (32 - count);
298 T0 = res;
299 #ifdef MEM_WRITE
300 glue(st, SUFFIX)((uint8_t *)A0, T0);
301 #endif
302 CC_SRC = tmp;
303 CC_DST = T0;
304 CC_OP = CC_OP_SARB + SHIFT;
306 FORCE_RET();
308 #endif
310 #if DATA_BITS == 32
311 void OPPROTO glue(glue(op_shld, MEM_SUFFIX), _T0_T1_im_cc)(void)
313 int count, tmp;
314 count = PARAM1;
315 T0 &= DATA_MASK;
316 T1 &= DATA_MASK;
317 tmp = T0 << (count - 1);
318 T0 = (T0 << count) | (T1 >> (DATA_BITS - count));
319 #ifdef MEM_WRITE
320 glue(st, SUFFIX)((uint8_t *)A0, T0);
321 #endif
322 CC_SRC = tmp;
323 CC_DST = T0;
326 void OPPROTO glue(glue(op_shld, MEM_SUFFIX), _T0_T1_ECX_cc)(void)
328 int count, tmp;
329 count = ECX & 0x1f;
330 if (count) {
331 T0 &= DATA_MASK;
332 T1 &= DATA_MASK;
333 tmp = T0 << (count - 1);
334 T0 = (T0 << count) | (T1 >> (DATA_BITS - count));
335 #ifdef MEM_WRITE
336 glue(st, SUFFIX)((uint8_t *)A0, T0);
337 #endif
338 CC_SRC = tmp;
339 CC_DST = T0;
340 CC_OP = CC_OP_SHLB + SHIFT;
342 FORCE_RET();
345 void OPPROTO glue(glue(op_shrd, MEM_SUFFIX), _T0_T1_im_cc)(void)
347 int count, tmp;
348 count = PARAM1;
349 T0 &= DATA_MASK;
350 T1 &= DATA_MASK;
351 tmp = T0 >> (count - 1);
352 T0 = (T0 >> count) | (T1 << (DATA_BITS - count));
353 #ifdef MEM_WRITE
354 glue(st, SUFFIX)((uint8_t *)A0, T0);
355 #endif
356 CC_SRC = tmp;
357 CC_DST = T0;
361 void OPPROTO glue(glue(op_shrd, MEM_SUFFIX), _T0_T1_ECX_cc)(void)
363 int count, tmp;
364 count = ECX & 0x1f;
365 if (count) {
366 T0 &= DATA_MASK;
367 T1 &= DATA_MASK;
368 tmp = T0 >> (count - 1);
369 T0 = (T0 >> count) | (T1 << (DATA_BITS - count));
370 #ifdef MEM_WRITE
371 glue(st, SUFFIX)((uint8_t *)A0, T0);
372 #endif
373 CC_SRC = tmp;
374 CC_DST = T0;
375 CC_OP = CC_OP_SARB + SHIFT;
377 FORCE_RET();
379 #endif
381 /* carry add/sub (we only need to set CC_OP differently) */
383 void OPPROTO glue(glue(op_adc, MEM_SUFFIX), _T0_T1_cc)(void)
385 int cf;
386 cf = cc_table[CC_OP].compute_c();
387 T0 = T0 + T1 + cf;
388 #ifdef MEM_WRITE
389 glue(st, SUFFIX)((uint8_t *)A0, T0);
390 #endif
391 CC_SRC = T1;
392 CC_DST = T0;
393 CC_OP = CC_OP_ADDB + SHIFT + cf * 3;
396 void OPPROTO glue(glue(op_sbb, MEM_SUFFIX), _T0_T1_cc)(void)
398 int cf;
399 cf = cc_table[CC_OP].compute_c();
400 T0 = T0 - T1 - cf;
401 #ifdef MEM_WRITE
402 glue(st, SUFFIX)((uint8_t *)A0, T0);
403 #endif
404 CC_SRC = T1;
405 CC_DST = T0;
406 CC_OP = CC_OP_SUBB + SHIFT + cf * 3;
409 void OPPROTO glue(glue(op_cmpxchg, MEM_SUFFIX), _T0_T1_EAX_cc)(void)
411 unsigned int src, dst;
413 src = T0;
414 dst = EAX - T0;
415 if ((DATA_TYPE)dst == 0) {
416 T0 = T1;
417 } else {
418 EAX = (EAX & ~DATA_MASK) | (T0 & DATA_MASK);
420 #ifdef MEM_WRITE
421 glue(st, SUFFIX)((uint8_t *)A0, T0);
422 #endif
423 CC_SRC = src;
424 CC_DST = dst;
425 FORCE_RET();
428 #undef MEM_SUFFIX
429 #undef MEM_WRITE