~ubuntu-branches/ubuntu/saucy/bochs/saucy-proposed

« back to all changes in this revision

Viewing changes to cpu/ctrl_xfer32.cc

  • Committer: Bazaar Package Importer
  • Author(s): David Futcher
  • Date: 2009-04-30 07:46:11 UTC
  • mfrom: (1.1.11 upstream) (4.1.7 squeeze)
  • Revision ID: james.westby@ubuntu.com-20090430074611-6dih80a5mk2uvxhk
Tags: 2.3.7+20090416-1ubuntu1
* Merge from debian unstable (LP: #370427), remaining changes:
  - debian/patches/12_no-ssp.patch: Build bios with -fno-stack-protector
  - Add Replaces/Conflicts for bochsbios-qemu (<< 2.3.6-2)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/////////////////////////////////////////////////////////////////////////
2
 
// $Id: ctrl_xfer32.cc,v 1.72 2008/04/30 16:31:07 sshwarts Exp $
 
2
// $Id: ctrl_xfer32.cc,v 1.85 2009/03/22 21:12:35 sshwarts Exp $
3
3
/////////////////////////////////////////////////////////////////////////
4
4
//
5
5
//  Copyright (C) 2001  MandrakeSoft S.A.
22
22
//
23
23
//  You should have received a copy of the GNU Lesser General Public
24
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
 
25
//  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA
26
26
/////////////////////////////////////////////////////////////////////////
27
27
 
28
28
#define NEED_CPU_REG_SHORTCUTS 1
33
33
// Make code more tidy with a few macros.
34
34
#if BX_SUPPORT_X86_64==0
35
35
#define RSP ESP
 
36
#define RIP EIP
36
37
#endif
37
38
 
38
 
void BX_CPP_AttrRegparmN(1) BX_CPU_C::branch_near32(Bit32u new_EIP)
 
39
#if BX_CPU_LEVEL >= 3
 
40
 
 
41
BX_CPP_INLINE void BX_CPP_AttrRegparmN(1) BX_CPU_C::branch_near32(Bit32u new_EIP)
39
42
{
 
43
  BX_ASSERT(BX_CPU_THIS_PTR cpu_mode != BX_MODE_LONG_64);
 
44
 
40
45
  // check always, not only in protected mode
41
46
  if (new_EIP > BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.limit_scaled)
42
47
  {
43
 
    BX_ERROR(("branch_near: offset outside of CS limits"));
 
48
    BX_ERROR(("branch_near32: offset outside of CS limits"));
44
49
    exception(BX_GP_EXCEPTION, 0, 0);
45
50
  }
46
51
 
 
52
  EIP = new_EIP;
 
53
 
47
54
#if BX_SUPPORT_TRACE_CACHE && !defined(BX_TRACE_CACHE_NO_SPECULATIVE_TRACING)
48
55
  // assert magic async_event to stop trace execution
49
56
  BX_CPU_THIS_PTR async_event |= BX_ASYNC_EVENT_STOP_TRACE;
50
57
#endif
51
 
 
52
 
  EIP = new_EIP;
53
58
}
54
59
 
55
 
#if BX_CPU_LEVEL >= 3
56
 
 
57
60
void BX_CPP_AttrRegparmN(1) BX_CPU_C::RETnear32_Iw(bxInstruction_c *i)
58
61
{
 
62
  BX_ASSERT(BX_CPU_THIS_PTR cpu_mode != BX_MODE_LONG_64);
 
63
 
59
64
#if BX_DEBUGGER
60
65
  BX_CPU_THIS_PTR show_flag |= Flag_ret;
61
66
#endif
62
67
 
63
 
  BX_CPU_THIS_PTR speculative_rsp = 1;
64
 
  BX_CPU_THIS_PTR prev_rsp = RSP;
 
68
  RSP_SPECULATIVE;
65
69
 
66
70
  Bit16u imm16 = i->Iw();
67
71
  Bit32u return_EIP = pop_32();
68
 
  branch_near32(return_EIP);
 
72
  if (return_EIP > BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.limit_scaled)
 
73
  {
 
74
    BX_ERROR(("RETnear32_Iw: offset outside of CS limits"));
 
75
    exception(BX_GP_EXCEPTION, 0, 0);
 
76
  }
 
77
  EIP = return_EIP;
 
78
 
69
79
  if (BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.d_b)
70
80
    ESP += imm16;
71
81
  else
72
82
     SP += imm16;
73
83
 
74
 
  BX_CPU_THIS_PTR speculative_rsp = 0;
 
84
  RSP_COMMIT;
75
85
 
76
86
  BX_INSTR_UCNEAR_BRANCH(BX_CPU_ID, BX_INSTR_IS_RET, EIP);
77
87
}
78
88
 
79
89
void BX_CPP_AttrRegparmN(1) BX_CPU_C::RETnear32(bxInstruction_c *i)
80
90
{
 
91
  BX_ASSERT(BX_CPU_THIS_PTR cpu_mode != BX_MODE_LONG_64);
 
92
 
81
93
#if BX_DEBUGGER
82
94
  BX_CPU_THIS_PTR show_flag |= Flag_ret;
83
95
#endif
84
96
 
85
 
  BX_CPU_THIS_PTR speculative_rsp = 1;
86
 
  BX_CPU_THIS_PTR prev_rsp = RSP;
 
97
  RSP_SPECULATIVE;
87
98
 
88
99
  Bit32u return_EIP = pop_32();
89
 
  branch_near32(return_EIP);
 
100
  if (return_EIP > BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.limit_scaled)
 
101
  {
 
102
    BX_ERROR(("RETnear32: offset outside of CS limits"));
 
103
    exception(BX_GP_EXCEPTION, 0, 0);
 
104
  }
 
105
  EIP = return_EIP;
90
106
 
91
 
  BX_CPU_THIS_PTR speculative_rsp = 0;
 
107
  RSP_COMMIT;
92
108
 
93
109
  BX_INSTR_UCNEAR_BRANCH(BX_CPU_ID, BX_INSTR_IS_RET, EIP);
94
110
}
105
121
  Bit16u cs_raw;
106
122
  Bit32u eip;
107
123
 
108
 
  BX_CPU_THIS_PTR speculative_rsp = 1;
109
 
  BX_CPU_THIS_PTR prev_rsp = RSP;
 
124
  RSP_SPECULATIVE;
110
125
 
111
126
  if (protected_mode()) {
112
 
    BX_CPU_THIS_PTR return_protected(i, imm16);
 
127
    return_protected(i, imm16);
113
128
    goto done;
114
129
  }
115
130
 
116
 
  eip = pop_32();
 
131
  eip    =          pop_32();
 
132
  cs_raw = (Bit16u) pop_32(); /* 32bit pop, MSW discarded */
117
133
 
118
134
  // CS.LIMIT can't change when in real/v8086 mode
119
135
  if (eip > BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.limit_scaled) {
121
137
    exception(BX_GP_EXCEPTION, 0, 0);
122
138
  }
123
139
 
124
 
  cs_raw = (Bit16u) pop_32(); /* 32bit pop, MSW discarded */
125
 
 
126
140
  load_seg_reg(&BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS], cs_raw);
127
141
  EIP = eip;
128
142
 
132
146
     SP += imm16;
133
147
 
134
148
done:
135
 
  BX_CPU_THIS_PTR speculative_rsp = 0;
 
149
  RSP_COMMIT;
136
150
 
137
151
  BX_INSTR_FAR_BRANCH(BX_CPU_ID, BX_INSTR_IS_RET,
138
152
                      BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value, EIP);
149
163
  BX_CPU_THIS_PTR show_flag |= Flag_ret;
150
164
#endif
151
165
 
152
 
  BX_CPU_THIS_PTR speculative_rsp = 1;
153
 
  BX_CPU_THIS_PTR prev_rsp = RSP;
 
166
  RSP_SPECULATIVE;
154
167
 
155
168
  if (protected_mode()) {
156
 
    BX_CPU_THIS_PTR return_protected(i, 0);
 
169
    return_protected(i, 0);
157
170
    goto done;
158
171
  }
159
172
 
160
 
  eip = pop_32();
 
173
  eip    =          pop_32();
 
174
  cs_raw = (Bit16u) pop_32(); /* 32bit pop, MSW discarded */
161
175
 
162
176
  // CS.LIMIT can't change when in real/v8086 mode
163
177
  if (eip > BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.limit_scaled) {
165
179
    exception(BX_GP_EXCEPTION, 0, 0);
166
180
  }
167
181
 
168
 
  cs_raw = (Bit16u) pop_32(); /* 32bit pop, MSW discarded */
169
 
 
170
182
  load_seg_reg(&BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS], cs_raw);
171
183
  EIP = eip;
172
184
 
173
185
done:
174
 
  BX_CPU_THIS_PTR speculative_rsp = 0;
 
186
  RSP_COMMIT;
175
187
 
176
188
  BX_INSTR_FAR_BRANCH(BX_CPU_ID, BX_INSTR_IS_RET,
177
189
                      BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value, EIP);
185
197
 
186
198
  Bit32u new_EIP = EIP + i->Id();
187
199
 
188
 
  if (new_EIP > BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.limit_scaled) {
189
 
    BX_ERROR(("CALL_Jd: offset outside of CS limits"));
190
 
    exception(BX_GP_EXCEPTION, 0, 0);
191
 
  }
 
200
  RSP_SPECULATIVE;
192
201
 
193
202
  /* push 32 bit EA of next instruction */
194
203
  push_32(EIP);
195
 
  EIP = new_EIP;
 
204
 
 
205
  branch_near32(new_EIP);
 
206
 
 
207
  RSP_COMMIT;
196
208
 
197
209
  BX_INSTR_UCNEAR_BRANCH(BX_CPU_ID, BX_INSTR_IS_CALL, EIP);
198
210
}
199
211
 
200
212
void BX_CPP_AttrRegparmN(1) BX_CPU_C::CALL32_Ap(bxInstruction_c *i)
201
213
{
 
214
  BX_ASSERT(BX_CPU_THIS_PTR cpu_mode != BX_MODE_LONG_64);
 
215
 
202
216
  Bit16u cs_raw;
203
217
  Bit32u disp32;
204
218
 
211
225
  disp32 = i->Id();
212
226
  cs_raw = i->Iw2();
213
227
 
214
 
  BX_CPU_THIS_PTR speculative_rsp = 1;
215
 
  BX_CPU_THIS_PTR prev_rsp = RSP;
 
228
  RSP_SPECULATIVE;
216
229
 
217
230
  if (protected_mode()) {
218
 
    BX_CPU_THIS_PTR call_protected(i, cs_raw, disp32);
 
231
    call_protected(i, cs_raw, disp32);
219
232
    goto done;
220
233
  }
221
234
 
232
245
  EIP = disp32;
233
246
 
234
247
done:
235
 
  BX_CPU_THIS_PTR speculative_rsp = 0;
 
248
  RSP_COMMIT;
236
249
 
237
250
  BX_INSTR_FAR_BRANCH(BX_CPU_ID, BX_INSTR_IS_CALL,
238
251
                      BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value, EIP);
239
252
}
240
253
 
241
 
void BX_CPP_AttrRegparmN(1) BX_CPU_C::CALL_EdM(bxInstruction_c *i)
242
 
{
243
 
  BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
244
 
 
245
 
#if BX_DEBUGGER
246
 
  BX_CPU_THIS_PTR show_flag |= Flag_call;
247
 
#endif
248
 
 
249
 
  Bit32u op1_32 = read_virtual_dword(i->seg(), RMAddr(i));
250
 
 
251
 
  if (op1_32 > BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.limit_scaled)
252
 
  {
253
 
    BX_ERROR(("CALL_Ed: EIP out of CS limits!"));
254
 
    exception(BX_GP_EXCEPTION, 0, 0);
255
 
  }
256
 
 
257
 
  push_32(EIP);
258
 
  EIP = op1_32;
259
 
 
260
 
  BX_INSTR_UCNEAR_BRANCH(BX_CPU_ID, BX_INSTR_IS_CALL, EIP);
261
 
}
262
 
 
263
254
void BX_CPP_AttrRegparmN(1) BX_CPU_C::CALL_EdR(bxInstruction_c *i)
264
255
{
265
256
#if BX_DEBUGGER
266
257
  BX_CPU_THIS_PTR show_flag |= Flag_call;
267
258
#endif
268
259
 
269
 
  Bit32u op1_32 = BX_READ_32BIT_REG(i->rm());
270
 
 
271
 
  if (op1_32 > BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.limit_scaled)
272
 
  {
273
 
    BX_ERROR(("CALL_Ed: EIP out of CS limits!"));
274
 
    exception(BX_GP_EXCEPTION, 0, 0);
275
 
  }
276
 
 
 
260
  Bit32u new_EIP = BX_READ_32BIT_REG(i->rm());
 
261
 
 
262
  RSP_SPECULATIVE;
 
263
 
 
264
  /* push 32 bit EA of next instruction */
277
265
  push_32(EIP);
278
 
  EIP = op1_32;
 
266
 
 
267
  branch_near32(new_EIP);
 
268
 
 
269
  RSP_COMMIT;
279
270
 
280
271
  BX_INSTR_UCNEAR_BRANCH(BX_CPU_ID, BX_INSTR_IS_CALL, EIP);
281
272
}
291
282
  BX_CPU_THIS_PTR show_flag |= Flag_call;
292
283
#endif
293
284
 
294
 
  BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
 
285
  bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
295
286
 
296
287
  /* pointer, segment address pair */
297
 
  op1_32 = read_virtual_dword(i->seg(), RMAddr(i));
298
 
  cs_raw = read_virtual_word (i->seg(), RMAddr(i)+4);
 
288
  op1_32 = read_virtual_dword(i->seg(), eaddr);
 
289
  cs_raw = read_virtual_word (i->seg(), eaddr+4);
299
290
 
300
 
  BX_CPU_THIS_PTR speculative_rsp = 1;
301
 
  BX_CPU_THIS_PTR prev_rsp = RSP;
 
291
  RSP_SPECULATIVE;
302
292
 
303
293
  if (protected_mode()) {
304
 
    BX_CPU_THIS_PTR call_protected(i, cs_raw, op1_32);
 
294
    call_protected(i, cs_raw, op1_32);
305
295
    goto done;
306
296
  }
307
297
 
318
308
  EIP = op1_32;
319
309
 
320
310
done:
321
 
  BX_CPU_THIS_PTR speculative_rsp = 0;
 
311
  RSP_COMMIT;
322
312
 
323
313
  BX_INSTR_FAR_BRANCH(BX_CPU_ID, BX_INSTR_IS_CALL,
324
314
                      BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value, EIP);
327
317
void BX_CPP_AttrRegparmN(1) BX_CPU_C::JMP_Jd(bxInstruction_c *i)
328
318
{
329
319
  Bit32u new_EIP = EIP + (Bit32s) i->Id();
330
 
 
331
 
  if (new_EIP > BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.limit_scaled)
332
 
  {
333
 
    BX_ERROR(("JMP_Jd: offset outside of CS limits"));
334
 
    exception(BX_GP_EXCEPTION, 0, 0);
335
 
  }
336
 
 
337
 
  EIP = new_EIP;
338
 
 
 
320
  branch_near32(new_EIP);
339
321
  BX_INSTR_UCNEAR_BRANCH(BX_CPU_ID, BX_INSTR_IS_JMP, new_EIP);
340
322
}
341
323
 
345
327
    Bit32u new_EIP = EIP + (Bit32s) i->Id();
346
328
    branch_near32(new_EIP);
347
329
    BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, new_EIP);
348
 
    return;
349
 
  }
350
 
 
351
 
  BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID);
 
330
  }
 
331
#if BX_INSTRUMENTATION
 
332
  else {
 
333
    BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID);
 
334
  }
 
335
#endif
352
336
}
353
337
 
354
338
void BX_CPP_AttrRegparmN(1) BX_CPU_C::JNO_Jd(bxInstruction_c *i)
357
341
    Bit32u new_EIP = EIP + (Bit32s) i->Id();
358
342
    branch_near32(new_EIP);
359
343
    BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, new_EIP);
360
 
    return;
361
 
  }
362
 
 
363
 
  BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID);
 
344
  }
 
345
#if BX_INSTRUMENTATION
 
346
  else {
 
347
    BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID);
 
348
  }
 
349
#endif
364
350
}
365
351
 
366
352
void BX_CPP_AttrRegparmN(1) BX_CPU_C::JB_Jd(bxInstruction_c *i)
369
355
    Bit32u new_EIP = EIP + (Bit32s) i->Id();
370
356
    branch_near32(new_EIP);
371
357
    BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, new_EIP);
372
 
    return;
373
 
  }
374
 
 
375
 
  BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID);
 
358
  }
 
359
#if BX_INSTRUMENTATION
 
360
  else {
 
361
    BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID);
 
362
  }
 
363
#endif
376
364
}
377
365
 
378
366
void BX_CPP_AttrRegparmN(1) BX_CPU_C::JNB_Jd(bxInstruction_c *i)
381
369
    Bit32u new_EIP = EIP + (Bit32s) i->Id();
382
370
    branch_near32(new_EIP);
383
371
    BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, new_EIP);
384
 
    return;
385
 
  }
386
 
 
387
 
  BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID);
 
372
  }
 
373
#if BX_INSTRUMENTATION
 
374
  else {
 
375
    BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID);
 
376
  }
 
377
#endif
388
378
}
389
379
 
390
380
void BX_CPP_AttrRegparmN(1) BX_CPU_C::JZ_Jd(bxInstruction_c *i)
393
383
    Bit32u new_EIP = EIP + (Bit32s) i->Id();
394
384
    branch_near32(new_EIP);
395
385
    BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, new_EIP);
396
 
    return;
397
 
  }
398
 
 
399
 
  BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID);
 
386
  }
 
387
#if BX_INSTRUMENTATION
 
388
  else {
 
389
    BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID);
 
390
  }
 
391
#endif
400
392
}
401
393
 
402
394
void BX_CPP_AttrRegparmN(1) BX_CPU_C::JNZ_Jd(bxInstruction_c *i)
405
397
    Bit32u new_EIP = EIP + (Bit32s) i->Id();
406
398
    branch_near32(new_EIP);
407
399
    BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, new_EIP);
408
 
    return;
409
 
  }
410
 
 
411
 
  BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID);
 
400
  }
 
401
#if BX_INSTRUMENTATION
 
402
  else {
 
403
    BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID);
 
404
  }
 
405
#endif
412
406
}
413
407
 
414
408
void BX_CPP_AttrRegparmN(1) BX_CPU_C::JBE_Jd(bxInstruction_c *i)
417
411
    Bit32u new_EIP = EIP + (Bit32s) i->Id();
418
412
    branch_near32(new_EIP);
419
413
    BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, new_EIP);
420
 
    return;
421
 
  }
422
 
 
423
 
  BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID);
 
414
  }
 
415
#if BX_INSTRUMENTATION
 
416
  else {
 
417
    BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID);
 
418
  }
 
419
#endif
424
420
}
425
421
 
426
422
void BX_CPP_AttrRegparmN(1) BX_CPU_C::JNBE_Jd(bxInstruction_c *i)
429
425
    Bit32u new_EIP = EIP + (Bit32s) i->Id();
430
426
    branch_near32(new_EIP);
431
427
    BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, new_EIP);
432
 
    return;
433
 
  }
434
 
 
435
 
  BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID);
 
428
  }
 
429
#if BX_INSTRUMENTATION
 
430
  else {
 
431
    BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID);
 
432
  }
 
433
#endif
436
434
}
437
435
 
438
436
void BX_CPP_AttrRegparmN(1) BX_CPU_C::JS_Jd(bxInstruction_c *i)
441
439
    Bit32u new_EIP = EIP + (Bit32s) i->Id();
442
440
    branch_near32(new_EIP);
443
441
    BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, new_EIP);
444
 
    return;
445
 
  }
446
 
 
447
 
  BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID);
 
442
  }
 
443
#if BX_INSTRUMENTATION
 
444
  else {
 
445
    BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID);
 
446
  }
 
447
#endif
448
448
}
449
449
 
450
450
void BX_CPP_AttrRegparmN(1) BX_CPU_C::JNS_Jd(bxInstruction_c *i)
453
453
    Bit32u new_EIP = EIP + (Bit32s) i->Id();
454
454
    branch_near32(new_EIP);
455
455
    BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, new_EIP);
456
 
    return;
457
 
  }
458
 
 
459
 
  BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID);
 
456
  }
 
457
#if BX_INSTRUMENTATION
 
458
  else {
 
459
    BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID);
 
460
  }
 
461
#endif
460
462
}
461
463
 
462
464
void BX_CPP_AttrRegparmN(1) BX_CPU_C::JP_Jd(bxInstruction_c *i)
465
467
    Bit32u new_EIP = EIP + (Bit32s) i->Id();
466
468
    branch_near32(new_EIP);
467
469
    BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, new_EIP);
468
 
    return;
469
 
  }
470
 
 
471
 
  BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID);
 
470
  }
 
471
#if BX_INSTRUMENTATION
 
472
  else {
 
473
    BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID);
 
474
  }
 
475
#endif
472
476
}
473
477
 
474
478
void BX_CPP_AttrRegparmN(1) BX_CPU_C::JNP_Jd(bxInstruction_c *i)
477
481
    Bit32u new_EIP = EIP + (Bit32s) i->Id();
478
482
    branch_near32(new_EIP);
479
483
    BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, new_EIP);
480
 
    return;
481
 
  }
482
 
 
483
 
  BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID);
 
484
  }
 
485
#if BX_INSTRUMENTATION
 
486
  else {
 
487
    BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID);
 
488
  }
 
489
#endif
484
490
}
485
491
 
486
492
void BX_CPP_AttrRegparmN(1) BX_CPU_C::JL_Jd(bxInstruction_c *i)
489
495
    Bit32u new_EIP = EIP + (Bit32s) i->Id();
490
496
    branch_near32(new_EIP);
491
497
    BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, new_EIP);
492
 
    return;
493
 
  }
494
 
 
495
 
  BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID);
 
498
  }
 
499
#if BX_INSTRUMENTATION
 
500
  else {
 
501
    BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID);
 
502
  }
 
503
#endif
496
504
}
497
505
 
498
506
void BX_CPP_AttrRegparmN(1) BX_CPU_C::JNL_Jd(bxInstruction_c *i)
501
509
    Bit32u new_EIP = EIP + (Bit32s) i->Id();
502
510
    branch_near32(new_EIP);
503
511
    BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, new_EIP);
504
 
    return;
505
 
  }
506
 
 
507
 
  BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID);
 
512
  }
 
513
#if BX_INSTRUMENTATION
 
514
  else {
 
515
    BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID);
 
516
  }
 
517
#endif
508
518
}
509
519
 
510
520
void BX_CPP_AttrRegparmN(1) BX_CPU_C::JLE_Jd(bxInstruction_c *i)
513
523
    Bit32u new_EIP = EIP + (Bit32s) i->Id();
514
524
    branch_near32(new_EIP);
515
525
    BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, new_EIP);
516
 
    return;
517
 
  }
518
 
 
519
 
  BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID);
 
526
  }
 
527
#if BX_INSTRUMENTATION
 
528
  else {
 
529
    BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID);
 
530
  }
 
531
#endif
520
532
}
521
533
 
522
534
void BX_CPP_AttrRegparmN(1) BX_CPU_C::JNLE_Jd(bxInstruction_c *i)
535
547
 
536
548
void BX_CPP_AttrRegparmN(1) BX_CPU_C::JMP_Ap(bxInstruction_c *i)
537
549
{
 
550
  BX_ASSERT(BX_CPU_THIS_PTR cpu_mode != BX_MODE_LONG_64);
 
551
 
538
552
  Bit32u disp32;
539
553
  Bit16u cs_raw;
540
554
 
548
562
  }
549
563
  cs_raw = i->Iw2();
550
564
 
551
 
  // jump_protected doesn't affect RSP so it is RSP safe
 
565
  // jump_protected doesn't affect ESP so it is ESP safe
552
566
  if (protected_mode()) {
553
 
    BX_CPU_THIS_PTR jump_protected(i, cs_raw, disp32);
 
567
    jump_protected(i, cs_raw, disp32);
554
568
    goto done;
555
569
  }
556
570
 
568
582
                      BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value, EIP);
569
583
}
570
584
 
571
 
void BX_CPP_AttrRegparmN(1) BX_CPU_C::JMP_EdM(bxInstruction_c *i)
572
 
{
573
 
  BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
574
 
 
575
 
  /* pointer, segment address pair */
576
 
  Bit32u new_EIP = read_virtual_dword(i->seg(), RMAddr(i));
577
 
 
578
 
  if (new_EIP > BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.limit_scaled)
579
 
  {
580
 
    BX_ERROR(("JMP_Ed: offset outside of CS limits"));
581
 
    exception(BX_GP_EXCEPTION, 0, 0);
582
 
  }
583
 
 
584
 
  EIP = new_EIP;
585
 
 
586
 
  BX_INSTR_UCNEAR_BRANCH(BX_CPU_ID, BX_INSTR_IS_JMP, new_EIP);
587
 
}
588
 
 
589
585
void BX_CPP_AttrRegparmN(1) BX_CPU_C::JMP_EdR(bxInstruction_c *i)
590
586
{
591
587
  Bit32u new_EIP = BX_READ_32BIT_REG(i->rm());
592
 
 
593
 
  if (new_EIP > BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.limit_scaled)
594
 
  {
595
 
    BX_ERROR(("JMP_Ed: offset outside of CS limits"));
596
 
    exception(BX_GP_EXCEPTION, 0, 0);
597
 
  }
598
 
 
599
 
  EIP = new_EIP;
600
 
 
 
588
  branch_near32(new_EIP);
601
589
  BX_INSTR_UCNEAR_BRANCH(BX_CPU_ID, BX_INSTR_IS_JMP, new_EIP);
602
590
}
603
591
 
609
597
 
610
598
  invalidate_prefetch_q();
611
599
 
612
 
  BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
 
600
  bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
613
601
 
614
602
  /* pointer, segment address pair */
615
 
  op1_32 = read_virtual_dword(i->seg(), RMAddr(i));
616
 
  cs_raw = read_virtual_word (i->seg(), RMAddr(i)+4);
 
603
  op1_32 = read_virtual_dword(i->seg(), eaddr);
 
604
  cs_raw = read_virtual_word (i->seg(), eaddr+4);
617
605
 
618
606
  // jump_protected doesn't affect RSP so it is RSP safe
619
607
  if (protected_mode()) {
620
 
    BX_CPU_THIS_PTR jump_protected(i, cs_raw, op1_32);
 
608
    jump_protected(i, cs_raw, op1_32);
621
609
    goto done;
622
610
  }
623
611
 
637
625
 
638
626
void BX_CPP_AttrRegparmN(1) BX_CPU_C::IRET32(bxInstruction_c *i)
639
627
{
 
628
  BX_ASSERT(BX_CPU_THIS_PTR cpu_mode != BX_MODE_LONG_64);
 
629
 
640
630
  Bit32u eip, eflags32;
641
631
  Bit16u cs_raw;
642
632
 
643
633
  invalidate_prefetch_q();
644
634
 
 
635
#if BX_SUPPORT_VMX
 
636
  if (!BX_CPU_THIS_PTR in_vmx_guest || !VMEXIT(VMX_VM_EXEC_CTRL1_NMI_VMEXIT))
 
637
#endif
 
638
    BX_CPU_THIS_PTR disable_NMI = 0;
 
639
 
645
640
#if BX_DEBUGGER
646
641
  BX_CPU_THIS_PTR show_flag |= Flag_iret;
647
642
#endif
648
643
 
649
 
  BX_CPU_THIS_PTR nmi_disable = 0;
650
 
 
651
 
  BX_CPU_THIS_PTR speculative_rsp = 1;
652
 
  BX_CPU_THIS_PTR prev_rsp = RSP;
 
644
  RSP_SPECULATIVE;
653
645
 
654
646
  if (v8086_mode()) {
655
647
    // IOPL check in stack_return_from_v86()
662
654
    goto done;
663
655
  }
664
656
 
665
 
  eip = pop_32();
 
657
  eip      =          pop_32();
 
658
  cs_raw   = (Bit16u) pop_32(); // #SS has higher priority
 
659
  eflags32 =          pop_32();
666
660
 
667
661
  // CS.LIMIT can't change when in real/v8086 mode
668
662
  if (eip > BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.limit_scaled) {
670
664
    exception(BX_GP_EXCEPTION, 0, 0);
671
665
  }
672
666
 
673
 
  cs_raw   = (Bit16u) pop_32();
674
 
  eflags32 =          pop_32();
675
 
 
676
667
  load_seg_reg(&BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS], cs_raw);
677
668
  EIP = eip;
678
669
  writeEFlags(eflags32, 0x00257fd5); // VIF, VIP, VM unchanged
679
670
 
680
671
done:
681
 
  BX_CPU_THIS_PTR speculative_rsp = 0;
 
672
  RSP_COMMIT;
682
673
 
683
674
  BX_INSTR_FAR_BRANCH(BX_CPU_ID, BX_INSTR_IS_IRET,
684
675
                      BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value, EIP);
685
676
}
686
677
 
 
678
void BX_CPP_AttrRegparmN(1) BX_CPU_C::JECXZ_Jb(bxInstruction_c *i)
 
679
{
 
680
  // it is impossible to get this instruction in long mode
 
681
  BX_ASSERT(i->as64L() == 0);
 
682
 
 
683
  Bit32u temp_ECX;
 
684
 
 
685
  if (i->as32L())
 
686
    temp_ECX = ECX;
 
687
  else
 
688
    temp_ECX = CX;
 
689
 
 
690
  if (temp_ECX == 0) {
 
691
    Bit32u new_EIP = EIP + (Bit32s) i->Id();
 
692
    branch_near32(new_EIP);
 
693
    BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, new_EIP);
 
694
  }
 
695
#if BX_INSTRUMENTATION
 
696
  else {
 
697
    BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID);
 
698
  }
 
699
#endif
 
700
}
 
701
 
 
702
//
 
703
// There is some weirdness in LOOP instructions definition. If an exception
 
704
// was generated during the instruction execution (for example #GP fault
 
705
// because EIP was beyond CS segment limits) CPU state should restore the
 
706
// state prior to instruction execution.
 
707
//
 
708
// The final point that we are not allowed to decrement ECX register before
 
709
// it is known that no exceptions can happen.
 
710
//
 
711
 
 
712
void BX_CPP_AttrRegparmN(1) BX_CPU_C::LOOPNE32_Jb(bxInstruction_c *i)
 
713
{
 
714
  // it is impossible to get this instruction in long mode
 
715
  BX_ASSERT(i->as64L() == 0);
 
716
 
 
717
  if (i->as32L()) {
 
718
    Bit32u count = ECX;
 
719
 
 
720
    count--;
 
721
    if (count != 0 && (get_ZF()==0)) {
 
722
      Bit32u new_EIP = EIP + (Bit32s) i->Id();
 
723
      branch_near32(new_EIP);
 
724
      BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, new_EIP);
 
725
    }
 
726
#if BX_INSTRUMENTATION
 
727
    else {
 
728
      BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID);
 
729
    }
 
730
#endif
 
731
 
 
732
    ECX = count;
 
733
  }
 
734
  else {
 
735
    Bit16u count = CX;
 
736
 
 
737
    count--;
 
738
    if (count != 0 && (get_ZF()==0)) {
 
739
      Bit32u new_EIP = EIP + (Bit32s) i->Id();
 
740
      branch_near32(new_EIP);
 
741
      BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, new_EIP);
 
742
    }
 
743
#if BX_INSTRUMENTATION
 
744
    else {
 
745
      BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID);
 
746
    }
 
747
#endif
 
748
 
 
749
    CX = count;
 
750
  }
 
751
}
 
752
 
 
753
void BX_CPP_AttrRegparmN(1) BX_CPU_C::LOOPE32_Jb(bxInstruction_c *i)
 
754
{
 
755
  // it is impossible to get this instruction in long mode
 
756
  BX_ASSERT(i->as64L() == 0);
 
757
 
 
758
  if (i->as32L()) {
 
759
    Bit32u count = ECX;
 
760
 
 
761
    count--;
 
762
    if (count != 0 && get_ZF()) {
 
763
      Bit32u new_EIP = EIP + (Bit32s) i->Id();
 
764
      branch_near32(new_EIP);
 
765
      BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, new_EIP);
 
766
    }
 
767
#if BX_INSTRUMENTATION
 
768
    else {
 
769
      BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID);
 
770
    }
 
771
#endif
 
772
 
 
773
    ECX = count;
 
774
  }
 
775
  else {
 
776
    Bit16u count = CX;
 
777
 
 
778
    count--;
 
779
    if (count != 0 && get_ZF()) {
 
780
      Bit32u new_EIP = EIP + (Bit32s) i->Id();
 
781
      branch_near32(new_EIP);
 
782
      BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, new_EIP);
 
783
    }
 
784
#if BX_INSTRUMENTATION
 
785
    else {
 
786
      BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID);
 
787
    }
 
788
#endif
 
789
 
 
790
    CX = count;
 
791
  }
 
792
}
 
793
 
 
794
void BX_CPP_AttrRegparmN(1) BX_CPU_C::LOOP32_Jb(bxInstruction_c *i)
 
795
{
 
796
  // it is impossible to get this instruction in long mode
 
797
  BX_ASSERT(i->as64L() == 0);
 
798
 
 
799
  if (i->as32L()) {
 
800
    Bit32u count = ECX;
 
801
 
 
802
    count--;
 
803
    if (count != 0) {
 
804
      Bit32u new_EIP = EIP + (Bit32s) i->Id();
 
805
      branch_near32(new_EIP);
 
806
      BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, new_EIP);
 
807
    }
 
808
#if BX_INSTRUMENTATION
 
809
    else {
 
810
      BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID);
 
811
    }
 
812
#endif
 
813
 
 
814
    ECX = count;
 
815
  }
 
816
  else {
 
817
    Bit16u count = CX;
 
818
 
 
819
    count--;
 
820
    if (count != 0) {
 
821
      Bit32u new_EIP = EIP + (Bit32s) i->Id();
 
822
      branch_near32(new_EIP);
 
823
      BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, new_EIP);
 
824
    }
 
825
#if BX_INSTRUMENTATION
 
826
    else {
 
827
      BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID);
 
828
    }
 
829
#endif
 
830
 
 
831
    CX = count;
 
832
  }
 
833
}
 
834
 
687
835
#endif