Registers { a | Accumulator | 8-bit | Main working register x/y | Index registers | 8-bit | Generally used for array access ya | y << 8 OR a | 16-bit | Concatenation of y and a sp | Stack pointer | 8-bit | Index added to $0100. Gives the location of the first free byte on the stack. Decrements when pushed to, increments when pulled from pc | Program counter | 16-bit | The address of the next instruction to execute psw | Processor status word | 8-bit | Contains some flags concerning the CPU state: { 1 | c: Carry flag | See adc/sbc/cmp/asl/lsr/rol/ror/daa/das and *1 instructions 2 | z: Zero flag | Set if the result of an operation is zero 8 | h: Half-carry flag | See adc/sbc/daa/das/div 20h | p: Direct page location | p * 100h used as direct page base address 40h | v: Overflow flag | See adc/sbc/div 80h | n: Negative flag | Set if the result of an operation is negative (most significant bit is set) } } Let DP = psw.p * 100h be the direct page base address. mov { Move a value to/from a register Loads set PSR.Z and PSR.N according to the value loaded (except mov sp,x) Stores don't affect PSR 7D | mov a,x | a = x 5D | mov x,a | x = a DD | mov a,y | a = y FD | mov y,a | y = a 9D | mov x,sp | x = sp BD | mov sp,x | sp = x FA ss dd | mov (dd),(ss) | dd + DP = [ss + DP] E8 nn | mov a,#nn | a = nn CD nn | mov x,#nn | x = nn 8D nn | mov y,#nn | y = nn 8F nn dd | mov dd,#nn | dd + DP = nn E5 ssss | mov a,ssss | a = [ssss] E9 ssss | mov x,ssss | x = [ssss] EC ssss | mov y,ssss | y = [ssss] E4 ss | mov a,ss | a = [ss + DP] F8 ss | mov x,ss | x = [ss + DP] EB ss | mov y,ss | y = [ss + DP] C5 dddd | mov dddd,a | dddd = a C9 dddd | mov dddd,x | dddd = x CC dddd | mov dddd,y | dddd = y C4 dd | mov dd,a | dd + DP = a D8 dd | mov dd,x | dd + DP = x CB dd | mov dd,y | dd + DP = y F5 ssss | mov a,ssss+x | a = [ssss + x] F6 ssss | mov a,ssss+y | a = [ssss + y] F4 ss | mov a,ss+x | a = [ss + DP + x] F9 ss | mov x,ss+y | x = [ss + DP + y] FB ss | mov y,ss+x | y = [ss + DP + x] D5 dddd | mov dddd+x,a | dddd + x = a D6 dddd | mov dddd+y,a | dddd + y = a D4 dd | mov dd+x,a | dd + DP + x = a DB dd | mov dd+x,y | dd + DP + x = y D9 dd | mov dd+y,x | dd + DP + y = x E6 | mov a,(x) | a = [ss + DP] where ss = [x + DP] BF | mov a,(x)+ | a = [ss + DP] where ss = [x + DP], x += 1 C6 | mov (x),a | ss + DP = a where ss = [x + DP] AF | mov (x)+,a | ss + DP = a where ss = [x + DP], x += 1 F7 ss | mov a,(ss)+y | a = [tttt + y] where tttt = [ss + DP] D7 dd | mov (dd)+y,a | tttt + y = a where tttt = [dd + DP] E7 ss | mov a,(ss+x) | a = [tttt] where tttt = [ss + DP + x] C7 dd | mov (dd+x),a | tttt = a where tttt = [dd + DP + x] } cmp { Compare with memory Sets psw.z/psw.n/psw.c flags according to the result of subtraction Unlike sbc, this operation isn't affected by psw.c and doesn't set psw.v Let lhs and rhs be the left and right side operands: psw.z is set if lhs - rhs = 0 psw.n is set if 80h <= lhs - rhs <= FFh psw.c is set if subtraction doesn't exceed the range of unsigned numbers, i.e. unsigned(lhs) - unsigned(rhs) >= 0 (like ARM and unlike x86/z80) Thus: If lhs = rhs, then psw.z = 1 If unsigned(lhs) >= unsigned(rhs), then psw.c = 1 If signed(lhs) >= signed(rhs), then psw.n = 0 (assuming no overflow) 69 dd ss | cmp (dd),(ss) | [dd + DP] - [ss + DP] 68 nn | cmp a,#nn | a - nn C8 nn | cmp x,#nn | x - nn AD nn | cmp y,#nn | y - nn 78 nn dd | cmp dd,#nn | [dd + DP] - nn 65 ssss | cmp a,ssss | a - [ssss] 1E ssss | cmp x,ssss | x - [ssss] 5E ssss | cmp y,ssss | y - [ssss] 64 ss | cmp a,ss | a - [ss + DP] 3E ss | cmp x,ss | x - [ss + DP] 7E ss | cmp y,ss | y - [ss + DP] 75 ssss | cmp a,ssss+x | a - [ssss + x] 76 ssss | cmp a,ssss+y | a - [ssss + y] 74 ss | cmp a,ss+x | a - [ss + DP + x] 66 | cmp a,(x) | a - [ss + DP] where ss = [x + DP] 79 | cmp (x),(y) | [dd + DP] - [ss + DP] where dd = [x + DP], ss = [y + DP] 77 ss | cmp a,(ss)+y | a - [tttt + y] where tttt = [ss + DP] 67 ss | cmp a,(ss+x) | a - [tttt] where tttt = [ss + DP + x] } adc/sbc/and/or/eor { adc: Add with carry sbc: Subtract with carry and: Bitwise AND or: Bitwise OR eor: Bitwise XOR adc/sbc notes { Let lhs and rhs be the left and right side operands: sbc sets the carry/overflow flags as: psw.c is set if subtraction doesn't exceed the range of unsigned numbers (like 65816/ARM and unlike x86/z80), i.e. unsigned(lhs) - unsigned(rhs) + psw.c - 1 >= 0 psw.v is set if subtraction exceeds the range of signed numbers, i.e. not 80h <= signed(lhs) - signed(rhs) + psw.c - 1 <= 7Fh adc sets the carry/overflow flags as: psw.c is set if addition exceeds the range of unsigned numbers, i.e. unsigned(lhs) + unsigned(rhs) + psw.c > FFh psw.v is set if addition exceeds the range of signed numbers, i.e. not 80h <= signed(lhs) + signed(rhs) + psw.c <= 7Fh psw.h set whenever adc/sbc causes a carry to be propagated from the low nybble to the high nybble, i.e. for adc: (lhs & Fh) + (rhs & Fh) + psw.c > Fh for sbc: (lhs & Fh) - (rhs & Fh) + psw.c - 1 < 0 The reason adc/sbc involves the carry is for multiprecision variables. E.g.: Suppose: $01 contains an 8-bit position $00 contains an 8-bit subpixel position (where there are 100h subpixels per pixel) $11 contains an 8-bit speed $10 contains an 8-bit subpixel speed Then to add the speed to the position, one could do: clrc ; Clear the carry so that the first addition is correct adc $00,$10 ; Add the subpixel values, the carry is propagated to the next ADC adc $01,$11 ; Add the pixel values along with the carry To subtract the speed, one could do: setc sbc $00,$10 sbc $01,$11 } 89 dd ss | adc (dd),(ss) | dd + DP = [dd + DP] + [ss + DP] + psw.c A9 dd ss | sbc (dd),(ss) | dd + DP = [dd + DP] - [ss + DP] + psw.c - 1 29 dd ss | and (dd),(ss) | dd + DP = [dd + DP] AND [ss + DP] 09 dd ss | or (dd),(ss) | dd + DP = [dd + DP] OR [ss + DP] 49 dd ss | eor (dd),(ss) | dd + DP = [dd + DP] XOR [ss + DP] 88 nn | adc a,#nn | a = a + nn + psw.c A8 nn | sbc a,#nn | a = a - nn + psw.c - 1 28 nn | and a,#nn | a = a AND nn 08 nn | or a,#nn | a = a OR nn 48 nn | eor a,#nn | a = a XOR nn 98 nn dd | adc dd,#nn | dd + DP = [dd + DP] + nn + psw.c B8 nn dd | sbc dd,#nn | dd + DP = [dd + DP] - nn + psw.c - 1 38 nn dd | and dd,#nn | dd + DP = [dd + DP] AND nn 18 nn dd | or dd,#nn | dd + DP = [dd + DP] OR nn 58 nn dd | eor dd,#nn | dd + DP = [dd + DP] XOR nn 85 ssss | adc a,ssss | a = a + [ssss] + psw.c A5 ssss | sbc a,ssss | a = a - [ssss] + psw.c - 1 25 ssss | and a,ssss | a = a AND [ssss] 05 ssss | or a,ssss | a = a OR [ssss] 45 ssss | eor a,ssss | a = a XOR [ssss] 84 ss | adc a,ss | a = a + [ss + DP] + psw.c A4 ss | sbc a,ss | a = a - [ss + DP] + psw.c - 1 24 ss | and a,ss | a = a AND [ss + DP] 04 ss | or a,ss | a = a OR [ss + DP] 44 ss | eor a,ss | a = a XOR [ss + DP] 95 ssss | adc a,ssss+x | a = a + [ssss + x] + psw.c B5 ssss | sbc a,ssss+x | a = a - [ssss + x] + psw.c - 1 35 ssss | and a,ssss+x | a = a AND [ssss + x] 15 ssss | or a,ssss+x | a = a OR [ssss + x] 55 ssss | eor a,ssss+x | a = a XOR [ssss + x] 96 ssss | adc a,ssss+y | a = a + [ssss + y] + psw.c B6 ssss | sbc a,ssss+y | a = a - [ssss + y] + psw.c - 1 36 ssss | and a,ssss+y | a = a AND [ssss + y] 16 ssss | or a,ssss+y | a = a OR [ssss + y] 56 ssss | eor a,ssss+y | a = a XOR [ssss + y] 94 ss | adc a,ss+x | a = a + [ss + DP + x] + psw.c B4 ss | sbc a,ss+x | a = a - [ss + DP + x] + psw.c - 1 34 ss | and a,ss+x | a = a AND [ss + DP + x] 14 ss | or a,ss+x | a = a OR [ss + DP + x] 54 ss | eor a,ss+x | a = a XOR [ss + DP + x] 86 | adc a,(x) | a = a + [ss + DP] + psw.c where ss = [x + DP] A6 | sbc a,(x) | a = a - [ss + DP] + psw.c - 1 where ss = [x + DP] 26 | and a,(x) | a = a AND [ss + DP] where ss = [x + DP] 06 | or a,(x) | a = a OR [ss + DP] where ss = [x + DP] 46 | eor a,(x) | a = a XOR [ss + DP] where ss = [x + DP] 99 | adc (x),(y) | dd + DP = [dd + DP] + [ss + DP] + psw.c where dd = [x + DP], ss = [y + DP] B9 | sbc (x),(y) | dd + DP = [dd + DP] - [ss + DP] + psw.c - 1 where dd = [x + DP], ss = [y + DP] 39 | and (x),(y) | dd + DP = [dd + DP] AND [ss + DP] where dd = [x + DP], ss = [y + DP] 19 | or (x),(y) | dd + DP = [dd + DP] OR [ss + DP] where dd = [x + DP], ss = [y + DP] 59 | eor (x),(y) | dd + DP = [dd + DP] XOR [ss + DP] where dd = [x + DP], ss = [y + DP] 97 ss | adc a,(ss)+y | a = a + [tttt + y] + psw.c where tttt = [ss + DP] B7 ss | sbc a,(ss)+y | a = a - [tttt + y] + psw.c - 1 where tttt = [ss + DP] 37 ss | and a,(ss)+y | a = a AND [tttt + y] where tttt = [ss + DP] 17 ss | or a,(ss)+y | a = a OR [tttt + y] where tttt = [ss + DP] 57 ss | eor a,(ss)+y | a = a XOR [tttt + y] where tttt = [ss + DP] 87 ss | adc a,(ss+x) | a = a + [tttt] + psw.c where tttt = [ss + DP + x] A7 ss | sbc a,(ss+x) | a = a - [tttt] + psw.c - 1 where tttt = [ss + DP + x] 27 ss | and a,(ss+x) | a = a AND [tttt] where tttt = [ss + DP + x] 07 ss | or a,(ss+x) | a = a OR [tttt] where tttt = [ss + DP + x] 47 ss | eor a,(ss+x) | a = a XOR [tttt] where tttt = [ss + DP + x] } inc/dec / asl/lsr / rol/ror { inc: Increment dec: Decrement asl: (Arithmetic) shift left lsr: Logical shift right rol: Rotate left with carry ror: Rotate right with carry rol/ror are like asl/lsr instructions that operate on the 9-bit concatenation of a with psw.c, that is, the bit shifted out of a by rol/ror is shifted into psw.c, the old psw.c bit being shifted in to a The reason rol/ror exists is for multiprecision variables. E.g.: Suppose: $01 contains an 8-bit speed $00 contains an 8-bit subpixel speed (where there are 100h subpixels per pixel) Then to multiply the speed by 2, one would do asl $00 : rol $01 Or if dividing the speed by 2, one would do lsr $01 : ror $00 BC | inc a | a = a + 1 3D | inc x | x = x + 1 FC | inc y | y = y + 1 9C | dec a | a = a - 1 1D | dec x | x = x - 1 DC | dec y | y = y - 1 1C | asl a | a = a << 1 5C | lsr a | a = a >> 1 3C | rol a | a = a << 1, a.LSb = psw.c 7C | ror a | a = a >> 1, a.MSb = psw.c AC dddd | inc dddd | dddd = [dddd] + 1 8C dddd | dec dddd | dddd = [dddd] - 1 0C dddd | asl dddd | dddd = [dddd] << 1 4C dddd | lsr dddd | dddd = [dddd] >> 1 2C dddd | rol dddd | dddd = [dddd] << 1, a.LSb = psw.c 6C dddd | ror dddd | dddd = [dddd] >> 1, a.MSb = psw.c AB dd | inc dd | dd + DP = [dd + DP] + 1 8B dd | dec dd | dd + DP = [dd + DP] - 1 0B dd | asl dd | dd + DP = [dd + DP] << 1 4B dd | lsr dd | dd + DP = [dd + DP] >> 1 2B dd | rol dd | dd + DP = [dd + DP] << 1, a.LSb = psw.c 6B dd | ror dd | dd + DP = [dd + DP] >> 1, a.MSb = psw.c BB dd | inc dd+x | dd + DP + x = [dd + DP + x] + 1 9B dd | dec dd+x | dd + DP + x = [dd + DP + x] - 1 1B dd | asl dd+x | dd + DP + x = [dd + DP + x] << 1 5B dd | lsr dd+x | dd + DP + x = [dd + DP + x] >> 1 3B dd | rol dd+x | dd + DP + x = [dd + DP + x] << 1, a.LSb = psw.c 7B dd | ror dd+x | dd + DP + x = [dd + DP + x] >> 1, a.MSb = psw.c } movw / addw/subw/cmpw / incw/decw / mul/div { movw: Move word addw: Add word subw: Subtract word cmpw: Compare word incw: Increment word decw: Decrement word mul: Multiply (unsigned) div: Divide (unsigned) { movw/cmpw/incw/decw are straight-forward 16-bit extensions and set the psw flags in the same way Unlike adc/sbc, addw/subw aren't affected by psw.c (but still set psw.z/psw.n/psw.c/psw.v as expected) addw/subw set psw.h according to adc/sbc on the upper bytes of the operands (with the carry of the operation on the lower bytes) mul sets psw.z depending on y only (and sets psw.n as expected) div sets psw.v if ya / x >= 100h and sets psw.h if y & Fh >= x & Fh div sets psw.n and psw.z from the resulting quotient a div gives the expected results provided ya / x < 200h, equivalently y < x*2. Otherwise results are given by: a = FFh - (ya - x * 200h) / (100h - x) y = x + (ya - x * 200h) % (100h - x) } DA dd | movw dd,ya | dd + DP = ya BA ss | movw ya,ss | ya = [ss + DP] 7A ss | addw ya,ss | ya = ya + [ss + DP] 9A ss | subw ya,ss | ya = ya - [ss + DP] 5A ss | cmpw ya,ss | ya - [ss + DP] 3A dd | incw dd | dd + DP = [dd + DP] + 1 1A dd | decw dd | dd + DP = [dd + DP] - 1 CF | mul ya | ya = y * a 9E | div ya,x | a = ya / x, y = ya % x } clr*/set*/not1 / clrc/setc/notc / clrv / mov1 / and1/or1/eor1 { clr*: Clear bit set*: Set bit not1: Bitwise NOT 1 bit clrc: Clear carry setc: Set carry notc: Bitwise NOT carry clrv: Clear overflow (and half carry) mov1: Move 1 bit and1: Bitwise AND 1 bit or1: Bitwise OR 1 bit eor1: Bitwise XOR 1 bit No other psw flags are set than those explicitly described below The address range of not1/mov1/or1/and1/eor1 is 13 bits ($0000..1FFF) 12 dd | clr0 dd | dd + DP = [dd + DP] AND NOT 1 32 dd | clr1 dd | dd + DP = [dd + DP] AND NOT 2 52 dd | clr2 dd | dd + DP = [dd + DP] AND NOT 4 72 dd | clr3 dd | dd + DP = [dd + DP] AND NOT 8 92 dd | clr4 dd | dd + DP = [dd + DP] AND NOT 10h B2 dd | clr5 dd | dd + DP = [dd + DP] AND NOT 20h D2 dd | clr6 dd | dd + DP = [dd + DP] AND NOT 40h F2 dd | clr7 dd | dd + DP = [dd + DP] AND NOT 80h 02 dd | set0 dd | dd + DP = [dd + DP] OR 1 22 dd | set1 dd | dd + DP = [dd + DP] OR 2 42 dd | set2 dd | dd + DP = [dd + DP] OR 4 62 dd | set3 dd | dd + DP = [dd + DP] OR 8 82 dd | set4 dd | dd + DP = [dd + DP] OR 10h A2 dd | set5 dd | dd + DP = [dd + DP] OR 20h C2 dd | set6 dd | dd + DP = [dd + DP] OR 40h E2 dd | set7 dd | dd + DP = [dd + DP] OR 80h 60 | clrc | psw.c = 0 80 | setc | psw.c = 1 ED | notc | psw.c = psw.c ^ 1 E0 | clrv | psw.v = psw.h = 0 ; ssss/dddd = xxxx & 0x1FFF, b = xxxx >> Dh AA xxxx | mov1 c,ssss,b | psw.c = [ssss] >> b AND 1 0A xxxx | or1 c,ssss,b | psw.c = psw.c OR [ssss] >> b AND 1 2A xxxx | or1 c,!(ssss,b) | psw.c = psw.c OR NOT [ssss] >> b AND 1 4A xxxx | and1 c,ssss,b | psw.c = psw.c AND [ssss] >> b 6A xxxx | and1 c,!(ssss,b) | psw.c = psw.c AND NOT [ssss] >> b 8A xxxx | eor1 c,ssss,b | psw.c = psw.c XOR [ssss] >> b AND 1 EA bddd | not1 dddd,b | dddd = [dddd] XOR (1 << b) CA bddd | mov1 dddd,b,c | dddd = [dddd] AND NOT (1 << b) OR (psw.c << b) } xcn / tclr1/tset1 / daa/das { xcn: Exchange nybbles tclr1: Test and clear bits (not limited to one bit) tset1: Test and set bits (not limited to one bit) daa: Decimal adjust addition das: Decimal adjust subtraction xcn sets psw.n and psw.z according to result (as one would expect) tclr1/tset1 set psw.n and psw.z according to [dddd] - a (as if by cmp) before dddd is modified daa/das set psw.c as adc/sbc do, i.e. daa sets psw.c if BCD conversion propagates a carry das clears psw.c if BCD conversion requires a borrow daa/das notes { daa and das are instructions that correct the result of adc/sbc on two BCD values respectively. They cannot be used in any way to convert an arbitrary hexadecimal number to BCD. For daa: If psw.h is set, then the sum of the low nybbles that were added together by adc exceeded 10h, in this case, daa adds 6 to a to skip over the hexadecimal digits A-F, e.g. 19h + 19h sets a = 32h and psw.h = 1, daa then adds 6 to get 38h as expected If l >= Ah, then daa adds 6 to a (again, to skip over the hexadecimal digits A..F), e.g. 19h + 16h sets a = 2Fh and psw.h = 0, daa then adds 6 to get 35h as expected If psw.c is set, then the sum of the values that were added together by adc exceeded 100h in this case, daa adds 60h to a (to skip over the hexadecimal values A0h..FFh), e.g. 90h + 90h sets a = 20h and psw.c = 1, daa then adds 60h to get 80h (and psw.c = 1) as expected If a >= A0h, then daa adds 60h to a (to skip over the hexadecimal values A0h..FFh) and sets psw.c = 1 accordingly, e.g. 90h + 60h sets a = F0h and psw.c = 0, daa then adds 60h to get 50h and psw.c = 1 as expected Final example: 99h + 99h sets a = 32h, psw.h = psw.c = 1 daa adds 66h because both psw.h and psw.c are set Result is a = 98h with psw.c = 1 Usage for adding multiprecision variables: Suppose there is a 6 digit score that needs updating: $00..02 contains the 6-digit score in little endian (in BCD) $10..11 contains the 4-digit number of points to add (in BCD) Then to add the points to the score, one would do: clrc ; Clear the carry so that the first addition is correct mov a,$00 : adc a,$10 : daa : mov $00,a ; Add the least significant 2 digits, carry is propagated to next adc irrespective of whether it came from adc or daa mov a,$01 : adc a,$11 : daa : mov $01,a ; Add the middle 2 digits, "" mov a,$02 : adc a,#0 : daa : mov $02,a ; Propagate carry to most significant 2 digits das works the same way, except that the psw.c/psw.h have the inverted meanings and 6/60h is subtracted rather than added } 9F | xcn a | a = (a AND Fh) << 4 OR (a >> 4) 4E dddd | tclr1 dddd | dddd = [dddd] AND NOT a 0E dddd | tset1 dddd | dddd = [dddd] OR a DF | daa a | Converts the result of an adc of two BCD values to BCD BE | das a | Converts the result of an sbc of two BCD values to BCD } bra/bcc/bcs/bne/beq/bpl/bmi/bvc/bvs / bbs*/bbc* / cbne / dbnz { bra: Branch bcc: Branch if carry clear bcs: Branch if carry set bne: Branch if not equal beq: Branch if equal bpl: Branch if plus bmi: Branch if minus bvc: Branch if overflow clear bvs: Branch if overflow set bbc*: Branch if bit clear bbs*: Branch if bit set cbne: Compare and branch if not equal dbnz: Decrement and branch if not zero No psw flags are set (even cbne/dbnz) Note that bne/beq can be misleading names, especially after AND. In practice, they're more like bzc/bzs 2F oo | bra oo | pc = pc + signed(oo) 90 oo | bcc oo | pc = pc + signed(oo) if psw.c = 0 B0 oo | bcs oo | pc = pc + signed(oo) if psw.c = 1 D0 oo | bne oo | pc = pc + signed(oo) if psw.z = 0 F0 oo | beq oo | pc = pc + signed(oo) if psw.z = 1 10 oo | bpl oo | pc = pc + signed(oo) if psw.n = 0 30 oo | bmi oo | pc = pc + signed(oo) if psw.n = 1 50 oo | bvc oo | pc = pc + signed(oo) if psw.v = 0 70 oo | bvs oo | pc = pc + signed(oo) if psw.v = 1 13 ss oo | bbc0 ss,oo | pc = pc + signed(oo) if [ss + DP] AND 1 = 0 33 ss oo | bbc1 ss,oo | pc = pc + signed(oo) if [ss + DP] AND 2 = 0 53 ss oo | bbc2 ss,oo | pc = pc + signed(oo) if [ss + DP] AND 4 = 0 73 ss oo | bbc3 ss,oo | pc = pc + signed(oo) if [ss + DP] AND 8 = 0 93 ss oo | bbc4 ss,oo | pc = pc + signed(oo) if [ss + DP] AND 10h = 0 B3 ss oo | bbc5 ss,oo | pc = pc + signed(oo) if [ss + DP] AND 20h = 0 D3 ss oo | bbc6 ss,oo | pc = pc + signed(oo) if [ss + DP] AND 40h = 0 F3 ss oo | bbc7 ss,oo | pc = pc + signed(oo) if [ss + DP] AND 80h = 0 03 ss oo | bbs0 ss,oo | pc = pc + signed(oo) if [ss + DP] AND 1 != 0 23 ss oo | bbs1 ss,oo | pc = pc + signed(oo) if [ss + DP] AND 2 != 0 43 ss oo | bbs2 ss,oo | pc = pc + signed(oo) if [ss + DP] AND 4 != 0 63 ss oo | bbs3 ss,oo | pc = pc + signed(oo) if [ss + DP] AND 8 != 0 83 ss oo | bbs4 ss,oo | pc = pc + signed(oo) if [ss + DP] AND 10h != 0 A3 ss oo | bbs5 ss,oo | pc = pc + signed(oo) if [ss + DP] AND 20h != 0 C3 ss oo | bbs6 ss,oo | pc = pc + signed(oo) if [ss + DP] AND 40h != 0 E3 ss oo | bbs7 ss,oo | pc = pc + signed(oo) if [ss + DP] AND 80h != 0 2E ss oo | cbne ss,oo | pc = pc + signed(oo) if a != [ss + DP] DE ss oo | cbne ss+x,oo | pc = pc + signed(oo) if a != [ss + DP + x] FE oo | dbnz y,oo | y = y - 1, pc = pc + signed(oo) if y != 0 6E dd oo | dbnz dd,oo | dd + DP = [dd + DP] - 1, pc = pc + signed(oo) if y != 0 } jmp/call / tcall/pcall/brk / ret/reti { jmp: Jump call: Call tcall: Table call pcall: Uppermost page call brk: Breakpoint interrupt ret: Return reti: Return from interrupt No psw flags are set (except reti) 5F dddd | jmp dddd | pc = dddd 1F dddd | jmp (dddd+x) | pc = [dddd + x] 3F dddd | call dddd | Push pc, pc = dddd n1 | tcall n | Push pc, pc = [$FFDE - n * 2] 4F dd | pcall dd | Push pc, pc = $FF00 + dd 0F | brk | Push pc, push psw, pc = [$FFDE] 6F | ret | Pull to pc 7F | reti | Pull to psw, pull to pc } push/pop { Push to stack / pop to registers No psw flags are set (except pop psw) Pushing register r onto the stack means: [sp] = r sp -= 1 Conversely, pulling to r from the stack means: sp += 1 [sp] = r 2D | push a | Push a AE | pop a | Pop to a 4D | push x | Push x CE | pop x | Pop to x 6D | push y | Push y EE | pop y | Pop to y 0D | push psw | Push psw 8E | pop psw | Pop to psw } sleep/stop / clrp/setp / di/ei / nop { EF | sleep | Sleep until interrupt occurs (interrupts cannot occur) FF | stop | Kill CPU 20 | clrp | psw.p = 0 40 | setp | psw.p = 1 C0 | di | psw.i = 0 (interrupt flag not doc'd here) A0 | ei | psw.i = 1 (interrupt flag not doc'd here) 00 | nop | Nothing }