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

Subversion Repositories s80186

[/] [s80186/] [trunk/] [sim/] [cppmodel/] [Emulate.cpp] - Blame information for rev 2

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 jamieiles
// Copyright Jamie Iles, 2017
2
//
3
// This file is part of s80x86.
4
//
5
// s80x86 is free software: you can redistribute it and/or modify
6
// it under the terms of the GNU General Public License as published by
7
// the Free Software Foundation, either version 3 of the License, or
8
// (at your option) any later version.
9
//
10
// s80x86 is distributed in the hope that it will be useful,
11
// but WITHOUT ANY WARRANTY; without even the implied warranty of
12
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
// GNU General Public License for more details.
14
//
15
// You should have received a copy of the GNU General Public License
16
// along with s80x86.  If not, see <http://www.gnu.org/licenses/>.
17
 
18
#include "Emulate.h"
19
 
20
#include <cassert>
21
#include <cstdlib>
22
#include <iostream>
23
#include <functional>
24
#include <stdint.h>
25
#include "Memory.h"
26
#include "SoftwareCPU.h"
27
 
28
#include <config.h>
29
 
30
template <typename Out, typename In>
31
static inline Out sign_extend(In v)
32
{
33
    static_assert(sizeof(Out) > sizeof(In),
34
                  "May only sign extend to larger types");
35
 
36
    size_t bit_shift = (sizeof(Out) - sizeof(In)) * 8;
37
    Out o = static_cast<Out>(v);
38
 
39
    o <<= bit_shift;
40
    o >>= bit_shift;
41
 
42
    return o;
43
}
44
 
45
enum RepMode {
46
    REPNE, // Prefix 0xf2
47
    REPE,  // Prefix 0xf3
48
};
49
 
50
class EmulatorPimpl
51
{
52
public:
53
    EmulatorPimpl(RegisterFile *registers, SimCPU *sim_cpu);
54
 
55
    size_t step();
56
    size_t step_with_io(std::function<void(unsigned long)> io_callback,
57
                        unsigned long cur_cycle_count);
58
 
59
    void set_memory(Memory *mem)
60
    {
61
        this->mem = mem;
62
    }
63
 
64
    void set_io(std::map<uint16_t, IOPorts *> *io)
65
    {
66
        this->io = io;
67
    }
68
 
69
    bool has_trapped() const
70
    {
71
        auto int_cs = mem->read<uint16_t>(VEC_INT + 2);
72
        auto int_ip = mem->read<uint16_t>(VEC_INT + 0);
73
 
74
        return registers->get(CS) == int_cs && registers->get(IP) == int_ip;
75
    }
76
 
77
    void reset();
78
    void raise_nmi();
79
    void raise_irq(int irq_num);
80
 
81
private:
82
    size_t emulate_insn();
83
    void mov88();
84
    void mov89();
85
    void mov8a();
86
    void mov8b();
87
    void movc6();
88
    void movc7();
89
    void movb0_b7();
90
    void movb8_bf();
91
    void mova0();
92
    void mova1();
93
    void mova2();
94
    void mova3();
95
    void mov8e();
96
    void mov8c();
97
    void pusha60();
98
    void popa61();
99
    void pushff();
100
    void push50_57();
101
    void pushsr();
102
    void push68();
103
    void push6a();
104
    void pop8f();
105
    void pop58_5f();
106
    void popsr();
107
    void xchg86();
108
    void xchg87();
109
    void xchg90_97();
110
    void ine4();
111
    void ine5();
112
    void inec();
113
    void ined();
114
    void oute6();
115
    void oute7();
116
    void outee();
117
    void outef();
118
    void setalcd6();
119
    void xlatd7();
120
    void lea8d();
121
    void ldsc5();
122
    void lesc4();
123
    void lahf9f();
124
    void sahf9e();
125
    void pushf9c();
126
    void popf9d();
127
    void add_adc_sub_sbb_cmp_xor_or_and_80();
128
    void add_adc_sub_sbb_cmp_xor_or_and_81();
129
    void add_adc_sub_sbb_cmp_82();
130
    void add_adc_sub_sbb_cmp_83();
131
    void add00();
132
    void add01();
133
    void add02();
134
    void add03();
135
    void add04();
136
    void add05();
137
    void and20();
138
    void and21();
139
    void and22();
140
    void and23();
141
    void and24();
142
    void and25();
143
    void xor30();
144
    void xor31();
145
    void xor32();
146
    void xor33();
147
    void xor34();
148
    void xor35();
149
    void or08();
150
    void or09();
151
    void or0a();
152
    void or0b();
153
    void or0c();
154
    void or0d();
155
    void adc10();
156
    void adc11();
157
    void adc12();
158
    void adc13();
159
    void adc14();
160
    void adc15();
161
    void sub28();
162
    void sub29();
163
    void sub2a();
164
    void sub2b();
165
    void sub2c();
166
    void sub2d();
167
    void sbb18();
168
    void sbb19();
169
    void sbb1a();
170
    void sbb1b();
171
    void sbb1c();
172
    void sbb1d();
173
    void inc_dec_fe();
174
    void incff();
175
    void inc40_47();
176
    void decff();
177
    void dec48_4f();
178
    void aaa37();
179
    void daa27();
180
    void aas3f();
181
    void das2f();
182
    void aamd4();
183
    void negf6();
184
    void negf7();
185
    void notf6();
186
    void notf7();
187
    void cmp38();
188
    void cmp39();
189
    void cmp3a();
190
    void cmp3b();
191
    void cmp3c();
192
    void cmp3d();
193
    void mulf6();
194
    void mulf7();
195
    void imul6b();
196
    void imul69();
197
    void imulf6();
198
    void imulf7();
199
    void divf6();
200
    void divf7();
201
    void idivf6();
202
    void idivf7();
203
    void intcc();
204
    void intcd();
205
    void intoce();
206
    void cbw98();
207
    void cwd99();
208
    void jmpe9();
209
    void jmpeb();
210
    void jmpff_intra();
211
    void jmpff_inter();
212
    void jmpea();
213
    void je74();
214
    void jl7c();
215
    void jle7e();
216
    void jp7a();
217
    void jb72();
218
    void jbe76();
219
    void jo70();
220
    void js78();
221
    void jns79();
222
    void jne75();
223
    void jnl7d();
224
    void jnle7f();
225
    void jnb73();
226
    void jnbe77();
227
    void jnp7b();
228
    void jno71();
229
    void jcxze3();
230
    void calle8();
231
    void callff_intra();
232
    void callff_inter();
233
    void call9a();
234
    void retc3();
235
    void retc2();
236
    void retcb();
237
    void retca();
238
    void iretcf();
239
    void clcf8();
240
    void cmcf5();
241
    void stcf9();
242
    void cldfc();
243
    void stdfd();
244
    void clifa();
245
    void stifb();
246
    void loope2();
247
    void loopee1();
248
    void loopnze0();
249
    void scasbae();
250
    void scasbaf();
251
    void movsba4();
252
    void movswa5();
253
    void cmpsba6();
254
    void cmpswa7();
255
    void lodsbac();
256
    void lodswad();
257
    void stosbaa();
258
    void stoswab();
259
    void hltf4();
260
    void wait9b();
261
    void escd8();
262
    void aadd5();
263
    void shiftc0();
264
    void shiftc1();
265
    void shiftd0();
266
    void shiftd1();
267
    void shiftd2();
268
    void shiftd3();
269
    void shlc0();
270
    void shlc1();
271
    void shld0();
272
    void shld1();
273
    void shld2();
274
    void shld3();
275
    void shrc0();
276
    void shrc1();
277
    void shrd0();
278
    void shrd1();
279
    void shrd2();
280
    void shrd3();
281
    void sarc0();
282
    void sarc1();
283
    void sard0();
284
    void sard1();
285
    void sard2();
286
    void sard3();
287
    void rolc0();
288
    void rolc1();
289
    void rold0();
290
    void rold1();
291
    void rold2();
292
    void rold3();
293
    void rclc0();
294
    void rclc1();
295
    void rcld0();
296
    void rcld1();
297
    void rcld2();
298
    void rcld3();
299
    void rcrc0();
300
    void rcrc1();
301
    void rcrd0();
302
    void rcrd1();
303
    void rcrd2();
304
    void rcrd3();
305
    void rorc0();
306
    void rorc1();
307
    void rord0();
308
    void rord1();
309
    void rord2();
310
    void rord3();
311
    void test84();
312
    void test85();
313
    void testa8();
314
    void testa9();
315
    void testf6();
316
    void testf7();
317
    void bound62();
318
    void outsb6e();
319
    void outsw6f();
320
    void insb6c();
321
    void insw6d();
322
    void leavec9();
323
    void enterc8();
324
    void invalid_opcode();
325
 
326
    uint8_t fetch_byte();
327
    template <typename T>
328
    std::pair<uint16_t, T> do_mul(int32_t v1, int32_t v2);
329
    template <typename T>
330
    std::pair<uint16_t, T> do_add(uint16_t v1,
331
                                  uint16_t v2,
332
                                  uint16_t carry_in = 0);
333
    template <typename T>
334
    std::pair<uint16_t, T> do_sub(uint16_t v1,
335
                                  uint16_t v2,
336
                                  uint16_t carry_in = 0);
337
    template <typename T>
338
    std::pair<uint16_t, T> do_xor(uint16_t v1, uint16_t v2);
339
    template <typename T>
340
    std::pair<uint16_t, T> do_or(uint16_t v1, uint16_t v2);
341
    template <typename T>
342
    std::pair<uint16_t, T> do_and(uint16_t v1, uint16_t v2);
343
    void push_inc_jmp_call_ff();
344
    void neg_mul_not_test_div_f6();
345
    void neg_mul_not_test_div_f7();
346
    void push_word(uint16_t v);
347
    uint16_t pop_word();
348
    template <typename T>
349
    std::pair<uint16_t, T> do_alu(
350
        int32_t v1,
351
        int32_t v2,
352
        int32_t carry_in,
353
        std::function<uint32_t(uint32_t, uint32_t, uint32_t)> alu_op);
354
    template <typename T>
355
    void write_data(T val, bool stack = false);
356
    template <typename T>
357
    T read_data(bool stack = false);
358
    uint16_t fetch_16bit();
359
    GPR get_segment(bool is_stack_reference);
360
    void set_override_segment(GPR segment);
361
 
362
    void write_io8(uint32_t addr, uint8_t val)
363
    {
364
        if (!io->count(addr & ~1))
365
            return;
366
 
367
        auto p = (*io)[addr & ~1];
368
        p->write8((addr & ~1) - p->get_base(), addr & 1, val);
369
    }
370
    void write_io16(uint32_t addr, uint16_t val)
371
    {
372
        if (!io->count(addr & ~1))
373
            return;
374
 
375
        auto p = (*io)[addr & ~1];
376
        p->write16((addr & ~1) - p->get_base(), val);
377
    }
378
 
379
    uint8_t read_io8(uint32_t addr)
380
    {
381
        if (!io->count(addr & ~1))
382
            return 0;
383
 
384
        auto p = (*io)[addr & ~1];
385
        return p->read8((addr & ~1) - p->get_base(), addr & 1);
386
    }
387
    uint16_t read_io16(uint32_t addr)
388
    {
389
        if (!io->count(addr & ~1))
390
            return 0;
391
 
392
        auto p = (*io)[addr & ~1];
393
        return p->read16((addr & ~1) - p->get_base());
394
    }
395
 
396
    void do_rep(std::function<void()> primitive,
397
                std::function<bool()> should_terminate);
398
    bool string_rep_complete();
399
 
400
    void handle_nmi();
401
    void handle_irq();
402
    void single_step();
403
 
404
    Memory *mem;
405
    std::map<uint16_t, IOPorts *> *io;
406
    RegisterFile *registers;
407
    size_t instr_length = 0;
408
    std::unique_ptr<ModRMDecoder> modrm_decoder;
409
    uint8_t opcode;
410
    bool jump_taken;
411
 
412
    bool default_segment_overriden;
413
    GPR override_segment;
414
 
415
    RepMode rep_mode;
416
    bool has_rep_prefix;
417
    bool nmi_pending;
418
    bool ext_int_inhibit;
419
    uint8_t pending_irq;
420
    bool tf_was_set;
421
    SimCPU *sim_cpu;
422
};
423
 
424
void EmulatorPimpl::do_rep(std::function<void()> primitive,
425
                           std::function<bool()> should_terminate)
426
{
427
    if (!has_rep_prefix) {
428
        primitive();
429
        return;
430
    }
431
 
432
    while (registers->get(CX) != 0) {
433
        primitive();
434
        registers->set(CX, registers->get(CX) - 1);
435
        if (should_terminate())
436
            break;
437
    }
438
}
439
 
440
bool EmulatorPimpl::string_rep_complete()
441
{
442
    if (rep_mode == REPE && !registers->get_flag(ZF))
443
        return true;
444
    if (rep_mode == REPNE && registers->get_flag(ZF))
445
        return true;
446
    return false;
447
}
448
 
449
EmulatorPimpl::EmulatorPimpl(RegisterFile *registers, SimCPU *sim_cpu)
450
    : mem(NULL),
451
      io(NULL),
452
      registers(registers),
453
      jump_taken(false),
454
      default_segment_overriden(false),
455
      rep_mode(REPE),
456
      has_rep_prefix(false),
457
      tf_was_set(false),
458
      sim_cpu(sim_cpu)
459
{
460
    modrm_decoder = std::make_unique<ModRMDecoder>(
461
        [&] { return this->fetch_byte(); }, this->registers);
462
 
463
    reset();
464
}
465
 
466
void EmulatorPimpl::reset()
467
{
468
    registers->reset();
469
    opcode = 0;
470
    instr_length = 0;
471
    nmi_pending = false;
472
    ext_int_inhibit = false;
473
    pending_irq = 0;
474
}
475
 
476
void EmulatorPimpl::raise_nmi()
477
{
478
    nmi_pending = true;
479
}
480
 
481
void EmulatorPimpl::raise_irq(int irq_num)
482
{
483
    pending_irq = irq_num;
484
}
485
 
486
void EmulatorPimpl::handle_nmi()
487
{
488
    nmi_pending = false;
489
 
490
    auto flags = registers->get_flags();
491
 
492
    push_word(flags);
493
    push_word(registers->get(CS));
494
    push_word(registers->get(IP));
495
 
496
    flags &= ~(IF | TF);
497
    registers->set_flags(flags, IF | TF);
498
 
499
    auto new_cs = mem->read<uint16_t>(VEC_NMI + 2);
500
    auto new_ip = mem->read<uint16_t>(VEC_NMI + 0);
501
 
502
    registers->set(CS, new_cs);
503
    registers->set(IP, new_ip);
504
    jump_taken = true;
505
 
506
    single_step();
507
}
508
 
509
void EmulatorPimpl::handle_irq()
510
{
511
    assert(pending_irq);
512
 
513
    auto irq_num = pending_irq;
514
    pending_irq = 0;
515
    sim_cpu->ack_int(irq_num);
516
 
517
    auto flags = registers->get_flags();
518
 
519
    push_word(flags);
520
    push_word(registers->get(CS));
521
    push_word(registers->get(IP));
522
 
523
    flags &= ~(IF | TF);
524
    registers->set_flags(flags, IF | TF);
525
 
526
    auto new_cs = mem->read<uint16_t>(irq_num * 4 + 2);
527
    auto new_ip = mem->read<uint16_t>(irq_num * 4 + 0);
528
 
529
    registers->set(CS, new_cs);
530
    registers->set(IP, new_ip);
531
    jump_taken = true;
532
 
533
    single_step();
534
}
535
 
536
void EmulatorPimpl::single_step()
537
{
538
    if (!tf_was_set || ext_int_inhibit)
539
        return;
540
 
541
    auto flags = registers->get_flags();
542
    push_word(flags);
543
    push_word(registers->get(CS));
544
    push_word(registers->get(IP));
545
 
546
    flags &= ~(IF | TF);
547
    registers->set_flags(flags, IF | TF);
548
 
549
    auto new_cs = mem->read<uint16_t>(VEC_SINGLE_STEP + 2);
550
    auto new_ip = mem->read<uint16_t>(VEC_SINGLE_STEP + 0);
551
 
552
    registers->set(CS, new_cs);
553
    registers->set(IP, new_ip);
554
    jump_taken = true;
555
}
556
 
557
size_t EmulatorPimpl::step()
558
{
559
    tf_was_set = registers->get_flag(TF);
560
    if (nmi_pending && !ext_int_inhibit) {
561
        handle_nmi();
562
        return 0;
563
    } else if (pending_irq && !ext_int_inhibit && registers->get_flag(IF)) {
564
        handle_irq();
565
        return 0;
566
    }
567
 
568
    auto len = emulate_insn();
569
    // Hardware also processes interrupt entry at the tail of an instruction
570
    // rather than a conditional check at the start of each instruction.  So
571
    // when single stepping, stepping an instruction may retire that
572
    // instruction and then jump to the NMI/INT handler.
573
    if (nmi_pending && !ext_int_inhibit)
574
        handle_nmi();
575
    else if (pending_irq && !ext_int_inhibit && registers->get_flag(IF))
576
        handle_irq();
577
    else if (!ext_int_inhibit)
578
        single_step();
579
 
580
    return len;
581
}
582
 
583
size_t EmulatorPimpl::step_with_io(
584
    std::function<void(unsigned long)> io_callback,
585
    unsigned long cur_cycle_count)
586
{
587
    io_callback(cur_cycle_count);
588
 
589
    return this->step();
590
}
591
 
592
size_t EmulatorPimpl::emulate_insn()
593
{
594
    instr_length = 0;
595
    bool processing_prefixes;
596
    default_segment_overriden = false;
597
    has_rep_prefix = false;
598
    modrm_decoder->clear();
599
    jump_taken = false;
600
    ext_int_inhibit = false;
601
 
602
    do {
603
        processing_prefixes = false;
604
        opcode = fetch_byte();
605
        // clang-format off
606
        switch (opcode) {
607
        case 0x06: // fallthrough
608
        case 0x0e: // fallthrough
609
        case 0x16: // fallthrough
610
        case 0x1e: pushsr(); break;
611
        case 0x0f: invalid_opcode(); break;
612
        case 0x07: // fallthrough
613
        case 0x17: // fallthrough
614
        case 0x1f: popsr(); break;
615
 
616
        case 0x00: add00(); break;
617
        case 0x01: add01(); break;
618
        case 0x02: add02(); break;
619
        case 0x03: add03(); break;
620
        case 0x04: add04(); break;
621
        case 0x05: add05(); break;
622
        case 0x08: or08(); break;
623
        case 0x09: or09(); break;
624
        case 0x0a: or0a(); break;
625
        case 0x0b: or0b(); break;
626
        case 0x0c: or0c(); break;
627
        case 0x0d: or0d(); break;
628
        case 0x10: adc10(); break;
629
        case 0x11: adc11(); break;
630
        case 0x12: adc12(); break;
631
        case 0x13: adc13(); break;
632
        case 0x14: adc14(); break;
633
        case 0x15: adc15(); break;
634
        case 0x18: sbb18(); break;
635
        case 0x19: sbb19(); break;
636
        case 0x1a: sbb1a(); break;
637
        case 0x1b: sbb1b(); break;
638
        case 0x1c: sbb1c(); break;
639
        case 0x1d: sbb1d(); break;
640
        case 0x20: and20(); break;
641
        case 0x21: and21(); break;
642
        case 0x22: and22(); break;
643
        case 0x23: and23(); break;
644
        case 0x24: and24(); break;
645
        case 0x25: and25(); break;
646
        case 0x27: daa27(); break;
647
        case 0x28: sub28(); break;
648
        case 0x29: sub29(); break;
649
        case 0x2a: sub2a(); break;
650
        case 0x2b: sub2b(); break;
651
        case 0x2c: sub2c(); break;
652
        case 0x2d: sub2d(); break;
653
        case 0x2f: das2f(); break;
654
        case 0x30: xor30(); break;
655
        case 0x31: xor31(); break;
656
        case 0x32: xor32(); break;
657
        case 0x33: xor33(); break;
658
        case 0x34: xor34(); break;
659
        case 0x35: xor35(); break;
660
        case 0x37: aaa37(); break;
661
        case 0x38: cmp38(); break;
662
        case 0x39: cmp39(); break;
663
        case 0x3a: cmp3a(); break;
664
        case 0x3b: cmp3b(); break;
665
        case 0x3c: cmp3c(); break;
666
        case 0x3d: cmp3d(); break;
667
        case 0x3f: aas3f(); break;
668
        case 0x40 ... 0x47: inc40_47(); break;
669
        case 0x48 ... 0x4f: dec48_4f(); break;
670
        case 0x50 ... 0x57: push50_57(); break;
671
        case 0x58 ... 0x5f: pop58_5f(); break;
672
        case 0x60: pusha60(); break;
673
        case 0x61: popa61(); break;
674
        case 0x62: bound62(); break;
675
        case 0x63: invalid_opcode(); break;
676
        case 0x64: invalid_opcode(); break;
677
        case 0x65: invalid_opcode(); break;
678
        case 0x66: invalid_opcode(); break;
679
        case 0x67: invalid_opcode(); break;
680
        case 0x68: push68(); break;
681
        case 0x69: imul69(); break;
682
        case 0x6a: push6a(); break;
683
        case 0x6b: imul6b(); break;
684
        case 0x6c: insb6c(); break;
685
        case 0x6d: insw6d(); break;
686
        case 0x6e: outsb6e(); break;
687
        case 0x6f: outsw6f(); break;
688
        case 0x70: jo70(); break;
689
        case 0x71: jno71(); break;
690
        case 0x72: jb72(); break;
691
        case 0x73: jnb73(); break;
692
        case 0x74: je74(); break;
693
        case 0x75: jne75(); break;
694
        case 0x76: jbe76(); break;
695
        case 0x77: jnbe77(); break;
696
        case 0x78: js78(); break;
697
        case 0x79: jns79(); break;
698
        case 0x7a: jp7a(); break;
699
        case 0x7b: jnp7b(); break;
700
        case 0x7c: jl7c(); break;
701
        case 0x7d: jnl7d(); break;
702
        case 0x7e: jle7e(); break;
703
        case 0x7f: jnle7f(); break;
704
        case 0x80: add_adc_sub_sbb_cmp_xor_or_and_80(); break;
705
        case 0x81: add_adc_sub_sbb_cmp_xor_or_and_81(); break;
706
        case 0x82: add_adc_sub_sbb_cmp_82(); break;
707
        case 0x83: add_adc_sub_sbb_cmp_83(); break;
708
        case 0x84: test84(); break;
709
        case 0x85: test85(); break;
710
        case 0x86: xchg86(); break;
711
        case 0x87: xchg87(); break;
712
        case 0x88: mov88(); break;
713
        case 0x89: mov89(); break;
714
        case 0x8a: mov8a(); break;
715
        case 0x8b: mov8b(); break;
716
        case 0x8c: mov8c(); break;
717
        case 0x8d: lea8d(); break;
718
        case 0x8e: mov8e(); break;
719
        case 0x8f: pop8f(); break;
720
        case 0x90 ... 0x97: xchg90_97(); break;
721
        case 0x98: cbw98(); break;
722
        case 0x99: cwd99(); break;
723
        case 0x9a: call9a(); break;
724
        case 0x9b: wait9b(); break;
725
        case 0x9c: pushf9c(); break;
726
        case 0x9d: popf9d(); break;
727
        case 0x9e: sahf9e(); break;
728
        case 0x9f: lahf9f(); break;
729
        case 0xa0: mova0(); break;
730
        case 0xa1: mova1(); break;
731
        case 0xa2: mova2(); break;
732
        case 0xa3: mova3(); break;
733
        case 0xa4: movsba4(); break;
734
        case 0xa5: movswa5(); break;
735
        case 0xa6: cmpsba6(); break;
736
        case 0xa7: cmpswa7(); break;
737
        case 0xa8: testa8(); break;
738
        case 0xa9: testa9(); break;
739
        case 0xaa: stosbaa(); break;
740
        case 0xab: stoswab(); break;
741
        case 0xac: lodsbac(); break;
742
        case 0xad: lodswad(); break;
743
        case 0xae: scasbae(); break;
744
        case 0xaf: scasbaf(); break;
745
        case 0xb0 ... 0xb7: movb0_b7(); break;
746
        case 0xb8 ... 0xbf: movb8_bf(); break;
747
        case 0xc0: shiftc0(); break;
748
        case 0xc1: shiftc1(); break;
749
        case 0xc2: retc2(); break;
750
        case 0xc3: retc3(); break;
751
        case 0xc4: lesc4(); break;
752
        case 0xc5: ldsc5(); break;
753
        case 0xc6: movc6(); break;
754
        case 0xc7: movc7(); break;
755
        case 0xc8: enterc8(); break;
756
        case 0xc9: leavec9(); break;
757
        case 0xca: retca(); break;
758
        case 0xcb: retcb(); break;
759
        case 0xcc: intcc(); break;
760
        case 0xcd: intcd(); break;
761
        case 0xce: intoce(); break;
762
        case 0xcf: iretcf(); break;
763
        case 0xd0: shiftd0(); break;
764
        case 0xd1: shiftd1(); break;
765
        case 0xd2: shiftd2(); break;
766
        case 0xd3: shiftd3(); break;
767
        case 0xd4: aamd4(); break;
768
        case 0xd5: aadd5(); break;
769
        case 0xd6: setalcd6(); break;
770
        case 0xd7: xlatd7(); break;
771
        case 0xd8 ... 0xdf: escd8(); break;
772
        case 0xe0: loopnze0(); break;
773
        case 0xe1: loopee1(); break;
774
        case 0xe2: loope2(); break;
775
        case 0xe3: jcxze3(); break;
776
        case 0xe4: ine4(); break;
777
        case 0xe5: ine5(); break;
778
        case 0xe6: oute6(); break;
779
        case 0xe7: oute7(); break;
780
        case 0xe8: calle8(); break;
781
        case 0xe9: jmpe9(); break;
782
        case 0xea: jmpea(); break;
783
        case 0xeb: jmpeb(); break;
784
        case 0xec: inec(); break;
785
        case 0xed: ined(); break;
786
        case 0xee: outee(); break;
787
        case 0xef: outef(); break;
788
        case 0xf1: invalid_opcode(); break;
789
        case 0xf4: hltf4(); break;
790
        case 0xf5: cmcf5(); break;
791
        case 0xf6: neg_mul_not_test_div_f6(); break;
792
        case 0xf7: neg_mul_not_test_div_f7(); break;
793
        case 0xf8: clcf8(); break;
794
        case 0xf9: stcf9(); break;
795
        case 0xfa: clifa(); break;
796
        case 0xfb: stifb(); break;
797
        case 0xfc: cldfc(); break;
798
        case 0xfd: stdfd(); break;
799
        case 0xfe: inc_dec_fe(); break;
800
        case 0xff: push_inc_jmp_call_ff(); break;
801
        case 0xf0: // lock
802
            processing_prefixes = true;
803
            break;
804
        case 0x26:
805
            set_override_segment(ES);
806
            processing_prefixes = true;
807
            break;
808
        case 0x2e:
809
            set_override_segment(CS);
810
            processing_prefixes = true;
811
            break;
812
        case 0x36:
813
            set_override_segment(SS);
814
            processing_prefixes = true;
815
            break;
816
        case 0x3e:
817
            set_override_segment(DS);
818
            processing_prefixes = true;
819
            break;
820
        case 0xf2:
821
            rep_mode = REPNE;
822
            has_rep_prefix = true;
823
            processing_prefixes = true;
824
            break;
825
        case 0xf3:
826
            rep_mode = REPE;
827
            has_rep_prefix = true;
828
            processing_prefixes = true;
829
            break;
830
        default:
831
            std::cerr << "warning: unknown opcode 0x" << std::hex <<
832
                (unsigned)opcode << " at " << (unsigned)registers->get(CS) <<
833
                ":" << (unsigned)registers->get(IP) << std::endl;
834
        }
835
        // clang-format on
836
    } while (processing_prefixes);
837
 
838
    if (!jump_taken)
839
        registers->set(IP, registers->get(IP) + instr_length);
840
 
841
    return instr_length;
842
}
843
 
844
void EmulatorPimpl::push_inc_jmp_call_ff()
845
{
846
    modrm_decoder->set_width(OP_WIDTH_16);
847
    modrm_decoder->decode();
848
 
849
    if (modrm_decoder->raw_reg() == 6)
850
        pushff();
851
    else if (modrm_decoder->raw_reg() == 0)
852
        incff();
853
    else if (modrm_decoder->raw_reg() == 1)
854
        decff();
855
    else if (modrm_decoder->raw_reg() == 2)
856
        callff_intra();
857
    else if (modrm_decoder->raw_reg() == 3)
858
        callff_inter();
859
    else if (modrm_decoder->raw_reg() == 4)
860
        jmpff_intra();
861
    else if (modrm_decoder->raw_reg() == 5)
862
        jmpff_inter();
863
    else
864
        invalid_opcode();
865
}
866
 
867
template <typename T>
868
std::pair<uint16_t, T> EmulatorPimpl::do_alu(
869
    int32_t v1,
870
    int32_t v2,
871
    int32_t carry,
872
    std::function<uint32_t(uint32_t, uint32_t, uint32_t)> alu_op)
873
{
874
    uint16_t flags = registers->get_flags();
875
 
876
    flags &= ~(AF | CF | OF | PF | SF | ZF);
877
 
878
    uint32_t result32 =
879
        alu_op(static_cast<uint32_t>(v1), static_cast<uint32_t>(v2),
880
               static_cast<uint32_t>(carry));
881
    bool af = !!(alu_op(v1 & 0xf, v2 & 0xf, carry) & (1 << 4));
882
 
883
    auto sign_bit = (8 * sizeof(T)) - 1;
884
    auto carry_bit = (8 * sizeof(T));
885
 
886
    if (af)
887
        flags |= AF;
888
    if (result32 & (1 << carry_bit))
889
        flags |= CF;
890
    if (result32 & (1 << sign_bit))
891
        flags |= SF;
892
    if ((result32 & static_cast<T>(-1)) == 0)
893
        flags |= ZF;
894
    if (!__builtin_parity(result32 & static_cast<uint8_t>(-1)))
895
        flags |= PF;
896
    bool carry_in = !!(alu_op(static_cast<uint32_t>(v1) & ~(1 << sign_bit),
897
                              static_cast<uint32_t>(v2) & ~(1 << sign_bit),
898
                              static_cast<uint32_t>(carry)) &
899
                       (1 << sign_bit));
900
    if (carry_in ^ !!(flags & CF))
901
        flags |= OF;
902
 
903
    return std::make_pair(flags, static_cast<T>(result32));
904
}
905
 
906
template <typename T>
907
std::pair<uint16_t, T> EmulatorPimpl::do_add(uint16_t v1,
908
                                             uint16_t v2,
909
                                             uint16_t carry_in)
910
{
911
    return do_alu<T>(v1, v2, carry_in,
912
                     [](uint32_t a, uint32_t b, uint32_t c) -> uint32_t {
913
                         return a + b + c;
914
                     });
915
}
916
 
917
template <typename T>
918
std::pair<uint16_t, T> EmulatorPimpl::do_xor(uint16_t v1, uint16_t v2)
919
{
920
    return do_alu<T>(
921
        v1, v2, 0, [](uint32_t a, uint32_t b, uint32_t __attribute__((unused))
922
                                              c) -> uint32_t { return a ^ b; });
923
}
924
 
925
template <typename T>
926
std::pair<uint16_t, T> EmulatorPimpl::do_or(uint16_t v1, uint16_t v2)
927
{
928
    return do_alu<T>(
929
        v1, v2, 0, [](uint32_t a, uint32_t b, uint32_t __attribute__((unused))
930
                                              c) -> uint32_t { return a | b; });
931
}
932
 
933
template <typename T>
934
std::pair<uint16_t, T> EmulatorPimpl::do_and(uint16_t v1, uint16_t v2)
935
{
936
    return do_alu<T>(
937
        v1, v2, 0, [](uint32_t a, uint32_t b, uint32_t __attribute__((unused))
938
                                              c) -> uint32_t { return a & b; });
939
}
940
 
941
template <typename T>
942
std::pair<uint16_t, T> EmulatorPimpl::do_sub(uint16_t v1,
943
                                             uint16_t v2,
944
                                             uint16_t carry_in)
945
{
946
    return do_alu<T>(v1, v2, carry_in,
947
                     [](uint32_t a, uint32_t b, uint32_t c) -> uint32_t {
948
                         return a - b - c;
949
                     });
950
}
951
 
952
template <typename T>
953
std::pair<uint16_t, T> EmulatorPimpl::do_mul(int32_t v1, int32_t v2)
954
{
955
    return do_alu<T>(
956
        v1, v2, 0, [](uint32_t a, uint32_t b, uint32_t __attribute__((unused))
957
                                              c) -> uint32_t { return a * b; });
958
}
959
 
960
void EmulatorPimpl::add_adc_sub_sbb_cmp_xor_or_and_80()
961
{
962
    modrm_decoder->set_width(OP_WIDTH_8);
963
    modrm_decoder->decode();
964
 
965
    uint8_t v1 = read_data<uint8_t>();
966
    uint8_t v2 = fetch_byte();
967
    bool carry_in =
968
        modrm_decoder->raw_reg() == 2 || modrm_decoder->raw_reg() == 3
969
            ? !!(registers->get_flags() & CF)
970
            : 0;
971
 
972
    uint8_t result;
973
    uint16_t flags;
974
    uint16_t update_mask = OF | SF | ZF | CF | PF | AF;
975
    if (modrm_decoder->raw_reg() == 0 || modrm_decoder->raw_reg() == 2)
976
        std::tie(flags, result) = do_add<uint8_t>(v1, v2, carry_in);
977
    else if (modrm_decoder->raw_reg() == 6) {
978
        std::tie(flags, result) = do_xor<uint8_t>(v1, v2);
979
        flags &= ~(CF | OF);
980
        update_mask &= ~AF;
981
    } else if (modrm_decoder->raw_reg() == 1) {
982
        std::tie(flags, result) = do_or<uint8_t>(v1, v2);
983
        flags &= ~(CF | OF);
984
        update_mask &= ~AF;
985
    } else if (modrm_decoder->raw_reg() == 4) {
986
        std::tie(flags, result) = do_and<uint8_t>(v1, v2);
987
        flags &= ~(CF | OF);
988
        update_mask &= ~AF;
989
    } else
990
        std::tie(flags, result) = do_sub<uint8_t>(v1, v2, carry_in);
991
 
992
    registers->set_flags(flags, update_mask);
993
    // cmp doesn't write the result
994
    if (modrm_decoder->raw_reg() != 7)
995
        write_data<uint8_t>(result & 0xff);
996
}
997
 
998
void EmulatorPimpl::add_adc_sub_sbb_cmp_82()
999
{
1000
    add_adc_sub_sbb_cmp_xor_or_and_80();
1001
}
1002
 
1003
// add r/m, immediate, 16-bit
1004
void EmulatorPimpl::add_adc_sub_sbb_cmp_xor_or_and_81()
1005
{
1006
    modrm_decoder->set_width(OP_WIDTH_16);
1007
    modrm_decoder->decode();
1008
 
1009
    uint16_t v1 = read_data<uint16_t>();
1010
    uint16_t v2 = fetch_16bit();
1011
    bool carry_in =
1012
        modrm_decoder->raw_reg() == 2 || modrm_decoder->raw_reg() == 3
1013
            ? !!(registers->get_flags() & CF)
1014
            : 0;
1015
 
1016
    uint16_t result;
1017
    uint16_t flags;
1018
    uint16_t update_mask = OF | SF | ZF | CF | PF | AF;
1019
    if (modrm_decoder->raw_reg() == 0 || modrm_decoder->raw_reg() == 2)
1020
        std::tie(flags, result) = do_add<uint16_t>(v1, v2, carry_in);
1021
    else if (modrm_decoder->raw_reg() == 6) {
1022
        std::tie(flags, result) = do_xor<uint16_t>(v1, v2);
1023
        flags &= ~(CF | OF);
1024
        update_mask &= ~AF;
1025
    } else if (modrm_decoder->raw_reg() == 1) {
1026
        std::tie(flags, result) = do_or<uint16_t>(v1, v2);
1027
        flags &= ~(CF | OF);
1028
        update_mask &= ~AF;
1029
    } else if (modrm_decoder->raw_reg() == 4) {
1030
        std::tie(flags, result) = do_and<uint16_t>(v1, v2);
1031
        flags &= ~(CF | OF);
1032
        update_mask &= ~AF;
1033
    } else
1034
        std::tie(flags, result) = do_sub<uint16_t>(v1, v2, carry_in);
1035
 
1036
    registers->set_flags(flags, update_mask);
1037
    // cmp doesn't write the result
1038
    if (modrm_decoder->raw_reg() != 7)
1039
        write_data<uint16_t>(result & 0xffff);
1040
}
1041
 
1042
// add r/m, immediate, 8-bit, sign-extended
1043
void EmulatorPimpl::add_adc_sub_sbb_cmp_83()
1044
{
1045
    modrm_decoder->set_width(OP_WIDTH_16);
1046
    modrm_decoder->decode();
1047
 
1048
    uint16_t v1 = read_data<uint16_t>();
1049
    int16_t v2 = sign_extend<int16_t, uint8_t>(fetch_byte());
1050
    bool carry_in =
1051
        modrm_decoder->raw_reg() == 2 || modrm_decoder->raw_reg() == 3
1052
            ? !!(registers->get_flags() & CF)
1053
            : 0;
1054
 
1055
    uint16_t result;
1056
    uint16_t flags;
1057
    uint16_t update_mask = OF | SF | ZF | CF | PF | AF;
1058
    if (modrm_decoder->raw_reg() == 0 || modrm_decoder->raw_reg() == 2)
1059
        std::tie(flags, result) = do_add<uint16_t>(v1, v2, carry_in);
1060
    else if (modrm_decoder->raw_reg() == 6) {
1061
        std::tie(flags, result) = do_xor<uint16_t>(v1, v2);
1062
        flags &= ~(CF | OF);
1063
        update_mask &= ~AF;
1064
    } else if (modrm_decoder->raw_reg() == 1) {
1065
        std::tie(flags, result) = do_or<uint16_t>(v1, v2);
1066
        flags &= ~(CF | OF);
1067
        update_mask &= ~AF;
1068
    } else if (modrm_decoder->raw_reg() == 4) {
1069
        std::tie(flags, result) = do_and<uint16_t>(v1, v2);
1070
        flags &= ~(CF | OF);
1071
        update_mask &= ~AF;
1072
    } else
1073
        std::tie(flags, result) = do_sub<uint16_t>(v1, v2, carry_in);
1074
 
1075
    registers->set_flags(flags, update_mask);
1076
    // cmp doesn't write the result
1077
    if (modrm_decoder->raw_reg() != 7)
1078
        write_data<uint16_t>(result & 0xffff);
1079
}
1080
 
1081
uint8_t EmulatorPimpl::fetch_byte()
1082
{
1083
    return mem->read<uint8_t>(
1084
        get_phys_addr(registers->get(CS), registers->get(IP) + instr_length++));
1085
}
1086
 
1087
void EmulatorPimpl::neg_mul_not_test_div_f6()
1088
{
1089
    modrm_decoder->set_width(OP_WIDTH_8);
1090
    modrm_decoder->decode();
1091
 
1092
    if (modrm_decoder->raw_reg() == 0x2)
1093
        notf6();
1094
    else if (modrm_decoder->raw_reg() == 0x3)
1095
        negf6();
1096
    else if (modrm_decoder->raw_reg() == 0x4)
1097
        mulf6();
1098
    else if (modrm_decoder->raw_reg() == 0x5)
1099
        imulf6();
1100
    else if (modrm_decoder->raw_reg() == 0x0 || modrm_decoder->raw_reg() == 1)
1101
        testf6();
1102
    else if (modrm_decoder->raw_reg() == 0x6)
1103
        divf6();
1104
    else if (modrm_decoder->raw_reg() == 0x7)
1105
        idivf6();
1106
    else
1107
        std::cerr << "warning: invalid reg " << std::hex
1108
                  << (unsigned)modrm_decoder->raw_reg() << " for opcode 0x"
1109
                  << (unsigned)opcode << std::endl;
1110
}
1111
 
1112
void EmulatorPimpl::neg_mul_not_test_div_f7()
1113
{
1114
    modrm_decoder->set_width(OP_WIDTH_16);
1115
    modrm_decoder->decode();
1116
 
1117
    if (modrm_decoder->raw_reg() == 0x2)
1118
        notf7();
1119
    else if (modrm_decoder->raw_reg() == 0x3)
1120
        negf7();
1121
    else if (modrm_decoder->raw_reg() == 0x4)
1122
        mulf7();
1123
    else if (modrm_decoder->raw_reg() == 0x5)
1124
        imulf7();
1125
    else if (modrm_decoder->raw_reg() == 0x0 || modrm_decoder->raw_reg() == 1)
1126
        testf7();
1127
    else if (modrm_decoder->raw_reg() == 0x6)
1128
        divf7();
1129
    else if (modrm_decoder->raw_reg() == 0x7)
1130
        idivf7();
1131
    else
1132
        std::cerr << "warning: invalid reg " << std::hex
1133
                  << (unsigned)modrm_decoder->raw_reg() << " for opcode 0x"
1134
                  << (unsigned)opcode << std::endl;
1135
}
1136
 
1137
void EmulatorPimpl::shiftc0()
1138
{
1139
    modrm_decoder->set_width(OP_WIDTH_8);
1140
    modrm_decoder->decode();
1141
 
1142
    if (modrm_decoder->raw_reg() == 4 || modrm_decoder->raw_reg() == 6)
1143
        shlc0();
1144
    else if (modrm_decoder->raw_reg() == 5)
1145
        shrc0();
1146
    else if (modrm_decoder->raw_reg() == 7)
1147
        sarc0();
1148
    else if (modrm_decoder->raw_reg() == 0)
1149
        rolc0();
1150
    else if (modrm_decoder->raw_reg() == 2)
1151
        rclc0();
1152
    else if (modrm_decoder->raw_reg() == 3)
1153
        rcrc0();
1154
    else if (modrm_decoder->raw_reg() == 1)
1155
        rorc0();
1156
    else
1157
        std::cerr << "warning: invalid reg " << std::hex
1158
                  << (unsigned)modrm_decoder->raw_reg() << " for opcode 0x"
1159
                  << (unsigned)opcode << std::endl;
1160
}
1161
 
1162
void EmulatorPimpl::shiftc1()
1163
{
1164
    modrm_decoder->set_width(OP_WIDTH_16);
1165
    modrm_decoder->decode();
1166
 
1167
    if (modrm_decoder->raw_reg() == 4 || modrm_decoder->raw_reg() == 6)
1168
        shlc1();
1169
    else if (modrm_decoder->raw_reg() == 5)
1170
        shrc1();
1171
    else if (modrm_decoder->raw_reg() == 7)
1172
        sarc1();
1173
    else if (modrm_decoder->raw_reg() == 0)
1174
        rolc1();
1175
    else if (modrm_decoder->raw_reg() == 2)
1176
        rclc1();
1177
    else if (modrm_decoder->raw_reg() == 3)
1178
        rcrc1();
1179
    else if (modrm_decoder->raw_reg() == 1)
1180
        rorc1();
1181
    else
1182
        std::cerr << "warning: invalid reg " << std::hex
1183
                  << (unsigned)modrm_decoder->raw_reg() << " for opcode 0x"
1184
                  << (unsigned)opcode << std::endl;
1185
}
1186
 
1187
void EmulatorPimpl::shiftd0()
1188
{
1189
    modrm_decoder->set_width(OP_WIDTH_8);
1190
    modrm_decoder->decode();
1191
 
1192
    if (modrm_decoder->raw_reg() == 4 || modrm_decoder->raw_reg() == 6)
1193
        shld0();
1194
    else if (modrm_decoder->raw_reg() == 5)
1195
        shrd0();
1196
    else if (modrm_decoder->raw_reg() == 7)
1197
        sard0();
1198
    else if (modrm_decoder->raw_reg() == 0)
1199
        rold0();
1200
    else if (modrm_decoder->raw_reg() == 2)
1201
        rcld0();
1202
    else if (modrm_decoder->raw_reg() == 3)
1203
        rcrd0();
1204
    else if (modrm_decoder->raw_reg() == 1)
1205
        rord0();
1206
    else
1207
        std::cerr << "warning: invalid reg " << std::hex
1208
                  << (unsigned)modrm_decoder->raw_reg() << " for opcode 0x"
1209
                  << (unsigned)opcode << std::endl;
1210
}
1211
 
1212
void EmulatorPimpl::shiftd1()
1213
{
1214
    modrm_decoder->set_width(OP_WIDTH_16);
1215
    modrm_decoder->decode();
1216
 
1217
    if (modrm_decoder->raw_reg() == 4 || modrm_decoder->raw_reg() == 6)
1218
        shld1();
1219
    else if (modrm_decoder->raw_reg() == 5)
1220
        shrd1();
1221
    else if (modrm_decoder->raw_reg() == 7)
1222
        sard1();
1223
    else if (modrm_decoder->raw_reg() == 0)
1224
        rold1();
1225
    else if (modrm_decoder->raw_reg() == 2)
1226
        rcld1();
1227
    else if (modrm_decoder->raw_reg() == 3)
1228
        rcrd1();
1229
    else if (modrm_decoder->raw_reg() == 1)
1230
        rord1();
1231
    else
1232
        std::cerr << "warning: invalid reg " << std::hex
1233
                  << (unsigned)modrm_decoder->raw_reg() << " for opcode 0x"
1234
                  << (unsigned)opcode << std::endl;
1235
}
1236
 
1237
void EmulatorPimpl::shiftd2()
1238
{
1239
    modrm_decoder->set_width(OP_WIDTH_8);
1240
    modrm_decoder->decode();
1241
 
1242
    if (modrm_decoder->raw_reg() == 4 || modrm_decoder->raw_reg() == 6)
1243
        shld2();
1244
    else if (modrm_decoder->raw_reg() == 5)
1245
        shrd2();
1246
    else if (modrm_decoder->raw_reg() == 7)
1247
        sard2();
1248
    else if (modrm_decoder->raw_reg() == 0)
1249
        rold2();
1250
    else if (modrm_decoder->raw_reg() == 2)
1251
        rcld2();
1252
    else if (modrm_decoder->raw_reg() == 1)
1253
        rord2();
1254
    else if (modrm_decoder->raw_reg() == 3)
1255
        rcrd2();
1256
    else
1257
        std::cerr << "warning: invalid reg " << std::hex
1258
                  << (unsigned)modrm_decoder->raw_reg() << " for opcode 0x"
1259
                  << (unsigned)opcode << std::endl;
1260
}
1261
 
1262
void EmulatorPimpl::shiftd3()
1263
{
1264
    modrm_decoder->set_width(OP_WIDTH_16);
1265
    modrm_decoder->decode();
1266
 
1267
    if (modrm_decoder->raw_reg() == 4 || modrm_decoder->raw_reg() == 6)
1268
        shld3();
1269
    else if (modrm_decoder->raw_reg() == 5)
1270
        shrd3();
1271
    else if (modrm_decoder->raw_reg() == 7)
1272
        sard3();
1273
    else if (modrm_decoder->raw_reg() == 0)
1274
        rold3();
1275
    else if (modrm_decoder->raw_reg() == 2)
1276
        rcld3();
1277
    else if (modrm_decoder->raw_reg() == 1)
1278
        rord3();
1279
    else if (modrm_decoder->raw_reg() == 3)
1280
        rcrd3();
1281
    else
1282
        std::cerr << "warning: invalid reg " << std::hex
1283
                  << (unsigned)modrm_decoder->raw_reg() << " for opcode 0x"
1284
                  << (unsigned)opcode << std::endl;
1285
}
1286
 
1287
void EmulatorPimpl::invalid_opcode()
1288
{
1289
    auto flags = registers->get_flags();
1290
 
1291
    push_word(flags);
1292
    push_word(registers->get(CS));
1293
    push_word(registers->get(IP) + instr_length);
1294
 
1295
    flags &= ~(IF | TF);
1296
    registers->set_flags(flags, IF | TF);
1297
 
1298
    // int 3
1299
    auto new_cs = mem->read<uint16_t>(VEC_INVALID_OPCODE + 2);
1300
    auto new_ip = mem->read<uint16_t>(VEC_INVALID_OPCODE + 0);
1301
 
1302
    registers->set(CS, new_cs);
1303
    registers->set(IP, new_ip);
1304
    jump_taken = true;
1305
}
1306
 
1307
#include "instructions/mov.cpp"
1308
#include "instructions/push.cpp"
1309
#include "instructions/pop.cpp"
1310
#include "instructions/xchg.cpp"
1311
#include "instructions/io.cpp"
1312
#include "instructions/xlat.cpp"
1313
#include "instructions/lea.cpp"
1314
#include "instructions/lahf_sahf.cpp"
1315
#include "instructions/add.cpp"
1316
#include "instructions/xor.cpp"
1317
#include "instructions/and.cpp"
1318
#include "instructions/or.cpp"
1319
#include "instructions/adc.cpp"
1320
#include "instructions/sub.cpp"
1321
#include "instructions/sbb.cpp"
1322
#include "instructions/inc_dec.cpp"
1323
#include "instructions/aaa.cpp"
1324
#include "instructions/daa.cpp"
1325
#include "instructions/aas.cpp"
1326
#include "instructions/aam.cpp"
1327
#include "instructions/das.cpp"
1328
#include "instructions/aad.cpp"
1329
#include "instructions/neg.cpp"
1330
#include "instructions/cmp.cpp"
1331
#include "instructions/mul.cpp"
1332
#include "instructions/imul.cpp"
1333
#include "instructions/div.cpp"
1334
#include "instructions/int.cpp"
1335
#include "instructions/cbw.cpp"
1336
#include "instructions/cwd.cpp"
1337
#include "instructions/jmp.cpp"
1338
#include "instructions/call.cpp"
1339
#include "instructions/ret.cpp"
1340
#include "instructions/clc.cpp"
1341
#include "instructions/cmc.cpp"
1342
#include "instructions/stc.cpp"
1343
#include "instructions/setalc.cpp"
1344
#include "instructions/cld.cpp"
1345
#include "instructions/std.cpp"
1346
#include "instructions/cli.cpp"
1347
#include "instructions/sti.cpp"
1348
#include "instructions/loop.cpp"
1349
#include "instructions/loope.cpp"
1350
#include "instructions/loopnz.cpp"
1351
#include "instructions/scas.cpp"
1352
#include "instructions/movs.cpp"
1353
#include "instructions/cmps.cpp"
1354
#include "instructions/lods.cpp"
1355
#include "instructions/stos.cpp"
1356
#include "instructions/hlt.cpp"
1357
#include "instructions/wait.cpp"
1358
#include "instructions/esc.cpp"
1359
#include "instructions/not.cpp"
1360
#include "instructions/shl.cpp"
1361
#include "instructions/shr.cpp"
1362
#include "instructions/sar.cpp"
1363
#include "instructions/rol.cpp"
1364
#include "instructions/rcl.cpp"
1365
#include "instructions/ror.cpp"
1366
#include "instructions/rcr.cpp"
1367
#include "instructions/test.cpp"
1368
#include "instructions/bound.cpp"
1369
#include "instructions/outs.cpp"
1370
#include "instructions/ins.cpp"
1371
#include "instructions/leave.cpp"
1372
#include "instructions/enter.cpp"
1373
 
1374
void EmulatorPimpl::push_word(uint16_t v)
1375
{
1376
    registers->set(SP, registers->get(SP) - 2);
1377
    auto addr = get_phys_addr(registers->get(SS), registers->get(SP));
1378
    mem->write<uint16_t>(addr, v);
1379
}
1380
 
1381
uint16_t EmulatorPimpl::pop_word()
1382
{
1383
    auto addr = get_phys_addr(registers->get(SS), registers->get(SP));
1384
    auto v = mem->read<uint16_t>(addr);
1385
    registers->set(SP, registers->get(SP) + 2);
1386
 
1387
    return v;
1388
}
1389
 
1390
uint16_t EmulatorPimpl::fetch_16bit()
1391
{
1392
    uint16_t immed = (static_cast<uint16_t>(fetch_byte()) |
1393
                      (static_cast<uint16_t>(fetch_byte()) << 8));
1394
    return immed;
1395
}
1396
 
1397
template <typename T>
1398
void EmulatorPimpl::write_data(T val, bool stack)
1399
{
1400
    if (modrm_decoder->rm_type() == OP_REG) {
1401
        auto dest = modrm_decoder->rm_reg();
1402
        registers->set(dest, val);
1403
    } else {
1404
        auto ea = modrm_decoder->effective_address();
1405
        auto segment = get_segment(stack);
1406
        auto addr = get_phys_addr(registers->get(segment), ea);
1407
        mem->write<T>(addr, val);
1408
    }
1409
}
1410
 
1411
template <typename T>
1412
T EmulatorPimpl::read_data(bool stack)
1413
{
1414
    if (modrm_decoder->rm_type() == OP_MEM) {
1415
        auto displacement = modrm_decoder->effective_address();
1416
        auto segment = get_segment(stack);
1417
        auto addr = get_phys_addr(registers->get(segment), displacement);
1418
 
1419
        return mem->read<T>(addr);
1420
    } else {
1421
        auto source = modrm_decoder->rm_reg();
1422
        return registers->get(source);
1423
    }
1424
}
1425
 
1426
GPR EmulatorPimpl::get_segment(bool is_stack_reference)
1427
{
1428
    if (is_stack_reference)
1429
        return SS;
1430
 
1431
    if (default_segment_overriden)
1432
        return override_segment;
1433
 
1434
    return modrm_decoder->uses_bp_as_base() || is_stack_reference ? SS : DS;
1435
}
1436
 
1437
void EmulatorPimpl::set_override_segment(GPR segment)
1438
{
1439
    default_segment_overriden = true;
1440
    override_segment = segment;
1441
}
1442
 
1443
Emulator::Emulator(RegisterFile *registers, SoftwareCPU *cpu)
1444
    : pimpl(std::make_unique<EmulatorPimpl>(registers, cpu))
1445
{
1446
}
1447
 
1448
Emulator::~Emulator()
1449
{
1450
}
1451
 
1452
size_t Emulator::step()
1453
{
1454
    ++num_cycles;
1455
 
1456
    return pimpl->step();
1457
}
1458
 
1459
size_t Emulator::step_with_io(std::function<void(unsigned long)> io_callback)
1460
{
1461
    ++num_cycles;
1462
 
1463
    return pimpl->step_with_io(io_callback, num_cycles);
1464
}
1465
 
1466
void Emulator::set_memory(Memory *mem)
1467
{
1468
    pimpl->set_memory(mem);
1469
}
1470
 
1471
void Emulator::set_io(std::map<uint16_t, IOPorts *> *io)
1472
{
1473
    pimpl->set_io(io);
1474
}
1475
 
1476
bool Emulator::has_trapped() const
1477
{
1478
    return pimpl->has_trapped();
1479
}
1480
 
1481
void Emulator::reset()
1482
{
1483
    pimpl->reset();
1484
}
1485
 
1486
void Emulator::raise_nmi()
1487
{
1488
    pimpl->raise_nmi();
1489
}
1490
 
1491
void Emulator::raise_irq(int irq_num)
1492
{
1493
    pimpl->raise_irq(irq_num);
1494
}
1495
 
1496
unsigned long Emulator::cycle_count() const
1497
{
1498
    return num_cycles;
1499
}

powered by: WebSVN 2.1.0

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