         Page   6809 Instruction assembly logic
SemanticPUSHPULLPOSTBYTE1 ; PUSHPULLPOSTBYTE = REGISTER
         ldx    #PushPullRegisterTable pointer to conversion table
         lda    b,x          fetch bit pattern specifying register bits
         beq    SemanticError b/ can't push/pull that register
         rts                 (A) contain partial push/pull post byte

SemanticPUSHPULLPOSTBYTE ; PUSHPULLPOSTBYTE = PUSHPULLPOSTBYTE ',' REGISTER
         ldb    Semantic3rdValue,x fetch new register desired
         ldx    #PushPullRegisterTable pointer to conversion table
         tst    b,x          is it legal to push/pull that register ?
         beq    SemanticError b/ no, illegal register specified
         bita   b,x          is register already in push/pull post byte ?
         bne    SemanticError b/ can't push/pull that register twice
*        cba                 must specify registers in "push" order
*        bls    SemanticError b/ wrong push order
         ora    b,x          = new value for partially assembled push/pull byte
         rts                 (A) = partial push/pull post byte

SemanticPullInstruction ; INSTRUCTION = OPPUSHPULL BLANK PUSHPULLPOSTBYTE ;
SemanticPushInstruction ; INSTRUCTION = OPPUSHPULL BLANK PUSHPULLPOSTBYTE ;
         tfr    b,a          move opcode to (A)
         ldb    Semantic3rdValue,x grab push/pull postbyte
         std    TokenBuffer+1 this is the desired instruction
         rts
         page
PushPullRegisterTable ; Translates register name to push/pull postbyte code
         fcb    %00000010    A register
         fcb    %00000100    B register
         fcb    %00000001    C register
         fcb    %00000110    D register
         fcb    0            E register *ILLEGAL*
         fcb    0            F register *ILLEGAL*
         fcb    0            G register *ILLEGAL*
         fcb    0            H register *ILLEGAL*
         fcb    0            I register *ILLEGAL*
         fcb    0            J register *ILLEGAL*
         fcb    0            K register *ILLEGAL*
         fcb    0            L register *ILLEGAL*
         fcb    0            M register *ILLEGAL*
         fcb    0            N register *ILLEGAL*
         fcb    0            O register *ILLEGAL*
         fcb    %10000000    P register
         fcb    0            Q register *ILLEGAL*
         fcb    0            R register *ILLEGAL*
         fcb    %01000000    S (or U) register
         fcb    0            T register *ILLEGAL*
         fcb    %01000000    U (or S) register
         fcb    0            V register *ILLEGAL*
         fcb    0            W register *ILLEGAL*
         fcb    %00010000    X register
         fcb    %00100000    Y register
         fcb    %00001000    Z register (DPR)
         page
SemanticTFREXG ; INSTRUCTION = OPTFREXG BLANK REGISTERNAME ',' REGISTERNAME ;
         ldb    Semantic3rdValue,x fetch source register name
         bsr    SemanticTFRGetReg determine TFR/EXG register feild/type
         lslb                shift source register spec to left 4 bits
         lslb
         lslb
         lslb
         stb    Semantic1stValue,x save source register specification
         lda    Semantic5thValue,x fetch target register name
         bcs    SemanticTFREXGD b/ double register type
         bsr    SemanticTFRGetReg determine TFR/EXG register feild/type
         bcs    SemanticError b/ can't TFR/EXG single byte to double byte
SemanticTFREXG1 ; ok to construct final postbyte
         orb    Semantic1stValue,x construct actual TFR/EXG postbyte
         lda    Semantic1stValue+1,x fetch opcode byte
         std    TokenBuffer+1 store assembled instruction
         lda    #2           = size of instruction
         rts

SemanticTFREXGD ; TFR/EXG with double register pair
         bsr    SemanticTFRGetReg determine TFR/EXG register feild/type
         bcs    SemanticTFREXG1 b/ TFR/EXG double register to double register
         bra    SemanticError b/ can't TFR/EXG double byte to single byte

SemanticTFRGetReg ; Translate register name in (B) to TFR/EXG postbyte code
         ldx    #TFREXGRegisterTable Use this table to effect translation
         ldb    b,x          fetch postbyte code
         bmi    SemanticError b/ bad register name
         rorb                move postbyte code into lower nibble of (B)
         rts
         page
TFREXGRegisterTable ; Translates Register name to TFR/EXG post byte code
*        Table format: Bit 0 = 0 --> 8 bit register transfer, bits 4-1 = code
*                      Bit 0 = 1 --> 16 bit transfer, bits 4-1 = code
*                      Bit 7 set --> illegal
         fcb    %1000*2+1    A register
         fcb    %1001*2+1    B register
         fcb    %1010*2+1    C register
         fcb    %0000*2+2    D register
         fcb    -1           E register *ILLEGAL*
         fcb    -1           F register *ILLEGAL*
         fcb    -1           G register *ILLEGAL*
         fcb    -1           H register *ILLEGAL*
         fcb    -1           I register *ILLEGAL*
         fcb    -1           J register *ILLEGAL*
         fcb    -1           K register *ILLEGAL*
         fcb    -1           L register *ILLEGAL*
         fcb    -1           M register *ILLEGAL*
         fcb    -1           N register *ILLEGAL*
         fcb    -1           O register *ILLEGAL*
         fcb    %0101*2+2    P register
         fcb    -1           Q register *ILLEGAL*
         fcb    -1           R register *ILLEGAL*
         fcb    %0100*2+2    S register
         fcb    -1           T register *ILLEGAL*
         fcb    %0011*2+2    U register
         fcb    -1           V register *ILLEGAL*
         fcb    -1           W register *ILLEGAL*
         fcb    %0001*2+2    X register
         fcb    %0010*2+2    Y register
         fcb    %1011*2+1    Z register (DPR)
         page
SemanticRelativeBranch ; INSTRUCTION = OPRELATIVEBRANCH BLANK EXP ;
         ldx   Semantic1stValue,x get opcode
         tsta                Long branch ?
         bne   SemanticLongBranch
         stb   Tokenbuffer   save opcode byte (short relative branch or bsr)
         cmpb  #$16          LBRA ?
         beq   SemanticLBRAorLBSR b/ yes
         cmpb  #$17          LBSR ?
         beq   SemanticLBRAorLBSR  b/ yes, go handle
         ldd   Semantic3rdValue,x grab target address
         subd  OpenCellLocation = displacment to target address
         subd  #2            because PC will be 2 past opcode address
         stb   Tokenbuffer+1 save branch displacement
         rolb                verify that (A) = sign bit of (B)
         adca  #0            should give zero!
         bne   SemanticError b/ short relative branch out of range
         lda   #2            = instruction size
         rts

SemanticLBRAorLBSR ; Handle LBRA or LBSR
         ldd   Semantic3rdValue,x grab target address
         subd  OpenCellLocation = approx. displacement to target
         subd  #3            = actual displacement needed by instruction
         std   TokenBuffer+1 fill in rest of instruction
         lda   #3            = instruction length
         rts

SemanticLongBranch ; Long branch if relative desired
         std   Tokenbuffer   save opcode bytes
         ldd   Semantic3rdValue,x grab target address
         subd  OpenCellLocation = approx. displacement to target
         subd  #4            = actual displacement needed by instruction
         std   TokenBuffer+2 fill in rest of instruction
         lda   #4            = instruction length
         rts
         page
SemanticInstructionInherent ; INSTRUCTION = OPWITHINHERENTOPERAND ;
         ldd   Semantic1stValue,x get instruction
         tsta                prefix byte given ?
         bne   SemanticInstructionInherent1 b/ yes
         stb   TokenBuffer   save instruction byte
         lda   #1            = instruction length
         rts

SemanticInstructionInherent1
         std   TokenBuffer+1 save 2 byte inherent instruction
         lda   #2            = length
         sta   TokenBuffer
         rts
         page
VerifyNotLEAx ; Verify that opcode is not LEAx ...
         ???

SemanticMemoryRef ; INSTRUCTION = OPWITHMEMADDRESS BLANK EXP ;
         bsr   VerifyNotLEAx can't do LEAx if not indexed addressing
         std   InstructionPrefix save instruction opcode (Zero page ref form)
         ldd   Semantic3rdValue,x fetch specified address
         cmpa  SetDP         page zero reference?
         bne   SemanticMemoryExtendedRef b/ no
SemanticMemoryPZRef ; Page zero reference is required
         stb   InstructionAddress b/ yes, save 8 bit address
         lda   #2            = instruction length
         sta   InstructionLength
         rts

SemanticMemoryExtendedRef ; Long reference required
         std   InstructionAddress assume 16 bit reference required
         ldb   InstructionOpcode get opcode skeleton
         orb   #%00100000    force extended mode on instruction
         bmi   SemanticMemoryExtendedRef1 b/ not monadic class opcode
         orb   #%01110000    Monadic class, finish conversion to extended mode
SemanticMemoryExtendedRef1 ; Long reference required, not a monadic opcode
         stb   InstructionOpcode
SemanticImmediate16bits
         lda   #3            ...makes this a 3 byte instructon
         sta   InstructionLength
         rts

SemanticShortRef ; INSTRUCTION = OPWITHMEMADDRESS BLANK '<' EXP ;
         bsr   VerifyNotLEAx can't do LEAx if not indexed addressing
         std   InstructionPrefix save instruction opcode (Zero page ref form)
         ldd   Semantic4thValue,x fetch specified address
         cmpa  SetDP         page zero reference?
         bne   SemanticError b/ no, so I can't assemble it!
         bra   SemanticMemoryPZRef

SemanticLongRef ; INSTRUCTION = OPWITHMEMADDRESS BLANK '>' EXP ;
         bsr   VerifyNotLEAx can't do LEAx if not indexed addressing
         std   InstructionPrefix save instruction opcode (Zero page ref form)
         ldd   Semantic4thValue,x fetch specified address
         bra   SemanticMemoryExtendedRef go build instruction

SemanticImmediateRef ; INSTRUCTION = OPWITHMEMADDRESS BLANK '#' EXP ;
         bsr   VerifyNotLEAx can't do LEAx if not indexed addressing
         std   InstructionPrefix save instruction opcode (Zero page ref form)
         tstb                monadic or LEAx opcode ?
         beq   SemanticError b/ yes, no immediate allowed!
         andb  #%10111111    fold $C0-$FF into $80 thru $7f
         cmpb  #$97          STA/STB # ?
         beq   SemanticError b/ STq #... is absolutely insane!
         cmpb  #$9D          JSR/STD # ?
         beq   SemanticError b/ STq #... is absolutely insane!
         cmpb  #$9F          STX/STU/STY/STS # ?
         beq   SemanticError b/ STq #... is absolutely insane!
         ldd   Semantic3rdValue,x fetch specified operand
         std   InstructionAddress assume all 16 bits required as operand
         lda   InstructionOpcode fetch opcode being processed
         suba  #%00010000    convert from Zero page ref to Immediate ref form
         sta   InstructionOpcode
         anda  #%10111111    fold $C0-$FF into $80 thru $7F
         cmpa  #$83          SUBD/ADDD/CMPD/CMPU # ?
         beq   SemanticImmediate16bits b/ yes, generate 16 bit roperand
         cmpa  #$8C          CMPX/LDD/CMPY # ?
         beq   SemanticImmediate16bits b/ yes, generate 16 bit roperand
         cmpa  #$8E          LDX/LDU/LDY/LDS # ?
         beq   SemanticImmediate16bits b/ yes, generate 16 bit roperand
         stb   InstructionAddress shorten immediate operand to 8 bits
         lda   #2            = instruction length
         sta   InstructionLength
         rts
         page
SemanticIndexRef ; INSTRUCTION = OPWITHMEMADDRESS BLANK INDEXMODE ;
*        Note: Postbyte of instruction is already assembled in Postbyte area
         std   InstructionPrefix save instruction Prefix and opcode byte
         bitb  #%11110000    monadic class instruction ?
         beq   SemanticIndexMonadic b/ yes, go handle
         bpl   SemanticIndexDone b/ LEAx instruction, index mode is implicit
         addb  #%00010000    force index mode on Arithmetic class instruction
         bra   SemanticIndexDone go store instruction opcode and length

SemanticIndexMonadic ; Monadic class instruction with index ref
         orb   #%01100000    force "index mode" opcode
SemanticIndexDone ; come here when Index opcode has been built
         stb   InstructionOpcode
         lda   Semantic3rdValue,x = instruction length
         sta   InstructionLength
         rts

SemanticMustBeSUXYPCR ; Check register name in (D) for S, U, X, Y or P
         lda   #%10001101    assume PC+-15 bit offset for Post-byte
         cmpb  #'P           P register ?
         beq   SemanticMustBeSUXYrts b/ yes
SemanticMustBeSUXY ; Check register name in (D) for S, U, X or Y
         lda   #%01100000    Assume S: fill in bits 6 and 5 of Post-byte
         cmpb  #'S           S register ?
         beq   SemanticMustBeSUXYrts b/ yes
         lda   #%01000000    Assume U: fill in bits 6 and 5 of Post-byte
         cmpb  #'U           U register ?
         beq   SemanticMustBeSUXYrts b/ yes
         lda   #%00000000    Assume X: fill in bits 6 and 5 of Post-byte
         cmpb  #'X           X register ?
         beq   SemanticMustBeSUXYrts b/ yes
         lda   #%00100000    Assume Y: fill in bits 6 and 5 of Post-byte
         cmpb  #'Y           Y register ?
         bne   SemanticError b/ not a legal index register
SemanticMustBeSUXYrts
         rts
         page
SemanticZeroOffset ; INDEXTYPE = ',' REGISTERNAME ;
         lda   Semantic2ndValue,x fetch register name
         bsr   SemanticMustbeSUXY      check validity
         ora   #%10000100    Select ,R with 0 offset index mode
Semantic1ByteIndexMode
         sta   InstructionPostbyte and save it
         lda   #1+1          = number of index mode bytes,+1 for opcode byte
         rts

SemanticRegisterOffset ; INDEXTYPE = REGISTERNAME ',' REGISTERNAME ;
         ldd   Semantic3rdValue,x fetch index register specification
         bsr   SemanticMustBeSUXY check validity
         ldb   Semantic1stValue,x fetch Offset register name
         cmpb  #'A           A register offset ?
         beq   SemanticRegisterOffsetA b/ yes
         cmpb  #'B           B register offset ?
         beq   SemanticRegisterOffsetB b/ yes
         cmpb  #'D           D register offset ?
         bne   SemanticError b/ no, illegal offset register
SemanticRegisterOffsetD ; REGISTEROFFSETINDEX = 'D' ',' SUXY ;
         ora   #%10001011    Select D,R index mode
         bra   Semantic1ByteIndexMode

SemanticRegisterOffsetA ; REGISTEROFFSETINDEX = 'A' ',' SUXY ;
         ora   #%10000110    Select A,R index mode
         bra   Semantic1ByteIndexMode

SemanticRegisterOffsetB ; REGISTEROFFSETINDEX = 'B' ',' SUXY ;
         ora   #%10000101    Select B,R index mode
         bra   Semantic1ByteIndexMode
         page
SemanticAutoInc ; INDEXTYPE = ',' REGISTERNAME '+' ;
         ldd   Semantic2ndValue,x fetch register name
         bsr   SemanticMustBeSUXY check validity
         ora   #%10000000    Select R+ index mode
         bra   Semantic1ByteIndexMode

SemanticDblAutoInc ; INDEXTYPE = ',' REGISTERNAME '+' '+' ;
         ldd   Semantic2ndValue,x fetch register name
         bsr   SemanticMustBeSUXY check validity
         ora   #%10000001    Select R++ index mode
         bra   Semantic1ByteIndexMode

SemanticPreDec ; INDEXTYPE = ',' '-' REGISTERNAME ;
         ldd   Semantic3rdValue,x fetch register name
         bsr   SemanticMustBeSUXY check validity
         ora   #%10000010    Select -R index mode
         bra   Semantic1ByteIndexMode

SemanticDblDec ; INDEXTYPE = ',' '-' '-' REGISTERNAME ;
         ldd   Semantic4thValue,x fetch register name
         bsr   SemanticMustBeSUXY check validity
         ora   #%10000011    Select --R index mode
         bra   Semantic1ByteIndexMode
         page
SemanticDisplacedIndex ; INDEXTYPE = EXP ',' REGISTER ;
         lda   Semantic3rdValue,x fetch index register specification
         bsr   SemanticMustBeSUXYPCR go check validity
         tsta                PCR ?
         bmi   SemanticDisplacedPCR b/ PCR displacement
         ora   #%10001001    Select n,R with 15 bit offset index mode
         sta   InstructionPostbyte save index mode
         ldd   Semantic1stValue,x get offset desired
SemanticDisplacedIndex3
         std   InstructionPostbyte+1 save offset required
         lda   #3+1          = # bytes in indextype, +1 for opcode byte
         rts

SemanticDisplacedPCR ; PCR displacement specified
         sta   InstructionPostbyte save index mode
         ldd   Semantic1stValue,x fetch absolute address desired
         subd  OpenCellAddress = displacement from instruction to location
         bra   SemanticDisplacedIndex3

SemanticIndirectAddress ; INDEXMODE = '[' EXP ']' ;
         ldd   Semantic2ndValue,x get desired address
         std   InstructionPostbyte+1 save address for indirect mode
         lda   #%10011111    = indirect address mode
         sta   InstructionPostbyte
         lda   #3+1          = number of index mode bytes,+1 for opcode byte
         rts

SemanticIndirectIndex ; INDIRECTINDEX = '[' INDEXTYPE ']' ;
         lda   InstructionPostbyte fetch index mode postbyte
         ora   #%00010000    set the 'indirect' bit
         sta   InstructionPostbyte
         anda  #%10001111    check for illegal cases...
         cmpa  #%10000000    Auto-inc mode ?
         beq   SemanticError b/ yes, can't do indirect!
         cmpa  #%10000010    Pre-decrement mode ?
         beq   SemanticError b/ yes, can't do indirect!
         rts
         page
SemanticSimpleIndex ; INDEXMODE = INDIRECTINDEX ;
         lda   InstructionPostbyte fetch postbyte generated
         anda  #%10001111    (mask off index register name and indirect bit)
         cmpa  #%10001001    15 bit offset from P ?
         beq   SemanticOptimized7 b/ yes, might be able to use 7 bit index
         cmpa  #%10001001    15 bit offset from S, U, X or Y?
         bne   SemanticSimpleIndexDone b/ yes, can't optimize if not offset!
         ldd   InstructionPostbyte+1 fetch index mode displacement
         beq   SemanticOptimizedIndex0 b/ zero displacement
         cmpd  #-16          4 bit offset ok ?
         blt   SemanticOptimized7 b/ no, might be able to use 7 bit index
         cmpd  #15           ... ?
         bgt   SemanticOptimized7 b/ no, might be able to use 7 bit index
         andb  #$1111        extract 4 bit offset value
         lda   InstructionPostbyte get index register selector + indirect bit
         anda  #%01110000    mask off other garbage
         aba                 combine to create n,R with 4 bit offset
         sta   InstructionPostbyte save final postbyte
         lda   #1+1          = size of entire instruction, including opcode
         rts

SemanticOptimizedIndex0 ; 0 offset, optimize to appropriate post-byte
         lda   InstructionPostbyte fetch index register selector and indirect bit
         anda  #%11110000    mask of index style, retain index reg and indirect
         oraa  #%00000100    select 0,R index mode
         sta   InstructionPostbyte
         lda   #1+1          = size of entire instruction, including opcode
         rts

SemanticOptimizedIndex7 ; try to optimize for 7 bit index
         ldd   InstructionPostbyte+1 fetch index displacement
         cmpd  #-128         will 7 bit offset work ?
         blt   SemanticOptimizedIndex1 b/ no
         cmpd  #127          ...?
         bgt   SemanticOptimizedIndex1 b/ no
SemanticMake7bitIndex
         dec   InstructionPostbyte modify index mode postbyte to 7 bit offset
         stb   InstructionPostbyte+1 store 7 bit offset in proper place
         lda   #1+1            = size of index part of instruction,+1 for opcode
         rts

SemanticOptimizedIndex1 ; Can't optimized index displacement
*** should leave postbyte in (A), length in (B)???
         lda   #3            = size of index part of instruction
         rts

SemanticShortIndexReqd ; INDEXMODE = '<' INDIRECTINDEX ;
         lda   InstructionPostbyte fetch postbyte generated
         anda  #%10001111    (mask off index register name and indirect bit)
         cmpa  #%10001001    15 bit offset from P ?
         beq   SemanticForceOptimized7 b/ yes, might be able to use 7 bit index
         cmpa  #%10001001    15 bit offset from S, U, X or Y?
         bne   SemanticError b/ no, can't force mode!
*** should we try for 0 or 4 bit displacement here?
SemanticOptimizedIndex7 ; try to optimize for 7 bit index
         ldd   InstructionPostbyte+1 fetch index displacement
         cmpd  #-128         will 7 bit offset work ?
         blt   SemanticError can't make into short index mode
         cmpd  #127          ...?
         bgt   SemanticError b/ no
         bra   SemanticMake7bitIndex
