SPC-700 instruction set: Difference between revisions

From SNESdev Wiki
Jump to navigationJump to search
(→‎Instructions: fix OR1)
 
(17 intermediate revisions by 3 users not shown)
Line 1: Line 1:
The Sony SPC-700 CPU is part of the [[S-SMP]] sound processor of the SNES. It runs at 2.048 MHz, and behaves similarly to a 6502 at 1.024 MHz with some extensions.
The Sony SPC-700 CPU is part of the [[S-SMP]] sound processor of the SNES. It runs at 1.024 MHz, and behaves similarly to a 6502 with some extensions.


== Architecture ==
== Architecture ==
Line 25: Line 25:


* imm - 8-bit immediate value
* imm - 8-bit immediate value
* dp - 8-bit direct page offset ($0000+dp or $01000+dp)
* dp - 8-bit direct page offset ($0000 + dp or $0100 + dp)
* !abs - 16-bit absolute address
* !abs - 16-bit absolute address
* rel - relative offset in two's complement
* rel - relative offset in two's complement
Line 35: Line 35:
=== Differences from the 6502 ===
=== Differences from the 6502 ===


* A 16-bit combined YA register is available for some operations.
==== Removed from SPC700 ====
 
* Decimal mode is missing; instead, <tt>DAA</tt> and <tt>DAS</tt> instructions which use the added half-carry flag are provided.
* The indirect ''non''-indexed variant of <tt>JMP</tt>.
* The <tt>LDX abs, Y</tt> and <tt>LDY abs, X</tt> instructions.
* The <tt>BIT</tt> instruction.
* <tt>abs, X</tt> modes in read-modify-write instructions: <tt>INC</tt>, <tt>DEC</tt>, <tt>ASL</tt>, <tt>LSR</tt>, <tt>ROL</tt>, <tt>ROR</tt>. (The <tt>zp, X</tt> and <tt>abs</tt> modes are available).
 
==== New to SPC700 ====
 
* The direct page can be moved to $0100. (Rarely used.)
* The direct page can be moved to $0100. (Rarely used.)
* A half carry flag that is useful for nibble operations, can be cleared by <tt>CLRV</tt>.
* 16-bit operations, using either the direct page or the new 16-bit register YA:
* No decimal mode, instead provides <tt>DAA</tt> and <tt>DAS</tt> instructions.
** <tt>MOVW</tt>, <tt>ADDW</tt>, <tt>SUBW</tt>, <tt>CMPW</tt>, <tt>INCW</tt>, <tt>DECW</tt>.
* Iterrupt status flag is enable, not disable. (Not important for SNES.)
** <tt>MUL</tt>, <tt>DIV</tt>: multiply/divide instructions.
* Some operations allow direct page as a register-like destination, e.g. <tt>MOV dp, #imm</tt> or <tt>ADC dp, dp</tt>.
* <tt>CBNE</tt>, <tt>DBNZ</tt>: loop instructions.
* X or Y can be sometimes be used as an index to the direct page, possibly with an automatic post-increment, e.g. <tt>MOV (X)+</tt> or <tt>ADC (X), (Y)</tt>.
* <tt>PCALL</tt>, <tt>TCALL</tt>: abbreviated call instructions for the high page of memory.
* Multiply and divide instructions <tt>MUL</tt> and <tt>DIV</tt>.
* <tt>SET1</tt>, <tt>NOT1</tt>, <tt>MOV1</tt>, <tt>AND1</tt>, <tt>OR1</tt>, <tt>EOR1</tt>: single-bit operations on the lower 8KB of memory.
* Loop instructions <tt>CBNE</tt> and <tt>DBNZ</tt>.
* <tt>XCN A</tt>: nibble exchange.
* Abbreviated call instructions the high page of memory <tt>PCALL</tt> and <tt>TCALL</tt>.
 
* Memory bit operations <tt>SET1</tt>, <tt>NOT1</tt>, <tt>MOV1</tt>, etc.
New addressing modes:
 
* Load/store, arithmetic and boolean operations have added the following modes:
** Direct page <- Immediate: <tt>MOV dp, #imm</tt>
** Direct page <- Direct page: <tt>AND dp, dp</tt>
** A <- Direct page pointer in X: <tt>OR A, (X)</tt>
** Direct page pointer in X <- Direct page pointer in Y: <tt>EOR (X), (Y)</tt>
* Load/store operations have added these additional modes:
** Direct page pointer in X, post-increment: <tt>MOV (X)+</tt>
 
Note that some features, despite not being available in the original 6502, have been previously introduced by the 65C02:
 
* <tt>BBC</tt>, <tt>BBS</tt>: branch on an individual bit set/clear in direct page locations.
* <tt>BRA</tt>: branch always.
* <tt>INC</tt>, <tt>DEC</tt> for the accumulator.
* <tt>RMB</tt>, <tt>SMB</tt>: set/clear an individual bit in direct page locations.
* The indirect indexed variant of <tt>JMP</tt>.
* The ability to directly push and pop <tt>X</tt> and <tt>Y</tt>.
 
==== Changed in SPC700 ====
 
* Interrupt status flag is enable, not disable. (Not important for SNES: there is no IRQ.)
* The cycle timings of many instructions are slightly different.
* <tt>POP</tt> instructions do not modify flags (except <tt>POP PSW</tt>).
* <tt>CALL</tt> places the address of the next instruction on the stack, rather than a pre-increment (-1) address like the 6502. <tt>RET</tt> similarly does not have a post-increment for the popped address.
* <tt>TSET1</tt> and <tt>TCLR1</tt> don't work like <tt>TSB</tt> and <tt>TRB</tt> on the 65C02: instead of using a bit test to set Z, the N/Z flags are set using an equality test.


== Instructions ==
== Instructions ==
Line 53: Line 87:
Sony instruction convention puts the destination on the left, source on the right (Intel syntax).
Sony instruction convention puts the destination on the left, source on the right (Intel syntax).


Cycles in this table are 1.024 MHz CPU cycles. Each one is equal to 2 clocks of the 2.048 Mhz S-SMP.
Cycles in this table are 1.024 MHz CPU cycles. Each one is equal to 2 clocks of the 2.048 MHz S-SMP.


{| class="wikitable sortable"
{| class="wikitable sortable"
Line 93: Line 127:
|-
|-
| <tt>MOV A, dp</tt>
| <tt>MOV A, dp</tt>
| <tt>LDA zp</tt>
| <tt>LDA dp</tt>
| <tt>E4</tt>
| <tt>E4</tt>
| 2
| 2
Line 101: Line 135:
|-
|-
| <tt>MOV A, dp+X</tt>
| <tt>MOV A, dp+X</tt>
| <tt>LDA zp, X</tt>
| <tt>LDA dp, X</tt>
| <tt>F4</tt>
| <tt>F4</tt>
| 2
| 2
Line 133: Line 167:
|-
|-
| <tt>MOV A, [dp+X]</tt>
| <tt>MOV A, [dp+X]</tt>
| <tt>LDA (zp, X)</tt>
| <tt>LDA (dp, X)</tt>
| <tt>E7</tt>
| <tt>E7</tt>
| 2
| 2
Line 157: Line 191:
|-
|-
| <tt>MOV X, dp</tt>
| <tt>MOV X, dp</tt>
| <tt>LDX zp</tt>
| <tt>LDX dp</tt>
| <tt>F8</tt>
| <tt>F8</tt>
| 2
| 2
Line 165: Line 199:
|-
|-
| <tt>MOV X, dp+Y</tt>
| <tt>MOV X, dp+Y</tt>
| <tt>LDX zp, Y</tt>
| <tt>LDX dp, Y</tt>
| <tt>F9</tt>
| <tt>F9</tt>
| 2
| 2
Line 190: Line 224:
|-
|-
| <tt>MOV Y, dp</tt>
| <tt>MOV Y, dp</tt>
| <tt>LDY zp</tt>
| <tt>LDY dp</tt>
| <tt>EB</tt>
| <tt>EB</tt>
| 2
| 2
Line 198: Line 232:
|-
|-
| <tt>MOV Y, dp+X</tt>
| <tt>MOV Y, dp+X</tt>
| <tt>LDY zp, X</tt>
| <tt>LDY dp, X</tt>
| <tt>FB</tt>
| <tt>FB</tt>
| 2
| 2
Line 232: Line 266:
|-
|-
| <tt>MOV dp, A</tt>
| <tt>MOV dp, A</tt>
| <tt>STA zp</tt>
| <tt>STA dp</tt>
| <tt>C4</tt>
| <tt>C4</tt>
| 2
| 2
Line 240: Line 274:
|-
|-
| <tt>MOV dp+X, A</tt>
| <tt>MOV dp+X, A</tt>
| <tt>STA zp, X</tt>
| <tt>STA dp, X</tt>
| <tt>D4</tt>
| <tt>D4</tt>
| 2
| 2
Line 272: Line 306:
|-
|-
| <tt>MOV [dp+X], A</tt>
| <tt>MOV [dp+X], A</tt>
| <tt>STA (zp, X)</tt>
| <tt>STA (dp, X)</tt>
| <tt>C7</tt>
| <tt>C7</tt>
| 2
| 2
Line 280: Line 314:
|-
|-
| <tt>MOV [dp]+Y, A</tt>
| <tt>MOV [dp]+Y, A</tt>
| <tt>STA (zp), Y</tt>
| <tt>STA (dp), Y</tt>
| <tt>D7</tt>
| <tt>D7</tt>
| 2
| 2
Line 288: Line 322:
|-
|-
| <tt>MOV dp, X</tt>
| <tt>MOV dp, X</tt>
| <tt>STX zp</tt>
| <tt>STX dp</tt>
| <tt>D8</tt>
| <tt>D8</tt>
| 2
| 2
Line 296: Line 330:
|-
|-
| <tt>MOV dp+Y, X</tt>
| <tt>MOV dp+Y, X</tt>
| <tt>STX zp, Y</tt>
| <tt>STX dp, Y</tt>
| <tt>D9</tt>
| <tt>D9</tt>
| 2
| 2
Line 312: Line 346:
|-
|-
| <tt>MOV dp, Y</tt>
| <tt>MOV dp, Y</tt>
| <tt>STY zp</tt>
| <tt>STY dp</tt>
| <tt>CB</tt>
| <tt>CB</tt>
| 2
| 2
Line 320: Line 354:
|-
|-
| <tt>MOV dp+X, Y</tt>
| <tt>MOV dp+X, Y</tt>
| <tt>STY zp, X</tt>
| <tt>STY dp, X</tt>
| <tt>DB</tt>
| <tt>DB</tt>
| 2
| 2
Line 420: Line 454:
|-
|-
| <tt>ADC A, dp</tt>
| <tt>ADC A, dp</tt>
| <tt>ADC zp</tt>
| <tt>ADC dp</tt>
| <tt>84</tt>
| <tt>84</tt>
| 2
| 2
Line 428: Line 462:
|-
|-
| <tt>ADC A, dp+X</tt>
| <tt>ADC A, dp+X</tt>
| <tt>ADC zp, X</tt>
| <tt>ADC dp, X</tt>
| <tt>94</tt>
| <tt>94</tt>
| 2
| 2
Line 460: Line 494:
|-
|-
| <tt>ADC A, [dp+X]</tt>
| <tt>ADC A, [dp+X]</tt>
| <tt>ADC (zp, X)</tt>
| <tt>ADC (dp, X)</tt>
| <tt>87</tt>
| <tt>87</tt>
| 2
| 2
Line 516: Line 550:
|-
|-
| <tt>SBC A, dp</tt>
| <tt>SBC A, dp</tt>
| <tt>SBC zp</tt>
| <tt>SBC dp</tt>
| <tt>A4</tt>
| <tt>A4</tt>
| 2
| 2
Line 524: Line 558:
|-
|-
| <tt>SBC A, dp+X</tt>
| <tt>SBC A, dp+X</tt>
| <tt>SBC zp, X</tt>
| <tt>SBC dp, X</tt>
| <tt>B4</tt>
| <tt>B4</tt>
| 2
| 2
Line 556: Line 590:
|-
|-
| <tt>SBC A, [dp+X]</tt>
| <tt>SBC A, [dp+X]</tt>
| <tt>SBC (zp, X)</tt>
| <tt>SBC (dp, X)</tt>
| <tt>A7</tt>
| <tt>A7</tt>
| 2
| 2
Line 612: Line 646:
|-
|-
| <tt>CMP A, dp</tt>
| <tt>CMP A, dp</tt>
| <tt>CMP zp</tt>
| <tt>CMP dp</tt>
| <tt>64</tt>
| <tt>64</tt>
| 2
| 2
Line 620: Line 654:
|-
|-
| <tt>CMP A, dp+X</tt>
| <tt>CMP A, dp+X</tt>
| <tt>CMP zp, X</tt>
| <tt>CMP dp, X</tt>
| <tt>74</tt>
| <tt>74</tt>
| 2
| 2
Line 652: Line 686:
|-
|-
| <tt>CMP A, [dp+X]</tt>
| <tt>CMP A, [dp+X]</tt>
| <tt>CMP (zp, X)</tt>
| <tt>CMP (dp, X)</tt>
| <tt>67</tt>
| <tt>67</tt>
| 2
| 2
Line 700: Line 734:
|-
|-
| <tt>CMP X, dp</tt>
| <tt>CMP X, dp</tt>
| <tt>CPX zp</tt>
| <tt>CPX dp</tt>
| <tt>3E</tt>
| <tt>3E</tt>
| 2
| 2
Line 724: Line 758:
|-
|-
| <tt>CMP Y, dp</tt>
| <tt>CMP Y, dp</tt>
| <tt>CPY zp</tt>
| <tt>CPY dp</tt>
| <tt>7E</tt>
| <tt>7E</tt>
| 2
| 2
Line 758: Line 792:
|-
|-
| <tt>AND A, dp</tt>
| <tt>AND A, dp</tt>
| <tt>AND zp</tt>
| <tt>AND dp</tt>
| <tt>24</tt>
| <tt>24</tt>
| 2
| 2
Line 766: Line 800:
|-
|-
| <tt>AND A, dp+X</tt>
| <tt>AND A, dp+X</tt>
| <tt>AND zp, X</tt>
| <tt>AND dp, X</tt>
| <tt>34</tt>
| <tt>34</tt>
| 2
| 2
Line 798: Line 832:
|-
|-
| <tt>AND A, [dp+X]</tt>
| <tt>AND A, [dp+X]</tt>
| <tt>AND (zp, X)</tt>
| <tt>AND (dp, X)</tt>
| <tt>27</tt>
| <tt>27</tt>
| 2
| 2
Line 838: Line 872:
|-
|-
| <tt>OR A, #imm</tt>
| <tt>OR A, #imm</tt>
| <tt>OR #imm</tt>
| <tt>ORA #imm</tt>
| <tt>08</tt>
| <tt>08</tt>
| 2
| 2
Line 854: Line 888:
|-
|-
| <tt>OR A, dp</tt>
| <tt>OR A, dp</tt>
| <tt>OR zp</tt>
| <tt>ORA dp</tt>
| <tt>04</tt>
| <tt>04</tt>
| 2
| 2
Line 862: Line 896:
|-
|-
| <tt>OR A, dp+X</tt>
| <tt>OR A, dp+X</tt>
| <tt>OR zp, X</tt>
| <tt>ORA dp, X</tt>
| <tt>14</tt>
| <tt>14</tt>
| 2
| 2
Line 870: Line 904:
|-
|-
| <tt>OR A, !abs</tt>
| <tt>OR A, !abs</tt>
| <tt>OR abs</tt>
| <tt>ORA abs</tt>
| <tt>05</tt>
| <tt>05</tt>
| 3
| 3
Line 878: Line 912:
|-
|-
| <tt>OR A, !abs+X</tt>
| <tt>OR A, !abs+X</tt>
| <tt>OR abs, X</tt>
| <tt>ORA abs, X</tt>
| <tt>15</tt>
| <tt>15</tt>
| 3
| 3
Line 886: Line 920:
|-
|-
| <tt>OR A, !abs+Y</tt>
| <tt>OR A, !abs+Y</tt>
| <tt>OR abs, Y</tt>
| <tt>ORA abs, Y</tt>
| <tt>16</tt>
| <tt>16</tt>
| 3
| 3
Line 894: Line 928:
|-
|-
| <tt>OR A, [dp+X]</tt>
| <tt>OR A, [dp+X]</tt>
| <tt>OR (zp, X)</tt>
| <tt>ORA (dp, X)</tt>
| <tt>07</tt>
| <tt>07</tt>
| 2
| 2
Line 902: Line 936:
|-
|-
| <tt>OR A, [dp]+Y</tt>
| <tt>OR A, [dp]+Y</tt>
| <tt>OR (dp), Y</tt>
| <tt>ORA (dp), Y</tt>
| <tt>17</tt>
| <tt>17</tt>
| 2
| 2
Line 950: Line 984:
|-
|-
| <tt>EOR A, dp</tt>
| <tt>EOR A, dp</tt>
| <tt>EOR zp</tt>
| <tt>EOR dp</tt>
| <tt>44</tt>
| <tt>44</tt>
| 2
| 2
Line 958: Line 992:
|-
|-
| <tt>EOR A, dp+X</tt>
| <tt>EOR A, dp+X</tt>
| <tt>EOR zp, X</tt>
| <tt>EOR dp, X</tt>
| <tt>54</tt>
| <tt>54</tt>
| 2
| 2
Line 990: Line 1,024:
|-
|-
| <tt>EOR A, [dp+X]</tt>
| <tt>EOR A, [dp+X]</tt>
| <tt>EOR (zp, X)</tt>
| <tt>EOR (dp, X)</tt>
| <tt>47</tt>
| <tt>47</tt>
| 2
| 2
Line 1,040: Line 1,074:
|-
|-
| <tt>INC dp</tt>
| <tt>INC dp</tt>
| <tt>INC zp</tt>
| <tt>INC dp</tt>
| <tt>AB</tt>
| <tt>AB</tt>
| 2
| 2
Line 1,048: Line 1,082:
|-
|-
| <tt>INC dp+X</tt>
| <tt>INC dp+X</tt>
| <tt>INC zp, X</tt>
| <tt>INC dp, X</tt>
| <tt>BB</tt>
| <tt>BB</tt>
| 2
| 2
Line 1,088: Line 1,122:
|-
|-
| <tt>DEC dp</tt>
| <tt>DEC dp</tt>
| <tt>DEC zp</tt>
| <tt>DEC dp</tt>
| <tt>8B</tt>
| <tt>8B</tt>
| 2
| 2
Line 1,096: Line 1,130:
|-
|-
| <tt>DEC dp+X</tt>
| <tt>DEC dp+X</tt>
| <tt>DEC zp, X</tt>
| <tt>DEC dp, X</tt>
| <tt>9B</tt>
| <tt>9B</tt>
| 2
| 2
Line 1,138: Line 1,172:
|-
|-
| <tt>ASL dp</tt>
| <tt>ASL dp</tt>
| <tt>ASL zp</tt>
| <tt>ASL dp</tt>
| <tt>0B</tt>
| <tt>0B</tt>
| 2
| 2
Line 1,146: Line 1,180:
|-
|-
| <tt>ASL dp+X</tt>
| <tt>ASL dp+X</tt>
| <tt>ASL zp, X</tt>
| <tt>ASL dp, X</tt>
| <tt>1B</tt>
| <tt>1B</tt>
| 2
| 2
Line 1,170: Line 1,204:
|-
|-
| <tt>LSR dp</tt>
| <tt>LSR dp</tt>
| <tt>LSR zp</tt>
| <tt>LSR dp</tt>
| <tt>4B</tt>
| <tt>4B</tt>
| 2
| 2
Line 1,178: Line 1,212:
|-
|-
| <tt>LSR dp+X</tt>
| <tt>LSR dp+X</tt>
| <tt>LSR zp, X</tt>
| <tt>LSR dp, X</tt>
| <tt>5B</tt>
| <tt>5B</tt>
| 2
| 2
Line 1,202: Line 1,236:
|-
|-
| <tt>ROL dp</tt>
| <tt>ROL dp</tt>
| <tt>ROL zp</tt>
| <tt>ROL dp</tt>
| <tt>2B</tt>
| <tt>2B</tt>
| 2
| 2
Line 1,210: Line 1,244:
|-
|-
| <tt>ROL dp+X</tt>
| <tt>ROL dp+X</tt>
| <tt>ROL zp, X</tt>
| <tt>ROL dp, X</tt>
| <tt>3B</tt>
| <tt>3B</tt>
| 2
| 2
Line 1,234: Line 1,268:
|-
|-
| <tt>ROR dp</tt>
| <tt>ROR dp</tt>
| <tt>ROR zp</tt>
| <tt>ROR dp</tt>
| <tt>6B</tt>
| <tt>6B</tt>
| 2
| 2
Line 1,242: Line 1,276:
|-
|-
| <tt>ROR dp+X</tt>
| <tt>ROR dp+X</tt>
| <tt>ROR zp, X</tt>
| <tt>ROR dp, X</tt>
| <tt>7B</tt>
| <tt>7B</tt>
| 2
| 2
Line 1,329: Line 1,363:
| 9
| 9
| <tt>N.....Z.</tt>
| <tt>N.....Z.</tt>
| YA = Y * A
| <tt>YA = Y * A</tt><br/>n/z flags based on Y register (high-byte) only
|-
|-
| <tt>DIV YA, X</tt>
| <tt>DIV YA, X</tt>
Line 1,337: Line 1,371:
| 12
| 12
| <tt>NV..H.Z.</tt>
| <tt>NV..H.Z.</tt>
| <tt>A = YA / X</tt>, <tt>Y = YA % X</tt>
| <tt>A = YA / X</tt>, <tt>Y = YA % X</tt><br/>Bit 8 of quotient is stored in the overflow (v) flag.<br/>Output only valid if quotient is &lt;= 511.<br/>n/z flags based on A register (bits 0-7 of quotient) only.
|-
|-
| colspan=7 | . '''decimal adjust'''
| colspan=7 | . '''decimal adjust'''
Line 1,347: Line 1,381:
| 3
| 3
| <tt>N.....ZC</tt>
| <tt>N.....ZC</tt>
| TODO
| Apply carry/half-carry after BCD addition
|-
|-
| <tt>DAS A</tt>
| <tt>DAS A</tt>
Line 1,355: Line 1,389:
| 3
| 3
| <tt>N.....ZC</tt>
| <tt>N.....ZC</tt>
| TODO
| Apply carry/half-carry after BCD subtraction
|-
|-
| colspan=7 | . '''branching'''
| colspan=7 | . '''branching'''
|-
|-
| <tt>BRA rel</tt>
| <tt>BRA rel</tt>
| <tt>?</tt>
| <tt>BRA rel</tt>
| <tt>2F</tt>
| <tt>2F</tt>
| 2
| 2
Line 1,432: Line 1,466:
|-
|-
| <tt>BBS dp, bit, rel</tt>
| <tt>BBS dp, bit, rel</tt>
| <tt>?</tt>
| <tt>BBS bit, dp, rel</tt>
| <tt>x3</tt>
| <tt>x3</tt>
| 3
| 3
Line 1,440: Line 1,474:
|-
|-
| <tt>BBC dp, bit, rel</tt>
| <tt>BBC dp, bit, rel</tt>
| <tt>?</tt>
| <tt>BBR bit, dp, rel</tt>
| <tt>y3</tt>
| <tt>y3</tt>
| 3
| 3
Line 1,488: Line 1,522:
|-
|-
| <tt>JMP [!abs+X]</tt>
| <tt>JMP [!abs+X]</tt>
| <tt>?</tt>
| <tt>JMP (abs, X)</tt>
| <tt>1F</tt>
| <tt>1F</tt>
| 3
| 3
Line 1,530: Line 1,564:
|-
|-
| <tt>RET</tt>
| <tt>RET</tt>
| <tt>RET</tt>
| <tt>RTS</tt>
| <tt>6F</tt>
| <tt>6F</tt>
| 1
| 1
Line 1,538: Line 1,572:
|-
|-
| <tt>RETI</tt>
| <tt>RETI</tt>
| <tt>RETI</tt>
| <tt>RTI</tt>
| <tt>7F</tt>
| <tt>7F</tt>
| 1
| 1
Line 1,614: Line 1,648:
|-
|-
| <tt>SET1 dp, bit</tt>
| <tt>SET1 dp, bit</tt>
| <tt>?</tt>
| <tt>SMB bit, dp</tt>
| <tt>x2</tt>
| <tt>x2</tt>
| 2
| 2
Line 1,622: Line 1,656:
|-
|-
| <tt>CLR1 dp, bit</tt>
| <tt>CLR1 dp, bit</tt>
| <tt>?</tt>
| <tt>RMB bit, dp</tt>
| <tt>y2</tt>
| <tt>y2</tt>
| 2
| 2
Line 1,635: Line 1,669:
| 6
| 6
| <tt>N.....Z.</tt>
| <tt>N.....Z.</tt>
| Test and set bits with A
| Test and set bits with A<br/>Equality test (<tt>A - old_value</tt>)
|-
|-
| <tt>TCLR1 !abs</tt>
| <tt>TCLR1 !abs</tt>
Line 1,643: Line 1,677:
| 6
| 6
| <tt>N.....Z.</tt>
| <tt>N.....Z.</tt>
| Test and clear bits with A
| Test and clear bits with A<br/>Equality test (<tt>A - old_value</tt>)
|-
|-
| <tt>AND1 C, abs, bit</tt>
| <tt>AND1 C, abs, bit</tt>
Line 1,735: Line 1,769:
| C ^= 1
| C ^= 1
|-
|-
| <tt>CLRC</tt>
| <tt>CLRV</tt>
| <tt>CLV</tt>
| <tt>CLV</tt>
| <tt>E0</tt>
| <tt>E0</tt>
Line 1,786: Line 1,820:
|-
|-
| <tt>SLEEP</tt>
| <tt>SLEEP</tt>
| <tt>?</tt>
| <tt>WAI</tt>
| <tt>EF</tt>
| <tt>EF</tt>
| 1
| 1
Line 1,794: Line 1,828:
|-
|-
| <tt>STOP</tt>
| <tt>STOP</tt>
| <tt>?</tt>
| <tt>STP</tt>
| <tt>FF</tt>
| <tt>FF</tt>
| 1
| 1
Line 1,801: Line 1,835:
|
|
|}
|}
Instruction list:
* <tt>MOV</tt>
* <tt>ADC</tt> <tt>SBC</tt> <tt>CMP</tt>
* <tt>AND</tt> <tt>OR</tt> <tt>EOR</tt> <tt>ASL</tt> <tt>LSR</tt> <tt>ROL</tt> <tt>XCN</tt>
* <tt>INC</tt> <tt>DEC</tt>
* <tt>MOVW</tt> <tt>INCW</tt> <tt>DECW</tt> <tt>ADDW</tt> <tt>SUBW</tt> <tt>CMPW</tt> <tt>MUL</tt> <tt>DIV</tt>
* <tt>DAA</tt> <tt>DAS</tt>
* <tt>BRA</tt> <tt>BEQ</tt> <tt>BNE</tt> <tt>BCS</tt> <tt>BCC</tt> <tt>BVS</tt> <tt>BVC</tt> <tt>BMI</tt> <tt>BPL</tt> <tt>BBS</tt> <tt>BBC</tt> <tt>CBNE</tt> <tt>DBNZ</tt> <tt>JMP</tt>
* <tt>CALL</tt> <tt>PCALL</tt> <tt>TCALL</tt> <tt>BRK</tt> <tt>RET</tt> <tt>RETI</tt>
* <tt>PUSH</tt> <tt>POP</tt>
* <tt>SET1</tt> <tt>CLR1</tt> <tt>TSET1</tt> <tt>TCLR1</tt> <tt>AND1</tt> <tt>OR1</tt> <tt>EOR1</tt> <tt>NOT1</tt> <tt>MOV1</tt>
* <tt>CLRC</tt> <tt>SETC</tt> <tt>NOTC</tt> <tt>CLRV</tt> <tt>CLRP</tt> <tt>SETP</tt> <tt>EI</tt> <tt>DI</tt>
* <tt>NOP</tt> <tt>SLEEP</tt> <tt>STOP</tt>


== Links ==
== Links ==

Latest revision as of 17:16, 4 March 2024

The Sony SPC-700 CPU is part of the S-SMP sound processor of the SNES. It runs at 1.024 MHz, and behaves similarly to a 6502 with some extensions.

Architecture

The SPC-700 has a 16-bit address space, and a similar set of registers to the 6502.

Registers

  • A - 8-bit accumulator
  • X - 8-bit index
  • Y - 8-bit index
  • YA - 16-bit pair of A (lsb) and Y (msb).
  • PC - program counter
  • SP - stack pointer
  • PSW - program status word: NVPBHIZC
    • N - negative flag (high bit of result was set)
    • V - overflow flag (signed overflow indication)
    • P - direct page flag (moves the direct page to $0100 if set)
    • H - half-carry flag (carry between low and high nibble)
    • I - interrupt enable (unused: the S-SMP has no attached interrupts)
    • Z - zero flag (set if last result was zero)
    • C - carry flag

Addressing Modes

  • imm - 8-bit immediate value
  • dp - 8-bit direct page offset ($0000 + dp or $0100 + dp)
  • !abs - 16-bit absolute address
  • rel - relative offset in two's complement
  • (i) - direct-page relative index (P * $100 + i)
  • (i)+ - direct-page relative index with post-increment (i is incremented after read)
  • [addr]+i - indirect indexed (add index after 16-bit lookup)
  • [addr+i] - indexed indirect (add index before 16-bit lookup)

Differences from the 6502

Removed from SPC700

  • Decimal mode is missing; instead, DAA and DAS instructions which use the added half-carry flag are provided.
  • The indirect non-indexed variant of JMP.
  • The LDX abs, Y and LDY abs, X instructions.
  • The BIT instruction.
  • abs, X modes in read-modify-write instructions: INC, DEC, ASL, LSR, ROL, ROR. (The zp, X and abs modes are available).

New to SPC700

  • The direct page can be moved to $0100. (Rarely used.)
  • 16-bit operations, using either the direct page or the new 16-bit register YA:
    • MOVW, ADDW, SUBW, CMPW, INCW, DECW.
    • MUL, DIV: multiply/divide instructions.
  • CBNE, DBNZ: loop instructions.
  • PCALL, TCALL: abbreviated call instructions for the high page of memory.
  • SET1, NOT1, MOV1, AND1, OR1, EOR1: single-bit operations on the lower 8KB of memory.
  • XCN A: nibble exchange.

New addressing modes:

  • Load/store, arithmetic and boolean operations have added the following modes:
    • Direct page <- Immediate: MOV dp, #imm
    • Direct page <- Direct page: AND dp, dp
    • A <- Direct page pointer in X: OR A, (X)
    • Direct page pointer in X <- Direct page pointer in Y: EOR (X), (Y)
  • Load/store operations have added these additional modes:
    • Direct page pointer in X, post-increment: MOV (X)+

Note that some features, despite not being available in the original 6502, have been previously introduced by the 65C02:

  • BBC, BBS: branch on an individual bit set/clear in direct page locations.
  • BRA: branch always.
  • INC, DEC for the accumulator.
  • RMB, SMB: set/clear an individual bit in direct page locations.
  • The indirect indexed variant of JMP.
  • The ability to directly push and pop X and Y.

Changed in SPC700

  • Interrupt status flag is enable, not disable. (Not important for SNES: there is no IRQ.)
  • The cycle timings of many instructions are slightly different.
  • POP instructions do not modify flags (except POP PSW).
  • CALL places the address of the next instruction on the stack, rather than a pre-increment (-1) address like the 6502. RET similarly does not have a post-increment for the popped address.
  • TSET1 and TCLR1 don't work like TSB and TRB on the 65C02: instead of using a bit test to set Z, the N/Z flags are set using an equality test.

Instructions

Official instruction names and syntax for SPC-700 instruction were provided by Sony. However, because of its architectural similarity to 6502, some prefer to rename and remap them using a 6502 style syntax. Both are provided here.

Sony instruction convention puts the destination on the left, source on the right (Intel syntax).

Cycles in this table are 1.024 MHz CPU cycles. Each one is equal to 2 clocks of the 2.048 MHz S-SMP.

SPC-700 Instruction Set
Instruction 6502-Style Opcode Bytes Cycles Flags Notes
. 8-bit move memory to register
MOV A, #imm LDA #imm E8 2 2 N.....Z.
MOV A, (X) ? E6 1 3 N.....Z.
MOV A, (X)+ ? BF 1 4 N.....Z. X++ after read
MOV A, dp LDA dp E4 2 3 N.....Z.
MOV A, dp+X LDA dp, X F4 2 4 N.....Z.
MOV A, !abs LDA abs E5 3 4 N.....Z.
MOV A, !abs+X LDA abs, X F5 3 5 N.....Z.
MOV A, !abs+Y LDA abs, Y F6 3 5 N.....Z.
MOV A, [dp+X] LDA (dp, X) E7 2 6 N.....Z.
MOV A, [dp]+Y LDA (dp), Y F7 2 6 N.....Z.
MOV X, #imm LDX #imm CD 2 2 N.....Z.
MOV X, dp LDX dp F8 2 3 N.....Z.
MOV X, dp+Y LDX dp, Y F9 2 4 N.....Z.
MOV X, !abs LDX abs E9 3 4 N.....Z.
MOV Y, #imm LDY #imm 8D 2 2 N.....Z.
MOV Y, dp LDY dp EB 2 3 N.....Z.
MOV Y, dp+X LDY dp, X FB 2 4 N.....Z.
MOV Y, !abs LDY abs EC 3 4 N.....Z.
. 8-bit move register to memory
MOV (X), A ? C6 1 4 ........
MOV (X)+, A ? AF 1 4 ........ X++ after read
MOV dp, A STA dp C4 2 4 ........
MOV dp+X, A STA dp, X D4 2 5 ........
MOV !abs, A STA abs C5 3 5 ........
MOV !abs+X, A STA abs, X D5 3 6 ........
MOV !abs+Y, A STA abs, Y D6 3 6 ........
MOV [dp+X], A STA (dp, X) C7 2 7 ........
MOV [dp]+Y, A STA (dp), Y D7 2 7 ........
MOV dp, X STX dp D8 2 4 ........
MOV dp+Y, X STX dp, Y D9 2 5 ........
MOV !abs, X STX abs C9 3 5 ........
MOV dp, Y STY dp CB 2 4 ........
MOV dp+X, Y STY dp, X DB 2 5 ........
MOV !abs, Y STY abs CC 3 5 ........
. 8-bit move register to register / special direct page moves
MOV A, X TXA 7D 1 2 N.....Z.
MOV A, Y TYA DD 1 2 N.....Z.
MOV X, A TAX 5D 1 2 N.....Z.
MOV Y, A TAY FD 1 2 N.....Z.
MOV X, SP TSX 9D 1 2 N.....Z.
MOV SP, X TXS BD 1 2 ........
MOV dp, dp ? FA 3 5 ........
MOV dp, #imm ? 8F 3 5 ........
. 8-bit arithmetic
ADC A, #imm ADC #imm 88 2 2 NV..H.ZC
ADC A, (X) ? 86 1 3 NV..H.ZC
ADC A, dp ADC dp 84 2 3 NV..H.ZC
ADC A, dp+X ADC dp, X 94 2 4 NV..H.ZC
ADC A, !abs ADC abs 85 3 4 NV..H.ZC
ADC A, !abs+X ADC abs, X 95 3 5 NV..H.ZC
ADC A, !abs+Y ADC abs, Y 96 3 5 NV..H.ZC
ADC A, [dp+X] ADC (dp, X) 87 2 6 NV..H.ZC
ADC A, [dp]+Y ADC (dp), Y 97 2 6 NV..H.ZC
ADC (X), (Y) ? 99 1 5 NV..H.ZC
ADC dp, dp ? 89 3 6 NV..H.ZC
ADC dp, #imm ? 98 3 5 NV..H.ZC
SBC A, #imm SBC #imm A8 2 2 NV..H.ZC
SBC A, (X) ? A6 1 3 NV..H.ZC
SBC A, dp SBC dp A4 2 3 NV..H.ZC
SBC A, dp+X SBC dp, X B4 2 4 NV..H.ZC
SBC A, !abs SBC abs A5 3 4 NV..H.ZC
SBC A, !abs+X SBC abs, X B5 3 5 NV..H.ZC
SBC A, !abs+Y SBC abs, Y B6 3 5 NV..H.ZC
SBC A, [dp+X] SBC (dp, X) A7 2 6 NV..H.ZC
SBC A, [dp]+Y SBC (dp), Y B7 2 6 NV..H.ZC
SBC (X), (Y) ? B9 1 5 NV..H.ZC
SBC dp, dp ? A9 3 6 NV..H.ZC
SBC dp, #imm ? B8 3 5 NV..H.ZC
CMP A, #imm CMP #imm 68 2 2 N.....ZC
CMP A, (X) ? 66 1 3 N.....ZC
CMP A, dp CMP dp 64 2 3 N.....ZC
CMP A, dp+X CMP dp, X 74 2 4 N.....ZC
CMP A, !abs CMP abs 65 3 4 N.....ZC
CMP A, !abs+X CMP abs, X 75 3 5 N.....ZC
CMP A, !abs+Y CMP abs, Y 76 3 5 N.....ZC
CMP A, [dp+X] CMP (dp, X) 67 2 6 N.....ZC
CMP A, [dp]+Y CMP (dp), Y 77 2 6 N.....ZC
CMP (X), (Y) ? 79 1 5 N.....ZC
CMP dp, dp ? 69 3 6 N.....ZC
CMP dp, #imm ? 78 3 5 N.....ZC
CMP X, #imm CPX #imm C8 2 2 N.....ZC
CMP X, dp CPX dp 3E 2 3 N.....ZC
CMP X, !abs CPX abs 1E 3 4 N.....ZC
CMP Y, #imm CPY #imm AD 2 2 N.....ZC
CMP Y, dp CPY dp 7E 2 3 N.....ZC
CMP Y, !abs CPY abs 5E 3 4 N.....ZC
. 8-bit boolean logic
AND A, #imm AND #imm 28 2 2 N.....Z.
AND A, (X) ? 26 1 3 N.....Z.
AND A, dp AND dp 24 2 3 N.....Z.
AND A, dp+X AND dp, X 34 2 4 N.....Z.
AND A, !abs AND abs 25 3 4 N.....Z.
AND A, !abs+X AND abs, X 35 3 5 N.....Z.
AND A, !abs+Y AND abs, Y 36 3 5 N.....Z.
AND A, [dp+X] AND (dp, X) 27 2 6 N.....Z.
AND A, [dp]+Y AND (dp), Y 37 2 6 N.....Z.
AND (X), (Y) ? 39 1 5 N.....Z.
AND dp, dp ? 29 3 6 N.....Z.
AND dp, #imm ? 38 3 5 N.....Z.
OR A, #imm ORA #imm 08 2 2 N.....Z.
OR A, (X) ? 06 1 3 N.....Z.
OR A, dp ORA dp 04 2 3 N.....Z.
OR A, dp+X ORA dp, X 14 2 4 N.....Z.
OR A, !abs ORA abs 05 3 4 N.....Z.
OR A, !abs+X ORA abs, X 15 3 5 N.....Z.
OR A, !abs+Y ORA abs, Y 16 3 5 N.....Z.
OR A, [dp+X] ORA (dp, X) 07 2 6 N.....Z.
OR A, [dp]+Y ORA (dp), Y 17 2 6 N.....Z.
OR (X), (Y) ? 19 1 5 N.....Z.
OR dp, dp ? 09 3 6 N.....Z.
OR dp, #imm ? 18 3 5 N.....Z.
EOR A, #imm EOR #imm 48 2 2 N.....Z.
EOR A, (X) ? 46 1 3 N.....Z.
EOR A, dp EOR dp 44 2 3 N.....Z.
EOR A, dp+X EOR dp, X 54 2 4 N.....Z.
EOR A, !abs EOR abs 45 3 4 N.....Z.
EOR A, !abs+X EOR abs, X 55 3 5 N.....Z.
EOR A, !abs+Y EOR abs, Y 56 3 5 N.....Z.
EOR A, [dp+X] EOR (dp, X) 47 2 6 N.....Z.
EOR A, [dp]+Y EOR (dp), Y 57 2 6 N.....Z.
EOR (X), (Y) ? 59 1 5 N.....Z.
EOR dp, dp ? 49 3 6 N.....Z.
EOR dp, #imm ? 58 3 5 N.....Z.
. 8-bit increment / decrement
INC A INC BC 1 2 N.....Z.
INC dp INC dp AB 2 4 N.....Z.
INC dp+X INC dp, X BB 2 5 N.....Z.
INC !abs INC abs AC 3 5 N.....Z.
INC X INX 3D 1 2 N.....Z.
INC Y INY FC 1 2 N.....Z.
DEC A DEC 9C 1 2 N.....Z.
DEC dp DEC dp 8B 2 4 N.....Z.
DEC dp+X DEC dp, X 9B 2 5 N.....Z.
DEC !abs DEC abs 8C 3 5 N.....Z.
DEC X DEX 1D 1 2 N.....Z.
DEC Y DEY DC 1 2 N.....Z.
. 8-bit shift / rotation
ASL A ASL 1C 1 2 N.....ZC
ASL dp ASL dp 0B 2 4 N.....ZC
ASL dp+X ASL dp, X 1B 2 5 N.....ZC
ASL !abs ASL abs 0C 3 5 N.....ZC
LSR A LSR 5C 1 2 N.....ZC
LSR dp LSR dp 4B 2 4 N.....ZC
LSR dp+X LSR dp, X 5B 2 5 N.....ZC
LSR !abs LSR abs 4C 3 5 N.....ZC
ROL A ROL 3C 1 2 N.....ZC
ROL dp ROL dp 2B 2 4 N.....ZC
ROL dp+X ROL dp, X 3B 2 5 N.....ZC
ROL !abs ROL abs 2C 3 5 N.....ZC
ROR A ROR 7C 1 2 N.....ZC
ROR dp ROR dp 6B 2 4 N.....ZC
ROR dp+X ROR dp, X 7B 2 5 N.....ZC
ROR !abs ROR abs 6C 3 5 N.....ZC
XCN A ? 9F 1 5 N.....Z. Exchange nibbles of A
. 16-bit operations
MOVW YA, dp ? BA 2 5 N.....Z.
MOVW dp, YA ? DA 2 4 ........
INCW dp ? 3A 2 6 N.....Z.
DECW dp ? 1A 2 6 N.....Z.
ADDW YA, dp ? 7A 2 5 NV..H.ZC Uses carry flag
SUBW YA, dp ? 9A 2 5 NV..H.ZC Uses carry flag
CMPW YA, dp ? 5A 2 4 N.....ZC
MUL YA ? CF 1 9 N.....Z. YA = Y * A
n/z flags based on Y register (high-byte) only
DIV YA, X ? 9E 1 12 NV..H.Z. A = YA / X, Y = YA % X
Bit 8 of quotient is stored in the overflow (v) flag.
Output only valid if quotient is <= 511.
n/z flags based on A register (bits 0-7 of quotient) only.
. decimal adjust
DAA A ? DF 1 3 N.....ZC Apply carry/half-carry after BCD addition
DAS A ? BE 1 3 N.....ZC Apply carry/half-carry after BCD subtraction
. branching
BRA rel BRA rel 2F 2 4 ........ Branch always
BEQ rel BEQ rel F0 2 2/4 ........ Branch if Z=1
BNE rel BNE rel D0 2 2/4 ........ Branch if Z=0
BCS rel BCS rel B0 2 2/4 ........ Branch if C=1
BCC rel BCC rel 90 2 2/4 ........ Branch if C=0
BVS rel BVS rel 70 2 2/4 ........ Branch if V=1
BVC rel BVC rel 50 2 2/4 ........ Branch if V=0
BMI rel BMI rel 30 2 2/4 ........ Branch if N=1
BPL rel BPL rel 10 2 2/4 ........ Branch if N=0
BBS dp, bit, rel BBS bit, dp, rel x3 3 5/7 ........ Branch if dp bit=1, x=(bit*2)
BBC dp, bit, rel BBR bit, dp, rel y3 3 5/7 ........ Branch if dp bit=1, y=(bit*2)+1
CBNE dp, rel ? 2E 3 5/7 ........ CMP A, dp then BNE
CBNE dp+X, rel ? DE 3 6/8 ........ CMP A, dp+X then BNE
DBNZ dp, rel ? 6E 3 5/7 ........ DEC dp then BNE
DBNZ Y, rel ? FE 2 4/6 ........ DEC Y then BNE
JMP !abs JMP abs 5F 3 3 ........
JMP [!abs+X] JMP (abs, X) 1F 3 6 ........
. subroutines
CALL !abs JSR abs 3F 3 8 ........
PCALL up ? 4F 2 6 ........ CALL $FF00 + up
TCALL n ? n1 1 8 ........ CALL [$FFDE-(2*n)]
BRK BRK 0F 1 8 ...1.0..
RET RTS 6F 1 5 ........
RETI RTI 7F 1 6 NVPBHIZC
. stack
PUSH A PHA 2D 1 4 ........
PUSH X PHX 4D 1 4 ........
PUSH Y PHY 6D 1 4 ........
PUSH PSW PHP 0D 1 4 ........
POP A PLA AE 1 4 ........
POP X PLX CE 1 4 ........
POP Y PLY EE 1 4 ........
POP PSW PLP 8E 1 4 NVPBHIZC
. memory bit operations
SET1 dp, bit SMB bit, dp x2 2 4 ........ Set dp bit, x=(bit*2)
CLR1 dp, bit RMB bit, dp y2 2 4 ........ Set dp bit, y=(bit*2)+1
TSET1 !abs TSB abs 0E 3 6 N.....Z. Test and set bits with A
Equality test (A - old_value)
TCLR1 !abs TRB abs 4E 3 6 N.....Z. Test and clear bits with A
Equality test (A - old_value)
AND1 C, abs, bit ? 4A 3 4 .......C C &= [abs] bit
AND1 C, /abs, bit ? 6A 3 4 .......C C &= !([abs] bit)
OR1 C, abs, bit ? 0A 3 5 .......C C |= [abs] bit
OR1 C, /abs, bit ? 2A 3 5 .......C C |= !([abs] bit)
EOR1 C, abs, bit ? 8A 3 5 .......C C ^= [abs] bit
NOT1 abs, bit ? EA 3 5 ........ [abs] bit ^= 1
MOV1 C, abs, bit ? AA 3 4 .......C C = [abs] bit
MOV1 abs, bit, C ? CA 3 6 ........ [abs] bit = C
. status flags
CLRC CLC 60 1 2 .......0
SETC SEC 80 1 2 .......1
NOTC ? ED 1 3 .......C C ^= 1
CLRV CLV E0 1 2 .0..0... Clears V and H
CLRP ? 20 1 2 ..0.....
SETP ? 40 1 2 ..1.....
EI CLI A0 1 3 ......1.
DI SEI C0 1 3 ......0.
. no-operation and halt
NOP NOP 00 1 2 ........
SLEEP WAI EF 1 3 ........
STOP STP FF 1 2 ........

Instruction list:

  • MOV
  • ADC SBC CMP
  • AND OR EOR ASL LSR ROL XCN
  • INC DEC
  • MOVW INCW DECW ADDW SUBW CMPW MUL DIV
  • DAA DAS
  • BRA BEQ BNE BCS BCC BVS BVC BMI BPL BBS BBC CBNE DBNZ JMP
  • CALL PCALL TCALL BRK RET RETI
  • PUSH POP
  • SET1 CLR1 TSET1 TCLR1 AND1 OR1 EOR1 NOT1 MOV1
  • CLRC SETC NOTC CLRV CLRP SETP EI DI
  • NOP SLEEP STOP

Links