SPC700 Processor Data by: Mark Ormston (aka Zolaerla or MeMSO) of NeueTECH Software memso@memso.net Version: 0.2 Date Created: 2006-10-24 Last Modified: 2007-02-17 Please leave this notice in any version of this text file! This document was made for readability in any general ASCII system, with 100 or more characters per line and 2 spaces per tab. I shall endeavor to convert all tabs to spaces before releasing a version of this document, but if I forget, this at least tells you how to correct it. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! NOTICE! Though I attempt to be as accurate as possible, I am limited to what other sources state. Often times these sources disagree with one another and I end up having to pick and choose what sounds "right", even if it may not necessarily be so. I can give no guarantee of any sort that this information is 100% accurate. I just would like to think it is! If there is any information that would make this more complete, please email me above and let me know! Please put "For MeMSO" (capitalize it properly please) in the subject so I know it's not spam (I get up to 100 of those a day!). !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! This document describes in full detail exactly how the SPC700 processor works. This information was gathered so I could program the CPU core into my emulator. Anybody that knows much of anything about emulators knows that they need to be very exact to properly emulate the systems they are designed for, and it is this exactness I sought when creating this document. Only a few sources were used (or even to be found!), and I have listed as many as I could in an appendix. A .xls file should come with this file. It contains charts of the opcodes/mnemonics in Opcode and Mnemonic sort order, for reference purposes. I have used this chart extensively myself. This document covers the following processors: SPC700 What this document *IS*: o Quite Unabridged o A gathering of information from many, many different sources to consolodate information in a single file o Useful for details on the inner workings of this CPU o A place to find psuedo-code for EVERY opcode (often times not optimized for clarity's sake) o Will give all information necessary to both program and to emulate this processor o System independent, assuming this CPU could have been used for anything but as an SNES sound chip o As accurate as possible given the sources found and used What this document *IS NOT*: o A teaching guide for using/programming this processor o A guide for creating computers/systems using this processor (unless you just want the CPU details) o System dependent (as much as possible) Note that while the SPC700 is the CPU for sound generation on the Super Nintendo/Famicon, this document only describes the use of the CPU. Memory addresses, timers, transferring data to/from the SPC, etc. are not considered. In fact, this processor is as capable as an overloaded 65c02 and could have been used as the CPU for it's own system. Throughout this document, I may add an indented section with "* Opinion" to show when I am stating my opinion on something. These may be ignored completely but may point out something that you may not otherwise think about. [x] - I use this to denote sources. For example, if I mention something from "APU Manual in Text", I will simply call it [1]. See Sources at the end of the file for a list of sources. ??? - I put this anywhere where I am making a guess but do not know for certain. These are very frustrating for everyone, to be sure. KERBLUH - This is what I use to tell me that more information is needed. *************************************************************************************************** TABLE OF CONTENTS 1 Description of the processor 2 List of processor registers 3 Interrupts 4 Addressing Modes 5 Alphabetic Opcode Listing w/ Complete Descriptions 6 Pins 7 Quirks and Nuances 7.1 Nuances (Intentional Processor Behavior) 7.2 Quirks/Bugs ___________________________________________________________________________________________________ A1 Miscellaneous Notes and Issues A2 To Do List A3 Version History ___________________________________________________________________________________________________ Sources Information Sources ___________________________________________________________________________________________________ In the Spreadsheet: Sheet1 Opcode List, sorted by Opcode Sheet2 Opcode List, sorted by Mnemonic *************************************************************************************************** 1 Description of the processor Specifications for this processor: Native Depth: 8bit Endianness: Little (LSB first, 0x1234 is stored as 34 12) Addressing: 16bit (64KB) 64KB is directly addressable from the processor Hardware Via: Memory Mapped Interrupts: RESET, Software, some have: NMI, Maskable Interrupt Supposedly the SPC700 had support for an IRQ and an NMI, but neither exists on the version used in the SNES # of gen regs: 3 A, X and Y # of spcl regs:0 Stack: Post decremented, Single 256 byte region of memory The stack pointer is decremented AFTER pushing and incremented BEFORE popping. The current stack pointer is pointing to the next address to be pushed to. The stack occupied page 1 (0x0100 to 0x1FF) Segmentation: None Bitwise: Fair AND, OR, XOR, single bit shifting, single bit rotating, setting, clearing, testing and setting/clearing, branch on bit Single bit rotation and shifting: ASL, LSR, ROL, ROR Specific bit setting, clearing and switching: SETx, CLRx, NOT1 AND, OR, XOR: AND, OR and EOR Single bit and carry flag: AND1, EOR1, MOV1, OR1 Test and clear/set: TCLR1, TSET1 Branch on specific bits set: BBCx, BBSx Relocatable: Minimal Relative jump support and indexable memory access, but no relative CALL support Conditions: Poor Branching if: equal, not equal, above or equal, below, greater or equal, less, positive, negative (BEQ, BNE, BCC, BCS, BVC, BVS, BPL, BMI) Compare and branch if not equal (CBNE) Branch if a bit is set or clear (BBCx, BBSx) Loop Opcodes: Minimal A compare and branch if not equal (CBNE) and a decrement and branch if not zero (DBNZ) exist Mult/Div: Minimal A 16bit to 8bit divide (DIV) and a two 8bit to 16bit multiply (MUL) Block Opcodes: None Floating Point:None BCD Math: BCD adjust instructions Decimal Adjust after Add/Subtract: DAA, DAS Priviledges: None Pipelining: None Multitasking: No hardware support Mult Proc Supp:None SIMD Support: None The SPC700 was an 8bit CPU very similar to the R65c02 family of processors (see 65xx Processor Data) and was created by Sony. I'd go so far as to say that when Sony developed the CPU, they took the list of opcodes, addressing modes and even the exact same registers as the 65xx processors to make a cost-effective processor of their own, adding in some features they liked from other processors (such as the MUL and DIV statements). Just like the 65xx, the SPC700 is little endian. When multiple values are used in assembly (for example: MOV $12, $34), the destination is listed first and the source is second (that is read as: move the value from $34 to $12). In the actual byte code, the source is actually first, so this example would be FA 34 12 (FA is the opcode for a direct page to direct page move). See A2 for further CPU specific details. As far as I know, the SPC700 was only ever used on the Super Nintendo (Super Famicon) consoles to control the audio for the game system. It was force-fed it's code through a tiny 4 byte hole. * Opinion: It almost makes me think of it as a capable but caged beast. I've seen numerous complaints about how "stupid" the SPC700 is, though the CPU itself isn't to blame for the ridiculous communication method that was configured for it. Used as a stand-alone processor, it could have been a serious contender. It did things that would take the parent 65c816 of the SNES LONGER TO DO, in particular multiplication and division. As a matter of fact, the SPC700 uses LESS cycles to do an 8bit divide than a PENTIUM! Don't expect it to do anything else anywhere near as fast as a Pentium, I'm just impressed with that one thing. SNES Details Full Name: Sony SPC700 series CMOS 8-bit CPU core Speed: 2.048MHz ROM: 64bytes Memory: 64KB Addressable *************************************************************************************************** 2 List of processor registers ___________________________________________________________________________________________________ 2.1 A: Accumulator 8bit. The accumulator, the main register. Most of the work of the processor operates through this register, especially math and binary operations. ___________________________________________________________________________________________________ 2.2 X: X Index 8bit. A general purpose indexing register. Often used for preindexed indirect addressing (an offset into a list of pointers). ___________________________________________________________________________________________________ 2.3 Y: Y Index 8bit. A general purpose indexing register. Often used for postindexed indirect addressing (an offset to a pointer). Also, combined with A, used for 16bit operations. ___________________________________________________________________________________________________ 2.4 PC: Program Counter 16bit. This register points to the location the program is currently executing at. For Example: If PC is $2000, then the next instruction to be executed will be that at $2000 in memory. ___________________________________________________________________________________________________ 2.5 SP: Stack Pointer 8bit. Where the stack currently is located, offset in page 1 ($0100) in memory for the stack to use. Whenever a value is pushed onto the stack (see the PUSH opcodes, such as PUSH A), that value is written to memory where S is pointing, then S is decreased by the size of the data (by 1 for 8bit, 2 for 16bit) It is reset to $FF by the CPU on reset (??? this is just a guess), giving 256 bytes of stack space. ___________________________________________________________________________________________________ 2.6 PSW: Program Status Word 8bit. This is a register that holds flags for the system. Bits .......... 7 6 5 4 3 2 1 0 N V P B H I Z C BIT: 0 - 01 - Carry flag 1 - 02 - Zero flag 2 - 04 - Interrupt Enable flag If this is clear, interrupts are disabled If this is set, interrupts are enabled This is the opposite of the 65xx processors 3 - 08 - Half-Carry flag 4 - 10 - Break flag Set when BRK is used, clear otherwise ??? 5 - 20 - Direct Page flag If this is clear, then Direct Page functions access $0000 to $00FF If this is set, then Direct Page functions access $0100 to $01FF * Opinion: At first, this seems kinda stupid... but think about it. This gives you a means of accessing the stack without having to add more opcodes. You can do a MOV X, SP and then use any DPX or DPIndX with a number to offset by to have stack-relative addressing. For example: SETP MOV X, SP MOV A, $01 + X ; The same as MOV A, 1 + SP MOV A, ($02 + X) ; The same as MOV A, (2 + SP) CLRP 6 - 40 - Overflow flag 7 - 80 - Negative flag *************************************************************************************************** 3 Interrupts Reset 0xFFFE BRK 0xFFDE // ??? Some sources say this goes to $FFC0 IRQ 0xFFFC // ??? Unknown if this is correct NMI 0xFFFA // ??? Unknown if this is correct *************************************************************************************************** 4 Addressing Modes KERBLUH - Yeah, I need to fill out this section *************************************************************************************************** 5 Alphabetic Opcode Listing w/ Complete Descriptions Each code will have a C-style psuedo code snip, and a verbal description of the opcodes. The code style one assumes the following values: A Accumulator b Break flag c Carry flag h Half-carry flag i Interrupt enable flag n Negative flag p Direct page flag PC Program Counter PSW Program Status Word SP Stack Pointer v Overflow flag X X Index Y Y Index z Zero flag All flags are assumed to have a 1 or a 0 (their bit value). If they equal a non-zero or true value, they are set (1) If they equal a zero or false value, they are clear (0) Specials (all of these are assumed to be unsigned and able to hold at least 32bits of data): opcode 8bit value that holds the opcode's value operand The current operand (value to read/write) operand1 The left-side operand (destination) operand2 The right-side operand (source) result A temporary placeholder for a result temp A temporary value ___________________________________________________________________________________________________ ADC ADd with Carry Description: .......................................................................... Adds the two operands, adding one if carry is set and storing the result in the first operand. Flags: ................................................................................ nvpbhizc **--*-** n - Was the high bit of the result set? v - Was there signed overflow? h - Was there overflow on the bottom nibble? z - Was the result zero? c - Was there overflow? Code: ................................................................................. result = operand1 + operand2 + c; v = (~(operand1 ^ operand2) & (operand1 ^ result)) & 0x80; h = ((operand1 & 0x0F) + (operand2 & 0x0F) + c) > 0x0F; z = !result; n = result & 0x80; c = result > 0xFF; operand1 = result; Opcodes: .............................................................................. Op Format Size Cyc 84 ADC A, $12 2 3 85 ADC A, $1234 3 4 86 ADC A, (X 1 3 87 ADC A, ($12+X) 2 6 88 ADC A, #$12 2 2 89 ADC $12, $34 3 6 94 ADC A, $12+X 2 4 95 ADC A, $1234+X 3 5 96 ADC A, $1234+Y 3 5 97 ADC A, ($12)+Y 2 6 98 ADC $12, #$34 3 5 99 ADC (X), (Y) 1 5 ___________________________________________________________________________________________________ ADDW ADD Word Description: .......................................................................... Adds the two operands, storing the result in the first operand. Unlike ADC, this does NOT add with carry. Flags: ................................................................................ nvpbhizc **--*-** n - Was the high bit of the result set? v - Was there signed overflow? h - Was there overflow on the bottom nibble of the upper byte? z - Was the result zero? c - Was there overflow? Code: ................................................................................. result = operand1 + operand2; v = (~(operand1 ^ operand2) & (operand1 ^ result)) & 0x8000; c = result > 0xFFFF; h = ((operand1 & 0x0FFF) + (operand2 & 0x0FFF)) > 0x0FFF; z = !result; n = result & 0x8000; operand1 = result; Opcodes: .............................................................................. Op Format Size Cyc 7A ADDW YA, $12 2 5 ___________________________________________________________________________________________________ AND AND Description: .......................................................................... Performs a bitwise AND of operand1 and operand2, storing the result in operand1. Flags: ................................................................................ nvpbhizc *-----*- n - Was the high bit of the result set? z - Was the result zero? Code: ................................................................................. operand1 &= operand2; n = operand1 & 0x80; z = !operand1; Opcodes: .............................................................................. Op Format Size Cyc 24 AND A, $12 2 3 25 AND A, $1234 3 4 26 AND A, (X) 1 3 27 AND A, ($12+X) 2 6 28 AND A, #$12 2 2 29 AND $12, $34 3 6 34 AND A, $12+X 2 4 35 AND A, $1234+X 3 5 36 AND A, $1234+Y 3 5 37 AND A, ($12)+Y 2 6 38 AND $12, #$34 3 5 39 AND (X), (Y) 1 5 ___________________________________________________________________________________________________ AND1 AND bit with carry Description: .......................................................................... Ands the value or inverse value of the specified bit with c and stores the result in c. Opcode 4A uses the bit, 6A inverses the bit The top 3 bits of the value are the bit to use, the bottom 13 are a pointer to the address of the value to use. This only gives a range of 0x0000 to 0x1FFF to use this opcode on. Flags: ................................................................................ nvpbhizc -------* c - Result of c & (bit or inverse of bit) Code: [FULL VERSION] .................................................................. // Based on what [4] gives us PC += 3; curpnt = GetWord(PC - 2); bittouse = curpnt >> 13; curpnt &= 0x1FFF; operand = GetByte(curpnt); // Opcode 4A c &= operand & (1 << bittouse); // Opcode 6A c &= (~operand) & (1 << bittouse); Opcodes: .............................................................................. Op Format Size Cyc 4A AND1 C, $1234.$5 3 4 6A AND1 C, /$1234.$5 3 4 ___________________________________________________________________________________________________ ASL Arithmetic Shift Left Description: .......................................................................... Shifts the bits of the operand one to the left, essentially multiplying the value by 2. Flags: ................................................................................ nvpbhizc *-----** n - Was the result negative? z - Was the result 0? c - Was the high bit set before the operation? Code: ................................................................................. c = operand & 0x80; operand <<= 1; n = operand & 0x80; z = !operand; Opcodes: .............................................................................. Op Format Size Cyc 0B ASL $12 2 4 0C ASL $1234 3 5 1B ASL $12+X 2 5 1C ASL A 1 2 ___________________________________________________________________________________________________ BBCx Branch if Bit Clear Description: .......................................................................... Branches to the specified location (a near label, -128 to +127 from the next instruction) if the specified bit is clear in the operand. Flags: ................................................................................ nvpbhizc -------- Code: ................................................................................. if (!(operand1 & (1 << (opcode >> 5)))) { CurCycle += 2; PC += (S8) operand2; } Opcodes: .............................................................................. Op Format Size Cyc 13 BBC0 $12, nearlabel 3 5/7 33 BBC1 $12, nearlabel 3 5/7 53 BBC2 $12, nearlabel 3 5/7 73 BBC3 $12, nearlabel 3 5/7 93 BBC4 $12, nearlabel 3 5/7 B3 BBC5 $12, nearlabel 3 5/7 D3 BBC6 $12, nearlabel 3 5/7 F3 BBC7 $12, nearlabel 3 5/7 ___________________________________________________________________________________________________ BBSx Branch if Bit Set Description: .......................................................................... Branches to the specified location (a near label, -128 to +127 from the next instruction) if the specified bit is set in the operand. Flags: ................................................................................ nvpbhizc -------- Code: ................................................................................. if (operand1 & (1 << (opcode >> 5))) { CurCycle += 2; PC += (S8) operand2; } Opcodes: .............................................................................. Op Format Size Cyc 03 BBS0 $12, nearlabel 3 5/7 23 BBS1 $12, nearlabel 3 5/7 43 BBS2 $12, nearlabel 3 5/7 63 BBS3 $12, nearlabel 3 5/7 83 BBS4 $12, nearlabel 3 5/7 A3 BBS5 $12, nearlabel 3 5/7 C3 BBS6 $12, nearlabel 3 5/7 E3 BBS7 $12, nearlabel 3 5/7 ___________________________________________________________________________________________________ BCC Branch if Carry Clear Description: .......................................................................... Branches to the specified location (a near label, -128 to +127 from the next instruction) if the carry flag is clear Flags: ................................................................................ nvpbhizc -------- Code: ................................................................................. if (!c) { CurCycle += 2; PC += (S8) operand; } Opcodes: .............................................................................. Op Format Size Cyc 90 BCC nearlabel 2 2/4 ___________________________________________________________________________________________________ BCS Branch if Carry Set Description: .......................................................................... Branches to the specified location (a near label, -128 to +127 from the next instruction) if the carry flag is set Flags: ................................................................................ nvpbhizc -------- Code: ................................................................................. if (c) { CurCycle += 2; PC += (S8) operand; } Opcodes: .............................................................................. Op Format Size Cyc B0 BCS nearlabel 2 2/4 ___________________________________________________________________________________________________ BEQ Branch if EQual Description: .......................................................................... Branches to the specified location (a near label, -128 to +127 from the next instruction) if the zero flag is set Flags: ................................................................................ nvpbhizc -------- Code: ................................................................................. if (z) { CurCycle += 2; PC += (S8) operand; } Opcodes: .............................................................................. Op Format Size Cyc F0 BEQ nearlabel 2 2/4 ___________________________________________________________________________________________________ BMI Branch if MInus Description: .......................................................................... Branches to the specified location (a near label, -128 to +127 from the next instruction) if the negative flag is set Flags: ................................................................................ nvpbhizc -------- Code: ................................................................................. if (n) { CurCycle += 2; PC += (S8) operand; } Opcodes: .............................................................................. Op Format Size Cyc 30 BMI nearlabel 2 2/4 ___________________________________________________________________________________________________ BNE Branch if Not Equal Description: .......................................................................... Branches to the specified location (a near label, -128 to +127 from the next instruction) if the zero flag is clear Flags: ................................................................................ nvpbhizc -------- Code: ................................................................................. if (!z) { CurCycle += 2; PC += (S8) operand; } Opcodes: .............................................................................. Op Format Size Cyc D0 BNE nearlabel 2 2/4 ___________________________________________________________________________________________________ BPL Branch if PLus Description: .......................................................................... Branches to the specified location (a near label, -128 to +127 from the next instruction) if the negative flag is clear Flags: ................................................................................ nvpbhizc -------- Code: ................................................................................. if (!n) { CurCycle += 2; PC += (S8) operand; } Opcodes: .............................................................................. Op Format Size Cyc 10 BPL nearlabel 2 2/4 ___________________________________________________________________________________________________ BRA BRanch Always Description: .......................................................................... Branches to the specified location (a near label, -128 to +127 from the next instruction) Flags: ................................................................................ nvpbhizc -------- Code: ................................................................................. PC += (S8) operand; Opcodes: .............................................................................. Op Format Size Cyc 2F BRA nearlabel 2 4 ___________________________________________________________________________________________________ BRK BReaK Description: .......................................................................... Causes a software interrupt, doing the following: Sets the b flag Pushes PC of the next instruction Pushes PSW Clears the i flag Jumps to the address stored at $FFDE Flags: ................................................................................ nvpbhizc ---1-0-- Code: ................................................................................. b = 1; StackPushWord(PC); StackPushByte(PSW); i = 0; PC = GetWord(0xFFDE); Opcodes: .............................................................................. Op Format Size Cyc 0F BRK 1 8 ___________________________________________________________________________________________________ BVC Branch if oVerflow Clear Description: .......................................................................... Branches to the specified location (a near label, -128 to +127 from the next instruction) if the overflow flag is clear Flags: ................................................................................ nvpbhizc -------- Code: ................................................................................. if (!v) { CurCycle += 2; PC += (S8) operand; } Opcodes: .............................................................................. Op Format Size Cyc 50 BVC nearlabel 2 2/4 ___________________________________________________________________________________________________ BVS Branch if oVerflow Set Description: .......................................................................... Branches to the specified location (a near label, -128 to +127 from the next instruction) if the overflow flag is clear Flags: ................................................................................ nvpbhizc -------- Code: ................................................................................. if (v) { CurCycle += 2; PC += (S8) operand; } Opcodes: .............................................................................. Op Format Size Cyc 70 BVS nearlabel 2 2/4 ___________________________________________________________________________________________________ CALL CALL subroutine Description: .......................................................................... Pushes PC of the next instruction on the stack, then jumps to the address at the specified location Flags: ................................................................................ nvpbhizc -------- Code: ................................................................................. StackPushWord(PC); PC = GetWord(curpnt); Opcodes: .............................................................................. Op Format Size Cyc 3F CALL $1234 3 8 ___________________________________________________________________________________________________ CBNE Compare then Branch if Not Equal Description: .......................................................................... Compares the value with A, then branches if they are not equal. This does NOT affect the flags. Flags: ................................................................................ nvpbhizc -------- Code: ................................................................................. if (operand1 != A) { CurCycle += 2; PC += (S8) operand2; } Opcodes: .............................................................................. Op Format Size Cyc 2E CBNE $12, nearlabel 3 5/7 DE CBNE $12+X, nearlabel 3 6/8 ___________________________________________________________________________________________________ CLRx CLeaR bit Description: .......................................................................... Clears the specified bit in the memory value. Flags: ................................................................................ nvpbhizc -------- Code: ................................................................................. operand &= ~(1 << (opcode >> 5)); Opcodes: .............................................................................. Op Format Size Cyc 02 CLR0 $12 2 4 22 CLR1 $12 2 4 42 CLR2 $12 2 4 62 CLR3 $12 2 4 82 CLR4 $12 2 4 A2 CLR5 $12 2 4 C2 CLR6 $12 2 4 E2 CLR7 $12 2 4 ___________________________________________________________________________________________________ CLRC CLeaR Carry Description: .......................................................................... Clears the carry flag Flags: ................................................................................ nvpbhizc -------0 Code: ................................................................................. c = 0; Opcodes: .............................................................................. Op Format Size Cyc 60 CLRC 1 2 ___________________________________________________________________________________________________ CLRP CLeaR direct Page flag Description: .......................................................................... Clears the direct page flag. After this instruction, direct page addressing access page 0 ($0000 - $00FF) Flags: ................................................................................ nvpbhizc --0----- Code: ................................................................................. p = 0; Opcodes: .............................................................................. Op Format Size Cyc 20 CLRP 1 2 ___________________________________________________________________________________________________ CLRV CLeaR oVerflow Description: .......................................................................... Clears the overflow flag. This also clears the half-carry flag. Flags: ................................................................................ nvpbhizc -0--0--- Code: ................................................................................. v = 0; Opcodes: .............................................................................. Op Format Size Cyc E0 CLRV 1 2 ___________________________________________________________________________________________________ CMP CoMPare Description: .......................................................................... Compares two values, setting the flags accordingly. The compare is done by subtracting operand2 from operand1. The result is discarded, only flags are affected. Flags: ................................................................................ nvpbhizc *-----** n - Was the high bit set on the result? z - Was the result 0? c - Was there NOT borrow (ie, was operand1 >= operand2)? The z and c flags are set according to this chart: z c ------------------------- operand1 < operand2 0 0 operand1 = operand2 1 1 operand1 > operand2 0 1 Code: ................................................................................. result = operand1 - operand2; z = !result; c = result >= 0; n = operand1 >= operand2; Opcodes: .............................................................................. Op Format Size Cyc 1E CMP X, $1234 3 4 3E CMP X, $12 2 3 5E CMP Y, $1234 3 4 64 CMP A, $12 2 3 65 CMP A, $1234 3 4 66 CMP A, (X) 1 3 67 CMP A, ($12+X) 2 6 68 CMP A, #$12 2 2 69 CMP $12, $34 3 6 74 CMP A, $12+X 2 4 75 CMP A, $1234+X 3 5 76 CMP A, $1234+Y 3 5 77 CMP A, ($12)+Y 2 6 78 CMP $12, #$34 3 5 79 CMP (X), (Y) 1 5 7E CMP Y, $12 2 3 AD CMP Y, #$12 2 2 C8 CMP X, #$12 2 2 ___________________________________________________________________________________________________ CMPW CoMPare Word Description: .......................................................................... Compares two values, setting the flags accordingly. * [1] and [5] state that Carry is not set by this opcode, [4] does. We're going to assume that [4] is wrong... Flags: ................................................................................ nvpbhizc *-----*- n - Was the high bit set on the result? z - Was the result 0? Code: ................................................................................. result = operand1 - operand2; z = !result; n = operand1 >= operand2; Opcodes: .............................................................................. Op Format Size Cyc 5A CMPW YA, $12 2 4 ___________________________________________________________________________________________________ DAA Decimal Adjust after Addition Description: .......................................................................... Decimal adjusts A for addition. Different sources state that this opcode functions differently, so for full details on implementation see the code below. The textual description from [5] is: If A > 0x99 or c is set, add 0x60 and set c. If (A & 0x0F) > 0x09 or h is set, add 0x06. h is not affected. Flags: ................................................................................ nvpbhizc *-----** n - Was the high bit set on the result? z - Was the result 0? c - Was there overflow? Code: ................................................................................. // :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: // One version from [3] and matches the description from [5]: // To me, this looks more accurate than the [4] version, but still not quite right. // If: h = 1, c = 0, A = 99, then we end up with: c = 0, A = 9F!!!! // Of course, according to people with real SPCs, this code is 100% accurate so // maybe it couldn't tolerate certain values of A... if (c || A > 0x99) { c = 1; A += 0x60; } if (h || (A & 0x0F) > 0x09) A += 0x06; n = A & 0x80; z = !A; // :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: // ANOTHER VERSION: // CODE SNIPPET MODIFIED FROM [4] // I really don't like this... // If: h = 0, c = 0, A = 1A: // I'd think A should become 20 // However, this code would make it become 80! temp = A; // If the lower nibble is too big OR half-carry is set, adjust it if ((A & 0x0F) > 9 || h) { A += 0x06; // If the nibble was too big, set carry... why are we doing this??? if (A < 0x06) c = 1; } // If carry is set or the value is bigger than 0x99, adjust it also if (temp > 0x99 || c) { A += 0x60; c = 1; } n = A & 0x80; z = !A; Opcodes: .............................................................................. Op Format Size Cyc DF DAA A 1 3 ___________________________________________________________________________________________________ DAS Decimal Adjust after Subtraction Description: .......................................................................... Decimal adjusts A for subtraction. This is used to do a subtraction on a BCD value. This instruction should be run before the subtraction. If A is greater than 0x99 or carry is clear, then subtract 0x60 from A. If the low nibble of A is greater than 0x09 or half-carry is clear, subtract 0x06 from A. * Unlike DAA, both [3] and [4] agree on the operation of this opcode Flags: ................................................................................ nvpbhizc *-----** n - Was the high bit set on the result? z - Was the result 0? c - Was there no overflow? Code: ................................................................................. if (!c || A > 0x99) { c = 0; A -= 0x60; } if (!h || (A & 0x0F) > 0x09) A -= 0x06; n = A & 0x80; z = !A; Opcodes: .............................................................................. Op Format Size Cyc BE DAS A 1 3 ___________________________________________________________________________________________________ DBNZ Decrement then Branch if Not Zero Description: .......................................................................... Decrements a value then branches to the specified location if the value is not zero. The location is a near label (signed byte or -128 to +127) from the next instruction. Flags: ................................................................................ nvpbhizc -------- Code: ................................................................................. operand1--; if (!operand1) PC += (S8) operand2; Opcodes: .............................................................................. Op Format Size Cyc 6E DBNZ $12, nearlabel 3 5/7 FE DBNZ Y, nearlabel 2 4/6 ___________________________________________________________________________________________________ DEC DECrement Description: .......................................................................... Decrement a value. Flags: ................................................................................ nvpbhizc *-----*- n - Was the high bit set on the result? z - Was the result 0? Code: ................................................................................. operand--; n = operand & 0x80; z = !operand; Opcodes: .............................................................................. Op Format Size Cyc 1D DEC X 1 2 8B DEC $12 2 4 8C DEC $1234 3 5 9B DEC $12+X 2 5 9C DEC A 1 2 DC DEC Y 1 2 ___________________________________________________________________________________________________ DECW DECrement Word Description: .......................................................................... Decrement a word value. Flags: ................................................................................ nvpbhizc *-----*- n - Was the high bit set on the result? z - Was the result 0? Code: ................................................................................. operand--; n = operand & 0x80; z = !operand; Opcodes: .............................................................................. Op Format Size Cyc 1A DECW $12 2 6 ___________________________________________________________________________________________________ DI Disable Interrupts Description: .......................................................................... Clears the interrupt flag, disabling interrupts. Flags: ................................................................................ nvpbhizc -----0-- Code: ................................................................................. i = 0; Opcodes: .............................................................................. Op Format Size Cyc C0 DI 1 3 ___________________________________________________________________________________________________ DIV DIVide Description: .......................................................................... Divides the 16bit value YA (Y as the high byte) by X, storing the quotient in A and the remainder in Y. Flags: ................................................................................ nvpbhizc **--*-*- n - Was the high bit of the quotient set? v - Was the quotient greater than 256? h - Was the lower nibble of Y greater or equal to the lower nibble of X? z - Was the quotient 0? Code: ................................................................................. // This one is preferable if it works better // Supposedly it produces the exact same results as the real CPU unsigned short YA; YA = (Y << 8) + A; v = (Y >= X); h = (Y & 0x0F >= X & 0x0F); if (Y < (X << 1)) { A = YA / X; Y = YA % X; } else { A = 255 - (YA - (X << 9)) / (256 - X); Y = X + (YA - (X << 9)) % (256 - X); } z = !A; n = A & 0x80; // OR ******** // A hardware test against this states it matches exactly // Probably pretty close to what the processor is actually doing // This doesn't affect all flags, however, and is much slower than the above version unsigned long yva, xtemp, q; yva = (Y << 8) + A; xtemp = X << 9; h = (Y & 0x0F >= X & 0x0F); for (q = 0; q < 9; q++){ yva <<= 1; if (yva & 0x20000) yva = (yva & 0x1FFFF) | 0x01; if (yva >= xtemp) yva ^= 1; if (yva & 1) yva = (yva - xtemp) & 0x1FFFF; } Y = (yva >> 9) & 0xFF; A = yva & 0xFF; v = (yva & 0x100); z = !A; n = A & 0x80; Opcodes: .............................................................................. Op Format Size Cyc 9E DIV YA, X 1 12 ___________________________________________________________________________________________________ EI Enable Interrupts Description: .......................................................................... Sets i to 1, enabling interrupts. Flags: ................................................................................ nvpbhizc -----1-- Code: ................................................................................. i = 1; Opcodes: .............................................................................. Op Format Size Cyc A0 EI 1 3 ___________________________________________________________________________________________________ EOR Exclusive OR Description: .......................................................................... Does an exclusive OR on the two values, storing the result in the first operand. Flags: ................................................................................ nvpbhizc *-----*- n - Was the highbit set on the result? z - Was the result 0? Code: ................................................................................. operand1 ^= operand2; n = operand1 & 0x80; z = !operand2; Opcodes: .............................................................................. Op Format Size Cyc 44 EOR A, $12 2 3 45 EOR A, $1234 3 4 46 EOR A, (X) 1 3 47 EOR A, ($12+X) 2 6 48 EOR A, #$12 2 2 49 EOR $12, $34 3 6 54 EOR A, $12+X 2 4 55 EOR A, $1234+X 3 5 56 EOR A, $1234+Y 3 5 57 EOR A, ($12)+Y 2 6 58 EOR $12, #$34 3 5 59 EOR (X), (Y) 1 5 ___________________________________________________________________________________________________ EOR1 Exclusive OR a bit Description: .......................................................................... Exclusive ORs the value of the specified bit with c and stores the result in c. The top 3 bits of the value are the bit to use, the bottom 13 are a pointer to the address of the value to use. This only gives a range of 0x0000 to 0x1FFF to use this opcode on. Flags: ................................................................................ nvpbhizc -------* c - Was c XOR the bit set? Code: [FULL VERSION] .................................................................. // Based on what [4] gives us PC += 3; curpnt = GetWord(PC - 2); bittouse = curpnt >> 13; curpnt &= 0x1FFF; operand = GetByte(curpnt); c = c ^ (operand & (1 << bittouse)); Opcodes: .............................................................................. Op Format Size Cyc 8A EOR1 C, $1234.$5 3 5 ___________________________________________________________________________________________________ INC INCrement Description: .......................................................................... Increments a value. Flags: ................................................................................ nvpbhizc *-----*- n - Was the highbit of the result set? z - Was the result 0? Code: ................................................................................. operand++; n = operand & 0x80; z = !operand; Opcodes: .............................................................................. Op Format Size Cyc 3D INC X 1 2 AB INC $12 2 4 AC INC $1234 3 5 BB INC $12+X 2 5 BC INC A 1 2 FC INC Y 1 2 ___________________________________________________________________________________________________ INCW INCrement Word Description: .......................................................................... Increments a word value. Flags: ................................................................................ nvpbhizc *-----*- n - Was the highbit of the result set? z - Was the result 0? Code: ................................................................................. operand++; n = operand & 0x8000; z = !operand; Opcodes: .............................................................................. Op Format Size Cyc 3A INCW $12 2 6 ___________________________________________________________________________________________________ JMP JuMP Description: .......................................................................... Jumps to the specified location. Note that the effective address is used, instead of reading the value from memory. So, if JMP $1234 is used, PC would become $1234. Flags: ................................................................................ nvpbhizc -------- Code: ................................................................................. PC = curpnt; Opcodes: .............................................................................. Op Format Size Cyc 1F JMP ($1234+X) 3 6 5F JMP $1234 3 3 ___________________________________________________________________________________________________ LSR Logical Shift Right Description: .......................................................................... Shifts a value one bit to the right, moving a 0 into the high bit and moving the low bit into c. Flags: ................................................................................ nvpbhizc 0-----** n - Always becomes 0 since the high bit becomes 0 z - Was the result 0? c - Was the low bit set before the operation? Code: ................................................................................. c = operand & 0x01; operand >>= 1; z = !operand; n = 0; Opcodes: .............................................................................. Op Format Size Cyc 4B LSR $12 2 4 4C LSR $1234 3 5 5B LSR $12+X 2 5 5C LSR A 1 2 ___________________________________________________________________________________________________ MOV MOVe value Description: .......................................................................... Sets one value equal to another. Flags: ................................................................................ If a MOV's destination is A, X or Y, then the Zero and Negative flags are modified Opcodes: 5D, 7D, 8D, 9D, BF, CD, DD, E4, E5, E6, E7, E8, E9, EB, EC, F4, F5, F6, F7, F8, F9, FB, FD nvpbhizc *-----*- n - Was the high bit set on the value? z - Was the value 0? If a MOV's destination is not A, X or Y, then no flags are affected Opcodes: 8F, AF, BD, C4, C5, C6, C7, C9, CB, CC, D4, D5, D6, D7, D8, D9, DB, FA nvpbhizc -------- No flags are modified for these opcodes Code: ................................................................................. operand1 = operand2; // Only do the following for opcodes that set these flags: n = operand1 & 0x80; z = !operand1; Opcodes: .............................................................................. Op Format Size Cyc 5D MOV X, A 1 2 7D MOV A, X 1 2 8D MOV Y, #$12 2 2 8F MOV $12, #$34 3 5 9D MOV X, SP 1 2 AF MOV (X)+, A 1 4 BD MOV SP, X 1 2 BF MOV A, (X)+ 1 4 C4 MOV $12, A 2 4 C5 MOV $1234, A 3 5 C6 MOV (X), A 1 4 C7 MOV ($12+X), A 2 7 C9 MOV $1234, X 3 5 CB MOV $12, Y 2 4 CC MOV $1234, Y 3 5 CD MOV X, #$12 2 2 D4 MOV $12+X, A 2 5 D5 MOV $1234+X, A 3 6 D6 MOV $1234+Y, A 3 6 D7 MOV ($12)+Y, A 2 7 D8 MOV $12, X 2 4 D9 MOV $12+Y, X 2 5 DB MOV $12+X, Y 2 5 DD MOV A, Y 1 2 E4 MOV A, $12 2 3 E5 MOV A, $1234 3 4 E6 MOV A, (X) 1 3 E7 MOV A, ($12+X) 2 6 E8 MOV A, #$12 2 2 E9 MOV X, $1234 3 4 EB MOV Y, $12 2 3 EC MOV Y, $1234 3 4 F4 MOV A, $12+X 2 4 F5 MOV A, $1234+X 3 5 F6 MOV A, $1234+Y 3 5 F7 MOV A, ($12)+Y 2 6 F8 MOV X, $12 2 3 F9 MOV X, $12+Y 2 4 FA MOV $12, $34 3 5 FB MOV Y, $12+X 2 4 FD MOV Y, A 1 2 ___________________________________________________________________________________________________ MOV1 MOVe bit Description: .......................................................................... Either moves the specified bit into carry or moves carry into the specified bit. The top 3 bits of the value are the bit to use, the bottom 13 are a pointer to the address of the value to use. This only gives a range of 0x0000 to 0x1FFF to use this opcode on. Flags: ................................................................................ Opcode: AA nvpbhizc -------* c - Was the specified bit set? Opcode: CA nvpbhizc -------- Code: ................................................................................. // Opcode AA c = operand & (1 << bittouse); // Opcode CA if (c) operand |= (1 << bittouse); else operand &= ~(1 << bittouse); Opcodes: .............................................................................. Op Format Size Cyc AA MOV1 C, $1234.$5 3 4 CA MOV1 $1234.$5, C 3 6 ___________________________________________________________________________________________________ MOVW MOVe Word Description: .......................................................................... Sets a word value equal to another. Flags: ................................................................................ Opcode: BA nvpbhizc *-----*- n - Was the high bit set on the value? z - Was the value 0? Opcode: DA nvpbhizc -------- No flags are modified for these opcodes Code: ................................................................................. // Opcode BA Y = operand >> 8; A = (U8) operand; n = operand & 0x8000; z = !operand; // Opcode DA operand = (Y << 8) + A; Opcodes: .............................................................................. Op Format Size Cyc BA MOVW YA, $12 2 5 DA MOVW $12, YA 2 5 ___________________________________________________________________________________________________ MUL MULtiply Description: .......................................................................... Stores the 16bit value of Y * A into YA (Y has the high byte, A has the low byte). * According to [4] and [5], z is only set according to the high byte value. Flags: ................................................................................ nvpbhizc *-----*- n - Was the high bit of the result set? z - Was the high byte 0? Code: ................................................................................. result = Y * A; Y = result >> 8; A = result & 0xFF; n = A & 0x80; z = !Y; Opcodes: .............................................................................. Op Format Size Cyc CF MUL YA 1 9 ___________________________________________________________________________________________________ NOP No OPeration Description: .......................................................................... This opcode performs no operation. Nothing is changed. It is generally used as a place holder or to comment out existing code without reassembling/recompiling. Flags: ................................................................................ nvpbhizc -------- Code: ................................................................................. // Nothing happens, so there's no code! Opcodes: .............................................................................. Op Format Size Cyc 00 NOP 1 2 ___________________________________________________________________________________________________ NOT1 NOT bit Description: .......................................................................... Performs a logical NOT operation on the specified bit. The top 3 bits of the value are the bit to use, the bottom 13 are a pointer to the address of the value to use. This only gives a range of 0x0000 to 0x1FFF to use this opcode on. Flags: ................................................................................ nvpbhizc -------- Code: [FULL VERSION] .................................................................. // Based on what [4] gives us PC += 3; curpnt = GetWord(PC - 2); bittouse = curpnt >> 13; curpnt &= 0x1FFF; operand = GetByte(curpnt); operand ^= (1 << bittouse); Opcodes: .............................................................................. Op Format Size Cyc EA NOT1 $1234.$5 3 5 ___________________________________________________________________________________________________ NOTC NOT Carry Description: .......................................................................... Performs a logical NOT operation on carry. Flags: ................................................................................ nvpbhizc -------* c - Carry is set if carry was clear, otherwise it's clear. Code: ................................................................................. c ^= c; Opcodes: .............................................................................. Op Format Size Cyc ED NOTC 1 3 ___________________________________________________________________________________________________ OR OR Description: .......................................................................... Performs a bitwise OR of operand1 and operand2, storing the result in operand1. Flags: ................................................................................ nvpbhizc *-----*- n - Was the high bit of the result set? z - Was the result zero? Code: ................................................................................. operand1 |= operand2; n = operand1 & 0x80; z = !operand1; Opcodes: .............................................................................. Op Format Size Cyc 04 OR A, $12 2 3 05 OR A, $1234 3 4 06 OR A, (X) 1 3 07 OR A, ($12+X) 2 6 08 OR A, #$12 2 2 09 OR $12, $34 3 6 14 OR A, $12+X 2 4 15 OR A, $1234+X 3 5 16 OR A, $1234+Y 3 5 17 OR A, ($12)+Y 2 6 18 OR $12, #$34 3 5 19 OR (X), (Y) 1 5 ___________________________________________________________________________________________________ OR1 OR a bit Description: .......................................................................... Performs a bitwise OR of the specified bit (or the inverse of the bit) and carry, storing the result in carry. Opcode 0A uses the bit as is, 2A uses the inverse of the bit. The top 3 bits of the value are the bit to use, the bottom 13 are a pointer to the address of the value to use. This only gives a range of 0x0000 to 0x1FFF to use this opcode on. Flags: ................................................................................ nvpbhizc -------* Code: [FULL VERSION] .................................................................. // Based on what [4] gives us PC += 3; curpnt = GetWord(PC - 2); bittouse = curpnt >> 13; curpnt &= 0x1FFF; operand = GetByte(curpnt); // Opcode 0A c |= operand & (1 << bittouse); // Opcode 2A c |= (~operand) & (1 << bittouse); Opcodes: .............................................................................. Op Format Size Cyc 0A OR1 C, $1234.$5 3 5 2A OR1 C, /$1234.$5 3 5 ___________________________________________________________________________________________________ PCALL upper Page CALL Description: .......................................................................... This operation performs a call in the upper page of memory. It takes an 8bit value and adds $FF00 to get the final address. This is used to access code loaded into the ROM of the system, which is located in the upper memory region. Flags: ................................................................................ nvpbhizc -------- Code: ................................................................................. PC = 0xFF00 + curpnt; Opcodes: .............................................................................. Op Format Size Cyc 4F PCALL $12 (upage) 2 6 ___________________________________________________________________________________________________ POP POP a value from the stack Description: .......................................................................... Pops a single value from the stack. If PSW is popped, all flags are affected, otherwise no flags are affected. When a value is popped from the stack, SP is first incremented, then the value is grabbed at $0100 + SP Flags: ................................................................................ Opcodes: AE, CE, EE nvpbhizc -------- Opcode: 8E nvpbhizc ******** All bits of PSW are set to the popped value Code: ................................................................................. // Opcodes AE, CE and EE operand = StackPopByte(); // Opcode 8E // Sets the flags byte all at once PSW = StackPopByte(); Opcodes: .............................................................................. Op Format Size Cyc 8E POP PSW 1 4 AE POP A 1 4 CE POP X 1 4 EE POP Y 1 4 ___________________________________________________________________________________________________ PUSH PUSH a value onto the stack Description: .......................................................................... Pushes a value onto the stack. First the value is pushed at $0100 + SP, then SP is decremented. Flags: ................................................................................ nvpbhizc -------- Code: ................................................................................. StackPushByte(operand); Opcodes: .............................................................................. Op Format Size Cyc 0D PUSH PSW 1 4 2D PUSH A 1 4 4D PUSH X 1 4 6D PUSH Y 1 4 ___________________________________________________________________________________________________ RET RETurn from subroutine Description: .......................................................................... Pops a word off of the stack and stores it into PC, effectively returning from a subroutine. Flags: ................................................................................ nvpbhizc -------- Code: ................................................................................. PC = StackPopWord(); Opcodes: .............................................................................. Op Format Size Cyc 6F RET 1 5 ___________________________________________________________________________________________________ RETI RETurn from Interrupt Description: .......................................................................... Pops a byte off of the stack into PSW, then pops a word off of the stack and stores it into PC. Flags: ................................................................................ nvpbhizc ******** Code: ................................................................................. PSW = StackPopByte(); PC = StackPopWord(); Opcodes: .............................................................................. Op Format Size Cyc 7F RETI 1 6 ___________________________________________________________________________________________________ ROL ROtate bits Left Description: .......................................................................... Rotates bits left by one, moving carry into the low bit and moving the original high bit into carry. Flags: ................................................................................ nvpbhizc -------* c - Was the high bit set before the bit shift? Code: ................................................................................. temp = operand & 0x80; operand = (operand << 1) + c; c = temp; Opcodes: .............................................................................. Op Format Size Cyc 2B ROL $12 2 4 2C ROL $1234 3 5 3B ROL $12+X 2 5 3C ROL A 1 2 ___________________________________________________________________________________________________ ROR ROtate bits Right Description: .......................................................................... Rotates bits right by one, moving carry into the high bit and moving the original low bit into carry. Flags: ................................................................................ nvpbhizc -------* c - Was the low bit set before the bit shift? Code: ................................................................................. temp = operand & 0x01; operand = (operand >> 1) + c; c = temp; Opcodes: .............................................................................. Op Format Size Cyc 6B ROR $12 2 4 6C ROR $1234 3 5 7B ROR $12+X 2 5 7C ROR A 1 2 ___________________________________________________________________________________________________ SBC SuBtract with Carry Description: .......................................................................... Subtracts operand2 from operand1, subtracting one more if carry is clear. Flags: ................................................................................ nvpbhizc **--*-** n - Was the high bit of the result set? v - Was there signed overflow? h - Was there no borrow on the bottom nibble? z - Was the result zero? c - Was there no borrow? Code: ................................................................................. result = operand1 - operand2 - ~c; v = ((operand1 ^ operand2) & (operand1 ^ result)) & 0x80; h = ((result & 0x0F) - ((operand1 & 0x0F) + c)) > 0x0F; z = !result; n = result & 0x80; c = result <= 0xFF; operand1 = result; Opcodes: .............................................................................. Op Format Size Cyc A4 SBC A, $12 2 3 A5 SBC A, $1234 3 4 A6 SBC A, (X) 1 3 A7 SBC A, ($12+X) 2 6 A8 SBC A, #$12 2 2 A9 SBC $12, $34 3 6 B4 SBC A, $12+X 2 4 B5 SBC A, $1234+X 3 5 B6 SBC A, $1234+Y 3 5 B7 SBC A, ($12)+Y 2 6 B8 SBC $12, #$34 3 5 B9 SBC (X), (Y) 1 5 ___________________________________________________________________________________________________ SETx SET bit Description: .......................................................................... Sets a single bit on a value in memory. Flags: ................................................................................ nvpbhizc -------- Code: ................................................................................. operand |= (1 << (opcode >> 5)); Opcodes: .............................................................................. Op Format Size Cyc 12 SET0 $12 2 4 32 SET1 $12 2 4 52 SET2 $12 2 4 72 SET3 $12 2 4 92 SET4 $12 2 4 B2 SET5 $12 2 4 D2 SET6 $12 2 4 F2 SET7 $12 2 4 ___________________________________________________________________________________________________ SETC SET Carry Description: .......................................................................... Sets the carry flag. Flags: ................................................................................ nvpbhizc -------1 Code: ................................................................................. c = 1; Opcodes: .............................................................................. Op Format Size Cyc 80 SETC 1 2 ___________________________________________________________________________________________________ SETP SET direct Page flag Description: .......................................................................... Sets the direct page flag. Flags: ................................................................................ nvpbhizc --1----- Code: ................................................................................. p = 1; Opcodes: .............................................................................. Op Format Size Cyc 40 SETP 1 2 ___________________________________________________________________________________________________ SLEEP SLEEP mode Description: .......................................................................... Puts the processor into sleep mode. It can be awoken with an interrupt. Flags: ................................................................................ nvpbhizc -------- Code: ................................................................................. CPUStop(SleepMode); Opcodes: .............................................................................. Op Format Size Cyc EF SLEEP 1 3 ___________________________________________________________________________________________________ STOP STOP processor Description: .......................................................................... Stops the processor completely. KERBLUH - The only way to restart it is to reset??? Flags: ................................................................................ nvpbhizc -------- Code: ................................................................................. CPUStop(StopMode); Opcodes: .............................................................................. Op Format Size Cyc FF STOP 1 3 ___________________________________________________________________________________________________ SUBW SUBtract Word Description: .......................................................................... Subtracts the second operand from the first operand, storing the result in the first operand. Unlike SBC, this does NOT subtract with carry. Flags: ................................................................................ nvpbhizc **--*-** n - Was the high bit of the result set? v - Was there signed overflow? h - Was there not borrow on the bottom nibble of the upper byte? z - Was the result zero? c - Was there not borrow? Code: ................................................................................. result = operand1 - operand2; v = ((operand1 ^ operand2) & (operand1 ^ result)) & 0x8000; c = result <= 0xFFFF; // This code is derived from the SUBW code of [4] temp = ((operand1 & 0x0F00) - (operand2 & 0x0F00)) >> 8; if (operand1 & 0xFF < operand2 & 0xFF) temp--; h = temp <= 0x0F; z = !result; n = result & 0x8000; operand1 = result; Opcodes: .............................................................................. Op Format Size Cyc 9A SUBW YA, $12 2 5 ___________________________________________________________________________________________________ TCALL Table CALL Description: .......................................................................... Performs a call on one of the 16 vectors in the memory range of $FFC0 to $FFDF. According to [4] and [5], these are done BACKWARDS. So TCALL 15 accesses $FFC0, TCALL 14 accesses $FFC2, etc. Flags: ................................................................................ nvpbhizc -------- Code: ................................................................................. // (opcode & 0xF0) >> 3 is the same as (opcode >> 4) << 1 PC = GetWord(0xFFDE - ((opcode & 0xF0) >> 3)); Opcodes: .............................................................................. Op Format Size Cyc 01 TCALL 0 1 8 11 TCALL 1 1 8 21 TCALL 2 1 8 31 TCALL 3 1 8 41 TCALL 4 1 8 51 TCALL 5 1 8 61 TCALL 6 1 8 71 TCALL 7 1 8 81 TCALL 8 1 8 91 TCALL 9 1 8 A1 TCALL 10 1 8 B1 TCALL 11 1 8 C1 TCALL 12 1 8 D1 TCALL 13 1 8 E1 TCALL 14 1 8 F1 TCALL 15 1 8 ___________________________________________________________________________________________________ TCLR1 Test and CLeaR bits Description: .......................................................................... Clears every bit on the memory value that is set in A. Essentially it performs an AND operation on the memory operand with the opposite bits of A (value &= ~A;). The flags are set based on the operand AND A. Flags: ................................................................................ nvpbhizc *-----*- n - Was the high bit set on operand AND A? z - Was operand AND A = 0? Code: ................................................................................. temp = operand & A; operand &= ~A; n = temp & 0x80; z = !temp; Opcodes: .............................................................................. Op Format Size Cyc 4E TCLR1 $1234 3 6 ___________________________________________________________________________________________________ TSET1 Test and SET bits Description: .......................................................................... Sets every bit on the memory value that is set in A. This is identical to an OR operand, A except the flags are set based on the operand AND A. Flags: ................................................................................ nvpbhizc *-----*- n - Was the high bit set on operand AND A? z - Was operand AND A = 0? Code: ................................................................................. temp = operand & A; operand |= A; n = temp & 0x80; z = !temp; Opcodes: .............................................................................. Op Format Size Cyc 0E TSET1 $1234 3 6 ___________________________________________________________________________________________________ XCN eXChange Nibbles Description: .......................................................................... Exchanges the high and low nibbles in A. Flags: ................................................................................ nvpbhizc *-----*- n - Was the high bit set in A? z - Was A = 0? Code: ................................................................................. A = (A >> 4) | (A << 4); n = A & 0x80; z = !A; Opcodes: .............................................................................. Op Format Size Cyc 9F XCN A 1 5 *************************************************************************************************** 6 Pins KERBLUH - No information is currently available for the pins *************************************************************************************************** 7 Quirks and Nuances ___________________________________________________________________________________________________ 7.1 Nuances (Intentional Processor Behavior) Multi-byte values are little endian. $1234 is stored as $34 $12 in memory. When multiple values are used in assembly (for example: MOV $12, $34), the destination is listed first and the source is second (that is read as: move the value from $34 to $12). In the actual byte code, the source is actually first, so the example above would be FA 34 12 (FA is the opcode for a direct page to direct page move). BCD is not directly supported by arithmetic functions, but rather by BCD modification routines, such as DAA. To supplement this, a special bit, h (Half Carry), stores whether there was carry/borrow from the low nibble. For subtract instructions, c (Carry) (and h [Half Carry] for DAS) is 0 for borrow and 1 for no borrow, which is backwards from most other processors. Execution and instructions will wrap from $FFFF to $0000. Direct page accesses will wrap within the direct page (page $00 or $01, depending on the P flag). The stack is always in page 1 and wraps. ___________________________________________________________________________________________________ 7.2 Quirks/Bugs --------------------------------------------------------------------------------------------------- Some MOV instructions that read before writing (according to [5]): Some of the MOV instructions with a memory operand for the destination will sometimes perform a read before writing to the destination. Note that the effected MOVW opcode (DA) only reads the low byte. The following opcodes exhibit this behavior: 8F MOV $12, #$34 C4 MOV $12, A C5 MOV $1234, A C6 MOV (X), A C7 MOV ($12+X), A C9 MOV $1234, X CB MOV $12, Y CC MOV $1234, Y D4 MOV $12+X, A D5 MOV $1234+X, A D6 MOV $1234+Y, A D7 MOV ($12)+Y, A D8 MOV $12, X D9 MOV $12+Y, X DB MOV $12+X, Y DA MOVW $12, YA The following MOV instructions DO NOT exhibit this behavior: AF MOV (X)+, A FA MOV $12, $34 --------------------------------------------------------------------------------------------------- DIV is a bit strange If you look at the two source samples for the DIV instruction, you can see that they behave a bit oddly. [5] explains the oddness best: "DIV has some interesting corner cases. ZN are set based on A. V is set if YA/X > 0xFF (so the result won't fit in A). H is odd, it seems to get set based on X & 0xF<=Y & 0xF. The result is correct as long as YA/X < 0x200, otherwise Y and A are not helpful." *************************************************************************************************** A1 Miscellaneous Notes and Issues Opcode 0F: BRK is listed as taking an immediate value in [4], like the 65xx processors, but [1] and [5] state it only uses 1 byte... which is correct? Opcode 40: [1] states that H is set to 0 from this opcode... is that correct? Opcodes 4A and 6A: These only take 4 cycles whereas all the other bitwise of the same type take 5. Is this correct??? Opcode 5A: CMPW YA, $12 according to [1] and [5], CLRW $12 according to [2] Opcode 99: [2] calls it MOV (X), (Y), other documentation calls it ADC (X), (Y) Since both state that opcode 89 is SBC (X), (Y) and more documentation uses ADC (X), (Y), I'm going to believe that ADC (X), (Y) is correct Opcode DA: Takes 5 cycles according to exact CPU testing [3] and listed by [5], not 4 as stated by [1] [4] states you only add 1 clock for taking a branch, [1] and [5] state you add 2. I am using 2 because more sources say to use 2 instead of 1. B flag is set by BRK, and POP PSW or RET1 can set or clear it just as they can any other flag. Presumably it would also be cleared by an IRQ or NMI, were either of those to exist. The BRK vector is the same as TCALL 0 (or CALL $FFDE). It pushes the PC and flags, then sets B and clears I before jumping to the BRK handler. *************************************************************************************************** A2 To Do List o Does the SPC700 add extra cycles for crossing page boundaries? o Fill in the Addressing Modes information o Real detailed descriptions of the various opcodes, if possible o Add pin information if we can find it o Add a list of the SPC700's addressing modes o I heard a rumor that another computer/system used the SPC700... see if we can find out what it was and if there is further information about the processor through that channel *************************************************************************************************** A3 Version History v0.2 2007-01-28 to 2007-02-17 Additions o Added sections 6 (Pins, no data yet), 7 (Quirks), A2 (To Do) and A3 (Version History) sections o Added information from [5] which added quirks information as well as clarification of a few issues o Added opcode data to each Mnemonic o Updated Excel Spreadsheet look o Added Specifications chart Corrections: o Reformatted to match the rest of the processor files o According to [5], MOV $12, $34 is stored as FA 34 12, so this has been changed v0.1 2006-10-24 to 2006-11-06? Original Version *************************************************************************************************** Sources Information Sources [1] APU Manual in Text (c) 1997, Ledi??? * Used for the SPC opcodes and timing. This documentation is riddle with typographical errors unfortunately [2] SPC 700 Documentation (c) ????, Gau of the Veldt * Cross checked the opcodes from Ledi's document, though both are wrong in some places it seems [3] ZNES Forums http://board.zsnes.com/phpBB2/viewtopic.php?t=3753 (c) 2005, Various Sources * Lots of stray comments in here about the SPC700 helped me figure out some of the workings, in particular those from anomie and blarrg [4] MAME Emulator Source Code http://www.mameworld.net/ and http://mamedev.org/ (c) 1998? - 2006, MAME * Used to cross check the other data Also, this was about the only place I could find any code (psuedo or real) for each instruction [5] Anomie's SPC700 Doc and Anomie's SPC700 Cycle Doc (c) ???, Anomie * Seems to be one of the most reliable single sources of information that I've found and is especially useful because of the quirks listing