Mercurial > spc_convert
diff snes_spc/SPC_CPU.h @ 0:e38dacceb958
initial import
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Fri, 21 Oct 2011 05:53:11 -0700 |
parents | |
children |
line wrap: on
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/snes_spc/SPC_CPU.h Fri Oct 21 05:53:11 2011 -0700 1.3 @@ -0,0 +1,1220 @@ 1.4 +// snes_spc 0.9.0. http://www.slack.net/~ant/ 1.5 + 1.6 +/* Copyright (C) 2004-2007 Shay Green. This module is free software; you 1.7 +can redistribute it and/or modify it under the terms of the GNU Lesser 1.8 +General Public License as published by the Free Software Foundation; either 1.9 +version 2.1 of the License, or (at your option) any later version. This 1.10 +module is distributed in the hope that it will be useful, but WITHOUT ANY 1.11 +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 1.12 +FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more 1.13 +details. You should have received a copy of the GNU Lesser General Public 1.14 +License along with this module; if not, write to the Free Software Foundation, 1.15 +Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ 1.16 + 1.17 +//// Memory access 1.18 + 1.19 +#if SPC_MORE_ACCURACY 1.20 + #define SUSPICIOUS_OPCODE( name ) ((void) 0) 1.21 +#else 1.22 + #define SUSPICIOUS_OPCODE( name ) dprintf( "SPC: suspicious opcode: " name "\n" ) 1.23 +#endif 1.24 + 1.25 +#define CPU_READ( time, offset, addr )\ 1.26 + cpu_read( addr, time + offset ) 1.27 + 1.28 +#define CPU_WRITE( time, offset, addr, data )\ 1.29 + cpu_write( data, addr, time + offset ) 1.30 + 1.31 +#if SPC_MORE_ACCURACY 1.32 + #define CPU_READ_TIMER( time, offset, addr, out )\ 1.33 + { out = CPU_READ( time, offset, addr ); } 1.34 + 1.35 +#else 1.36 + // timers are by far the most common thing read from dp 1.37 + #define CPU_READ_TIMER( time, offset, addr_, out )\ 1.38 + {\ 1.39 + rel_time_t adj_time = time + offset;\ 1.40 + int dp_addr = addr_;\ 1.41 + int ti = dp_addr - (r_t0out + 0xF0);\ 1.42 + if ( (unsigned) ti < timer_count )\ 1.43 + {\ 1.44 + Timer* t = &m.timers [ti];\ 1.45 + if ( adj_time >= t->next_time )\ 1.46 + t = run_timer_( t, adj_time );\ 1.47 + out = t->counter;\ 1.48 + t->counter = 0;\ 1.49 + }\ 1.50 + else\ 1.51 + {\ 1.52 + out = ram [dp_addr];\ 1.53 + int i = dp_addr - 0xF0;\ 1.54 + if ( (unsigned) i < 0x10 )\ 1.55 + out = cpu_read_smp_reg( i, adj_time );\ 1.56 + }\ 1.57 + } 1.58 +#endif 1.59 + 1.60 +#define TIME_ADJ( n ) (n) 1.61 + 1.62 +#define READ_TIMER( time, addr, out ) CPU_READ_TIMER( rel_time, TIME_ADJ(time), (addr), out ) 1.63 +#define READ( time, addr ) CPU_READ ( rel_time, TIME_ADJ(time), (addr) ) 1.64 +#define WRITE( time, addr, data ) CPU_WRITE( rel_time, TIME_ADJ(time), (addr), (data) ) 1.65 + 1.66 +#define DP_ADDR( addr ) (dp + (addr)) 1.67 + 1.68 +#define READ_DP_TIMER( time, addr, out ) CPU_READ_TIMER( rel_time, TIME_ADJ(time), DP_ADDR( addr ), out ) 1.69 +#define READ_DP( time, addr ) READ ( time, DP_ADDR( addr ) ) 1.70 +#define WRITE_DP( time, addr, data ) WRITE( time, DP_ADDR( addr ), data ) 1.71 + 1.72 +#define READ_PROG16( addr ) GET_LE16( ram + (addr) ) 1.73 + 1.74 +#define SET_PC( n ) (pc = ram + (n)) 1.75 +#define GET_PC() (pc - ram) 1.76 +#define READ_PC( pc ) (*(pc)) 1.77 +#define READ_PC16( pc ) GET_LE16( pc ) 1.78 + 1.79 +// TODO: remove non-wrapping versions? 1.80 +#define SPC_NO_SP_WRAPAROUND 0 1.81 + 1.82 +#define SET_SP( v ) (sp = ram + 0x101 + (v)) 1.83 +#define GET_SP() (sp - 0x101 - ram) 1.84 + 1.85 +#if SPC_NO_SP_WRAPAROUND 1.86 +#define PUSH16( v ) (sp -= 2, SET_LE16( sp, v )) 1.87 +#define PUSH( v ) (void) (*--sp = (uint8_t) (v)) 1.88 +#define POP( out ) (void) ((out) = *sp++) 1.89 + 1.90 +#else 1.91 +#define PUSH16( data )\ 1.92 +{\ 1.93 + int addr = (sp -= 2) - ram;\ 1.94 + if ( addr > 0x100 )\ 1.95 + {\ 1.96 + SET_LE16( sp, data );\ 1.97 + }\ 1.98 + else\ 1.99 + {\ 1.100 + ram [(uint8_t) addr + 0x100] = (uint8_t) data;\ 1.101 + sp [1] = (uint8_t) (data >> 8);\ 1.102 + sp += 0x100;\ 1.103 + }\ 1.104 +} 1.105 + 1.106 +#define PUSH( data )\ 1.107 +{\ 1.108 + *--sp = (uint8_t) (data);\ 1.109 + if ( sp - ram == 0x100 )\ 1.110 + sp += 0x100;\ 1.111 +} 1.112 + 1.113 +#define POP( out )\ 1.114 +{\ 1.115 + out = *sp++;\ 1.116 + if ( sp - ram == 0x201 )\ 1.117 + {\ 1.118 + out = sp [-0x101];\ 1.119 + sp -= 0x100;\ 1.120 + }\ 1.121 +} 1.122 + 1.123 +#endif 1.124 + 1.125 +#define MEM_BIT( rel ) CPU_mem_bit( pc, rel_time + rel ) 1.126 + 1.127 +unsigned SNES_SPC::CPU_mem_bit( uint8_t const* pc, rel_time_t rel_time ) 1.128 +{ 1.129 + unsigned addr = READ_PC16( pc ); 1.130 + unsigned t = READ( 0, addr & 0x1FFF ) >> (addr >> 13); 1.131 + return t << 8 & 0x100; 1.132 +} 1.133 + 1.134 +//// Status flag handling 1.135 + 1.136 +// Hex value in name to clarify code and bit shifting. 1.137 +// Flag stored in indicated variable during emulation 1.138 +int const n80 = 0x80; // nz 1.139 +int const v40 = 0x40; // psw 1.140 +int const p20 = 0x20; // dp 1.141 +int const b10 = 0x10; // psw 1.142 +int const h08 = 0x08; // psw 1.143 +int const i04 = 0x04; // psw 1.144 +int const z02 = 0x02; // nz 1.145 +int const c01 = 0x01; // c 1.146 + 1.147 +int const nz_neg_mask = 0x880; // either bit set indicates N flag set 1.148 + 1.149 +#define GET_PSW( out )\ 1.150 +{\ 1.151 + out = psw & ~(n80 | p20 | z02 | c01);\ 1.152 + out |= c >> 8 & c01;\ 1.153 + out |= dp >> 3 & p20;\ 1.154 + out |= ((nz >> 4) | nz) & n80;\ 1.155 + if ( !(uint8_t) nz ) out |= z02;\ 1.156 +} 1.157 + 1.158 +#define SET_PSW( in )\ 1.159 +{\ 1.160 + psw = in;\ 1.161 + c = in << 8;\ 1.162 + dp = in << 3 & 0x100;\ 1.163 + nz = (in << 4 & 0x800) | (~in & z02);\ 1.164 +} 1.165 + 1.166 +SPC_CPU_RUN_FUNC 1.167 +{ 1.168 + uint8_t* const ram = RAM; 1.169 + int a = m.cpu_regs.a; 1.170 + int x = m.cpu_regs.x; 1.171 + int y = m.cpu_regs.y; 1.172 + uint8_t const* pc; 1.173 + uint8_t* sp; 1.174 + int psw; 1.175 + int c; 1.176 + int nz; 1.177 + int dp; 1.178 + 1.179 + SET_PC( m.cpu_regs.pc ); 1.180 + SET_SP( m.cpu_regs.sp ); 1.181 + SET_PSW( m.cpu_regs.psw ); 1.182 + 1.183 + goto loop; 1.184 + 1.185 + 1.186 + // Main loop 1.187 + 1.188 +cbranch_taken_loop: 1.189 + pc += *(BOOST::int8_t const*) pc; 1.190 +inc_pc_loop: 1.191 + pc++; 1.192 +loop: 1.193 +{ 1.194 + unsigned opcode; 1.195 + unsigned data; 1.196 + 1.197 + check( (unsigned) a < 0x100 ); 1.198 + check( (unsigned) x < 0x100 ); 1.199 + check( (unsigned) y < 0x100 ); 1.200 + 1.201 + opcode = *pc; 1.202 + if ( (rel_time += m.cycle_table [opcode]) > 0 ) 1.203 + goto out_of_time; 1.204 + 1.205 + #ifdef SPC_CPU_OPCODE_HOOK 1.206 + SPC_CPU_OPCODE_HOOK( GET_PC(), opcode ); 1.207 + #endif 1.208 + /* 1.209 + //SUB_CASE_COUNTER( 1 ); 1.210 + #define PROFILE_TIMER_LOOP( op, addr, len )\ 1.211 + if ( opcode == op )\ 1.212 + {\ 1.213 + int cond = (unsigned) ((addr) - 0xFD) < 3 &&\ 1.214 + pc [len] == 0xF0 && pc [len+1] == 0xFE - len;\ 1.215 + SUB_CASE_COUNTER( op && cond );\ 1.216 + } 1.217 + 1.218 + PROFILE_TIMER_LOOP( 0xEC, GET_LE16( pc + 1 ), 3 ); 1.219 + PROFILE_TIMER_LOOP( 0xEB, pc [1], 2 ); 1.220 + PROFILE_TIMER_LOOP( 0xE4, pc [1], 2 ); 1.221 + */ 1.222 + 1.223 + // TODO: if PC is at end of memory, this will get wrong operand (very obscure) 1.224 + data = *++pc; 1.225 + switch ( opcode ) 1.226 + { 1.227 + 1.228 +// Common instructions 1.229 + 1.230 +#define BRANCH( cond )\ 1.231 +{\ 1.232 + pc++;\ 1.233 + pc += (BOOST::int8_t) data;\ 1.234 + if ( cond )\ 1.235 + goto loop;\ 1.236 + pc -= (BOOST::int8_t) data;\ 1.237 + rel_time -= 2;\ 1.238 + goto loop;\ 1.239 +} 1.240 + 1.241 + case 0xF0: // BEQ 1.242 + BRANCH( !(uint8_t) nz ) // 89% taken 1.243 + 1.244 + case 0xD0: // BNE 1.245 + BRANCH( (uint8_t) nz ) 1.246 + 1.247 + case 0x3F:{// CALL 1.248 + int old_addr = GET_PC() + 2; 1.249 + SET_PC( READ_PC16( pc ) ); 1.250 + PUSH16( old_addr ); 1.251 + goto loop; 1.252 + } 1.253 + 1.254 + case 0x6F:// RET 1.255 + #if SPC_NO_SP_WRAPAROUND 1.256 + { 1.257 + SET_PC( GET_LE16( sp ) ); 1.258 + sp += 2; 1.259 + } 1.260 + #else 1.261 + { 1.262 + int addr = sp - ram; 1.263 + SET_PC( GET_LE16( sp ) ); 1.264 + sp += 2; 1.265 + if ( addr < 0x1FF ) 1.266 + goto loop; 1.267 + 1.268 + SET_PC( sp [-0x101] * 0x100 + ram [(uint8_t) addr + 0x100] ); 1.269 + sp -= 0x100; 1.270 + } 1.271 + #endif 1.272 + goto loop; 1.273 + 1.274 + case 0xE4: // MOV a,dp 1.275 + ++pc; 1.276 + // 80% from timer 1.277 + READ_DP_TIMER( 0, data, a = nz ); 1.278 + goto loop; 1.279 + 1.280 + case 0xFA:{// MOV dp,dp 1.281 + int temp; 1.282 + READ_DP_TIMER( -2, data, temp ); 1.283 + data = temp + no_read_before_write ; 1.284 + } 1.285 + // fall through 1.286 + case 0x8F:{// MOV dp,#imm 1.287 + int temp = READ_PC( pc + 1 ); 1.288 + pc += 2; 1.289 + 1.290 + #if !SPC_MORE_ACCURACY 1.291 + { 1.292 + int i = dp + temp; 1.293 + ram [i] = (uint8_t) data; 1.294 + i -= 0xF0; 1.295 + if ( (unsigned) i < 0x10 ) // 76% 1.296 + { 1.297 + REGS [i] = (uint8_t) data; 1.298 + 1.299 + // Registers other than $F2 and $F4-$F7 1.300 + //if ( i != 2 && i != 4 && i != 5 && i != 6 && i != 7 ) 1.301 + if ( ((~0x2F00 << (bits_in_int - 16)) << i) < 0 ) // 12% 1.302 + cpu_write_smp_reg( data, rel_time, i ); 1.303 + } 1.304 + } 1.305 + #else 1.306 + WRITE_DP( 0, temp, data ); 1.307 + #endif 1.308 + goto loop; 1.309 + } 1.310 + 1.311 + case 0xC4: // MOV dp,a 1.312 + ++pc; 1.313 + #if !SPC_MORE_ACCURACY 1.314 + { 1.315 + int i = dp + data; 1.316 + ram [i] = (uint8_t) a; 1.317 + i -= 0xF0; 1.318 + if ( (unsigned) i < 0x10 ) // 39% 1.319 + { 1.320 + unsigned sel = i - 2; 1.321 + REGS [i] = (uint8_t) a; 1.322 + 1.323 + if ( sel == 1 ) // 51% $F3 1.324 + dsp_write( a, rel_time ); 1.325 + else if ( sel > 1 ) // 1% not $F2 or $F3 1.326 + cpu_write_smp_reg_( a, rel_time, i ); 1.327 + } 1.328 + } 1.329 + #else 1.330 + WRITE_DP( 0, data, a ); 1.331 + #endif 1.332 + goto loop; 1.333 + 1.334 +#define CASE( n ) case n: 1.335 + 1.336 +// Define common address modes based on opcode for immediate mode. Execution 1.337 +// ends with data set to the address of the operand. 1.338 +#define ADDR_MODES_( op )\ 1.339 + CASE( op - 0x02 ) /* (X) */\ 1.340 + data = x + dp;\ 1.341 + pc--;\ 1.342 + goto end_##op;\ 1.343 + CASE( op + 0x0F ) /* (dp)+Y */\ 1.344 + data = READ_PROG16( data + dp ) + y;\ 1.345 + goto end_##op;\ 1.346 + CASE( op - 0x01 ) /* (dp+X) */\ 1.347 + data = READ_PROG16( ((uint8_t) (data + x)) + dp );\ 1.348 + goto end_##op;\ 1.349 + CASE( op + 0x0E ) /* abs+Y */\ 1.350 + data += y;\ 1.351 + goto abs_##op;\ 1.352 + CASE( op + 0x0D ) /* abs+X */\ 1.353 + data += x;\ 1.354 + CASE( op - 0x03 ) /* abs */\ 1.355 + abs_##op:\ 1.356 + data += 0x100 * READ_PC( ++pc );\ 1.357 + goto end_##op;\ 1.358 + CASE( op + 0x0C ) /* dp+X */\ 1.359 + data = (uint8_t) (data + x); 1.360 + 1.361 +#define ADDR_MODES_NO_DP( op )\ 1.362 + ADDR_MODES_( op )\ 1.363 + data += dp;\ 1.364 + end_##op: 1.365 + 1.366 +#define ADDR_MODES( op )\ 1.367 + ADDR_MODES_( op )\ 1.368 + CASE( op - 0x04 ) /* dp */\ 1.369 + data += dp;\ 1.370 + end_##op: 1.371 + 1.372 +// 1. 8-bit Data Transmission Commands. Group I 1.373 + 1.374 + ADDR_MODES_NO_DP( 0xE8 ) // MOV A,addr 1.375 + a = nz = READ( 0, data ); 1.376 + goto inc_pc_loop; 1.377 + 1.378 + case 0xBF:{// MOV A,(X)+ 1.379 + int temp = x + dp; 1.380 + x = (uint8_t) (x + 1); 1.381 + a = nz = READ( -1, temp ); 1.382 + goto loop; 1.383 + } 1.384 + 1.385 + case 0xE8: // MOV A,imm 1.386 + a = data; 1.387 + nz = data; 1.388 + goto inc_pc_loop; 1.389 + 1.390 + case 0xF9: // MOV X,dp+Y 1.391 + data = (uint8_t) (data + y); 1.392 + case 0xF8: // MOV X,dp 1.393 + READ_DP_TIMER( 0, data, x = nz ); 1.394 + goto inc_pc_loop; 1.395 + 1.396 + case 0xE9: // MOV X,abs 1.397 + data = READ_PC16( pc ); 1.398 + ++pc; 1.399 + data = READ( 0, data ); 1.400 + case 0xCD: // MOV X,imm 1.401 + x = data; 1.402 + nz = data; 1.403 + goto inc_pc_loop; 1.404 + 1.405 + case 0xFB: // MOV Y,dp+X 1.406 + data = (uint8_t) (data + x); 1.407 + case 0xEB: // MOV Y,dp 1.408 + // 70% from timer 1.409 + pc++; 1.410 + READ_DP_TIMER( 0, data, y = nz ); 1.411 + goto loop; 1.412 + 1.413 + case 0xEC:{// MOV Y,abs 1.414 + int temp = READ_PC16( pc ); 1.415 + pc += 2; 1.416 + READ_TIMER( 0, temp, y = nz ); 1.417 + //y = nz = READ( 0, temp ); 1.418 + goto loop; 1.419 + } 1.420 + 1.421 + case 0x8D: // MOV Y,imm 1.422 + y = data; 1.423 + nz = data; 1.424 + goto inc_pc_loop; 1.425 + 1.426 +// 2. 8-BIT DATA TRANSMISSION COMMANDS, GROUP 2 1.427 + 1.428 + ADDR_MODES_NO_DP( 0xC8 ) // MOV addr,A 1.429 + WRITE( 0, data, a ); 1.430 + goto inc_pc_loop; 1.431 + 1.432 + { 1.433 + int temp; 1.434 + case 0xCC: // MOV abs,Y 1.435 + temp = y; 1.436 + goto mov_abs_temp; 1.437 + case 0xC9: // MOV abs,X 1.438 + temp = x; 1.439 + mov_abs_temp: 1.440 + WRITE( 0, READ_PC16( pc ), temp ); 1.441 + pc += 2; 1.442 + goto loop; 1.443 + } 1.444 + 1.445 + case 0xD9: // MOV dp+Y,X 1.446 + data = (uint8_t) (data + y); 1.447 + case 0xD8: // MOV dp,X 1.448 + WRITE( 0, data + dp, x ); 1.449 + goto inc_pc_loop; 1.450 + 1.451 + case 0xDB: // MOV dp+X,Y 1.452 + data = (uint8_t) (data + x); 1.453 + case 0xCB: // MOV dp,Y 1.454 + WRITE( 0, data + dp, y ); 1.455 + goto inc_pc_loop; 1.456 + 1.457 +// 3. 8-BIT DATA TRANSMISSIN COMMANDS, GROUP 3. 1.458 + 1.459 + case 0x7D: // MOV A,X 1.460 + a = x; 1.461 + nz = x; 1.462 + goto loop; 1.463 + 1.464 + case 0xDD: // MOV A,Y 1.465 + a = y; 1.466 + nz = y; 1.467 + goto loop; 1.468 + 1.469 + case 0x5D: // MOV X,A 1.470 + x = a; 1.471 + nz = a; 1.472 + goto loop; 1.473 + 1.474 + case 0xFD: // MOV Y,A 1.475 + y = a; 1.476 + nz = a; 1.477 + goto loop; 1.478 + 1.479 + case 0x9D: // MOV X,SP 1.480 + x = nz = GET_SP(); 1.481 + goto loop; 1.482 + 1.483 + case 0xBD: // MOV SP,X 1.484 + SET_SP( x ); 1.485 + goto loop; 1.486 + 1.487 + //case 0xC6: // MOV (X),A (handled by MOV addr,A in group 2) 1.488 + 1.489 + case 0xAF: // MOV (X)+,A 1.490 + WRITE_DP( 0, x, a + no_read_before_write ); 1.491 + x++; 1.492 + goto loop; 1.493 + 1.494 +// 5. 8-BIT LOGIC OPERATION COMMANDS 1.495 + 1.496 +#define LOGICAL_OP( op, func )\ 1.497 + ADDR_MODES( op ) /* addr */\ 1.498 + data = READ( 0, data );\ 1.499 + case op: /* imm */\ 1.500 + nz = a func##= data;\ 1.501 + goto inc_pc_loop;\ 1.502 + { unsigned addr;\ 1.503 + case op + 0x11: /* X,Y */\ 1.504 + data = READ_DP( -2, y );\ 1.505 + addr = x + dp;\ 1.506 + goto addr_##op;\ 1.507 + case op + 0x01: /* dp,dp */\ 1.508 + data = READ_DP( -3, data );\ 1.509 + case op + 0x10:{/*dp,imm*/\ 1.510 + uint8_t const* addr2 = pc + 1;\ 1.511 + pc += 2;\ 1.512 + addr = READ_PC( addr2 ) + dp;\ 1.513 + }\ 1.514 + addr_##op:\ 1.515 + nz = data func READ( -1, addr );\ 1.516 + WRITE( 0, addr, nz );\ 1.517 + goto loop;\ 1.518 + } 1.519 + 1.520 + LOGICAL_OP( 0x28, & ); // AND 1.521 + 1.522 + LOGICAL_OP( 0x08, | ); // OR 1.523 + 1.524 + LOGICAL_OP( 0x48, ^ ); // EOR 1.525 + 1.526 +// 4. 8-BIT ARITHMETIC OPERATION COMMANDS 1.527 + 1.528 + ADDR_MODES( 0x68 ) // CMP addr 1.529 + data = READ( 0, data ); 1.530 + case 0x68: // CMP imm 1.531 + nz = a - data; 1.532 + c = ~nz; 1.533 + nz &= 0xFF; 1.534 + goto inc_pc_loop; 1.535 + 1.536 + case 0x79: // CMP (X),(Y) 1.537 + data = READ_DP( -2, y ); 1.538 + nz = READ_DP( -1, x ) - data; 1.539 + c = ~nz; 1.540 + nz &= 0xFF; 1.541 + goto loop; 1.542 + 1.543 + case 0x69: // CMP dp,dp 1.544 + data = READ_DP( -3, data ); 1.545 + case 0x78: // CMP dp,imm 1.546 + nz = READ_DP( -1, READ_PC( ++pc ) ) - data; 1.547 + c = ~nz; 1.548 + nz &= 0xFF; 1.549 + goto inc_pc_loop; 1.550 + 1.551 + case 0x3E: // CMP X,dp 1.552 + data += dp; 1.553 + goto cmp_x_addr; 1.554 + case 0x1E: // CMP X,abs 1.555 + data = READ_PC16( pc ); 1.556 + pc++; 1.557 + cmp_x_addr: 1.558 + data = READ( 0, data ); 1.559 + case 0xC8: // CMP X,imm 1.560 + nz = x - data; 1.561 + c = ~nz; 1.562 + nz &= 0xFF; 1.563 + goto inc_pc_loop; 1.564 + 1.565 + case 0x7E: // CMP Y,dp 1.566 + data += dp; 1.567 + goto cmp_y_addr; 1.568 + case 0x5E: // CMP Y,abs 1.569 + data = READ_PC16( pc ); 1.570 + pc++; 1.571 + cmp_y_addr: 1.572 + data = READ( 0, data ); 1.573 + case 0xAD: // CMP Y,imm 1.574 + nz = y - data; 1.575 + c = ~nz; 1.576 + nz &= 0xFF; 1.577 + goto inc_pc_loop; 1.578 + 1.579 + { 1.580 + int addr; 1.581 + case 0xB9: // SBC (x),(y) 1.582 + case 0x99: // ADC (x),(y) 1.583 + pc--; // compensate for inc later 1.584 + data = READ_DP( -2, y ); 1.585 + addr = x + dp; 1.586 + goto adc_addr; 1.587 + case 0xA9: // SBC dp,dp 1.588 + case 0x89: // ADC dp,dp 1.589 + data = READ_DP( -3, data ); 1.590 + case 0xB8: // SBC dp,imm 1.591 + case 0x98: // ADC dp,imm 1.592 + addr = READ_PC( ++pc ) + dp; 1.593 + adc_addr: 1.594 + nz = READ( -1, addr ); 1.595 + goto adc_data; 1.596 + 1.597 +// catch ADC and SBC together, then decode later based on operand 1.598 +#undef CASE 1.599 +#define CASE( n ) case n: case (n) + 0x20: 1.600 + ADDR_MODES( 0x88 ) // ADC/SBC addr 1.601 + data = READ( 0, data ); 1.602 + case 0xA8: // SBC imm 1.603 + case 0x88: // ADC imm 1.604 + addr = -1; // A 1.605 + nz = a; 1.606 + adc_data: { 1.607 + int flags; 1.608 + if ( opcode >= 0xA0 ) // SBC 1.609 + data ^= 0xFF; 1.610 + 1.611 + flags = data ^ nz; 1.612 + nz += data + (c >> 8 & 1); 1.613 + flags ^= nz; 1.614 + 1.615 + psw = (psw & ~(v40 | h08)) | 1.616 + (flags >> 1 & h08) | 1.617 + ((flags + 0x80) >> 2 & v40); 1.618 + c = nz; 1.619 + if ( addr < 0 ) 1.620 + { 1.621 + a = (uint8_t) nz; 1.622 + goto inc_pc_loop; 1.623 + } 1.624 + WRITE( 0, addr, /*(uint8_t)*/ nz ); 1.625 + goto inc_pc_loop; 1.626 + } 1.627 + 1.628 + } 1.629 + 1.630 +// 6. ADDITION & SUBTRACTION COMMANDS 1.631 + 1.632 +#define INC_DEC_REG( reg, op )\ 1.633 + nz = reg op;\ 1.634 + reg = (uint8_t) nz;\ 1.635 + goto loop; 1.636 + 1.637 + case 0xBC: INC_DEC_REG( a, + 1 ) // INC A 1.638 + case 0x3D: INC_DEC_REG( x, + 1 ) // INC X 1.639 + case 0xFC: INC_DEC_REG( y, + 1 ) // INC Y 1.640 + 1.641 + case 0x9C: INC_DEC_REG( a, - 1 ) // DEC A 1.642 + case 0x1D: INC_DEC_REG( x, - 1 ) // DEC X 1.643 + case 0xDC: INC_DEC_REG( y, - 1 ) // DEC Y 1.644 + 1.645 + case 0x9B: // DEC dp+X 1.646 + case 0xBB: // INC dp+X 1.647 + data = (uint8_t) (data + x); 1.648 + case 0x8B: // DEC dp 1.649 + case 0xAB: // INC dp 1.650 + data += dp; 1.651 + goto inc_abs; 1.652 + case 0x8C: // DEC abs 1.653 + case 0xAC: // INC abs 1.654 + data = READ_PC16( pc ); 1.655 + pc++; 1.656 + inc_abs: 1.657 + nz = (opcode >> 4 & 2) - 1; 1.658 + nz += READ( -1, data ); 1.659 + WRITE( 0, data, /*(uint8_t)*/ nz ); 1.660 + goto inc_pc_loop; 1.661 + 1.662 +// 7. SHIFT, ROTATION COMMANDS 1.663 + 1.664 + case 0x5C: // LSR A 1.665 + c = 0; 1.666 + case 0x7C:{// ROR A 1.667 + nz = (c >> 1 & 0x80) | (a >> 1); 1.668 + c = a << 8; 1.669 + a = nz; 1.670 + goto loop; 1.671 + } 1.672 + 1.673 + case 0x1C: // ASL A 1.674 + c = 0; 1.675 + case 0x3C:{// ROL A 1.676 + int temp = c >> 8 & 1; 1.677 + c = a << 1; 1.678 + nz = c | temp; 1.679 + a = (uint8_t) nz; 1.680 + goto loop; 1.681 + } 1.682 + 1.683 + case 0x0B: // ASL dp 1.684 + c = 0; 1.685 + data += dp; 1.686 + goto rol_mem; 1.687 + case 0x1B: // ASL dp+X 1.688 + c = 0; 1.689 + case 0x3B: // ROL dp+X 1.690 + data = (uint8_t) (data + x); 1.691 + case 0x2B: // ROL dp 1.692 + data += dp; 1.693 + goto rol_mem; 1.694 + case 0x0C: // ASL abs 1.695 + c = 0; 1.696 + case 0x2C: // ROL abs 1.697 + data = READ_PC16( pc ); 1.698 + pc++; 1.699 + rol_mem: 1.700 + nz = c >> 8 & 1; 1.701 + nz |= (c = READ( -1, data ) << 1); 1.702 + WRITE( 0, data, /*(uint8_t)*/ nz ); 1.703 + goto inc_pc_loop; 1.704 + 1.705 + case 0x4B: // LSR dp 1.706 + c = 0; 1.707 + data += dp; 1.708 + goto ror_mem; 1.709 + case 0x5B: // LSR dp+X 1.710 + c = 0; 1.711 + case 0x7B: // ROR dp+X 1.712 + data = (uint8_t) (data + x); 1.713 + case 0x6B: // ROR dp 1.714 + data += dp; 1.715 + goto ror_mem; 1.716 + case 0x4C: // LSR abs 1.717 + c = 0; 1.718 + case 0x6C: // ROR abs 1.719 + data = READ_PC16( pc ); 1.720 + pc++; 1.721 + ror_mem: { 1.722 + int temp = READ( -1, data ); 1.723 + nz = (c >> 1 & 0x80) | (temp >> 1); 1.724 + c = temp << 8; 1.725 + WRITE( 0, data, nz ); 1.726 + goto inc_pc_loop; 1.727 + } 1.728 + 1.729 + case 0x9F: // XCN 1.730 + nz = a = (a >> 4) | (uint8_t) (a << 4); 1.731 + goto loop; 1.732 + 1.733 +// 8. 16-BIT TRANSMISION COMMANDS 1.734 + 1.735 + case 0xBA: // MOVW YA,dp 1.736 + a = READ_DP( -2, data ); 1.737 + nz = (a & 0x7F) | (a >> 1); 1.738 + y = READ_DP( 0, (uint8_t) (data + 1) ); 1.739 + nz |= y; 1.740 + goto inc_pc_loop; 1.741 + 1.742 + case 0xDA: // MOVW dp,YA 1.743 + WRITE_DP( -1, data, a ); 1.744 + WRITE_DP( 0, (uint8_t) (data + 1), y + no_read_before_write ); 1.745 + goto inc_pc_loop; 1.746 + 1.747 +// 9. 16-BIT OPERATION COMMANDS 1.748 + 1.749 + case 0x3A: // INCW dp 1.750 + case 0x1A:{// DECW dp 1.751 + int temp; 1.752 + // low byte 1.753 + data += dp; 1.754 + temp = READ( -3, data ); 1.755 + temp += (opcode >> 4 & 2) - 1; // +1 for INCW, -1 for DECW 1.756 + nz = ((temp >> 1) | temp) & 0x7F; 1.757 + WRITE( -2, data, /*(uint8_t)*/ temp ); 1.758 + 1.759 + // high byte 1.760 + data = (uint8_t) (data + 1) + dp; 1.761 + temp = (uint8_t) ((temp >> 8) + READ( -1, data )); 1.762 + nz |= temp; 1.763 + WRITE( 0, data, temp ); 1.764 + 1.765 + goto inc_pc_loop; 1.766 + } 1.767 + 1.768 + case 0x7A: // ADDW YA,dp 1.769 + case 0x9A:{// SUBW YA,dp 1.770 + int lo = READ_DP( -2, data ); 1.771 + int hi = READ_DP( 0, (uint8_t) (data + 1) ); 1.772 + int result; 1.773 + int flags; 1.774 + 1.775 + if ( opcode == 0x9A ) // SUBW 1.776 + { 1.777 + lo = (lo ^ 0xFF) + 1; 1.778 + hi ^= 0xFF; 1.779 + } 1.780 + 1.781 + lo += a; 1.782 + result = y + hi + (lo >> 8); 1.783 + flags = hi ^ y ^ result; 1.784 + 1.785 + psw = (psw & ~(v40 | h08)) | 1.786 + (flags >> 1 & h08) | 1.787 + ((flags + 0x80) >> 2 & v40); 1.788 + c = result; 1.789 + a = (uint8_t) lo; 1.790 + result = (uint8_t) result; 1.791 + y = result; 1.792 + nz = (((lo >> 1) | lo) & 0x7F) | result; 1.793 + 1.794 + goto inc_pc_loop; 1.795 + } 1.796 + 1.797 + case 0x5A: { // CMPW YA,dp 1.798 + int temp = a - READ_DP( -1, data ); 1.799 + nz = ((temp >> 1) | temp) & 0x7F; 1.800 + temp = y + (temp >> 8); 1.801 + temp -= READ_DP( 0, (uint8_t) (data + 1) ); 1.802 + nz |= temp; 1.803 + c = ~temp; 1.804 + nz &= 0xFF; 1.805 + goto inc_pc_loop; 1.806 + } 1.807 + 1.808 +// 10. MULTIPLICATION & DIVISON COMMANDS 1.809 + 1.810 + case 0xCF: { // MUL YA 1.811 + unsigned temp = y * a; 1.812 + a = (uint8_t) temp; 1.813 + nz = ((temp >> 1) | temp) & 0x7F; 1.814 + y = temp >> 8; 1.815 + nz |= y; 1.816 + goto loop; 1.817 + } 1.818 + 1.819 + case 0x9E: // DIV YA,X 1.820 + { 1.821 + unsigned ya = y * 0x100 + a; 1.822 + 1.823 + psw &= ~(h08 | v40); 1.824 + 1.825 + if ( y >= x ) 1.826 + psw |= v40; 1.827 + 1.828 + if ( (y & 15) >= (x & 15) ) 1.829 + psw |= h08; 1.830 + 1.831 + if ( y < x * 2 ) 1.832 + { 1.833 + a = ya / x; 1.834 + y = ya - a * x; 1.835 + } 1.836 + else 1.837 + { 1.838 + a = 255 - (ya - x * 0x200) / (256 - x); 1.839 + y = x + (ya - x * 0x200) % (256 - x); 1.840 + } 1.841 + 1.842 + nz = (uint8_t) a; 1.843 + a = (uint8_t) a; 1.844 + 1.845 + goto loop; 1.846 + } 1.847 + 1.848 +// 11. DECIMAL COMPENSATION COMMANDS 1.849 + 1.850 + case 0xDF: // DAA 1.851 + SUSPICIOUS_OPCODE( "DAA" ); 1.852 + if ( a > 0x99 || c & 0x100 ) 1.853 + { 1.854 + a += 0x60; 1.855 + c = 0x100; 1.856 + } 1.857 + 1.858 + if ( (a & 0x0F) > 9 || psw & h08 ) 1.859 + a += 0x06; 1.860 + 1.861 + nz = a; 1.862 + a = (uint8_t) a; 1.863 + goto loop; 1.864 + 1.865 + case 0xBE: // DAS 1.866 + SUSPICIOUS_OPCODE( "DAS" ); 1.867 + if ( a > 0x99 || !(c & 0x100) ) 1.868 + { 1.869 + a -= 0x60; 1.870 + c = 0; 1.871 + } 1.872 + 1.873 + if ( (a & 0x0F) > 9 || !(psw & h08) ) 1.874 + a -= 0x06; 1.875 + 1.876 + nz = a; 1.877 + a = (uint8_t) a; 1.878 + goto loop; 1.879 + 1.880 +// 12. BRANCHING COMMANDS 1.881 + 1.882 + case 0x2F: // BRA rel 1.883 + pc += (BOOST::int8_t) data; 1.884 + goto inc_pc_loop; 1.885 + 1.886 + case 0x30: // BMI 1.887 + BRANCH( (nz & nz_neg_mask) ) 1.888 + 1.889 + case 0x10: // BPL 1.890 + BRANCH( !(nz & nz_neg_mask) ) 1.891 + 1.892 + case 0xB0: // BCS 1.893 + BRANCH( c & 0x100 ) 1.894 + 1.895 + case 0x90: // BCC 1.896 + BRANCH( !(c & 0x100) ) 1.897 + 1.898 + case 0x70: // BVS 1.899 + BRANCH( psw & v40 ) 1.900 + 1.901 + case 0x50: // BVC 1.902 + BRANCH( !(psw & v40) ) 1.903 + 1.904 + #define CBRANCH( cond )\ 1.905 + {\ 1.906 + pc++;\ 1.907 + if ( cond )\ 1.908 + goto cbranch_taken_loop;\ 1.909 + rel_time -= 2;\ 1.910 + goto inc_pc_loop;\ 1.911 + } 1.912 + 1.913 + case 0x03: // BBS dp.bit,rel 1.914 + case 0x23: 1.915 + case 0x43: 1.916 + case 0x63: 1.917 + case 0x83: 1.918 + case 0xA3: 1.919 + case 0xC3: 1.920 + case 0xE3: 1.921 + CBRANCH( READ_DP( -4, data ) >> (opcode >> 5) & 1 ) 1.922 + 1.923 + case 0x13: // BBC dp.bit,rel 1.924 + case 0x33: 1.925 + case 0x53: 1.926 + case 0x73: 1.927 + case 0x93: 1.928 + case 0xB3: 1.929 + case 0xD3: 1.930 + case 0xF3: 1.931 + CBRANCH( !(READ_DP( -4, data ) >> (opcode >> 5) & 1) ) 1.932 + 1.933 + case 0xDE: // CBNE dp+X,rel 1.934 + data = (uint8_t) (data + x); 1.935 + // fall through 1.936 + case 0x2E:{// CBNE dp,rel 1.937 + int temp; 1.938 + // 61% from timer 1.939 + READ_DP_TIMER( -4, data, temp ); 1.940 + CBRANCH( temp != a ) 1.941 + } 1.942 + 1.943 + case 0x6E: { // DBNZ dp,rel 1.944 + unsigned temp = READ_DP( -4, data ) - 1; 1.945 + WRITE_DP( -3, (uint8_t) data, /*(uint8_t)*/ temp + no_read_before_write ); 1.946 + CBRANCH( temp ) 1.947 + } 1.948 + 1.949 + case 0xFE: // DBNZ Y,rel 1.950 + y = (uint8_t) (y - 1); 1.951 + BRANCH( y ) 1.952 + 1.953 + case 0x1F: // JMP [abs+X] 1.954 + SET_PC( READ_PC16( pc ) + x ); 1.955 + // fall through 1.956 + case 0x5F: // JMP abs 1.957 + SET_PC( READ_PC16( pc ) ); 1.958 + goto loop; 1.959 + 1.960 +// 13. SUB-ROUTINE CALL RETURN COMMANDS 1.961 + 1.962 + case 0x0F:{// BRK 1.963 + int temp; 1.964 + int ret_addr = GET_PC(); 1.965 + SUSPICIOUS_OPCODE( "BRK" ); 1.966 + SET_PC( READ_PROG16( 0xFFDE ) ); // vector address verified 1.967 + PUSH16( ret_addr ); 1.968 + GET_PSW( temp ); 1.969 + psw = (psw | b10) & ~i04; 1.970 + PUSH( temp ); 1.971 + goto loop; 1.972 + } 1.973 + 1.974 + case 0x4F:{// PCALL offset 1.975 + int ret_addr = GET_PC() + 1; 1.976 + SET_PC( 0xFF00 | data ); 1.977 + PUSH16( ret_addr ); 1.978 + goto loop; 1.979 + } 1.980 + 1.981 + case 0x01: // TCALL n 1.982 + case 0x11: 1.983 + case 0x21: 1.984 + case 0x31: 1.985 + case 0x41: 1.986 + case 0x51: 1.987 + case 0x61: 1.988 + case 0x71: 1.989 + case 0x81: 1.990 + case 0x91: 1.991 + case 0xA1: 1.992 + case 0xB1: 1.993 + case 0xC1: 1.994 + case 0xD1: 1.995 + case 0xE1: 1.996 + case 0xF1: { 1.997 + int ret_addr = GET_PC(); 1.998 + SET_PC( READ_PROG16( 0xFFDE - (opcode >> 3) ) ); 1.999 + PUSH16( ret_addr ); 1.1000 + goto loop; 1.1001 + } 1.1002 + 1.1003 +// 14. STACK OPERATION COMMANDS 1.1004 + 1.1005 + { 1.1006 + int temp; 1.1007 + case 0x7F: // RET1 1.1008 + temp = *sp; 1.1009 + SET_PC( GET_LE16( sp + 1 ) ); 1.1010 + sp += 3; 1.1011 + goto set_psw; 1.1012 + case 0x8E: // POP PSW 1.1013 + POP( temp ); 1.1014 + set_psw: 1.1015 + SET_PSW( temp ); 1.1016 + goto loop; 1.1017 + } 1.1018 + 1.1019 + case 0x0D: { // PUSH PSW 1.1020 + int temp; 1.1021 + GET_PSW( temp ); 1.1022 + PUSH( temp ); 1.1023 + goto loop; 1.1024 + } 1.1025 + 1.1026 + case 0x2D: // PUSH A 1.1027 + PUSH( a ); 1.1028 + goto loop; 1.1029 + 1.1030 + case 0x4D: // PUSH X 1.1031 + PUSH( x ); 1.1032 + goto loop; 1.1033 + 1.1034 + case 0x6D: // PUSH Y 1.1035 + PUSH( y ); 1.1036 + goto loop; 1.1037 + 1.1038 + case 0xAE: // POP A 1.1039 + POP( a ); 1.1040 + goto loop; 1.1041 + 1.1042 + case 0xCE: // POP X 1.1043 + POP( x ); 1.1044 + goto loop; 1.1045 + 1.1046 + case 0xEE: // POP Y 1.1047 + POP( y ); 1.1048 + goto loop; 1.1049 + 1.1050 +// 15. BIT OPERATION COMMANDS 1.1051 + 1.1052 + case 0x02: // SET1 1.1053 + case 0x22: 1.1054 + case 0x42: 1.1055 + case 0x62: 1.1056 + case 0x82: 1.1057 + case 0xA2: 1.1058 + case 0xC2: 1.1059 + case 0xE2: 1.1060 + case 0x12: // CLR1 1.1061 + case 0x32: 1.1062 + case 0x52: 1.1063 + case 0x72: 1.1064 + case 0x92: 1.1065 + case 0xB2: 1.1066 + case 0xD2: 1.1067 + case 0xF2: { 1.1068 + int bit = 1 << (opcode >> 5); 1.1069 + int mask = ~bit; 1.1070 + if ( opcode & 0x10 ) 1.1071 + bit = 0; 1.1072 + data += dp; 1.1073 + WRITE( 0, data, (READ( -1, data ) & mask) | bit ); 1.1074 + goto inc_pc_loop; 1.1075 + } 1.1076 + 1.1077 + case 0x0E: // TSET1 abs 1.1078 + case 0x4E: // TCLR1 abs 1.1079 + data = READ_PC16( pc ); 1.1080 + pc += 2; 1.1081 + { 1.1082 + unsigned temp = READ( -2, data ); 1.1083 + nz = (uint8_t) (a - temp); 1.1084 + temp &= ~a; 1.1085 + if ( opcode == 0x0E ) 1.1086 + temp |= a; 1.1087 + WRITE( 0, data, temp ); 1.1088 + } 1.1089 + goto loop; 1.1090 + 1.1091 + case 0x4A: // AND1 C,mem.bit 1.1092 + c &= MEM_BIT( 0 ); 1.1093 + pc += 2; 1.1094 + goto loop; 1.1095 + 1.1096 + case 0x6A: // AND1 C,/mem.bit 1.1097 + c &= ~MEM_BIT( 0 ); 1.1098 + pc += 2; 1.1099 + goto loop; 1.1100 + 1.1101 + case 0x0A: // OR1 C,mem.bit 1.1102 + c |= MEM_BIT( -1 ); 1.1103 + pc += 2; 1.1104 + goto loop; 1.1105 + 1.1106 + case 0x2A: // OR1 C,/mem.bit 1.1107 + c |= ~MEM_BIT( -1 ); 1.1108 + pc += 2; 1.1109 + goto loop; 1.1110 + 1.1111 + case 0x8A: // EOR1 C,mem.bit 1.1112 + c ^= MEM_BIT( -1 ); 1.1113 + pc += 2; 1.1114 + goto loop; 1.1115 + 1.1116 + case 0xEA: // NOT1 mem.bit 1.1117 + data = READ_PC16( pc ); 1.1118 + pc += 2; 1.1119 + { 1.1120 + unsigned temp = READ( -1, data & 0x1FFF ); 1.1121 + temp ^= 1 << (data >> 13); 1.1122 + WRITE( 0, data & 0x1FFF, temp ); 1.1123 + } 1.1124 + goto loop; 1.1125 + 1.1126 + case 0xCA: // MOV1 mem.bit,C 1.1127 + data = READ_PC16( pc ); 1.1128 + pc += 2; 1.1129 + { 1.1130 + unsigned temp = READ( -2, data & 0x1FFF ); 1.1131 + unsigned bit = data >> 13; 1.1132 + temp = (temp & ~(1 << bit)) | ((c >> 8 & 1) << bit); 1.1133 + WRITE( 0, data & 0x1FFF, temp + no_read_before_write ); 1.1134 + } 1.1135 + goto loop; 1.1136 + 1.1137 + case 0xAA: // MOV1 C,mem.bit 1.1138 + c = MEM_BIT( 0 ); 1.1139 + pc += 2; 1.1140 + goto loop; 1.1141 + 1.1142 +// 16. PROGRAM PSW FLAG OPERATION COMMANDS 1.1143 + 1.1144 + case 0x60: // CLRC 1.1145 + c = 0; 1.1146 + goto loop; 1.1147 + 1.1148 + case 0x80: // SETC 1.1149 + c = ~0; 1.1150 + goto loop; 1.1151 + 1.1152 + case 0xED: // NOTC 1.1153 + c ^= 0x100; 1.1154 + goto loop; 1.1155 + 1.1156 + case 0xE0: // CLRV 1.1157 + psw &= ~(v40 | h08); 1.1158 + goto loop; 1.1159 + 1.1160 + case 0x20: // CLRP 1.1161 + dp = 0; 1.1162 + goto loop; 1.1163 + 1.1164 + case 0x40: // SETP 1.1165 + dp = 0x100; 1.1166 + goto loop; 1.1167 + 1.1168 + case 0xA0: // EI 1.1169 + SUSPICIOUS_OPCODE( "EI" ); 1.1170 + psw |= i04; 1.1171 + goto loop; 1.1172 + 1.1173 + case 0xC0: // DI 1.1174 + SUSPICIOUS_OPCODE( "DI" ); 1.1175 + psw &= ~i04; 1.1176 + goto loop; 1.1177 + 1.1178 +// 17. OTHER COMMANDS 1.1179 + 1.1180 + case 0x00: // NOP 1.1181 + goto loop; 1.1182 + 1.1183 + case 0xFF:{// STOP 1.1184 + // handle PC wrap-around 1.1185 + unsigned addr = GET_PC() - 1; 1.1186 + if ( addr >= 0x10000 ) 1.1187 + { 1.1188 + addr &= 0xFFFF; 1.1189 + SET_PC( addr ); 1.1190 + dprintf( "SPC: PC wrapped around\n" ); 1.1191 + goto loop; 1.1192 + } 1.1193 + } 1.1194 + // fall through 1.1195 + case 0xEF: // SLEEP 1.1196 + SUSPICIOUS_OPCODE( "STOP/SLEEP" ); 1.1197 + --pc; 1.1198 + rel_time = 0; 1.1199 + m.cpu_error = "SPC emulation error"; 1.1200 + goto stop; 1.1201 + } // switch 1.1202 + 1.1203 + assert( 0 ); // catch any unhandled instructions 1.1204 +} 1.1205 +out_of_time: 1.1206 + rel_time -= m.cycle_table [*pc]; // undo partial execution of opcode 1.1207 +stop: 1.1208 + 1.1209 + // Uncache registers 1.1210 + if ( GET_PC() >= 0x10000 ) 1.1211 + dprintf( "SPC: PC wrapped around\n" ); 1.1212 + m.cpu_regs.pc = (uint16_t) GET_PC(); 1.1213 + m.cpu_regs.sp = ( uint8_t) GET_SP(); 1.1214 + m.cpu_regs.a = ( uint8_t) a; 1.1215 + m.cpu_regs.x = ( uint8_t) x; 1.1216 + m.cpu_regs.y = ( uint8_t) y; 1.1217 + { 1.1218 + int temp; 1.1219 + GET_PSW( temp ); 1.1220 + m.cpu_regs.psw = (uint8_t) temp; 1.1221 + } 1.1222 +} 1.1223 +SPC_CPU_RUN_FUNC_END