tangled
alpha
login
or
join now
jcs.org
/
pce
0
fork
atom
fork of PCE focusing on macplus, supporting DaynaPort SCSI network emulation
0
fork
atom
overview
issues
pulls
pipelines
8080: Support Z80 interrupt modes
Hampa Hug
2 years ago
62a84a49
a3720df6
+189
-10
5 changed files
expand all
collapse all
unified
split
src
cpu
e8080
e8080.c
e8080.h
op_ed.c
op_z80.c
opcodes.c
+128
-1
src/cpu/e8080/e8080.c
reviewed
···
37
37
38
38
c->flags = 0;
39
39
40
40
+
c->int_val = 0;
41
41
+
c->nmi_val = 0;
42
42
+
c->int_req = 0;
43
43
+
44
44
+
c->int_cnt = 0;
45
45
+
c->int_pc = 0;
46
46
+
40
47
c->mem_rd_ext = NULL;
41
48
c->mem_wr_ext = NULL;
42
49
···
219
226
c->hook_rst = fct;
220
227
}
221
228
229
229
+
void e8080_rst (e8080_t *c, unsigned val)
230
230
+
{
231
231
+
e8080_set_clk (c, 0, 11);
232
232
+
233
233
+
e8080_set_sp (c, e8080_get_sp (c) - 2);
234
234
+
e8080_set_mem16 (c, e8080_get_sp (c), e8080_get_pc (c));
235
235
+
e8080_set_pc (c, val);
236
236
+
}
237
237
+
238
238
+
void e8080_set_int (e8080_t *c, unsigned char val)
239
239
+
{
240
240
+
c->int_val = (val != 0);
241
241
+
242
242
+
if (c->int_val && c->iff) {
243
243
+
c->int_req = 1;
244
244
+
}
245
245
+
246
246
+
}
247
247
+
222
248
unsigned char e8080_get_port8 (e8080_t *c, unsigned addr)
223
249
{
224
250
if (c->get_port8 != NULL) {
···
301
327
*val = e8080_get_sp (c);
302
328
return (0);
303
329
}
330
330
+
else if (strcmp (reg, "i") == 0) {
331
331
+
*val = e8080_get_i (c);
332
332
+
return (0);
333
333
+
}
334
334
+
else if (strcmp (reg, "icnt") == 0) {
335
335
+
*val = e8080_get_int_cnt (c);
336
336
+
return (0);
337
337
+
}
338
338
+
else if (strcmp (reg, "iff") == 0) {
339
339
+
*val = e8080_get_iff1 (c);
340
340
+
return (0);
341
341
+
}
342
342
+
else if (strcmp (reg, "iff2") == 0) {
343
343
+
*val = e8080_get_iff2 (c);
344
344
+
return (0);
345
345
+
}
346
346
+
else if (strcmp (reg, "im") == 0) {
347
347
+
*val = e8080_get_im (c);
348
348
+
return (0);
349
349
+
}
350
350
+
else if (strcmp (reg, "ipc") == 0) {
351
351
+
*val = e8080_get_int_pc (c);
352
352
+
return (0);
353
353
+
}
304
354
else if (strcmp (reg, "r") == 0) {
305
355
*val = e8080_get_r (c);
306
356
return (0);
···
375
425
e8080_set_sp (c, val);
376
426
return (0);
377
427
}
428
428
+
else if (strcmp (reg, "i") == 0) {
429
429
+
e8080_set_i (c, val);
430
430
+
return (0);
431
431
+
}
432
432
+
else if (strcmp (reg, "icnt") == 0) {
433
433
+
e8080_set_int_cnt (c, val);
434
434
+
return (0);
435
435
+
}
436
436
+
else if (strcmp (reg, "iff") == 0) {
437
437
+
e8080_set_iff1 (c, val);
438
438
+
return (0);
439
439
+
}
440
440
+
else if (strcmp (reg, "iff2") == 0) {
441
441
+
e8080_set_iff2 (c, val);
442
442
+
return (0);
443
443
+
}
444
444
+
else if (strcmp (reg, "im") == 0) {
445
445
+
e8080_set_im (c, val);
446
446
+
return (0);
447
447
+
}
448
448
+
else if (strcmp (reg, "ipc") == 0) {
449
449
+
e8080_set_int_pc (c, val);
450
450
+
return (0);
451
451
+
}
378
452
else if (strcmp (reg, "r") == 0) {
379
453
e8080_set_r (c, val);
380
454
return (0);
···
449
523
c->iff = 0;
450
524
c->iff2 = 0;
451
525
526
526
+
c->int_req = 0;
527
527
+
c->int_pc = 0;
528
528
+
c->im = 0;
529
529
+
452
530
c->halt = 0;
453
531
}
454
532
533
533
+
void e8080_interrupt (e8080_t *c)
534
534
+
{
535
535
+
unsigned addr;
536
536
+
537
537
+
e8080_inc_r (c);
538
538
+
c->inscnt += 1;
539
539
+
540
540
+
if (c->halt) {
541
541
+
c->halt = 0;
542
542
+
e8080_set_pc (c, e8080_get_pc (c) + 1);
543
543
+
}
544
544
+
545
545
+
c->int_cnt += 1;
546
546
+
c->int_pc = e8080_get_pc (c);
547
547
+
548
548
+
c->int_req = 0;
549
549
+
550
550
+
if (c->im == 1) {
551
551
+
e8080_rst (c, 0x38);
552
552
+
553
553
+
c->iff = 0;
554
554
+
c->iff2 = 0;
555
555
+
}
556
556
+
else if (c->im == 2) {
557
557
+
addr = (e8080_get_i (c) << 8) | 0xff;
558
558
+
addr = e8080_get_mem16 (c, addr);
559
559
+
560
560
+
e8080_rst (c, addr);
561
561
+
562
562
+
c->iff = 0;
563
563
+
c->iff2 = 0;
564
564
+
}
565
565
+
else {
566
566
+
fprintf (stderr, "8080: interrupt mode %u\n", c->im);
567
567
+
}
568
568
+
}
569
569
+
455
570
void e8080_execute (e8080_t *c)
456
571
{
457
572
unsigned short pc;
573
573
+
unsigned char iff;
458
574
459
575
if (c->halt) {
460
460
-
c->delay = 4;
576
576
+
if (c->int_req && c->iff) {
577
577
+
e8080_interrupt (c);
578
578
+
}
579
579
+
else {
580
580
+
c->delay += 1;
581
581
+
}
461
582
return;
462
583
}
463
584
···
475
596
}
476
597
#endif
477
598
599
599
+
iff = c->iff;
600
600
+
478
601
c->op[c->inst[0]] (c);
479
602
480
603
c->inscnt += 1;
604
604
+
605
605
+
if (c->int_req && iff && c->iff) {
606
606
+
e8080_interrupt (c);
607
607
+
}
481
608
}
482
609
483
610
void e8080_clock (e8080_t *c, unsigned n)
+27
src/cpu/e8080/e8080.h
reviewed
···
64
64
unsigned char iff;
65
65
unsigned char iff2;
66
66
67
67
+
unsigned char im;
68
68
+
67
69
unsigned char halt;
70
70
+
71
71
+
unsigned char int_val;
72
72
+
unsigned char nmi_val;
73
73
+
unsigned char int_req;
74
74
+
75
75
+
unsigned int_cnt;
76
76
+
unsigned short int_pc;
68
77
69
78
void *mem_rd_ext;
70
79
void *mem_wr_ext;
···
128
137
#define e8080_get_l2(c) ((c)->reg2[5]);
129
138
#define e8080_get_psw2(c) ((c)->psw2)
130
139
140
140
+
#define e8080_get_halt(c) ((c)->halt)
141
141
+
#define e8080_get_iff1(c) ((c)->iff)
142
142
+
#define e8080_get_iff2(c) ((c)->iff2)
143
143
+
#define e8080_get_im(c) ((c)->im)
144
144
+
#define e8080_get_int_cnt(c) ((c)->int_cnt)
145
145
+
#define e8080_get_int_pc(c) ((c)->int_pc)
146
146
+
131
147
#define e8080_set_a(c, v) do { (c)->reg[7] = (v) & 0xff; } while (0)
132
148
#define e8080_set_b(c, v) do { (c)->reg[0] = (v) & 0xff; } while (0)
133
149
#define e8080_set_c(c, v) do { (c)->reg[1] = (v) & 0xff; } while (0)
···
159
175
#define e8080_set_h2(c, v) do { (c)->reg2[4] = (v) & 0xff; } while (0)
160
176
#define e8080_set_l2(c, v) do { (c)->reg2[5] = (v) & 0xff; } while (0)
161
177
#define e8080_set_psw2(c, v) do { (c)->psw2 = (v) & 0xff; } while (0)
178
178
+
179
179
+
#define e8080_set_halt(c, v) do { (c)->halt = ((v) != 0); } while (0)
180
180
+
#define e8080_set_iff1(c, v) do { (c)->iff = ((v) != 0); } while (0)
181
181
+
#define e8080_set_iff2(c, v) do { (c)->iff2 = ((v) != 0); } while (0)
182
182
+
#define e8080_set_im(c, v) do { (c)->im = (v); } while (0)
183
183
+
#define e8080_set_int_cnt(c, v) do { (c)->int_cnt = (v); } while (0)
184
184
+
#define e8080_set_int_pc(c, v) do { (c)->int_pc = (v) & 0xffff; } while (0)
162
185
163
186
#define e8080_get_cf(c) (((c)->psw & E8080_FLG_C) != 0)
164
187
#define e8080_get_nf(c) (((c)->psw & E8080_FLG_N) != 0)
···
285
308
void e8080_set_hook_all_fct (e8080_t *c, void *ext, void *fct);
286
309
void e8080_set_hook_undef_fct (e8080_t *c, void *ext, void *fct);
287
310
void e8080_set_hook_rst_fct (e8080_t *c, void *ext, void *fct);
311
311
+
312
312
+
void e8080_rst (e8080_t *c, unsigned val);
313
313
+
314
314
+
void e8080_set_int (e8080_t *c, unsigned char val);
288
315
289
316
unsigned char e8080_get_port8 (e8080_t *c, unsigned addr);
290
317
void e8080_set_port8 (e8080_t *c, unsigned addr, unsigned char val);
+28
-3
src/cpu/e8080/op_ed.c
reviewed
···
99
99
/* OP ED 45: RETN */
100
100
static void op_ed_45 (e8080_t *c)
101
101
{
102
102
+
e8080_set_iff1 (c, e8080_get_iff2 (c));
102
103
e8080_set_pc (c, e8080_get_mem16 (c, e8080_get_sp (c)));
103
104
e8080_set_sp (c, e8080_get_sp (c) + 2);
104
105
e8080_set_clk (c, 0, 14);
106
106
+
}
107
107
+
108
108
+
/* OP ED 46: IM 0 */
109
109
+
static void op_ed_46 (e8080_t *c)
110
110
+
{
111
111
+
c->im = 0;
112
112
+
113
113
+
e8080_set_clk (c, 2, 8);
105
114
}
106
115
107
116
/* OP ED 47: LD I, A */
···
174
183
e8080_set_clk (c, 4, 20);
175
184
}
176
185
186
186
+
/* OP ED 56: IM 1 */
187
187
+
static void op_ed_56 (e8080_t *c)
188
188
+
{
189
189
+
c->im = 1;
190
190
+
191
191
+
e8080_set_clk (c, 2, 8);
192
192
+
}
193
193
+
177
194
/* OP ED 57: LD A, I */
178
195
static void op_ed_57 (e8080_t *c)
179
196
{
···
208
225
adr = e8080_uint16 (c->inst[2], c->inst[3]);
209
226
e8080_set_de (c, e8080_get_mem16 (c, adr));
210
227
e8080_set_clk (c, 4, 20);
228
228
+
}
229
229
+
230
230
+
/* OP ED 5E: IM 2 */
231
231
+
static void op_ed_5e (e8080_t *c)
232
232
+
{
233
233
+
c->im = 2;
234
234
+
235
235
+
e8080_set_clk (c, 2, 8);
211
236
}
212
237
213
238
/* OP ED 5F: LD A, R */
···
682
707
op_ed_ud, op_ed_ud, op_ed_ud, op_ed_ud, op_ed_ud, op_ed_ud, op_ed_ud, op_ed_ud,
683
708
op_ed_ud, op_ed_ud, op_ed_ud, op_ed_ud, op_ed_ud, op_ed_ud, op_ed_ud, op_ed_ud, /* 30 */
684
709
op_ed_ud, op_ed_ud, op_ed_ud, op_ed_ud, op_ed_ud, op_ed_ud, op_ed_ud, op_ed_ud,
685
685
-
op_ed_40, op_ed_41, op_ed_42, op_ed_43, op_ed_44, op_ed_45, op_ed_ud, op_ed_47, /* 40 */
710
710
+
op_ed_40, op_ed_41, op_ed_42, op_ed_43, op_ed_44, op_ed_45, op_ed_46, op_ed_47, /* 40 */
686
711
op_ed_40, op_ed_41, op_ed_4a, op_ed_4b, op_ed_ud, op_ed_4d, op_ed_ud, op_ed_4f,
687
687
-
op_ed_40, op_ed_41, op_ed_52, op_ed_53, op_ed_ud, op_ed_45, op_ed_ud, op_ed_57, /* 50 */
688
688
-
op_ed_40, op_ed_41, op_ed_5a, op_ed_5b, op_ed_ud, op_ed_45, op_ed_ud, op_ed_5f,
712
712
+
op_ed_40, op_ed_41, op_ed_52, op_ed_53, op_ed_ud, op_ed_45, op_ed_56, op_ed_57, /* 50 */
713
713
+
op_ed_40, op_ed_41, op_ed_5a, op_ed_5b, op_ed_ud, op_ed_45, op_ed_5e, op_ed_5f,
689
714
op_ed_40, op_ed_41, op_ed_62, op_ed_63, op_ed_ud, op_ed_45, op_ed_ud, op_ed_67, /* 60 */
690
715
op_ed_40, op_ed_41, op_ed_6a, op_ed_6b, op_ed_ud, op_ed_45, op_ed_ud, op_ed_6f,
691
716
op_ed_70, op_ed_71, op_ed_72, op_ed_73, op_ed_ud, op_ed_45, op_ed_ud, op_ed_ud, /* 70 */
+1
-1
src/cpu/e8080/op_z80.c
reviewed
···
530
530
static void op_76 (e8080_t *c)
531
531
{
532
532
c->halt = 1;
533
533
-
e8080_set_clk (c, 1, 7);
533
533
+
e8080_set_clk (c, 0, 7);
534
534
}
535
535
536
536
/* OP 80: ADD A, r */
+5
-5
src/cpu/e8080/opcodes.c
reviewed
···
571
571
static void op_76 (e8080_t *c)
572
572
{
573
573
c->halt = 1;
574
574
-
e8080_set_clk (c, 1, 7);
574
574
+
e8080_set_clk (c, 0, 7);
575
575
}
576
576
577
577
/* OP 80: ADD R */
···
1296
1296
/* OP F3: DI */
1297
1297
static void op_f3 (e8080_t *c)
1298
1298
{
1299
1299
-
c->iff = 0;
1300
1300
-
c->iff2 = 0;
1299
1299
+
e8080_set_iff1 (c, 0);
1300
1300
+
e8080_set_iff2 (c, 0);
1301
1301
e8080_set_clk (c, 1, 4);
1302
1302
}
1303
1303
···
1376
1376
/* OP FB: EI */
1377
1377
static void op_fb (e8080_t *c)
1378
1378
{
1379
1379
-
c->iff = 1;
1380
1380
-
c->iff2 = 1;
1379
1379
+
e8080_set_iff1 (c, 1);
1380
1380
+
e8080_set_iff2 (c, 1);
1381
1381
e8080_set_clk (c, 1, 4);
1382
1382
}
1383
1383