User Tools

Site Tools


sd:isa

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
sd:isa [2026/06/16 07:53] appledogsd:isa [2026/06/18 04:53] (current) appledog
Line 3: Line 3:
 == ISA Overview == ISA Overview
 The SD-8516 instruction set is organized into four tiers. Numbering is canonical The SD-8516 instruction set is organized into four tiers. Numbering is canonical
-in decimal (as defined in ''arch.h''); hex is given alongside for convenience.+in decimal (as defined in ''arch.h'' and ''arch.ts''); hex is given alongside for convenience.
  
 * **Tier 1 - Core** behaves like a RISC instruction set: small, orthogonal, and complete on its own. Target this first. Everything above it can be synthesized from the core if you have to. * **Tier 1 - Core** behaves like a RISC instruction set: small, orthogonal, and complete on its own. Target this first. Everything above it can be synthesized from the core if you have to.
 * **Tier 2 - Extended** are quality-of-life instructions for hand assemblers. ''ADD reg, imm'' is the canonical example: you do not need it (load the immediate and ''ADD''), but it is provided for convenience. ''MUL'' is in the same spirit, since you can loop with ''ADD''. * **Tier 2 - Extended** are quality-of-life instructions for hand assemblers. ''ADD reg, imm'' is the canonical example: you do not need it (load the immediate and ''ADD''), but it is provided for convenience. ''MUL'' is in the same spirit, since you can loop with ''ADD''.
 * **Tier 3 - CISC** are heavier, mostly VAX- and 680x0-flavored instructions: block memory, queue management, character scanning, jump tables. Each one folds a small loop into a single fetch-execute. * **Tier 3 - CISC** are heavier, mostly VAX- and 680x0-flavored instructions: block memory, queue management, character scanning, jump tables. Each one folds a small loop into a single fetch-execute.
-* **Tier 4 - Acceleration** are instructions added primarily to speed up a specific consumer: the LLVM backend (''MOVSX''/''MOVZX'', indexed addressing), the Forth system (''LSTEP'' and friends), or the hardware (PPU). They exist to remove instructions from a hot path, not to add expressiveness.+* **Tier 4 - Acceleration** are instructions added primarily to speed up a specific consumer: the LLVM backend (''MOVSX''/''MOVZX'', indexed addressing), the Forth system (''LSTEP'' and friends), or the hardware (PPU/ASU). They exist to remove instructions from a hot path, not to add expressiveness.
  
 A handful of opcodes carry aliases (e.g. ''JC''/''JAE'', ''BC''/''BAE'', ''CMPC''/''CMPC3''); both names assemble to the same byte. A handful of opcodes carry aliases (e.g. ''JC''/''JAE'', ''BC''/''BAE'', ''CMPC''/''CMPC3''); both names assemble to the same byte.
  
-//Removed since the previous revision: CASE3 (201), CASEB, PAB, UAB. These slots are no longer emitted and should not be relied upon.//+//Deprecated since the previous revision: CASE3, CASEB, PAB, UABand conditional JMPR.//
  
 === Tier 1: Core (RISC) === Tier 1: Core (RISC)
Line 27: Line 27:
 | 7   | $07  | [[#ld|ST_REG]]   | STA [X]       | Store register to memory (register pointer)  |         | | 7   | $07  | [[#ld|ST_REG]]   | STA [X]       | Store register to memory (register pointer)  |         |
 | 9   | $09  | [[#mov|MOV]]     | MOV Y, A      | Copy register to register (//same width//          | | 9   | $09  | [[#mov|MOV]]     | MOV Y, A      | Copy register to register (//same width//          |
-| 11  | $0B  | PUSH     | PUSH A        | Push register onto stack                             | +| 11  | $0B  | [[#PUSH]]     | PUSH A        | Push register onto stack                             | 
-| 12  | $0C  | POP      | POP Y         | Pop stack into register                      |         | +| 12  | $0C  | [[#POP]]      | POP Y         | Pop stack into register                      |         | 
-| 15  | $0F  | PUSHF    | PUSHF         | Push flags                                           | +| 15  | $0F  | [[#PUSHF]]    | PUSHF         | Push flags                                           | 
-| 16  | $10  | POPF     | POPF          | Pop flags                                    | *       | +| 16  | $10  | [[#POPF]]     | POPF          | Pop flags                                    | *       | 
-| 23  | $17  | INC      | INC X         | Increment register by 1 (any width)          |         | +| 23  | $17  | [[#INC]]      | INC X         | Increment register by 1 (any width)          |         | 
-| 24  | $18  | DEC      | DEC Y         | Decrement register by 1 (any width)          |         | +| 24  | $18  | [[#DEC]]      | DEC Y         | Decrement register by 1 (any width)          |         | 
-| 30  | $1E  | ADD      | ADD X, Y      | X = X + Y                                             | +| 30  | $1E  | [[#ADD]]      | ADD X, Y      | X = X + Y                                             | 
-| 31  | $1F  | SUB      | SUB X, Y      | X = X - Y                                             | +| 31  | $1F  | [[#SUB]]      | SUB X, Y      | X = X - Y                                             | 
-| 50  | $32  | AND      | AND dst, src  | Bitwise AND                                  |         | +| 50  | $32  | [[#AND]]      | AND dst, src  | Bitwise AND                                  |         | 
-| 51  | $33  | OR       | OR dst, src   | Bitwise OR                                           | +| 51  | $33  | [[#OR]]       | OR dst, src   | Bitwise OR                                           | 
-| 52  | $34  | XOR      | XOR dst, src  | Bitwise XOR                                  |         | +| 52  | $34  | [[#XOR]]      | XOR dst, src  | Bitwise XOR                                  |         | 
-| 53  | $35  | NOT      | NOT reg       | Bitwise NOT (invert all bits)                |         | +| 53  | $35  | [[#NOT]]      | NOT reg       | Bitwise NOT (invert all bits)                |         | 
-| 70  | $46  | SHL      | SHL A         | Shift left                                   | Z N C   | +| 70  | $46  | [[#SHL]]      | SHL A         | Shift left                                   | Z N C   | 
-| 71  | $47  | SHR      | SHR A         | Shift right                                  | Z N C   | +| 71  | $47  | [[#SHR]]      | SHR A         | Shift right                                  | Z N C   | 
-| 90  | $5A  | CMP      | CMP A, B      | Compare (subtract, discard result)           | Z N C V | +| 90  | $5A  | [[#CMP]]      | CMP A, B      | Compare (subtract, discard result)           | Z N C V | 
-| 91  | $5B  | CMP_IMM  | CMP A, $1     | Compare against immediate                    | Z N C V | +| 91  | $5B  | [[#CMP_IMM]]  | CMP A, $1     | Compare against immediate                    | Z N C V | 
-| 100 | $64  | JMP      | JMP @label    | Unconditional jump                                   | +| 100 | $64  | [[#JMP]]      | JMP @label    | Unconditional jump                                   | 
-| 101 | $65  | JZ       | JZ @label     | Jump if zero                                         | +| 101 | $65  | [[#JZ]]       | JZ @label     | Jump if zero                                         | 
-| 102 | $66  | JNZ      | JNZ @label    | Jump if not zero                                     | +| 102 | $66  | [[#JNZ]]      | JNZ @label    | Jump if not zero                                     | 
-| 105 | $69  | JC       | JC @label     | Jump if carry set (alias //JAE//           |         | +| 105 | $69  | [[#JC]]       | JC @label     | Jump if carry set (alias //JAE//           |         | 
-| 106 | $6A  | JNC      | JNC @label    | Jump if carry clear (alias //JNAE//                |+| 106 | $6A  | [[#JNC]]      | JNC @label    | Jump if carry clear (alias //JNAE//                |
 | 130 | $82  | [[#call|CALL]]   | CALL @label   | Call subroutine (push IP, jump)              |         | | 130 | $82  | [[#call|CALL]]   | CALL @label   | Call subroutine (push IP, jump)              |         |
-| 133 | $85  | RET      | RET           | Return from subroutine (pop IP)              |         | +| 133 | $85  | [[#RET]]      | RET           | Return from subroutine (pop IP)              |         | 
-| 134 | $86  | INT      | INT $10       | Software interrupt                                   | +| 134 | $86  | [[#INT]]      | INT $10       | Software interrupt                                   | 
-| 135 | $87  | RTI      | RTI           | Return from interrupt                        | *       | +| 135 | $87  | [[#RTI]]      | RTI           | Return from interrupt                        | *       | 
-| 182 | $B6  | SETF     | SETF $80      | Set bits in the flags register               | *       | +| 182 | $B6  | [[#SETF]]     | SETF $80      | Set bits in the flags register               | *       | 
-| 183 | $B7  | CLRF     | CLRF $80      | Clear bits in the flags register             | *       | +| 183 | $B7  | [[#CLRF]]     | CLRF $80      | Clear bits in the flags register             | *       | 
-| 184 | $B8  | TESTF    | TESTF $80     | Non-destructive AND against flags            | Z C     | +| 184 | $B8  | [[#TESTF]]    | TESTF $80     | Non-destructive AND against flags            | Z C     | 
-| 254 | $FE  | NOP      | NOP           | No operation                                         | +| 254 | $FE  | [[#NOP]]      | NOP           | No operation                                         | 
-| 255 | $FF  | HALT     | HALT          | Halt CPU (sets HALT flag)                    |         |+| 255 | $FF  | [[#HALT]]     | HALT          | Halt CPU (sets HALT flag)                    |         | 
 + 
 +Although this is intended as a RISC core, there are some extras here, primarily LD-8bit hot path, which is done to speed up execution of 8 bit loads by about 30%. Additionally, INC, DEC and CALL/RET are semi-RISC because you can ADD reg, #1 or PUSH ptr0 and JMP (then POP IP to return). INT and RTI are suspect here, as well as CMP_IMM (you can just load into a register and use register compare). But these instructions are so common that it is difficult to justify not including them. The core set is intended to be minimalist, but not obtusely so. 
 + 
 +POPF however, is a strong canidate for removal. It would really only be needed for a kind of protected mode, interrupt mode or kernal mode, and we dont use it currently. 
 + 
 +Finally, it may be interesting to fuse CMP and JZ. Imagine, any CMP and conditional jump could be a CJMP. ex. ''CJZ A, B, address'' -- if they're equal, then we jump. One instruction. We save a dispatch and a byte. 
 + 
 +Consider: 
 +* No CMP exists in isolation 
 +* No JZ exists without responding to a change in the Z flag. 
 +* CJZ A, A can test for zero after a load if we really need one. 
 + 
 +Further investigate: 
 +* Does the cost of flag calculation outweight dispatch for how often a CMP occurrs?
  
 === Tier 2: Extended (Quality of Life) === Tier 2: Extended (Quality of Life)
Line 164: Line 178:
  
 === Tier 4: Acceleration (LLVM / Forth / Hardware) === Tier 4: Acceleration (LLVM / Forth / Hardware)
-Instructions added to remove work from a specific hot path rather than to add +Instructions added to remove work from a specific hot path rather than to add expressiveness. Each one has a primary consumer noted below. 
-expressiveness. Each one has a primary consumer noted below.+ 
 +Canidates for inclusion: LEA, fused CMP-Bcc and CMP-Jcc, conditional move, LD_IDX16
  
 | #   | hex  | Mnemonic | Example          | Description                                  | Consumer | Flags | | #   | hex  | Mnemonic | Example          | Description                                  | Consumer | Flags |
Line 196: Line 211:
 from the tables above. from the tables above.
  
-<wrap #ld /> +<wrap #ld_imm /> 
-**''LD_IMM / LD_MEM / LD_REG / LD_IMM8 / LD_MEM8 / LD_REG8 / ST_MEM / ST_REG''**\\ The core load/store set. Word loads come in three addressing modes -- immediate (''$5''), absolute (''[$5]''), and register-pointer (''[X]'') -- and the ''*8'' variants are their byte-width counterpartsStores provide absolute and register-pointer formsWider-than-16-bit memory access uses 24-bit pointer registers (the paired registers such as BLX/ELMas the pointer operand; there is no separate "24-bit load" opcodeFor indexed access with a displacement, see the acceleration-tier [[#idx|indexed loads and stores]].+**''#0 $00 LD_IMM''**\\ 
 +Load register with an immediate value. ''A = $5'' (16/24/32-bit depending on register width)
 + 
 +<wrap #ld_mem /> 
 +**''#1 $01 LD_MEM''**\\ 
 +Load register from memory (absolute address). ''A = [$5]''
 + 
 +<wrap #ld_reg /> 
 +**''#2 $02 LD_REG''**\\ 
 +Load register from memory (register-indirect pointer). ''A = [X]''
 + 
 +<wrap #ld_imm8 /> 
 +**''#3 $03 LD_IMM8''**\\ 
 +Load byte register with an immediate value''AL = $5''
 + 
 +<wrap #ld_mem8 /> 
 +**''#4 $04 LD_MEM8''**\\ 
 +Load byte from memory (absolute). ''AL = [$5]''
 + 
 +<wrap #ld_reg8 /> 
 +**''#5 $05 LD_REG8''**\\ 
 +Load byte from memory (register-indirect)''AL = [X]''
 + 
 +<wrap #st_mem /> 
 +**''#6 $06 ST_MEM''**\\ 
 +Store register to memory (absolute). ''[$10] = A''
 + 
 +<wrap #st_reg /> 
 +**''#7 $07 ST_REG''**\\ 
 +Store register to memory (register-indirect). ''[X= A''.
  
 <wrap #mov /> <wrap #mov />
 **''#9 $09 MOV dst, src''**\\ **''#9 $09 MOV dst, src''**\\
-Register-to-register copy. **MOV requires source and destination of equal width**; +Register-to-register copy ex. ''Y = A''. **MOV requires source and destination of equal width**; this is enforced at assemble time. A move that changes width is not a MOV -- use [[#movx|MOVSX/MOVZX]] to widen. The assembler rejects a mismatched-width MOV rather than guessing which bytes you meant. Mismatched MOV is undefined at execution time.
-this is enforced at assemble time. A move that changes width is not a MOV -- use +
-[[#movx|MOVSX/MOVZX]] to widen. The assembler rejects a mismatched-width MOV rather +
-than guessing which bytes you meant.+
  
-<wrap #call /> +<wrap #push /> 
-**''#130 $82 CALL addr / CALL reg / #131 $83 CALLR reg''**\\ +**''#11 $0B PUSH''**\\ 
-CALL pushes the return address (the instruction after the call) and jumps to the +Push register onto stack. ''SP -= width; [SP] = A''
-target. CALLR takes a register operand and dispatches on its width16-bit and + 
-8-bit registers combine with the current bank, 24-bit registers give a full +<wrap #pop /
-address, and a 32-bit pair (e.gAB) is narrowed to 24 bits by discarding the high +**''#12 $0C POP''**\\ 
-byteThis makes 32-bit register pairs usable as function pointers.+Pop stack into register. ''Y = [SP]; SP += width''
 + 
 +<wrap #pushf /> 
 +**''#15 $0F PUSHF''**\\ 
 +Push flags register onto stack. 
 + 
 +<wrap #popf /> 
 +**''#16 $10 POPF''**\\ 
 +Pop stack into flags register. * 
 + 
 +<wrap #inc /> 
 +**''#23 $17 INC''**\\ 
 +Increment register by 1 (any width)''X += 1''Sets Z/N flags. 
 + 
 +<wrap #dec /> 
 +**''#24 $18 DEC''**\\ 
 +Decrement register by 1 (any width)''-= 1''. Sets Z/N flags.
  
 <wrap #step /> <wrap #step />
Line 220: Line 277:
 pointer (''LDA [BLX, +]''), and ST_FS stores then advances. These collapse the pointer (''LDA [BLX, +]''), and ST_FS stores then advances. These collapse the
 pointer bookkeeping of a copy loop into the access itself. pointer bookkeeping of a copy loop into the access itself.
 +
 +<wrap #mov-x />
 +**''#28 $1C MOVSX dst, src / #29 $1D MOVZX dst, src''**\\
 +Move with sign-extend (MOVSX) or zero-extend (MOVZX). The source is read at its own
 +width and written across the full destination, with the high bytes filled from the
 +source's sign bit (MOVSX) or with zero (MOVZX). The destination **must be strictly
 +wider** than the source; this is checked at assemble time. Both fully define the
 +destination, so unlike a byte ALU op there is no partial-register hazard, and the
 +in-place overlapping case (''MOVSX A, AL'') is well defined.
 +
 +These exist to collapse the compiler's extend sequence: without a native
 +sign-extend, widening a signed ''char'' to ''int'' took three ops
 +(''AND''/''XOR''/''SUB'' implementing the ''(x ^ 0x80) - 0x80'' identity). MOVSX does
 +it in one. Integer promotion makes signed widening pervasive in C, so this is a
 +recurring code-size win. MOVZX similarly drops the masking immediate of an
 +''AND $FF'' style zero-extend.
 +
 +<wrap #add />
 +**''#30 $1E ADD''**\\
 +Add registers. ''X = X + Y''. Updates Z N C V.
 +
 +<wrap #sub />
 +**''#31 $1F SUB''**\\
 +Subtract registers. ''X = X - Y''. Updates Z N C V.
 +
 +<wrap #and />
 +**''#50 $32 AND''**\\
 +Bitwise AND. ''dst = dst & src''. Updates Z N.
 +
 +<wrap #or />
 +**''#51 $33 OR''**\\
 +Bitwise OR. ''dst = dst | src''. Updates Z N.
 +
 +<wrap #xor />
 +**''#52 $34 XOR''**\\
 +Bitwise XOR. ''dst = dst ^ src''. Updates Z N.
 +
 +<wrap #not />
 +**''#53 $35 NOT''**\\
 +Bitwise NOT (invert all bits). ''reg = ~reg''. Updates Z N.
 +
 +<wrap #shl />
 +**''#70 $46 SHL''**\\
 +Shift left. ''A <<= count''. Updates Z N C.
 +
 +<wrap #shr />
 +**''#71 $47 SHR''**\\
 +Shift right (logical). ''A >>= count''. Updates Z N C.
  
 <wrap #shx /> <wrap #shx />
Line 227: Line 332:
 the current emulator handler before relying on this entry.// the current emulator handler before relying on this entry.//
  
-<wrap #branch /> +<wrap #cmp /> 
-**''#120-#129 Branches (BZ, BNZ, BC, BNC, BA, BNA, BG, BGE, BL, BLE)''**\\ +**''#90 $64 CMP''**\\ 
-Two-byte relative branches with a signed 8-bit displacement (range -128..+127 from +Compare registers (subtract, discard result). ''tmp = A B''Updates Z N C V.
-the instruction). They mirror the absolute jumps but encode shorter and stay +
-position-independent, so they are preferred for tight local loopsBC/BAE and +
-BNC/BNAE are aliases. For targets outside +/-127, use the absolute jumps.+
  
-<wrap #setflag /> +<wrap #cmp_imm /> 
-**''#160 SEZ / #161 SEN / #162 SEC / #163 SEV''**\\ +**''#91 $5B CMP_IMM''**\\ 
-Set the zero, negative, carry, and overflow flags respectivelyUseful when you are +Compare register against immediate. ''tmp = A - $1''. Updates Z N C V.
-certain no intervening operation disturbs the flag -- for example, carry survives +
-POP and MOV, so it is a common error/clear channel out of a routine (''JC @error'').+
  
-<wrap #see /> +<wrap #jmp /> 
-**''#164 $A4 SEE''**\\ Set the Exception flag. Used by some interrupts and the +**''#100 $64 JMP''**\\ 
-system to signal an error, but free for your own use otherwiseThink of it as an +Unconditional jump''IP = @label''.
-"Extra" flag.+
  
-<wrap #sef /> +<wrap #jz /> 
-**''#165 $A5 SEF''**\\ Set the F ("free"flag. Used for "first-statement" in BASIC; +**''#101 $65 JZ''**\\ 
-otherwise safe for machine-language use.+Jump if zero. ''if (ZIP = @label''.
  
-<wrap #seb /> +<wrap #jnz /> 
-**''#166 $A6 SEB''**\\ Set the B ("bonus"flag. Used for BREAK in BASIC; otherwise +**''#102 $66 JNZ''**\\ 
-safe for machine-language use.+Jump if not zero. ''if (!ZIP = @label''.
  
-<wrap #seu /> +<wrap #jc /> 
-**''#167 $A7 SEU''**\\ Set the User flag. Not used by the system; reserved for the +**''#105 $69 JC''**\\ 
-programmer.+Jump if carry set (alias JAE for unsigned {{{>=)}}}. ''if (C) IP = @label''.
  
-<wrap #sed /> +<wrap #jnc /> 
-**''#168 $A8 SED''**\\ Set Debug. Emits trace messages while on; slows the system +**''#106 $6A JNC''**\\ 
-considerablyTrace output may be compiled out in some builds.+Jump if carry clear (alias JNAE for unsigned <)''if (!C) IP = @label''.
  
-<wrap #sei /> +<wrap #call /> 
-**''#169 $A9 SEI''**\\ Enable/disable interruptsWith interrupts offINT will not +**''#130 $82 CALL addr / CALL reg / #131 $83 CALLR reg''**\\ 
-fire.+CALL pushes the return address (the instruction after the call) and jumps to the 
 +targetCALLR takes a register operand and dispatches on its width: 16-bit and 
 +8-bit registers combine with the current bank24-bit registers give a full 
 +address, and a 32-bit pair (e.g. AB) is narrowed to 24 bits by discarding the high 
 +byte. This makes 32-bit register pairs usable as function pointers.
  
-<wrap #ssi /> +<wrap #branch /> 
-**''#170 $AA SSI''**\\ Set the Sound Interrupt flagManaged by the KERNAL; +**''#120-#129 Branches (BZ, BNZ, BC, BNC, BA, BNA, BG, BGE, BL, BLE)''**\\ 
-semi-reserved and may be removed.+Two-byte relative branches with a signed 8-bit displacement (range -128..+127 from 
 +the instruction)They mirror the absolute jumps but encode shorter and stay 
 +position-independent, so they are preferred for tight local loops. BC/BAE and 
 +BNC/BNAE are aliases. For targets outside +/-127, use the absolute jumps.
  
 <wrap #memcopy /> <wrap #memcopy />
Line 283: Line 389:
 <wrap #cmpc /> <wrap #cmpc />
 **''#142 $8E CMPC ELM, FLD, C''** (alias //CMPC3//)\\ **''#142 $8E CMPC ELM, FLD, C''** (alias //CMPC3//)\\
-Non-zero byte compare, useful for strings. Compares up to C characters; C returns +Non-zero byte compare, useful for strings. Compares up to C characters; C returns either the index of the first mismatch or the matched length. Sets ZERO on a full match; otherwise CARRY distinguishes the -1 / +1 ordering.
-either the index of the first mismatch or the matched length. Sets ZERO on a full +
-match; otherwise CARRY distinguishes the -1 / +1 ordering.+
  
-CMPC allows early termination when ''byte_a == 0'' -- the C-string "begins with" +CMPC allows early termination when ''byte_a == 0'' -- the C-string "begins with" semantics. If both strings reach a terminator at the same position with all prior bytes equal, the loop exits matched (Z=1, C=1). Only ''byte_a'' is tested because by that point ''byte_a == byte_b'' is already proven, so ''byte_a == 0'' implies ''byte_b == 0''. This lets CMPC do double duty: fixed-length compare and null-terminated strcmp in one instruction.
-semantics. If both strings reach a terminator at the same position with all prior +
-bytes equal, the loop exits matched (Z=1, C=1). Only ''byte_a'' is tested because by +
-that point ''byte_a == byte_b`` is already proven, so ''byte_a == 0'' implies +
-''byte_b == 0''. This lets CMPC do double duty: fixed-length compare and +
-null-terminated strcmp in one instruction.+
  
 <wrap #skpc /> <wrap #skpc />
Line 324: Line 423:
 you write CRUD for a struct); the register form exists so generic kernel queue you write CRUD for a struct); the register form exists so generic kernel queue
 helpers can take "field offset" as a parameter. helpers can take "field offset" as a parameter.
 +
 +<wrap #setflag />
 +**''#160 SEZ / #161 SEN / #162 SEC / #163 SEV''**\\
 +Set the zero, negative, carry, and overflow flags respectively. Useful when you are
 +certain no intervening operation disturbs the flag -- for example, carry survives
 +POP and MOV, so it is a common error/clear channel out of a routine (''JC @error'').
 +
 +<wrap #see />
 +**''#164 $A4 SEE''**\\ Set the Exception flag. Used by some interrupts and the
 +system to signal an error, but free for your own use otherwise. Think of it as an
 +"Extra" flag.
 +
 +<wrap #sef />
 +**''#165 $A5 SEF''**\\ Set the F ("free") flag. Used for "first-statement" in BASIC;
 +otherwise safe for machine-language use.
 +
 +<wrap #seb />
 +**''#166 $A6 SEB''**\\ Set the B ("bonus") flag. Used for BREAK in BASIC; otherwise
 +safe for machine-language use.
 +
 +<wrap #seu />
 +**''#167 $A7 SEU''**\\ Set the User flag. Not used by the system; reserved for the
 +programmer.
 +
 +<wrap #sed />
 +**''#168 $A8 SED''**\\ Set Debug. Emits trace messages while on; slows the system
 +considerably. Trace output may be compiled out in some builds.
 +
 +<wrap #sei />
 +**''#169 $A9 SEI''**\\ Enable/disable interrupts. With interrupts off, INT will not
 +fire.
 +
 +<wrap #ssi />
 +**''#170 $AA SSI''**\\ Set the Sound Interrupt flag. Managed by the KERNAL;
 +semi-reserved and may be removed.
  
 <wrap #case /> <wrap #case />
Line 353: Line 487:
 <wrap #casetab /> <wrap #casetab />
 **''#202 $CA CASETAB base, selector, #limit''**\\ **''#202 $CA CASETAB base, selector, #limit''**\\
-Jump table held at a base address rather than inline. Indexes an address from the +Jump table held at a base address rather than inline. Indexes an address from the table at ''base'' by ''selector'', bounded by ''limit'', and dispatches to it.
-table at ''base'' by ''selector'', bounded by ''limit'', and dispatches to it. +
-//The precise indexing and out-of-bounds policy should be confirmed against the +
-current emulator handler: the older CASE3 (computed table at base) and CASEB +
-(scanned ''[selector][addr]'' table) were removed, and CASETAB is the surviving +
-table-at-base form.//+
  
 <wrap #cvtan /> <wrap #cvtan />
 **''#203 $CB CVTAN reg8''**\\ **''#203 $CB CVTAN reg8''**\\
-Convert ASCII to number. Maps '0'-'Z' to 0-35. Sets Overflow if the character is not +Convert ASCII to number. Maps '0'-'Z' to 0-35. Sets Overflow if the character is not a decimal digit (0-9) and Carry if it is not a hex digit (0-15). Also a fast digit test: ''MOV reg8, AL'' then ''CVTAN reg8'' lets you branch with JO/JNO (JV/JNV). Designed for zoned decimal, and works for zoned hex.
-a decimal digit (0-9) and Carry if it is not a hex digit (0-15). Also a fast digit +
-test: ''MOV reg8, AL'' then ''CVTAN reg8'' lets you branch with JO/JNO (JV/JNV). +
-Designed for zoned decimal, and works for zoned hex.+
  
 <wrap #cvtna /> <wrap #cvtna />
Line 371: Line 497:
 Convert number to ASCII, the inverse of CVTAN. Maps 0-35 to '0'-'Z'. Sets Overflow Convert number to ASCII, the inverse of CVTAN. Maps 0-35 to '0'-'Z'. Sets Overflow
 if outside 0-9 and Carry if outside 0-15. if outside 0-9 and Carry if outside 0-15.
- 
-<wrap #movx /> 
-**''#28 $1C MOVSX dst, src / #29 $1D MOVZX dst, src''**\\ 
-Move with sign-extend (MOVSX) or zero-extend (MOVZX). The source is read at its own 
-width and written across the full destination, with the high bytes filled from the 
-source's sign bit (MOVSX) or with zero (MOVZX). The destination **must be strictly 
-wider** than the source; this is checked at assemble time. Both fully define the 
-destination, so unlike a byte ALU op there is no partial-register hazard, and the 
-in-place overlapping case (''MOVSX A, AL'') is well defined. 
- 
-These exist to collapse the compiler's extend sequence: without a native 
-sign-extend, widening a signed ''char'' to ''int'' took three ops 
-(''AND''/''XOR''/''SUB'' implementing the ''(x ^ 0x80) - 0x80'' identity). MOVSX does 
-it in one. Integer promotion makes signed widening pervasive in C, so this is a 
-recurring code-size win. MOVZX similarly drops the masking immediate of an 
-''AND $FF'' style zero-extend. 
  
 <wrap #idx /> <wrap #idx />
-**''#210 LD_IDXI / #211 LD_IDXR / #212 ST_IDXI / #213 ST_IDXR''**\\ +**''#210 LD_IDXI / #211 LD_IDXR / #212 ST_IDXI / #213 ST_IDXR''**\\ Indexed load/store: a 24-bit pointer register plus a displacement. The ''I'' forms take a signed byte immediate (-128..+127); the ''R'' forms take a register offset. These back the compiler's frame-slot and struct-field access (''[ptr + disp]''). The pointer base must be a 24-bit register; the effective address reads the base at its
-Indexed load/store: a 24-bit pointer register plus a displacement. The ''I'' forms +
-take a signed byte immediate (-128..+127); the ''R'' forms take a register offset. +
-These back the compiler's frame-slot and struct-field access (''[ptr + disp]''). The +
-pointer base must be a 24-bit register; the effective address reads the base at its+
 true width before applying the offset. true width before applying the offset.
  
Line 410: Line 516:
 in memory: in memory:
  
-<code+<codify armasm
-    LDFLX $F000       ; loop start +    LDFLX $F000       ; 8 byte loop data start 
-    LDA #1 +    LDA #1            ; start at 
-    STA [FLX] +    STA [FLX]         ; write starting counter at first four bytes 
-    LDA #1000 +    LDA #1000         ; go until 1000 
-    STA [FLX+4]+    STA [FLX+4]       ; write finish (until) counter at second four bytes
 loop: loop:
-    <body> +    LSTEPM            ; INC N1, if N1==N2 set Z=1
-    LSTEPM+
     JNZ @loop     JNZ @loop
-</code>+</codify> 
 + 
 +Unlike a DEC loop it counts upward and supports an arbitrary start. The generalized form of this is [[#lstep|LSTEP]] which counts downwards instead.
  
-Unlike a DEC loop it counts upward and supports an arbitrary start. It is a kludge +Only used by Forth. It is recommended to use LSTEP insteadthis instruction is a canidate for removal.
-for Forth and has been generalized by [[#lstep|LSTEP]]once Forth uses LSTEP, +
-LSTEPM is a candidate for removal.+
  
 <wrap #ttos /> <wrap #ttos />
Line 440: Line 545:
 inspired by the VAX SOB (subtract one and branch) and the 68000 DBcc. inspired by the VAX SOB (subtract one and branch) and the 68000 DBcc.
  
-<code>+<codify armasm>
     LDC #1000       ; loop range     LDC #1000       ; loop range
 loop: loop:
-    <body> 
     LSTEP C, @loop     LSTEP C, @loop
-</code>+</codify>
sd/isa.1781596407.txt.gz · Last modified: by appledog

Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki