Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
alexbevi
GitHub Repository: alexbevi/BizHawk
Path: blob/master/libsnes/bsnes/snes/smp/core/opcodes.cpp
2 views
1
#ifdef SMPCORE_CPP
2
#define call (this->*op)
3
4
template<uint8 (SMPcore::*op)(uint8)>
5
void SMPcore::op_adjust(uint8 &r) {
6
op_io();
7
r = call(r);
8
}
9
10
template<uint8 (SMPcore::*op)(uint8)>
11
void SMPcore::op_adjust_addr() {
12
dp.l = op_readpc();
13
dp.h = op_readpc();
14
rd = op_read(dp);
15
rd = call(rd);
16
op_write(dp, rd);
17
}
18
19
template<uint8 (SMPcore::*op)(uint8)>
20
void SMPcore::op_adjust_dp() {
21
dp = op_readpc();
22
rd = op_readdp(dp);
23
rd = call(rd);
24
op_writedp(dp, rd);
25
}
26
27
void SMPcore::op_adjust_dpw(signed n) {
28
dp = op_readpc();
29
rd.w = op_readdp(dp) + n;
30
op_writedp(dp++, rd.l);
31
rd.h += op_readdp(dp);
32
op_writedp(dp++, rd.h);
33
regs.p.n = rd & 0x8000;
34
regs.p.z = rd == 0;
35
}
36
37
template<uint8 (SMPcore::*op)(uint8)>
38
void SMPcore::op_adjust_dpx() {
39
dp = op_readpc();
40
op_io();
41
rd = op_readdp(dp + regs.x);
42
rd = call(rd);
43
op_writedp(dp + regs.x, rd);
44
}
45
46
void SMPcore::op_branch(bool condition) {
47
rd = op_readpc();
48
if(condition == false) return;
49
op_io();
50
op_io();
51
regs.pc += (int8)rd;
52
}
53
54
void SMPcore::op_branch_bit() {
55
dp = op_readpc();
56
sp = op_readdp(dp);
57
rd = op_readpc();
58
op_io();
59
if((bool)(sp & (1 << (opcode >> 5))) == (bool)(opcode & 0x10)) return;
60
op_io();
61
op_io();
62
regs.pc += (int8)rd;
63
}
64
65
void SMPcore::op_pull(uint8 &r) {
66
op_io();
67
op_io();
68
r = op_readsp();
69
}
70
71
void SMPcore::op_push(uint8 r) {
72
op_io();
73
op_io();
74
op_writesp(r);
75
}
76
77
template<uint8 (SMPcore::*op)(uint8, uint8)>
78
void SMPcore::op_read_addr(uint8 &r) {
79
dp.l = op_readpc();
80
dp.h = op_readpc();
81
rd = op_read(dp);
82
r = call(r, rd);
83
}
84
85
template<uint8 (SMPcore::*op)(uint8, uint8)>
86
void SMPcore::op_read_addri(uint8 &r) {
87
dp.l = op_readpc();
88
dp.h = op_readpc();
89
op_io();
90
rd = op_read(dp + r);
91
regs.a = call(regs.a, rd);
92
}
93
94
template<uint8 (SMPcore::*op)(uint8, uint8)>
95
void SMPcore::op_read_const(uint8 &r) {
96
rd = op_readpc();
97
r = call(r, rd);
98
}
99
100
template<uint8 (SMPcore::*op)(uint8, uint8)>
101
void SMPcore::op_read_dp(uint8 &r) {
102
dp = op_readpc();
103
rd = op_readdp(dp);
104
r = call(r, rd);
105
}
106
107
template<uint8 (SMPcore::*op)(uint8, uint8)>
108
void SMPcore::op_read_dpi(uint8 &r, uint8 &i) {
109
dp = op_readpc();
110
op_io();
111
rd = op_readdp(dp + i);
112
r = call(r, rd);
113
}
114
115
template<uint16 (SMPcore::*op)(uint16, uint16)>
116
void SMPcore::op_read_dpw() {
117
dp = op_readpc();
118
rd.l = op_readdp(dp++);
119
if(op != &SMPcore::op_cpw) op_io();
120
rd.h = op_readdp(dp++);
121
regs.ya = call(regs.ya, rd);
122
}
123
124
template<uint8 (SMPcore::*op)(uint8, uint8)>
125
void SMPcore::op_read_idpx() {
126
dp = op_readpc() + regs.x;
127
op_io();
128
sp.l = op_readdp(dp++);
129
sp.h = op_readdp(dp++);
130
rd = op_read(sp);
131
regs.a = call(regs.a, rd);
132
}
133
134
template<uint8 (SMPcore::*op)(uint8, uint8)>
135
void SMPcore::op_read_idpy() {
136
dp = op_readpc();
137
op_io();
138
sp.l = op_readdp(dp++);
139
sp.h = op_readdp(dp++);
140
rd = op_read(sp + regs.y);
141
regs.a = call(regs.a, rd);
142
}
143
144
template<uint8 (SMPcore::*op)(uint8, uint8)>
145
void SMPcore::op_read_ix() {
146
op_io();
147
rd = op_readdp(regs.x);
148
regs.a = call(regs.a, rd);
149
}
150
151
void SMPcore::op_set_addr_bit() {
152
dp.l = op_readpc();
153
dp.h = op_readpc();
154
bit = dp >> 13;
155
dp &= 0x1fff;
156
rd = op_read(dp);
157
switch(opcode >> 5) {
158
case 0: //orc addr:bit
159
case 1: //orc !addr:bit
160
op_io();
161
regs.p.c |= (rd & (1 << bit)) ^ (bool)(opcode & 0x20);
162
break;
163
case 2: //and addr:bit
164
case 3: //and !addr:bit
165
regs.p.c &= (rd & (1 << bit)) ^ (bool)(opcode & 0x20);
166
break;
167
case 4: //eor addr:bit
168
op_io();
169
regs.p.c ^= (bool)(rd & (1 << bit));
170
break;
171
case 5: //ldc addr:bit
172
regs.p.c = (rd & (1 << bit));
173
break;
174
case 6: //stc addr:bit
175
op_io();
176
rd = (rd & ~(1 << bit)) | (regs.p.c << bit);
177
op_write(dp, rd);
178
break;
179
case 7: //not addr:bit
180
rd ^= 1 << bit;
181
op_write(dp, rd);
182
break;
183
}
184
}
185
186
void SMPcore::op_set_bit() {
187
dp = op_readpc();
188
rd = op_readdp(dp) & ~(1 << (opcode >> 5));
189
op_writedp(dp, rd | (!(opcode & 0x10) << (opcode >> 5)));
190
}
191
192
void SMPcore::op_set_flag(bool &flag, bool data) {
193
op_io();
194
if(&flag == &regs.p.i) op_io();
195
flag = data;
196
}
197
198
void SMPcore::op_test_addr(bool set) {
199
dp.l = op_readpc();
200
dp.h = op_readpc();
201
rd = op_read(dp);
202
regs.p.n = (regs.a - rd) & 0x80;
203
regs.p.z = (regs.a - rd) == 0;
204
op_read(dp);
205
op_write(dp, set ? rd | regs.a : rd & ~regs.a);
206
}
207
208
void SMPcore::op_transfer(uint8 &from, uint8 &to) {
209
op_io();
210
to = from;
211
if(&to == &regs.s) return;
212
regs.p.n = (to & 0x80);
213
regs.p.z = (to == 0);
214
}
215
216
void SMPcore::op_write_addr(uint8 &r) {
217
dp.l = op_readpc();
218
dp.h = op_readpc();
219
op_read(dp);
220
op_write(dp, r);
221
}
222
223
void SMPcore::op_write_addri(uint8 &i) {
224
dp.l = op_readpc();
225
dp.h = op_readpc();
226
op_io();
227
dp += i;
228
op_read(dp);
229
op_write(dp, regs.a);
230
}
231
232
void SMPcore::op_write_dp(uint8 &r) {
233
dp = op_readpc();
234
op_readdp(dp);
235
op_writedp(dp, r);
236
}
237
238
void SMPcore::op_write_dpi(uint8 &r, uint8 &i) {
239
dp = op_readpc() + i;
240
op_io();
241
op_readdp(dp);
242
op_writedp(dp, r);
243
}
244
245
template<uint8 (SMPcore::*op)(uint8, uint8)>
246
void SMPcore::op_write_dp_const() {
247
rd = op_readpc();
248
dp = op_readpc();
249
wr = op_readdp(dp);
250
wr = call(wr, rd);
251
op != &SMPcore::op_cmp ? op_writedp(dp, wr) : op_io();
252
}
253
254
template<uint8 (SMPcore::*op)(uint8, uint8)>
255
void SMPcore::op_write_dp_dp() {
256
sp = op_readpc();
257
rd = op_readdp(sp);
258
dp = op_readpc();
259
if(op != &SMPcore::op_st) wr = op_readdp(dp);
260
wr = call(wr, rd);
261
op != &SMPcore::op_cmp ? op_writedp(dp, wr) : op_io();
262
}
263
264
template<uint8 (SMPcore::*op)(uint8, uint8)>
265
void SMPcore::op_write_ix_iy() {
266
op_io();
267
rd = op_readdp(regs.y);
268
wr = op_readdp(regs.x);
269
wr = call(wr, rd);
270
op != &SMPcore::op_cmp ? op_writedp(regs.x, wr) : op_io();
271
}
272
273
//
274
275
void SMPcore::op_bne_dp() {
276
dp = op_readpc();
277
sp = op_readdp(dp);
278
rd = op_readpc();
279
op_io();
280
if(regs.a == sp) return;
281
op_io();
282
op_io();
283
regs.pc += (int8)rd;
284
}
285
286
void SMPcore::op_bne_dpdec() {
287
dp = op_readpc();
288
wr = op_readdp(dp);
289
op_writedp(dp, --wr);
290
rd = op_readpc();
291
if(wr == 0) return;
292
op_io();
293
op_io();
294
regs.pc += (int8)rd;
295
}
296
297
void SMPcore::op_bne_dpx() {
298
dp = op_readpc();
299
op_io();
300
sp = op_readdp(dp + regs.x);
301
rd = op_readpc();
302
op_io();
303
if(regs.a == sp) return;
304
op_io();
305
op_io();
306
regs.pc += (int8)rd;
307
}
308
309
void SMPcore::op_bne_ydec() {
310
rd = op_readpc();
311
op_io();
312
op_io();
313
if(--regs.y == 0) return;
314
op_io();
315
op_io();
316
regs.pc += (int8)rd;
317
}
318
319
void SMPcore::op_brk() {
320
rd.l = op_read(0xffde);
321
rd.h = op_read(0xffdf);
322
op_io();
323
op_io();
324
op_writesp(regs.pc.h);
325
op_writesp(regs.pc.l);
326
op_writesp(regs.p);
327
regs.pc = rd;
328
regs.p.b = 1;
329
regs.p.i = 0;
330
}
331
332
void SMPcore::op_clv() {
333
op_io();
334
regs.p.v = 0;
335
regs.p.h = 0;
336
}
337
338
void SMPcore::op_cmc() {
339
op_io();
340
op_io();
341
regs.p.c = !regs.p.c;
342
}
343
344
void SMPcore::op_daa() {
345
op_io();
346
op_io();
347
if(regs.p.c || (regs.a) > 0x99) {
348
regs.a += 0x60;
349
regs.p.c = 1;
350
}
351
if(regs.p.h || (regs.a & 15) > 0x09) {
352
regs.a += 0x06;
353
}
354
regs.p.n = (regs.a & 0x80);
355
regs.p.z = (regs.a == 0);
356
}
357
358
void SMPcore::op_das() {
359
op_io();
360
op_io();
361
if(!regs.p.c || (regs.a) > 0x99) {
362
regs.a -= 0x60;
363
regs.p.c = 0;
364
}
365
if(!regs.p.h || (regs.a & 15) > 0x09) {
366
regs.a -= 0x06;
367
}
368
regs.p.n = (regs.a & 0x80);
369
regs.p.z = (regs.a == 0);
370
}
371
372
void SMPcore::op_div_ya_x() {
373
op_io();
374
op_io();
375
op_io();
376
op_io();
377
op_io();
378
op_io();
379
op_io();
380
op_io();
381
op_io();
382
op_io();
383
op_io();
384
ya = regs.ya;
385
//overflow set if quotient >= 256
386
regs.p.v = (regs.y >= regs.x);
387
regs.p.h = ((regs.y & 15) >= (regs.x & 15));
388
if(regs.y < (regs.x << 1)) {
389
//if quotient is <= 511 (will fit into 9-bit result)
390
regs.a = ya / regs.x;
391
regs.y = ya % regs.x;
392
} else {
393
//otherwise, the quotient won't fit into regs.p.v + regs.a
394
//this emulates the odd behavior of the S-SMP in this case
395
regs.a = 255 - (ya - (regs.x << 9)) / (256 - regs.x);
396
regs.y = regs.x + (ya - (regs.x << 9)) % (256 - regs.x);
397
}
398
//result is set based on a (quotient) only
399
regs.p.n = (regs.a & 0x80);
400
regs.p.z = (regs.a == 0);
401
}
402
403
void SMPcore::op_jmp_addr() {
404
rd.l = op_readpc();
405
rd.h = op_readpc();
406
regs.pc = rd;
407
}
408
409
void SMPcore::op_jmp_iaddrx() {
410
dp.l = op_readpc();
411
dp.h = op_readpc();
412
op_io();
413
dp += regs.x;
414
rd.l = op_read(dp++);
415
rd.h = op_read(dp++);
416
regs.pc = rd;
417
}
418
419
void SMPcore::op_jsp_dp() {
420
rd = op_readpc();
421
op_io();
422
op_io();
423
op_writesp(regs.pc.h);
424
op_writesp(regs.pc.l);
425
regs.pc = 0xff00 | rd;
426
}
427
428
void SMPcore::op_jsr_addr() {
429
rd.l = op_readpc();
430
rd.h = op_readpc();
431
op_io();
432
op_io();
433
op_io();
434
op_writesp(regs.pc.h);
435
op_writesp(regs.pc.l);
436
regs.pc = rd;
437
}
438
439
void SMPcore::op_jst() {
440
dp = 0xffde - ((opcode >> 4) << 1);
441
rd.l = op_read(dp++);
442
rd.h = op_read(dp++);
443
op_io();
444
op_io();
445
op_io();
446
op_writesp(regs.pc.h);
447
op_writesp(regs.pc.l);
448
regs.pc = rd;
449
}
450
451
void SMPcore::op_lda_ixinc() {
452
op_io();
453
regs.a = op_readdp(regs.x++);
454
op_io();
455
regs.p.n = regs.a & 0x80;
456
regs.p.z = regs.a == 0;
457
}
458
459
void SMPcore::op_mul_ya() {
460
op_io();
461
op_io();
462
op_io();
463
op_io();
464
op_io();
465
op_io();
466
op_io();
467
op_io();
468
ya = regs.y * regs.a;
469
regs.a = ya;
470
regs.y = ya >> 8;
471
//result is set based on y (high-byte) only
472
regs.p.n = (regs.y & 0x80);
473
regs.p.z = (regs.y == 0);
474
}
475
476
void SMPcore::op_nop() {
477
op_io();
478
}
479
480
void SMPcore::op_plp() {
481
op_io();
482
op_io();
483
regs.p = op_readsp();
484
}
485
486
void SMPcore::op_rti() {
487
regs.p = op_readsp();
488
rd.l = op_readsp();
489
rd.h = op_readsp();
490
op_io();
491
op_io();
492
regs.pc = rd;
493
}
494
495
void SMPcore::op_rts() {
496
rd.l = op_readsp();
497
rd.h = op_readsp();
498
op_io();
499
op_io();
500
regs.pc = rd;
501
}
502
503
void SMPcore::op_sta_idpx() {
504
sp = op_readpc() + regs.x;
505
op_io();
506
dp.l = op_readdp(sp++);
507
dp.h = op_readdp(sp++);
508
op_read(dp);
509
op_write(dp, regs.a);
510
}
511
512
void SMPcore::op_sta_idpy() {
513
sp = op_readpc();
514
dp.l = op_readdp(sp++);
515
dp.h = op_readdp(sp++);
516
op_io();
517
dp += regs.y;
518
op_read(dp);
519
op_write(dp, regs.a);
520
}
521
522
void SMPcore::op_sta_ix() {
523
op_io();
524
op_readdp(regs.x);
525
op_writedp(regs.x, regs.a);
526
}
527
528
void SMPcore::op_sta_ixinc() {
529
op_io();
530
op_io();
531
op_writedp(regs.x++, regs.a);
532
}
533
534
void SMPcore::op_stw_dp() {
535
dp = op_readpc();
536
op_readdp(dp);
537
op_writedp(dp++, regs.a);
538
op_writedp(dp++, regs.y);
539
}
540
541
void SMPcore::op_wait() {
542
while(true) {
543
if(scheduler.sync == Scheduler::SynchronizeMode::All) {
544
regs.pc--; // repeat this opcode on next run
545
scheduler.exit(Scheduler::ExitReason::SynchronizeEvent);
546
}
547
op_io();
548
op_io();
549
}
550
}
551
552
void SMPcore::op_xcn() {
553
op_io();
554
op_io();
555
op_io();
556
op_io();
557
regs.a = (regs.a >> 4) | (regs.a << 4);
558
regs.p.n = regs.a & 0x80;
559
regs.p.z = regs.a == 0;
560
}
561
562
#undef call
563
#endif
564
565