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

« back to all changes in this revision

Viewing changes to cpu/ctrl_xfer16.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_xfer16.cc,v 1.55 2008/05/08 21:04:03 sshwarts Exp $
 
2
// $Id: ctrl_xfer16.cc,v 1.68 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
 
#endif
 
36
#define RIP EIP
 
37
#endif
 
38
 
 
39
BX_CPP_INLINE void BX_CPP_AttrRegparmN(1) BX_CPU_C::branch_near16(Bit16u new_IP)
 
40
{
 
41
  BX_ASSERT(BX_CPU_THIS_PTR cpu_mode != BX_MODE_LONG_64);
 
42
 
 
43
  // check always, not only in protected mode
 
44
  if (new_IP > BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.limit_scaled)
 
45
  {
 
46
    BX_ERROR(("branch_near16: offset outside of CS limits"));
 
47
    exception(BX_GP_EXCEPTION, 0, 0);
 
48
  }
 
49
 
 
50
  EIP = new_IP;
 
51
 
 
52
#if BX_SUPPORT_TRACE_CACHE && !defined(BX_TRACE_CACHE_NO_SPECULATIVE_TRACING)
 
53
  // assert magic async_event to stop trace execution
 
54
  BX_CPU_THIS_PTR async_event |= BX_ASYNC_EVENT_STOP_TRACE;
 
55
#endif
 
56
}
37
57
 
38
58
void BX_CPP_AttrRegparmN(1) BX_CPU_C::RETnear16_Iw(bxInstruction_c *i)
39
59
{
 
60
  BX_ASSERT(BX_CPU_THIS_PTR cpu_mode != BX_MODE_LONG_64);
 
61
 
40
62
#if BX_DEBUGGER
41
63
  BX_CPU_THIS_PTR show_flag |= Flag_ret;
42
64
#endif
43
65
 
44
 
  BX_CPU_THIS_PTR speculative_rsp = 1;
45
 
  BX_CPU_THIS_PTR prev_rsp = RSP;
 
66
  RSP_SPECULATIVE;
46
67
 
47
68
  Bit16u return_IP = pop_16();
48
69
 
61
82
  else
62
83
     SP += imm16;
63
84
 
64
 
  BX_CPU_THIS_PTR speculative_rsp = 0;
 
85
  RSP_COMMIT;
65
86
 
66
87
  BX_INSTR_UCNEAR_BRANCH(BX_CPU_ID, BX_INSTR_IS_RET, EIP);
67
88
}
68
89
 
69
90
void BX_CPP_AttrRegparmN(1) BX_CPU_C::RETnear16(bxInstruction_c *i)
70
91
{
 
92
  BX_ASSERT(BX_CPU_THIS_PTR cpu_mode != BX_MODE_LONG_64);
 
93
 
71
94
#if BX_DEBUGGER
72
95
  BX_CPU_THIS_PTR show_flag |= Flag_ret;
73
96
#endif
74
97
 
75
 
  BX_CPU_THIS_PTR speculative_rsp = 1;
76
 
  BX_CPU_THIS_PTR prev_rsp = RSP;
 
98
  RSP_SPECULATIVE;
77
99
 
78
100
  Bit16u return_IP = pop_16();
79
101
 
85
107
 
86
108
  EIP = return_IP;
87
109
 
88
 
  BX_CPU_THIS_PTR speculative_rsp = 0;
 
110
  RSP_COMMIT;
89
111
 
90
112
  BX_INSTR_UCNEAR_BRANCH(BX_CPU_ID, BX_INSTR_IS_RET, EIP);
91
113
}
92
114
 
93
115
void BX_CPP_AttrRegparmN(1) BX_CPU_C::RETfar16_Iw(bxInstruction_c *i)
94
116
{
95
 
  Bit16s imm16;
96
117
  Bit16u ip, cs_raw;
97
118
 
98
119
  invalidate_prefetch_q();
101
122
  BX_CPU_THIS_PTR show_flag |= Flag_ret;
102
123
#endif
103
124
 
104
 
  imm16 = i->Iw();
 
125
  Bit16s imm16 = (Bit16s) i->Iw();
105
126
 
106
 
  BX_CPU_THIS_PTR speculative_rsp = 1;
107
 
  BX_CPU_THIS_PTR prev_rsp = RSP;
 
127
  RSP_SPECULATIVE;
108
128
 
109
129
  if (protected_mode()) {
110
 
    BX_CPU_THIS_PTR return_protected(i, imm16);
 
130
    return_protected(i, imm16);
111
131
    goto done;
112
132
  }
113
133
 
114
134
  ip     = pop_16();
115
135
  cs_raw = pop_16();
116
136
 
 
137
  // CS.LIMIT can't change when in real/v8086 mode
 
138
  if (ip > BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.limit_scaled) {
 
139
    BX_ERROR(("RETfar16_Iw: instruction pointer not within code segment limits"));
 
140
    exception(BX_GP_EXCEPTION, 0, 0);
 
141
  }
 
142
 
117
143
  load_seg_reg(&BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS], cs_raw);
118
 
  EIP = (Bit32u) ip;
 
144
  RIP = (Bit32u) ip;
119
145
 
120
146
  if (BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.d_b)
121
147
    ESP += imm16;
123
149
     SP += imm16;
124
150
 
125
151
done:
126
 
 
127
 
  BX_CPU_THIS_PTR speculative_rsp = 0;
 
152
  RSP_COMMIT;
128
153
 
129
154
  BX_INSTR_FAR_BRANCH(BX_CPU_ID, BX_INSTR_IS_RET,
130
155
                      BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value, EIP);
140
165
  BX_CPU_THIS_PTR show_flag |= Flag_ret;
141
166
#endif
142
167
 
143
 
  BX_CPU_THIS_PTR speculative_rsp = 1;
144
 
  BX_CPU_THIS_PTR prev_rsp = RSP;
 
168
  RSP_SPECULATIVE;
145
169
 
146
170
  if (protected_mode()) {
147
 
    BX_CPU_THIS_PTR return_protected(i, 0);
 
171
    return_protected(i, 0);
148
172
    goto done;
149
173
  }
150
174
 
151
175
  ip     = pop_16();
152
176
  cs_raw = pop_16();
153
177
 
 
178
  // CS.LIMIT can't change when in real/v8086 mode
 
179
  if (ip > BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.limit_scaled) {
 
180
    BX_ERROR(("RETfar16: instruction pointer not within code segment limits"));
 
181
    exception(BX_GP_EXCEPTION, 0, 0);
 
182
  }
 
183
 
154
184
  load_seg_reg(&BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS], cs_raw);
155
185
  EIP = (Bit32u) ip;
156
186
 
157
187
done:
158
 
 
159
 
  BX_CPU_THIS_PTR speculative_rsp = 0;
 
188
  RSP_COMMIT;
160
189
 
161
190
  BX_INSTR_FAR_BRANCH(BX_CPU_ID, BX_INSTR_IS_RET,
162
191
                      BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value, EIP);
164
193
 
165
194
void BX_CPP_AttrRegparmN(1) BX_CPU_C::CALL_Jw(bxInstruction_c *i)
166
195
{
167
 
  Bit32u new_EIP;
168
 
 
169
196
#if BX_DEBUGGER
170
197
  BX_CPU_THIS_PTR show_flag |= Flag_call;
171
198
#endif
172
199
 
173
 
  new_EIP = EIP + (Bit32s) i->Id();
174
 
  new_EIP &= 0x0000ffff;
175
 
 
176
 
  if (new_EIP > BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.limit_scaled)
177
 
  {
178
 
    BX_ERROR(("CALL_Jw: new_IP > BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].limit"));
179
 
    exception(BX_GP_EXCEPTION, 0, 0);
180
 
  }
 
200
  RSP_SPECULATIVE;
181
201
 
182
202
  /* push 16 bit EA of next instruction */
183
203
  push_16(IP);
184
 
  EIP = new_EIP;
 
204
 
 
205
  Bit16u new_IP = IP + i->Iw();
 
206
  branch_near16(new_IP);
 
207
 
 
208
  RSP_COMMIT;
185
209
 
186
210
  BX_INSTR_UCNEAR_BRANCH(BX_CPU_ID, BX_INSTR_IS_CALL, EIP);
187
211
}
188
212
 
189
213
void BX_CPP_AttrRegparmN(1) BX_CPU_C::CALL16_Ap(bxInstruction_c *i)
190
214
{
191
 
  Bit16u cs_raw;
192
 
  Bit16u disp16;
 
215
  BX_ASSERT(BX_CPU_THIS_PTR cpu_mode != BX_MODE_LONG_64);
193
216
 
194
217
  invalidate_prefetch_q();
195
218
 
197
220
  BX_CPU_THIS_PTR show_flag |= Flag_call;
198
221
#endif
199
222
 
200
 
  disp16 = i->Iw();
201
 
  cs_raw = i->Iw2();
 
223
  Bit16u disp16 = i->Iw();
 
224
  Bit16u cs_raw = i->Iw2();
202
225
 
203
 
  BX_CPU_THIS_PTR speculative_rsp = 1;
204
 
  BX_CPU_THIS_PTR prev_rsp = RSP;
 
226
  RSP_SPECULATIVE;
205
227
 
206
228
  if (protected_mode()) {
207
 
    BX_CPU_THIS_PTR call_protected(i, cs_raw, disp16);
 
229
    call_protected(i, cs_raw, disp16);
208
230
    goto done;
209
231
  }
210
232
 
211
233
  push_16(BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value);
212
 
  push_16((Bit16u) EIP);
 
234
  push_16(IP);
 
235
 
 
236
  // CS.LIMIT can't change when in real/v8086 mode
 
237
  if (disp16 > BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.limit_scaled) {
 
238
    BX_ERROR(("CALL16_Ap: instruction pointer not within code segment limits"));
 
239
    exception(BX_GP_EXCEPTION, 0, 0);
 
240
  }
213
241
 
214
242
  load_seg_reg(&BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS], cs_raw);
215
243
  EIP = (Bit32u) disp16;
216
244
 
217
245
done:
218
 
 
219
 
  BX_CPU_THIS_PTR speculative_rsp = 0;
 
246
  RSP_COMMIT;
220
247
 
221
248
  BX_INSTR_FAR_BRANCH(BX_CPU_ID, BX_INSTR_IS_CALL,
222
249
                      BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value, EIP);
223
250
}
224
251
 
225
 
void BX_CPP_AttrRegparmN(1) BX_CPU_C::CALL_EwM(bxInstruction_c *i)
226
 
{
227
 
  BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
228
 
 
229
 
#if BX_DEBUGGER
230
 
  BX_CPU_THIS_PTR show_flag |= Flag_call;
231
 
#endif
232
 
 
233
 
  Bit16u op1_16 = read_virtual_word(i->seg(), RMAddr(i));
234
 
 
235
 
  if (op1_16 > BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.limit_scaled)
236
 
  {
237
 
    BX_ERROR(("CALL_Ew: IP out of CS limits!"));
238
 
    exception(BX_GP_EXCEPTION, 0, 0);
239
 
  }
240
 
 
241
 
  push_16(IP);
242
 
  EIP = op1_16;
243
 
 
244
 
  BX_INSTR_UCNEAR_BRANCH(BX_CPU_ID, BX_INSTR_IS_CALL, EIP);
245
 
}
246
 
 
247
252
void BX_CPP_AttrRegparmN(1) BX_CPU_C::CALL_EwR(bxInstruction_c *i)
248
253
{
249
 
  Bit16u op1_16 = BX_READ_16BIT_REG(i->rm());
 
254
  Bit16u new_IP = BX_READ_16BIT_REG(i->rm());
250
255
 
251
256
#if BX_DEBUGGER
252
257
  BX_CPU_THIS_PTR show_flag |= Flag_call;
253
258
#endif
254
259
 
255
 
  if (op1_16 > BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.limit_scaled)
256
 
  {
257
 
    BX_ERROR(("CALL_Ew: IP out of CS limits!"));
258
 
    exception(BX_GP_EXCEPTION, 0, 0);
259
 
  }
 
260
  RSP_SPECULATIVE;
260
261
 
 
262
  /* push 16 bit EA of next instruction */
261
263
  push_16(IP);
262
 
  EIP = op1_16;
 
264
 
 
265
  branch_near16(new_IP);
 
266
 
 
267
  RSP_COMMIT;
263
268
 
264
269
  BX_INSTR_UCNEAR_BRANCH(BX_CPU_ID, BX_INSTR_IS_CALL, EIP);
265
270
}
275
280
  BX_CPU_THIS_PTR show_flag |= Flag_call;
276
281
#endif
277
282
 
278
 
  BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
279
 
 
280
 
  op1_16 = read_virtual_word(i->seg(), RMAddr(i));
281
 
  cs_raw = read_virtual_word(i->seg(), RMAddr(i)+2);
282
 
 
283
 
  BX_CPU_THIS_PTR speculative_rsp = 1;
284
 
  BX_CPU_THIS_PTR prev_rsp = RSP;
 
283
  bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
 
284
 
 
285
  op1_16 = read_virtual_word(i->seg(), eaddr);
 
286
  cs_raw = read_virtual_word(i->seg(), eaddr+2);
 
287
 
 
288
  RSP_SPECULATIVE;
285
289
 
286
290
  if (protected_mode()) {
287
 
    BX_CPU_THIS_PTR call_protected(i, cs_raw, op1_16);
 
291
    call_protected(i, cs_raw, op1_16);
288
292
    goto done;
289
293
  }
290
294
 
291
295
  push_16(BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value);
292
296
  push_16(IP);
293
297
 
 
298
  // CS.LIMIT can't change when in real/v8086 mode
 
299
  if (op1_16 > BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.limit_scaled) {
 
300
    BX_ERROR(("CALL16_Ep: instruction pointer not within code segment limits"));
 
301
    exception(BX_GP_EXCEPTION, 0, 0);
 
302
  }
 
303
 
294
304
  load_seg_reg(&BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS], cs_raw);
295
305
  EIP = op1_16;
296
306
 
297
307
done:
298
 
 
299
 
  BX_CPU_THIS_PTR speculative_rsp = 0;
 
308
  RSP_COMMIT;
300
309
 
301
310
  BX_INSTR_FAR_BRANCH(BX_CPU_ID, BX_INSTR_IS_CALL,
302
311
                      BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value, EIP);
304
313
 
305
314
void BX_CPP_AttrRegparmN(1) BX_CPU_C::JMP_Jw(bxInstruction_c *i)
306
315
{
307
 
  Bit32u new_EIP = EIP + (Bit32s) i->Id();
308
 
  new_EIP &= 0x0000ffff;
309
 
 
310
 
  if (new_EIP > BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.limit_scaled)
311
 
  {
312
 
    BX_ERROR(("JMP_Jw: offset outside of CS limits"));
313
 
    exception(BX_GP_EXCEPTION, 0, 0);
314
 
  }
315
 
 
316
 
  EIP = new_EIP;
317
 
 
318
 
  BX_INSTR_UCNEAR_BRANCH(BX_CPU_ID, BX_INSTR_IS_JMP, new_EIP);
 
316
  Bit16u new_IP = IP + i->Iw();
 
317
  branch_near16(new_IP);
 
318
  BX_INSTR_UCNEAR_BRANCH(BX_CPU_ID, BX_INSTR_IS_JMP, new_IP);
319
319
}
320
320
 
321
321
void BX_CPP_AttrRegparmN(1) BX_CPU_C::JO_Jw(bxInstruction_c *i)
322
322
{
323
323
  if (get_OF()) {
324
 
    Bit32u new_EIP = EIP + (Bit32s) i->Id();
325
 
    new_EIP &= 0x0000ffff;
326
 
    branch_near32(new_EIP);
327
 
    BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, new_EIP);
328
 
    return;
329
 
  }
330
 
 
331
 
  BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID);
 
324
    Bit16u new_IP = IP + i->Iw();
 
325
    branch_near16(new_IP);
 
326
    BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, new_IP);
 
327
  }
 
328
#if BX_INSTRUMENTATION
 
329
  else {
 
330
    BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID);
 
331
  }
 
332
#endif
332
333
}
333
334
 
334
335
void BX_CPP_AttrRegparmN(1) BX_CPU_C::JNO_Jw(bxInstruction_c *i)
335
336
{
336
337
  if (! get_OF()) {
337
 
    Bit32u new_EIP = EIP + (Bit32s) i->Id();
338
 
    new_EIP &= 0x0000ffff;
339
 
    branch_near32(new_EIP);
340
 
    BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, new_EIP);
341
 
    return;
342
 
  }
343
 
 
344
 
  BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID);
 
338
    Bit16u new_IP = IP + i->Iw();
 
339
    branch_near16(new_IP);
 
340
    BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, new_IP);
 
341
  }
 
342
#if BX_INSTRUMENTATION
 
343
  else {
 
344
    BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID);
 
345
  }
 
346
#endif
345
347
}
346
348
 
347
349
void BX_CPP_AttrRegparmN(1) BX_CPU_C::JB_Jw(bxInstruction_c *i)
348
350
{
349
351
  if (get_CF()) {
350
 
    Bit32u new_EIP = EIP + (Bit32s) i->Id();
351
 
    new_EIP &= 0x0000ffff;
352
 
    branch_near32(new_EIP);
353
 
    BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, new_EIP);
354
 
    return;
355
 
  }
356
 
 
357
 
  BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID);
 
352
    Bit16u new_IP = IP + i->Iw();
 
353
    branch_near16(new_IP);
 
354
    BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, new_IP);
 
355
  }
 
356
#if BX_INSTRUMENTATION
 
357
  else {
 
358
    BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID);
 
359
  }
 
360
#endif
358
361
}
359
362
 
360
363
void BX_CPP_AttrRegparmN(1) BX_CPU_C::JNB_Jw(bxInstruction_c *i)
361
364
{
362
365
  if (! get_CF()) {
363
 
    Bit32u new_EIP = EIP + (Bit32s) i->Id();
364
 
    new_EIP &= 0x0000ffff;
365
 
    branch_near32(new_EIP);
366
 
    BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, new_EIP);
367
 
    return;
368
 
  }
369
 
 
370
 
  BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID);
 
366
    Bit16u new_IP = IP + i->Iw();
 
367
    branch_near16(new_IP);
 
368
    BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, new_IP);
 
369
  }
 
370
#if BX_INSTRUMENTATION
 
371
  else {
 
372
    BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID);
 
373
  }
 
374
#endif
371
375
}
372
376
 
373
377
void BX_CPP_AttrRegparmN(1) BX_CPU_C::JZ_Jw(bxInstruction_c *i)
374
378
{
375
379
  if (get_ZF()) {
376
 
    Bit32u new_EIP = EIP + (Bit32s) i->Id();
377
 
    new_EIP &= 0x0000ffff;
378
 
    branch_near32(new_EIP);
379
 
    BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, new_EIP);
380
 
    return;
381
 
  }
382
 
 
383
 
  BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID);
 
380
    Bit16u new_IP = IP + i->Iw();
 
381
    branch_near16(new_IP);
 
382
    BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, new_IP);
 
383
  }
 
384
#if BX_INSTRUMENTATION
 
385
  else {
 
386
    BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID);
 
387
  }
 
388
#endif
384
389
}
385
390
 
386
391
void BX_CPP_AttrRegparmN(1) BX_CPU_C::JNZ_Jw(bxInstruction_c *i)
387
392
{
388
393
  if (! get_ZF()) {
389
 
    Bit32u new_EIP = EIP + (Bit32s) i->Id();
390
 
    new_EIP &= 0x0000ffff;
391
 
    branch_near32(new_EIP);
392
 
    BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, new_EIP);
393
 
    return;
394
 
  }
395
 
 
396
 
  BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID);
 
394
    Bit16u new_IP = IP + i->Iw();
 
395
    branch_near16(new_IP);
 
396
    BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, new_IP);
 
397
  }
 
398
#if BX_INSTRUMENTATION
 
399
  else {
 
400
    BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID);
 
401
  }
 
402
#endif
397
403
}
398
404
 
399
405
void BX_CPP_AttrRegparmN(1) BX_CPU_C::JBE_Jw(bxInstruction_c *i)
400
406
{
401
407
  if (get_CF() || get_ZF()) {
402
 
    Bit32u new_EIP = EIP + (Bit32s) i->Id();
403
 
    new_EIP &= 0x0000ffff;
404
 
    branch_near32(new_EIP);
405
 
    BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, new_EIP);
406
 
    return;
407
 
  }
408
 
 
409
 
  BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID);
 
408
    Bit16u new_IP = IP + i->Iw();
 
409
    branch_near16(new_IP);
 
410
    BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, new_IP);
 
411
  }
 
412
#if BX_INSTRUMENTATION
 
413
  else {
 
414
    BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID);
 
415
  }
 
416
#endif
410
417
}
411
418
 
412
419
void BX_CPP_AttrRegparmN(1) BX_CPU_C::JNBE_Jw(bxInstruction_c *i)
413
420
{
414
421
  if (! (get_CF() || get_ZF())) {
415
 
    Bit32u new_EIP = EIP + (Bit32s) i->Id();
416
 
    new_EIP &= 0x0000ffff;
417
 
    branch_near32(new_EIP);
418
 
    BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, new_EIP);
419
 
    return;
420
 
  }
421
 
 
422
 
  BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID);
 
422
    Bit16u new_IP = IP + i->Iw();
 
423
    branch_near16(new_IP);
 
424
    BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, new_IP);
 
425
  }
 
426
#if BX_INSTRUMENTATION
 
427
  else {
 
428
    BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID);
 
429
  }
 
430
#endif
423
431
}
424
432
 
425
433
void BX_CPP_AttrRegparmN(1) BX_CPU_C::JS_Jw(bxInstruction_c *i)
426
434
{
427
435
  if (get_SF()) {
428
 
    Bit32u new_EIP = EIP + (Bit32s) i->Id();
429
 
    new_EIP &= 0x0000ffff;
430
 
    branch_near32(new_EIP);
431
 
    BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, new_EIP);
432
 
    return;
433
 
  }
434
 
 
435
 
  BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID);
 
436
    Bit16u new_IP = IP + i->Iw();
 
437
    branch_near16(new_IP);
 
438
    BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, new_IP);
 
439
  }
 
440
#if BX_INSTRUMENTATION
 
441
  else {
 
442
    BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID);
 
443
  }
 
444
#endif
436
445
}
437
446
 
438
447
void BX_CPP_AttrRegparmN(1) BX_CPU_C::JNS_Jw(bxInstruction_c *i)
439
448
{
440
449
  if (! get_SF()) {
441
 
    Bit32u new_EIP = EIP + (Bit32s) i->Id();
442
 
    new_EIP &= 0x0000ffff;
443
 
    branch_near32(new_EIP);
444
 
    BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, new_EIP);
445
 
    return;
446
 
  }
447
 
 
448
 
  BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID);
 
450
    Bit16u new_IP = IP + i->Iw();
 
451
    branch_near16(new_IP);
 
452
    BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, new_IP);
 
453
  }
 
454
#if BX_INSTRUMENTATION
 
455
  else {
 
456
    BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID);
 
457
  }
 
458
#endif
449
459
}
450
460
 
451
461
void BX_CPP_AttrRegparmN(1) BX_CPU_C::JP_Jw(bxInstruction_c *i)
452
462
{
453
463
  if (get_PF()) {
454
 
    Bit32u new_EIP = EIP + (Bit32s) i->Id();
455
 
    new_EIP &= 0x0000ffff;
456
 
    branch_near32(new_EIP);
457
 
    BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, new_EIP);
458
 
    return;
459
 
  }
460
 
 
461
 
  BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID);
 
464
    Bit16u new_IP = IP + i->Iw();
 
465
    branch_near16(new_IP);
 
466
    BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, new_IP);
 
467
  }
 
468
#if BX_INSTRUMENTATION
 
469
  else {
 
470
    BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID);
 
471
  }
 
472
#endif
462
473
}
463
474
 
464
475
void BX_CPP_AttrRegparmN(1) BX_CPU_C::JNP_Jw(bxInstruction_c *i)
465
476
{
466
477
  if (! get_PF()) {
467
 
    Bit32u new_EIP = EIP + (Bit32s) i->Id();
468
 
    new_EIP &= 0x0000ffff;
469
 
    branch_near32(new_EIP);
470
 
    BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, new_EIP);
471
 
    return;
472
 
  }
473
 
 
474
 
  BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID);
 
478
    Bit16u new_IP = IP + i->Iw();
 
479
    branch_near16(new_IP);
 
480
    BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, new_IP);
 
481
  }
 
482
#if BX_INSTRUMENTATION
 
483
  else {
 
484
    BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID);
 
485
  }
 
486
#endif
475
487
}
476
488
 
477
489
void BX_CPP_AttrRegparmN(1) BX_CPU_C::JL_Jw(bxInstruction_c *i)
478
490
{
479
491
  if (getB_SF() != getB_OF()) {
480
 
    Bit32u new_EIP = EIP + (Bit32s) i->Id();
481
 
    new_EIP &= 0x0000ffff;
482
 
    branch_near32(new_EIP);
483
 
    BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, new_EIP);
484
 
    return;
485
 
  }
486
 
 
487
 
  BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID);
 
492
    Bit16u new_IP = IP + i->Iw();
 
493
    branch_near16(new_IP);
 
494
    BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, new_IP);
 
495
  }
 
496
#if BX_INSTRUMENTATION
 
497
  else {
 
498
    BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID);
 
499
  }
 
500
#endif
488
501
}
489
502
 
490
503
void BX_CPP_AttrRegparmN(1) BX_CPU_C::JNL_Jw(bxInstruction_c *i)
491
504
{
492
505
  if (getB_SF() == getB_OF()) {
493
 
    Bit32u new_EIP = EIP + (Bit32s) i->Id();
494
 
    new_EIP &= 0x0000ffff;
495
 
    branch_near32(new_EIP);
496
 
    BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, new_EIP);
497
 
    return;
498
 
  }
499
 
 
500
 
  BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID);
 
506
    Bit16u new_IP = IP + i->Iw();
 
507
    branch_near16(new_IP);
 
508
    BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, new_IP);
 
509
  }
 
510
#if BX_INSTRUMENTATION
 
511
  else {
 
512
    BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID);
 
513
  }
 
514
#endif
501
515
}
502
516
 
503
517
void BX_CPP_AttrRegparmN(1) BX_CPU_C::JLE_Jw(bxInstruction_c *i)
504
518
{
505
519
  if (get_ZF() || (getB_SF() != getB_OF())) {
506
 
    Bit32u new_EIP = EIP + (Bit32s) i->Id();
507
 
    new_EIP &= 0x0000ffff;
508
 
    branch_near32(new_EIP);
509
 
    BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, new_EIP);
510
 
    return;
511
 
  }
512
 
 
513
 
  BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID);
 
520
    Bit16u new_IP = IP + i->Iw();
 
521
    branch_near16(new_IP);
 
522
    BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, new_IP);
 
523
  }
 
524
#if BX_INSTRUMENTATION
 
525
  else {
 
526
    BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID);
 
527
  }
 
528
#endif
514
529
}
515
530
 
516
531
void BX_CPP_AttrRegparmN(1) BX_CPU_C::JNLE_Jw(bxInstruction_c *i)
517
532
{
518
533
  if (! get_ZF() && (getB_SF() == getB_OF())) {
519
 
    Bit32u new_EIP = EIP + (Bit32s) i->Id();
520
 
    new_EIP &= 0x0000ffff;
521
 
    branch_near32(new_EIP);
522
 
    BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, new_EIP);
523
 
    return;
524
 
  }
525
 
 
526
 
  BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID);
527
 
}
528
 
 
529
 
void BX_CPP_AttrRegparmN(1) BX_CPU_C::JMP_EwM(bxInstruction_c *i)
530
 
{
531
 
  BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
532
 
 
533
 
  Bit16u new_IP = read_virtual_word(i->seg(), RMAddr(i));
534
 
 
535
 
  if (new_IP > BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.limit_scaled)
536
 
  {
537
 
    BX_ERROR(("JMP_Ew: offset outside of CS limits"));
538
 
    exception(BX_GP_EXCEPTION, 0, 0);
539
 
  }
540
 
 
541
 
  EIP = new_IP;
542
 
 
543
 
  BX_INSTR_UCNEAR_BRANCH(BX_CPU_ID, BX_INSTR_IS_JMP, new_IP);
 
534
    Bit16u new_IP = IP + i->Iw();
 
535
    branch_near16(new_IP);
 
536
    BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, new_IP);
 
537
  }
 
538
#if BX_INSTRUMENTATION
 
539
  else {
 
540
    BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID);
 
541
  }
 
542
#endif
544
543
}
545
544
 
546
545
void BX_CPP_AttrRegparmN(1) BX_CPU_C::JMP_EwR(bxInstruction_c *i)
547
546
{
548
547
  Bit16u new_IP = BX_READ_16BIT_REG(i->rm());
549
 
 
550
 
  if (new_IP > BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.limit_scaled)
551
 
  {
552
 
    BX_ERROR(("JMP_Ew: offset outside of CS limits"));
553
 
    exception(BX_GP_EXCEPTION, 0, 0);
554
 
  }
555
 
 
556
 
  EIP = new_IP;
557
 
 
 
548
  branch_near16(new_IP);
558
549
  BX_INSTR_UCNEAR_BRANCH(BX_CPU_ID, BX_INSTR_IS_JMP, new_IP);
559
550
}
560
551
 
566
557
 
567
558
  invalidate_prefetch_q();
568
559
 
569
 
  BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
 
560
  bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
570
561
 
571
 
  op1_16 = read_virtual_word(i->seg(), RMAddr(i));
572
 
  cs_raw = read_virtual_word(i->seg(), RMAddr(i)+2);
 
562
  op1_16 = read_virtual_word(i->seg(), eaddr);
 
563
  cs_raw = read_virtual_word(i->seg(), eaddr+2);
573
564
 
574
565
  // jump_protected doesn't affect RSP so it is RSP safe
575
566
  if (protected_mode()) {
576
 
    BX_CPU_THIS_PTR jump_protected(i, cs_raw, op1_16);
 
567
    jump_protected(i, cs_raw, op1_16);
577
568
    goto done;
578
569
  }
579
570
 
 
571
  // CS.LIMIT can't change when in real/v8086 mode
 
572
  if (op1_16 > BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.limit_scaled) {
 
573
    BX_ERROR(("JMP16_Ep: instruction pointer not within code segment limits"));
 
574
    exception(BX_GP_EXCEPTION, 0, 0);
 
575
  }
 
576
 
580
577
  load_seg_reg(&BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS], cs_raw);
581
578
  EIP = op1_16;
582
579
 
583
580
done:
 
581
 
584
582
  BX_INSTR_FAR_BRANCH(BX_CPU_ID, BX_INSTR_IS_JMP,
585
583
                      BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value, EIP);
586
584
}
591
589
 
592
590
  invalidate_prefetch_q();
593
591
 
 
592
#if BX_SUPPORT_VMX
 
593
  if (!BX_CPU_THIS_PTR in_vmx_guest || !VMEXIT(VMX_VM_EXEC_CTRL1_NMI_VMEXIT))
 
594
#endif
 
595
    BX_CPU_THIS_PTR disable_NMI = 0;
 
596
 
594
597
#if BX_DEBUGGER
595
598
  BX_CPU_THIS_PTR show_flag |= Flag_iret;
596
599
#endif
597
600
 
598
 
  BX_CPU_THIS_PTR nmi_disable = 0;
599
 
 
600
 
  BX_CPU_THIS_PTR speculative_rsp = 1;
601
 
  BX_CPU_THIS_PTR prev_rsp = RSP;
 
601
  RSP_SPECULATIVE;
602
602
 
603
603
  if (v8086_mode()) {
604
604
    // IOPL check in stack_return_from_v86()
612
612
  }
613
613
 
614
614
  ip     = pop_16();
615
 
  cs_raw = pop_16();
 
615
  cs_raw = pop_16(); // #SS has higher priority
616
616
  flags  = pop_16();
617
617
 
 
618
  // CS.LIMIT can't change when in real/v8086 mode
 
619
  if(ip > BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.limit_scaled) {
 
620
    BX_ERROR(("IRET16: instruction pointer not within code segment limits"));
 
621
    exception(BX_GP_EXCEPTION, 0, 0);
 
622
  }
 
623
 
618
624
  load_seg_reg(&BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS], cs_raw);
619
 
  EIP = (Bit32u) ip;
 
625
  RIP = (Bit32u) ip;
620
626
  write_flags(flags, /* change IOPL? */ 1, /* change IF? */ 1);
621
627
 
622
628
done:
623
 
  BX_CPU_THIS_PTR speculative_rsp = 0;
 
629
  RSP_COMMIT;
624
630
 
625
631
  BX_INSTR_FAR_BRANCH(BX_CPU_ID, BX_INSTR_IS_IRET,
626
632
                      BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value, EIP);
627
633
}
 
634
 
 
635
void BX_CPP_AttrRegparmN(1) BX_CPU_C::JCXZ_Jb(bxInstruction_c *i)
 
636
{
 
637
  // it is impossible to get this instruction in long mode
 
638
  BX_ASSERT(i->as64L() == 0);
 
639
 
 
640
  Bit32u temp_ECX;
 
641
 
 
642
  if (i->as32L())
 
643
    temp_ECX = ECX;
 
644
  else
 
645
    temp_ECX = CX;
 
646
 
 
647
  if (temp_ECX == 0) {
 
648
    Bit16u new_IP = IP + i->Iw();
 
649
    branch_near16(new_IP);
 
650
    BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, new_IP);
 
651
  }
 
652
#if BX_INSTRUMENTATION
 
653
  else {
 
654
    BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID);
 
655
  }
 
656
#endif
 
657
}
 
658
 
 
659
//
 
660
// There is some weirdness in LOOP instructions definition. If an exception
 
661
// was generated during the instruction execution (for example #GP fault
 
662
// because EIP was beyond CS segment limits) CPU state should restore the
 
663
// state prior to instruction execution.
 
664
//
 
665
// The final point that we are not allowed to decrement ECX register before
 
666
// it is known that no exceptions can happen.
 
667
//
 
668
 
 
669
void BX_CPP_AttrRegparmN(1) BX_CPU_C::LOOPNE16_Jb(bxInstruction_c *i)
 
670
{
 
671
  // it is impossible to get this instruction in long mode
 
672
  BX_ASSERT(i->as64L() == 0);
 
673
 
 
674
  if (i->as32L()) {
 
675
    Bit32u count = ECX;
 
676
 
 
677
    count--;
 
678
    if (count != 0 && (get_ZF()==0)) {
 
679
      Bit16u new_IP = IP + i->Iw();
 
680
      branch_near16(new_IP);
 
681
      BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, new_IP);
 
682
    }
 
683
#if BX_INSTRUMENTATION
 
684
    else {
 
685
      BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID);
 
686
    }
 
687
#endif
 
688
 
 
689
    ECX = count;
 
690
  }
 
691
  else {
 
692
    Bit16u count = CX;
 
693
 
 
694
    count--;
 
695
    if (count != 0 && (get_ZF()==0)) {
 
696
      Bit16u new_IP = IP + i->Iw();
 
697
      branch_near16(new_IP);
 
698
      BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, new_IP);
 
699
    }
 
700
#if BX_INSTRUMENTATION
 
701
    else {
 
702
      BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID);
 
703
    }
 
704
#endif
 
705
 
 
706
    CX = count;
 
707
  }
 
708
}
 
709
 
 
710
void BX_CPP_AttrRegparmN(1) BX_CPU_C::LOOPE16_Jb(bxInstruction_c *i)
 
711
{
 
712
  // it is impossible to get this instruction in long mode
 
713
  BX_ASSERT(i->as64L() == 0);
 
714
 
 
715
  if (i->as32L()) {
 
716
    Bit32u count = ECX;
 
717
 
 
718
    count--;
 
719
    if (count != 0 && get_ZF()) {
 
720
      Bit16u new_IP = IP + i->Iw();
 
721
      branch_near16(new_IP);
 
722
      BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, new_IP);
 
723
    }
 
724
#if BX_INSTRUMENTATION
 
725
    else {
 
726
      BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID);
 
727
    }
 
728
#endif
 
729
 
 
730
    ECX = count;
 
731
  }
 
732
  else {
 
733
    Bit16u count = CX;
 
734
 
 
735
    count--;
 
736
    if (count != 0 && get_ZF()) {
 
737
      Bit16u new_IP = IP + i->Iw();
 
738
      branch_near16(new_IP);
 
739
      BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, new_IP);
 
740
    }
 
741
#if BX_INSTRUMENTATION
 
742
    else {
 
743
      BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID);
 
744
    }
 
745
#endif
 
746
 
 
747
    CX = count;
 
748
  }
 
749
}
 
750
 
 
751
void BX_CPP_AttrRegparmN(1) BX_CPU_C::LOOP16_Jb(bxInstruction_c *i)
 
752
{
 
753
  // it is impossible to get this instruction in long mode
 
754
  BX_ASSERT(i->as64L() == 0);
 
755
 
 
756
  if (i->as32L()) {
 
757
    Bit32u count = ECX;
 
758
 
 
759
    count--;
 
760
    if (count != 0) {
 
761
      Bit16u new_IP = IP + i->Iw();
 
762
      branch_near16(new_IP);
 
763
      BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, new_IP);
 
764
    }
 
765
#if BX_INSTRUMENTATION
 
766
    else {
 
767
      BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID);
 
768
    }
 
769
#endif
 
770
 
 
771
    ECX = count;
 
772
  }
 
773
  else {
 
774
    Bit16u count = CX;
 
775
 
 
776
    count--;
 
777
    if (count != 0) {
 
778
      Bit16u new_IP = IP + i->Iw();
 
779
      branch_near16(new_IP);
 
780
      BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, new_IP);
 
781
    }
 
782
#if BX_INSTRUMENTATION
 
783
    else {
 
784
      BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID);
 
785
    }
 
786
#endif
 
787
 
 
788
    CX = count;
 
789
  }
 
790
}