Browse code

Update snes9x code from 1.53 to 1.6.0.

Notable differences from upstream:
* Did not use the same #include setup for the new byuu apu and instead chose to do things more traditionally, as the latter is also much easier to deal with in Visual Studio than just including .cpp files into other .cpp files...
* MSU1 support not included (I see no need for this in a plugin meant to be used for original SNES music).
* The dynamic rate control on the APU not included (I also see no need for it in this plugin).
* The extra resamplers I added in were removed as the original hermite resampler was folded into a single non-inhertiable resampler.
* Bits of cleanup.

Naram Qashat authored on 2021/04/19 21:20:36
Showing 1 changed files
1 1
deleted file mode 100644
... ...
@@ -1,1173 +0,0 @@
1
-// snes_spc 0.9.0. http://www.slack.net/~ant/
2
-
3
-/* Copyright (C) 2004-2007 Shay Green. This module is free software; you
4
-can redistribute it and/or modify it under the terms of the GNU Lesser
5
-General Public License as published by the Free Software Foundation; either
6
-version 2.1 of the License, or (at your option) any later version. This
7
-module is distributed in the hope that it will be useful, but WITHOUT ANY
8
-WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
9
-FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
10
-details. You should have received a copy of the GNU Lesser General Public
11
-License along with this module; if not, write to the Free Software Foundation,
12
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
13
-
14
-#pragma once
15
-
16
-//// Memory access
17
-
18
-// TODO: remove non-wrapping versions?
19
-#define SPC_NO_SP_WRAPAROUND 0
20
-
21
-unsigned SNES_SPC::CPU_mem_bit(const uint8_t *pc, rel_time_t rel_time)
22
-{
23
-	unsigned addr = get_le16(pc);
24
-	unsigned t = this->cpu_read(addr & 0x1FFF, rel_time) >> (addr >> 13);
25
-	return (t << 8) & 0x100;
26
-}
27
-
28
-//// Status flag handling
29
-
30
-// Hex value in name to clarify code and bit shifting.
31
-// Flag stored in indicated variable during emulation
32
-const int n80 = 0x80; // nz
33
-const int v40 = 0x40; // psw
34
-const int p20 = 0x20; // dp
35
-const int b10 = 0x10; // psw
36
-const int h08 = 0x08; // psw
37
-const int i04 = 0x04; // psw
38
-const int z02 = 0x02; // nz
39
-const int c01 = 0x01; // c
40
-
41
-const int nz_neg_mask = 0x880; // either bit set indicates N flag set
42
-
43
-uint8_t *SNES_SPC::run_until_(time_t end_time)
44
-{
45
-	rel_time_t rel_time = this->m.spc_time - end_time;
46
-	/*assert( rel_time <= 0 );*/
47
-	this->m.spc_time = end_time;
48
-	this->m.dsp_time += rel_time;
49
-	this->m.timers[0].next_time += rel_time;
50
-	this->m.timers[1].next_time += rel_time;
51
-	this->m.timers[2].next_time += rel_time;
52
-
53
-	auto ram = this->m.ram.ram;
54
-	int a = this->m.cpu_regs.a;
55
-	int x = this->m.cpu_regs.x;
56
-	int y = this->m.cpu_regs.y;
57
-	const uint8_t *pc;
58
-	uint8_t *sp;
59
-	int psw;
60
-	int c;
61
-	int nz;
62
-	int dp;
63
-
64
-	// timers are by far the most common thing read from dp
65
-	auto CPU_READ_TIMER = [&](rel_time_t offset, int addr_) -> int
66
-	{
67
-		int out;
68
-		rel_time_t adj_time = rel_time + offset;
69
-		int dp_addr = addr_;
70
-		int ti = dp_addr - (r_t0out + 0xF0);
71
-		if (static_cast<unsigned>(ti) < timer_count)
72
-		{
73
-			auto t = &this->m.timers[ti];
74
-			if (adj_time >= t->next_time)
75
-				t = this->run_timer_(t, adj_time);
76
-			out = t->counter;
77
-			t->counter = 0;
78
-		}
79
-		else
80
-		{
81
-			out = ram[dp_addr];
82
-			int i = dp_addr - 0xF0;
83
-			if (static_cast<unsigned>(i) < 0x10)
84
-				out = this->cpu_read_smp_reg(i, adj_time);
85
-		}
86
-		return out;
87
-	};
88
-
89
-	auto DP_ADDR = [&](int addr) { return dp + addr; };
90
-
91
-	auto READ_PROG16 = [&](int addr) { return get_le16(ram + addr); };
92
-
93
-	auto SET_PC = [&](int n) { pc = ram + n; };
94
-	auto GET_PC = [&]() { return pc - ram; };
95
-
96
-	auto SET_SP = [&](int v) { sp = ram + 0x101 + v; };
97
-	auto GET_SP = [&]() { return sp - 0x101 - ram; };
98
-
99
-	auto PUSH16 = [&](int data)
100
-	{
101
-		sp -= 2;
102
-#if !SPC_NO_SP_WRAPAROUND
103
-		int addr = sp - ram;
104
-		if (addr > 0x100)
105
-#endif
106
-			set_le16(sp, data);
107
-#if !SPC_NO_SP_WRAPAROUND
108
-		else
109
-		{
110
-			ram[static_cast<uint8_t>(addr) + 0x100] = static_cast<uint8_t>(data);
111
-			sp[1] = static_cast<uint8_t>(data >> 8);
112
-			sp += 0x100;
113
-		}
114
-#endif
115
-	};
116
-	auto PUSH = [&](int data)
117
-	{
118
-		*--sp = static_cast<uint8_t>(data);
119
-#if !SPC_NO_SP_WRAPAROUND
120
-		if (sp - ram == 0x100)
121
-			sp += 0x100;
122
-#endif
123
-	};
124
-	auto POP = [&](int &out)
125
-	{
126
-		out = *sp++;
127
-#if !SPC_NO_SP_WRAPAROUND
128
-		if (sp - ram == 0x201)
129
-		{
130
-			out = sp[-0x101];
131
-			sp -= 0x100;
132
-		}
133
-#endif
134
-	};
135
-
136
-	auto MEM_BIT = [&](rel_time_t rel) { return this->CPU_mem_bit(pc, rel_time + rel); };
137
-
138
-	auto GET_PSW = [&](int &out)
139
-	{
140
-		out = psw & ~(n80 | p20 | z02 | c01);
141
-		out |= (c >> 8) & c01;
142
-		out |= (dp >> 3) & p20;
143
-		out |= ((nz >> 4) | nz) & n80;
144
-		if (!static_cast<uint8_t>(nz))
145
-			out |= z02;
146
-	};
147
-	auto SET_PSW = [&](int in)
148
-	{
149
-		psw = in;
150
-		c = in << 8;
151
-		dp = (in << 3) & 0x100;
152
-		nz = ((in << 4) & 0x800) | (~in & z02);
153
-	};
154
-
155
-	SET_PC(this->m.cpu_regs.pc);
156
-	SET_SP(this->m.cpu_regs.sp);
157
-	SET_PSW(this->m.cpu_regs.psw);
158
-
159
-	goto loop;
160
-
161
-	// Main loop
162
-
163
-cbranch_taken_loop:
164
-	pc += *reinterpret_cast<const int8_t *>(pc);
165
-inc_pc_loop:
166
-	++pc;
167
-loop:
168
-	unsigned data;
169
-
170
-	unsigned opcode = *pc;
171
-	if (this->allow_time_overflow && rel_time >= 0)
172
-		goto stop;
173
-	if ((rel_time += this->m.cycle_table[opcode]) > 0 && !this->allow_time_overflow)
174
-		goto out_of_time;
175
-
176
-#ifdef SPC_CPU_OPCODE_HOOK
177
-	SPC_CPU_OPCODE_HOOK(GET_PC(), opcode);
178
-#endif
179
-
180
-	// TODO: if PC is at end of memory, this will get wrong operand (very obscure)
181
-	data = *++pc;
182
-	switch (opcode)
183
-	{
184
-		// Common instructions
185
-
186
-#define BRANCH(cond) \
187
-{ \
188
-	++pc; \
189
-	pc += static_cast<int8_t>(data); \
190
-	if (cond) \
191
-		goto loop; \
192
-	pc -= static_cast<int8_t>(data); \
193
-	rel_time -= 2; \
194
-	goto loop; \
195
-}
196
-
197
-		case 0xF0: // BEQ
198
-			BRANCH(!static_cast<uint8_t>(nz)) // 89% taken
199
-
200
-		case 0xD0: // BNE
201
-			BRANCH(static_cast<uint8_t>(nz))
202
-
203
-		case 0x3F: // CALL
204
-		{
205
-			int old_addr = GET_PC() + 2;
206
-			SET_PC(get_le16(pc));
207
-			PUSH16(old_addr);
208
-			goto loop;
209
-		}
210
-
211
-		case 0x6F:// RET
212
-#if SPC_NO_SP_WRAPAROUND
213
-			SET_PC(get_le16(sp));
214
-			sp += 2;
215
-#else
216
-			{
217
-				int addr = sp - ram;
218
-				SET_PC(get_le16(sp));
219
-				sp += 2;
220
-				if (addr < 0x1FF)
221
-					goto loop;
222
-
223
-				SET_PC(sp[-0x101] * 0x100 + ram[static_cast<uint8_t>(addr) + 0x100]);
224
-				sp -= 0x100;
225
-			}
226
-#endif
227
-			goto loop;
228
-
229
-		case 0xE4: // MOV a,dp
230
-			++pc;
231
-			// 80% from timer
232
-			a = nz = CPU_READ_TIMER(0, DP_ADDR(data));
233
-			goto loop;
234
-
235
-		case 0xFA: // MOV dp,dp
236
-		{
237
-			int temp = CPU_READ_TIMER(-2, DP_ADDR(data));
238
-			data = temp + no_read_before_write;
239
-		}
240
-		// fall through
241
-		case 0x8F: // MOV dp,#imm
242
-		{
243
-			int temp = *(pc + 1);
244
-			pc += 2;
245
-			{
246
-				int i = dp + temp;
247
-				ram[i] = static_cast<uint8_t>(data);
248
-				i -= 0xF0;
249
-				if (static_cast<unsigned>(i) < 0x10) // 76%
250
-				{
251
-					this->m.smp_regs[0][i] = static_cast<uint8_t>(data);
252
-
253
-					// Registers other than $F2 and $F4-$F7
254
-					//if ( i != 2 && i != 4 && i != 5 && i != 6 && i != 7 )
255
-					if (((~0x2F00 << (bits_in_int - 16)) << i) < 0) // 12%
256
-						this->cpu_write_smp_reg(data, rel_time, i);
257
-				}
258
-			}
259
-			goto loop;
260
-		}
261
-
262
-		case 0xC4: // MOV dp,a
263
-			++pc;
264
-			{
265
-				int i = dp + data;
266
-				ram[i] = static_cast<uint8_t>(a);
267
-				i -= 0xF0;
268
-				if (static_cast<unsigned>(i) < 0x10) // 39%
269
-				{
270
-					unsigned sel = i - 2;
271
-					this->m.smp_regs[0][i] = static_cast<uint8_t>(a);
272
-
273
-					if (sel == 1) // 51% $F3
274
-						this->dsp_write(a, rel_time);
275
-					else if (sel > 1) // 1% not $F2 or $F3
276
-						this->cpu_write_smp_reg_(a, rel_time, i);
277
-				}
278
-			}
279
-			goto loop;
280
-
281
-#define CASE(n) case n:
282
-
283
-// Define common address modes based on opcode for immediate mode. Execution
284
-// ends with data set to the address of the operand.
285
-#define ADDR_MODES_(op) \
286
-	CASE(op - 0x02) /* (X) */ \
287
-		data = x + dp; \
288
-		--pc; \
289
-		goto end_##op; \
290
-	CASE(op + 0x0F) /* (dp)+Y */ \
291
-		data = READ_PROG16(data + dp) + y; \
292
-		goto end_##op; \
293
-	CASE(op - 0x01) /* (dp+X) */ \
294
-		data = READ_PROG16(static_cast<uint8_t>(data + x) + dp); \
295
-		goto end_##op; \
296
-	CASE(op + 0x0E) /* abs+Y */ \
297
-		data += y; \
298
-		goto abs_##op; \
299
-	CASE(op + 0x0D) /* abs+X */ \
300
-		data += x; \
301
-	CASE(op - 0x03) /* abs */ \
302
-	abs_##op: \
303
-		data += 0x100 * *(++pc); \
304
-		goto end_##op; \
305
-	CASE(op + 0x0C) /* dp+X */ \
306
-		data = static_cast<uint8_t>(data + x);
307
-
308
-#define ADDR_MODES_NO_DP(op) \
309
-	ADDR_MODES_(op) \
310
-		data += dp; \
311
-	end_##op:
312
-
313
-#define ADDR_MODES(op) \
314
-	ADDR_MODES_(op) \
315
-	CASE(op - 0x04) /* dp */ \
316
-		data += dp; \
317
-	end_##op:
318
-
319
-		// 1. 8-bit Data Transmission Commands. Group I
320
-
321
-		ADDR_MODES_NO_DP(0xE8) // MOV A,addr
322
-			a = nz = this->cpu_read(data, rel_time);
323
-			goto inc_pc_loop;
324
-
325
-		case 0xBF: // MOV A,(X)+
326
-		{
327
-			int temp = x + dp;
328
-			x = static_cast<uint8_t>(x + 1);
329
-			a = nz = this->cpu_read(temp, rel_time - 1);
330
-			goto loop;
331
-		}
332
-
333
-		case 0xE8: // MOV A,imm
334
-			a  = data;
335
-			nz = data;
336
-			goto inc_pc_loop;
337
-
338
-		case 0xF9: // MOV X,dp+Y
339
-			data = static_cast<uint8_t>(data + y);
340
-		case 0xF8: // MOV X,dp
341
-			x = nz = CPU_READ_TIMER(0, DP_ADDR(data));
342
-			goto inc_pc_loop;
343
-
344
-		case 0xE9: // MOV X,abs
345
-			data = get_le16(pc);
346
-			++pc;
347
-			data = this->cpu_read(data, rel_time);
348
-		case 0xCD: // MOV X,imm
349
-			x  = data;
350
-			nz = data;
351
-			goto inc_pc_loop;
352
-
353
-		case 0xFB: // MOV Y,dp+X
354
-			data = static_cast<uint8_t>(data + x);
355
-		case 0xEB: // MOV Y,dp
356
-			// 70% from timer
357
-			++pc;
358
-			y = nz = CPU_READ_TIMER(0, DP_ADDR(data));
359
-			goto loop;
360
-
361
-		case 0xEC: // MOV Y,abs
362
-		{
363
-			int temp = get_le16(pc);
364
-			pc += 2;
365
-			y = nz = CPU_READ_TIMER(0, temp);
366
-			//y = nz = this->cpu_read(temp, rel_time);
367
-			goto loop;
368
-		}
369
-
370
-		case 0x8D: // MOV Y,imm
371
-			y  = data;
372
-			nz = data;
373
-			goto inc_pc_loop;
374
-
375
-		// 2. 8-BIT DATA TRANSMISSION COMMANDS, GROUP 2
376
-
377
-		ADDR_MODES_NO_DP(0xC8) // MOV addr,A
378
-			this->cpu_write(a, data, rel_time);
379
-			goto inc_pc_loop;
380
-
381
-		{
382
-			int temp;
383
-			case 0xCC: // MOV abs,Y
384
-				temp = y;
385
-				goto mov_abs_temp;
386
-			case 0xC9: // MOV abs,X
387
-				temp = x;
388
-			mov_abs_temp:
389
-				this->cpu_write(temp, get_le16(pc), rel_time);
390
-				pc += 2;
391
-				goto loop;
392
-		}
393
-
394
-		case 0xD9: // MOV dp+Y,X
395
-			data = static_cast<uint8_t>(data + y);
396
-		case 0xD8: // MOV dp,X
397
-			this->cpu_write(x, data + dp, rel_time);
398
-			goto inc_pc_loop;
399
-
400
-		case 0xDB: // MOV dp+X,Y
401
-			data = static_cast<uint8_t>(data + x);
402
-		case 0xCB: // MOV dp,Y
403
-			this->cpu_write(y, data + dp, rel_time);
404
-			goto inc_pc_loop;
405
-
406
-		// 3. 8-BIT DATA TRANSMISSIN COMMANDS, GROUP 3.
407
-
408
-		case 0x7D: // MOV A,X
409
-			a = nz = x;
410
-			goto loop;
411
-
412
-		case 0xDD: // MOV A,Y
413
-			a = nz = y;
414
-			goto loop;
415
-
416
-		case 0x5D: // MOV X,A
417
-			x = nz = a;
418
-			goto loop;
419
-
420
-		case 0xFD: // MOV Y,A
421
-			y = nz = a;
422
-			goto loop;
423
-
424
-		case 0x9D: // MOV X,SP
425
-			x = nz = GET_SP();
426
-			goto loop;
427
-
428
-		case 0xBD: // MOV SP,X
429
-			SET_SP(x);
430
-			goto loop;
431
-
432
-		//case 0xC6: // MOV (X),A (handled by MOV addr,A in group 2)
433
-
434
-		case 0xAF: // MOV (X)+,A
435
-			this->cpu_write(a + no_read_before_write, DP_ADDR(x), rel_time);
436
-			++x;
437
-			goto loop;
438
-
439
-		// 5. 8-BIT LOGIC OPERATION COMMANDS
440
-
441
-#define LOGICAL_OP(op, func) \
442
-	ADDR_MODES(op) /* addr */ \
443
-		data = this->cpu_read(data, rel_time); \
444
-	case op: /* imm */ \
445
-		nz = a func##= data; \
446
-		goto inc_pc_loop; \
447
-		{ \
448
-			unsigned addr; \
449
-			case op + 0x11: /* X,Y */ \
450
-				data = this->cpu_read(DP_ADDR(y), rel_time - 2); \
451
-				addr = x + dp; \
452
-				goto addr_##op; \
453
-			case op + 0x01: /* dp,dp */ \
454
-				data = this->cpu_read(DP_ADDR(data), rel_time - 3); \
455
-			case op + 0x10: /*dp,imm*/ \
456
-			{ \
457
-				auto addr2 = pc + 1; \
458
-				pc += 2; \
459
-				addr = *addr2 + dp; \
460
-			} \
461
-			addr_##op: \
462
-				nz = data func this->cpu_read(addr, rel_time - 1); \
463
-				this->cpu_write(nz, addr, rel_time); \
464
-				goto loop; \
465
-		}
466
-
467
-		LOGICAL_OP(0x28, &); // AND
468
-
469
-		LOGICAL_OP(0x08, |); // OR
470
-
471
-		LOGICAL_OP(0x48, ^); // EOR
472
-
473
-		// 4. 8-BIT ARITHMETIC OPERATION COMMANDS
474
-
475
-		ADDR_MODES(0x68) // CMP addr
476
-			data = this->cpu_read(data, rel_time);
477
-		case 0x68: // CMP imm
478
-			nz = a - data;
479
-			c = ~nz;
480
-			nz &= 0xFF;
481
-			goto inc_pc_loop;
482
-
483
-		case 0x79: // CMP (X),(Y)
484
-			data = this->cpu_read(DP_ADDR(y), rel_time - 2);
485
-			nz = this->cpu_read(DP_ADDR(x), rel_time - 1) - data;
486
-			c = ~nz;
487
-			nz &= 0xFF;
488
-			goto loop;
489
-
490
-		case 0x69: // CMP dp,dp
491
-			data = this->cpu_read(DP_ADDR(data), rel_time - 3);
492
-		case 0x78: // CMP dp,imm
493
-			nz = this->cpu_read(DP_ADDR(*(++pc)), rel_time - 1) - data;
494
-			c = ~nz;
495
-			nz &= 0xFF;
496
-			goto inc_pc_loop;
497
-
498
-		case 0x3E: // CMP X,dp
499
-			data += dp;
500
-			goto cmp_x_addr;
501
-		case 0x1E: // CMP X,abs
502
-			data = get_le16(pc);
503
-			++pc;
504
-		cmp_x_addr:
505
-			data = this->cpu_read(data, rel_time);
506
-		case 0xC8: // CMP X,imm
507
-			nz = x - data;
508
-			c = ~nz;
509
-			nz &= 0xFF;
510
-			goto inc_pc_loop;
511
-
512
-		case 0x7E: // CMP Y,dp
513
-			data += dp;
514
-			goto cmp_y_addr;
515
-		case 0x5E: // CMP Y,abs
516
-			data = get_le16(pc);
517
-			++pc;
518
-		cmp_y_addr:
519
-			data = this->cpu_read(data, rel_time);
520
-		case 0xAD: // CMP Y,imm
521
-			nz = y - data;
522
-			c = ~nz;
523
-			nz &= 0xFF;
524
-			goto inc_pc_loop;
525
-
526
-		{
527
-			int addr;
528
-			case 0xB9: // SBC (x),(y)
529
-			case 0x99: // ADC (x),(y)
530
-				--pc; // compensate for inc later
531
-				data = this->cpu_read(DP_ADDR(y), rel_time - 2);
532
-				addr = x + dp;
533
-				goto adc_addr;
534
-			case 0xA9: // SBC dp,dp
535
-			case 0x89: // ADC dp,dp
536
-				data = this->cpu_read(DP_ADDR(data), rel_time - 3);
537
-			case 0xB8: // SBC dp,imm
538
-			case 0x98: // ADC dp,imm
539
-				addr = *(++pc) + dp;
540
-			adc_addr:
541
-				nz = this->cpu_read(addr, rel_time - 1);
542
-				goto adc_data;
543
-
544
-			// catch ADC and SBC together, then decode later based on operand
545
-#undef CASE
546
-#define CASE(n) case n: case (n) + 0x20:
547
-				ADDR_MODES(0x88) // ADC/SBC addr
548
-				data = this->cpu_read(data, rel_time);
549
-			case 0xA8: // SBC imm
550
-			case 0x88: // ADC imm
551
-				addr = -1; // A
552
-				nz = a;
553
-			adc_data:
554
-			{
555
-				int flags;
556
-				if (opcode >= 0xA0) // SBC
557
-					data ^= 0xFF;
558
-
559
-				flags = data ^ nz;
560
-				nz += data + (c >> 8 & 1);
561
-				flags ^= nz;
562
-
563
-				psw = (psw & ~(v40 | h08)) | ((flags >> 1) & h08) | (((flags + 0x80) >> 2) & v40);
564
-				c = nz;
565
-				if (addr < 0)
566
-				{
567
-					a = static_cast<uint8_t>(nz);
568
-					goto inc_pc_loop;
569
-				}
570
-				this->cpu_write(/*(uint8_t)*/nz, addr, rel_time);
571
-				goto inc_pc_loop;
572
-			}
573
-		}
574
-
575
-		// 6. ADDITION & SUBTRACTION COMMANDS
576
-
577
-#define INC_DEC_REG(reg, op) \
578
-	nz = reg op; \
579
-	reg = static_cast<uint8_t>(nz); \
580
-	goto loop;
581
-
582
-		case 0xBC: INC_DEC_REG(a, + 1) // INC A
583
-		case 0x3D: INC_DEC_REG(x, + 1) // INC X
584
-		case 0xFC: INC_DEC_REG(y, + 1) // INC Y
585
-
586
-		case 0x9C: INC_DEC_REG(a, - 1) // DEC A
587
-		case 0x1D: INC_DEC_REG(x, - 1) // DEC X
588
-		case 0xDC: INC_DEC_REG(y, - 1) // DEC Y
589
-
590
-		case 0x9B: // DEC dp+X
591
-		case 0xBB: // INC dp+X
592
-			data = static_cast<uint8_t>(data + x);
593
-		case 0x8B: // DEC dp
594
-		case 0xAB: // INC dp
595
-			data += dp;
596
-			goto inc_abs;
597
-		case 0x8C: // DEC abs
598
-		case 0xAC: // INC abs
599
-			data = get_le16(pc);
600
-			++pc;
601
-		inc_abs:
602
-			nz = ((opcode >> 4) & 2) - 1;
603
-			nz += this->cpu_read(data, rel_time - 1);
604
-			this->cpu_write(/*(uint8_t)*/ nz, data, rel_time);
605
-			goto inc_pc_loop;
606
-
607
-		// 7. SHIFT, ROTATION COMMANDS
608
-
609
-		case 0x5C: // LSR A
610
-			c = 0;
611
-		case 0x7C: // ROR A
612
-		{
613
-			nz = ((c >> 1) & 0x80) | (a >> 1);
614
-			c = a << 8;
615
-			a = nz;
616
-			goto loop;
617
-		}
618
-
619
-		case 0x1C: // ASL A
620
-			c = 0;
621
-		case 0x3C: // ROL A
622
-		{
623
-			int temp = c >> 8 & 1;
624
-			c = a << 1;
625
-			nz = c | temp;
626
-			a = static_cast<uint8_t>(nz);
627
-			goto loop;
628
-		}
629
-
630
-		case 0x0B: // ASL dp
631
-			c = 0;
632
-			data += dp;
633
-			goto rol_mem;
634
-		case 0x1B: // ASL dp+X
635
-			c = 0;
636
-		case 0x3B: // ROL dp+X
637
-			data = static_cast<uint8_t>(data + x);
638
-		case 0x2B: // ROL dp
639
-			data += dp;
640
-			goto rol_mem;
641
-		case 0x0C: // ASL abs
642
-			c = 0;
643
-		case 0x2C: // ROL abs
644
-			data = get_le16(pc);
645
-			++pc;
646
-		rol_mem:
647
-			nz = c >> 8 & 1;
648
-			nz |= (c = this->cpu_read(data, rel_time - 1) << 1);
649
-			this->cpu_write(/*(uint8_t)*/ nz, data, rel_time);
650
-			goto inc_pc_loop;
651
-
652
-		case 0x4B: // LSR dp
653
-			c = 0;
654
-			data += dp;
655
-			goto ror_mem;
656
-		case 0x5B: // LSR dp+X
657
-			c = 0;
658
-		case 0x7B: // ROR dp+X
659
-			data = static_cast<uint8_t>(data + x);
660
-		case 0x6B: // ROR dp
661
-			data += dp;
662
-			goto ror_mem;
663
-		case 0x4C: // LSR abs
664
-			c = 0;
665
-		case 0x6C: // ROR abs
666
-			data = get_le16(pc);
667
-			++pc;
668
-		ror_mem:
669
-		{
670
-			int temp = this->cpu_read(data, rel_time - 1);
671
-			nz = (c >> 1 & 0x80) | (temp >> 1);
672
-			c = temp << 8;
673
-			this->cpu_write(nz, data, rel_time);
674
-			goto inc_pc_loop;
675
-		}
676
-
677
-		case 0x9F: // XCN
678
-			nz = a = (a >> 4) | static_cast<uint8_t>(a << 4);
679
-			goto loop;
680
-
681
-		// 8. 16-BIT TRANSMISION COMMANDS
682
-
683
-		case 0xBA: // MOVW YA,dp
684
-			a = this->cpu_read(DP_ADDR(data), rel_time - 2);
685
-			nz = (a & 0x7F) | (a >> 1);
686
-			y = this->cpu_read(DP_ADDR(static_cast<uint8_t>(data + 1)), rel_time);
687
-			nz |= y;
688
-			goto inc_pc_loop;
689
-
690
-		case 0xDA: // MOVW dp,YA
691
-			this->cpu_write(a, DP_ADDR(data), rel_time - 1);
692
-			this->cpu_write(y + no_read_before_write, DP_ADDR(static_cast<uint8_t>(data + 1)), rel_time);
693
-			goto inc_pc_loop;
694
-
695
-		// 9. 16-BIT OPERATION COMMANDS
696
-
697
-		case 0x3A: // INCW dp
698
-		case 0x1A: // DECW dp
699
-		{
700
-			int temp;
701
-			// low byte
702
-			data += dp;
703
-			temp = this->cpu_read(data, rel_time - 3);
704
-			temp += (opcode >> 4 & 2) - 1; // +1 for INCW, -1 for DECW
705
-			nz = ((temp >> 1) | temp) & 0x7F;
706
-			this->cpu_write(/*(uint8_t)*/ temp, data, rel_time - 2);
707
-
708
-			// high byte
709
-			data = static_cast<uint8_t>(data + 1) + dp;
710
-			temp = static_cast<uint8_t>((temp >> 8) + this->cpu_read(data, rel_time - 1));
711
-			nz |= temp;
712
-			this->cpu_write(temp, data, rel_time);
713
-
714
-			goto inc_pc_loop;
715
-		}
716
-
717
-		case 0x7A: // ADDW YA,dp
718
-		case 0x9A: // SUBW YA,dp
719
-		{
720
-			int lo = this->cpu_read(DP_ADDR(data), rel_time - 2);
721
-			int hi = this->cpu_read(DP_ADDR(static_cast<uint8_t>(data + 1)), rel_time);
722
-
723
-			if (opcode == 0x9A) // SUBW
724
-			{
725
-				lo = (lo ^ 0xFF) + 1;
726
-				hi ^= 0xFF;
727
-			}
728
-
729
-			lo += a;
730
-			int result = y + hi + (lo >> 8);
731
-			int flags = hi ^ y ^ result;
732
-
733
-			psw = (psw & ~(v40 | h08)) | (flags >> 1 & h08) | ((flags + 0x80) >> 2 & v40);
734
-			c = result;
735
-			a = static_cast<uint8_t>(lo);
736
-			result = static_cast<uint8_t>(result);
737
-			y = result;
738
-			nz = (((lo >> 1) | lo) & 0x7F) | result;
739
-
740
-			goto inc_pc_loop;
741
-		}
742
-
743
-		case 0x5A: // CMPW YA,dp
744
-		{
745
-			int temp = a - this->cpu_read(DP_ADDR(data), rel_time - 1);
746
-			nz = ((temp >> 1) | temp) & 0x7F;
747
-			temp = y + (temp >> 8);
748
-			temp -= this->cpu_read(DP_ADDR(static_cast<uint8_t>(data + 1)), rel_time);
749
-			nz |= temp;
750
-			c  = ~temp;
751
-			nz &= 0xFF;
752
-			goto inc_pc_loop;
753
-		}
754
-
755
-		// 10. MULTIPLICATION & DIVISON COMMANDS
756
-
757
-		case 0xCF: // MUL YA
758
-		{
759
-			unsigned temp = y * a;
760
-			a = static_cast<uint8_t>(temp);
761
-			nz = ((temp >> 1) | temp) & 0x7F;
762
-			y = temp >> 8;
763
-			nz |= y;
764
-			goto loop;
765
-		}
766
-
767
-		case 0x9E: // DIV YA,X
768
-		{
769
-			unsigned ya = y * 0x100 + a;
770
-
771
-			psw &= ~(h08 | v40);
772
-
773
-			if (y >= x)
774
-				psw |= v40;
775
-
776
-			if ((y & 15) >= (x & 15))
777
-				psw |= h08;
778
-
779
-			if (y < x * 2)
780
-			{
781
-				a = ya / x;
782
-				y = ya - a * x;
783
-			}
784
-			else
785
-			{
786
-				a = 255 - (ya - x * 0x200) / (256 - x);
787
-				y = x + (ya - x * 0x200) % (256 - x);
788
-			}
789
-
790
-			nz = static_cast<uint8_t>(a);
791
-			a = static_cast<uint8_t>(a);
792
-
793
-			goto loop;
794
-		}
795
-
796
-		// 11. DECIMAL COMPENSATION COMMANDS
797
-
798
-		case 0xDF: // DAA
799
-			if (a > 0x99 || c & 0x100)
800
-			{
801
-				a += 0x60;
802
-				c = 0x100;
803
-			}
804
-
805
-			if ((a & 0x0F) > 9 || psw & h08)
806
-				a += 0x06;
807
-
808
-			nz = a;
809
-			a = static_cast<uint8_t>(a);
810
-			goto loop;
811
-
812
-		case 0xBE: // DAS
813
-			if (a > 0x99 || !(c & 0x100))
814
-			{
815
-				a -= 0x60;
816
-				c = 0;
817
-			}
818
-
819
-			if ((a & 0x0F) > 9 || !(psw & h08))
820
-				a -= 0x06;
821
-
822
-			nz = a;
823
-			a = static_cast<uint8_t>(a);
824
-			goto loop;
825
-
826
-		// 12. BRANCHING COMMANDS
827
-
828
-		case 0x2F: // BRA rel
829
-			pc += static_cast<int8_t>(data);
830
-			goto inc_pc_loop;
831
-
832
-		case 0x30: // BMI
833
-			BRANCH(nz & nz_neg_mask)
834
-
835
-		case 0x10: // BPL
836
-			BRANCH(!(nz & nz_neg_mask))
837
-
838
-		case 0xB0: // BCS
839
-			BRANCH(c & 0x100)
840
-
841
-		case 0x90: // BCC
842
-			BRANCH(!(c & 0x100))
843
-
844
-		case 0x70: // BVS
845
-			BRANCH(psw & v40)
846
-
847
-		case 0x50: // BVC
848
-			BRANCH(!(psw & v40))
849
-
850
-#define CBRANCH(cond) \
851
-{ \
852
-	++pc; \
853
-	if (cond) \
854
-		goto cbranch_taken_loop; \
855
-	rel_time -= 2; \
856
-	goto inc_pc_loop; \
857
-}
858
-
859
-		case 0x03: // BBS dp.bit,rel
860
-		case 0x23:
861
-		case 0x43:
862
-		case 0x63:
863
-		case 0x83:
864
-		case 0xA3:
865
-		case 0xC3:
866
-		case 0xE3:
867
-			CBRANCH((this->cpu_read(DP_ADDR(data), rel_time - 4) >> (opcode >> 5)) & 1)
868
-
869
-		case 0x13: // BBC dp.bit,rel
870
-		case 0x33:
871
-		case 0x53:
872
-		case 0x73:
873
-		case 0x93:
874
-		case 0xB3:
875
-		case 0xD3:
876
-		case 0xF3:
877
-			CBRANCH(!((this->cpu_read(DP_ADDR(data), rel_time - 4) >> (opcode >> 5)) & 1))
878
-
879
-		case 0xDE: // CBNE dp+X,rel
880
-			data = static_cast<uint8_t>(data + x);
881
-			// fall through
882
-		case 0x2E: // CBNE dp,rel
883
-		{
884
-			// 61% from timer
885
-			int temp = CPU_READ_TIMER(-4, DP_ADDR(data));
886
-			CBRANCH(temp != a)
887
-		}
888
-
889
-		case 0x6E: // DBNZ dp,rel
890
-		{
891
-			unsigned temp = this->cpu_read(DP_ADDR(data), rel_time - 4) - 1;
892
-			this->cpu_write(/*(uint8_t)*/ temp + no_read_before_write, DP_ADDR(static_cast<uint8_t>(data)), rel_time - 3);
893
-			CBRANCH(temp)
894
-		}
895
-
896
-		case 0xFE: // DBNZ Y,rel
897
-			y = static_cast<uint8_t>(y - 1);
898
-			BRANCH(y)
899
-
900
-		case 0x1F: // JMP [abs+X]
901
-			SET_PC(get_le16(pc) + x);
902
-			// fall through
903
-		case 0x5F: // JMP abs
904
-			SET_PC(get_le16(pc));
905
-			goto loop;
906
-
907
-		// 13. SUB-ROUTINE CALL RETURN COMMANDS
908
-
909
-		case 0x0F: // BRK
910
-		{
911
-			int temp;
912
-			int ret_addr = GET_PC();
913
-			SET_PC(READ_PROG16(0xFFDE)); // vector address verified
914
-			PUSH16(ret_addr);
915
-			GET_PSW(temp);
916
-			psw = (psw | b10) & ~i04;
917
-			PUSH(temp);
918
-			goto loop;
919
-		}
920
-
921
-		case 0x4F: // PCALL offset
922
-		{
923
-			int ret_addr = GET_PC() + 1;
924
-			SET_PC(0xFF00 | data);
925
-			PUSH16(ret_addr);
926
-			goto loop;
927
-		}
928
-
929
-		case 0x01: // TCALL n
930
-		case 0x11:
931
-		case 0x21:
932
-		case 0x31:
933
-		case 0x41:
934
-		case 0x51:
935
-		case 0x61:
936
-		case 0x71:
937
-		case 0x81:
938
-		case 0x91:
939
-		case 0xA1:
940
-		case 0xB1:
941
-		case 0xC1:
942
-		case 0xD1:
943
-		case 0xE1:
944
-		case 0xF1:
945
-		{
946
-			int ret_addr = GET_PC();
947
-			SET_PC(READ_PROG16(0xFFDE - (opcode >> 3)));
948
-			PUSH16(ret_addr);
949
-			goto loop;
950
-		}
951
-
952
-		// 14. STACK OPERATION COMMANDS
953
-
954
-		{
955
-			int temp;
956
-		case 0x7F: // RET1
957
-			temp = *sp;
958
-			SET_PC(get_le16(sp + 1));
959
-			sp += 3;
960
-			goto set_psw;
961
-		case 0x8E: // POP PSW
962
-			POP(temp);
963
-		set_psw:
964
-			SET_PSW(temp);
965
-			goto loop;
966
-		}
967
-
968
-		case 0x0D: // PUSH PSW
969
-		{
970
-			int temp;
971
-			GET_PSW(temp);
972
-			PUSH(temp);
973
-			goto loop;
974
-		}
975
-
976
-		case 0x2D: // PUSH A
977
-			PUSH(a);
978
-			goto loop;
979
-
980
-		case 0x4D: // PUSH X
981
-			PUSH(x);
982
-			goto loop;
983
-
984
-		case 0x6D: // PUSH Y
985
-			PUSH(y);
986
-			goto loop;
987
-
988
-		case 0xAE: // POP A
989
-			POP(a);
990
-			goto loop;
991
-
992
-		case 0xCE: // POP X
993
-			POP(x);
994
-			goto loop;
995
-
996
-		case 0xEE: // POP Y
997
-			POP(y);
998
-			goto loop;
999
-
1000
-		// 15. BIT OPERATION COMMANDS
1001
-
1002
-		case 0x02: // SET1
1003
-		case 0x22:
1004
-		case 0x42:
1005
-		case 0x62:
1006
-		case 0x82:
1007
-		case 0xA2:
1008
-		case 0xC2:
1009
-		case 0xE2:
1010
-		case 0x12: // CLR1
1011
-		case 0x32:
1012
-		case 0x52:
1013
-		case 0x72:
1014
-		case 0x92:
1015
-		case 0xB2:
1016
-		case 0xD2:
1017
-		case 0xF2:
1018
-		{
1019
-			int bit = 1 << (opcode >> 5);
1020
-			int mask = ~bit;
1021
-			if (opcode & 0x10)
1022
-				bit = 0;
1023
-			data += dp;
1024
-			this->cpu_write((this->cpu_read(data, rel_time - 1) & mask) | bit, data, rel_time);
1025
-			goto inc_pc_loop;
1026
-		}
1027
-
1028
-		case 0x0E: // TSET1 abs
1029
-		case 0x4E: // TCLR1 abs
1030
-			data = get_le16(pc);
1031
-			pc += 2;
1032
-			{
1033
-				unsigned temp = this->cpu_read(data, rel_time - 2);
1034
-				nz = static_cast<uint8_t>(a - temp);
1035
-				temp &= ~a;
1036
-				if (opcode == 0x0E)
1037
-					temp |= a;
1038
-				this->cpu_write(temp, data, rel_time);
1039
-			}
1040
-			goto loop;
1041
-
1042
-		case 0x4A: // AND1 C,mem.bit
1043
-			c &= MEM_BIT(0);
1044
-			pc += 2;
1045
-			goto loop;
1046
-
1047
-		case 0x6A: // AND1 C,/mem.bit
1048
-			c &= ~MEM_BIT(0);
1049
-			pc += 2;
1050
-			goto loop;
1051
-
1052
-		case 0x0A: // OR1 C,mem.bit
1053
-			c |= MEM_BIT(-1);
1054
-			pc += 2;
1055
-			goto loop;
1056
-
1057
-		case 0x2A: // OR1 C,/mem.bit
1058
-			c |= ~MEM_BIT(-1);
1059
-			pc += 2;
1060
-			goto loop;
1061
-
1062
-		case 0x8A: // EOR1 C,mem.bit
1063
-			c ^= MEM_BIT(-1);
1064
-			pc += 2;
1065
-			goto loop;
1066
-
1067
-		case 0xEA: // NOT1 mem.bit
1068
-			data = get_le16(pc);
1069
-			pc += 2;
1070
-			{
1071
-				unsigned temp = this->cpu_read(data & 0x1FFF, rel_time - 1);
1072
-				temp ^= 1 << (data >> 13);
1073
-				this->cpu_write(temp, data & 0x1FFF, rel_time);
1074
-			}
1075
-			goto loop;
1076
-
1077
-		case 0xCA: // MOV1 mem.bit,C
1078
-			data = get_le16(pc);
1079
-			pc += 2;
1080
-			{
1081
-				unsigned temp = this->cpu_read(data & 0x1FFF, rel_time - 2);
1082
-				unsigned bit = data >> 13;
1083
-				temp = (temp & ~(1 << bit)) | ((c >> 8 & 1) << bit);
1084
-				this->cpu_write(temp + no_read_before_write, data & 0x1FFF, rel_time);
1085
-			}
1086
-			goto loop;
1087
-
1088
-		case 0xAA: // MOV1 C,mem.bit
1089
-			c = MEM_BIT(0);
1090
-			pc += 2;
1091
-			goto loop;
1092
-
1093
-		// 16. PROGRAM PSW FLAG OPERATION COMMANDS
1094
-
1095
-		case 0x60: // CLRC
1096
-			c = 0;
1097
-			goto loop;
1098
-
1099
-		case 0x80: // SETC
1100
-			c = ~0;
1101
-			goto loop;
1102
-
1103
-		case 0xED: // NOTC
1104
-			c ^= 0x100;
1105
-			goto loop;
1106
-
1107
-		case 0xE0: // CLRV
1108
-			psw &= ~(v40 | h08);
1109
-			goto loop;
1110
-
1111
-		case 0x20: // CLRP
1112
-			dp = 0;
1113
-			goto loop;
1114
-
1115
-		case 0x40: // SETP
1116
-			dp = 0x100;
1117
-			goto loop;
1118
-
1119
-		case 0xA0: // EI
1120
-			psw |= i04;
1121
-			goto loop;
1122
-
1123
-		case 0xC0: // DI
1124
-			psw &= ~i04;
1125
-			goto loop;
1126
-
1127
-		// 17. OTHER COMMANDS
1128
-
1129
-		case 0x00: // NOP
1130
-			goto loop;
1131
-
1132
-		case 0xFF: // STOP
1133
-		{
1134
-			// handle PC wrap-around
1135
-			unsigned addr = GET_PC() - 1;
1136
-			if (addr >= 0x10000)
1137
-			{
1138
-				addr &= 0xFFFF;
1139
-				SET_PC(addr);
1140
-				goto loop;
1141
-			}
1142
-		}
1143
-		// fall through
1144
-		case 0xEF: // SLEEP
1145
-			--pc;
1146
-			rel_time = 0;
1147
-			goto stop;
1148
-	} // switch
1149
-
1150
-	assert(0); // catch any unhandled instructions
1151
-
1152
-out_of_time:
1153
-	rel_time -= this->m.cycle_table[*pc]; // undo partial execution of opcode
1154
-stop:
1155
-
1156
-	// Uncache registers
1157
-	m.cpu_regs.pc = static_cast<uint16_t>(GET_PC());
1158
-	m.cpu_regs.sp = static_cast<uint8_t>(GET_SP());
1159
-	m.cpu_regs.a = static_cast<uint8_t>(a);
1160
-	m.cpu_regs.x = static_cast<uint8_t>(x);
1161
-	m.cpu_regs.y = static_cast<uint8_t>(y);
1162
-	int temp;
1163
-	GET_PSW(temp);
1164
-	m.cpu_regs.psw = static_cast<uint8_t>(temp);
1165
-
1166
-	this->m.spc_time += rel_time;
1167
-	this->m.dsp_time -= rel_time;
1168
-	this->m.timers[0].next_time -= rel_time;
1169
-	this->m.timers[1].next_time -= rel_time;
1170
-	this->m.timers[2].next_time -= rel_time;
1171
-	/*assert( m.spc_time >= end_time );*/
1172
-	return &this->m.smp_regs[0][r_cpuio0];
1173
-}
Browse code

* Fixes for gcc and clang (while they can compile the code, the DLLs made aren't functional, but oh well).

* [2SF] Used more up-to-date asmjit, despite the ugly looking code.

Naram Qashat authored on 2014/09/17 19:51:45
Showing 1 changed files
... ...
@@ -172,7 +172,7 @@ loop:
172 172
 		goto stop;
173 173
 	if ((rel_time += this->m.cycle_table[opcode]) > 0 && !this->allow_time_overflow)
174 174
 		goto out_of_time;
175
-	
175
+
176 176
 #ifdef SPC_CPU_OPCODE_HOOK
177 177
 	SPC_CPU_OPCODE_HOOK(GET_PC(), opcode);
178 178
 #endif
Browse code

A few more cases of using #pragma once instead of include guards.

Naram Qashat authored on 2014/09/08 14:51:19
Showing 1 changed files
... ...
@@ -11,6 +11,8 @@ details. You should have received a copy of the GNU Lesser General Public
11 11
 License along with this module; if not, write to the Free Software Foundation,
12 12
 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
13 13
 
14
+#pragma once
15
+
14 16
 //// Memory access
15 17
 
16 18
 // TODO: remove non-wrapping versions?
Browse code

[SNSF] Replaced most uses of fill/copy with fill_n/copy_n, and a few other minor code cleanups.

Naram Qashat authored on 2013/05/27 22:34:22
Showing 1 changed files
... ...
@@ -38,8 +38,16 @@ const int c01 = 0x01; // c
38 38
 
39 39
 const int nz_neg_mask = 0x880; // either bit set indicates N flag set
40 40
 
41
-SPC_CPU_RUN_FUNC
41
+uint8_t *SNES_SPC::run_until_(time_t end_time)
42 42
 {
43
+	rel_time_t rel_time = this->m.spc_time - end_time;
44
+	/*assert( rel_time <= 0 );*/
45
+	this->m.spc_time = end_time;
46
+	this->m.dsp_time += rel_time;
47
+	this->m.timers[0].next_time += rel_time;
48
+	this->m.timers[1].next_time += rel_time;
49
+	this->m.timers[2].next_time += rel_time;
50
+
43 51
 	auto ram = this->m.ram.ram;
44 52
 	int a = this->m.cpu_regs.a;
45 53
 	int x = this->m.cpu_regs.x;
... ...
@@ -155,7 +163,6 @@ cbranch_taken_loop:
155 163
 inc_pc_loop:
156 164
 	++pc;
157 165
 loop:
158
-{
159 166
 	unsigned data;
160 167
 
161 168
 	unsigned opcode = *pc;
... ...
@@ -167,20 +174,6 @@ loop:
167 174
 #ifdef SPC_CPU_OPCODE_HOOK
168 175
 	SPC_CPU_OPCODE_HOOK(GET_PC(), opcode);
169 176
 #endif
170
-	/*
171
-	//SUB_CASE_COUNTER( 1 );
172
-	#define PROFILE_TIMER_LOOP( op, addr, len )\
173
-	if ( opcode == op )\
174
-	{\
175
-		int cond = (unsigned) ((addr) - 0xFD) < 3 &&\
176
-				pc [len] == 0xF0 && pc [len+1] == 0xFE - len;\
177
-		SUB_CASE_COUNTER( op && cond );\
178
-	}
179
-	
180
-	PROFILE_TIMER_LOOP( 0xEC, get_le16( pc + 1 ), 3 );
181
-	PROFILE_TIMER_LOOP( 0xEB, pc [1], 2 );
182
-	PROFILE_TIMER_LOOP( 0xE4, pc [1], 2 );
183
-	*/
184 177
 
185 178
 	// TODO: if PC is at end of memory, this will get wrong operand (very obscure)
186 179
 	data = *++pc;
... ...
@@ -268,7 +261,7 @@ loop:
268 261
 			++pc;
269 262
 			{
270 263
 				int i = dp + data;
271
-				ram [i] = static_cast<uint8_t>(a);
264
+				ram[i] = static_cast<uint8_t>(a);
272 265
 				i -= 0xF0;
273 266
 				if (static_cast<unsigned>(i) < 0x10) // 39%
274 267
 				{
... ...
@@ -411,23 +404,19 @@ loop:
411 404
 		// 3. 8-BIT DATA TRANSMISSIN COMMANDS, GROUP 3.
412 405
 
413 406
 		case 0x7D: // MOV A,X
414
-			a  = x;
415
-			nz = x;
407
+			a = nz = x;
416 408
 			goto loop;
417 409
 
418 410
 		case 0xDD: // MOV A,Y
419
-			a  = y;
420
-			nz = y;
411
+			a = nz = y;
421 412
 			goto loop;
422 413
 
423 414
 		case 0x5D: // MOV X,A
424
-			x  = a;
425
-			nz = a;
415
+			x = nz = a;
426 416
 			goto loop;
427 417
 
428 418
 		case 0xFD: // MOV Y,A
429
-			y  = a;
430
-			nz = a;
419
+			y = nz = a;
431 420
 			goto loop;
432 421
 
433 422
 		case 0x9D: // MOV X,SP
... ...
@@ -1157,7 +1146,7 @@ loop:
1157 1146
 	} // switch
1158 1147
 
1159 1148
 	assert(0); // catch any unhandled instructions
1160
-}
1149
+
1161 1150
 out_of_time:
1162 1151
 	rel_time -= this->m.cycle_table[*pc]; // undo partial execution of opcode
1163 1152
 stop:
... ...
@@ -1168,10 +1157,15 @@ stop:
1168 1157
 	m.cpu_regs.a = static_cast<uint8_t>(a);
1169 1158
 	m.cpu_regs.x = static_cast<uint8_t>(x);
1170 1159
 	m.cpu_regs.y = static_cast<uint8_t>(y);
1171
-	{
1172
-		int temp;
1173
-		GET_PSW(temp);
1174
-		m.cpu_regs.psw = static_cast<uint8_t>(temp);
1175
-	}
1160
+	int temp;
1161
+	GET_PSW(temp);
1162
+	m.cpu_regs.psw = static_cast<uint8_t>(temp);
1163
+
1164
+	this->m.spc_time += rel_time;
1165
+	this->m.dsp_time -= rel_time;
1166
+	this->m.timers[0].next_time -= rel_time;
1167
+	this->m.timers[1].next_time -= rel_time;
1168
+	this->m.timers[2].next_time -= rel_time;
1169
+	/*assert( m.spc_time >= end_time );*/
1170
+	return &this->m.smp_regs[0][r_cpuio0];
1176 1171
 }
1177
-SPC_CPU_RUN_FUNC_END
Browse code

[SNSF] Massive code cleanup, as well as removing as much unused code/variables as possible.

Naram Qashat authored on 2013/05/23 06:02:16
Showing 1 changed files
... ...
@@ -13,197 +13,160 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
13 13
 
14 14
 //// Memory access
15 15
 
16
-#if SPC_MORE_ACCURACY
17
-	#define SUSPICIOUS_OPCODE( name ) ((void) 0)
18
-#else
19
-	#define SUSPICIOUS_OPCODE( name ) dprintf( "SPC: suspicious opcode: " name "\n" )
20
-#endif
21
-
22
-#define CPU_READ( time, offset, addr )\
23
-	cpu_read( addr, time + offset )
24
-
25
-#define CPU_WRITE( time, offset, addr, data )\
26
-	cpu_write( data, addr, time + offset )
27
-
28
-#if SPC_MORE_ACCURACY
29
-	#define CPU_READ_TIMER( time, offset, addr, out )\
30
-		{ out = CPU_READ( time, offset, addr ); }
31
-
32
-#else
33
-	// timers are by far the most common thing read from dp
34
-	#define CPU_READ_TIMER( time, offset, addr_, out )\
35
-	{\
36
-		rel_time_t adj_time = time + offset;\
37
-		int dp_addr = addr_;\
38
-		int ti = dp_addr - (r_t0out + 0xF0);\
39
-		if ( (unsigned) ti < timer_count )\
40
-		{\
41
-			Timer* t = &m.timers [ti];\
42
-			if ( adj_time >= t->next_time )\
43
-				t = run_timer_( t, adj_time );\
44
-			out = t->counter;\
45
-			t->counter = 0;\
46
-		}\
47
-		else\
48
-		{\
49
-			out = ram [dp_addr];\
50
-			int i = dp_addr - 0xF0;\
51
-			if ( (unsigned) i < 0x10 )\
52
-				out = cpu_read_smp_reg( i, adj_time );\
53
-		}\
54
-	}
55
-#endif
56
-
57
-#define TIME_ADJ( n )   (n)
58
-
59
-#define READ_TIMER( time, addr, out )       CPU_READ_TIMER( rel_time, TIME_ADJ(time), (addr), out )
60
-#define READ(  time, addr )                 CPU_READ ( rel_time, TIME_ADJ(time), (addr) )
61
-#define WRITE( time, addr, data )           CPU_WRITE( rel_time, TIME_ADJ(time), (addr), (data) )
62
-
63
-#define DP_ADDR( addr )                     (dp + (addr))
64
-
65
-#define READ_DP_TIMER(  time, addr, out )   CPU_READ_TIMER( rel_time, TIME_ADJ(time), DP_ADDR( addr ), out )
66
-#define READ_DP(  time, addr )              READ ( time, DP_ADDR( addr ) )
67
-#define WRITE_DP( time, addr, data )        WRITE( time, DP_ADDR( addr ), data )
68
-
69
-#define READ_PROG16( addr )                 GET_LE16( ram + (addr) )
70
-
71
-#define SET_PC( n )     (pc = ram + (n))
72
-#define GET_PC()        (pc - ram)
73
-#define READ_PC( pc )   (*(pc))
74
-#define READ_PC16( pc ) GET_LE16( pc )
75
-
76 16
 // TODO: remove non-wrapping versions?
77 17
 #define SPC_NO_SP_WRAPAROUND 0
78 18
 
79
-#define SET_SP( v )     (sp = ram + 0x101 + (v))
80
-#define GET_SP()        (sp - 0x101 - ram)
81
-
82
-#if SPC_NO_SP_WRAPAROUND
83
-#define PUSH16( v )     (sp -= 2, SET_LE16( sp, v ))
84
-#define PUSH( v )       (void) (*--sp = (uint8_t) (v))
85
-#define POP( out )      (void) ((out) = *sp++)
86
-
87
-#else
88
-#define PUSH16( data )\
89
-{\
90
-	int addr = (sp -= 2) - ram;\
91
-	if ( addr > 0x100 )\
92
-	{\
93
-		SET_LE16( sp, data );\
94
-	}\
95
-	else\
96
-	{\
97
-		ram [(uint8_t) addr + 0x100] = (uint8_t) data;\
98
-		sp [1] = (uint8_t) (data >> 8);\
99
-		sp += 0x100;\
100
-	}\
101
-}
102
-
103
-#define PUSH( data )\
104
-{\
105
-	*--sp = (uint8_t) (data);\
106
-	if ( sp - ram == 0x100 )\
107
-		sp += 0x100;\
108
-}
109
-
110
-#define POP( out )\
111
-{\
112
-	out = *sp++;\
113
-	if ( sp - ram == 0x201 )\
114
-	{\
115
-		out = sp [-0x101];\
116
-		sp -= 0x100;\
117
-	}\
118
-}
119
-
120
-#endif
121
-
122
-#define MEM_BIT( rel ) CPU_mem_bit( pc, rel_time + rel )
123
-
124
-unsigned SNES_SPC::CPU_mem_bit( uint8_t const* pc, rel_time_t rel_time )
19
+unsigned SNES_SPC::CPU_mem_bit(const uint8_t *pc, rel_time_t rel_time)
125 20
 {
126
-	unsigned addr = READ_PC16( pc );
127
-	unsigned t = READ( 0, addr & 0x1FFF ) >> (addr >> 13);
128
-	return t << 8 & 0x100;
21
+	unsigned addr = get_le16(pc);
22
+	unsigned t = this->cpu_read(addr & 0x1FFF, rel_time) >> (addr >> 13);
23
+	return (t << 8) & 0x100;
129 24
 }
130 25
 
131 26
 //// Status flag handling
132 27
 
133 28
 // Hex value in name to clarify code and bit shifting.
134 29
 // Flag stored in indicated variable during emulation
135
-int const n80 = 0x80; // nz
136
-int const v40 = 0x40; // psw
137
-int const p20 = 0x20; // dp
138
-int const b10 = 0x10; // psw
139
-int const h08 = 0x08; // psw
140
-int const i04 = 0x04; // psw
141
-int const z02 = 0x02; // nz
142
-int const c01 = 0x01; // c
143
-
144
-int const nz_neg_mask = 0x880; // either bit set indicates N flag set
145
-
146
-#define GET_PSW( out )\
147
-{\
148
-	out = psw & ~(n80 | p20 | z02 | c01);\
149
-	out |= c  >> 8 & c01;\
150
-	out |= dp >> 3 & p20;\
151
-	out |= ((nz >> 4) | nz) & n80;\
152
-	if ( !(uint8_t) nz ) out |= z02;\
153
-}
30
+const int n80 = 0x80; // nz
31
+const int v40 = 0x40; // psw
32
+const int p20 = 0x20; // dp
33
+const int b10 = 0x10; // psw
34
+const int h08 = 0x08; // psw
35
+const int i04 = 0x04; // psw
36
+const int z02 = 0x02; // nz
37
+const int c01 = 0x01; // c
154 38
 
155
-#define SET_PSW( in )\
156
-{\
157
-	psw = in;\
158
-	c   = in << 8;\
159
-	dp  = in << 3 & 0x100;\
160
-	nz  = (in << 4 & 0x800) | (~in & z02);\
161
-}
39
+const int nz_neg_mask = 0x880; // either bit set indicates N flag set
162 40
 
163 41
 SPC_CPU_RUN_FUNC
164 42
 {
165
-	uint8_t* const ram = RAM;
166
-	int a = m.cpu_regs.a;
167
-	int x = m.cpu_regs.x;
168
-	int y = m.cpu_regs.y;
169
-	uint8_t const* pc;
170
-	uint8_t* sp;
43
+	auto ram = this->m.ram.ram;
44
+	int a = this->m.cpu_regs.a;
45
+	int x = this->m.cpu_regs.x;
46
+	int y = this->m.cpu_regs.y;
47
+	const uint8_t *pc;
48
+	uint8_t *sp;
171 49
 	int psw;
172 50
 	int c;
173 51
 	int nz;
174 52
 	int dp;
175
-	
176
-	SET_PC( m.cpu_regs.pc );
177
-	SET_SP( m.cpu_regs.sp );
178
-	SET_PSW( m.cpu_regs.psw );
179
-	
53
+
54
+	// timers are by far the most common thing read from dp
55
+	auto CPU_READ_TIMER = [&](rel_time_t offset, int addr_) -> int
56
+	{
57
+		int out;
58
+		rel_time_t adj_time = rel_time + offset;
59
+		int dp_addr = addr_;
60
+		int ti = dp_addr - (r_t0out + 0xF0);
61
+		if (static_cast<unsigned>(ti) < timer_count)
62
+		{
63
+			auto t = &this->m.timers[ti];
64
+			if (adj_time >= t->next_time)
65
+				t = this->run_timer_(t, adj_time);
66
+			out = t->counter;
67
+			t->counter = 0;
68
+		}
69
+		else
70
+		{
71
+			out = ram[dp_addr];
72
+			int i = dp_addr - 0xF0;
73
+			if (static_cast<unsigned>(i) < 0x10)
74
+				out = this->cpu_read_smp_reg(i, adj_time);
75
+		}
76
+		return out;
77
+	};
78
+
79
+	auto DP_ADDR = [&](int addr) { return dp + addr; };
80
+
81
+	auto READ_PROG16 = [&](int addr) { return get_le16(ram + addr); };
82
+
83
+	auto SET_PC = [&](int n) { pc = ram + n; };
84
+	auto GET_PC = [&]() { return pc - ram; };
85
+
86
+	auto SET_SP = [&](int v) { sp = ram + 0x101 + v; };
87
+	auto GET_SP = [&]() { return sp - 0x101 - ram; };
88
+
89
+	auto PUSH16 = [&](int data)
90
+	{
91
+		sp -= 2;
92
+#if !SPC_NO_SP_WRAPAROUND
93
+		int addr = sp - ram;
94
+		if (addr > 0x100)
95
+#endif
96
+			set_le16(sp, data);
97
+#if !SPC_NO_SP_WRAPAROUND
98
+		else
99
+		{
100
+			ram[static_cast<uint8_t>(addr) + 0x100] = static_cast<uint8_t>(data);
101
+			sp[1] = static_cast<uint8_t>(data >> 8);
102
+			sp += 0x100;
103
+		}
104
+#endif
105
+	};
106
+	auto PUSH = [&](int data)
107
+	{
108
+		*--sp = static_cast<uint8_t>(data);
109
+#if !SPC_NO_SP_WRAPAROUND
110
+		if (sp - ram == 0x100)
111
+			sp += 0x100;
112
+#endif
113
+	};
114
+	auto POP = [&](int &out)
115
+	{
116
+		out = *sp++;
117
+#if !SPC_NO_SP_WRAPAROUND
118
+		if (sp - ram == 0x201)
119
+		{
120
+			out = sp[-0x101];
121
+			sp -= 0x100;
122
+		}
123
+#endif
124
+	};
125
+
126
+	auto MEM_BIT = [&](rel_time_t rel) { return this->CPU_mem_bit(pc, rel_time + rel); };
127
+
128
+	auto GET_PSW = [&](int &out)
129
+	{
130
+		out = psw & ~(n80 | p20 | z02 | c01);
131
+		out |= (c >> 8) & c01;
132
+		out |= (dp >> 3) & p20;
133
+		out |= ((nz >> 4) | nz) & n80;
134
+		if (!static_cast<uint8_t>(nz))
135
+			out |= z02;
136
+	};
137
+	auto SET_PSW = [&](int in)
138
+	{
139
+		psw = in;
140
+		c = in << 8;
141
+		dp = (in << 3) & 0x100;
142
+		nz = ((in << 4) & 0x800) | (~in & z02);
143
+	};
144
+
145
+	SET_PC(this->m.cpu_regs.pc);
146
+	SET_SP(this->m.cpu_regs.sp);
147
+	SET_PSW(this->m.cpu_regs.psw);
148
+
180 149
 	goto loop;
181
-	
182
-	
150
+
183 151
 	// Main loop
184
-	
152
+
185 153
 cbranch_taken_loop:
186
-	pc += *(BOOST::int8_t const*) pc;
154
+	pc += *reinterpret_cast<const int8_t *>(pc);
187 155
 inc_pc_loop:
188
-	pc++;
156
+	++pc;
189 157
 loop:
190 158
 {
191
-	unsigned opcode;
192 159
 	unsigned data;
193
-	
194
-	check( (unsigned) a < 0x100 );
195
-	check( (unsigned) x < 0x100 );
196
-	check( (unsigned) y < 0x100 );
197
-	
198
-	opcode = *pc;
199
-	if (allow_time_overflow && rel_time >= 0 )
160
+
161
+	unsigned opcode = *pc;
162
+	if (this->allow_time_overflow && rel_time >= 0)
200 163
 		goto stop;
201
-	if ( (rel_time += m.cycle_table [opcode]) > 0 && !allow_time_overflow)
164
+	if ((rel_time += this->m.cycle_table[opcode]) > 0 && !this->allow_time_overflow)
202 165
 		goto out_of_time;
203 166
 	
204
-	#ifdef SPC_CPU_OPCODE_HOOK
205
-		SPC_CPU_OPCODE_HOOK( GET_PC(), opcode );
206
-	#endif
167
+#ifdef SPC_CPU_OPCODE_HOOK
168
+	SPC_CPU_OPCODE_HOOK(GET_PC(), opcode);
169
+#endif
207 170
 	/*
208 171
 	//SUB_CASE_COUNTER( 1 );
209 172
 	#define PROFILE_TIMER_LOOP( op, addr, len )\
... ...
@@ -214,1015 +177,1001 @@ loop:
214 177
 		SUB_CASE_COUNTER( op && cond );\
215 178
 	}
216 179
 	
217
-	PROFILE_TIMER_LOOP( 0xEC, GET_LE16( pc + 1 ), 3 );
180
+	PROFILE_TIMER_LOOP( 0xEC, get_le16( pc + 1 ), 3 );
218 181
 	PROFILE_TIMER_LOOP( 0xEB, pc [1], 2 );
219 182
 	PROFILE_TIMER_LOOP( 0xE4, pc [1], 2 );
220 183
 	*/
221 184
 
222
-#ifdef DEBUGGER
223
-	if (debug_trace)
224
-		debug_do_trace(a, x, y, pc, sp, psw, c, nz, dp);
225
-#endif
226
-
227
-
228 185
 	// TODO: if PC is at end of memory, this will get wrong operand (very obscure)
229 186
 	data = *++pc;
230
-	switch ( opcode )
187
+	switch (opcode)
231 188
 	{
232
-	
233
-// Common instructions
234
-
235
-#define BRANCH( cond )\
236
-{\
237
-	pc++;\
238
-	pc += (BOOST::int8_t) data;\
239
-	if ( cond )\
240
-		goto loop;\
241
-	pc -= (BOOST::int8_t) data;\
242
-	rel_time -= 2;\
243
-	goto loop;\
189
+		// Common instructions
190
+
191
+#define BRANCH(cond) \
192
+{ \
193
+	++pc; \
194
+	pc += static_cast<int8_t>(data); \
195
+	if (cond) \
196
+		goto loop; \
197
+	pc -= static_cast<int8_t>(data); \
198
+	rel_time -= 2; \
199
+	goto loop; \
244 200
 }
245 201
 
246
-	case 0xF0: // BEQ
247
-		BRANCH( !(uint8_t) nz ) // 89% taken
248
-	
249
-	case 0xD0: // BNE
250
-		BRANCH( (uint8_t) nz )
251
-	
252
-	case 0x3F:{// CALL
253
-		int old_addr = GET_PC() + 2;
254
-		SET_PC( READ_PC16( pc ) );
255
-		PUSH16( old_addr );
256
-		goto loop;
257
-	}
258
-	
259
-	case 0x6F:// RET
260
-		#if SPC_NO_SP_WRAPAROUND
202
+		case 0xF0: // BEQ
203
+			BRANCH(!static_cast<uint8_t>(nz)) // 89% taken
204
+
205
+		case 0xD0: // BNE
206
+			BRANCH(static_cast<uint8_t>(nz))
207
+
208
+		case 0x3F: // CALL
261 209
 		{
262
-			SET_PC( GET_LE16( sp ) );
263
-			sp += 2;
210
+			int old_addr = GET_PC() + 2;
211
+			SET_PC(get_le16(pc));
212
+			PUSH16(old_addr);
213
+			goto loop;
264 214
 		}
265
-		#else
266
-		{
267
-			int addr = sp - ram;
268
-			SET_PC( GET_LE16( sp ) );
215
+
216
+		case 0x6F:// RET
217
+#if SPC_NO_SP_WRAPAROUND
218
+			SET_PC(get_le16(sp));
269 219
 			sp += 2;
270
-			if ( addr < 0x1FF )
271
-				goto loop;
272
-			
273
-			SET_PC( sp [-0x101] * 0x100 + ram [(uint8_t) addr + 0x100] );
274
-			sp -= 0x100;
275
-		}
276
-		#endif
277
-		goto loop;
278
-	
279
-	case 0xE4: // MOV a,dp
280
-		++pc;
281
-		// 80% from timer
282
-		READ_DP_TIMER( 0, data, a = nz );
283
-		goto loop;
284
-	
285
-	case 0xFA:{// MOV dp,dp
286
-		int temp;
287
-		READ_DP_TIMER( -2, data, temp );
288
-		data = temp + no_read_before_write ;
289
-	}
290
-	// fall through
291
-	case 0x8F:{// MOV dp,#imm
292
-		int temp = READ_PC( pc + 1 );
293
-		pc += 2;
294
-		
295
-		#if !SPC_MORE_ACCURACY
296
-		{
297
-			int i = dp + temp;
298
-			ram [i] = (uint8_t) data;
299
-			i -= 0xF0;
300
-			if ( (unsigned) i < 0x10 ) // 76%
220
+#else
301 221
 			{
302
-				REGS [i] = (uint8_t) data;
303
-				
304
-				// Registers other than $F2 and $F4-$F7
305
-				//if ( i != 2 && i != 4 && i != 5 && i != 6 && i != 7 )
306
-				if ( ((~0x2F00 << (bits_in_int - 16)) << i) < 0 ) // 12%
307
-					cpu_write_smp_reg( data, rel_time, i );
222
+				int addr = sp - ram;
223
+				SET_PC(get_le16(sp));
224
+				sp += 2;
225
+				if (addr < 0x1FF)
226
+					goto loop;
227
+
228
+				SET_PC(sp[-0x101] * 0x100 + ram[static_cast<uint8_t>(addr) + 0x100]);
229
+				sp -= 0x100;
308 230
 			}
231
+#endif
232
+			goto loop;
233
+
234
+		case 0xE4: // MOV a,dp
235
+			++pc;
236
+			// 80% from timer
237
+			a = nz = CPU_READ_TIMER(0, DP_ADDR(data));
238
+			goto loop;
239
+
240
+		case 0xFA: // MOV dp,dp
241
+		{
242
+			int temp = CPU_READ_TIMER(-2, DP_ADDR(data));
243
+			data = temp + no_read_before_write;
309 244
 		}
310
-		#else
311
-			WRITE_DP( 0, temp, data );
312
-		#endif
313
-		goto loop;
314
-	}
315
-	
316
-	case 0xC4: // MOV dp,a
317
-		++pc;
318
-		#if !SPC_MORE_ACCURACY
245
+		// fall through
246
+		case 0x8F: // MOV dp,#imm
319 247
 		{
320
-			int i = dp + data;
321
-			ram [i] = (uint8_t) a;
322
-			i -= 0xF0;
323
-			if ( (unsigned) i < 0x10 ) // 39%
248
+			int temp = *(pc + 1);
249
+			pc += 2;
324 250
 			{
325
-				unsigned sel = i - 2;
326
-				REGS [i] = (uint8_t) a;
327
-				
328
-				if ( sel == 1 ) // 51% $F3
329
-					dsp_write( a, rel_time );
330
-				else if ( sel > 1 ) // 1% not $F2 or $F3
331
-					cpu_write_smp_reg_( a, rel_time, i );
251
+				int i = dp + temp;
252
+				ram[i] = static_cast<uint8_t>(data);
253
+				i -= 0xF0;
254
+				if (static_cast<unsigned>(i) < 0x10) // 76%
255
+				{
256
+					this->m.smp_regs[0][i] = static_cast<uint8_t>(data);
257
+
258
+					// Registers other than $F2 and $F4-$F7
259
+					//if ( i != 2 && i != 4 && i != 5 && i != 6 && i != 7 )
260
+					if (((~0x2F00 << (bits_in_int - 16)) << i) < 0) // 12%
261
+						this->cpu_write_smp_reg(data, rel_time, i);
262
+				}
332 263
 			}
264
+			goto loop;
333 265
 		}
334
-		#else
335
-			WRITE_DP( 0, data, a );
336
-		#endif
337
-		goto loop;
338
-	
339
-#define CASE( n )   case n:
266
+
267
+		case 0xC4: // MOV dp,a
268
+			++pc;
269
+			{
270
+				int i = dp + data;
271
+				ram [i] = static_cast<uint8_t>(a);
272
+				i -= 0xF0;
273
+				if (static_cast<unsigned>(i) < 0x10) // 39%
274
+				{
275
+					unsigned sel = i - 2;
276
+					this->m.smp_regs[0][i] = static_cast<uint8_t>(a);
277
+
278
+					if (sel == 1) // 51% $F3
279
+						this->dsp_write(a, rel_time);
280
+					else if (sel > 1) // 1% not $F2 or $F3
281
+						this->cpu_write_smp_reg_(a, rel_time, i);
282
+				}
283
+			}
284
+			goto loop;
285
+
286
+#define CASE(n) case n:
340 287
 
341 288
 // Define common address modes based on opcode for immediate mode. Execution
342 289
 // ends with data set to the address of the operand.
343
-#define ADDR_MODES_( op )\
344
-	CASE( op - 0x02 ) /* (X) */\
345
-		data = x + dp;\
346
-		pc--;\
347
-		goto end_##op;\
348
-	CASE( op + 0x0F ) /* (dp)+Y */\
349
-		data = READ_PROG16( data + dp ) + y;\
350
-		goto end_##op;\
351
-	CASE( op - 0x01 ) /* (dp+X) */\
352
-		data = READ_PROG16( ((uint8_t) (data + x)) + dp );\
353
-		goto end_##op;\
354
-	CASE( op + 0x0E ) /* abs+Y */\
355
-		data += y;\
356
-		goto abs_##op;\
357
-	CASE( op + 0x0D ) /* abs+X */\
358
-		data += x;\
359
-	CASE( op - 0x03 ) /* abs */\
360
-	abs_##op:\
361
-		data += 0x100 * READ_PC( ++pc );\
362
-		goto end_##op;\
363
-	CASE( op + 0x0C ) /* dp+X */\
364
-		data = (uint8_t) (data + x);
365
-
366
-#define ADDR_MODES_NO_DP( op )\
367
-	ADDR_MODES_( op )\
368
-		data += dp;\
290
+#define ADDR_MODES_(op) \
291
+	CASE(op - 0x02) /* (X) */ \
292
+		data = x + dp; \
293
+		--pc; \
294
+		goto end_##op; \
295
+	CASE(op + 0x0F) /* (dp)+Y */ \
296
+		data = READ_PROG16(data + dp) + y; \
297
+		goto end_##op; \
298
+	CASE(op - 0x01) /* (dp+X) */ \
299
+		data = READ_PROG16(static_cast<uint8_t>(data + x) + dp); \
300
+		goto end_##op; \
301
+	CASE(op + 0x0E) /* abs+Y */ \
302
+		data += y; \
303
+		goto abs_##op; \
304
+	CASE(op + 0x0D) /* abs+X */ \
305
+		data += x; \
306
+	CASE(op - 0x03) /* abs */ \
307
+	abs_##op: \
308
+		data += 0x100 * *(++pc); \
309
+		goto end_##op; \
310
+	CASE(op + 0x0C) /* dp+X */ \
311
+		data = static_cast<uint8_t>(data + x);
312
+
313
+#define ADDR_MODES_NO_DP(op) \
314
+	ADDR_MODES_(op) \
315
+		data += dp; \
369 316
 	end_##op:
370 317
 
371
-#define ADDR_MODES( op )\
372
-	ADDR_MODES_( op )\
373
-	CASE( op - 0x04 ) /* dp */\
374
-		data += dp;\
318
+#define ADDR_MODES(op) \
319
+	ADDR_MODES_(op) \
320
+	CASE(op - 0x04) /* dp */ \
321
+		data += dp; \
375 322
 	end_##op:
376 323
 
377
-// 1. 8-bit Data Transmission Commands. Group I
324
+		// 1. 8-bit Data Transmission Commands. Group I
378 325
 
379
-	ADDR_MODES_NO_DP( 0xE8 ) // MOV A,addr
380
-		a = nz = READ( 0, data );
381
-		goto inc_pc_loop;
382
-	
383
-	case 0xBF:{// MOV A,(X)+
384
-		int temp = x + dp;
385
-		x = (uint8_t) (x + 1);
386
-		a = nz = READ( -1, temp );
387
-		goto loop;
388
-	}
389
-	
390
-	case 0xE8: // MOV A,imm
391
-		a  = data;
392
-		nz = data;
393
-		goto inc_pc_loop;
394
-	
395
-	case 0xF9: // MOV X,dp+Y
396
-		data = (uint8_t) (data + y);
397
-	case 0xF8: // MOV X,dp
398
-		READ_DP_TIMER( 0, data, x = nz );
399
-		goto inc_pc_loop;
400
-	
401
-	case 0xE9: // MOV X,abs
402
-		data = READ_PC16( pc );
403
-		++pc;
404
-		data = READ( 0, data );
405
-	case 0xCD: // MOV X,imm
406
-		x  = data;
407
-		nz = data;
408
-		goto inc_pc_loop;
409
-	
410
-	case 0xFB: // MOV Y,dp+X
411
-		data = (uint8_t) (data + x);
412
-	case 0xEB: // MOV Y,dp
413
-		// 70% from timer
414
-		pc++;
415
-		READ_DP_TIMER( 0, data, y = nz );
416
-		goto loop;
417
-	
418
-	case 0xEC:{// MOV Y,abs
419
-		int temp = READ_PC16( pc );
420
-		pc += 2;
421
-		READ_TIMER( 0, temp, y = nz );
422
-		//y = nz = READ( 0, temp );
423
-		goto loop;
424
-	}
425
-	
426
-	case 0x8D: // MOV Y,imm
427
-		y  = data;
428
-		nz = data;
429
-		goto inc_pc_loop;
430
-	
431
-// 2. 8-BIT DATA TRANSMISSION COMMANDS, GROUP 2
326
+		ADDR_MODES_NO_DP(0xE8) // MOV A,addr
327
+			a = nz = this->cpu_read(data, rel_time);
328
+			goto inc_pc_loop;
432 329
 
433
-	ADDR_MODES_NO_DP( 0xC8 ) // MOV addr,A
434
-		WRITE( 0, data, a );
435
-		goto inc_pc_loop;
436
-	
437
-	{
438
-		int temp;
439
-	case 0xCC: // MOV abs,Y
440
-		temp = y;
441
-		goto mov_abs_temp;
442
-	case 0xC9: // MOV abs,X
443
-		temp = x;
444
-	mov_abs_temp:
445
-		WRITE( 0, READ_PC16( pc ), temp );
446
-		pc += 2;
447
-		goto loop;
448
-	}
449
-	
450
-	case 0xD9: // MOV dp+Y,X
451
-		data = (uint8_t) (data + y);
452
-	case 0xD8: // MOV dp,X
453
-		WRITE( 0, data + dp, x );
454
-		goto inc_pc_loop;
455
-	
456
-	case 0xDB: // MOV dp+X,Y
457
-		data = (uint8_t) (data + x);
458
-	case 0xCB: // MOV dp,Y
459
-		WRITE( 0, data + dp, y );
460
-		goto inc_pc_loop;
330
+		case 0xBF: // MOV A,(X)+
331
+		{
332
+			int temp = x + dp;
333
+			x = static_cast<uint8_t>(x + 1);
334
+			a = nz = this->cpu_read(temp, rel_time - 1);
335
+			goto loop;
336
+		}
461 337
 
462
-// 3. 8-BIT DATA TRANSMISSIN COMMANDS, GROUP 3.
463
-	
464
-	case 0x7D: // MOV A,X
465
-		a  = x;
466
-		nz = x;
467
-		goto loop;
468
-	
469
-	case 0xDD: // MOV A,Y
470
-		a  = y;
471
-		nz = y;
472
-		goto loop;
473
-	
474
-	case 0x5D: // MOV X,A
475
-		x  = a;
476
-		nz = a;
477
-		goto loop;
478
-	
479
-	case 0xFD: // MOV Y,A
480
-		y  = a;
481
-		nz = a;
482
-		goto loop;
483
-	
484
-	case 0x9D: // MOV X,SP
485
-		x = nz = GET_SP();
486
-		goto loop;
487
-	
488
-	case 0xBD: // MOV SP,X
489
-		SET_SP( x );
490
-		goto loop;
491
-	
492
-	//case 0xC6: // MOV (X),A (handled by MOV addr,A in group 2)
493
-	
494
-	case 0xAF: // MOV (X)+,A
495
-		WRITE_DP( 0, x, a + no_read_before_write  );
496
-		x++;
497
-		goto loop;
498
-	
499
-// 5. 8-BIT LOGIC OPERATION COMMANDS
500
-	
501
-#define LOGICAL_OP( op, func )\
502
-	ADDR_MODES( op ) /* addr */\
503
-		data = READ( 0, data );\
504
-	case op: /* imm */\
505
-		nz = a func##= data;\
506
-		goto inc_pc_loop;\
507
-	{   unsigned addr;\
508
-	case op + 0x11: /* X,Y */\
509
-		data = READ_DP( -2, y );\
510
-		addr = x + dp;\
511
-		goto addr_##op;\
512
-	case op + 0x01: /* dp,dp */\
513
-		data = READ_DP( -3, data );\
514
-	case op + 0x10:{/*dp,imm*/\
515
-		uint8_t const* addr2 = pc + 1;\
516
-		pc += 2;\
517
-		addr = READ_PC( addr2 ) + dp;\
518
-	}\
519
-	addr_##op:\
520
-		nz = data func READ( -1, addr );\
521
-		WRITE( 0, addr, nz );\
522
-		goto loop;\
523
-	}
524
-	
525
-	LOGICAL_OP( 0x28, & ); // AND
526
-	
527
-	LOGICAL_OP( 0x08, | ); // OR
528
-	
529
-	LOGICAL_OP( 0x48, ^ ); // EOR
530
-	
531
-// 4. 8-BIT ARITHMETIC OPERATION COMMANDS
532
-
533
-	ADDR_MODES( 0x68 ) // CMP addr
534
-		data = READ( 0, data );
535
-	case 0x68: // CMP imm
536
-		nz = a - data;
537
-		c = ~nz;
538
-		nz &= 0xFF;
539
-		goto inc_pc_loop;
540
-	
541
-	case 0x79: // CMP (X),(Y)
542
-		data = READ_DP( -2, y );
543
-		nz = READ_DP( -1, x ) - data;
544
-		c = ~nz;
545
-		nz &= 0xFF;
546
-		goto loop;
547
-	
548
-	case 0x69: // CMP dp,dp
549
-		data = READ_DP( -3, data );
550
-	case 0x78: // CMP dp,imm
551
-		nz = READ_DP( -1, READ_PC( ++pc ) ) - data;
552
-		c = ~nz;
553
-		nz &= 0xFF;
554
-		goto inc_pc_loop;
555
-	
556
-	case 0x3E: // CMP X,dp
557
-		data += dp;
558
-		goto cmp_x_addr;
559
-	case 0x1E: // CMP X,abs
560
-		data = READ_PC16( pc );
561
-		pc++;
562
-	cmp_x_addr:
563
-		data = READ( 0, data );
564
-	case 0xC8: // CMP X,imm
565
-		nz = x - data;
566
-		c = ~nz;
567
-		nz &= 0xFF;
568
-		goto inc_pc_loop;
569
-	
570
-	case 0x7E: // CMP Y,dp
571
-		data += dp;
572
-		goto cmp_y_addr;
573
-	case 0x5E: // CMP Y,abs
574
-		data = READ_PC16( pc );
575
-		pc++;
576
-	cmp_y_addr:
577
-		data = READ( 0, data );
578
-	case 0xAD: // CMP Y,imm
579
-		nz = y - data;
580
-		c = ~nz;
581
-		nz &= 0xFF;
582
-		goto inc_pc_loop;
583
-	
584
-	{
585
-		int addr;
586
-	case 0xB9: // SBC (x),(y)
587
-	case 0x99: // ADC (x),(y)
588
-		pc--; // compensate for inc later
589
-		data = READ_DP( -2, y );
590
-		addr = x + dp;
591
-		goto adc_addr;
592
-	case 0xA9: // SBC dp,dp
593
-	case 0x89: // ADC dp,dp
594
-		data = READ_DP( -3, data );
595
-	case 0xB8: // SBC dp,imm
596
-	case 0x98: // ADC dp,imm
597
-		addr = READ_PC( ++pc ) + dp;
598
-	adc_addr:
599
-		nz = READ( -1, addr );
600
-		goto adc_data;
601
-		
602
-// catch ADC and SBC together, then decode later based on operand
338
+		case 0xE8: // MOV A,imm
339
+			a  = data;
340
+			nz = data;
341
+			goto inc_pc_loop;
342
+
343
+		case 0xF9: // MOV X,dp+Y
344
+			data = static_cast<uint8_t>(data + y);
345
+		case 0xF8: // MOV X,dp
346
+			x = nz = CPU_READ_TIMER(0, DP_ADDR(data));
347
+			goto inc_pc_loop;
348
+
349
+		case 0xE9: // MOV X,abs
350
+			data = get_le16(pc);
351
+			++pc;
352
+			data = this->cpu_read(data, rel_time);
353
+		case 0xCD: // MOV X,imm
354
+			x  = data;
355
+			nz = data;
356
+			goto inc_pc_loop;
357
+
358
+		case 0xFB: // MOV Y,dp+X
359
+			data = static_cast<uint8_t>(data + x);
360
+		case 0xEB: // MOV Y,dp
361
+			// 70% from timer
362
+			++pc;
363
+			y = nz = CPU_READ_TIMER(0, DP_ADDR(data));
364
+			goto loop;
365
+
366
+		case 0xEC: // MOV Y,abs
367
+		{
368
+			int temp = get_le16(pc);
369
+			pc += 2;
370
+			y = nz = CPU_READ_TIMER(0, temp);
371
+			//y = nz = this->cpu_read(temp, rel_time);
372
+			goto loop;
373
+		}
374
+
375
+		case 0x8D: // MOV Y,imm
376
+			y  = data;
377
+			nz = data;
378
+			goto inc_pc_loop;
379
+
380
+		// 2. 8-BIT DATA TRANSMISSION COMMANDS, GROUP 2
381
+
382
+		ADDR_MODES_NO_DP(0xC8) // MOV addr,A
383
+			this->cpu_write(a, data, rel_time);
384
+			goto inc_pc_loop;
385
+
386
+		{
387
+			int temp;
388
+			case 0xCC: // MOV abs,Y
389
+				temp = y;
390
+				goto mov_abs_temp;
391
+			case 0xC9: // MOV abs,X
392
+				temp = x;
393
+			mov_abs_temp:
394
+				this->cpu_write(temp, get_le16(pc), rel_time);
395
+				pc += 2;
396
+				goto loop;
397
+		}
398
+
399
+		case 0xD9: // MOV dp+Y,X
400
+			data = static_cast<uint8_t>(data + y);
401
+		case 0xD8: // MOV dp,X
402
+			this->cpu_write(x, data + dp, rel_time);
403
+			goto inc_pc_loop;
404
+
405
+		case 0xDB: // MOV dp+X,Y
406
+			data = static_cast<uint8_t>(data + x);
407
+		case 0xCB: // MOV dp,Y
408
+			this->cpu_write(y, data + dp, rel_time);
409
+			goto inc_pc_loop;
410
+
411
+		// 3. 8-BIT DATA TRANSMISSIN COMMANDS, GROUP 3.
412
+
413
+		case 0x7D: // MOV A,X
414
+			a  = x;
415
+			nz = x;
416
+			goto loop;
417
+
418
+		case 0xDD: // MOV A,Y
419
+			a  = y;
420
+			nz = y;
421
+			goto loop;
422
+
423
+		case 0x5D: // MOV X,A
424
+			x  = a;
425
+			nz = a;
426
+			goto loop;
427
+
428
+		case 0xFD: // MOV Y,A
429
+			y  = a;
430
+			nz = a;
431
+			goto loop;
432
+
433
+		case 0x9D: // MOV X,SP
434
+			x = nz = GET_SP();
435
+			goto loop;
436
+
437
+		case 0xBD: // MOV SP,X
438
+			SET_SP(x);
439
+			goto loop;
440
+
441
+		//case 0xC6: // MOV (X),A (handled by MOV addr,A in group 2)
442
+
443
+		case 0xAF: // MOV (X)+,A
444
+			this->cpu_write(a + no_read_before_write, DP_ADDR(x), rel_time);
445
+			++x;
446
+			goto loop;
447
+
448
+		// 5. 8-BIT LOGIC OPERATION COMMANDS
449
+
450
+#define LOGICAL_OP(op, func) \
451
+	ADDR_MODES(op) /* addr */ \
452
+		data = this->cpu_read(data, rel_time); \
453
+	case op: /* imm */ \
454
+		nz = a func##= data; \
455
+		goto inc_pc_loop; \
456
+		{ \
457
+			unsigned addr; \
458
+			case op + 0x11: /* X,Y */ \
459
+				data = this->cpu_read(DP_ADDR(y), rel_time - 2); \
460
+				addr = x + dp; \
461
+				goto addr_##op; \
462
+			case op + 0x01: /* dp,dp */ \
463
+				data = this->cpu_read(DP_ADDR(data), rel_time - 3); \
464
+			case op + 0x10: /*dp,imm*/ \
465
+			{ \
466
+				auto addr2 = pc + 1; \
467
+				pc += 2; \
468
+				addr = *addr2 + dp; \
469
+			} \
470
+			addr_##op: \
471
+				nz = data func this->cpu_read(addr, rel_time - 1); \
472
+				this->cpu_write(nz, addr, rel_time); \
473
+				goto loop; \
474
+		}
475
+
476
+		LOGICAL_OP(0x28, &); // AND
477
+
478
+		LOGICAL_OP(0x08, |); // OR
479
+
480
+		LOGICAL_OP(0x48, ^); // EOR
481
+
482
+		// 4. 8-BIT ARITHMETIC OPERATION COMMANDS
483
+
484
+		ADDR_MODES(0x68) // CMP addr
485
+			data = this->cpu_read(data, rel_time);
486
+		case 0x68: // CMP imm
487
+			nz = a - data;
488
+			c = ~nz;
489
+			nz &= 0xFF;
490
+			goto inc_pc_loop;
491
+
492
+		case 0x79: // CMP (X),(Y)
493
+			data = this->cpu_read(DP_ADDR(y), rel_time - 2);
494
+			nz = this->cpu_read(DP_ADDR(x), rel_time - 1) - data;
495
+			c = ~nz;
496
+			nz &= 0xFF;
497
+			goto loop;
498
+
499
+		case 0x69: // CMP dp,dp
500
+			data = this->cpu_read(DP_ADDR(data), rel_time - 3);
501
+		case 0x78: // CMP dp,imm
502
+			nz = this->cpu_read(DP_ADDR(*(++pc)), rel_time - 1) - data;
503
+			c = ~nz;
504
+			nz &= 0xFF;
505
+			goto inc_pc_loop;
506
+
507
+		case 0x3E: // CMP X,dp
508
+			data += dp;
509
+			goto cmp_x_addr;
510
+		case 0x1E: // CMP X,abs
511
+			data = get_le16(pc);
512
+			++pc;
513
+		cmp_x_addr:
514
+			data = this->cpu_read(data, rel_time);
515
+		case 0xC8: // CMP X,imm
516
+			nz = x - data;
517
+			c = ~nz;
518
+			nz &= 0xFF;
519
+			goto inc_pc_loop;
520
+
521
+		case 0x7E: // CMP Y,dp
522
+			data += dp;
523
+			goto cmp_y_addr;
524
+		case 0x5E: // CMP Y,abs
525
+			data = get_le16(pc);
526
+			++pc;
527
+		cmp_y_addr:
528
+			data = this->cpu_read(data, rel_time);
529
+		case 0xAD: // CMP Y,imm
530
+			nz = y - data;
531
+			c = ~nz;
532
+			nz &= 0xFF;
533
+			goto inc_pc_loop;
534
+
535
+		{
536
+			int addr;
537
+			case 0xB9: // SBC (x),(y)
538
+			case 0x99: // ADC (x),(y)
539
+				--pc; // compensate for inc later
540
+				data = this->cpu_read(DP_ADDR(y), rel_time - 2);
541
+				addr = x + dp;
542
+				goto adc_addr;
543
+			case 0xA9: // SBC dp,dp
544
+			case 0x89: // ADC dp,dp
545
+				data = this->cpu_read(DP_ADDR(data), rel_time - 3);
546
+			case 0xB8: // SBC dp,imm
547
+			case 0x98: // ADC dp,imm
548
+				addr = *(++pc) + dp;
549
+			adc_addr:
550
+				nz = this->cpu_read(addr, rel_time - 1);
551
+				goto adc_data;
552
+
553
+			// catch ADC and SBC together, then decode later based on operand
603 554
 #undef CASE
604
-#define CASE( n ) case n: case (n) + 0x20:
605
-	ADDR_MODES( 0x88 ) // ADC/SBC addr
606
-		data = READ( 0, data );
607
-	case 0xA8: // SBC imm
608
-	case 0x88: // ADC imm
609
-		addr = -1; // A
610
-		nz = a;
611
-	adc_data: {
612
-		int flags;
613
-		if ( opcode >= 0xA0 ) // SBC
614
-			data ^= 0xFF;
615
-		
616
-		flags = data ^ nz;
617
-		nz += data + (c >> 8 & 1);
618
-		flags ^= nz;
619
-		
620
-		psw = (psw & ~(v40 | h08)) |
621
-				(flags >> 1 & h08) |
622
-				((flags + 0x80) >> 2 & v40);
623
-		c = nz;
624
-		if ( addr < 0 )
555
+#define CASE(n) case n: case (n) + 0x20:
556
+				ADDR_MODES(0x88) // ADC/SBC addr
557
+				data = this->cpu_read(data, rel_time);
558
+			case 0xA8: // SBC imm
559
+			case 0x88: // ADC imm
560
+				addr = -1; // A
561
+				nz = a;
562
+			adc_data:
563
+			{
564
+				int flags;
565
+				if (opcode >= 0xA0) // SBC
566
+					data ^= 0xFF;
567
+
568
+				flags = data ^ nz;
569
+				nz += data + (c >> 8 & 1);
570
+				flags ^= nz;
571
+
572
+				psw = (psw & ~(v40 | h08)) | ((flags >> 1) & h08) | (((flags + 0x80) >> 2) & v40);
573
+				c = nz;
574
+				if (addr < 0)
575
+				{
576
+					a = static_cast<uint8_t>(nz);
577
+					goto inc_pc_loop;
578
+				}
579
+				this->cpu_write(/*(uint8_t)*/nz, addr, rel_time);
580
+				goto inc_pc_loop;
581
+			}
582
+		}
583
+
584
+		// 6. ADDITION & SUBTRACTION COMMANDS
585
+
586
+#define INC_DEC_REG(reg, op) \
587
+	nz = reg op; \
588
+	reg = static_cast<uint8_t>(nz); \
589
+	goto loop;
590
+
591
+		case 0xBC: INC_DEC_REG(a, + 1) // INC A
592
+		case 0x3D: INC_DEC_REG(x, + 1) // INC X
593
+		case 0xFC: INC_DEC_REG(y, + 1) // INC Y
594
+
595
+		case 0x9C: INC_DEC_REG(a, - 1) // DEC A
596
+		case 0x1D: INC_DEC_REG(x, - 1) // DEC X
597
+		case 0xDC: INC_DEC_REG(y, - 1) // DEC Y
598
+
599
+		case 0x9B: // DEC dp+X
600
+		case 0xBB: // INC dp+X
601
+			data = static_cast<uint8_t>(data + x);
602
+		case 0x8B: // DEC dp
603
+		case 0xAB: // INC dp
604
+			data += dp;
605
+			goto inc_abs;
606
+		case 0x8C: // DEC abs
607
+		case 0xAC: // INC abs
608
+			data = get_le16(pc);
609
+			++pc;
610
+		inc_abs:
611
+			nz = ((opcode >> 4) & 2) - 1;
612
+			nz += this->cpu_read(data, rel_time - 1);
613
+			this->cpu_write(/*(uint8_t)*/ nz, data, rel_time);
614
+			goto inc_pc_loop;
615
+
616
+		// 7. SHIFT, ROTATION COMMANDS
617
+
618
+		case 0x5C: // LSR A
619
+			c = 0;
620
+		case 0x7C: // ROR A
621
+		{
622
+			nz = ((c >> 1) & 0x80) | (a >> 1);
623
+			c = a << 8;
624
+			a = nz;
625
+			goto loop;
626
+		}
627
+
628
+		case 0x1C: // ASL A
629
+			c = 0;
630
+		case 0x3C: // ROL A
631
+		{
632
+			int temp = c >> 8 & 1;
633
+			c = a << 1;
634
+			nz = c | temp;
635
+			a = static_cast<uint8_t>(nz);
636
+			goto loop;
637
+		}
638
+
639
+		case 0x0B: // ASL dp
640
+			c = 0;
641
+			data += dp;
642
+			goto rol_mem;
643
+		case 0x1B: // ASL dp+X
644
+			c = 0;
645
+		case 0x3B: // ROL dp+X
646
+			data = static_cast<uint8_t>(data + x);
647
+		case 0x2B: // ROL dp
648
+			data += dp;
649
+			goto rol_mem;
650
+		case 0x0C: // ASL abs
651
+			c = 0;
652
+		case 0x2C: // ROL abs
653
+			data = get_le16(pc);
654
+			++pc;
655
+		rol_mem:
656
+			nz = c >> 8 & 1;
657
+			nz |= (c = this->cpu_read(data, rel_time - 1) << 1);
658
+			this->cpu_write(/*(uint8_t)*/ nz, data, rel_time);
659
+			goto inc_pc_loop;
660
+
661
+		case 0x4B: // LSR dp
662
+			c = 0;
663
+			data += dp;
664
+			goto ror_mem;
665
+		case 0x5B: // LSR dp+X
666
+			c = 0;
667
+		case 0x7B: // ROR dp+X
668
+			data = static_cast<uint8_t>(data + x);
669
+		case 0x6B: // ROR dp
670
+			data += dp;
671
+			goto ror_mem;
672
+		case 0x4C: // LSR abs
673
+			c = 0;
674
+		case 0x6C: // ROR abs
675
+			data = get_le16(pc);
676
+			++pc;
677
+		ror_mem:
625 678
 		{
626
-			a = (uint8_t) nz;
679
+			int temp = this->cpu_read(data, rel_time - 1);
680
+			nz = (c >> 1 & 0x80) | (temp >> 1);
681
+			c = temp << 8;
682
+			this->cpu_write(nz, data, rel_time);
627 683
 			goto inc_pc_loop;
628 684
 		}
629
-		WRITE( 0, addr, /*(uint8_t)*/ nz );
630
-		goto inc_pc_loop;
631
-	}
632
-	
633
-	}
634
-	
635
-// 6. ADDITION & SUBTRACTION COMMANDS
636 685
 
637
-#define INC_DEC_REG( reg, op )\
638
-		nz  = reg op;\
639
-		reg = (uint8_t) nz;\
640
-		goto loop;
686
+		case 0x9F: // XCN
687
+			nz = a = (a >> 4) | static_cast<uint8_t>(a << 4);
688
+			goto loop;
641 689
 
642
-	case 0xBC: INC_DEC_REG( a, + 1 ) // INC A
643
-	case 0x3D: INC_DEC_REG( x, + 1 ) // INC X
644
-	case 0xFC: INC_DEC_REG( y, + 1 ) // INC Y
645
-	
646
-	case 0x9C: INC_DEC_REG( a, - 1 ) // DEC A
647
-	case 0x1D: INC_DEC_REG( x, - 1 ) // DEC X
648
-	case 0xDC: INC_DEC_REG( y, - 1 ) // DEC Y
649
-
650
-	case 0x9B: // DEC dp+X
651
-	case 0xBB: // INC dp+X
652
-		data = (uint8_t) (data + x);
653
-	case 0x8B: // DEC dp
654
-	case 0xAB: // INC dp
655
-		data += dp;
656
-		goto inc_abs;
657
-	case 0x8C: // DEC abs
658
-	case 0xAC: // INC abs
659
-		data = READ_PC16( pc );
660
-		pc++;
661
-	inc_abs:
662
-		nz = (opcode >> 4 & 2) - 1;
663
-		nz += READ( -1, data );
664
-		WRITE( 0, data, /*(uint8_t)*/ nz );
665
-		goto inc_pc_loop;
666
-	
667
-// 7. SHIFT, ROTATION COMMANDS
668
-
669
-	case 0x5C: // LSR A
670
-		c = 0;
671
-	case 0x7C:{// ROR A
672
-		nz = (c >> 1 & 0x80) | (a >> 1);
673
-		c = a << 8;
674
-		a = nz;
675
-		goto loop;
676
-	}
677
-	
678
-	case 0x1C: // ASL A
679
-		c = 0;
680
-	case 0x3C:{// ROL A
681
-		int temp = c >> 8 & 1;
682
-		c = a << 1;
683
-		nz = c | temp;
684
-		a = (uint8_t) nz;
685
-		goto loop;
686
-	}
687
-	
688
-	case 0x0B: // ASL dp
689
-		c = 0;
690
-		data += dp;
691
-		goto rol_mem;
692
-	case 0x1B: // ASL dp+X
693
-		c = 0;
694
-	case 0x3B: // ROL dp+X
695
-		data = (uint8_t) (data + x);
696
-	case 0x2B: // ROL dp
697
-		data += dp;
698
-		goto rol_mem;
699
-	case 0x0C: // ASL abs
700
-		c = 0;
701
-	case 0x2C: // ROL abs
702
-		data = READ_PC16( pc );
703
-		pc++;
704
-	rol_mem:
705
-		nz = c >> 8 & 1;
706
-		nz |= (c = READ( -1, data ) << 1);
707
-		WRITE( 0, data, /*(uint8_t)*/ nz );
708
-		goto inc_pc_loop;
709
-	
710
-	case 0x4B: // LSR dp
711
-		c = 0;
712
-		data += dp;
713
-		goto ror_mem;
714
-	case 0x5B: // LSR dp+X
715
-		c = 0;
716
-	case 0x7B: // ROR dp+X
717
-		data = (uint8_t) (data + x);
718
-	case 0x6B: // ROR dp
719
-		data += dp;
720
-		goto ror_mem;
721
-	case 0x4C: // LSR abs
722
-		c = 0;
723
-	case 0x6C: // ROR abs
724
-		data = READ_PC16( pc );
725
-		pc++;
726
-	ror_mem: {
727
-		int temp = READ( -1, data );
728
-		nz = (c >> 1 & 0x80) | (temp >> 1);
729
-		c = temp << 8;
730
-		WRITE( 0, data, nz );
731
-		goto inc_pc_loop;
732
-	}
690
+		// 8. 16-BIT TRANSMISION COMMANDS
733 691
 
734
-	case 0x9F: // XCN
735
-		nz = a = (a >> 4) | (uint8_t) (a << 4);
736
-		goto loop;
692
+		case 0xBA: // MOVW YA,dp
693
+			a = this->cpu_read(DP_ADDR(data), rel_time - 2);
694
+			nz = (a & 0x7F) | (a >> 1);
695
+			y = this->cpu_read(DP_ADDR(static_cast<uint8_t>(data + 1)), rel_time);
696
+			nz |= y;
697
+			goto inc_pc_loop;
737 698
 
738
-// 8. 16-BIT TRANSMISION COMMANDS
699
+		case 0xDA: // MOVW dp,YA
700
+			this->cpu_write(a, DP_ADDR(data), rel_time - 1);
701
+			this->cpu_write(y + no_read_before_write, DP_ADDR(static_cast<uint8_t>(data + 1)), rel_time);
702
+			goto inc_pc_loop;
739 703
 
740
-	case 0xBA: // MOVW YA,dp
741
-		a = READ_DP( -2, data );
742
-		nz = (a & 0x7F) | (a >> 1);
743
-		y = READ_DP( 0, (uint8_t) (data + 1) );
744
-		nz |= y;
745
-		goto inc_pc_loop;
746
-	
747
-	case 0xDA: // MOVW dp,YA
748
-		WRITE_DP( -1, data, a );
749
-		WRITE_DP( 0, (uint8_t) (data + 1), y + no_read_before_write  );
750
-		goto inc_pc_loop;
751
-	
752
-// 9. 16-BIT OPERATION COMMANDS
704
+		// 9. 16-BIT OPERATION COMMANDS
753 705
 
754
-	case 0x3A: // INCW dp
755
-	case 0x1A:{// DECW dp
756
-		int temp;
757
-		// low byte
758
-		data += dp;
759
-		temp = READ( -3, data );
760
-		temp += (opcode >> 4 & 2) - 1; // +1 for INCW, -1 for DECW
761
-		nz = ((temp >> 1) | temp) & 0x7F;
762
-		WRITE( -2, data, /*(uint8_t)*/ temp );
763
-		
764
-		// high byte
765
-		data = (uint8_t) (data + 1) + dp;
766
-		temp = (uint8_t) ((temp >> 8) + READ( -1, data ));
767
-		nz |= temp;
768
-		WRITE( 0, data, temp );
769
-		
770
-		goto inc_pc_loop;
771
-	}
772
-		
773
-	case 0x7A: // ADDW YA,dp
774
-	case 0x9A:{// SUBW YA,dp
775
-		int lo = READ_DP( -2, data );
776
-		int hi = READ_DP( 0, (uint8_t) (data + 1) );
777
-		int result;
778
-		int flags;
779
-		
780
-		if ( opcode == 0x9A ) // SUBW
706
+		case 0x3A: // INCW dp
707
+		case 0x1A: // DECW dp
781 708
 		{
782
-			lo = (lo ^ 0xFF) + 1;
783
-			hi ^= 0xFF;
709
+			int temp;
710
+			// low byte
711
+			data += dp;
712
+			temp = this->cpu_read(data, rel_time - 3);
713
+			temp += (opcode >> 4 & 2) - 1; // +1 for INCW, -1 for DECW
714
+			nz = ((temp >> 1) | temp) & 0x7F;
715
+			this->cpu_write(/*(uint8_t)*/ temp, data, rel_time - 2);
716
+
717
+			// high byte
718
+			data = static_cast<uint8_t>(data + 1) + dp;
719
+			temp = static_cast<uint8_t>((temp >> 8) + this->cpu_read(data, rel_time - 1));
720
+			nz |= temp;
721
+			this->cpu_write(temp, data, rel_time);
722
+
723
+			goto inc_pc_loop;
784 724
 		}
785
-		
786
-		lo += a;
787
-		result = y + hi + (lo >> 8);
788
-		flags = hi ^ y ^ result;
789
-		
790
-		psw = (psw & ~(v40 | h08)) |
791
-				(flags >> 1 & h08) |
792
-				((flags + 0x80) >> 2 & v40);
793
-		c = result;
794
-		a = (uint8_t) lo;
795
-		result = (uint8_t) result;
796
-		y = result;
797
-		nz = (((lo >> 1) | lo) & 0x7F) | result;
798
-		
799
-		goto inc_pc_loop;
800
-	}
801
-	
802
-	case 0x5A: { // CMPW YA,dp
803
-		int temp = a - READ_DP( -1, data );
804
-		nz = ((temp >> 1) | temp) & 0x7F;
805
-		temp = y + (temp >> 8);
806
-		temp -= READ_DP( 0, (uint8_t) (data + 1) );
807
-		nz |= temp;
808
-		c  = ~temp;
809
-		nz &= 0xFF;
810
-		goto inc_pc_loop;
811
-	}
812
-	
813
-// 10. MULTIPLICATION & DIVISON COMMANDS
814
-
815
-	case 0xCF: { // MUL YA
816
-		unsigned temp = y * a;
817
-		a = (uint8_t) temp;
818
-		nz = ((temp >> 1) | temp) & 0x7F;
819
-		y = temp >> 8;
820
-		nz |= y;
821
-		goto loop;
822
-	}
823
-	
824
-	case 0x9E: // DIV YA,X
825
-	{
826
-		unsigned ya = y * 0x100 + a;
827
-		
828
-		psw &= ~(h08 | v40);
829
-		
830
-		if ( y >= x )
831
-			psw |= v40;
832
-		
833
-		if ( (y & 15) >= (x & 15) )
834
-			psw |= h08;
835
-		
836
-		if ( y < x * 2 )
725
+
726
+		case 0x7A: // ADDW YA,dp
727
+		case 0x9A: // SUBW YA,dp
837 728
 		{
838
-			a = ya / x;
839
-			y = ya - a * x;
729
+			int lo = this->cpu_read(DP_ADDR(data), rel_time - 2);
730
+			int hi = this->cpu_read(DP_ADDR(static_cast<uint8_t>(data + 1)), rel_time);
731
+
732
+			if (opcode == 0x9A) // SUBW
733
+			{
734
+				lo = (lo ^ 0xFF) + 1;
735
+				hi ^= 0xFF;
736
+			}
737
+
738
+			lo += a;
739
+			int result = y + hi + (lo >> 8);
740
+			int flags = hi ^ y ^ result;
741
+
742
+			psw = (psw & ~(v40 | h08)) | (flags >> 1 & h08) | ((flags + 0x80) >> 2 & v40);
743
+			c = result;
744
+			a = static_cast<uint8_t>(lo);
745
+			result = static_cast<uint8_t>(result);
746
+			y = result;
747
+			nz = (((lo >> 1) | lo) & 0x7F) | result;
748
+
749
+			goto inc_pc_loop;
840 750
 		}
841
-		else
751
+
752
+		case 0x5A: // CMPW YA,dp
842 753
 		{
843
-			a = 255 - (ya - x * 0x200) / (256 - x);
844
-			y = x   + (ya - x * 0x200) % (256 - x);
754
+			int temp = a - this->cpu_read(DP_ADDR(data), rel_time - 1);
755
+			nz = ((temp >> 1) | temp) & 0x7F;
756
+			temp = y + (temp >> 8);
757
+			temp -= this->cpu_read(DP_ADDR(static_cast<uint8_t>(data + 1)), rel_time);
758
+			nz |= temp;
759
+			c  = ~temp;
760
+			nz &= 0xFF;
761
+			goto inc_pc_loop;
845 762
 		}
846
-		
847
-		nz = (uint8_t) a;
848
-		a = (uint8_t) a;
849
-		
850
-		goto loop;
851
-	}
852
-	
853
-// 11. DECIMAL COMPENSATION COMMANDS
854
-	
855
-	case 0xDF: // DAA
856
-		SUSPICIOUS_OPCODE( "DAA" );
857
-		if ( a > 0x99 || c & 0x100 )
763
+
764
+		// 10. MULTIPLICATION & DIVISON COMMANDS
765
+
766
+		case 0xCF: // MUL YA
858 767
 		{
859
-			a += 0x60;
860
-			c = 0x100;
768
+			unsigned temp = y * a;
769
+			a = static_cast<uint8_t>(temp);
770
+			nz = ((temp >> 1) | temp) & 0x7F;
771
+			y = temp >> 8;
772
+			nz |= y;
773
+			goto loop;
861 774
 		}
862
-		
863
-		if ( (a & 0x0F) > 9 || psw & h08 )
864
-			a += 0x06;
865
-		
866
-		nz = a;
867
-		a = (uint8_t) a;
868
-		goto loop;
869
-	
870
-	case 0xBE: // DAS
871
-		SUSPICIOUS_OPCODE( "DAS" );
872
-		if ( a > 0x99 || !(c & 0x100) )
775
+
776
+		case 0x9E: // DIV YA,X
873 777
 		{
874
-			a -= 0x60;
875
-			c = 0;
778
+			unsigned ya = y * 0x100 + a;
779
+
780
+			psw &= ~(h08 | v40);
781
+
782
+			if (y >= x)
783
+				psw |= v40;
784
+
785
+			if ((y & 15) >= (x & 15))
786
+				psw |= h08;
787
+
788
+			if (y < x * 2)
789
+			{
790
+				a = ya / x;
791
+				y = ya - a * x;
792
+			}
793
+			else
794
+			{
795
+				a = 255 - (ya - x * 0x200) / (256 - x);
796
+				y = x + (ya - x * 0x200) % (256 - x);
797
+			}
798
+
799
+			nz = static_cast<uint8_t>(a);
800
+			a = static_cast<uint8_t>(a);
801
+
802
+			goto loop;
876 803
 		}
877
-		
878
-		if ( (a & 0x0F) > 9 || !(psw & h08) )
879
-			a -= 0x06;
880
-		
881
-		nz = a;
882
-		a = (uint8_t) a;
883
-		goto loop;
884
-	
885
-// 12. BRANCHING COMMANDS
886 804
 
887
-	case 0x2F: // BRA rel
888
-		pc += (BOOST::int8_t) data;
889
-		goto inc_pc_loop;
890
-	
891
-	case 0x30: // BMI
892
-		BRANCH( (nz & nz_neg_mask) )
893
-	
894
-	case 0x10: // BPL
895
-		BRANCH( !(nz & nz_neg_mask) )
896
-	
897
-	case 0xB0: // BCS
898
-		BRANCH( c & 0x100 )
899
-	
900
-	case 0x90: // BCC
901
-		BRANCH( !(c & 0x100) )
902
-	
903
-	case 0x70: // BVS
904
-		BRANCH( psw & v40 )
905
-	
906
-	case 0x50: // BVC
907
-		BRANCH( !(psw & v40) )
908
-	
909
-	#define CBRANCH( cond )\
910
-	{\
911
-		pc++;\
912
-		if ( cond )\
913
-			goto cbranch_taken_loop;\
914
-		rel_time -= 2;\
915
-		goto inc_pc_loop;\
916
-	}
917
-	
918
-	case 0x03: // BBS dp.bit,rel
919
-	case 0x23:
920
-	case 0x43:
921
-	case 0x63:
922
-	case 0x83:
923
-	case 0xA3:
924
-	case 0xC3:
925
-	case 0xE3:
926
-		CBRANCH( READ_DP( -4, data ) >> (opcode >> 5) & 1 )
927
-	
928
-	case 0x13: // BBC dp.bit,rel
929
-	case 0x33:
930
-	case 0x53:
931
-	case 0x73:
932
-	case 0x93:
933
-	case 0xB3:
934
-	case 0xD3:
935
-	case 0xF3:
936
-		CBRANCH( !(READ_DP( -4, data ) >> (opcode >> 5) & 1) )
937
-	
938
-	case 0xDE: // CBNE dp+X,rel
939
-		data = (uint8_t) (data + x);
940
-		// fall through
941
-	case 0x2E:{// CBNE dp,rel
942
-		int temp;
943
-		// 61% from timer
944
-		READ_DP_TIMER( -4, data, temp );
945
-		CBRANCH( temp != a )
946
-	}
947
-	
948
-	case 0x6E: { // DBNZ dp,rel
949
-		unsigned temp = READ_DP( -4, data ) - 1;
950
-		WRITE_DP( -3, (uint8_t) data, /*(uint8_t)*/ temp + no_read_before_write  );
951
-		CBRANCH( temp )
952
-	}
953
-	
954
-	case 0xFE: // DBNZ Y,rel
955
-		y = (uint8_t) (y - 1);
956
-		BRANCH( y )
957
-	
958
-	case 0x1F: // JMP [abs+X]
959
-		SET_PC( READ_PC16( pc ) + x );
960
-		// fall through
961
-	case 0x5F: // JMP abs
962
-		SET_PC( READ_PC16( pc ) );
963
-		goto loop;
964
-	
965
-// 13. SUB-ROUTINE CALL RETURN COMMANDS
966
-	
967
-	case 0x0F:{// BRK
968
-		int temp;
969
-		int ret_addr = GET_PC();
970
-		SUSPICIOUS_OPCODE( "BRK" );
971
-		SET_PC( READ_PROG16( 0xFFDE ) ); // vector address verified
972
-		PUSH16( ret_addr );
973
-		GET_PSW( temp );
974
-		psw = (psw | b10) & ~i04;
975
-		PUSH( temp );
976
-		goto loop;
977
-	}
978
-	
979
-	case 0x4F:{// PCALL offset
980
-		int ret_addr = GET_PC() + 1;
981
-		SET_PC( 0xFF00 | data );
982
-		PUSH16( ret_addr );
983
-		goto loop;
984
-	}
985
-	
986
-	case 0x01: // TCALL n
987
-	case 0x11:
988
-	case 0x21:
989
-	case 0x31:
990
-	case 0x41:
991
-	case 0x51:
992
-	case 0x61:
993
-	case 0x71:
994
-	case 0x81:
995
-	case 0x91:
996
-	case 0xA1:
997
-	case 0xB1:
998
-	case 0xC1:
999
-	case 0xD1:
1000
-	case 0xE1:
1001
-	case 0xF1: {
1002
-		int ret_addr = GET_PC();
1003
-		SET_PC( READ_PROG16( 0xFFDE - (opcode >> 3) ) );
1004
-		PUSH16( ret_addr );
1005
-		goto loop;
1006
-	}
1007
-	
1008
-// 14. STACK OPERATION COMMANDS
805
+		// 11. DECIMAL COMPENSATION COMMANDS
1009 806
 
1010
-	{
1011
-		int temp;
1012
-	case 0x7F: // RET1
1013
-		temp = *sp;
1014
-		SET_PC( GET_LE16( sp + 1 ) );
1015
-		sp += 3;
1016
-		goto set_psw;
1017
-	case 0x8E: // POP PSW
1018
-		POP( temp );
1019
-	set_psw:
1020
-		SET_PSW( temp );
1021
-		goto loop;
1022
-	}
1023
-	
1024
-	case 0x0D: { // PUSH PSW
1025
-		int temp;
1026
-		GET_PSW( temp );
1027
-		PUSH( temp );
1028
-		goto loop;
1029
-	}
807
+		case 0xDF: // DAA
808
+			if (a > 0x99 || c & 0x100)
809
+			{
810
+				a += 0x60;
811
+				c = 0x100;
812
+			}
1030 813
 
1031
-	case 0x2D: // PUSH A
1032
-		PUSH( a );
1033
-		goto loop;
1034
-	
1035
-	case 0x4D: // PUSH X
1036
-		PUSH( x );
1037
-		goto loop;
1038
-	
1039
-	case 0x6D: // PUSH Y
1040
-		PUSH( y );
1041
-		goto loop;
1042
-	
1043
-	case 0xAE: // POP A
1044
-		POP( a );
1045
-		goto loop;
1046
-	
1047
-	case 0xCE: // POP X
1048
-		POP( x );
1049
-		goto loop;
1050
-	
1051
-	case 0xEE: // POP Y
1052
-		POP( y );
1053
-		goto loop;
1054
-	
1055
-// 15. BIT OPERATION COMMANDS
1056
-
1057
-	case 0x02: // SET1
1058
-	case 0x22:
1059
-	case 0x42:
1060
-	case 0x62:
1061
-	case 0x82:
1062
-	case 0xA2:
1063
-	case 0xC2:
1064
-	case 0xE2:
1065
-	case 0x12: // CLR1
1066
-	case 0x32:
1067
-	case 0x52:
1068
-	case 0x72:
1069
-	case 0x92:
1070
-	case 0xB2:
1071
-	case 0xD2:
1072
-	case 0xF2: {
1073
-		int bit = 1 << (opcode >> 5);
1074
-		int mask = ~bit;
1075
-		if ( opcode & 0x10 )
1076
-			bit = 0;
1077
-		data += dp;
1078
-		WRITE( 0, data, (READ( -1, data ) & mask) | bit );
1079
-		goto inc_pc_loop;
1080
-	}
1081
-		
1082
-	case 0x0E: // TSET1 abs
1083
-	case 0x4E: // TCLR1 abs
1084
-		data = READ_PC16( pc );
1085
-		pc += 2;
814
+			if ((a & 0x0F) > 9 || psw & h08)
815
+				a += 0x06;
816
+
817
+			nz = a;
818
+			a = static_cast<uint8_t>(a);
819
+			goto loop;
820
+
821
+		case 0xBE: // DAS
822
+			if (a > 0x99 || !(c & 0x100))
823
+			{
824
+				a -= 0x60;
825
+				c = 0;
826
+			}
827
+
828
+			if ((a & 0x0F) > 9 || !(psw & h08))
829
+				a -= 0x06;
830
+
831
+			nz = a;
832
+			a = static_cast<uint8_t>(a);
833
+			goto loop;
834
+
835
+		// 12. BRANCHING COMMANDS
836
+
837
+		case 0x2F: // BRA rel
838
+			pc += static_cast<int8_t>(data);
839
+			goto inc_pc_loop;
840
+
841
+		case 0x30: // BMI
842
+			BRANCH(nz & nz_neg_mask)
843
+
844
+		case 0x10: // BPL
845
+			BRANCH(!(nz & nz_neg_mask))
846
+
847
+		case 0xB0: // BCS
848
+			BRANCH(c & 0x100)
849
+
850
+		case 0x90: // BCC
851
+			BRANCH(!(c & 0x100))
852
+
853
+		case 0x70: // BVS
854
+			BRANCH(psw & v40)
855
+
856
+		case 0x50: // BVC
857
+			BRANCH(!(psw & v40))
858
+
859
+#define CBRANCH(cond) \
860
+{ \
861
+	++pc; \
862
+	if (cond) \
863
+		goto cbranch_taken_loop; \
864
+	rel_time -= 2; \
865
+	goto inc_pc_loop; \
866
+}
867
+
868
+		case 0x03: // BBS dp.bit,rel
869
+		case 0x23:
870
+		case 0x43:
871
+		case 0x63:
872
+		case 0x83:
873
+		case 0xA3:
874
+		case 0xC3:
875
+		case 0xE3:
876
+			CBRANCH((this->cpu_read(DP_ADDR(data), rel_time - 4) >> (opcode >> 5)) & 1)
877
+
878
+		case 0x13: // BBC dp.bit,rel
879
+		case 0x33:
880
+		case 0x53:
881
+		case 0x73:
882
+		case 0x93:
883
+		case 0xB3:
884
+		case 0xD3:
885
+		case 0xF3:
886
+			CBRANCH(!((this->cpu_read(DP_ADDR(data), rel_time - 4) >> (opcode >> 5)) & 1))
887
+
888
+		case 0xDE: // CBNE dp+X,rel
889
+			data = static_cast<uint8_t>(data + x);
890
+			// fall through
891
+		case 0x2E: // CBNE dp,rel
1086 892
 		{
1087
-			unsigned temp = READ( -2, data );
1088
-			nz = (uint8_t) (a - temp);
1089
-			temp &= ~a;
1090
-			if ( opcode == 0x0E )
1091
-				temp |= a;
1092
-			WRITE( 0, data, temp );
893
+			// 61% from timer
894
+			int temp = CPU_READ_TIMER(-4, DP_ADDR(data));
895
+			CBRANCH(temp != a)
1093 896
 		}
1094
-		goto loop;
1095
-	
1096
-	case 0x4A: // AND1 C,mem.bit
1097
-		c &= MEM_BIT( 0 );
1098
-		pc += 2;
1099
-		goto loop;
1100
-	
1101
-	case 0x6A: // AND1 C,/mem.bit
1102
-		c &= ~MEM_BIT( 0 );
1103
-		pc += 2;
1104
-		goto loop;
1105
-	
1106
-	case 0x0A: // OR1 C,mem.bit
1107
-		c |= MEM_BIT( -1 );
1108
-		pc += 2;
1109
-		goto loop;
1110
-	
1111
-	case 0x2A: // OR1 C,/mem.bit
1112
-		c |= ~MEM_BIT( -1 );
1113
-		pc += 2;
1114
-		goto loop;
1115
-	
1116
-	case 0x8A: // EOR1 C,mem.bit
1117
-		c ^= MEM_BIT( -1 );
1118
-		pc += 2;
1119
-		goto loop;
1120
-	
1121
-	case 0xEA: // NOT1 mem.bit
1122
-		data = READ_PC16( pc );
1123
-		pc += 2;
897
+
898
+		case 0x6E: // DBNZ dp,rel
1124 899
 		{
1125
-			unsigned temp = READ( -1, data & 0x1FFF );
1126
-			temp ^= 1 << (data >> 13);
1127
-			WRITE( 0, data & 0x1FFF, temp );
900
+			unsigned temp = this->cpu_read(DP_ADDR(data), rel_time - 4) - 1;
901
+			this->cpu_write(/*(uint8_t)*/ temp + no_read_before_write, DP_ADDR(static_cast<uint8_t>(data)), rel_time - 3);
902
+			CBRANCH(temp)
1128 903
 		}
1129
-		goto loop;
1130
-	
1131
-	case 0xCA: // MOV1 mem.bit,C
1132
-		data = READ_PC16( pc );
1133
-		pc += 2;
904
+
905
+		case 0xFE: // DBNZ Y,rel
906
+			y = static_cast<uint8_t>(y - 1);
907
+			BRANCH(y)
908
+
909
+		case 0x1F: // JMP [abs+X]
910
+			SET_PC(get_le16(pc) + x);
911
+			// fall through
912
+		case 0x5F: // JMP abs
913
+			SET_PC(get_le16(pc));
914
+			goto loop;
915
+
916
+		// 13. SUB-ROUTINE CALL RETURN COMMANDS
917
+
918
+		case 0x0F: // BRK
1134 919
 		{
1135
-			unsigned temp = READ( -2, data & 0x1FFF );
1136
-			unsigned bit = data >> 13;
1137
-			temp = (temp & ~(1 << bit)) | ((c >> 8 & 1) << bit);
1138
-			WRITE( 0, data & 0x1FFF, temp + no_read_before_write  );
920
+			int temp;
921
+			int ret_addr = GET_PC();
922
+			SET_PC(READ_PROG16(0xFFDE)); // vector address verified
923
+			PUSH16(ret_addr);
924
+			GET_PSW(temp);
925
+			psw = (psw | b10) & ~i04;
926
+			PUSH(temp);
927
+			goto loop;
1139 928
 		}
1140
-		goto loop;
1141
-	
1142
-	case 0xAA: // MOV1 C,mem.bit
1143
-		c = MEM_BIT( 0 );
1144
-		pc += 2;
1145
-		goto loop;
1146
-	
1147
-// 16. PROGRAM PSW FLAG OPERATION COMMANDS
1148
-
1149
-	case 0x60: // CLRC
1150
-		c = 0;
1151
-		goto loop;
1152
-		
1153
-	case 0x80: // SETC
1154
-		c = ~0;
1155
-		goto loop;
1156
-	
1157
-	case 0xED: // NOTC
1158
-		c ^= 0x100;
1159
-		goto loop;
1160
-		
1161
-	case 0xE0: // CLRV
1162
-		psw &= ~(v40 | h08);
1163
-		goto loop;
1164
-	
1165
-	case 0x20: // CLRP
1166
-		dp = 0;
1167
-		goto loop;
1168
-	
1169
-	case 0x40: // SETP
1170
-		dp = 0x100;
1171
-		goto loop;
1172
-	
1173
-	case 0xA0: // EI
1174
-		SUSPICIOUS_OPCODE( "EI" );
1175
-		psw |= i04;
1176
-		goto loop;
1177
-	
1178
-	case 0xC0: // DI
1179
-		SUSPICIOUS_OPCODE( "DI" );
1180
-		psw &= ~i04;
1181
-		goto loop;
1182
-	
1183
-// 17. OTHER COMMANDS
1184 929
 
1185
-	case 0x00: // NOP
1186
-		goto loop;
1187
-	
1188
-	case 0xFF:{// STOP
1189
-		// handle PC wrap-around
1190
-		unsigned addr = GET_PC() - 1;
1191
-		if ( addr >= 0x10000 )
930
+		case 0x4F: // PCALL offset
1192 931
 		{
1193
-			addr &= 0xFFFF;
1194
-			SET_PC( addr );
1195
-			dprintf( "SPC: PC wrapped around\n" );
932
+			int ret_addr = GET_PC() + 1;
933
+			SET_PC(0xFF00 | data);
934
+			PUSH16(ret_addr);
1196 935
 			goto loop;
1197 936
 		}
1198
-	}
1199
-	// fall through
1200
-	case 0xEF: // SLEEP
1201
-		SUSPICIOUS_OPCODE( "STOP/SLEEP" );
1202
-		--pc;
1203
-		rel_time = 0;
1204
-		m.cpu_error = "SPC emulation error";
1205
-		goto stop;
937
+
938
+		case 0x01: // TCALL n
939
+		case 0x11:
940
+		case 0x21:
941
+		case 0x31:
942
+		case 0x41:
943
+		case 0x51:
944
+		case 0x61:
945
+		case 0x71:
946
+		case 0x81:
947
+		case 0x91:
948
+		case 0xA1:
949
+		case 0xB1:
950
+		case 0xC1:
951
+		case 0xD1:
952
+		case 0xE1:
953
+		case 0xF1:
954
+		{
955
+			int ret_addr = GET_PC();
956
+			SET_PC(READ_PROG16(0xFFDE - (opcode >> 3)));
957
+			PUSH16(ret_addr);
958
+			goto loop;
959
+		}
960
+
961
+		// 14. STACK OPERATION COMMANDS
962
+
963
+		{
964
+			int temp;
965
+		case 0x7F: // RET1
966
+			temp = *sp;
967
+			SET_PC(get_le16(sp + 1));
968
+			sp += 3;
969
+			goto set_psw;
970
+		case 0x8E: // POP PSW
971
+			POP(temp);
972
+		set_psw:
973
+			SET_PSW(temp);
974
+			goto loop;
975
+		}
976
+
977
+		case 0x0D: // PUSH PSW
978
+		{
979
+			int temp;
980
+			GET_PSW(temp);
981
+			PUSH(temp);
982
+			goto loop;
983
+		}
984
+
985
+		case 0x2D: // PUSH A
986
+			PUSH(a);
987
+			goto loop;
988
+
989
+		case 0x4D: // PUSH X
990
+			PUSH(x);
991
+			goto loop;
992
+
993
+		case 0x6D: // PUSH Y
994
+			PUSH(y);
995
+			goto loop;
996
+
997
+		case 0xAE: // POP A
998
+			POP(a);
999
+			goto loop;
1000
+
1001
+		case 0xCE: // POP X
1002
+			POP(x);
1003
+			goto loop;
1004
+
1005
+		case 0xEE: // POP Y
1006
+			POP(y);
1007
+			goto loop;
1008
+
1009
+		// 15. BIT OPERATION COMMANDS
1010
+
1011
+		case 0x02: // SET1
1012
+		case 0x22:
1013
+		case 0x42:
1014
+		case 0x62:
1015
+		case 0x82:
1016
+		case 0xA2:
1017
+		case 0xC2:
1018
+		case 0xE2:
1019
+		case 0x12: // CLR1
1020
+		case 0x32:
1021
+		case 0x52:
1022
+		case 0x72:
1023
+		case 0x92:
1024
+		case 0xB2:
1025
+		case 0xD2:
1026
+		case 0xF2:
1027
+		{
1028
+			int bit = 1 << (opcode >> 5);
1029
+			int mask = ~bit;
1030
+			if (opcode & 0x10)
1031
+				bit = 0;
1032
+			data += dp;
1033
+			this->cpu_write((this->cpu_read(data, rel_time - 1) & mask) | bit, data, rel_time);
1034
+			goto inc_pc_loop;
1035
+		}
1036
+
1037
+		case 0x0E: // TSET1 abs
1038
+		case 0x4E: // TCLR1 abs
1039
+			data = get_le16(pc);
1040
+			pc += 2;
1041
+			{
1042
+				unsigned temp = this->cpu_read(data, rel_time - 2);
1043
+				nz = static_cast<uint8_t>(a - temp);
1044
+				temp &= ~a;
1045
+				if (opcode == 0x0E)
1046
+					temp |= a;
1047
+				this->cpu_write(temp, data, rel_time);
1048
+			}
1049
+			goto loop;
1050
+
1051
+		case 0x4A: // AND1 C,mem.bit
1052
+			c &= MEM_BIT(0);
1053
+			pc += 2;
1054
+			goto loop;
1055
+
1056
+		case 0x6A: // AND1 C,/mem.bit
1057
+			c &= ~MEM_BIT(0);
1058
+			pc += 2;
1059
+			goto loop;
1060
+
1061
+		case 0x0A: // OR1 C,mem.bit
1062
+			c |= MEM_BIT(-1);
1063
+			pc += 2;
1064
+			goto loop;
1065
+
1066
+		case 0x2A: // OR1 C,/mem.bit
1067
+			c |= ~MEM_BIT(-1);
1068
+			pc += 2;
1069
+			goto loop;
1070
+
1071
+		case 0x8A: // EOR1 C,mem.bit
1072
+			c ^= MEM_BIT(-1);
1073
+			pc += 2;
1074
+			goto loop;
1075
+
1076
+		case 0xEA: // NOT1 mem.bit
1077
+			data = get_le16(pc);
1078
+			pc += 2;
1079
+			{
1080
+				unsigned temp = this->cpu_read(data & 0x1FFF, rel_time - 1);
1081
+				temp ^= 1 << (data >> 13);
1082
+				this->cpu_write(temp, data & 0x1FFF, rel_time);
1083
+			}
1084
+			goto loop;
1085
+
1086
+		case 0xCA: // MOV1 mem.bit,C
1087
+			data = get_le16(pc);
1088
+			pc += 2;
1089
+			{
1090
+				unsigned temp = this->cpu_read(data & 0x1FFF, rel_time - 2);
1091
+				unsigned bit = data >> 13;
1092
+				temp = (temp & ~(1 << bit)) | ((c >> 8 & 1) << bit);
1093
+				this->cpu_write(temp + no_read_before_write, data & 0x1FFF, rel_time);
1094
+			}
1095
+			goto loop;
1096
+
1097
+		case 0xAA: // MOV1 C,mem.bit
1098
+			c = MEM_BIT(0);
1099
+			pc += 2;
1100
+			goto loop;
1101
+
1102
+		// 16. PROGRAM PSW FLAG OPERATION COMMANDS
1103
+
1104
+		case 0x60: // CLRC
1105
+			c = 0;
1106
+			goto loop;
1107
+
1108
+		case 0x80: // SETC
1109
+			c = ~0;
1110
+			goto loop;
1111
+
1112
+		case 0xED: // NOTC
1113
+			c ^= 0x100;
1114
+			goto loop;
1115
+
1116
+		case 0xE0: // CLRV
1117
+			psw &= ~(v40 | h08);
1118
+			goto loop;
1119
+
1120
+		case 0x20: // CLRP
1121
+			dp = 0;
1122
+			goto loop;
1123
+
1124
+		case 0x40: // SETP
1125
+			dp = 0x100;
1126
+			goto loop;
1127
+
1128
+		case 0xA0: // EI
1129
+			psw |= i04;
1130
+			goto loop;
1131
+
1132
+		case 0xC0: // DI
1133
+			psw &= ~i04;
1134
+			goto loop;
1135
+
1136
+		// 17. OTHER COMMANDS
1137
+
1138
+		case 0x00: // NOP
1139
+			goto loop;
1140
+
1141
+		case 0xFF: // STOP
1142
+		{
1143
+			// handle PC wrap-around
1144
+			unsigned addr = GET_PC() - 1;
1145
+			if (addr >= 0x10000)
1146
+			{
1147
+				addr &= 0xFFFF;
1148
+				SET_PC(addr);
1149
+				goto loop;
1150
+			}
1151
+		}
1152
+		// fall through
1153
+		case 0xEF: // SLEEP
1154
+			--pc;
1155
+			rel_time = 0;
1156
+			goto stop;
1206 1157
 	} // switch
1207
-	
1208
-	assert( 0 ); // catch any unhandled instructions
1209
-}   
1158
+
1159
+	assert(0); // catch any unhandled instructions
1160
+}
1210 1161
 out_of_time:
1211
-	rel_time -= m.cycle_table [*pc]; // undo partial execution of opcode
1162
+	rel_time -= this->m.cycle_table[*pc]; // undo partial execution of opcode
1212 1163
 stop:
1213
-	
1164
+
1214 1165
 	// Uncache registers
1215
-	if ( GET_PC() >= 0x10000 )
1216
-		dprintf( "SPC: PC wrapped around\n" );
1217
-	m.cpu_regs.pc = (uint16_t) GET_PC();
1218
-	m.cpu_regs.sp = ( uint8_t) GET_SP();
1219
-	m.cpu_regs.a  = ( uint8_t) a;
1220
-	m.cpu_regs.x  = ( uint8_t) x;
1221
-	m.cpu_regs.y  = ( uint8_t) y;
1166
+	m.cpu_regs.pc = static_cast<uint16_t>(GET_PC());
1167
+	m.cpu_regs.sp = static_cast<uint8_t>(GET_SP());
1168
+	m.cpu_regs.a = static_cast<uint8_t>(a);
1169
+	m.cpu_regs.x = static_cast<uint8_t>(x);
1170
+	m.cpu_regs.y = static_cast<uint8_t>(y);
1222 1171
 	{
1223 1172
 		int temp;
1224
-		GET_PSW( temp );
1225
-		m.cpu_regs.psw = (uint8_t) temp;
1173
+		GET_PSW(temp);
1174
+		m.cpu_regs.psw = static_cast<uint8_t>(temp);
1226 1175
 	}
1227 1176
 }
1228 1177
 SPC_CPU_RUN_FUNC_END
Browse code

Import actual code.

Naram Qashat authored on 2013/03/26 02:41:19
Showing 1 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1,1228 @@
1
+// snes_spc 0.9.0. http://www.slack.net/~ant/
2
+
3
+/* Copyright (C) 2004-2007 Shay Green. This module is free software; you
4
+can redistribute it and/or modify it under the terms of the GNU Lesser
5
+General Public License as published by the Free Software Foundation; either
6
+version 2.1 of the License, or (at your option) any later version. This
7
+module is distributed in the hope that it will be useful, but WITHOUT ANY
8
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
9
+FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
10
+details. You should have received a copy of the GNU Lesser General Public
11
+License along with this module; if not, write to the Free Software Foundation,
12
+Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
13
+
14
+//// Memory access
15
+
16
+#if SPC_MORE_ACCURACY
17
+	#define SUSPICIOUS_OPCODE( name ) ((void) 0)
18
+#else
19
+	#define SUSPICIOUS_OPCODE( name ) dprintf( "SPC: suspicious opcode: " name "\n" )
20
+#endif
21
+
22
+#define CPU_READ( time, offset, addr )\
23
+	cpu_read( addr, time + offset )
24
+
25
+#define CPU_WRITE( time, offset, addr, data )\
26
+	cpu_write( data, addr, time + offset )
27
+
28
+#if SPC_MORE_ACCURACY
29
+	#define CPU_READ_TIMER( time, offset, addr, out )\
30
+		{ out = CPU_READ( time, offset, addr ); }
31
+
32
+#else
33
+	// timers are by far the most common thing read from dp
34
+	#define CPU_READ_TIMER( time, offset, addr_, out )\
35
+	{\
36
+		rel_time_t adj_time = time + offset;\
37
+		int dp_addr = addr_;\
38
+		int ti = dp_addr - (r_t0out + 0xF0);\
39
+		if ( (unsigned) ti < timer_count )\
40
+		{\
41
+			Timer* t = &m.timers [ti];\
42
+			if ( adj_time >= t->next_time )\
43
+				t = run_timer_( t, adj_time );\
44
+			out = t->counter;\
45
+			t->counter = 0;\
46
+		}\
47
+		else\
48
+		{\
49
+			out = ram [dp_addr];\
50
+			int i = dp_addr - 0xF0;\
51
+			if ( (unsigned) i < 0x10 )\
52
+				out = cpu_read_smp_reg( i, adj_time );\
53
+		}\
54
+	}
55
+#endif
56
+
57
+#define TIME_ADJ( n )   (n)
58
+
59
+#define READ_TIMER( time, addr, out )       CPU_READ_TIMER( rel_time, TIME_ADJ(time), (addr), out )
60
+#define READ(  time, addr )                 CPU_READ ( rel_time, TIME_ADJ(time), (addr) )
61
+#define WRITE( time, addr, data )           CPU_WRITE( rel_time, TIME_ADJ(time), (addr), (data) )
62
+
63
+#define DP_ADDR( addr )                     (dp + (addr))
64
+
65
+#define READ_DP_TIMER(  time, addr, out )   CPU_READ_TIMER( rel_time, TIME_ADJ(time), DP_ADDR( addr ), out )
66
+#define READ_DP(  time, addr )              READ ( time, DP_ADDR( addr ) )
67
+#define WRITE_DP( time, addr, data )        WRITE( time, DP_ADDR( addr ), data )
68
+
69
+#define READ_PROG16( addr )                 GET_LE16( ram + (addr) )
70
+
71
+#define SET_PC( n )     (pc = ram + (n))
72
+#define GET_PC()        (pc - ram)
73
+#define READ_PC( pc )   (*(pc))
74
+#define READ_PC16( pc ) GET_LE16( pc )
75
+
76
+// TODO: remove non-wrapping versions?
77
+#define SPC_NO_SP_WRAPAROUND 0
78
+
79
+#define SET_SP( v )     (sp = ram + 0x101 + (v))
80
+#define GET_SP()        (sp - 0x101 - ram)
81
+
82
+#if SPC_NO_SP_WRAPAROUND
83
+#define PUSH16( v )     (sp -= 2, SET_LE16( sp, v ))
84
+#define PUSH( v )       (void) (*--sp = (uint8_t) (v))
85
+#define POP( out )      (void) ((out) = *sp++)
86
+
87
+#else
88
+#define PUSH16( data )\
89
+{\
90
+	int addr = (sp -= 2) - ram;\
91
+	if ( addr > 0x100 )\
92
+	{\
93
+		SET_LE16( sp, data );\
94
+	}\
95
+	else\
96
+	{\
97
+		ram [(uint8_t) addr + 0x100] = (uint8_t) data;\
98
+		sp [1] = (uint8_t) (data >> 8);\
99
+		sp += 0x100;\
100
+	}\
101
+}
102
+
103
+#define PUSH( data )\
104
+{\
105
+	*--sp = (uint8_t) (data);\
106
+	if ( sp - ram == 0x100 )\
107
+		sp += 0x100;\
108
+}
109
+
110
+#define POP( out )\
111
+{\
112
+	out = *sp++;\
113
+	if ( sp - ram == 0x201 )\
114
+	{\
115
+		out = sp [-0x101];\
116
+		sp -= 0x100;\
117
+	}\
118
+}
119
+
120
+#endif
121
+
122
+#define MEM_BIT( rel ) CPU_mem_bit( pc, rel_time + rel )
123
+
124
+unsigned SNES_SPC::CPU_mem_bit( uint8_t const* pc, rel_time_t rel_time )
125
+{
126
+	unsigned addr = READ_PC16( pc );
127
+	unsigned t = READ( 0, addr & 0x1FFF ) >> (addr >> 13);
128
+	return t << 8 & 0x100;
129
+}
130
+
131
+//// Status flag handling
132
+
133
+// Hex value in name to clarify code and bit shifting.
134
+// Flag stored in indicated variable during emulation
135
+int const n80 = 0x80; // nz
136
+int const v40 = 0x40; // psw
137
+int const p20 = 0x20; // dp
138
+int const b10 = 0x10; // psw
139
+int const h08 = 0x08; // psw
140
+int const i04 = 0x04; // psw
141
+int const z02 = 0x02; // nz
142
+int const c01 = 0x01; // c
143
+
144
+int const nz_neg_mask = 0x880; // either bit set indicates N flag set
145
+
146
+#define GET_PSW( out )\
147
+{\
148
+	out = psw & ~(n80 | p20 | z02 | c01);\
149
+	out |= c  >> 8 & c01;\
150
+	out |= dp >> 3 & p20;\
151
+	out |= ((nz >> 4) | nz) & n80;\
152
+	if ( !(uint8_t) nz ) out |= z02;\
153
+}
154
+
155
+#define SET_PSW( in )\
156
+{\
157
+	psw = in;\
158
+	c   = in << 8;\
159
+	dp  = in << 3 & 0x100;\
160
+	nz  = (in << 4 & 0x800) | (~in & z02);\
161
+}
162
+
163
+SPC_CPU_RUN_FUNC
164
+{
165
+	uint8_t* const ram = RAM;
166
+	int a = m.cpu_regs.a;
167
+	int x = m.cpu_regs.x;
168
+	int y = m.cpu_regs.y;
169
+	uint8_t const* pc;
170
+	uint8_t* sp;
171
+	int psw;
172
+	int c;
173
+	int nz;
174
+	int dp;
175
+	
176
+	SET_PC( m.cpu_regs.pc );
177
+	SET_SP( m.cpu_regs.sp );
178
+	SET_PSW( m.cpu_regs.psw );
179
+	
180
+	goto loop;
181
+	
182
+	
183
+	// Main loop
184
+	
185
+cbranch_taken_loop:
186
+	pc += *(BOOST::int8_t const*) pc;
187
+inc_pc_loop:
188
+	pc++;
189
+loop:
190
+{
191
+	unsigned opcode;
192
+	unsigned data;
193
+	
194
+	check( (unsigned) a < 0x100 );
195
+	check( (unsigned) x < 0x100 );
196
+	check( (unsigned) y < 0x100 );
197
+	
198
+	opcode = *pc;
199
+	if (allow_time_overflow && rel_time >= 0 )
200
+		goto stop;
201
+	if ( (rel_time += m.cycle_table [opcode]) > 0 && !allow_time_overflow)
202
+		goto out_of_time;
203
+	
204
+	#ifdef SPC_CPU_OPCODE_HOOK
205
+		SPC_CPU_OPCODE_HOOK( GET_PC(), opcode );
206
+	#endif
207
+	/*
208
+	//SUB_CASE_COUNTER( 1 );
209
+	#define PROFILE_TIMER_LOOP( op, addr, len )\
210
+	if ( opcode == op )\
211
+	{\
212
+		int cond = (unsigned) ((addr) - 0xFD) < 3 &&\
213
+				pc [len] == 0xF0 && pc [len+1] == 0xFE - len;\
214
+		SUB_CASE_COUNTER( op && cond );\
215
+	}
216
+	
217
+	PROFILE_TIMER_LOOP( 0xEC, GET_LE16( pc + 1 ), 3 );
218
+	PROFILE_TIMER_LOOP( 0xEB, pc [1], 2 );
219
+	PROFILE_TIMER_LOOP( 0xE4, pc [1], 2 );
220
+	*/
221
+
222
+#ifdef DEBUGGER
223
+	if (debug_trace)
224
+		debug_do_trace(a, x, y, pc, sp, psw, c, nz, dp);
225
+#endif
226
+
227
+
228
+	// TODO: if PC is at end of memory, this will get wrong operand (very obscure)
229
+	data = *++pc;
230
+	switch ( opcode )
231
+	{
232
+	
233
+// Common instructions
234
+
235
+#define BRANCH( cond )\
236
+{\
237
+	pc++;\
238
+	pc += (BOOST::int8_t) data;\
239
+	if ( cond )\
240
+		goto loop;\
241
+	pc -= (BOOST::int8_t) data;\
242
+	rel_time -= 2;\
243
+	goto loop;\
244
+}
245
+
246
+	case 0xF0: // BEQ
247
+		BRANCH( !(uint8_t) nz ) // 89% taken
248
+	
249
+	case 0xD0: // BNE
250
+		BRANCH( (uint8_t) nz )
251
+	
252
+	case 0x3F:{// CALL
253
+		int old_addr = GET_PC() + 2;
254
+		SET_PC( READ_PC16( pc ) );
255
+		PUSH16( old_addr );
256
+		goto loop;
257
+	}
258
+	
259
+	case 0x6F:// RET
260
+		#if SPC_NO_SP_WRAPAROUND
261
+		{
262
+			SET_PC( GET_LE16( sp ) );
263
+			sp += 2;
264
+		}
265
+		#else
266
+		{
267
+			int addr = sp - ram;
268
+			SET_PC( GET_LE16( sp ) );
269
+			sp += 2;
270
+			if ( addr < 0x1FF )
271
+				goto loop;
272
+			
273
+			SET_PC( sp [-0x101] * 0x100 + ram [(uint8_t) addr + 0x100] );
274
+			sp -= 0x100;
275
+		}
276
+		#endif
277
+		goto loop;
278
+	
279
+	case 0xE4: // MOV a,dp
280
+		++pc;
281
+		// 80% from timer
282
+		READ_DP_TIMER( 0, data, a = nz );
283
+		goto loop;
284
+	
285
+	case 0xFA:{// MOV dp,dp
286
+		int temp;
287
+		READ_DP_TIMER( -2, data, temp );
288
+		data = temp + no_read_before_write ;
289
+	}
290
+	// fall through
291
+	case 0x8F:{// MOV dp,#imm
292
+		int temp = READ_PC( pc + 1 );
293
+		pc += 2;
294
+		
295
+		#if !SPC_MORE_ACCURACY
296
+		{
297
+			int i = dp + temp;
298
+			ram [i] = (uint8_t) data;
299
+			i -= 0xF0;
300
+			if ( (unsigned) i < 0x10 ) // 76%
301
+			{
302
+				REGS [i] = (uint8_t) data;
303
+				
304
+				// Registers other than $F2 and $F4-$F7
305
+				//if ( i != 2 && i != 4 && i != 5 && i != 6 && i != 7 )
306
+				if ( ((~0x2F00 << (bits_in_int - 16)) << i) < 0 ) // 12%
307
+					cpu_write_smp_reg( data, rel_time, i );
308
+			}
309
+		}
310
+		#else
311
+			WRITE_DP( 0, temp, data );
312
+		#endif
313
+		goto loop;
314
+	}
315
+	
316
+	case 0xC4: // MOV dp,a
317
+		++pc;
318
+		#if !SPC_MORE_ACCURACY
319
+		{
320
+			int i = dp + data;
321
+			ram [i] = (uint8_t) a;
322
+			i -= 0xF0;
323
+			if ( (unsigned) i < 0x10 ) // 39%
324
+			{
325
+				unsigned sel = i - 2;
326
+				REGS [i] = (uint8_t) a;
327
+				
328
+				if ( sel == 1 ) // 51% $F3
329
+					dsp_write( a, rel_time );
330
+				else if ( sel > 1 ) // 1% not $F2 or $F3
331
+					cpu_write_smp_reg_( a, rel_time, i );
332
+			}
333
+		}
334
+		#else
335
+			WRITE_DP( 0, data, a );
336
+		#endif
337
+		goto loop;
338
+	
339
+#define CASE( n )   case n:
340
+
341
+// Define common address modes based on opcode for immediate mode. Execution
342
+// ends with data set to the address of the operand.
343
+#define ADDR_MODES_( op )\
344
+	CASE( op - 0x02 ) /* (X) */\
345
+		data = x + dp;\
346
+		pc--;\
347
+		goto end_##op;\
348
+	CASE( op + 0x0F ) /* (dp)+Y */\
349
+		data = READ_PROG16( data + dp ) + y;\
350
+		goto end_##op;\
351
+	CASE( op - 0x01 ) /* (dp+X) */\
352
+		data = READ_PROG16( ((uint8_t) (data + x)) + dp );\
353
+		goto end_##op;\
354
+	CASE( op + 0x0E ) /* abs+Y */\
355
+		data += y;\
356
+		goto abs_##op;\
357
+	CASE( op + 0x0D ) /* abs+X */\
358
+		data += x;\
359
+	CASE( op - 0x03 ) /* abs */\
360
+	abs_##op:\
361
+		data += 0x100 * READ_PC( ++pc );\
362
+		goto end_##op;\
363
+	CASE( op + 0x0C ) /* dp+X */\
364
+		data = (uint8_t) (data + x);
365
+
366
+#define ADDR_MODES_NO_DP( op )\
367
+	ADDR_MODES_( op )\
368
+		data += dp;\
369
+	end_##op:
370
+
371
+#define ADDR_MODES( op )\
372
+	ADDR_MODES_( op )\
373
+	CASE( op - 0x04 ) /* dp */\
374
+		data += dp;\
375
+	end_##op:
376
+
377
+// 1. 8-bit Data Transmission Commands. Group I
378
+
379
+	ADDR_MODES_NO_DP( 0xE8 ) // MOV A,addr
380
+		a = nz = READ( 0, data );
381
+		goto inc_pc_loop;
382
+	
383
+	case 0xBF:{// MOV A,(X)+
384
+		int temp = x + dp;
385
+		x = (uint8_t) (x + 1);
386
+		a = nz = READ( -1, temp );
387
+		goto loop;
388
+	}
389
+	
390
+	case 0xE8: // MOV A,imm
391
+		a  = data;
392
+		nz = data;
393
+		goto inc_pc_loop;
394
+	
395
+	case 0xF9: // MOV X,dp+Y
396
+		data = (uint8_t) (data + y);
397
+	case 0xF8: // MOV X,dp
398
+		READ_DP_TIMER( 0, data, x = nz );
399
+		goto inc_pc_loop;
400
+	
401
+	case 0xE9: // MOV X,abs
402
+		data = READ_PC16( pc );
403
+		++pc;
404
+		data = READ( 0, data );
405
+	case 0xCD: // MOV X,imm
406
+		x  = data;
407
+		nz = data;
408
+		goto inc_pc_loop;
409
+	
410
+	case 0xFB: // MOV Y,dp+X
411
+		data = (uint8_t) (data + x);
412
+	case 0xEB: // MOV Y,dp
413
+		// 70% from timer
414
+		pc++;
415
+		READ_DP_TIMER( 0, data, y = nz );
416
+		goto loop;
417
+	
418
+	case 0xEC:{// MOV Y,abs
419
+		int temp = READ_PC16( pc );
420
+		pc += 2;
421
+		READ_TIMER( 0, temp, y = nz );
422
+		//y = nz = READ( 0, temp );
423
+		goto loop;
424
+	}
425
+	
426
+	case 0x8D: // MOV Y,imm
427
+		y  = data;
428
+		nz = data;
429
+		goto inc_pc_loop;
430
+	
431
+// 2. 8-BIT DATA TRANSMISSION COMMANDS, GROUP 2
432
+
433
+	ADDR_MODES_NO_DP( 0xC8 ) // MOV addr,A
434
+		WRITE( 0, data, a );
435
+		goto inc_pc_loop;
436
+	
437
+	{
438
+		int temp;
439
+	case 0xCC: // MOV abs,Y
440
+		temp = y;
441
+		goto mov_abs_temp;
442
+	case 0xC9: // MOV abs,X
443
+		temp = x;
444
+	mov_abs_temp:
445
+		WRITE( 0, READ_PC16( pc ), temp );
446
+		pc += 2;
447
+		goto loop;
448
+	}
449
+	
450
+	case 0xD9: // MOV dp+Y,X
451
+		data = (uint8_t) (data + y);
452
+	case 0xD8: // MOV dp,X
453
+		WRITE( 0, data + dp, x );
454
+		goto inc_pc_loop;
455
+	
456
+	case 0xDB: // MOV dp+X,Y
457
+		data = (uint8_t) (data + x);
458
+	case 0xCB: // MOV dp,Y
459
+		WRITE( 0, data + dp, y );
460
+		goto inc_pc_loop;
461
+
462
+// 3. 8-BIT DATA TRANSMISSIN COMMANDS, GROUP 3.
463
+	
464
+	case 0x7D: // MOV A,X
465
+		a  = x;
466
+		nz = x;
467
+		goto loop;
468
+	
469
+	case 0xDD: // MOV A,Y
470
+		a  = y;
471
+		nz = y;
472
+		goto loop;
473
+	
474
+	case 0x5D: // MOV X,A
475
+		x  = a;
476
+		nz = a;
477
+		goto loop;
478
+	
479
+	case 0xFD: // MOV Y,A
480
+		y  = a;
481
+		nz = a;
482
+		goto loop;
483
+	
484
+	case 0x9D: // MOV X,SP
485
+		x = nz = GET_SP();
486
+		goto loop;
487
+	
488
+	case 0xBD: // MOV SP,X
489
+		SET_SP( x );
490
+		goto loop;
491
+	
492
+	//case 0xC6: // MOV (X),A (handled by MOV addr,A in group 2)
493
+	
494
+	case 0xAF: // MOV (X)+,A
495
+		WRITE_DP( 0, x, a + no_read_before_write  );
496
+		x++;
497
+		goto loop;
498
+	
499
+// 5. 8-BIT LOGIC OPERATION COMMANDS
500
+	
501
+#define LOGICAL_OP( op, func )\
502
+	ADDR_MODES( op ) /* addr */\
503
+		data = READ( 0, data );\
504
+	case op: /* imm */\
505
+		nz = a func##= data;\
506
+		goto inc_pc_loop;\
507
+	{   unsigned addr;\
508
+	case op + 0x11: /* X,Y */\
509
+		data = READ_DP( -2, y );\
510
+		addr = x + dp;\
511
+		goto addr_##op;\
512
+	case op + 0x01: /* dp,dp */\
513
+		data = READ_DP( -3, data );\
514
+	case op + 0x10:{/*dp,imm*/\
515
+		uint8_t const* addr2 = pc + 1;\
516
+		pc += 2;\
517
+		addr = READ_PC( addr2 ) + dp;\
518
+	}\
519
+	addr_##op:\
520
+		nz = data func READ( -1, addr );\
521
+		WRITE( 0, addr, nz );\
522
+		goto loop;\
523
+	}
524
+	
525
+	LOGICAL_OP( 0x28, & ); // AND
526
+	
527
+	LOGICAL_OP( 0x08, | ); // OR
528
+	
529
+	LOGICAL_OP( 0x48, ^ ); // EOR
530
+	
531
+// 4. 8-BIT ARITHMETIC OPERATION COMMANDS
532
+
533
+	ADDR_MODES( 0x68 ) // CMP addr
534
+		data = READ( 0, data );
535
+	case 0x68: // CMP imm
536
+		nz = a - data;
537
+		c = ~nz;
538
+		nz &= 0xFF;
539
+		goto inc_pc_loop;
540
+	
541
+	case 0x79: // CMP (X),(Y)
542
+		data = READ_DP( -2, y );
543
+		nz = READ_DP( -1, x ) - data;
544
+		c = ~nz;
545
+		nz &= 0xFF;
546
+		goto loop;
547
+	
548
+	case 0x69: // CMP dp,dp
549
+		data = READ_DP( -3, data );
550
+	case 0x78: // CMP dp,imm
551
+		nz = READ_DP( -1, READ_PC( ++pc ) ) - data;
552
+		c = ~nz;
553
+		nz &= 0xFF;
554
+		goto inc_pc_loop;
555
+	
556
+	case 0x3E: // CMP X,dp
557
+		data += dp;
558
+		goto cmp_x_addr;
559
+	case 0x1E: // CMP X,abs
560
+		data = READ_PC16( pc );
561
+		pc++;
562
+	cmp_x_addr:
563
+		data = READ( 0, data );
564
+	case 0xC8: // CMP X,imm
565
+		nz = x - data;
566
+		c = ~nz;
567
+		nz &= 0xFF;
568
+		goto inc_pc_loop;
569
+	
570
+	case 0x7E: // CMP Y,dp
571
+		data += dp;
572
+		goto cmp_y_addr;
573
+	case 0x5E: // CMP Y,abs
574
+		data = READ_PC16( pc );
575
+		pc++;
576
+	cmp_y_addr:
577
+		data = READ( 0, data );
578
+	case 0xAD: // CMP Y,imm
579
+		nz = y - data;
580
+		c = ~nz;
581
+		nz &= 0xFF;
582
+		goto inc_pc_loop;
583
+	
584
+	{
585
+		int addr;
586
+	case 0xB9: // SBC (x),(y)
587
+	case 0x99: // ADC (x),(y)
588
+		pc--; // compensate for inc later
589
+		data = READ_DP( -2, y );
590
+		addr = x + dp;
591
+		goto adc_addr;
592
+	case 0xA9: // SBC dp,dp
593
+	case 0x89: // ADC dp,dp
594
+		data = READ_DP( -3, data );
595
+	case 0xB8: // SBC dp,imm
596
+	case 0x98: // ADC dp,imm
597
+		addr = READ_PC( ++pc ) + dp;
598
+	adc_addr:
599
+		nz = READ( -1, addr );
600
+		goto adc_data;
601
+		
602
+// catch ADC and SBC together, then decode later based on operand
603
+#undef CASE
604
+#define CASE( n ) case n: case (n) + 0x20:
605
+	ADDR_MODES( 0x88 ) // ADC/SBC addr
606
+		data = READ( 0, data );
607
+	case 0xA8: // SBC imm
608
+	case 0x88: // ADC imm
609
+		addr = -1; // A
610
+		nz = a;
611
+	adc_data: {
612
+		int flags;
613
+		if ( opcode >= 0xA0 ) // SBC
614
+			data ^= 0xFF;
615
+		
616
+		flags = data ^ nz;
617
+		nz += data + (c >> 8 & 1);
618
+		flags ^= nz;
619
+		
620
+		psw = (psw & ~(v40 | h08)) |
621
+				(flags >> 1 & h08) |
622
+				((flags + 0x80) >> 2 & v40);
623
+		c = nz;
624
+		if ( addr < 0 )
625
+		{
626
+			a = (uint8_t) nz;
627
+			goto inc_pc_loop;
628
+		}
629
+		WRITE( 0, addr, /*(uint8_t)*/ nz );
630
+		goto inc_pc_loop;
631
+	}
632
+	
633
+	}
634
+	
635
+// 6. ADDITION & SUBTRACTION COMMANDS
636
+
637
+#define INC_DEC_REG( reg, op )\
638
+		nz  = reg op;\
639
+		reg = (uint8_t) nz;\
640
+		goto loop;
641
+
642
+	case 0xBC: INC_DEC_REG( a, + 1 ) // INC A
643
+	case 0x3D: INC_DEC_REG( x, + 1 ) // INC X
644
+	case 0xFC: INC_DEC_REG( y, + 1 ) // INC Y
645
+	
646
+	case 0x9C: INC_DEC_REG( a, - 1 ) // DEC A
647
+	case 0x1D: INC_DEC_REG( x, - 1 ) // DEC X
648
+	case 0xDC: INC_DEC_REG( y, - 1 ) // DEC Y
649
+
650
+	case 0x9B: // DEC dp+X
651
+	case 0xBB: // INC dp+X
652
+		data = (uint8_t) (data + x);
653
+	case 0x8B: // DEC dp
654
+	case 0xAB: // INC dp
655
+		data += dp;
656
+		goto inc_abs;
657
+	case 0x8C: // DEC abs
658
+	case 0xAC: // INC abs
659
+		data = READ_PC16( pc );
660
+		pc++;
661
+	inc_abs:
662
+		nz = (opcode >> 4 & 2) - 1;
663
+		nz += READ( -1, data );
664
+		WRITE( 0, data, /*(uint8_t)*/ nz );
665
+		goto inc_pc_loop;
666
+	
667
+// 7. SHIFT, ROTATION COMMANDS
668
+
669
+	case 0x5C: // LSR A
670
+		c = 0;
671
+	case 0x7C:{// ROR A
672
+		nz = (c >> 1 & 0x80) | (a >> 1);
673
+		c = a << 8;
674
+		a = nz;
675
+		goto loop;
676
+	}
677
+	
678
+	case 0x1C: // ASL A
679
+		c = 0;
680
+	case 0x3C:{// ROL A
681
+		int temp = c >> 8 & 1;
682
+		c = a << 1;
683
+		nz = c | temp;
684
+		a = (uint8_t) nz;
685
+		goto loop;
686
+	}
687
+	
688
+	case 0x0B: // ASL dp
689
+		c = 0;
690
+		data += dp;
691
+		goto rol_mem;
692
+	case 0x1B: // ASL dp+X
693
+		c = 0;
694
+	case 0x3B: // ROL dp+X
695
+		data = (uint8_t) (data + x);
696
+	case 0x2B: // ROL dp
697
+		data += dp;
698
+		goto rol_mem;
699
+	case 0x0C: // ASL abs
700
+		c = 0;
701
+	case 0x2C: // ROL abs
702
+		data = READ_PC16( pc );
703
+		pc++;
704
+	rol_mem:
705
+		nz = c >> 8 & 1;
706
+		nz |= (c = READ( -1, data ) << 1);
707
+		WRITE( 0, data, /*(uint8_t)*/ nz );
708
+		goto inc_pc_loop;
709
+	
710
+	case 0x4B: // LSR dp
711
+		c = 0;
712
+		data += dp;
713
+		goto ror_mem;
714
+	case 0x5B: // LSR dp+X
715
+		c = 0;
716
+	case 0x7B: // ROR dp+X
717
+		data = (uint8_t) (data + x);
718
+	case 0x6B: // ROR dp
719
+		data += dp;
720
+		goto ror_mem;
721
+	case 0x4C: // LSR abs
722
+		c = 0;
723
+	case 0x6C: // ROR abs
724
+		data = READ_PC16( pc );
725
+		pc++;
726
+	ror_mem: {
727
+		int temp = READ( -1, data );
728
+		nz = (c >> 1 & 0x80) | (temp >> 1);
729
+		c = temp << 8;
730
+		WRITE( 0, data, nz );
731
+		goto inc_pc_loop;
732
+	}
733
+
734
+	case 0x9F: // XCN
735
+		nz = a = (a >> 4) | (uint8_t) (a << 4);
736
+		goto loop;
737
+
738
+// 8. 16-BIT TRANSMISION COMMANDS
739
+
740
+	case 0xBA: // MOVW YA,dp
741
+		a = READ_DP( -2, data );
742
+		nz = (a & 0x7F) | (a >> 1);
743
+		y = READ_DP( 0, (uint8_t) (data + 1) );
744
+		nz |= y;
745
+		goto inc_pc_loop;
746
+	
747
+	case 0xDA: // MOVW dp,YA
748
+		WRITE_DP( -1, data, a );
749
+		WRITE_DP( 0, (uint8_t) (data + 1), y + no_read_before_write  );
750
+		goto inc_pc_loop;
751
+	
752
+// 9. 16-BIT OPERATION COMMANDS
753
+
754
+	case 0x3A: // INCW dp
755
+	case 0x1A:{// DECW dp
756
+		int temp;
757
+		// low byte
758
+		data += dp;
759
+		temp = READ( -3, data );
760
+		temp += (opcode >> 4 & 2) - 1; // +1 for INCW, -1 for DECW
761
+		nz = ((temp >> 1) | temp) & 0x7F;
762
+		WRITE( -2, data, /*(uint8_t)*/ temp );
763
+		
764
+		// high byte
765
+		data = (uint8_t) (data + 1) + dp;
766
+		temp = (uint8_t) ((temp >> 8) + READ( -1, data ));
767
+		nz |= temp;
768
+		WRITE( 0, data, temp );
769
+		
770
+		goto inc_pc_loop;
771
+	}
772
+		
773
+	case 0x7A: // ADDW YA,dp
774
+	case 0x9A:{// SUBW YA,dp
775
+		int lo = READ_DP( -2, data );
776
+		int hi = READ_DP( 0, (uint8_t) (data + 1) );
777
+		int result;
778
+		int flags;
779
+		
780
+		if ( opcode == 0x9A ) // SUBW
781
+		{
782
+			lo = (lo ^ 0xFF) + 1;
783
+			hi ^= 0xFF;
784
+		}
785
+		
786
+		lo += a;
787
+		result = y + hi + (lo >> 8);
788
+		flags = hi ^ y ^ result;
789
+		
790
+		psw = (psw & ~(v40 | h08)) |
791
+				(flags >> 1 & h08) |
792
+				((flags + 0x80) >> 2 & v40);
793
+		c = result;
794
+		a = (uint8_t) lo;
795
+		result = (uint8_t) result;
796
+		y = result;
797
+		nz = (((lo >> 1) | lo) & 0x7F) | result;
798
+		
799
+		goto inc_pc_loop;
800
+	}
801
+	
802
+	case 0x5A: { // CMPW YA,dp
803
+		int temp = a - READ_DP( -1, data );
804
+		nz = ((temp >> 1) | temp) & 0x7F;
805
+		temp = y + (temp >> 8);
806
+		temp -= READ_DP( 0, (uint8_t) (data + 1) );
807
+		nz |= temp;
808
+		c  = ~temp;
809
+		nz &= 0xFF;
810
+		goto inc_pc_loop;
811
+	}
812
+	
813
+// 10. MULTIPLICATION & DIVISON COMMANDS
814
+
815
+	case 0xCF: { // MUL YA
816
+		unsigned temp = y * a;
817
+		a = (uint8_t) temp;
818
+		nz = ((temp >> 1) | temp) & 0x7F;
819
+		y = temp >> 8;
820
+		nz |= y;
821
+		goto loop;
822
+	}
823
+	
824
+	case 0x9E: // DIV YA,X
825
+	{
826
+		unsigned ya = y * 0x100 + a;
827
+		
828
+		psw &= ~(h08 | v40);
829
+		
830
+		if ( y >= x )
831
+			psw |= v40;
832
+		
833
+		if ( (y & 15) >= (x & 15) )
834
+			psw |= h08;
835
+		
836
+		if ( y < x * 2 )
837
+		{
838
+			a = ya / x;
839
+			y = ya - a * x;
840
+		}
841
+		else
842
+		{
843
+			a = 255 - (ya - x * 0x200) / (256 - x);
844
+			y = x   + (ya - x * 0x200) % (256 - x);
845
+		}
846
+		
847
+		nz = (uint8_t) a;
848
+		a = (uint8_t) a;
849
+		
850
+		goto loop;
851
+	}
852
+	
853
+// 11. DECIMAL COMPENSATION COMMANDS
854
+	
855
+	case 0xDF: // DAA
856
+		SUSPICIOUS_OPCODE( "DAA" );
857
+		if ( a > 0x99 || c & 0x100 )
858
+		{
859
+			a += 0x60;
860
+			c = 0x100;
861
+		}
862
+		
863
+		if ( (a & 0x0F) > 9 || psw & h08 )
864
+			a += 0x06;
865
+		
866
+		nz = a;
867
+		a = (uint8_t) a;
868
+		goto loop;
869
+	
870
+	case 0xBE: // DAS
871
+		SUSPICIOUS_OPCODE( "DAS" );
872
+		if ( a > 0x99 || !(c & 0x100) )
873
+		{
874
+			a -= 0x60;
875
+			c = 0;
876
+		}
877
+		
878
+		if ( (a & 0x0F) > 9 || !(psw & h08) )
879
+			a -= 0x06;
880
+		
881
+		nz = a;
882
+		a = (uint8_t) a;
883
+		goto loop;
884
+	
885
+// 12. BRANCHING COMMANDS
886
+
887
+	case 0x2F: // BRA rel
888
+		pc += (BOOST::int8_t) data;
889
+		goto inc_pc_loop;
890
+	
891
+	case 0x30: // BMI
892
+		BRANCH( (nz & nz_neg_mask) )
893
+	
894
+	case 0x10: // BPL
895
+		BRANCH( !(nz & nz_neg_mask) )
896
+	
897
+	case 0xB0: // BCS
898
+		BRANCH( c & 0x100 )
899
+	
900
+	case 0x90: // BCC
901
+		BRANCH( !(c & 0x100) )
902
+	
903
+	case 0x70: // BVS
904
+		BRANCH( psw & v40 )
905
+	
906
+	case 0x50: // BVC
907
+		BRANCH( !(psw & v40) )
908
+	
909
+	#define CBRANCH( cond )\
910
+	{\
911
+		pc++;\
912
+		if ( cond )\
913
+			goto cbranch_taken_loop;\
914
+		rel_time -= 2;\
915
+		goto inc_pc_loop;\
916
+	}
917
+	
918
+	case 0x03: // BBS dp.bit,rel
919
+	case 0x23:
920
+	case 0x43:
921
+	case 0x63:
922
+	case 0x83:
923
+	case 0xA3:
924
+	case 0xC3:
925
+	case 0xE3:
926
+		CBRANCH( READ_DP( -4, data ) >> (opcode >> 5) & 1 )
927
+	
928
+	case 0x13: // BBC dp.bit,rel
929
+	case 0x33:
930
+	case 0x53:
931
+	case 0x73:
932
+	case 0x93:
933
+	case 0xB3:
934
+	case 0xD3:
935
+	case 0xF3:
936
+		CBRANCH( !(READ_DP( -4, data ) >> (opcode >> 5) & 1) )
937
+	
938
+	case 0xDE: // CBNE dp+X,rel
939
+		data = (uint8_t) (data + x);
940
+		// fall through
941
+	case 0x2E:{// CBNE dp,rel
942
+		int temp;
943
+		// 61% from timer
944
+		READ_DP_TIMER( -4, data, temp );
945
+		CBRANCH( temp != a )
946
+	}
947
+	
948
+	case 0x6E: { // DBNZ dp,rel
949
+		unsigned temp = READ_DP( -4, data ) - 1;
950
+		WRITE_DP( -3, (uint8_t) data, /*(uint8_t)*/ temp + no_read_before_write  );
951
+		CBRANCH( temp )
952
+	}
953
+	
954
+	case 0xFE: // DBNZ Y,rel
955
+		y = (uint8_t) (y - 1);
956
+		BRANCH( y )
957
+	
958
+	case 0x1F: // JMP [abs+X]
959
+		SET_PC( READ_PC16( pc ) + x );
960
+		// fall through
961
+	case 0x5F: // JMP abs
962
+		SET_PC( READ_PC16( pc ) );
963
+		goto loop;
964
+	
965
+// 13. SUB-ROUTINE CALL RETURN COMMANDS
966
+	
967
+	case 0x0F:{// BRK
968
+		int temp;
969
+		int ret_addr = GET_PC();
970
+		SUSPICIOUS_OPCODE( "BRK" );
971
+		SET_PC( READ_PROG16( 0xFFDE ) ); // vector address verified
972
+		PUSH16( ret_addr );
973
+		GET_PSW( temp );
974
+		psw = (psw | b10) & ~i04;
975
+		PUSH( temp );
976
+		goto loop;
977
+	}
978
+	
979
+	case 0x4F:{// PCALL offset
980
+		int ret_addr = GET_PC() + 1;
981
+		SET_PC( 0xFF00 | data );
982
+		PUSH16( ret_addr );
983
+		goto loop;
984
+	}
985
+	
986
+	case 0x01: // TCALL n
987
+	case 0x11:
988
+	case 0x21:
989
+	case 0x31:
990
+	case 0x41:
991
+	case 0x51:
992
+	case 0x61:
993
+	case 0x71:
994
+	case 0x81:
995
+	case 0x91:
996
+	case 0xA1:
997
+	case 0xB1:
998
+	case 0xC1:
999
+	case 0xD1:
1000
+	case 0xE1:
1001
+	case 0xF1: {
1002
+		int ret_addr = GET_PC();
1003
+		SET_PC( READ_PROG16( 0xFFDE - (opcode >> 3) ) );
1004
+		PUSH16( ret_addr );
1005
+		goto loop;
1006
+	}
1007
+	
1008
+// 14. STACK OPERATION COMMANDS
1009
+
1010
+	{
1011
+		int temp;
1012
+	case 0x7F: // RET1
1013
+		temp = *sp;
1014
+		SET_PC( GET_LE16( sp + 1 ) );
1015
+		sp += 3;
1016
+		goto set_psw;
1017
+	case 0x8E: // POP PSW
1018
+		POP( temp );
1019
+	set_psw:
1020
+		SET_PSW( temp );
1021
+		goto loop;
1022
+	}
1023
+	
1024
+	case 0x0D: { // PUSH PSW
1025
+		int temp;
1026
+		GET_PSW( temp );
1027
+		PUSH( temp );
1028
+		goto loop;
1029
+	}
1030
+
1031
+	case 0x2D: // PUSH A
1032
+		PUSH( a );
1033
+		goto loop;
1034
+	
1035
+	case 0x4D: // PUSH X
1036
+		PUSH( x );
1037
+		goto loop;
1038
+	
1039
+	case 0x6D: // PUSH Y
1040
+		PUSH( y );
1041
+		goto loop;
1042
+	
1043
+	case 0xAE: // POP A
1044
+		POP( a );
1045
+		goto loop;
1046
+	
1047
+	case 0xCE: // POP X
1048
+		POP( x );
1049
+		goto loop;
1050
+	
1051
+	case 0xEE: // POP Y
1052
+		POP( y );
1053
+		goto loop;
1054
+	
1055
+// 15. BIT OPERATION COMMANDS
1056
+
1057
+	case 0x02: // SET1
1058
+	case 0x22:
1059
+	case 0x42:
1060
+	case 0x62:
1061
+	case 0x82:
1062
+	case 0xA2:
1063
+	case 0xC2:
1064
+	case 0xE2:
1065
+	case 0x12: // CLR1
1066
+	case 0x32:
1067
+	case 0x52:
1068
+	case 0x72:
1069
+	case 0x92:
1070
+	case 0xB2:
1071
+	case 0xD2:
1072
+	case 0xF2: {
1073
+		int bit = 1 << (opcode >> 5);
1074
+		int mask = ~bit;
1075
+		if ( opcode & 0x10 )
1076
+			bit = 0;
1077
+		data += dp;
1078
+		WRITE( 0, data, (READ( -1, data ) & mask) | bit );
1079
+		goto inc_pc_loop;
1080
+	}
1081
+		
1082
+	case 0x0E: // TSET1 abs
1083
+	case 0x4E: // TCLR1 abs
1084
+		data = READ_PC16( pc );
1085
+		pc += 2;
1086
+		{
1087
+			unsigned temp = READ( -2, data );
1088
+			nz = (uint8_t) (a - temp);
1089
+			temp &= ~a;
1090
+			if ( opcode == 0x0E )
1091
+				temp |= a;
1092
+			WRITE( 0, data, temp );
1093
+		}
1094
+		goto loop;
1095
+	
1096
+	case 0x4A: // AND1 C,mem.bit
1097
+		c &= MEM_BIT( 0 );
1098
+		pc += 2;
1099
+		goto loop;
1100
+	
1101
+	case 0x6A: // AND1 C,/mem.bit
1102
+		c &= ~MEM_BIT( 0 );
1103
+		pc += 2;
1104
+		goto loop;
1105
+	
1106
+	case 0x0A: // OR1 C,mem.bit
1107
+		c |= MEM_BIT( -1 );
1108
+		pc += 2;
1109
+		goto loop;
1110
+	
1111
+	case 0x2A: // OR1 C,/mem.bit
1112
+		c |= ~MEM_BIT( -1 );
1113
+		pc += 2;
1114
+		goto loop;
1115
+	
1116
+	case 0x8A: // EOR1 C,mem.bit
1117
+		c ^= MEM_BIT( -1 );
1118
+		pc += 2;
1119
+		goto loop;
1120
+	
1121
+	case 0xEA: // NOT1 mem.bit
1122
+		data = READ_PC16( pc );
1123
+		pc += 2;
1124
+		{
1125
+			unsigned temp = READ( -1, data & 0x1FFF );
1126
+			temp ^= 1 << (data >> 13);
1127
+			WRITE( 0, data & 0x1FFF, temp );
1128
+		}
1129
+		goto loop;
1130
+	
1131
+	case 0xCA: // MOV1 mem.bit,C
1132
+		data = READ_PC16( pc );
1133
+		pc += 2;
1134
+		{
1135
+			unsigned temp = READ( -2, data & 0x1FFF );
1136
+			unsigned bit = data >> 13;
1137
+			temp = (temp & ~(1 << bit)) | ((c >> 8 & 1) << bit);
1138
+			WRITE( 0, data & 0x1FFF, temp + no_read_before_write  );
1139
+		}
1140
+		goto loop;
1141
+	
1142
+	case 0xAA: // MOV1 C,mem.bit
1143
+		c = MEM_BIT( 0 );
1144
+		pc += 2;
1145
+		goto loop;
1146
+	
1147
+// 16. PROGRAM PSW FLAG OPERATION COMMANDS
1148
+
1149
+	case 0x60: // CLRC
1150
+		c = 0;
1151
+		goto loop;
1152
+		
1153
+	case 0x80: // SETC
1154
+		c = ~0;
1155
+		goto loop;
1156
+	
1157
+	case 0xED: // NOTC
1158
+		c ^= 0x100;
1159
+		goto loop;
1160
+		
1161
+	case 0xE0: // CLRV
1162
+		psw &= ~(v40 | h08);
1163
+		goto loop;
1164
+	
1165
+	case 0x20: // CLRP
1166
+		dp = 0;
1167
+		goto loop;
1168
+	
1169
+	case 0x40: // SETP
1170
+		dp = 0x100;
1171
+		goto loop;
1172
+	
1173
+	case 0xA0: // EI
1174
+		SUSPICIOUS_OPCODE( "EI" );
1175
+		psw |= i04;
1176
+		goto loop;
1177
+	
1178
+	case 0xC0: // DI
1179
+		SUSPICIOUS_OPCODE( "DI" );
1180
+		psw &= ~i04;
1181
+		goto loop;
1182
+	
1183
+// 17. OTHER COMMANDS
1184
+
1185
+	case 0x00: // NOP
1186
+		goto loop;
1187
+	
1188
+	case 0xFF:{// STOP
1189
+		// handle PC wrap-around
1190
+		unsigned addr = GET_PC() - 1;
1191
+		if ( addr >= 0x10000 )
1192
+		{
1193
+			addr &= 0xFFFF;
1194
+			SET_PC( addr );
1195
+			dprintf( "SPC: PC wrapped around\n" );
1196
+			goto loop;
1197
+		}
1198
+	}
1199
+	// fall through
1200
+	case 0xEF: // SLEEP
1201
+		SUSPICIOUS_OPCODE( "STOP/SLEEP" );
1202
+		--pc;
1203
+		rel_time = 0;
1204
+		m.cpu_error = "SPC emulation error";
1205
+		goto stop;
1206
+	} // switch
1207
+	
1208
+	assert( 0 ); // catch any unhandled instructions
1209
+}   
1210
+out_of_time:
1211
+	rel_time -= m.cycle_table [*pc]; // undo partial execution of opcode
1212
+stop:
1213
+	
1214
+	// Uncache registers
1215
+	if ( GET_PC() >= 0x10000 )
1216
+		dprintf( "SPC: PC wrapped around\n" );
1217
+	m.cpu_regs.pc = (uint16_t) GET_PC();
1218
+	m.cpu_regs.sp = ( uint8_t) GET_SP();
1219
+	m.cpu_regs.a  = ( uint8_t) a;
1220
+	m.cpu_regs.x  = ( uint8_t) x;
1221
+	m.cpu_regs.y  = ( uint8_t) y;
1222
+	{
1223
+		int temp;
1224
+		GET_PSW( temp );
1225
+		m.cpu_regs.psw = (uint8_t) temp;
1226
+	}
1227
+}
1228
+SPC_CPU_RUN_FUNC_END