summaryrefslogtreecommitdiff
path: root/apps/codecs/libspc/spc_cpu.c
diff options
context:
space:
mode:
authorSean Bartell <wingedtachikoma@gmail.com>2011-06-25 21:32:25 -0400
committerNils Wallménius <nils@rockbox.org>2012-04-25 22:13:20 +0200
commitf40bfc9267b13b54e6379dfe7539447662879d24 (patch)
tree9b20069d5e62809ff434061ad730096836f916f2 /apps/codecs/libspc/spc_cpu.c
parenta0009907de7a0107d49040d8a180f140e2eff299 (diff)
downloadrockbox-f40bfc9267b13b54e6379dfe7539447662879d24.zip
rockbox-f40bfc9267b13b54e6379dfe7539447662879d24.tar.gz
rockbox-f40bfc9267b13b54e6379dfe7539447662879d24.tar.bz2
rockbox-f40bfc9267b13b54e6379dfe7539447662879d24.tar.xz
Add codecs to librbcodec.
Change-Id: Id7f4717d51ed02d67cb9f9cb3c0ada4a81843f97 Reviewed-on: http://gerrit.rockbox.org/137 Reviewed-by: Nils Wallménius <nils@rockbox.org> Tested-by: Nils Wallménius <nils@rockbox.org>
Diffstat (limited to 'apps/codecs/libspc/spc_cpu.c')
-rw-r--r--apps/codecs/libspc/spc_cpu.c1049
1 files changed, 0 insertions, 1049 deletions
diff --git a/apps/codecs/libspc/spc_cpu.c b/apps/codecs/libspc/spc_cpu.c
deleted file mode 100644
index 23dcc25..0000000
--- a/apps/codecs/libspc/spc_cpu.c
+++ /dev/null
@@ -1,1049 +0,0 @@
-/***************************************************************************
- * __________ __ ___.
- * Open \______ \ ____ ____ | | _\_ |__ _______ ___
- * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
- * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
- * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
- * \/ \/ \/ \/ \/
- * $Id$
- *
- * Copyright (C) 2006-2007 Adam Gashlin (hcs)
- * Copyright (C) 2004-2007 Shay Green (blargg)
- * Copyright (C) 2002 Brad Martin
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
- * KIND, either express or implied.
- *
- ****************************************************************************/
-
-/* The CPU portion (shock!) */
-#include "codeclib.h"
-#include "spc_codec.h"
-#include "spc_profiler.h"
-
-#undef check
-#define check assert
-
-#define READ( addr ) (SPC_read( this, addr, spc_time_ ))
-#define WRITE( addr, value ) (SPC_write( this, addr, value, spc_time_ ))
-
-#define READ_DP( addr ) READ( (addr) + dp )
-#define WRITE_DP( addr, value ) WRITE( (addr) + dp, value )
-
-#define READ_PROG16( addr ) GET_LE16( RAM + (addr) )
-
-#define READ_PC( pc ) (*(pc))
-#define READ_PC16( pc ) GET_LE16( pc )
-
-#define SET_PC( n ) (pc = RAM + (n))
-#define GET_PC() (pc - RAM)
-
-static unsigned char const cycle_table [0x100] = {
- 2,8,4,5,3,4,3,6,2,6,5,4,5,4,6,8, /* 0 */
- 2,8,4,5,4,5,5,6,5,5,6,5,2,2,4,6, /* 1 */
- 2,8,4,5,3,4,3,6,2,6,5,4,5,4,5,4, /* 2 */
- 2,8,4,5,4,5,5,6,5,5,6,5,2,2,3,8, /* 3 */
- 2,8,4,5,3,4,3,6,2,6,4,4,5,4,6,6, /* 4 */
- 2,8,4,5,4,5,5,6,5,5,4,5,2,2,4,3, /* 5 */
- 2,8,4,5,3,4,3,6,2,6,4,4,5,4,5,5, /* 6 */
- 2,8,4,5,4,5,5,6,5,5,5,5,2,2,3,6, /* 7 */
- 2,8,4,5,3,4,3,6,2,6,5,4,5,2,4,5, /* 8 */
- 2,8,4,5,4,5,5,6,5,5,5,5,2,2,12,5,/* 9 */
- 3,8,4,5,3,4,3,6,2,6,4,4,5,2,4,4, /* A */
- 2,8,4,5,4,5,5,6,5,5,5,5,2,2,3,4, /* B */
- 3,8,4,5,4,5,4,7,2,5,6,4,5,2,4,9, /* C */
- 2,8,4,5,5,6,6,7,4,5,4,5,2,2,6,3, /* D */
- 2,8,4,5,3,4,3,6,2,4,5,3,4,3,4,3, /* E */
- 2,8,4,5,4,5,5,6,3,4,5,4,2,2,4,3 /* F */
-};
-
-#define MEM_BIT() CPU_mem_bit( this, pc, spc_time_ )
-
-static unsigned CPU_mem_bit( THIS, uint8_t const* pc, long const spc_time_ )
- ICODE_ATTR_SPC;
-
-static unsigned CPU_mem_bit( THIS, uint8_t const* pc, long const spc_time_ )
-{
- unsigned addr = READ_PC16( pc );
- unsigned t = READ( addr & 0x1FFF ) >> (addr >> 13);
- return (t << 8) & 0x100;
-}
-
-/* status flags */
-enum { st_n = 0x80 };
-enum { st_v = 0x40 };
-enum { st_p = 0x20 };
-enum { st_b = 0x10 };
-enum { st_h = 0x08 };
-enum { st_i = 0x04 };
-enum { st_z = 0x02 };
-enum { st_c = 0x01 };
-
-#define IS_NEG (nz & 0x880)
-
-#define CALC_STATUS( out )\
-{\
- out = status & ~(st_n | st_z | st_c);\
- out |= (c >> 8) & st_c;\
- out |= (dp >> 3) & st_p;\
- if ( IS_NEG ) out |= st_n;\
- if ( !(nz & 0xFF) ) out |= st_z;\
-}
-
-#define SET_STATUS( in )\
-{\
- status = in & ~(st_n | st_z | st_c | st_p);\
- c = in << 8;\
- nz = ((in << 4) & 0x800) | (~in & st_z);\
- dp = (in << 3) & 0x100;\
-}
-
-
-/* stack */
-#define PUSH( v ) (*--sp = (uint8_t) (v))
-#define PUSH16( v ) (sp -= 2, SET_LE16( sp, v ))
-#define POP() (*sp++)
-#define SET_SP( v ) (sp = RAM + 0x101 + (v))
-#define GET_SP() (sp - 0x101 - RAM)
-
-long CPU_run( THIS, long start_time )
-{
-#if 0
- ENTER_TIMER(cpu);
-#endif
-
- register long spc_time_ = start_time;
-
-#ifdef CPU_ARM
- uint8_t* const ram_ = ram.ram;
- #undef RAM
- #define RAM ram_
-#endif
-
- int a = this->r.a;
- int x = this->r.x;
- int y = this->r.y;
-
- uint8_t const* pc;
- SET_PC( this->r.pc );
-
- uint8_t* sp;
- SET_SP( this->r.sp );
-
- int status;
- int c;
- int nz;
- unsigned dp;
- {
- int temp = this->r.status;
- SET_STATUS( temp );
- }
-
- goto loop;
-
- /* main loop */
-cbranch_taken_loop:
- pc += *(int8_t const*) pc;
- spc_time_ += 2;
-inc_pc_loop:
- pc++;
-loop:
- check( (unsigned) GET_PC() < 0x10000 );
- check( (unsigned) GET_SP() < 0x100 );
- check( (unsigned) a < 0x100 );
- check( (unsigned) x < 0x100 );
- check( (unsigned) y < 0x100 );
-
- unsigned opcode = *pc;
- int cycles = this->cycle_table [opcode];
- unsigned data = *++pc;
- if ( (spc_time_ += cycles) > 0 )
- goto out_of_time;
- switch ( opcode )
- {
-
-/* Common instructions */
-
-#define BRANCH( cond )\
-{\
- pc++;\
- int offset = (int8_t) data;\
- if ( cond ) {\
- pc += offset;\
- spc_time_ += 2;\
- }\
- goto loop;\
-}
-
- case 0xF0: /* BEQ (most common) */
- BRANCH( !(uint8_t) nz )
-
- case 0xD0: /* BNE */
- BRANCH( (uint8_t) nz )
-
- case 0x3F: /* CALL */
- PUSH16( GET_PC() + 2 );
- SET_PC( READ_PC16( pc ) );
- goto loop;
-
- case 0x6F: /* RET */
- SET_PC( POP() );
- pc += POP() * 0x100;
- goto loop;
-
-#define CASE( n ) case n:
-
-/* Define common address modes based on opcode for immediate mode. Execution
- ends with data set to the address of the operand. */
-#define ADDR_MODES( op )\
- CASE( op - 0x02 ) /* (X) */\
- data = x + dp;\
- pc--;\
- goto end_##op;\
- CASE( op + 0x0F ) /* (dp)+Y */\
- data = READ_PROG16( data + dp ) + y;\
- goto end_##op;\
- CASE( op - 0x01 ) /* (dp+X) */\
- data = READ_PROG16( ((uint8_t) (data + x)) + dp );\
- goto end_##op;\
- CASE( op + 0x0E ) /* abs+Y */\
- data += y;\
- goto abs_##op;\
- CASE( op + 0x0D ) /* abs+X */\
- data += x;\
- CASE( op - 0x03 ) /* abs */\
- abs_##op:\
- data += 0x100 * READ_PC( ++pc );\
- goto end_##op;\
- CASE( op + 0x0C ) /* dp+X */\
- data = (uint8_t) (data + x);\
- CASE( op - 0x04 ) /* dp */\
- data += dp;\
- end_##op:
-
-/* 1. 8-bit Data Transmission Commands. Group I */
-
- ADDR_MODES( 0xE8 ) /* MOV A,addr */
- /*case 0xE4:*/ /* MOV a,dp (most common) */
- mov_a_addr:
- a = nz = READ( data );
- goto inc_pc_loop;
- case 0xBF: /* MOV A,(X)+ */
- data = x + dp;
- x = (uint8_t) (x + 1);
- pc--;
- goto mov_a_addr;
-
- case 0xE8: /* MOV A,imm */
- a = data;
- nz = data;
- goto inc_pc_loop;
-
- case 0xF9: /* MOV X,dp+Y */
- data = (uint8_t) (data + y);
- case 0xF8: /* MOV X,dp */
- data += dp;
- goto mov_x_addr;
- case 0xE9: /* MOV X,abs */
- data = READ_PC16( pc );
- pc++;
- mov_x_addr:
- data = READ( data );
- case 0xCD: /* MOV X,imm */
- x = data;
- nz = data;
- goto inc_pc_loop;
-
- case 0xFB: /* MOV Y,dp+X */
- data = (uint8_t) (data + x);
- case 0xEB: /* MOV Y,dp */
- data += dp;
- goto mov_y_addr;
- case 0xEC: /* MOV Y,abs */
- data = READ_PC16( pc );
- pc++;
- mov_y_addr:
- data = READ( data );
- case 0x8D: /* MOV Y,imm */
- y = data;
- nz = data;
- goto inc_pc_loop;
-
-/* 2. 8-BIT DATA TRANSMISSION COMMANDS, GROUP 2 */
-
- ADDR_MODES( 0xC8 ) /* MOV addr,A */
- WRITE( data, a );
- goto inc_pc_loop;
-
- {
- int temp;
- case 0xCC: /* MOV abs,Y */
- temp = y;
- goto mov_abs_temp;
- case 0xC9: /* MOV abs,X */
- temp = x;
- mov_abs_temp:
- WRITE( READ_PC16( pc ), temp );
- pc += 2;
- goto loop;
- }
-
- case 0xD9: /* MOV dp+Y,X */
- data = (uint8_t) (data + y);
- case 0xD8: /* MOV dp,X */
- WRITE( data + dp, x );
- goto inc_pc_loop;
-
- case 0xDB: /* MOV dp+X,Y */
- data = (uint8_t) (data + x);
- case 0xCB: /* MOV dp,Y */
- WRITE( data + dp, y );
- goto inc_pc_loop;
-
- case 0xFA: /* MOV dp,dp */
- data = READ( data + dp );
- case 0x8F: /* MOV dp,#imm */
- WRITE_DP( READ_PC( ++pc ), data );
- goto inc_pc_loop;
-
-/* 3. 8-BIT DATA TRANSMISSIN COMMANDS, GROUP 3. */
-
- case 0x7D: /* MOV A,X */
- a = x;
- nz = x;
- goto loop;
-
- case 0xDD: /* MOV A,Y */
- a = y;
- nz = y;
- goto loop;
-
- case 0x5D: /* MOV X,A */
- x = a;
- nz = a;
- goto loop;
-
- case 0xFD: /* MOV Y,A */
- y = a;
- nz = a;
- goto loop;
-
- case 0x9D: /* MOV X,SP */
- x = nz = GET_SP();
- goto loop;
-
- case 0xBD: /* MOV SP,X */
- SET_SP( x );
- goto loop;
-
- /*case 0xC6:*/ /* MOV (X),A (handled by MOV addr,A in group 2) */
-
- case 0xAF: /* MOV (X)+,A */
- WRITE_DP( x, a );
- x++;
- goto loop;
-
-/* 5. 8-BIT LOGIC OPERATION COMMANDS */
-
-#define LOGICAL_OP( op, func )\
- ADDR_MODES( op ) /* addr */\
- data = READ( data );\
- case op: /* imm */\
- nz = a func##= data;\
- goto inc_pc_loop;\
- { unsigned addr;\
- case op + 0x11: /* X,Y */\
- data = READ_DP( y );\
- addr = x + dp;\
- pc--;\
- goto addr_##op;\
- case op + 0x01: /* dp,dp */\
- data = READ_DP( data );\
- case op + 0x10: /*dp,imm*/\
- addr = READ_PC( ++pc ) + dp;\
- addr_##op:\
- nz = data func READ( addr );\
- WRITE( addr, nz );\
- goto inc_pc_loop;\
- }
-
- LOGICAL_OP( 0x28, & ); /* AND */
-
- LOGICAL_OP( 0x08, | ); /* OR */
-
- LOGICAL_OP( 0x48, ^ ); /* EOR */
-
-/* 4. 8-BIT ARITHMETIC OPERATION COMMANDS */
-
- ADDR_MODES( 0x68 ) /* CMP addr */
- data = READ( data );
- case 0x68: /* CMP imm */
- nz = a - data;
- c = ~nz;
- nz &= 0xFF;
- goto inc_pc_loop;
-
- case 0x79: /* CMP (X),(Y) */
- data = READ_DP( x );
- nz = data - READ_DP( y );
- c = ~nz;
- nz &= 0xFF;
- goto loop;
-
- case 0x69: /* CMP (dp),(dp) */
- data = READ_DP( data );
- case 0x78: /* CMP dp,imm */
- nz = READ_DP( READ_PC( ++pc ) ) - data;
- c = ~nz;
- nz &= 0xFF;
- goto inc_pc_loop;
-
- case 0x3E: /* CMP X,dp */
- data += dp;
- goto cmp_x_addr;
- case 0x1E: /* CMP X,abs */
- data = READ_PC16( pc );
- pc++;
- cmp_x_addr:
- data = READ( data );
- case 0xC8: /* CMP X,imm */
- nz = x - data;
- c = ~nz;
- nz &= 0xFF;
- goto inc_pc_loop;
-
- case 0x7E: /* CMP Y,dp */
- data += dp;
- goto cmp_y_addr;
- case 0x5E: /* CMP Y,abs */
- data = READ_PC16( pc );
- pc++;
- cmp_y_addr:
- data = READ( data );
- case 0xAD: /* CMP Y,imm */
- nz = y - data;
- c = ~nz;
- nz &= 0xFF;
- goto inc_pc_loop;
-
- {
- int addr;
- case 0xB9: /* SBC (x),(y) */
- case 0x99: /* ADC (x),(y) */
- pc--; /* compensate for inc later */
- data = READ_DP( x );
- addr = y + dp;
- goto adc_addr;
- case 0xA9: /* SBC dp,dp */
- case 0x89: /* ADC dp,dp */
- data = READ_DP( data );
- case 0xB8: /* SBC dp,imm */
- case 0x98: /* ADC dp,imm */
- addr = READ_PC( ++pc ) + dp;
- adc_addr:
- nz = READ( addr );
- goto adc_data;
-
-/* catch ADC and SBC together, then decode later based on operand */
-#undef CASE
-#define CASE( n ) case n: case (n) + 0x20:
- ADDR_MODES( 0x88 ) /* ADC/SBC addr */
- data = READ( data );
- case 0xA8: /* SBC imm */
- case 0x88: /* ADC imm */
- addr = -1; /* A */
- nz = a;
- adc_data: {
- if ( opcode & 0x20 )
- data ^= 0xFF; /* SBC */
- int carry = (c >> 8) & 1;
- int ov = (nz ^ 0x80) + carry + (int8_t) data; /* sign-extend */
- int hc = (nz & 15) + carry;
- c = nz += data + carry;
- hc = (nz & 15) - hc;
- status = (status & ~(st_v | st_h)) | ((ov >> 2) & st_v) |
- ((hc >> 1) & st_h);
- if ( addr < 0 ) {
- a = (uint8_t) nz;
- goto inc_pc_loop;
- }
- WRITE( addr, (uint8_t) nz );
- goto inc_pc_loop;
- }
-
- }
-
-/* 6. ADDITION & SUBTRACTION COMMANDS */
-
-#define INC_DEC_REG( reg, n )\
- nz = reg + n;\
- reg = (uint8_t) nz;\
- goto loop;
-
- case 0xBC: INC_DEC_REG( a, 1 ) /* INC A */
- case 0x3D: INC_DEC_REG( x, 1 ) /* INC X */
- case 0xFC: INC_DEC_REG( y, 1 ) /* INC Y */
-
- case 0x9C: INC_DEC_REG( a, -1 ) /* DEC A */
- case 0x1D: INC_DEC_REG( x, -1 ) /* DEC X */
- case 0xDC: INC_DEC_REG( y, -1 ) /* DEC Y */
-
- case 0x9B: /* DEC dp+X */
- case 0xBB: /* INC dp+X */
- data = (uint8_t) (data + x);
- case 0x8B: /* DEC dp */
- case 0xAB: /* INC dp */
- data += dp;
- goto inc_abs;
- case 0x8C: /* DEC abs */
- case 0xAC: /* INC abs */
- data = READ_PC16( pc );
- pc++;
- inc_abs:
- nz = ((opcode >> 4) & 2) - 1;
- nz += READ( data );
- WRITE( data, (uint8_t) nz );
- goto inc_pc_loop;
-
-/* 7. SHIFT, ROTATION COMMANDS */
-
- case 0x5C: /* LSR A */
- c = 0;
- case 0x7C:{/* ROR A */
- nz = ((c >> 1) & 0x80) | (a >> 1);
- c = a << 8;
- a = nz;
- goto loop;
- }
-
- case 0x1C: /* ASL A */
- c = 0;
- case 0x3C:{/* ROL A */
- int temp = (c >> 8) & 1;
- c = a << 1;
- nz = c | temp;
- a = (uint8_t) nz;
- goto loop;
- }
-
- case 0x0B: /* ASL dp */
- c = 0;
- data += dp;
- goto rol_mem;
- case 0x1B: /* ASL dp+X */
- c = 0;
- case 0x3B: /* ROL dp+X */
- data = (uint8_t) (data + x);
- case 0x2B: /* ROL dp */
- data += dp;
- goto rol_mem;
- case 0x0C: /* ASL abs */
- c = 0;
- case 0x2C: /* ROL abs */
- data = READ_PC16( pc );
- pc++;
- rol_mem:
- nz = (c >> 8) & 1;
- nz |= (c = READ( data ) << 1);
- WRITE( data, (uint8_t) nz );
- goto inc_pc_loop;
-
- case 0x4B: /* LSR dp */
- c = 0;
- data += dp;
- goto ror_mem;
- case 0x5B: /* LSR dp+X */
- c = 0;
- case 0x7B: /* ROR dp+X */
- data = (uint8_t) (data + x);
- case 0x6B: /* ROR dp */
- data += dp;
- goto ror_mem;
- case 0x4C: /* LSR abs */
- c = 0;
- case 0x6C: /* ROR abs */
- data = READ_PC16( pc );
- pc++;
- ror_mem: {
- int temp = READ( data );
- nz = ((c >> 1) & 0x80) | (temp >> 1);
- c = temp << 8;
- WRITE( data, nz );
- goto inc_pc_loop;
- }
-
- case 0x9F: /* XCN */
- nz = a = (a >> 4) | (uint8_t) (a << 4);
- goto loop;
-
-/* 8. 16-BIT TRANSMISION COMMANDS */
-
- case 0xBA: /* MOVW YA,dp */
- a = READ_DP( data );
- nz = (a & 0x7F) | (a >> 1);
- y = READ_DP( (uint8_t) (data + 1) );
- nz |= y;
- goto inc_pc_loop;
-
- case 0xDA: /* MOVW dp,YA */
- WRITE_DP( data, a );
- WRITE_DP( (uint8_t) (data + 1), y );
- goto inc_pc_loop;
-
-/* 9. 16-BIT OPERATION COMMANDS */
-
- case 0x3A: /* INCW dp */
- case 0x1A:{/* DECW dp */
- data += dp;
-
- /* low byte */
- int temp = READ( data );
- temp += ((opcode >> 4) & 2) - 1; /* +1 for INCW, -1 for DECW */
- nz = ((temp >> 1) | temp) & 0x7F;
- WRITE( data, (uint8_t) temp );
-
- /* high byte */
- data = ((uint8_t) (data + 1)) + dp;
- temp >>= 8;
- temp = (uint8_t) (temp + READ( data ));
- nz |= temp;
- WRITE( data, temp );
-
- goto inc_pc_loop;
- }
-
- case 0x9A: /* SUBW YA,dp */
- case 0x7A: /* ADDW YA,dp */
- {
- /* read 16-bit addend */
- int temp = READ_DP( data );
- int sign = READ_DP( (uint8_t) (data + 1) );
- temp += 0x100 * sign;
- status &= ~(st_v | st_h);
-
- /* to do: fix half-carry for SUBW (it's probably wrong) */
-
- /* for SUBW, negate and truncate to 16 bits */
- if ( opcode & 0x80 ) {
- temp = (temp ^ 0xFFFF) + 1;
- sign = temp >> 8;
- }
-
- /* add low byte (A) */
- temp += a;
- a = (uint8_t) temp;
- nz = (temp | (temp >> 1)) & 0x7F;
-
- /* add high byte (Y) */
- temp >>= 8;
- c = y + temp;
- nz = (nz | c) & 0xFF;
-
- /* half-carry (temporary avoids CodeWarrior optimizer bug) */
- unsigned hc = (c & 15) - (y & 15);
- status |= (hc >> 4) & st_h;
-
- /* overflow if sign of YA changed when previous sign
- and addend sign were same */
- status |= (((c ^ y) & ~(y ^ sign)) >> 1) & st_v;
-
- y = (uint8_t) c;
-
- goto inc_pc_loop;
- }
-
- case 0x5A: { /* CMPW YA,dp */
- int temp = a - READ_DP( data );
- nz = ((temp >> 1) | temp) & 0x7F;
- temp = y + (temp >> 8);
- temp -= READ_DP( (uint8_t) (data + 1) );
- nz |= temp;
- c = ~temp;
- nz &= 0xFF;
- goto inc_pc_loop;
- }
-
-/* 10. MULTIPLICATION & DIVISON COMMANDS */
-
- case 0xCF: { /* MUL YA */
- unsigned temp = y * a;
- a = (uint8_t) temp;
- nz = ((temp >> 1) | temp) & 0x7F;
- y = temp >> 8;
- nz |= y;
- goto loop;
- }
-
- case 0x9E: /* DIV YA,X */
- {
- /* behavior based on SPC CPU tests */
-
- status &= ~(st_h | st_v);
-
- if ( (y & 15) >= (x & 15) )
- status |= st_h;
-
- if ( y >= x )
- status |= st_v;
-
- unsigned ya = y * 0x100 + a;
- if ( y < x * 2 )
- {
- a = ya / x;
- y = ya - a * x;
- }
- else
- {
- a = 255 - (ya - x * 0x200) / (256 - x);
- y = x + (ya - x * 0x200) % (256 - x);
- }
-
- nz = (uint8_t) a;
- a = (uint8_t) a;
-
- goto loop;
- }
-
-/* 11. DECIMAL COMPENSATION COMMANDS */
-
- /* seem unused */
- /* case 0xDF: */ /* DAA */
- /* case 0xBE: */ /* DAS */
-
-/* 12. BRANCHING COMMANDS */
-
- case 0x2F: /* BRA rel */
- pc += (int8_t) data;
- goto inc_pc_loop;
-
- case 0x30: /* BMI */
- BRANCH( IS_NEG )
-
- case 0x10: /* BPL */
- BRANCH( !IS_NEG )
-
- case 0xB0: /* BCS */
- BRANCH( c & 0x100 )
-
- case 0x90: /* BCC */
- BRANCH( !(c & 0x100) )
-
- case 0x70: /* BVS */
- BRANCH( status & st_v )
-
- case 0x50: /* BVC */
- BRANCH( !(status & st_v) )
-
- case 0x03: /* BBS dp.bit,rel */
- case 0x23:
- case 0x43:
- case 0x63:
- case 0x83:
- case 0xA3:
- case 0xC3:
- case 0xE3:
- pc++;
- if ( (READ_DP( data ) >> (opcode >> 5)) & 1 )
- goto cbranch_taken_loop;
- goto inc_pc_loop;
-
- case 0x13: /* BBC dp.bit,rel */
- case 0x33:
- case 0x53:
- case 0x73:
- case 0x93:
- case 0xB3:
- case 0xD3:
- case 0xF3:
- pc++;
- if ( !((READ_DP( data ) >> (opcode >> 5)) & 1) )
- goto cbranch_taken_loop;
- goto inc_pc_loop;
-
- case 0xDE: /* CBNE dp+X,rel */
- data = (uint8_t) (data + x);
- /* fall through */
- case 0x2E: /* CBNE dp,rel */
- pc++;
- if ( READ_DP( data ) != a )
- goto cbranch_taken_loop;
- goto inc_pc_loop;
-
- case 0xFE: /* DBNZ Y,rel */
- y = (uint8_t) (y - 1);
- BRANCH( y )
-
- case 0x6E: { /* DBNZ dp,rel */
- pc++;
- unsigned temp = READ_DP( data ) - 1;
- WRITE_DP( (uint8_t) data, (uint8_t) temp );
- if ( temp )
- goto cbranch_taken_loop;
- goto inc_pc_loop;
- }
-
- case 0x1F: /* JMP (abs+X) */
- SET_PC( READ_PC16( pc ) + x );
- /* fall through */
- case 0x5F: /* JMP abs */
- SET_PC( READ_PC16( pc ) );
- goto loop;
-
-/* 13. SUB-ROUTINE CALL RETURN COMMANDS */
-
- case 0x0F:{/* BRK */
- check( 0 ); /* untested */
- PUSH16( GET_PC() + 1 );
- SET_PC( READ_PROG16( 0xFFDE ) ); /* vector address verified */
- int temp;
- CALC_STATUS( temp );
- PUSH( temp );
- status = (status | st_b) & ~st_i;
- goto loop;
- }
-
- case 0x4F: /* PCALL offset */
- PUSH16( GET_PC() + 1 );
- SET_PC( 0xFF00 + data );
- goto loop;
-
- case 0x01: /* TCALL n */
- case 0x11:
- case 0x21:
- case 0x31:
- case 0x41:
- case 0x51:
- case 0x61:
- case 0x71:
- case 0x81:
- case 0x91:
- case 0xA1:
- case 0xB1:
- case 0xC1:
- case 0xD1:
- case 0xE1:
- case 0xF1:
- PUSH16( GET_PC() );
- SET_PC( READ_PROG16( 0xFFDE - (opcode >> 3) ) );
- goto loop;
-
-/* 14. STACK OPERATION COMMANDS */
-
- {
- int temp;
- case 0x7F: /* RET1 */
- temp = POP();
- SET_PC( POP() );
- pc += POP() << 8;
- goto set_status;
- case 0x8E: /* POP PSW */
- temp = POP();
- set_status:
- SET_STATUS( temp );
- goto loop;
- }
-
- case 0x0D: { /* PUSH PSW */
- int temp;
- CALC_STATUS( temp );
- PUSH( temp );
- goto loop;
- }
-
- case 0x2D: /* PUSH A */
- PUSH( a );
- goto loop;
-
- case 0x4D: /* PUSH X */
- PUSH( x );
- goto loop;
-
- case 0x6D: /* PUSH Y */
- PUSH( y );
- goto loop;
-
- case 0xAE: /* POP A */
- a = POP();
- goto loop;
-
- case 0xCE: /* POP X */
- x = POP();
- goto loop;
-
- case 0xEE: /* POP Y */
- y = POP();
- goto loop;
-
-/* 15. BIT OPERATION COMMANDS */
-
- case 0x02: /* SET1 */
- case 0x22:
- case 0x42:
- case 0x62:
- case 0x82:
- case 0xA2:
- case 0xC2:
- case 0xE2:
- case 0x12: /* CLR1 */
- case 0x32:
- case 0x52:
- case 0x72:
- case 0x92:
- case 0xB2:
- case 0xD2:
- case 0xF2: {
- data += dp;
- int bit = 1 << (opcode >> 5);
- int mask = ~bit;
- if ( opcode & 0x10 )
- bit = 0;
- WRITE( data, (READ( data ) & mask) | bit );
- goto inc_pc_loop;
- }
-
- case 0x0E: /* TSET1 abs */
- case 0x4E:{/* TCLR1 abs */
- data = READ_PC16( pc );
- pc += 2;
- unsigned temp = READ( data );
- nz = temp & a;
- temp &= ~a;
- if ( !(opcode & 0x40) )
- temp |= a;
- WRITE( data, temp );
- goto loop;
- }
-
- case 0x4A: /* AND1 C,mem.bit */
- c &= MEM_BIT();
- pc += 2;
- goto loop;
-
- case 0x6A: /* AND1 C,/mem.bit */
- check( 0 ); /* untested */
- c &= ~MEM_BIT();
- pc += 2;
- goto loop;
-
- case 0x0A: /* OR1 C,mem.bit */
- check( 0 ); /* untested */
- c |= MEM_BIT();
- pc += 2;
- goto loop;
-
- case 0x2A: /* OR1 C,/mem.bit */
- check( 0 ); /* untested */
- c |= ~MEM_BIT();
- pc += 2;
- goto loop;
-
- case 0x8A: /* EOR1 C,mem.bit */
- c ^= MEM_BIT();
- pc += 2;
- goto loop;
-
- case 0xEA: { /* NOT1 mem.bit */
- data = READ_PC16( pc );
- pc += 2;
- unsigned temp = READ( data & 0x1FFF );
- temp ^= 1 << (data >> 13);
- WRITE( data & 0x1FFF, temp );
- goto loop;
- }
-
- case 0xCA: { /* MOV1 mem.bit,C */
- data = READ_PC16( pc );
- pc += 2;
- unsigned temp = READ( data & 0x1FFF );
- unsigned bit = data >> 13;
- temp = (temp & ~(1 << bit)) | (((c >> 8) & 1) << bit);
- WRITE( data & 0x1FFF, temp );
- goto loop;
- }
-
- case 0xAA: /* MOV1 C,mem.bit */
- c = MEM_BIT();
- pc += 2;
- goto loop;
-
-/* 16. PROGRAM STATUS FLAG OPERATION COMMANDS */
-
- case 0x60: /* CLRC */
- c = 0;
- goto loop;
-
- case 0x80: /* SETC */
- c = ~0;
- goto loop;
-
- case 0xED: /* NOTC */
- c ^= 0x100;
- goto loop;
-
- case 0xE0: /* CLRV */
- status &= ~(st_v | st_h);
- goto loop;
-
- case 0x20: /* CLRP */
- dp = 0;
- goto loop;
-
- case 0x40: /* SETP */
- dp = 0x100;
- goto loop;
-
- case 0xA0: /* EI */
- check( 0 ); /* untested */
- status |= st_i;
- goto loop;
-
- case 0xC0: /* DI */
- check( 0 ); /* untested */
- status &= ~st_i;
- goto loop;
-
-/* 17. OTHER COMMANDS */
-
- case 0x00: /* NOP */
- goto loop;
-
- /*case 0xEF:*/ /* SLEEP */
- /*case 0xFF:*/ /* STOP */
- case 0xFF:
- c |= 1; /* force switch table to have 256 entries,
- hopefully helping optimizer */
- } /* switch */
-
- /* unhandled instructions fall out of switch so emulator can catch them */
-
-out_of_time:
- /* undo partial execution of opcode */
- spc_time_ -= this->cycle_table [*--pc];
- {
- int temp;
- CALC_STATUS( temp );
- this->r.status = (uint8_t) temp;
- }
-
- this->r.pc = GET_PC();
- this->r.sp = (uint8_t) GET_SP();
- this->r.a = (uint8_t) a;
- this->r.x = (uint8_t) x;
- this->r.y = (uint8_t) y;
-
-#if 0
- EXIT_TIMER(cpu);
-#endif
- return spc_time_;
-}
-
-void CPU_Init( THIS )
-{
- ci->memcpy( this->cycle_table, cycle_table, sizeof cycle_table );
-}
-