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

Subversion Repositories ao486

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

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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