debugger should have commands to allow register display/update
via use of SDOS/rt primitives; likewise, a way to select a
task for "debugging" would be very useful. then debugging over
a network would be possible!
         page        List Instruction in symbolic format
ListInstruction ; List instruction in memory location (X)
         jsr         FetchInstruction get the instruction (max of 5 bytes)
         jsr         ComputeEffectiveAddress decide if it is legal
         bne         ListInstruction1 b/ sure is
         jsr         PrintInLineCharacter illegal instruction!
         fcb         '?             print as ?xx
         inc         InstructionLength so caller knows how to get past "opcode"
         lda         InstructionOpcode get so-called opcode byte
         bra         PrintHexByte   and print it

ListInstruction1 ; Instruction to be list IS legal, print symbolic form
         lda         InstructionOpcode fetch instruction opcode
         ldb         InstructionPrefix see if pre-fixed instruction
         beq         ListInstructionNoPrefix b/ no prefix
         cmpb        #$11           $11 prefix ?
         beq         ListInstructionPrefix$11 b/ yep
ListInstructionPrefix$10 ; Instruction has prefix byte of $10
         tsta                       opcode >= $80 ?
         bmi         ListInstructionPrefix$108x b/ yes, not relative branch
         ldx         #TextSWI2      assume SWI2 opcode
         cmpa        #$3F           SWI2 ?
         beq         List4CharactersatX b/ yes, just list it and leave!
         ldb         #7             = size of long relative branch name slots
         mul                        = offset to name of long relative branch
         ldx         #TextLBRN-$20*7 = base of long relative branch name table
         leax        d,x            = pointer to 4 character long branch name
         bra         ListOpcodethenOperand go list opcode name, and target addr

ListInstructionPrefix$108x ; not LBR-- or SWI2
         anda        #%10011111     mask off address mode bits
         ldx         #TextCMPD      CMPD ?
         cmpa        #$83           ...?
         beq         ListOpcodethenAddressMode b/ yes
         ldx         #TextCMPY      CMPY ?
         cmpa        #$8C           ...?
         beq         ListOpcodethenAddressMode b/ yes
         ldx         #TextLDY       LDY ?
         cmpa        #$8E           ...?
         beq         ListOpcodethenAddressMode b/ yes
         ldx         #TextSTY       STY ?
         cmpa        #$8F           ...?
         beq         ListOpcodethenAddressMode b/ yes
         ldx         #TextLDS       LDS ?
         cmpa        #$CE           ...?
         beq         ListOpcodethenAddressMode b/ yes
         ldx         #TextSTS       STS ?
*        cmpa        #$CF           ...?
ListOpcodethenOperand ; (X) points to 4 character opcode name
         bsr         List4CharactersAtX output opcode name
         cmpx        #TextANDCC+4    special case: ANDCC being listed ?
         bne         ListOperand     b/ no
         jsr         PrintInLineCharacter yes, output extra 'C
         fcb         'c
ListOperand ; list operand of instruction
         bsr         PrintBlank     output a blank
         ldb         InstructionType branch on operand type
         aslb                       convert to word index
         ldx         #ListOperandTable and branch on it
         jmp         [b,x]
         page
ListOperandTable ; Branch table used to pass control to operand list routines
         #DebuggerFault             IAT:Illegal
         #ListInstructionDone       IAT:Inherent
         #ListDirectPage            IAT:2DirectPage
         #ListExtended              IAT:3Extended
         #ListIndexPostByte         IAT:LEAx
         #DebuggerFault             <not defined>
         #List8Immediate            IAT:2Immediate
         #List16Immediate           IAT:3Immediate
         #ListIndexPostByte         IAT:2Indexed8
         #ListIndexPostByte         IAT:3Indexed16
         #ListShortRelative         IAT:2ShortRelative
         #ListLongRelative          IAT:3LongRelative
         #ListPushPullPostbyte      IAT:2PushPull
         #ListCCImmPostByte         IAT:2CCImm
         #ListTRFEXGPostByte        IAT:2TFREXG

List4CharactersAtX ; (X) points to 4 character opcode name
         bsr         ListCharacterAtX list 1st character
List3CharactersAtX ; (X) points to 3 character opcode name
         bsr         ListCharacterAtX list 2nd character
         bsr         ListCharacterAtX list 3rd character
*        bsr         ListCharacterAtX list 4th character
*        rts                        ListCharacteratX must follow
ListCharacteratX ; Print character that X points at, advance X
         lda         ,x+            fetch the character
         cmpa        #$20           a printing character ?
         bhs         ListCharacteratX1 b/ yes, just print it
         dex                        no, back up X to point to terminator
         lda         #$20           and print a blank instead
         pshx                       save updated (X)
         jsr         PrintCharacter output the character
         pulx                       restore pointer to next character
         rts

ListInstructionPrefix$11 ; instruction has $11 prefix
         ldx         #TextSWI3      assume SWI3 opcode
         cmpa        #$3F           SWI3 ?
         beq         List4CharactersAtX b/ yes, list name and exit
         anda        #%10011111     drop address mode bits
         ldx         #TextCMPU      assume CMPU opcode
         cmpa        #$83           CMPU ?
         beq         ListOpcodethenOperand b/ yes
         ldx         #TextCMPS      must be CMPS!
         bra         ListOpcodethenOperand

ListInstructionNoPrefix ; instruction has no prefix byte
         tsta                       arithmetic class instruction ?
         bmi         ListInstructionArithmetic b/ yes
         cmpa        #$60           Monadic indexed/extended ?
         bhs         ListInstructionMonadic b/ yes
         cmpa        #$40           monadic to register ?
         bhs         ListMonadictoRegister b/ yes
         ldb         #6             opcode < $40, get size of Opcode table slot
         mul                        compute displacement for opcode name
         ldx         #TextNEG       = base of opcodes
         leax        d,x            (X) points to opcode name
         bra         ListOpcodethenOperand go output opcode followed by operand

ListInstructionMonadic ; monadic indexed or extended to memory
         ldb         #ascii:blank   get register name to display after opcode
         bra         ListInstructionMonadic1

ListMonadictoRegister ; instruction specifies a register
         tab                        compute register name to print after opcode
         lsrb                       shift register selector bit to LSB
         lsrb
         lsrb
         lsrb                       register selector bit now in LSB
         addb        #'a            register selector = 0 --> A, else B
ListInstructionMonadic1 ; (B) contains name of register to print after opcode
         pshb                       save register name to print after opcode
         anda        #%00001111     extract monadic sub-opcode
         ldb         #6             = size of opcode name slots in OpcodeTable
         mul                        = offset to desired name in Opcode Table
         ldx         #TextNeg       = address of NEG opcode name
         leax        d,x            = pointer to monadic opcode name
         bsr         List3CharactersAtX print monadic opcode name
         pula                       = name of register on which opcode operates
         jsr         PrintCharacter output register name
         bra         ListInstructionOperand go output address mode stuff

ListInstructionArithmetic ; seems to be arithmetic instruction
         ldx         #TextBSR       Assume BSR instruction
         cmpa        #$8D           BSR ?
         beq         ListOpcodethenOperand b/ yes, go handle
         tab                        compute pointer to name in OpcodeTable
         andb        #%00001111     = lower 4 bits...
         anda        #%01000000     and the bit differentiating A vs B register
         lsra                       combine to make code in range 0 to 31
         lsra
         aba                        = slot number after TextSUBA
         ldb         #6             = size of slots in Opcode table
         mul                        (D) holds offset to name in Opcode table
         ldx         #TextSUBA      = address of text for $80 opcode
         leax        d,x            = address of text for specified opcode
         bra         ListOpcodethenOperand go list opcode, then address mode
         page
TFREXGpostbytedecode
*        Transfer/Exchange postbyte format: s s s s d d d d
*        where ssss is the source register,
*        and dddd is the target register, as given by the following table:
*        d d d d
*        s s s s
*        0 0 0 0     D register
*        0 0 0 1     X register
*        0 0 1 0     Y register
*        0 0 1 1     U register
*        0 1 0 0     S register
*        0 1 0 1     PC register
*        0 1 1 0     Illegal
*        0 1 1 1     Illegal
*        1 0 0 0     A register
*        1 0 0 1     B register
*        1 0 1 0     CCR register
*        1 0 1 1     DPR register
*        1 1 0 0     Illegal
*        1 1 0 1     Illegal
*        1 1 1 0     Illegal
*        1 1 1 1     Illegal
         fcc         "dxyusp??abcz"
*
ListTFREXGPostByte ; list post-byte of TFR/EXG instruction
         lda         InstructionPostByte need more be said?
         lsra                       extract "from" register
         lsra
         lsra
         lsra
         ldx         #TFREXGpostbytedecode get corresponding character
         lda         a,x
         lbsr        PrintCharacter    output character
         lbsr        PrintInLineCharacter
         fcb         ',
         lda         InstructionPostByte
         anda        #$F            extract "to" register
         ldx         #TFREXGpostbytedecode get corresponding character
         lda         a,x
ListLastRegisterName ; come here to list final register name
         lbrs        PrintCharacter    output name of "to" register
         rts
         page
ListPUSHPULLPostByte ; list post-byte of PUSH/PULL instruction
         ldx         #PUSHPULLpostbytedecode set up to output list of registers
         ldb         InstructionPostByte assert: this byte is non-zero!
ListPUSHPULLPostByteLoop ; see if next bit specifies a register to be pushed
         lda         ,x+            fetch name of register for next bit
         rolb                       output name of this register ?
         bcc         ListPUSHPULLPostByteLoop b/ nope
         beq         ListLastRegisterName b/ this is final register name !
         pshs        x,b            save rest of register bits and scan pointer
         lbsr        PrintCharacter    output register name
         lbsr        PrintInLineCharacter output seperator comma
         fcc         ","
         puls        x,b            restore register bits and scan pointer
         bra         ListPUSHPULLPostByteLoop

PUSHPULLpostbytedecode ; Lookup table to decode push/pull post byte
         fcc         "puyxzbac"     P is bit 7, C is bit 0 of postbyte
         page
ListDirectPageOperand ; list direct page operand
         clra                       move "page zero" address to D
         ldb         InstructionAddress
         ldx         #0             set lower acceptable delta
         leay        1,x            set upper acceptable delta
         bra         ListValue

ListShortRelative ; list target of short relative branch
ListLongRelative ; list target of long relative branch
ListExtendedOperand ; list extended address mode operand
         ldd         EffectiveAddress fetch value to be printed
ListWordOperand ; list word value in (D)
         ldx         #-15           set lower acceptable delta
         ldy         #15            set upper acceptable delta
         bra         ListValue

ListCCImm ; list operand of 8 bit CC immediate class instruction
List8bitImmediate ; list 8 bit immediate operand
         lbsr        PrintInLineCharacter output "immediate" mark
         fcb         '#
         clra                       compute value to display
         ldb         InstructionPostByte
         ldx         #0             set lower acceptable delta
         leay        0,x            set upper acceptable delta
         bra         ListValue

List16bitImmediate ; list 16 bit immediate operand
         lbsr        PrintInLineCharacter output "immediate" mark
         fcb         '#
         ldd         InstructionAddress fetch value to display
         bra         ListWordOperand
         page
*     Index PostByte decoding
*     Postbyte format: a r r i t t t t
*     rr = 0 --> X register
*     rr = 1 --> Y register
*     rr = 2 --> U register
*     rr = 3 --> S register
*     where a = 0 <--> rr is register name, itttt is 5 bit offset
*     a = 1 means that i=0 --> not indirect, i=1 --> indirect
*     and the 4 t bits are interpreted as follows:
*        t t t t
*        0 0 0 0     ,r+    (i=0 --> illegal)
*        0 0 0 1     ,r++
*        0 0 1 0     ,-r    (i=0 --> illegal)
*        0 0 1 1     ,--r
*        0 1 0 0     ,r     (zero offset)
*        0 1 0 1     B,r    (ACCB offset)
*        0 1 1 0     A,r    (ACCA offset)
*        0 1 1 1     ????   (illegal)
*        1 0 0 0     d,r    (where d is 8 bit offset following postbyte)
*        1 0 0 1     d,r    (where d is 16 bit offset following postbyte)
*        1 0 1 0     ????   (illegal)
*        1 0 1 1     D,r    (ACCD offset)
*        1 1 0 0     d,PCR  (d is 8 bit offset; rr is ignored)
*        1 1 0 1     d,PCR  (d is 16 bit offset; rr is ignored)
*        1 1 1 0     ????   (illegal)
*        1 1 1 1     [addr] (i=0 --> illegal; rr<>0 is illegal)
*
ListIndexPostByte ; list symbolic form of index post byte
         lda         InstructionPostbyte fetch postbyte (assert: legal!)
         bita        #%00010000     indirect ?
         beq         ListIndexPostByte1 b/ no
         lbsr        PrintInLineCharacter yes, print opening [
         fcb         '[
ListIndexPostByte1 ; output displacement specified by index post-byte
         ldb         InstructionPostByte fetch postbyte, branch on index type
         bpl         ListEFA4bitoffset b/ 4 bit offset type
         andb        #%00001111     extract index displacement type
         rolb                       convert to word offset
         ldx         #ListIndexPostByteDecode branch on lower 4 bits of postbyte
         jsr         [b,y]
ListIndexPostByteFinish ; complete display of index post-byte
         lda         InstructionPostbyte fetch postbyte (assert: legal!)
         bita        #%00010000     indirect ?
         beq         ListIndexPostByteDone b/ no
         lbsr        PrintInLineCharacter yes, print opening [
         fcb         '[
ListIndexPostByteDone ; index post-byte completely displayed
         rts

ListIndexPostByteDecode ; branch table used to decode bottom 4 bits of postbyte
         #ListAutoInc               %00000000 ,r+
         #ListDblInc                %00000001 ,r++
         #ListPreDec                %00000010 ,-r
         #ListDblDec                %00000011 ,--r
         #ListZeroOffset            %00000100 ,r
         #ListOffsetbyA             %00000101 A,r
         #ListOffsetbyB             %00000110 B,r
         #DebuggerFault             %00000111 Illegal index mode
         #List8bitOffset            %00001000 <8bitoffset>,r
         #List16bitOffset           %00001001 <16bitoffset>,r
         #DebuggerFault             %00001010 Illegal index mode
         #ListOffsetbyD             %00001011 D,r
         #List8bitPCR               %00001100 <8bitoffset>,PCR
         #List16bitPCR              %00001101 <16bitoffset>,PCR
         #DebuggerFault             %00001110 Illegal index mode
         #ListExtendedIndirect      %00001111 [address]
         page
ListOffsetbyA ; List Offset by A mode post byte
         lda         #'a            get offset register name
         bra         ListOffsetbyRegister and go handle

ListOffsetbyB ; List Offset by B mode post byte
         lda         #'b            get offset register name
         bra         ListOffsetbyRegister and go handle

ListOffsetbyD ; List Offset by D mode post byte
         lda         #'d            get offset register name
ListOffsetbyRegister ; (A) contains name of register offset
         lbsr        PrintCharacter output offset register name
ListZeroOffset ; List Zero offset mode post byte
ListIndexRegister ; output ',r' with r being proper index register name
         lbsr        PrintInLineCharacter output the comma
         fcb         ',
ListIndexRegisterName ; output 'r' with r being proper index register name
         lda         InstructionPostByte fetch bits containing idx reg spec
         rola                       shift into bits 1 and 0
         rola
         rola
         rola
         anda        #%00000011     mask off other index mode bits
         ldx         #ListIndexRegisterDecode
         lda         a,x            fetch name of index register
         lbra        PrintCharacter and output it

ListIndexRegisterDecode ; Lookup table to convert index spec to index reg name
         fcc         "xyus"
ListAutoInc ; List auto-inc mode post-byte
         bsr         ListIndexRegister display ',r' with r being index reg name
ListAutoInc1 ; entry point for ListDblInc
         lbsr        PrintInLineCharacter add trailing '+'
         fcb         '+
         rts

ListDblInc ; List Double auto-inc mode post byte
         bsr         ListAutoInc    output ",r+"
         bra         ListAutoInc1   output 2nd trailing '+'

ListPreDec ; List pre-decrement mode post byte
         lbsr        PrintInLineCharacter output requisite comma
         fcb         ',
         lbsr        PrintInLineCharacter then the '-'
         fcb         '-
         bra         ListIndexRegisterName go output the name

ListDblDec ; List Double pre-decrement mode post byte
         lbsr        PrintInLineCharacter output requisite comma
         fcb         ',
         lbsr        PrintInLineCharacter now output '--'
         fcb         '-
         lbsr        PrintInLineCharacter
         fcb         '-
         bra         ListIndexRegisterName go output the name

List4bitOffset ; List Offset by 4 bit displacement mode post byte
         andb        #%00001111     mask off bits not related to displacement
         bitb        #%00001000     negative displacement ?
         beq         List4bitOffset1 b/ no
         orb         #%11110000     yes, sign extend to fill byte
List4bitOffset1 ; (B) contains 8 bit signed displacement
         bsr         List8bitOffset1 go display offset value
         bra         ListIndexPostbyteFinish and clean up!

List8bitOffset ; List Offset by 8 bit displacement mode post byte
         ldb         InstructionPostByte+1 fetch 8 bit offset byte
List8bitOffset1 ; entry point for List4bitOffset
         sex                        convert to 16 bit offset
         ldx         #-2            lower delta bound
         ldy         4,x            upper delta bound
List8bitoffset2
         bsr         ListValue      output index offset value
         bra         ListIndexRegister followed by ',r'

List16bitOffset ; List offset by 16 bit displacement mode post byte
         ldd         InstructionPostByte+1 fetch 16 bit displacement
         ldx         #-15           = lower delta bound
         ldy         #15            = upper delta bound
         bra         List8bitOffset2 go display offset

List8bitPCR ; List offset by 8 bit PC relative mode post byte
         ldb         InstructionPostByte+1 fetch 8 bit displacement
         sex                        convert to 16 bits
         bra         List16bitPCR1  and go process

List16bitPCR ; List offset by 16 bit PC relative mode post byte
         ldd         InstructionPostByte+1 fetch 16 bit displacement
         addd        InstructionAddress add address of instruction
         addb        InstructionLength and size of instruction
         adca        #0             = location referenced by PCR mode
         ldx         #-15           = acceptable lower delta bound
         ldy         #15            = acceptable upper delta bound
         bsr         ListValue      go output symbol address referenced
         lbsr        PrintInLineCharacter output ','
         fcb         ',
         lbsr        PrintInLineCharacter output pcr spec
         fcb         'p
         lbsr        PrintInLineCharacter
         fcb         'c
         lbsr        PrintInLineCharacter
         fcb         'r
         rts

ListExtendedIndirect ; List extended indirect mode post byte
         ldd         InstructionPostByte+1 fetch 16 bit displacement
         ldx         #-15           = lower delta bound
         ldy         #15            = upper delta bound
         bra         ListValue      list value
         page
ListValue ; List Symbolic version of value in (D)
*        (X) contains lower acceptable bound (as delta) on matching symbol value
*        (Y) contains upper acceptable bound (as delta) on matching symbol value
*        Searches symbol table for symbol whose value is closest to (D)
*        (ties broken in favor of symbols with values larger than (D)).
*        If no symbol found, or value of found symbol is outside of
*        range specified by ((X)..(Y)), then hex value of (D) is printed.
*        Otherwise, the sequence "symbol+delta" is printed, where
*        "symbol" is the name of the found symbol, "+" is "+" if
*        value of found symbol is greater than (D), "-" is less than;
*        and delta is the absolute value of the distance between the value
*        of the found symbol and the argument (D).  If this distance is
*        zero (i.e., symbol has exactly the correct value), then "+delta"
*        is not printed.
         pshs        d,x,y          save value bounds
         jsr         IDB:FindSymbolValue make symbol table routines do the work
         bcs         ListValueAsHex b/ cannot find any symbol
*        (D) contains actual symbol value; (X) points to symbol
         subd        0,s            compute delta from desired value
         cmpd        2,s            is delta within acceptable range ?
         blt         ListValueAsHex b/ no
         cmpd        4,s            ...?
         bgt         ListValueAsHex b/ no
ListValueasSymbol ; must print "symbol+delta"
         std         0,s            save delta as value to print
         jsr         IDB:PrintSymbolValue output the symbol name
         ldd         0,s            fetch delta again
         bne         ListValueAsDelta b/ non-zero, must list delta value
         leas        6,x            pop d,x,y from stack
         rts                        done!

ListValueasDelta ; must print delta value
         rola                       compute sign to print: "+" or "-"
         rola                       move sign bit of delta to bit 1 of (A)
         rola
         anda        #%00000010     mask off other trash
         adda        #'+            now (A)="+" if positive, "-" if negative
         jsr         PrintChar      output the sign character
ListValueAsHex ; print value in (D)
         puls        d,x,y          fetch value to print, pop range limits
         bra         PrintHex
         page
CCRFORMAT ; Lookup table to decode display of CC bits
         fcc         "efhinzvc"     in msb to lsb order

DisplayCCR ; Display CCR contents in people-readable format
         lda         UserRegisterCC get ccr bits
         ldx         #CCRFORMAT     = address of characters matching bits
         ldb         #8             number of bits to display
DisplayCCRloop ; Display bit of CCR
         asla                       examine next bit
         bcs         DisplayCCRbit  b/ bit is set
         pshs        x,b,a          save pointer, count and remaining CC bits
         lda         #ascii:blank   display a blank for that bit
         bra         DisplayCCR1    go display the character

DisplayCCRbit ; CCR bit is one, display corresponding character
         pshs        x,b,a          save pointer, count and remaining CC bits
         lda         ,x             fetch corresponding character
DisplayCCR1
         lbsr        PrintCharacter send character to operator
         puls        x,b,a          get all the good stuff back
         inx                        advance pointer to next bit
         decb                       more bits to display?
         bne         DisplayCCRloop b/ yep.
         ...
         page
*
*        Instruction Address Type Table
*        Used by ComputeEffectiveAddress to determine instruction Address Type
*        Indexed by Opcode; every nibble represents one (unprefixed) opcode
*        Lower two bits of nibble normally contain instruction length
*        Entire 4 bit code determines actual instruction length and mode

IAT:Illegal equ      0         This opcode is outright illegal
IAT:1Inherent equ    1         This instruction occupies 1 byte
IAT:2DirectPage equ  2         Instruction is 2 bytes, direct page ref
IAT:3Extended equ    3         Instruction is 3 byte, extended ref
IAT:2LEAx equ        4         Instruction is >=2 bytes, LEAx class
IAT:2Immediate equ   6         Instruction is 2 bytes, 8 bit immediate operand
IAT:3Immediate equ   7         Instruction is 3 bytes, 16 bit immediate operand
IAT:2Indexed8 equ    $8        Instruction is >=2 byte indexed, 8 bit operand
IAT:2Indexed16 equ   $9        Instruction is >=2 byte indexed, 16 bit operand
IAT:2ShortRelative equ $A      Instruction is 2 bytes, short relative
IAT:3LongRelative equ $B       Instruction is 3 bytes, long relative
IAT:2PushPull equ    $C        Instruction is 2 bytes, Push/Pull
IAT:2CCImm equ       $D        Instruction is 2 bytes, CC immediate
IAT:2TFREXG equ      $E        Instruction is 2 bytes, TFR or EXG

InstructionAddressTypes ; 1 nibble per opcode, MSB nibble for even opcode
    IAT:2DirectPage*16+IAT:Illegal     $00,$01
    IAT:Illegal*16+IAT:2DirectPage     $02,$03
    IAT:2DirectPage*16+IAT:Illegal     $04,$05
    IAT:2DirectPage*16+IAT:2DirectPage $06,$07
    IAT:2DirectPage*16+IAT:2DirectPage $08,$09
    IAT:2DirectPage*16+IAT:Illegal     $0A,$0B
    IAT:2DirectPage*16+IAT:2DirectPage $0C,$0D
    IAT:2DirectPage*16+IAT:2DirectPage $0E,$0F

    IAT:Illegal*16+IAT:Illegal         $10,$11
    IAT:1Inherent*16+IAT:1Inherent     $12,$13
    IAT:Illegal*16+IAT:Illegal         $14,$15
    IAT:3LongRelative*16+IAT:3LongRelative $16,$17
    IAT:Illegal*16+IAT:1Inherent       $18,$19
    IAT:2CCImm*16+IAT:Illegal          $1A,$1B
    IAT:2CCImm*16+IAT:1Inherent        $1C,$1D
    IAT:2TFREXG*16+IAT:2TFREXG         $1E,$1F
         page
    IAT:2ShortRelative*16+IAT:2ShortRelative $20,$21
    IAT:2ShortRelative*16+IAT:2ShortRelative $22,$23
    IAT:2ShortRelative*16+IAT:2ShortRelative $24,$25
    IAT:2ShortRelative*16+IAT:2ShortRelative $26,$27
    IAT:2ShortRelative*16+IAT:2ShortRelative $28,$29
    IAT:2ShortRelative*16+IAT:2ShortRelative $2A,$2B
    IAT:2ShortRelative*16+IAT:2ShortRelative $2C,$2D
    IAT:2ShortRelative*16+IAT:2ShortRelative $2E,$2F

    IAT:2LEAx*16+IAT:2LEAx             $30,$31
    IAT:2LEAx*16+IAT:2LEAx             $32,$33
    IAT:2PushPull*16+IAT:2PushPull     $34,$35
    IAT:2PushPull*16+IAT:2PushPull     $36,$37
    IAT:Illegal*16+IAT:1Inherent       $38,$39
    IAT:1Inherent*16+IAT:1Inherent     $3A,$3B
    IAT:2CCImm*16+IAT:1Inherent        $3C,$3D
    IAT:Illegal*16+IAT:1Inherent       $3E,$3F

    IAT:1Inherent*16+IAT:Illegal       $40,$41
    IAT:Illegal*16+IAT:1Inherent       $42,$43
    IAT:1Inherent*16+IAT:Illegal       $44,$45
    IAT:1Inherent*16+IAT:1Inherent     $46,$47
    IAT:1Inherent*16+IAT:1Inherent     $48,$49
    IAT:1Inherent*16+IAT:Illegal       $4A,$4B
    IAT:1Inherent*16+IAT:1Inherent     $4C,$4D
    IAT:Illegal*16+IAT:1Inherent       $4E,$4F

    IAT:1Inherent*16+IAT:Illegal       $50,$51
    IAT:Illegal*16+IAT:1Inherent       $52,$53
    IAT:1Inherent*16+IAT:Illegal       $54,$55
    IAT:1Inherent*16+IAT:1Inherent     $56,$57
    IAT:1Inherent*16+IAT:1Inherent     $58,$59
    IAT:1Inherent*16+IAT:Illegal       $5A,$5B
    IAT:1Inherent*16+IAT:1Inherent     $5C,$5D
    IAT:Illegal*16+IAT:1Inherent       $5E,$5F
         page
    IAT:2Indexed8*16+IAT:Illegal       $60,$61
    IAT:Illegal*16+IAT:2Indexed8       $62,$63
    IAT:2Indexed8*16+IAT:Illegal       $64,$65
    IAT:2Indexed8*16+IAT:2Indexed8     $66,$67
    IAT:2Indexed8*16+IAT:2Indexed8     $68,$69
    IAT:2Indexed8*16+IAT:Illegal       $6A,$6B
    IAT:2Indexed8*16+IAT:2Indexed8     $6C,$6D
    IAT:2Indexed16*16+IAT:2Indexed8    $6E,$6F

    IAT:3Extended*16+IAT:Illegal       $70,$71
    IAT:Illegal*16+IAT:3Extended       $72,$73
    IAT:3Extended*16+IAT:Illegal       $74,$75
    IAT:3Extended*16+IAT:3Extended     $76,$77
    IAT:3Extended*16+IAT:3Extended     $78,$79
    IAT:3Extended*16+IAT:Illegal       $7A,$7B
    IAT:3Extended*16+IAT:3Extended     $7C,$7D
    IAT:3Extended*16+IAT:3Extended     $7E,$7F
         page
    IAT:2Immediate*16+IAT:2Immediate   $80,$81
    IAT:2Immediate*16+IAT:3Immediate   $82,$83
    IAT:2Immediate*16+IAT:2Immediate   $84,$85
    IAT:2Immediate*16+IAT:Illegal      $86,$87
    IAT:2Immediate*16+IAT:2Immediate   $88,$89
    IAT:2Immediate*16+IAT:2Immediate   $8A,$8B
    IAT:3Immediate*16+IAT:2ShortRelative $8C,$8D
    IAT:3Immediate*16+IAT:Illegal      $8E,$8F

    IAT:2DirectPage*16+IAT:2DirectPage $90,$91
    IAT:2DirectPage*16+IAT:2DirectPage $92,$93
    IAT:2DirectPage*16+IAT:2DirectPage $94,$95
    IAT:2DirectPage*16+IAT:2DirectPage $96,$97
    IAT:2DirectPage*16+IAT:2DirectPage $98,$99
    IAT:2DirectPage*16+IAT:2DirectPage $9A,$9B
    IAT:2DirectPage*16+IAT:2DirectPage $9C,$9D
    IAT:2DirectPage*16+IAT:2DirectPage $9E,$9F

    IAT:2Indexed8*16+IAT:2Indexed8     $A0,$A1
    IAT:2Indexed8*16+IAT:2Indexed16    $A2,$A3
    IAT:2Indexed8*16+IAT:2Indexed8     $A4,$A5
    IAT:2Indexed8*16+IAT:2Indexed8     $A6,$A7
    IAT:2Indexed8*16+IAT:2Indexed8     $A8,$A9
    IAT:2Indexed8*16+IAT:2Indexed8     $AA,$AB
    IAT:2Indexed16*16+IAT:2Indexed16   $AC,$AD
    IAT:2Indexed16*16+IAT:2Indexed16   $AE,$AF

    IAT:3Extended*16+IAT:3Extended     $B0,$B1
    IAT:3Extended*16+IAT:3Extended     $B2,$B3
    IAT:3Extended*16+IAT:3Extended     $B4,$B5
    IAT:3Extended*16+IAT:3Extended     $B6,$B7
    IAT:3Extended*16+IAT:3Extended     $B8,$B9
    IAT:3Extended*16+IAT:3Extended     $BA,$BB
    IAT:3Extended*16+IAT:3Extended     $BC,$BD
    IAT:3Extended*16+IAT:3Extended     $BE,$BF
         page
    IAT:2Immediate*16+IAT:2Immediate   $C0,$C1
    IAT:2Immediate*16+IAT:3Immediate   $C2,$C3
    IAT:2Immediate*16+IAT:2Immediate   $C4,$C5
    IAT:2Immediate*16+IAT:Illegal      $C6,$C7
    IAT:2Immediate*16+IAT:2Immediate   $C8,$C9
    IAT:2Immediate*16+IAT:2Immediate   $CA,$CB
    IAT:3Immediate*16+IAT:Illegal      $CC,$CD
    IAT:3Immediate*16+IAT:Illegal      $CE,$CF

    IAT:2DirectPage*16+IAT:2DirectPage $D0,$D1
    IAT:2DirectPage*16+IAT:2DirectPage $D2,$D3
    IAT:2DirectPage*16+IAT:2DirectPage $D4,$D5
    IAT:2DirectPage*16+IAT:2DirectPage $D6,$D7
    IAT:2DirectPage*16+IAT:2DirectPage $D8,$D9
    IAT:2DirectPage*16+IAT:2DirectPage $DA,$DB
    IAT:2DirectPage*16+IAT:2DirectPage $DC,$DD
    IAT:2DirectPage*16+IAT:2DirectPage $DE,$DF

    IAT:2Indexed8*16+IAT:2Indexed8     $E0,$E1
    IAT:2Indexed8*16+IAT:2Indexed16    $E2,$E3
    IAT:2Indexed8*16+IAT:2Indexed8     $E4,$E5
    IAT:2Indexed8*16+IAT:2Indexed8     $E6,$E7
    IAT:2Indexed8*16+IAT:2Indexed8     $E8,$E9
    IAT:2Indexed8*16+IAT:2Indexed8     $EA,$EB
    IAT:2Indexed16*16+IAT:2Indexed16   $EC,$ED
    IAT:2Indexed16*16+IAT:2Indexed16   $EE,$EF

    IAT:3Extended*16+IAT:3Extended     $F0,$F1
    IAT:3Extended*16+IAT:3Extended     $F2,$F3
    IAT:3Extended*16+IAT:3Extended     $F4,$F5
    IAT:3Extended*16+IAT:3Extended     $F6,$F7
    IAT:3Extended*16+IAT:3Extended     $F8,$F9
    IAT:3Extended*16+IAT:3Extended     $FA,$FB
    IAT:3Extended*16+IAT:3Extended     $FC,$FD
    IAT:3Extended*16+IAT:3Extended     $FE,$FF
         page
ComputeEffectiveAddress ; Computes Effective Address of instruction
*        Instruction has be fetched by FetchInstruction
*        Computes length of instruction and places in InstructionLength
*        Returns Z bit set if instruction is illegal in form.
*        Places Effective Address of instruction in "EffectiveAddress"
*        and sets EFApresent flag.
*        (If instruction logically has no EFA, resets "EFApresent" flag)
*        Effective address is address of final operand given by Index Postbyte,
*        Direct Page or Extended addressing modes.
*        Effective address of immediate instructions is ptr into instruction.
*        Effective address of Relative branch instructions is branch target.
*        (computed using InstructionAddress instead of UserRegisterPC)
*        Effective address for EXG, TFR and other such is $FFFF.
*        Also decides which index register, if any, will be modified,.
*        and computes new value for that index register, but does not update.
*
?? what about indirect cycle ?
!! just do it, make executer re-fetch if indirect
         ldx         #0                assume no index register will change
         stx         ModifiedIndexRegister
         clr         EFApresent        Reset "Effective address is present"
         lda         InstructionOpcode fetch opcode byte
         clr         InstructionLength assume no prefix byte
         ldb         InstructionPrefix is this a prefixed instruction?
         beq         ComputeEFANoPrefix no, process normally
         inc         InstructionLength add 1 because of prefix byte
         cmpb        #$11              $11 prefix ?
         beq         ComputeEFAPrefix$11 b/ yes
ComputeEFAPrefix$10 ; $10 prefix byte seen
         tsta                          opcode >= $80 ?
         bmi         ComputeEFAPrefix$1080 b/ opcode >= $80
         cmpa        #$20              illegal branch ?
         lbls        ComputeEFAIllegal b/ yes
         cmpa        #$2F              legal long branch ?
         bls         ComputeEFANoPrefix b/ yes
ComputeEFAcheckforSWI
         cmpa        #$3F              SWI2 ?
         beq         ComputeEFANoPrefix b/ yes
         lbra        ComputeEFAIllegal no, illegal instruction

ComputeEFAPrefix$1080 ; Prefix $10, opcode >=$80
         tab                           preserve (A)
         andb        #%11001111        mask off addressing mode
         cmpb        #$83              CMPD ?
         beq         ComputeEFANoPrefix b/ yes, that's ok!
         cmpb        #$8C              CMPY ?
         beq         ComputeEFANoPrefix b/ yes, that's ok!
         andb        #%10001110        mask off $40's and 1's bit
         cmpb        #$8E              LDY/LDS/STY/STS ?
         beq         ComputeEFANoPrefix b/ yes, that's ok!
         lbra        ComputeEFAIllegal b/ illegal opcode byte after $10

ComputeEFAPrefix11 ; $11 prefix byte seen
         tsta                          opcode >= $80 ?
         bpl         ComputeEFAcheckforSWI b/ no, must be SWI3
ComputeEFAPrefix$1180 ; Prefix $11, opcode >=$80
         tab                           preserve (A)
         andb        #%11001111        mask off addressing mode
         cmpb        #$83              CMPU ?
         beq         ComputeEFANoPrefix b/ yes, that's ok!
         cmpb        #$8C              CMPS ?
         lbne        ComputeEFAIllegal b/ illegal opcode byte after $11
ComputeEFANoPrefix ; Instruction has no prefix
         ldx         #InstructionAddressTypes get nibble about opcode
         lsra                          carry = 0 --> left nibble
         lda         a,x               fetch byte containing desired nibble
         bcs         ComputeEFA1       b/ want lower nibble
         lsra                          want upper nibble, shift down
         lsra
         lsra
         lsra
ComputeEFA1 ; nibble containing addresstype is in lower 4 bits of (A)
         anda        #$F               mask off unwanted bits
         sta         InstructionType   save Type, in case called by List logic
         tab                           save copy of address type
         anda        #%11              get initial estimate of instruction size
         adda        InstructionLength Take prefix byte into account
         sta         InstructionLength = better estimate
         leax        ComputeEFABranch,pcr branch on address type to process
         aslb                          make into word index
         jmp         [b,x]             go process address type
ComputeEFABranch ; Branch table used to decode address type
         #ComputeEFAIllegal            IAT:Illegal
         #ComputeEFADone               IAT:1Inherent
         #ComputeEFADirectPage         IAT:2DirectPage
         #ComputeEFAExtended           IAT:3Extended
         #ComputeEFALEAx               IAT:LEAx
         #ComputeEFAIllegal            <not defined>
         #ComputeEFAImmediate          IAT:2Immediate
         #ComputeEFAImmediate          IAT:3Immediate
         #ComputeEFA2Indexed8          IAT:2Indexed8
         #ComputeEFA2Indexed16         IAT:2Indexed16
         #ComputeEFAShortRelative      IAT:2ShortRelative
         #ComputeEFALongRelative       IAT:3LongRelative
         #ComputeEFAPushPull           IAT:2PushPull
         #ComputeEFADone               IAT:2CCImm
         #ComputeEFATFREXG             IAT:2TFREXG

ComputeEFAPushPull ; Push/Pull opcode encountered
         tst         InstructionPostByte does postbyte push/pull anything ?
         bne         ComputeEFAdone    b/ yes, all done
         bra         ComputeEFAIllegal b/ no, illegal instruction!

ComputeEFATFREXG ; TFR/EXG opcode, check post-byte validity
         lda         InstructionPostbyte fetch transfer postbyte
         cmpa        #$55              16 bit register transfer ?
         bls         ComputeEFAdone    b/ yes, all is fine
         cmpa        #$88              8 bit register transfer ?
         blo         ComputeEFAIllegal b/ no, illegal mix of 8-to-16 transfer
         cmpa        #$BB              ...?
         bls         ComputeEFAdone    b/ yes, all is fine
         bra         ComputeEFAIllegal b/ illegal transfer post-byte

ComputeEFAShortRelative ; 8 bit offset from end of instruction
         ldx         InstructionAddress EFA=PC+2+offset
         leax        2,x               =PC+2...
         ldb         InstructionAddress (displacement)
         leax        b,x               = EFA
         bra         ComputeEFAinX     store final EFA

ComputeEFALongRelative ; 16 bit offset from end of instruction
         ldx         InstructionAddress EFA=PC+instructionLength+offset
         ldb         InstructionLength
         leax        b,x               = PC+instructionlength...
         ldd         InstructionAddress (displacement)
         leax        d,x               = effective address
         bra         ComputeEFAinX     store final EFA

ComputeEFADirectPage ; Instruction contains Direct Page reference
         lda         UserRegisterDP    get upper 8 bits of page address
         lda         InstructionAddress get lower 8 bits of address
         std         EffectiveAddress  save computed address
         bra         ComputeEFAdoneInc tell world EFA is valid

ComputeEFAExtended ; opcode is legal, and is 3 bytes long
         ldx         InstructionAddress fetch Extended address
ComputeEFAinX ; Effective Address is in (X)
         stx         EffectiveAddress  save as Effective address
ComputeEFAdoneInc ; signal that Effective Address is valid
         inc         EFApresent        remember that EFA is present
         rts

ComputeEFAImmediate ; Instruction contains immediate operand
         ldx         InstructionAddress compute address of immediate operand
         tst         InstructionPrefix prefixed instruction ?
         beq         ComputeEFAImmediate1 b/ no
         inx                           yes, add 1 for prefix
ComputeEFAImmediate1
         stx         EffectiveAddress
         rts                           Note: EFApresent is false!

ComputeEFA2Indexed16 ; Index postbyte follows, 16 bit operand will be used
         lda         InstructionPostByte fetch the post byte
         bpl         ComputeEFALEAx    b/ 4 bit offset, legal reference
         anda        #%00001111        mask to obtain index mode bits
         beq         ComputeEFAIllegal b/ ,R+, illegal on 16 bit operand
         cmpa        #2                ,-R ?
         bne         ComputeEFALEAx    go process index post byte
ComputeEFAIllegal ; Illegal instruction encountered
         clr         InstructionLength to make sure everybody knows...
ComputeEFADone ; Instruction EFA computation completed
         rts

ComputeEFA2Indexed8 ; Index postbyte follows, 8 bit operand will be used
         lda         InstructionPostByte fetch the post byte
         bpl         ComputeEFALEAx    b/ 4 bit offset, legal reference
         anda        #%00001111        mask to obtain index mode bits
         cmpa        #1                ,R++ ?
         beq         ComputeEFAIllegal b/ yes, illegal on 8 bit operand
         cmpa        #3                ,--R ?
         beq         ComputeEFAIllegal b/ yes, illegal on 8 bit operand
ComputeEFALEAx ; instruction is LEAX, LEAY, LEAS, LEAU
         page
*
*        ComputeEFAAnalyzeIndexPostbyte -- check index post byte for legality
*        Decides if illegal postbyte, and if not,
*        Adjusts instruction length by extra number of bytes req'd
*
ComputeEFAAnalyzeIndexPostbyte ; Analyze index mode postbyte in (A)
         inc         EFApresent        Index post-byte ALWAYS compute an EFA
         lda         InstructionPostbyte fetch index mode byte
         tab                           index register displacement, pleez
         andb        #%01100000        get index register number
         lsrb                          compute pointer to index register slot
         lsrb
         lsrb
         lsrb
         ldx         #ComputeEFAIndexRegLookup
         ldx         b,x               = pointer to index register
         stx         ModifiedIndexRegister
         ldx         ,x                fetch index register (approx EFA) to X
         tab                           save postbyte...
         bpl         ComputeEFA4bitoffset b/ 4 bit offset
         andb        #%00001111        mask to obtain index mode type
         aslb                          double to make word index...
         ldy         #ComputeEFAPostByteDecode
         jmp         [b,y]             go to routine to handle postbyte mode
*  how do we make this completely relocatable?
ComputeEFAPostByteDecode ; branch table to decode bottom 4 bits of post byte
         #ComputeEFAAutoInc            %00000000 ,r+
         #ComputeEFADblInc             %00000001 ,r++
         #ComputeEFAPreDec             %00000010 ,-r
         #ComputeEFADblDec             %00000011 ,--r
         #ComputeEFAZeroOffset         %00000100 ,r
         #ComputeEFAOffsetbyA          %00000101 A,r
         #ComputeEFAOffsetbyB          %00000110 B,r
         #ComputeEFAIllegal            %00000111 illegal index mode
         #ComputeEFA8bitOffset         %00001000 <8bitoffset>,r
         #ComputeEFA16bitOffset        %00001001 <16bitoffset>,r
         #ComputeEFAIllegal            %00001010 illegal index mode
         #ComputeEFAOffsetbyD          %00001011 D,r
         #ComputeEFA8bitPCR            %00001100 <8bitoffset>,PCR
         #ComputeEFA16bitPCR           %00001101 <16bitoffset>,PCR
         #ComputeEFAIllegal            %00001110 illegal index mode
         #ComputeEFAExtendedIndirect   %00001111 [address]
         page
ComputeEFAAutoInc ; Auto-Inc address mode
         inx                           = new index register value
         stx         NewIndexRegister
         dex                           = EFA desired
         bita        #%00010000        indirect ?
         beq         ComputeEFAIndirect go check indirect bits (redundantly!)
         bra         ComputeEFAIllegal b/ yes, illegal.
????????
computeefa mustc heck TFR/EXG byte for legaliity!
         blo         ComputeEFAIllegal b/ illegal mix of 8-to-16 transfer
         cmpa        #$BB              legal 8 bit transfer ?
         bls         Execute2bytes     b/ yes
         bra         ComputeEFAIllegal b/ no
?????????
ComputeEFADblInc ; DoubleAuto-Inc address mode
         leax        2,x               = new index value after instruction
         stx         NewIndexRegister  new value to use later
         leax        -2,x              = EFA again
ComputeEFAZeroOffset ; Zero offset index mode
ComputeEFAIndirect ; (X) contains EFA, see if Indirect bit needs processing
         stx         EffectiveAddress  and save it
         lda         InstructionPostByte see if indirect bit is set
         bita        #%00010000        indirect ?
         beq         ComputeEFAIndexRts b/ no, all done!
         tst         WantEFA           is EFA *REALLY* wanted ?
         beq         ComputeEFAIndexRts b/ no, all done!
??? seeach bkpt table here?
         jsr         fetchword         go get word at EFA
         std         EffectiveAddress  save as EFA
         rts

ComputeEFAPreDec ; Pre-decrement address mode
         bita        #%00010000        indirect ?
         bne         ComputeEFAIllegal b/ yes, illegal.
         dex                           = EFA
         stx         NewIndexRegister  store new value for index register
         bra         ComputeEFAIndirect go check indirect bits

ComputeEFADblDec ; Double Pre-decrement address mode
         leax        -2,x               = EFA
         stx         NewIndexRegister  new value for index register
         bra         ComputeEFAIndirect go check indirect bits
         page
ComputeEFAOffsetbyA ; A register offset mode
         ldb         UserRegisterA     = displacement
ComputeEFAOffsetinB ; (B) contains offset, (X) contains base address
         leax        b,x               = EFA
         bra         ComputeEFAIndirect

ComputeEFAOffsetbyB ; B register offset mode
         ldb         UserRegisterB     = displacement
         bra         ComputeEFAOffsetinB

ComputeEFA4bitOffset ; Offset by 4 bit displacement mode post byte
         andb        #%00001111     mask off bits not related to displacement
         bitb        #%00001000     negative displacement ?
         beq         ComputeEFA4bitOffset1 b/ no
         orb         #%11110000     yes, sign extend to fill byte
ComputeEFA4bitOffset1 ; (B) contains 8 bit signed displacement
         bra         ComputeEFAOffsetinB

ComputeEFA8bitOffset ; 8 bit offset mode
         inc         InstructionLength account for displacement byte
         ldb         InstructionPostbyte+1 = displacement
         bra         ComputeEFAOffsetinB

ComputeEFA16bitOffset ; 16 bit offset mode
         inc         InstructionLength account for 16 bit displacement
         inc         InstructionLength
         ldd         InstructionPostbyte+1 = displacement
ComputeEFAOffsetinD ; index offset in (C), base address in (X)
         leax        d,x
         bra         ComputeEFAIndirect

ComputeEFAOffsetbyD ; D register offset mode
         ldd         UserRegisterD     = displacement
         bra         ComputeEFAOffsetinD

ComputeEFA8bitPCR ; PC relative, 8 bit offset mode
         inc         InstructionLength account for 8 bit displacement byte
         ldx         InstructionAddress = base address
         ldb         InstructionLength find end of instruction
         leax        b,x
         bra         ComputeEFAOffsetinB

ComputeEFA16bitPCR ; PC relative, 16 bit offset mode
         inc         InstructionLength account for 16 bit displacement
         inc         InstructionLength
         ldx         InstructionAddress = base address
         ldb         InstructionLength find end of instruction
         leax        b,x
         ldd         InstructionPostByte+1 = 8 bit offset
         bra         ComputeEFAOffsetinD

ComputeEFAExtendedIndirect ; Indirect address
         bita        #%00010000        make sure indirect bit is set
         beq         ComputeEFAIllegal b/ 0, illegal postbyte
         inc         InstructionLength account for 16 bit address
         inc         InstructionLength
         ldx         InstructionPostByte+1 get EFA
         bra         ComputeEFACheckIndirect which, of course, is set!
         page
