OpenCores
URL https://opencores.org/ocsvn/ao486/ao486/trunk

Subversion Repositories ao486

[/] [ao486/] [trunk/] [bochs486/] [cpu/] [string.cc] - Blame information for rev 2

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 alfik
/////////////////////////////////////////////////////////////////////////
2
// $Id: string.cc 11117 2012-03-28 21:11:19Z sshwarts $
3
/////////////////////////////////////////////////////////////////////////
4
//
5
//  Copyright (C) 2001-2011  The Bochs Project
6
//
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.
11
//
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.
16
//
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., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA
20
/////////////////////////////////////////////////////////////////////////
21
 
22
#define NEED_CPU_REG_SHORTCUTS 1
23
#include "bochs.h"
24
#include "cpu.h"
25
#define LOG_THIS BX_CPU_THIS_PTR
26
 
27
//
28
// Repeat Speedups methods
29
//
30
 
31
#if BX_SUPPORT_REPEAT_SPEEDUPS
32
Bit32u BX_CPU_C::FastRepMOVSB(bxInstruction_c *i, unsigned srcSeg, bx_address srcOff, unsigned dstSeg, bx_address dstOff, Bit32u count)
33
{
34
  Bit32u bytesFitSrc, bytesFitDst;
35
  signed int pointerDelta;
36
  bx_address laddrDst, laddrSrc;
37
  Bit8u *hostAddrSrc, *hostAddrDst;
38
 
39
  BX_ASSERT(BX_CPU_THIS_PTR cpu_mode != BX_MODE_LONG_64);
40
 
41
  bx_segment_reg_t *srcSegPtr = &BX_CPU_THIS_PTR sregs[srcSeg];
42
  if (!(srcSegPtr->cache.valid & SegAccessROK))
43
    return 0;
44
  if ((srcOff | 0xfff) > srcSegPtr->cache.u.segment.limit_scaled)
45
    return 0;
46
 
47
  bx_segment_reg_t *dstSegPtr = &BX_CPU_THIS_PTR sregs[dstSeg];
48
  if (!(dstSegPtr->cache.valid & SegAccessWOK))
49
    return 0;
50
  if ((dstOff | 0xfff) > dstSegPtr->cache.u.segment.limit_scaled)
51
    return 0;
52
 
53
  laddrSrc = get_laddr32(srcSeg, srcOff);
54
 
55
  hostAddrSrc = v2h_read_byte(laddrSrc, BX_CPU_THIS_PTR user_pl);
56
  if (! hostAddrSrc) return 0;
57
 
58
  laddrDst = get_laddr32(dstSeg, dstOff);
59
 
60
  hostAddrDst = v2h_write_byte(laddrDst, BX_CPU_THIS_PTR user_pl);
61
  // Check that native host access was not vetoed for that page
62
  if (!hostAddrDst) return 0;
63
 
64
  // See how many bytes can fit in the rest of this page.
65
  if (BX_CPU_THIS_PTR get_DF()) {
66
    // Counting downward.
67
    bytesFitSrc = 1 + PAGE_OFFSET(laddrSrc);
68
    bytesFitDst = 1 + PAGE_OFFSET(laddrDst);
69
    pointerDelta = (signed int) -1;
70
  }
71
  else {
72
    // Counting upward.
73
    bytesFitSrc = 0x1000 - PAGE_OFFSET(laddrSrc);
74
    bytesFitDst = 0x1000 - PAGE_OFFSET(laddrDst);
75
    pointerDelta = (signed int)  1;
76
  }
77
 
78
  // Restrict word count to the number that will fit in either
79
  // source or dest pages.
80
  if (count > bytesFitSrc)
81
    count = bytesFitSrc;
82
  if (count > bytesFitDst)
83
    count = bytesFitDst;
84
  if (count > bx_pc_system.getNumCpuTicksLeftNextEvent())
85
    count = bx_pc_system.getNumCpuTicksLeftNextEvent();
86
 
87
  // If after all the restrictions, there is anything left to do...
88
  if (count) {
89
    // Transfer data directly using host addresses
90
    for (unsigned j=0; j<count; j++) {
91
      * (Bit8u *) hostAddrDst = * (Bit8u *) hostAddrSrc;
92
      hostAddrDst += pointerDelta;
93
      hostAddrSrc += pointerDelta;
94
    }
95
 
96
    return count;
97
  }
98
 
99
  return 0;
100
}
101
 
102
Bit32u BX_CPU_C::FastRepMOVSW(bxInstruction_c *i, unsigned srcSeg, bx_address srcOff, unsigned dstSeg, bx_address dstOff, Bit32u count)
103
{
104
  Bit32u wordsFitSrc, wordsFitDst;
105
  signed int pointerDelta;
106
  bx_address laddrDst, laddrSrc;
107
  Bit8u *hostAddrSrc, *hostAddrDst;
108
 
109
  BX_ASSERT(BX_CPU_THIS_PTR cpu_mode != BX_MODE_LONG_64);
110
 
111
  bx_segment_reg_t *srcSegPtr = &BX_CPU_THIS_PTR sregs[srcSeg];
112
  if (!(srcSegPtr->cache.valid & SegAccessROK))
113
    return 0;
114
  if ((srcOff | 0xfff) > srcSegPtr->cache.u.segment.limit_scaled)
115
    return 0;
116
 
117
  bx_segment_reg_t *dstSegPtr = &BX_CPU_THIS_PTR sregs[dstSeg];
118
  if (!(dstSegPtr->cache.valid & SegAccessWOK))
119
    return 0;
120
  if ((dstOff | 0xfff) > dstSegPtr->cache.u.segment.limit_scaled)
121
    return 0;
122
 
123
  laddrSrc = get_laddr32(srcSeg, srcOff);
124
 
125
  hostAddrSrc = v2h_read_byte(laddrSrc, BX_CPU_THIS_PTR user_pl);
126
  if (! hostAddrSrc) return 0;
127
 
128
  laddrDst = get_laddr32(dstSeg, dstOff);
129
 
130
  hostAddrDst = v2h_write_byte(laddrDst, BX_CPU_THIS_PTR user_pl);
131
  // Check that native host access was not vetoed for that page
132
  if (!hostAddrDst) return 0;
133
 
134
  // See how many words can fit in the rest of this page.
135
  if (BX_CPU_THIS_PTR get_DF()) {
136
    // Counting downward.
137
    // Note: 1st word must not cross page boundary.
138
    if (((laddrSrc & 0xfff) > 0xffe) || ((laddrDst & 0xfff) > 0xffe))
139
       return 0;
140
    wordsFitSrc = (2 + PAGE_OFFSET(laddrSrc)) >> 1;
141
    wordsFitDst = (2 + PAGE_OFFSET(laddrDst)) >> 1;
142
    pointerDelta = (signed int) -2;
143
  }
144
  else {
145
    // Counting upward.
146
    wordsFitSrc = (0x1000 - PAGE_OFFSET(laddrSrc)) >> 1;
147
    wordsFitDst = (0x1000 - PAGE_OFFSET(laddrDst)) >> 1;
148
    pointerDelta = (signed int)  2;
149
  }
150
 
151
  // Restrict word count to the number that will fit in either
152
  // source or dest pages.
153
  if (count > wordsFitSrc)
154
    count = wordsFitSrc;
155
  if (count > wordsFitDst)
156
    count = wordsFitDst;
157
  if (count > bx_pc_system.getNumCpuTicksLeftNextEvent())
158
    count = bx_pc_system.getNumCpuTicksLeftNextEvent();
159
 
160
  // If after all the restrictions, there is anything left to do...
161
  if (count) {
162
    // Transfer data directly using host addresses
163
    for (unsigned j=0; j<count; j++) {
164
      CopyHostWordLittleEndian(hostAddrDst, hostAddrSrc);
165
      hostAddrDst += pointerDelta;
166
      hostAddrSrc += pointerDelta;
167
    }
168
 
169
    return count;
170
  }
171
 
172
  return 0;
173
}
174
 
175
Bit32u BX_CPU_C::FastRepMOVSD(bxInstruction_c *i, unsigned srcSeg, bx_address srcOff, unsigned dstSeg, bx_address dstOff, Bit32u count)
176
{
177
  Bit32u dwordsFitSrc, dwordsFitDst;
178
  signed int pointerDelta;
179
  bx_address laddrDst, laddrSrc;
180
  Bit8u *hostAddrSrc, *hostAddrDst;
181
 
182
  BX_ASSERT(BX_CPU_THIS_PTR cpu_mode != BX_MODE_LONG_64);
183
 
184
  bx_segment_reg_t *srcSegPtr = &BX_CPU_THIS_PTR sregs[srcSeg];
185
  if (!(srcSegPtr->cache.valid & SegAccessROK))
186
    return 0;
187
  if ((srcOff | 0xfff) > srcSegPtr->cache.u.segment.limit_scaled)
188
    return 0;
189
 
190
  bx_segment_reg_t *dstSegPtr = &BX_CPU_THIS_PTR sregs[dstSeg];
191
  if (!(dstSegPtr->cache.valid & SegAccessWOK))
192
    return 0;
193
  if ((dstOff | 0xfff) > dstSegPtr->cache.u.segment.limit_scaled)
194
    return 0;
195
 
196
  laddrSrc = get_laddr32(srcSeg, srcOff);
197
 
198
  hostAddrSrc = v2h_read_byte(laddrSrc, BX_CPU_THIS_PTR user_pl);
199
  if (! hostAddrSrc) return 0;
200
 
201
  laddrDst = get_laddr32(dstSeg, dstOff);
202
 
203
  hostAddrDst = v2h_write_byte(laddrDst, BX_CPU_THIS_PTR user_pl);
204
  // Check that native host access was not vetoed for that page
205
  if (!hostAddrDst) return 0;
206
 
207
  // See how many dwords can fit in the rest of this page.
208
  if (BX_CPU_THIS_PTR get_DF()) {
209
    // Counting downward.
210
    // Note: 1st dword must not cross page boundary.
211
    if (((laddrSrc & 0xfff) > 0xffc) || ((laddrDst & 0xfff) > 0xffc))
212
      return 0;
213
    dwordsFitSrc = (4 + PAGE_OFFSET(laddrSrc)) >> 2;
214
    dwordsFitDst = (4 + PAGE_OFFSET(laddrDst)) >> 2;
215
    pointerDelta = (signed int) -4;
216
  }
217
  else {
218
    // Counting upward.
219
    dwordsFitSrc = (0x1000 - PAGE_OFFSET(laddrSrc)) >> 2;
220
    dwordsFitDst = (0x1000 - PAGE_OFFSET(laddrDst)) >> 2;
221
    pointerDelta = (signed int)  4;
222
  }
223
 
224
  // Restrict dword count to the number that will fit in either
225
  // source or dest pages.
226
  if (count > dwordsFitSrc)
227
    count = dwordsFitSrc;
228
  if (count > dwordsFitDst)
229
    count = dwordsFitDst;
230
  if (count > bx_pc_system.getNumCpuTicksLeftNextEvent())
231
    count = bx_pc_system.getNumCpuTicksLeftNextEvent();
232
 
233
  // If after all the restrictions, there is anything left to do...
234
  if (count) {
235
    // Transfer data directly using host addresses
236
    for (unsigned j=0; j<count; j++) {
237
      CopyHostDWordLittleEndian(hostAddrDst, hostAddrSrc);
238
      hostAddrDst += pointerDelta;
239
      hostAddrSrc += pointerDelta;
240
    }
241
 
242
    return count;
243
  }
244
 
245
  return 0;
246
}
247
 
248
Bit32u BX_CPU_C::FastRepSTOSB(bxInstruction_c *i, unsigned dstSeg, bx_address dstOff, Bit8u val, Bit32u count)
249
{
250
  Bit32u bytesFitDst;
251
  signed int pointerDelta;
252
  bx_address laddrDst;
253
  Bit8u *hostAddrDst;
254
 
255
  BX_ASSERT(BX_CPU_THIS_PTR cpu_mode != BX_MODE_LONG_64);
256
 
257
  bx_segment_reg_t *dstSegPtr = &BX_CPU_THIS_PTR sregs[dstSeg];
258
  if (!(dstSegPtr->cache.valid & SegAccessWOK))
259
    return 0;
260
  if ((dstOff | 0xfff) > dstSegPtr->cache.u.segment.limit_scaled)
261
    return 0;
262
 
263
  laddrDst = get_laddr32(dstSeg, dstOff);
264
 
265
  hostAddrDst = v2h_write_byte(laddrDst, BX_CPU_THIS_PTR user_pl);
266
  // Check that native host access was not vetoed for that page
267
  if (!hostAddrDst) return 0;
268
 
269
  // See how many bytes can fit in the rest of this page.
270
  if (BX_CPU_THIS_PTR get_DF()) {
271
    // Counting downward.
272
    bytesFitDst = 1 + PAGE_OFFSET(laddrDst);
273
    pointerDelta = (signed int) -1;
274
  }
275
  else {
276
    // Counting upward.
277
    bytesFitDst = 0x1000 - PAGE_OFFSET(laddrDst);
278
    pointerDelta = (signed int)  1;
279
  }
280
 
281
  // Restrict word count to the number that will fit in either
282
  // source or dest pages.
283
  if (count > bytesFitDst)
284
    count = bytesFitDst;
285
  if (count > bx_pc_system.getNumCpuTicksLeftNextEvent())
286
    count = bx_pc_system.getNumCpuTicksLeftNextEvent();
287
 
288
  // If after all the restrictions, there is anything left to do...
289
  if (count) {
290
    // Transfer data directly using host addresses
291
    for (unsigned j=0; j<count; j++) {
292
      * (Bit8u *) hostAddrDst = val;
293
      hostAddrDst += pointerDelta;
294
    }
295
 
296
    return count;
297
  }
298
 
299
  return 0;
300
}
301
 
302
Bit32u BX_CPU_C::FastRepSTOSW(bxInstruction_c *i, unsigned dstSeg, bx_address dstOff, Bit16u val, Bit32u count)
303
{
304
  Bit32u wordsFitDst;
305
  signed int pointerDelta;
306
  bx_address laddrDst;
307
  Bit8u *hostAddrDst;
308
 
309
  BX_ASSERT(BX_CPU_THIS_PTR cpu_mode != BX_MODE_LONG_64);
310
 
311
  bx_segment_reg_t *dstSegPtr = &BX_CPU_THIS_PTR sregs[dstSeg];
312
  if (!(dstSegPtr->cache.valid & SegAccessWOK))
313
    return 0;
314
  if ((dstOff | 0xfff) > dstSegPtr->cache.u.segment.limit_scaled)
315
    return 0;
316
 
317
  laddrDst = get_laddr32(dstSeg, dstOff);
318
 
319
  hostAddrDst = v2h_write_byte(laddrDst, BX_CPU_THIS_PTR user_pl);
320
  // Check that native host access was not vetoed for that page
321
  if (!hostAddrDst) return 0;
322
 
323
  // See how many words can fit in the rest of this page.
324
  if (BX_CPU_THIS_PTR get_DF()) {
325
    // Counting downward.
326
    // Note: 1st word must not cross page boundary.
327
    if ((laddrDst & 0xfff) > 0xffe) return 0;
328
    wordsFitDst = (2 + PAGE_OFFSET(laddrDst)) >> 1;
329
    pointerDelta = (signed int) -2;
330
  }
331
  else {
332
    // Counting upward.
333
    wordsFitDst = (0x1000 - PAGE_OFFSET(laddrDst)) >> 1;
334
    pointerDelta = (signed int)  2;
335
  }
336
 
337
  // Restrict word count to the number that will fit in either
338
  // source or dest pages.
339
  if (count > wordsFitDst)
340
    count = wordsFitDst;
341
  if (count > bx_pc_system.getNumCpuTicksLeftNextEvent())
342
    count = bx_pc_system.getNumCpuTicksLeftNextEvent();
343
 
344
  // If after all the restrictions, there is anything left to do...
345
  if (count) {
346
    // Transfer data directly using host addresses
347
    for (unsigned j=0; j<count; j++) {
348
      WriteHostWordToLittleEndian(hostAddrDst, val);
349
      hostAddrDst += pointerDelta;
350
    }
351
 
352
    return count;
353
  }
354
 
355
  return 0;
356
}
357
 
358
Bit32u BX_CPU_C::FastRepSTOSD(bxInstruction_c *i, unsigned dstSeg, bx_address dstOff, Bit32u val, Bit32u count)
359
{
360
  Bit32u dwordsFitDst;
361
  signed int pointerDelta;
362
  bx_address laddrDst;
363
  Bit8u *hostAddrDst;
364
 
365
  BX_ASSERT(BX_CPU_THIS_PTR cpu_mode != BX_MODE_LONG_64);
366
 
367
  bx_segment_reg_t *dstSegPtr = &BX_CPU_THIS_PTR sregs[dstSeg];
368
  if (!(dstSegPtr->cache.valid & SegAccessWOK))
369
    return 0;
370
  if ((dstOff | 0xfff) > dstSegPtr->cache.u.segment.limit_scaled)
371
    return 0;
372
 
373
  laddrDst = get_laddr32(dstSeg, dstOff);
374
 
375
  hostAddrDst = v2h_write_byte(laddrDst, BX_CPU_THIS_PTR user_pl);
376
  // Check that native host access was not vetoed for that page
377
  if (!hostAddrDst) return 0;
378
 
379
  // See how many dwords can fit in the rest of this page.
380
  if (BX_CPU_THIS_PTR get_DF()) {
381
    // Counting downward.
382
    // Note: 1st dword must not cross page boundary.
383
    if ((laddrDst & 0xfff) > 0xffc) return 0;
384
    dwordsFitDst = (4 + PAGE_OFFSET(laddrDst)) >> 2;
385
    pointerDelta = (signed int) -4;
386
  }
387
  else {
388
    // Counting upward.
389
    dwordsFitDst = (0x1000 - PAGE_OFFSET(laddrDst)) >> 2;
390
    pointerDelta = (signed int)  4;
391
  }
392
 
393
  // Restrict dword count to the number that will fit in either
394
  // source or dest pages.
395
  if (count > dwordsFitDst)
396
    count = dwordsFitDst;
397
  if (count > bx_pc_system.getNumCpuTicksLeftNextEvent())
398
    count = bx_pc_system.getNumCpuTicksLeftNextEvent();
399
 
400
  // If after all the restrictions, there is anything left to do...
401
  if (count) {
402
    // Transfer data directly using host addresses
403
    for (unsigned j=0; j<count; j++) {
404
      WriteHostDWordToLittleEndian(hostAddrDst, val);
405
      hostAddrDst += pointerDelta;
406
    }
407
 
408
    return count;
409
  }
410
 
411
  return 0;
412
}
413
#endif
414
 
415
//
416
// REP MOVS methods
417
//
418
 
419
BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::REP_MOVSB_XbYb(bxInstruction_c *i)
420
{
421
#if BX_SUPPORT_X86_64
422
  if (i->as64L())
423
    BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::MOVSB64_XbYb);
424
  else
425
#endif
426
  if (i->as32L()) {
427
    BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::MOVSB32_XbYb);
428
    BX_CLEAR_64BIT_HIGH(BX_64BIT_REG_RSI); // always clear upper part of RSI/RDI
429
    BX_CLEAR_64BIT_HIGH(BX_64BIT_REG_RDI);
430
  }
431
  else {
432
    BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::MOVSB16_XbYb);
433
  }
434
 
435
  BX_NEXT_INSTR(i);
436
}
437
 
438
BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::REP_MOVSW_XwYw(bxInstruction_c *i)
439
{
440
#if BX_SUPPORT_X86_64
441
  if (i->as64L())
442
    BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::MOVSW64_XwYw);
443
  else
444
#endif
445
  if (i->as32L()) {
446
    BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::MOVSW32_XwYw);
447
    BX_CLEAR_64BIT_HIGH(BX_64BIT_REG_RSI); // always clear upper part of RSI/RDI
448
    BX_CLEAR_64BIT_HIGH(BX_64BIT_REG_RDI);
449
  }
450
  else {
451
    BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::MOVSW16_XwYw);
452
  }
453
 
454
  BX_NEXT_INSTR(i);
455
}
456
 
457
BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::REP_MOVSD_XdYd(bxInstruction_c *i)
458
{
459
#if BX_SUPPORT_X86_64
460
  if (i->as64L())
461
    BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::MOVSD64_XdYd);
462
  else
463
#endif
464
  if (i->as32L()) {
465
    BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::MOVSD32_XdYd);
466
    BX_CLEAR_64BIT_HIGH(BX_64BIT_REG_RSI); // always clear upper part of RSI/RDI
467
    BX_CLEAR_64BIT_HIGH(BX_64BIT_REG_RDI);
468
  }
469
  else {
470
    BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::MOVSD16_XdYd);
471
  }
472
 
473
  BX_NEXT_INSTR(i);
474
}
475
 
476
#if BX_SUPPORT_X86_64
477
BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::REP_MOVSQ_XqYq(bxInstruction_c *i)
478
{
479
  if (i->as64L()) {
480
    BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::MOVSQ64_XqYq);
481
  }
482
  else {
483
    BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::MOVSQ32_XqYq);
484
    BX_CLEAR_64BIT_HIGH(BX_64BIT_REG_RSI); // always clear upper part of RSI/RDI
485
    BX_CLEAR_64BIT_HIGH(BX_64BIT_REG_RDI);
486
  }
487
 
488
  BX_NEXT_INSTR(i);
489
}
490
#endif
491
 
492
//
493
// MOVSB/MOVSW/MOVSD/MOVSQ methods
494
//
495
 
496
// 16 bit address size
497
void BX_CPP_AttrRegparmN(1) BX_CPU_C::MOVSB16_XbYb(bxInstruction_c *i)
498
{
499
  Bit8u temp8 = read_virtual_byte_32(i->seg(), SI);
500
  write_virtual_byte_32(BX_SEG_REG_ES, DI, temp8);
501
 
502
  if (BX_CPU_THIS_PTR get_DF()) {
503
    /* decrement SI, DI */
504
    SI--;
505
    DI--;
506
  }
507
  else {
508
    /* increment SI, DI */
509
    SI++;
510
    DI++;
511
  }
512
}
513
 
514
// 32 bit address size
515
void BX_CPP_AttrRegparmN(1) BX_CPU_C::MOVSB32_XbYb(bxInstruction_c *i)
516
{
517
  Bit8u temp8;
518
 
519
  Bit32u incr = 1;
520
 
521
#if (BX_SUPPORT_REPEAT_SPEEDUPS) && (BX_DEBUGGER == 0)
522
  /* If conditions are right, we can transfer IO to physical memory
523
   * in a batch, rather than one instruction at a time */
524
  if (i->repUsedL() && !BX_CPU_THIS_PTR async_event)
525
  {
526
    Bit32u byteCount = FastRepMOVSB(i, i->seg(), ESI, BX_SEG_REG_ES, EDI, ECX);
527
    if (byteCount) {
528
      // Decrement the ticks count by the number of iterations, minus
529
      // one, since the main cpu loop will decrement one.  Also,
530
      // the count is predecremented before examined, so defintely
531
      // don't roll it under zero.
532
      BX_TICKN(byteCount-1);
533
 
534
      // Decrement eCX. Note, the main loop will decrement 1 also, so
535
      // decrement by one less than expected, like the case above.
536
      RCX = ECX - (byteCount-1);
537
 
538
      incr = byteCount;
539
    }
540
    else {
541
      temp8 = read_virtual_byte(i->seg(), ESI);
542
      write_virtual_byte(BX_SEG_REG_ES, EDI, temp8);
543
    }
544
  }
545
  else
546
#endif
547
  {
548
    temp8 = read_virtual_byte(i->seg(), ESI);
549
    write_virtual_byte(BX_SEG_REG_ES, EDI, temp8);
550
  }
551
 
552
  if (BX_CPU_THIS_PTR get_DF()) {
553
    RSI = ESI - incr;
554
    RDI = EDI - incr;
555
  }
556
  else {
557
    RSI = ESI + incr;
558
    RDI = EDI + incr;
559
  }
560
}
561
 
562
#if BX_SUPPORT_X86_64
563
// 64 bit address size
564
void BX_CPP_AttrRegparmN(1) BX_CPU_C::MOVSB64_XbYb(bxInstruction_c *i)
565
{
566
  Bit8u temp8;
567
 
568
  Bit64u rsi = RSI;
569
  Bit64u rdi = RDI;
570
 
571
  temp8 = read_virtual_byte_64(i->seg(), rsi);
572
  write_virtual_byte_64(BX_SEG_REG_ES, rdi, temp8);
573
 
574
  if (BX_CPU_THIS_PTR get_DF()) {
575
    /* decrement RSI, RDI */
576
    rsi--;
577
    rdi--;
578
  }
579
  else {
580
    /* increment RSI, RDI */
581
    rsi++;
582
    rdi++;
583
  }
584
 
585
  RSI = rsi;
586
  RDI = rdi;
587
}
588
#endif
589
 
590
/* 16 bit opsize mode, 16 bit address size */
591
void BX_CPP_AttrRegparmN(1) BX_CPU_C::MOVSW16_XwYw(bxInstruction_c *i)
592
{
593
  Bit16u si = SI;
594
  Bit16u di = DI;
595
 
596
  Bit16u temp16 = read_virtual_word_32(i->seg(), si);
597
  write_virtual_word_32(BX_SEG_REG_ES, di, temp16);
598
 
599
  if (BX_CPU_THIS_PTR get_DF()) {
600
    /* decrement SI, DI */
601
    si -= 2;
602
    di -= 2;
603
  }
604
  else {
605
    /* increment SI, DI */
606
    si += 2;
607
    di += 2;
608
  }
609
 
610
  SI = si;
611
  DI = di;
612
}
613
 
614
/* 16 bit opsize mode, 32 bit address size */
615
void BX_CPP_AttrRegparmN(1) BX_CPU_C::MOVSW32_XwYw(bxInstruction_c *i)
616
{
617
  Bit16u temp16;
618
 
619
  Bit32u esi = ESI;
620
  Bit32u edi = EDI;
621
 
622
  temp16 = read_virtual_word(i->seg(), esi);
623
  write_virtual_word(BX_SEG_REG_ES, edi, temp16);
624
 
625
  if (BX_CPU_THIS_PTR get_DF()) {
626
    esi -= 2;
627
    edi -= 2;
628
  }
629
  else {
630
    esi += 2;
631
    edi += 2;
632
  }
633
 
634
  // zero extension of RSI/RDI
635
  RSI = esi;
636
  RDI = edi;
637
}
638
 
639
#if BX_SUPPORT_X86_64
640
/* 16 bit opsize mode, 64 bit address size */
641
void BX_CPP_AttrRegparmN(1) BX_CPU_C::MOVSW64_XwYw(bxInstruction_c *i)
642
{
643
  Bit16u temp16;
644
 
645
  Bit64u rsi = RSI;
646
  Bit64u rdi = RDI;
647
 
648
  temp16 = read_virtual_word_64(i->seg(), rsi);
649
  write_virtual_word_64(BX_SEG_REG_ES, rdi, temp16);
650
 
651
  if (BX_CPU_THIS_PTR get_DF()) {
652
    rsi -= 2;
653
    rdi -= 2;
654
  }
655
  else {
656
    rsi += 2;
657
    rdi += 2;
658
  }
659
 
660
  RSI = rsi;
661
  RDI = rdi;
662
}
663
#endif
664
 
665
/* 32 bit opsize mode, 16 bit address size */
666
void BX_CPP_AttrRegparmN(1) BX_CPU_C::MOVSD16_XdYd(bxInstruction_c *i)
667
{
668
  Bit32u temp32;
669
 
670
  Bit16u si = SI;
671
  Bit16u di = DI;
672
 
673
  temp32 = read_virtual_dword_32(i->seg(), si);
674
  write_virtual_dword_32(BX_SEG_REG_ES, di, temp32);
675
 
676
  if (BX_CPU_THIS_PTR get_DF()) {
677
    si -= 4;
678
    di -= 4;
679
  }
680
  else {
681
    si += 4;
682
    di += 4;
683
  }
684
 
685
  SI = si;
686
  DI = di;
687
}
688
 
689
/* 32 bit opsize mode, 32 bit address size */
690
void BX_CPP_AttrRegparmN(1) BX_CPU_C::MOVSD32_XdYd(bxInstruction_c *i)
691
{
692
  Bit32u temp32;
693
 
694
  Bit32u incr = 4;
695
 
696
  Bit32u esi = ESI;
697
  Bit32u edi = EDI;
698
 
699
#if (BX_SUPPORT_REPEAT_SPEEDUPS) && (BX_DEBUGGER == 0)
700
  /* If conditions are right, we can transfer IO to physical memory
701
   * in a batch, rather than one instruction at a time.
702
   */
703
  if (i->repUsedL() && !BX_CPU_THIS_PTR async_event)
704
  {
705
    Bit32u dwordCount = FastRepMOVSD(i, i->seg(), esi, BX_SEG_REG_ES, edi, ECX);
706
    if (dwordCount) {
707
      // Decrement the ticks count by the number of iterations, minus
708
      // one, since the main cpu loop will decrement one.  Also,
709
      // the count is predecremented before examined, so defintely
710
      // don't roll it under zero.
711
      BX_TICKN(dwordCount-1);
712
 
713
      // Decrement eCX. Note, the main loop will decrement 1 also, so
714
      // decrement by one less than expected, like the case above.
715
      RCX = ECX - (dwordCount-1);
716
 
717
      incr = dwordCount << 2; // count * 4
718
    }
719
    else {
720
      temp32 = read_virtual_dword(i->seg(), esi);
721
      write_virtual_dword(BX_SEG_REG_ES, edi, temp32);
722
    }
723
  }
724
  else
725
#endif
726
  {
727
    temp32 = read_virtual_dword(i->seg(), esi);
728
    write_virtual_dword(BX_SEG_REG_ES, edi, temp32);
729
  }
730
 
731
  if (BX_CPU_THIS_PTR get_DF()) {
732
    esi -= incr;
733
    edi -= incr;
734
  }
735
  else {
736
    esi += incr;
737
    edi += incr;
738
  }
739
 
740
  // zero extension of RSI/RDI
741
  RSI = esi;
742
  RDI = edi;
743
}
744
 
745
#if BX_SUPPORT_X86_64
746
 
747
/* 32 bit opsize mode, 64 bit address size */
748
void BX_CPP_AttrRegparmN(1) BX_CPU_C::MOVSD64_XdYd(bxInstruction_c *i)
749
{
750
  Bit32u temp32;
751
 
752
  Bit64u rsi = RSI;
753
  Bit64u rdi = RDI;
754
 
755
  temp32 = read_virtual_dword_64(i->seg(), rsi);
756
  write_virtual_dword_64(BX_SEG_REG_ES, rdi, temp32);
757
 
758
  if (BX_CPU_THIS_PTR get_DF()) {
759
    rsi -= 4;
760
    rdi -= 4;
761
  }
762
  else {
763
    rsi += 4;
764
    rdi += 4;
765
  }
766
 
767
  RSI = rsi;
768
  RDI = rdi;
769
}
770
 
771
/* 64 bit opsize mode, 32 bit address size */
772
void BX_CPP_AttrRegparmN(1) BX_CPU_C::MOVSQ32_XqYq(bxInstruction_c *i)
773
{
774
  Bit64u temp64;
775
 
776
  Bit32u esi = ESI;
777
  Bit32u edi = EDI;
778
 
779
  temp64 = read_virtual_qword_64(i->seg(), esi);
780
  write_virtual_qword_64(BX_SEG_REG_ES, edi, temp64);
781
 
782
  if (BX_CPU_THIS_PTR get_DF()) {
783
    esi -= 8;
784
    edi -= 8;
785
  }
786
  else {
787
    esi += 8;
788
    edi += 8;
789
  }
790
 
791
  // zero extension of RSI/RDI
792
  RSI = esi;
793
  RDI = edi;
794
}
795
 
796
/* 64 bit opsize mode, 64 bit address size */
797
void BX_CPP_AttrRegparmN(1) BX_CPU_C::MOVSQ64_XqYq(bxInstruction_c *i)
798
{
799
  Bit64u temp64;
800
 
801
  Bit64u rsi = RSI;
802
  Bit64u rdi = RDI;
803
 
804
  temp64 = read_virtual_qword_64(i->seg(), rsi);
805
  write_virtual_qword_64(BX_SEG_REG_ES, rdi, temp64);
806
 
807
  if (BX_CPU_THIS_PTR get_DF()) {
808
    rsi -= 8;
809
    rdi -= 8;
810
  }
811
  else {
812
    rsi += 8;
813
    rdi += 8;
814
  }
815
 
816
  RSI = rsi;
817
  RDI = rdi;
818
}
819
 
820
#endif
821
 
822
//
823
// REP CMPS methods
824
//
825
 
826
BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::REP_CMPSB_XbYb(bxInstruction_c *i)
827
{
828
#if BX_SUPPORT_X86_64
829
  if (i->as64L()) {
830
    BX_CPU_THIS_PTR repeat_ZF(i, &BX_CPU_C::CMPSB64_XbYb);
831
  }
832
  else
833
#endif
834
  if (i->as32L()) {
835
    BX_CPU_THIS_PTR repeat_ZF(i, &BX_CPU_C::CMPSB32_XbYb);
836
    BX_CLEAR_64BIT_HIGH(BX_64BIT_REG_RSI); // always clear upper part of RSI/RDI
837
    BX_CLEAR_64BIT_HIGH(BX_64BIT_REG_RDI);
838
  }
839
  else {
840
    BX_CPU_THIS_PTR repeat_ZF(i, &BX_CPU_C::CMPSB16_XbYb);
841
  }
842
 
843
  BX_NEXT_INSTR(i);
844
}
845
 
846
BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::REP_CMPSW_XwYw(bxInstruction_c *i)
847
{
848
#if BX_SUPPORT_X86_64
849
  if (i->as64L()) {
850
    BX_CPU_THIS_PTR repeat_ZF(i, &BX_CPU_C::CMPSW64_XwYw);
851
  }
852
  else
853
#endif
854
  if (i->as32L()) {
855
    BX_CPU_THIS_PTR repeat_ZF(i, &BX_CPU_C::CMPSW32_XwYw);
856
    BX_CLEAR_64BIT_HIGH(BX_64BIT_REG_RSI); // always clear upper part of RSI/RDI
857
    BX_CLEAR_64BIT_HIGH(BX_64BIT_REG_RDI);
858
  }
859
  else {
860
    BX_CPU_THIS_PTR repeat_ZF(i, &BX_CPU_C::CMPSW16_XwYw);
861
  }
862
 
863
  BX_NEXT_INSTR(i);
864
}
865
 
866
BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::REP_CMPSD_XdYd(bxInstruction_c *i)
867
{
868
#if BX_SUPPORT_X86_64
869
  if (i->as64L()) {
870
    BX_CPU_THIS_PTR repeat_ZF(i, &BX_CPU_C::CMPSD64_XdYd);
871
  }
872
  else
873
#endif
874
  if (i->as32L()) {
875
    BX_CPU_THIS_PTR repeat_ZF(i, &BX_CPU_C::CMPSD32_XdYd);
876
    BX_CLEAR_64BIT_HIGH(BX_64BIT_REG_RSI); // always clear upper part of RSI/RDI
877
    BX_CLEAR_64BIT_HIGH(BX_64BIT_REG_RDI);
878
  }
879
  else {
880
    BX_CPU_THIS_PTR repeat_ZF(i, &BX_CPU_C::CMPSD16_XdYd);
881
  }
882
 
883
  BX_NEXT_INSTR(i);
884
}
885
 
886
#if BX_SUPPORT_X86_64
887
BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::REP_CMPSQ_XqYq(bxInstruction_c *i)
888
{
889
  if (i->as64L()) {
890
    BX_CPU_THIS_PTR repeat_ZF(i, &BX_CPU_C::CMPSQ64_XqYq);
891
  }
892
  else {
893
    BX_CPU_THIS_PTR repeat_ZF(i, &BX_CPU_C::CMPSQ32_XqYq);
894
    BX_CLEAR_64BIT_HIGH(BX_64BIT_REG_RSI); // always clear upper part of RSI/RDI
895
    BX_CLEAR_64BIT_HIGH(BX_64BIT_REG_RDI);
896
  }
897
 
898
  BX_NEXT_INSTR(i);
899
}
900
#endif
901
 
902
//
903
// CMPSB/CMPSW/CMPSD/CMPSQ methods
904
//
905
 
906
/* 16 bit address size */
907
void BX_CPP_AttrRegparmN(1) BX_CPU_C::CMPSB16_XbYb(bxInstruction_c *i)
908
{
909
  Bit8u op1_8, op2_8, diff_8;
910
 
911
  Bit16u si = SI;
912
  Bit16u di = DI;
913
 
914
  op1_8 = read_virtual_byte_32(i->seg(), si);
915
  op2_8 = read_virtual_byte_32(BX_SEG_REG_ES, di);
916
 
917
  diff_8 = op1_8 - op2_8;
918
 
919
  SET_FLAGS_OSZAPC_SUB_8(op1_8, op2_8, diff_8);
920
 
921
  if (BX_CPU_THIS_PTR get_DF()) {
922
    si--;
923
    di--;
924
  }
925
  else {
926
    si++;
927
    di++;
928
  }
929
 
930
  DI = di;
931
  SI = si;
932
}
933
 
934
/* 32 bit address size */
935
void BX_CPP_AttrRegparmN(1) BX_CPU_C::CMPSB32_XbYb(bxInstruction_c *i)
936
{
937
  Bit8u op1_8, op2_8, diff_8;
938
 
939
  Bit32u esi = ESI;
940
  Bit32u edi = EDI;
941
 
942
  op1_8 = read_virtual_byte(i->seg(), esi);
943
  op2_8 = read_virtual_byte(BX_SEG_REG_ES, edi);
944
 
945
  diff_8 = op1_8 - op2_8;
946
 
947
  SET_FLAGS_OSZAPC_SUB_8(op1_8, op2_8, diff_8);
948
 
949
  if (BX_CPU_THIS_PTR get_DF()) {
950
    esi--;
951
    edi--;
952
  }
953
  else {
954
    esi++;
955
    edi++;
956
  }
957
 
958
  // zero extension of RSI/RDI
959
  RDI = edi;
960
  RSI = esi;
961
}
962
 
963
#if BX_SUPPORT_X86_64
964
/* 64 bit address size */
965
void BX_CPP_AttrRegparmN(1) BX_CPU_C::CMPSB64_XbYb(bxInstruction_c *i)
966
{
967
  Bit8u op1_8, op2_8, diff_8;
968
 
969
  Bit64u rsi = RSI;
970
  Bit64u rdi = RDI;
971
 
972
  op1_8 = read_virtual_byte_64(i->seg(), rsi);
973
  op2_8 = read_virtual_byte_64(BX_SEG_REG_ES, rdi);
974
 
975
  diff_8 = op1_8 - op2_8;
976
 
977
  SET_FLAGS_OSZAPC_SUB_8(op1_8, op2_8, diff_8);
978
 
979
  if (BX_CPU_THIS_PTR get_DF()) {
980
    rsi--;
981
    rdi--;
982
  }
983
  else {
984
    rsi++;
985
    rdi++;
986
  }
987
 
988
  RDI = rdi;
989
  RSI = rsi;
990
}
991
#endif
992
 
993
/* 16 bit opsize mode, 16 bit address size */
994
void BX_CPP_AttrRegparmN(1) BX_CPU_C::CMPSW16_XwYw(bxInstruction_c *i)
995
{
996
  Bit16u op1_16, op2_16, diff_16;
997
 
998
  Bit16u si = SI;
999
  Bit16u di = DI;
1000
 
1001
  op1_16 = read_virtual_word_32(i->seg(), si);
1002
  op2_16 = read_virtual_word_32(BX_SEG_REG_ES, di);
1003
 
1004
  diff_16 = op1_16 - op2_16;
1005
 
1006
  SET_FLAGS_OSZAPC_SUB_16(op1_16, op2_16, diff_16);
1007
 
1008
  if (BX_CPU_THIS_PTR get_DF()) {
1009
    si -= 2;
1010
    di -= 2;
1011
  }
1012
  else {
1013
    si += 2;
1014
    di += 2;
1015
  }
1016
 
1017
  DI = di;
1018
  SI = si;
1019
}
1020
 
1021
/* 16 bit opsize mode, 32 bit address size */
1022
void BX_CPP_AttrRegparmN(1) BX_CPU_C::CMPSW32_XwYw(bxInstruction_c *i)
1023
{
1024
  Bit16u op1_16, op2_16, diff_16;
1025
 
1026
  Bit32u esi = ESI;
1027
  Bit32u edi = EDI;
1028
 
1029
  op1_16 = read_virtual_word(i->seg(), esi);
1030
  op2_16 = read_virtual_word(BX_SEG_REG_ES, edi);
1031
 
1032
  diff_16 = op1_16 - op2_16;
1033
 
1034
  SET_FLAGS_OSZAPC_SUB_16(op1_16, op2_16, diff_16);
1035
 
1036
  if (BX_CPU_THIS_PTR get_DF()) {
1037
    esi -= 2;
1038
    edi -= 2;
1039
  }
1040
  else {
1041
    esi += 2;
1042
    edi += 2;
1043
  }
1044
 
1045
  // zero extension of RSI/RDI
1046
  RDI = edi;
1047
  RSI = esi;
1048
}
1049
 
1050
#if BX_SUPPORT_X86_64
1051
/* 16 bit opsize mode, 64 bit address size */
1052
void BX_CPP_AttrRegparmN(1) BX_CPU_C::CMPSW64_XwYw(bxInstruction_c *i)
1053
{
1054
  Bit16u op1_16, op2_16, diff_16;
1055
 
1056
  Bit64u rsi = RSI;
1057
  Bit64u rdi = RDI;
1058
 
1059
  op1_16 = read_virtual_word_64(i->seg(), rsi);
1060
  op2_16 = read_virtual_word_64(BX_SEG_REG_ES, rdi);
1061
 
1062
  diff_16 = op1_16 - op2_16;
1063
 
1064
  SET_FLAGS_OSZAPC_SUB_16(op1_16, op2_16, diff_16);
1065
 
1066
  if (BX_CPU_THIS_PTR get_DF()) {
1067
    rsi -= 2;
1068
    rdi -= 2;
1069
  }
1070
  else {
1071
    rsi += 2;
1072
    rdi += 2;
1073
  }
1074
 
1075
  RDI = rdi;
1076
  RSI = rsi;
1077
}
1078
#endif
1079
 
1080
/* 32 bit opsize mode, 16 bit address size */
1081
void BX_CPP_AttrRegparmN(1) BX_CPU_C::CMPSD16_XdYd(bxInstruction_c *i)
1082
{
1083
  Bit32u op1_32, op2_32, diff_32;
1084
 
1085
  Bit16u si = SI;
1086
  Bit16u di = DI;
1087
 
1088
  op1_32 = read_virtual_dword_32(i->seg(), si);
1089
  op2_32 = read_virtual_dword_32(BX_SEG_REG_ES, di);
1090
 
1091
  diff_32 = op1_32 - op2_32;
1092
 
1093
  SET_FLAGS_OSZAPC_SUB_32(op1_32, op2_32, diff_32);
1094
 
1095
  if (BX_CPU_THIS_PTR get_DF()) {
1096
    si -= 4;
1097
    di -= 4;
1098
  }
1099
  else {
1100
    si += 4;
1101
    di += 4;
1102
  }
1103
 
1104
  DI = di;
1105
  SI = si;
1106
}
1107
 
1108
/* 32 bit opsize mode, 32 bit address size */
1109
void BX_CPP_AttrRegparmN(1) BX_CPU_C::CMPSD32_XdYd(bxInstruction_c *i)
1110
{
1111
  Bit32u op1_32, op2_32, diff_32;
1112
 
1113
  Bit32u esi = ESI;
1114
  Bit32u edi = EDI;
1115
 
1116
  op1_32 = read_virtual_dword(i->seg(), esi);
1117
  op2_32 = read_virtual_dword(BX_SEG_REG_ES, edi);
1118
 
1119
  diff_32 = op1_32 - op2_32;
1120
 
1121
  SET_FLAGS_OSZAPC_SUB_32(op1_32, op2_32, diff_32);
1122
 
1123
  if (BX_CPU_THIS_PTR get_DF()) {
1124
    esi -= 4;
1125
    edi -= 4;
1126
  }
1127
  else {
1128
    esi += 4;
1129
    edi += 4;
1130
  }
1131
 
1132
  // zero extension of RSI/RDI
1133
  RDI = edi;
1134
  RSI = esi;
1135
}
1136
 
1137
#if BX_SUPPORT_X86_64
1138
 
1139
/* 32 bit opsize mode, 64 bit address size */
1140
void BX_CPP_AttrRegparmN(1) BX_CPU_C::CMPSD64_XdYd(bxInstruction_c *i)
1141
{
1142
  Bit32u op1_32, op2_32, diff_32;
1143
 
1144
  Bit64u rsi = RSI;
1145
  Bit64u rdi = RDI;
1146
 
1147
  op1_32 = read_virtual_dword_64(i->seg(), rsi);
1148
  op2_32 = read_virtual_dword_64(BX_SEG_REG_ES, rdi);
1149
 
1150
  diff_32 = op1_32 - op2_32;
1151
 
1152
  SET_FLAGS_OSZAPC_SUB_32(op1_32, op2_32, diff_32);
1153
 
1154
  if (BX_CPU_THIS_PTR get_DF()) {
1155
    rsi -= 4;
1156
    rdi -= 4;
1157
  }
1158
  else {
1159
    rsi += 4;
1160
    rdi += 4;
1161
  }
1162
 
1163
  RDI = rdi;
1164
  RSI = rsi;
1165
}
1166
 
1167
/* 64 bit opsize mode, 32 bit address size */
1168
void BX_CPP_AttrRegparmN(1) BX_CPU_C::CMPSQ32_XqYq(bxInstruction_c *i)
1169
{
1170
  Bit64u op1_64, op2_64, diff_64;
1171
 
1172
  Bit32u esi = ESI;
1173
  Bit32u edi = EDI;
1174
 
1175
  op1_64 = read_virtual_qword_64(i->seg(), esi);
1176
  op2_64 = read_virtual_qword_64(BX_SEG_REG_ES, edi);
1177
 
1178
  diff_64 = op1_64 - op2_64;
1179
 
1180
  SET_FLAGS_OSZAPC_SUB_64(op1_64, op2_64, diff_64);
1181
 
1182
  if (BX_CPU_THIS_PTR get_DF()) {
1183
    esi -= 8;
1184
    edi -= 8;
1185
  }
1186
  else {
1187
    esi += 8;
1188
    edi += 8;
1189
  }
1190
 
1191
  // zero extension of RSI/RDI
1192
  RDI = edi;
1193
  RSI = esi;
1194
}
1195
 
1196
/* 64 bit opsize mode, 64 bit address size */
1197
void BX_CPP_AttrRegparmN(1) BX_CPU_C::CMPSQ64_XqYq(bxInstruction_c *i)
1198
{
1199
  Bit64u op1_64, op2_64, diff_64;
1200
 
1201
  Bit64u rsi = RSI;
1202
  Bit64u rdi = RDI;
1203
 
1204
  op1_64 = read_virtual_qword_64(i->seg(), rsi);
1205
  op2_64 = read_virtual_qword_64(BX_SEG_REG_ES, rdi);
1206
 
1207
  diff_64 = op1_64 - op2_64;
1208
 
1209
  SET_FLAGS_OSZAPC_SUB_64(op1_64, op2_64, diff_64);
1210
 
1211
  if (BX_CPU_THIS_PTR get_DF()) {
1212
    rsi -= 8;
1213
    rdi -= 8;
1214
  }
1215
  else {
1216
    rsi += 8;
1217
    rdi += 8;
1218
  }
1219
 
1220
  RDI = rdi;
1221
  RSI = rsi;
1222
}
1223
 
1224
#endif
1225
 
1226
//
1227
// REP SCAS methods
1228
//
1229
 
1230
BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::REP_SCASB_ALXb(bxInstruction_c *i)
1231
{
1232
#if BX_SUPPORT_X86_64
1233
  if (i->as64L()) {
1234
    BX_CPU_THIS_PTR repeat_ZF(i, &BX_CPU_C::SCASB64_ALXb);
1235
  }
1236
  else
1237
#endif
1238
  if (i->as32L()) {
1239
    BX_CPU_THIS_PTR repeat_ZF(i, &BX_CPU_C::SCASB32_ALXb);
1240
    BX_CLEAR_64BIT_HIGH(BX_64BIT_REG_RDI); // always clear upper part of RDI
1241
  }
1242
  else {
1243
    BX_CPU_THIS_PTR repeat_ZF(i, &BX_CPU_C::SCASB16_ALXb);
1244
  }
1245
 
1246
  BX_NEXT_INSTR(i);
1247
}
1248
 
1249
BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::REP_SCASW_AXXw(bxInstruction_c *i)
1250
{
1251
#if BX_SUPPORT_X86_64
1252
  if (i->as64L()) {
1253
    BX_CPU_THIS_PTR repeat_ZF(i, &BX_CPU_C::SCASW64_AXXw);
1254
  }
1255
  else
1256
#endif
1257
  if (i->as32L()) {
1258
    BX_CPU_THIS_PTR repeat_ZF(i, &BX_CPU_C::SCASW32_AXXw);
1259
    BX_CLEAR_64BIT_HIGH(BX_64BIT_REG_RDI); // always clear upper part of RDI
1260
  }
1261
  else {
1262
    BX_CPU_THIS_PTR repeat_ZF(i, &BX_CPU_C::SCASW16_AXXw);
1263
  }
1264
 
1265
  BX_NEXT_INSTR(i);
1266
}
1267
 
1268
BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::REP_SCASD_EAXXd(bxInstruction_c *i)
1269
{
1270
#if BX_SUPPORT_X86_64
1271
  if (i->as64L()) {
1272
    BX_CPU_THIS_PTR repeat_ZF(i, &BX_CPU_C::SCASD64_EAXXd);
1273
  }
1274
  else
1275
#endif
1276
  if (i->as32L()) {
1277
    BX_CPU_THIS_PTR repeat_ZF(i, &BX_CPU_C::SCASD32_EAXXd);
1278
    BX_CLEAR_64BIT_HIGH(BX_64BIT_REG_RDI); // always clear upper part of RDI
1279
  }
1280
  else {
1281
    BX_CPU_THIS_PTR repeat_ZF(i, &BX_CPU_C::SCASD16_EAXXd);
1282
  }
1283
 
1284
  BX_NEXT_INSTR(i);
1285
}
1286
 
1287
#if BX_SUPPORT_X86_64
1288
BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::REP_SCASQ_RAXXq(bxInstruction_c *i)
1289
{
1290
  if (i->as64L()) {
1291
    BX_CPU_THIS_PTR repeat_ZF(i, &BX_CPU_C::SCASQ64_RAXXq);
1292
  }
1293
  else {
1294
    BX_CPU_THIS_PTR repeat_ZF(i, &BX_CPU_C::SCASQ32_RAXXq);
1295
    BX_CLEAR_64BIT_HIGH(BX_64BIT_REG_RDI); // always clear upper part of RDI
1296
  }
1297
 
1298
  BX_NEXT_INSTR(i);
1299
}
1300
#endif
1301
 
1302
//
1303
// SCASB/SCASW/SCASD/SCASQ methods
1304
//
1305
 
1306
/* 16 bit address size */
1307
void BX_CPP_AttrRegparmN(1) BX_CPU_C::SCASB16_ALXb(bxInstruction_c *i)
1308
{
1309
  Bit8u op1_8 = AL, op2_8, diff_8;
1310
 
1311
  Bit16u di = DI;
1312
 
1313
  op2_8 = read_virtual_byte_32(BX_SEG_REG_ES, di);
1314
 
1315
  diff_8 = op1_8 - op2_8;
1316
 
1317
  SET_FLAGS_OSZAPC_SUB_8(op1_8, op2_8, diff_8);
1318
 
1319
  if (BX_CPU_THIS_PTR get_DF()) {
1320
    di--;
1321
  }
1322
  else {
1323
    di++;
1324
  }
1325
 
1326
  DI = di;
1327
}
1328
 
1329
/* 32 bit address size */
1330
void BX_CPP_AttrRegparmN(1) BX_CPU_C::SCASB32_ALXb(bxInstruction_c *i)
1331
{
1332
  Bit8u op1_8 = AL, op2_8, diff_8;
1333
 
1334
  Bit32u edi = EDI;
1335
 
1336
  op2_8 = read_virtual_byte(BX_SEG_REG_ES, edi);
1337
  diff_8 = op1_8 - op2_8;
1338
 
1339
  SET_FLAGS_OSZAPC_SUB_8(op1_8, op2_8, diff_8);
1340
 
1341
  if (BX_CPU_THIS_PTR get_DF()) {
1342
    edi--;
1343
  }
1344
  else {
1345
    edi++;
1346
  }
1347
 
1348
  // zero extension of RDI
1349
  RDI = edi;
1350
}
1351
 
1352
#if BX_SUPPORT_X86_64
1353
/* 64 bit address size */
1354
void BX_CPP_AttrRegparmN(1) BX_CPU_C::SCASB64_ALXb(bxInstruction_c *i)
1355
{
1356
  Bit8u op1_8 = AL, op2_8, diff_8;
1357
 
1358
  Bit64u rdi = RDI;
1359
 
1360
  op2_8 = read_virtual_byte_64(BX_SEG_REG_ES, rdi);
1361
 
1362
  diff_8 = op1_8 - op2_8;
1363
 
1364
  SET_FLAGS_OSZAPC_SUB_8(op1_8, op2_8, diff_8);
1365
 
1366
  if (BX_CPU_THIS_PTR get_DF()) {
1367
    rdi--;
1368
  }
1369
  else {
1370
    rdi++;
1371
  }
1372
 
1373
  RDI = rdi;
1374
}
1375
#endif
1376
 
1377
/* 16 bit opsize mode, 16 bit address size */
1378
void BX_CPP_AttrRegparmN(1) BX_CPU_C::SCASW16_AXXw(bxInstruction_c *i)
1379
{
1380
  Bit16u op1_16 = AX, op2_16, diff_16;
1381
 
1382
  Bit16u di = DI;
1383
 
1384
  op2_16 = read_virtual_word_32(BX_SEG_REG_ES, di);
1385
  diff_16 = op1_16 - op2_16;
1386
 
1387
  SET_FLAGS_OSZAPC_SUB_16(op1_16, op2_16, diff_16);
1388
 
1389
  if (BX_CPU_THIS_PTR get_DF()) {
1390
    di -= 2;
1391
  }
1392
  else {
1393
    di += 2;
1394
  }
1395
 
1396
  DI = di;
1397
}
1398
 
1399
/* 16 bit opsize mode, 32 bit address size */
1400
void BX_CPP_AttrRegparmN(1) BX_CPU_C::SCASW32_AXXw(bxInstruction_c *i)
1401
{
1402
  Bit16u op1_16 = AX, op2_16, diff_16;
1403
 
1404
  Bit32u edi = EDI;
1405
 
1406
  op2_16 = read_virtual_word(BX_SEG_REG_ES, edi);
1407
  diff_16 = op1_16 - op2_16;
1408
 
1409
  SET_FLAGS_OSZAPC_SUB_16(op1_16, op2_16, diff_16);
1410
 
1411
  if (BX_CPU_THIS_PTR get_DF()) {
1412
    edi -= 2;
1413
  }
1414
  else {
1415
    edi += 2;
1416
  }
1417
 
1418
  // zero extension of RDI
1419
  RDI = edi;
1420
}
1421
 
1422
#if BX_SUPPORT_X86_64
1423
/* 16 bit opsize mode, 64 bit address size */
1424
void BX_CPP_AttrRegparmN(1) BX_CPU_C::SCASW64_AXXw(bxInstruction_c *i)
1425
{
1426
  Bit16u op1_16 = AX, op2_16, diff_16;
1427
 
1428
  Bit64u rdi = RDI;
1429
 
1430
  op2_16 = read_virtual_word_64(BX_SEG_REG_ES, rdi);
1431
 
1432
  diff_16 = op1_16 - op2_16;
1433
 
1434
  SET_FLAGS_OSZAPC_SUB_16(op1_16, op2_16, diff_16);
1435
 
1436
  if (BX_CPU_THIS_PTR get_DF()) {
1437
    rdi -= 2;
1438
  }
1439
  else {
1440
    rdi += 2;
1441
  }
1442
 
1443
  RDI = rdi;
1444
}
1445
#endif
1446
 
1447
/* 32 bit opsize mode, 16 bit address size */
1448
void BX_CPP_AttrRegparmN(1) BX_CPU_C::SCASD16_EAXXd(bxInstruction_c *i)
1449
{
1450
  Bit32u op1_32 = EAX, op2_32, diff_32;
1451
 
1452
  Bit16u di = DI;
1453
 
1454
  op2_32 = read_virtual_dword_32(BX_SEG_REG_ES, di);
1455
  diff_32 = op1_32 - op2_32;
1456
 
1457
  SET_FLAGS_OSZAPC_SUB_32(op1_32, op2_32, diff_32);
1458
 
1459
  if (BX_CPU_THIS_PTR get_DF()) {
1460
    di -= 4;
1461
  }
1462
  else {
1463
    di += 4;
1464
  }
1465
 
1466
  DI = di;
1467
}
1468
 
1469
/* 32 bit opsize mode, 32 bit address size */
1470
void BX_CPP_AttrRegparmN(1) BX_CPU_C::SCASD32_EAXXd(bxInstruction_c *i)
1471
{
1472
  Bit32u op1_32 = EAX, op2_32, diff_32;
1473
 
1474
  Bit32u edi = EDI;
1475
 
1476
  op2_32 = read_virtual_dword(BX_SEG_REG_ES, edi);
1477
  diff_32 = op1_32 - op2_32;
1478
 
1479
  SET_FLAGS_OSZAPC_SUB_32(op1_32, op2_32, diff_32);
1480
 
1481
  if (BX_CPU_THIS_PTR get_DF()) {
1482
    edi -= 4;
1483
  }
1484
  else {
1485
    edi += 4;
1486
  }
1487
 
1488
  // zero extension of RDI
1489
  RDI = edi;
1490
}
1491
 
1492
#if BX_SUPPORT_X86_64
1493
 
1494
/* 32 bit opsize mode, 64 bit address size */
1495
void BX_CPP_AttrRegparmN(1) BX_CPU_C::SCASD64_EAXXd(bxInstruction_c *i)
1496
{
1497
  Bit32u op1_32 = EAX, op2_32, diff_32;
1498
 
1499
  Bit64u rdi = RDI;
1500
 
1501
  op2_32 = read_virtual_dword_64(BX_SEG_REG_ES, rdi);
1502
 
1503
  diff_32 = op1_32 - op2_32;
1504
 
1505
  SET_FLAGS_OSZAPC_SUB_32(op1_32, op2_32, diff_32);
1506
 
1507
  if (BX_CPU_THIS_PTR get_DF()) {
1508
    rdi -= 4;
1509
  }
1510
  else {
1511
    rdi += 4;
1512
  }
1513
 
1514
  RDI = rdi;
1515
}
1516
 
1517
/* 64 bit opsize mode, 32 bit address size */
1518
void BX_CPP_AttrRegparmN(1) BX_CPU_C::SCASQ32_RAXXq(bxInstruction_c *i)
1519
{
1520
  Bit64u op1_64 = RAX, op2_64, diff_64;
1521
 
1522
  Bit32u edi = EDI;
1523
 
1524
  op2_64 = read_virtual_qword_64(BX_SEG_REG_ES, edi);
1525
 
1526
  diff_64 = op1_64 - op2_64;
1527
 
1528
  SET_FLAGS_OSZAPC_SUB_64(op1_64, op2_64, diff_64);
1529
 
1530
  if (BX_CPU_THIS_PTR get_DF()) {
1531
    edi -= 8;
1532
  }
1533
  else {
1534
    edi += 8;
1535
  }
1536
 
1537
  // zero extension of RDI
1538
  RDI = edi;
1539
}
1540
 
1541
/* 64 bit opsize mode, 64 bit address size */
1542
void BX_CPP_AttrRegparmN(1) BX_CPU_C::SCASQ64_RAXXq(bxInstruction_c *i)
1543
{
1544
  Bit64u op1_64 = RAX, op2_64, diff_64;
1545
 
1546
  Bit64u rdi = RDI;
1547
 
1548
  op2_64 = read_virtual_qword_64(BX_SEG_REG_ES, rdi);
1549
 
1550
  diff_64 = op1_64 - op2_64;
1551
 
1552
  SET_FLAGS_OSZAPC_SUB_64(op1_64, op2_64, diff_64);
1553
 
1554
  if (BX_CPU_THIS_PTR get_DF()) {
1555
    rdi -= 8;
1556
  }
1557
  else {
1558
    rdi += 8;
1559
  }
1560
 
1561
  RDI = rdi;
1562
}
1563
 
1564
#endif
1565
 
1566
//
1567
// REP STOS methods
1568
//
1569
 
1570
BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::REP_STOSB_YbAL(bxInstruction_c *i)
1571
{
1572
#if BX_SUPPORT_X86_64
1573
  if (i->as64L())
1574
    BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::STOSB64_YbAL);
1575
  else
1576
#endif
1577
  if (i->as32L()) {
1578
    BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::STOSB32_YbAL);
1579
    BX_CLEAR_64BIT_HIGH(BX_64BIT_REG_RDI); // always clear upper part of RDI
1580
  }
1581
  else {
1582
    BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::STOSB16_YbAL);
1583
  }
1584
 
1585
  BX_NEXT_INSTR(i);
1586
}
1587
 
1588
BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::REP_STOSW_YwAX(bxInstruction_c *i)
1589
{
1590
#if BX_SUPPORT_X86_64
1591
  if (i->as64L())
1592
  BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::STOSW64_YwAX);
1593
  else
1594
#endif
1595
  if (i->as32L()) {
1596
    BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::STOSW32_YwAX);
1597
    BX_CLEAR_64BIT_HIGH(BX_64BIT_REG_RDI); // always clear upper part of RDI
1598
  }
1599
  else {
1600
    BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::STOSW16_YwAX);
1601
  }
1602
 
1603
  BX_NEXT_INSTR(i);
1604
}
1605
 
1606
BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::REP_STOSD_YdEAX(bxInstruction_c *i)
1607
{
1608
#if BX_SUPPORT_X86_64
1609
  if (i->as64L())
1610
    BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::STOSD64_YdEAX);
1611
  else
1612
#endif
1613
  if (i->as32L()) {
1614
    BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::STOSD32_YdEAX);
1615
    BX_CLEAR_64BIT_HIGH(BX_64BIT_REG_RDI); // always clear upper part of RDI
1616
  }
1617
  else {
1618
    BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::STOSD16_YdEAX);
1619
  }
1620
 
1621
  BX_NEXT_INSTR(i);
1622
}
1623
 
1624
#if BX_SUPPORT_X86_64
1625
BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::REP_STOSQ_YqRAX(bxInstruction_c *i)
1626
{
1627
  if (i->as64L()) {
1628
    BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::STOSQ64_YqRAX);
1629
  }
1630
  else {
1631
    BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::STOSQ32_YqRAX);
1632
    BX_CLEAR_64BIT_HIGH(BX_64BIT_REG_RDI); // always clear upper part of RDI
1633
  }
1634
 
1635
  BX_NEXT_INSTR(i);
1636
}
1637
#endif
1638
 
1639
//
1640
// STOSB/STOSW/STOSD/STOSQ methods
1641
//
1642
 
1643
// 16 bit address size
1644
void BX_CPP_AttrRegparmN(1) BX_CPU_C::STOSB16_YbAL(bxInstruction_c *i)
1645
{
1646
  Bit16u di = DI;
1647
 
1648
  write_virtual_byte_32(BX_SEG_REG_ES, di, AL);
1649
 
1650
  if (BX_CPU_THIS_PTR get_DF()) {
1651
    di--;
1652
  }
1653
  else {
1654
    di++;
1655
  }
1656
 
1657
  DI = di;
1658
}
1659
 
1660
// 32 bit address size
1661
void BX_CPP_AttrRegparmN(1) BX_CPU_C::STOSB32_YbAL(bxInstruction_c *i)
1662
{
1663
  Bit32u incr = 1;
1664
  Bit32u edi = EDI;
1665
 
1666
#if (BX_SUPPORT_REPEAT_SPEEDUPS) && (BX_DEBUGGER == 0)
1667
  /* If conditions are right, we can transfer IO to physical memory
1668
   * in a batch, rather than one instruction at a time.
1669
   */
1670
  if (i->repUsedL() && !BX_CPU_THIS_PTR async_event)
1671
  {
1672
    Bit32u byteCount = FastRepSTOSB(i, BX_SEG_REG_ES, edi, AL, ECX);
1673
    if (byteCount) {
1674
      // Decrement the ticks count by the number of iterations, minus
1675
      // one, since the main cpu loop will decrement one.  Also,
1676
      // the count is predecremented before examined, so defintely
1677
      // don't roll it under zero.
1678
      BX_TICKN(byteCount-1);
1679
 
1680
      // Decrement eCX.  Note, the main loop will decrement 1 also, so
1681
      // decrement by one less than expected, like the case above.
1682
      RCX = ECX - (byteCount-1);
1683
 
1684
      incr = byteCount;
1685
    }
1686
    else {
1687
      write_virtual_byte(BX_SEG_REG_ES, edi, AL);
1688
    }
1689
  }
1690
  else
1691
#endif
1692
  {
1693
    write_virtual_byte(BX_SEG_REG_ES, edi, AL);
1694
  }
1695
 
1696
  if (BX_CPU_THIS_PTR get_DF()) {
1697
    edi -= incr;
1698
  }
1699
  else {
1700
    edi += incr;
1701
  }
1702
 
1703
  // zero extension of RDI
1704
  RDI = edi;
1705
}
1706
 
1707
#if BX_SUPPORT_X86_64
1708
// 64 bit address size
1709
void BX_CPP_AttrRegparmN(1) BX_CPU_C::STOSB64_YbAL(bxInstruction_c *i)
1710
{
1711
  Bit64u rdi = RDI;
1712
 
1713
  write_virtual_byte_64(BX_SEG_REG_ES, rdi, AL);
1714
 
1715
  if (BX_CPU_THIS_PTR get_DF()) {
1716
    rdi--;
1717
  }
1718
  else {
1719
    rdi++;
1720
  }
1721
 
1722
  RDI = rdi;
1723
}
1724
#endif
1725
 
1726
/* 16 bit opsize mode, 16 bit address size */
1727
void BX_CPP_AttrRegparmN(1) BX_CPU_C::STOSW16_YwAX(bxInstruction_c *i)
1728
{
1729
  Bit16u di = DI;
1730
 
1731
  write_virtual_word_32(BX_SEG_REG_ES, di, AX);
1732
 
1733
  if (BX_CPU_THIS_PTR get_DF()) {
1734
    di -= 2;
1735
  }
1736
  else {
1737
    di += 2;
1738
  }
1739
 
1740
  DI = di;
1741
}
1742
 
1743
/* 16 bit opsize mode, 32 bit address size */
1744
void BX_CPP_AttrRegparmN(1) BX_CPU_C::STOSW32_YwAX(bxInstruction_c *i)
1745
{
1746
  Bit32u edi = EDI;
1747
 
1748
  write_virtual_word(BX_SEG_REG_ES, edi, AX);
1749
 
1750
  if (BX_CPU_THIS_PTR get_DF()) {
1751
    edi -= 2;
1752
  }
1753
  else {
1754
    edi += 2;
1755
  }
1756
 
1757
  // zero extension of RDI
1758
  RDI = edi;
1759
}
1760
 
1761
#if BX_SUPPORT_X86_64
1762
/* 16 bit opsize mode, 32 bit address size */
1763
void BX_CPP_AttrRegparmN(1) BX_CPU_C::STOSW64_YwAX(bxInstruction_c *i)
1764
{
1765
  Bit64u rdi = RDI;
1766
 
1767
  write_virtual_word_64(BX_SEG_REG_ES, rdi, AX);
1768
 
1769
  if (BX_CPU_THIS_PTR get_DF()) {
1770
    rdi -= 2;
1771
  }
1772
  else {
1773
    rdi += 2;
1774
  }
1775
 
1776
  RDI = rdi;
1777
}
1778
#endif
1779
 
1780
/* 32 bit opsize mode, 16 bit address size */
1781
void BX_CPP_AttrRegparmN(1) BX_CPU_C::STOSD16_YdEAX(bxInstruction_c *i)
1782
{
1783
  Bit16u di = DI;
1784
 
1785
  write_virtual_dword_32(BX_SEG_REG_ES, di, EAX);
1786
 
1787
  if (BX_CPU_THIS_PTR get_DF()) {
1788
    di -= 4;
1789
  }
1790
  else {
1791
    di += 4;
1792
  }
1793
 
1794
  DI = di;
1795
}
1796
 
1797
/* 32 bit opsize mode, 32 bit address size */
1798
void BX_CPP_AttrRegparmN(1) BX_CPU_C::STOSD32_YdEAX(bxInstruction_c *i)
1799
{
1800
  Bit32u edi = EDI;
1801
 
1802
  write_virtual_dword(BX_SEG_REG_ES, edi, EAX);
1803
 
1804
  if (BX_CPU_THIS_PTR get_DF()) {
1805
    edi -= 4;
1806
  }
1807
  else {
1808
    edi += 4;
1809
  }
1810
 
1811
  // zero extension of RDI
1812
  RDI = edi;
1813
}
1814
 
1815
#if BX_SUPPORT_X86_64
1816
 
1817
/* 32 bit opsize mode, 32 bit address size */
1818
void BX_CPP_AttrRegparmN(1) BX_CPU_C::STOSD64_YdEAX(bxInstruction_c *i)
1819
{
1820
  Bit64u rdi = RDI;
1821
 
1822
  write_virtual_dword_64(BX_SEG_REG_ES, rdi, EAX);
1823
 
1824
  if (BX_CPU_THIS_PTR get_DF()) {
1825
    rdi -= 4;
1826
  }
1827
  else {
1828
    rdi += 4;
1829
  }
1830
 
1831
  RDI = rdi;
1832
}
1833
 
1834
/* 64 bit opsize mode, 32 bit address size */
1835
void BX_CPP_AttrRegparmN(1) BX_CPU_C::STOSQ32_YqRAX(bxInstruction_c *i)
1836
{
1837
  Bit32u edi = EDI;
1838
 
1839
  write_virtual_qword_64(BX_SEG_REG_ES, edi, RAX);
1840
 
1841
  if (BX_CPU_THIS_PTR get_DF()) {
1842
    edi -= 8;
1843
  }
1844
  else {
1845
    edi += 8;
1846
  }
1847
 
1848
  // zero extension of RDI
1849
  RDI = edi;
1850
}
1851
 
1852
/* 64 bit opsize mode, 64 bit address size */
1853
void BX_CPP_AttrRegparmN(1) BX_CPU_C::STOSQ64_YqRAX(bxInstruction_c *i)
1854
{
1855
  Bit64u rdi = RDI;
1856
 
1857
  write_virtual_qword_64(BX_SEG_REG_ES, rdi, RAX);
1858
 
1859
  if (BX_CPU_THIS_PTR get_DF()) {
1860
    rdi -= 8;
1861
  }
1862
  else {
1863
    rdi += 8;
1864
  }
1865
 
1866
  RDI = rdi;
1867
}
1868
 
1869
#endif
1870
 
1871
//
1872
// REP LODS methods
1873
//
1874
 
1875
BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::REP_LODSB_ALXb(bxInstruction_c *i)
1876
{
1877
#if BX_SUPPORT_X86_64
1878
  if (i->as64L())
1879
    BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::LODSB64_ALXb);
1880
  else
1881
#endif
1882
  if (i->as32L()) {
1883
    BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::LODSB32_ALXb);
1884
    BX_CLEAR_64BIT_HIGH(BX_64BIT_REG_RSI); // always clear upper part of RSI
1885
  }
1886
  else {
1887
    BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::LODSB16_ALXb);
1888
  }
1889
 
1890
  BX_NEXT_INSTR(i);
1891
}
1892
 
1893
BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::REP_LODSW_AXXw(bxInstruction_c *i)
1894
{
1895
#if BX_SUPPORT_X86_64
1896
  if (i->as64L())
1897
    BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::LODSW64_AXXw);
1898
  else
1899
#endif
1900
  if (i->as32L()) {
1901
    BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::LODSW32_AXXw);
1902
    BX_CLEAR_64BIT_HIGH(BX_64BIT_REG_RSI); // always clear upper part of RSI
1903
  }
1904
  else {
1905
    BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::LODSW16_AXXw);
1906
  }
1907
 
1908
  BX_NEXT_INSTR(i);
1909
}
1910
 
1911
BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::REP_LODSD_EAXXd(bxInstruction_c *i)
1912
{
1913
#if BX_SUPPORT_X86_64
1914
  if (i->as64L())
1915
    BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::LODSD64_EAXXd);
1916
  else
1917
#endif
1918
  if (i->as32L()) {
1919
    BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::LODSD32_EAXXd);
1920
    BX_CLEAR_64BIT_HIGH(BX_64BIT_REG_RSI); // always clear upper part of RSI
1921
  }
1922
  else {
1923
    BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::LODSD16_EAXXd);
1924
  }
1925
 
1926
  BX_NEXT_INSTR(i);
1927
}
1928
 
1929
#if BX_SUPPORT_X86_64
1930
BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::REP_LODSQ_RAXXq(bxInstruction_c *i)
1931
{
1932
  if (i->as64L()) {
1933
    BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::LODSQ64_RAXXq);
1934
  }
1935
  else {
1936
    BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::LODSQ32_RAXXq);
1937
    BX_CLEAR_64BIT_HIGH(BX_64BIT_REG_RSI); // always clear upper part of RSI
1938
  }
1939
 
1940
  BX_NEXT_INSTR(i);
1941
}
1942
#endif
1943
 
1944
//
1945
// LODSB/LODSW/LODSD/LODSQ methods
1946
//
1947
 
1948
/* 16 bit address size */
1949
void BX_CPP_AttrRegparmN(1) BX_CPU_C::LODSB16_ALXb(bxInstruction_c *i)
1950
{
1951
  Bit16u si = SI;
1952
 
1953
  AL = read_virtual_byte_32(i->seg(), si);
1954
 
1955
  if (BX_CPU_THIS_PTR get_DF()) {
1956
    si--;
1957
  }
1958
  else {
1959
    si++;
1960
  }
1961
 
1962
  SI = si;
1963
}
1964
 
1965
/* 32 bit address size */
1966
void BX_CPP_AttrRegparmN(1) BX_CPU_C::LODSB32_ALXb(bxInstruction_c *i)
1967
{
1968
  Bit32u esi = ESI;
1969
 
1970
  AL = read_virtual_byte(i->seg(), esi);
1971
 
1972
  if (BX_CPU_THIS_PTR get_DF()) {
1973
    esi--;
1974
  }
1975
  else {
1976
    esi++;
1977
  }
1978
 
1979
  // zero extension of RSI
1980
  RSI = esi;
1981
}
1982
 
1983
#if BX_SUPPORT_X86_64
1984
/* 64 bit address size */
1985
void BX_CPP_AttrRegparmN(1) BX_CPU_C::LODSB64_ALXb(bxInstruction_c *i)
1986
{
1987
  Bit64u rsi = RSI;
1988
 
1989
  AL = read_virtual_byte_64(i->seg(), rsi);
1990
 
1991
  if (BX_CPU_THIS_PTR get_DF()) {
1992
    rsi--;
1993
  }
1994
  else {
1995
    rsi++;
1996
  }
1997
 
1998
  RSI = rsi;
1999
}
2000
#endif
2001
 
2002
/* 16 bit opsize mode, 16 bit address size */
2003
void BX_CPP_AttrRegparmN(1) BX_CPU_C::LODSW16_AXXw(bxInstruction_c *i)
2004
{
2005
  Bit16u si = SI;
2006
 
2007
  AX = read_virtual_word_32(i->seg(), si);
2008
 
2009
  if (BX_CPU_THIS_PTR get_DF()) {
2010
    si -= 2;
2011
  }
2012
  else {
2013
    si += 2;
2014
  }
2015
 
2016
  SI = si;
2017
}
2018
 
2019
/* 16 bit opsize mode, 32 bit address size */
2020
void BX_CPP_AttrRegparmN(1) BX_CPU_C::LODSW32_AXXw(bxInstruction_c *i)
2021
{
2022
  Bit32u esi = ESI;
2023
 
2024
  AX = read_virtual_word(i->seg(), esi);
2025
 
2026
  if (BX_CPU_THIS_PTR get_DF()) {
2027
    esi -= 2;
2028
  }
2029
  else {
2030
    esi += 2;
2031
  }
2032
 
2033
  // zero extension of RSI
2034
  RSI = esi;
2035
}
2036
 
2037
#if BX_SUPPORT_X86_64
2038
/* 16 bit opsize mode, 64 bit address size */
2039
void BX_CPP_AttrRegparmN(1) BX_CPU_C::LODSW64_AXXw(bxInstruction_c *i)
2040
{
2041
  Bit64u rsi = RSI;
2042
 
2043
  AX = read_virtual_word_64(i->seg(), rsi);
2044
 
2045
  if (BX_CPU_THIS_PTR get_DF()) {
2046
    rsi -= 2;
2047
  }
2048
  else {
2049
    rsi += 2;
2050
  }
2051
 
2052
  RSI = rsi;
2053
}
2054
#endif
2055
 
2056
/* 32 bit opsize mode, 16 bit address size */
2057
void BX_CPP_AttrRegparmN(1) BX_CPU_C::LODSD16_EAXXd(bxInstruction_c *i)
2058
{
2059
  Bit16u si = SI;
2060
 
2061
  RAX = read_virtual_dword_32(i->seg(), si);
2062
 
2063
  if (BX_CPU_THIS_PTR get_DF()) {
2064
    si -= 4;
2065
  }
2066
  else {
2067
    si += 4;
2068
  }
2069
 
2070
  SI = si;
2071
}
2072
 
2073
/* 32 bit opsize mode, 32 bit address size */
2074
void BX_CPP_AttrRegparmN(1) BX_CPU_C::LODSD32_EAXXd(bxInstruction_c *i)
2075
{
2076
  Bit32u esi = ESI;
2077
 
2078
  RAX = read_virtual_dword(i->seg(), esi);
2079
 
2080
  if (BX_CPU_THIS_PTR get_DF()) {
2081
    esi -= 4;
2082
  }
2083
  else {
2084
    esi += 4;
2085
  }
2086
 
2087
  // zero extension of RSI
2088
  RSI = esi;
2089
}
2090
 
2091
#if BX_SUPPORT_X86_64
2092
 
2093
/* 32 bit opsize mode, 64 bit address size */
2094
void BX_CPP_AttrRegparmN(1) BX_CPU_C::LODSD64_EAXXd(bxInstruction_c *i)
2095
{
2096
  Bit64u rsi = RSI;
2097
 
2098
  RAX = read_virtual_dword_64(i->seg(), rsi);
2099
 
2100
  if (BX_CPU_THIS_PTR get_DF()) {
2101
    rsi -= 4;
2102
  }
2103
  else {
2104
    rsi += 4;
2105
  }
2106
 
2107
  RSI = rsi;
2108
}
2109
 
2110
/* 64 bit opsize mode, 32 bit address size */
2111
void BX_CPP_AttrRegparmN(1) BX_CPU_C::LODSQ32_RAXXq(bxInstruction_c *i)
2112
{
2113
  Bit32u esi = ESI;
2114
 
2115
  RAX = read_virtual_qword_64(i->seg(), esi);
2116
 
2117
  if (BX_CPU_THIS_PTR get_DF()) {
2118
    esi -= 8;
2119
  }
2120
  else {
2121
    esi += 8;
2122
  }
2123
 
2124
  // zero extension of RSI
2125
  RSI = esi;
2126
}
2127
 
2128
/* 64 bit opsize mode, 64 bit address size */
2129
void BX_CPP_AttrRegparmN(1) BX_CPU_C::LODSQ64_RAXXq(bxInstruction_c *i)
2130
{
2131
  Bit64u rsi = RSI;
2132
 
2133
  RAX = read_virtual_qword_64(i->seg(), rsi);
2134
 
2135
  if (BX_CPU_THIS_PTR get_DF()) {
2136
    rsi -= 8;
2137
  }
2138
  else {
2139
    rsi += 8;
2140
  }
2141
 
2142
  RSI = rsi;
2143
}
2144
 
2145
#endif

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.