795 lines
15 KiB
NASM
795 lines
15 KiB
NASM
;TODO, sort out overflow flag
|
|
;DEBUG STUFF
|
|
.equ ZP_offset = 0x00 ;offset for Zero page, set to 0 for non debug
|
|
.MACRO cp1
|
|
|
|
; clc
|
|
|
|
cp @0,@1
|
|
|
|
|
|
brcs PC+3 ;invert carry
|
|
sec
|
|
rjmp PC+2
|
|
clc
|
|
|
|
in Pstat1,SREG ;save status bits
|
|
|
|
.ENDMACRO
|
|
|
|
.MACRO move_to_reg
|
|
|
|
mov r17,Pstat1 ;TEST ME
|
|
tst @0 ;all this is need becase the Z and N flags get changed, but dont in a mov operation
|
|
;add zero should test register
|
|
|
|
in r16,SREG
|
|
|
|
;N flag
|
|
sbrs r16,2
|
|
cbr r17,EXP2(Ns)
|
|
sbrc r16,2
|
|
sbr r17,EXP2(Ns)
|
|
;Z flag
|
|
sbrs r16,1
|
|
cbr r17,EXP2(Zs)
|
|
sbrc r16,1
|
|
sbr r17,EXP2(Zs)
|
|
|
|
mov Pstat1,r17
|
|
|
|
.ENDMACRO
|
|
;-----------01-----------------------------------------------------------
|
|
op_ORA: ;OR
|
|
rcall get_value_01
|
|
|
|
out SREG,Pstat1 ;still need to do this to preserve carry
|
|
or A,retL ;perform OR function
|
|
in Pstat1,SREG ;save status bits
|
|
rjmp next_op
|
|
op_AND: ;AND
|
|
rcall get_value_01
|
|
|
|
out SREG,Pstat1
|
|
and A,retL
|
|
in Pstat1,SREG ;save status bits
|
|
rjmp next_op
|
|
|
|
|
|
op_EOR: ;Exclusive or
|
|
rcall get_value_01
|
|
|
|
out SREG,Pstat1
|
|
eor A,retL
|
|
in Pstat1,SREG ;save status bits
|
|
rjmp next_op
|
|
op_ADC: ;ADD with carry
|
|
rcall get_value_01
|
|
|
|
out SREG,Pstat1 ;restor status reg for carry op
|
|
|
|
ldi r17,1
|
|
|
|
; in r16,SREG
|
|
; sbrc r16,0
|
|
; add A,r17
|
|
|
|
adc A,retL
|
|
|
|
in r16,SREG
|
|
|
|
|
|
|
|
mov Pstat1,r16 ;save status bits
|
|
|
|
|
|
mov r17,Pstat2
|
|
|
|
;sort out O(V) flag
|
|
sbrs r16,3
|
|
cbr r17,EXP2(Os)
|
|
sbrc r16,3
|
|
sbr r17,EXP2(Os)
|
|
|
|
;sbr r17,EXP2(Os)
|
|
|
|
mov Pstat2,r17 ;copy back
|
|
|
|
rjmp next_op
|
|
|
|
op_STA: ;Store A to mem
|
|
rcall get_value_01 ;Dont acctualy need to get that value, but called to work out address for write
|
|
mov retL,A
|
|
st_cpuZ A
|
|
rjmp next_op
|
|
|
|
op_LDA: ;Load A with mem
|
|
rcall get_value_01
|
|
mov A,retL
|
|
|
|
move_to_reg A
|
|
|
|
|
|
rjmp next_op
|
|
|
|
op_CMP: ;Compare A and mem
|
|
rcall get_value_01
|
|
cp1 A,retL
|
|
|
|
rjmp next_op
|
|
op_SBC: ;Subtract A-M with carry
|
|
rcall get_value_01
|
|
|
|
; mov r18,A ;TEST
|
|
|
|
out SREG,Pstat1 ;restor status reg for carry op
|
|
|
|
brcs PC+3 ;Strange subtraction as works on an inverted carry
|
|
sec
|
|
rjmp PC+2
|
|
clc
|
|
|
|
; ldi r17,1
|
|
;---TEST
|
|
; in r16,SREG
|
|
; sbrc r16,0
|
|
; add A,r17
|
|
; SUB A,retL
|
|
|
|
SEZ ;needed because only clears Z if result <> 0!
|
|
|
|
sbc A,retL
|
|
|
|
brcs PC+3 ;again..it inverts the carry???
|
|
sec
|
|
rjmp PC+2
|
|
clc
|
|
|
|
in Pstat1,SREG ;save status bits
|
|
|
|
|
|
; sbc r18,retL
|
|
|
|
in r16,SREG
|
|
|
|
mov r17,Pstat2
|
|
|
|
;sort out O(V) flag
|
|
sbrs r16,3
|
|
cbr r17,EXP2(Os)
|
|
sbrc r16,3
|
|
sbr r17,EXP2(Os)
|
|
|
|
; sbr r17,EXP2(Os)
|
|
|
|
|
|
mov Pstat2,r17 ;copy back
|
|
|
|
|
|
|
|
rjmp next_op
|
|
|
|
;-----------10-----------------------------------------------------------
|
|
op_ASL: ;Logcial shift left
|
|
rcall get_value_10
|
|
lsl retL
|
|
in Pstat1,SREG ;save status bits
|
|
st_cpuZ retL
|
|
rjmp next_op
|
|
|
|
|
|
op_ROL: ;Left shit with caryy
|
|
rcall get_value_10
|
|
out SREG,Pstat1 ;restor status reg for carry op
|
|
rol retL
|
|
in Pstat1,SREG ;save status bits
|
|
st_cpuZ retL
|
|
rjmp next_op
|
|
|
|
op_LSR: ;Logcial shift right
|
|
rcall get_value_10
|
|
lsr retL
|
|
in Pstat1,SREG ;save status bits
|
|
st_cpuZ retL
|
|
rjmp next_op
|
|
op_ROR: ;Right shit with caryy
|
|
rcall get_value_10
|
|
out SREG,Pstat1 ;restor status reg for carry op
|
|
ror retL
|
|
in Pstat1,SREG ;save status bits
|
|
st_cpuZ retL
|
|
rjmp next_op
|
|
|
|
op_STX: ;Store X to memory
|
|
rcall get_value_10
|
|
mov retL,Xr
|
|
st_cpuZ retL
|
|
rjmp next_op
|
|
|
|
op_LDX: ;Load X with memory
|
|
rcall get_value_10
|
|
mov Xr,retL
|
|
|
|
move_to_reg Xr
|
|
rjmp next_op
|
|
|
|
op_DEC: ;dec memory
|
|
rcall get_value_10
|
|
out SREG,Pstat1
|
|
dec retL
|
|
in Pstat1,SREG
|
|
st_cpuZ retL
|
|
rjmp next_op
|
|
|
|
op_INC:
|
|
rcall get_value_10
|
|
out SREG,Pstat1
|
|
inc retL
|
|
in Pstat1,SREG
|
|
st_cpuZ retL
|
|
rjmp next_op
|
|
;-----------00-----------------------------------------------------------
|
|
;same as 10 but accum missing
|
|
op_BIT: ;This instructions is used to test if one or more bits are set in a target memory location.
|
|
;The mask pattern in A is ANDed with the value in memory to set or clear the zero flag,
|
|
;but the result is not kept. Bits 7 and 6 of the value from memory are copied into the N and V flags.
|
|
rcall get_value_10
|
|
out SREG,Pstat1
|
|
mov r16,A ;make copy
|
|
and r16,retL ;perform AND
|
|
in r16,SREG ;copy SREG for Z flag
|
|
|
|
;sort out N flag
|
|
sbrs retL,7
|
|
cbr r16,EXP2(Ns)
|
|
sbrc retL,7
|
|
sbr r16,EXP2(Ns)
|
|
|
|
mov Pstat1,r16 ;copy back
|
|
mov r16,Pstat2
|
|
|
|
;sort out O(V) flag
|
|
sbrs retL,6
|
|
cbr r16,EXP2(Os)
|
|
sbrc retL,6
|
|
sbr r16,EXP2(Os)
|
|
|
|
mov Pstat2,r16 ;copy back
|
|
|
|
rjmp next_op
|
|
|
|
op_JMP: ;Jump absolute
|
|
get_pc_mem r18
|
|
get_pc_mem r17
|
|
|
|
mov PL,r18
|
|
mov PH,r17
|
|
rjmp next_op
|
|
|
|
|
|
op_JMPI: ;Jump absolute indirect
|
|
get_pc_mem YL ;get indirect address
|
|
get_pc_mem YH
|
|
ld_cpuY PL ;load PC with indriect value
|
|
inc YL ;NOTE, not using Y+ because of CPU bug which does not carry the carry to high byte
|
|
ld_cpuY PH
|
|
rjmp next_op
|
|
|
|
op_STY: ;Store Y to memory
|
|
rcall get_value_10
|
|
mov retL,Yr
|
|
st_cpuZ retL
|
|
rjmp next_op
|
|
op_LDY:
|
|
rcall get_value_10
|
|
mov Yr,retL
|
|
|
|
move_to_reg Yr
|
|
rjmp next_op
|
|
op_CPY: ;Compare Y with memory
|
|
rcall get_value_10
|
|
cp1 Yr,retL
|
|
|
|
rjmp next_op
|
|
op_CPX: ;Compare X with memory
|
|
rcall get_value_10
|
|
|
|
cp1 Xr,retL
|
|
|
|
rjmp next_op
|
|
;--BRANCHES---
|
|
|
|
op_BPL: ;Branch if Positive (N = 0)
|
|
mov r16,Pstat1
|
|
sbrs r16,Ns
|
|
rjmp Branch_take
|
|
adiw PL,1 ;skip over address if no branch
|
|
rjmp next_op
|
|
|
|
op_BMI: ;Branch if minus (N = 1)
|
|
mov r16,Pstat1
|
|
sbrc r16,Ns
|
|
rjmp Branch_take
|
|
adiw PL,1 ;skip over address if no branch
|
|
rjmp next_op
|
|
op_BVC: ;Branch if (O = 0)
|
|
mov r16,Pstat2
|
|
sbrs r16,Os
|
|
rjmp Branch_take
|
|
adiw PL,1 ;skip over address if no branch
|
|
rjmp next_op
|
|
|
|
op_BVS: ;Branch if (O = 1)
|
|
mov r16,Pstat2
|
|
sbrc r16,Os
|
|
rjmp Branch_take
|
|
adiw PL,1 ;skip over address if no branch
|
|
rjmp next_op
|
|
op_BCC: ;Branch is Carry clear
|
|
mov r16,Pstat1
|
|
sbrs r16,Cs
|
|
rjmp Branch_take
|
|
adiw PL,1 ;skip over address if no branch
|
|
rjmp next_op
|
|
op_BCS:
|
|
mov r16,Pstat1
|
|
sbrc r16,Cs
|
|
rjmp Branch_take
|
|
adiw PL,1 ;skip over address if no branch
|
|
rjmp next_op
|
|
op_BNE: ;Branch is (Z=0)
|
|
mov r16,Pstat1
|
|
sbrs r16,Zs
|
|
rjmp Branch_take
|
|
adiw PL,1 ;skip over address if no branch
|
|
rjmp next_op
|
|
op_BEQ:
|
|
mov r16,Pstat1
|
|
sbrc r16,Zs
|
|
rjmp Branch_take
|
|
adiw PL,1 ;skip over address if no branch
|
|
rjmp next_op
|
|
|
|
op_BRK:
|
|
;TODO
|
|
ldi r16,'B'
|
|
rcall rs232_0_tx
|
|
nop
|
|
nop
|
|
rjmp next_op
|
|
op_JSRA:
|
|
get_pc_mem r17 ;get jump address
|
|
stack_push PH ;push address to stack, done here because accutaly save PC-1
|
|
stack_push PL
|
|
get_pc_mem r18 ;get high jump address
|
|
|
|
mov PL,r17
|
|
mov PH,r18
|
|
rjmp next_op
|
|
|
|
op_RTI:
|
|
stack_pop retL
|
|
rcall stack_decomp
|
|
stack_pop PL
|
|
stack_pop PH
|
|
nop ;TODO
|
|
nop
|
|
rjmp next_op
|
|
|
|
op_RTS:
|
|
stack_pop PL ;get return address from stack
|
|
stack_pop PH
|
|
|
|
adiw PL,1 ;add on to PC
|
|
|
|
rjmp next_op
|
|
|
|
|
|
;--------SPECIAL CASES and operations only on the accumulator---------
|
|
op_ASL_A: ;logical shift left
|
|
lsl A
|
|
|
|
in Pstat1,SREG ;save status bits
|
|
rjmp next_op
|
|
|
|
op_ROL_A: ;shift left with carry
|
|
out SREG,Pstat1 ;restor status reg for carry op
|
|
|
|
rol A
|
|
|
|
in Pstat1,SREG ;save status bits
|
|
rjmp next_op
|
|
|
|
|
|
op_LSR_A:
|
|
lsr A
|
|
|
|
in Pstat1,SREG ;save status bits
|
|
rjmp next_op
|
|
op_ROR_A:
|
|
out SREG,Pstat1 ;restor status reg for carry op
|
|
|
|
ror A
|
|
|
|
in Pstat1,SREG ;save status bits
|
|
rjmp next_op
|
|
|
|
op_STX_ZPY: ;Store X to memory
|
|
rcall get_value_ZP_idx_Y
|
|
|
|
mov retL,Xr
|
|
st_cpuZ retL
|
|
rjmp next_op
|
|
|
|
op_LDX_ZPY:
|
|
rcall get_value_ZP_idx_Y
|
|
mov Xr,retL
|
|
|
|
move_to_reg Xr
|
|
rjmp next_op
|
|
|
|
op_LDX_XY:
|
|
rcall get_value_ZP_abs_idx_Y
|
|
mov Xr,retL
|
|
|
|
move_to_reg Xr
|
|
rjmp next_op
|
|
op_PHP:
|
|
rcall stack_build
|
|
stack_push retL
|
|
rjmp next_op
|
|
|
|
op_PLP:
|
|
stack_pop retL
|
|
rcall stack_decomp
|
|
rjmp next_op
|
|
op_PHA:
|
|
stack_push A
|
|
rjmp next_op
|
|
op_PLA:
|
|
stack_pop A
|
|
move_to_reg A
|
|
rjmp next_op
|
|
op_DEY:
|
|
out SREG,Pstat1 ;restor SREG so carry isnt changed
|
|
dec Yr ;perform dec
|
|
in Pstat1,SREG ;save changed N and Z
|
|
rjmp next_op
|
|
|
|
op_TAY: ;Transfer A to Y
|
|
|
|
mov Yr,A ;
|
|
|
|
move_to_reg Yr
|
|
rjmp next_op
|
|
|
|
op_INY:
|
|
out SREG,Pstat1
|
|
inc Yr
|
|
in Pstat1,SREG
|
|
rjmp next_op
|
|
|
|
op_INX:
|
|
out SREG,Pstat1
|
|
inc Xr
|
|
in Pstat1,SREG
|
|
rjmp next_op
|
|
|
|
op_CLC:
|
|
mov r16,Pstat1
|
|
cbr r16,EXP2(Cs)
|
|
mov Pstat1,r16
|
|
rjmp next_op
|
|
op_SEC:
|
|
mov r16,Pstat1
|
|
sbr r16,EXP2(Cs)
|
|
mov Pstat1,r16
|
|
rjmp next_op
|
|
op_CLI:
|
|
mov r16,Pstat2
|
|
cbr r16,EXP2(Is)
|
|
mov Pstat2,r16
|
|
rjmp next_op
|
|
op_SEI:
|
|
mov r16,Pstat2
|
|
sbr r16,EXP2(Is)
|
|
mov Pstat2,r16
|
|
rjmp next_op
|
|
op_TYA: ;Transfer Y to A
|
|
mov A,Yr ;
|
|
|
|
move_to_reg A
|
|
rjmp next_op
|
|
op_CLV:
|
|
mov r16,Pstat2
|
|
cbr r16,EXP2(Os)
|
|
mov Pstat2,r16
|
|
rjmp next_op
|
|
|
|
op_CLD:
|
|
mov r16,Pstat2
|
|
cbr r16,EXP2(Ds)
|
|
mov Pstat2,r16
|
|
rjmp next_op
|
|
op_SED:
|
|
mov r16,Pstat2
|
|
sbr r16,EXP2(Ds)
|
|
mov Pstat2,r16
|
|
rjmp next_op
|
|
op_TXA: ;TRans X to A
|
|
mov A,Xr ;
|
|
|
|
move_to_reg A
|
|
rjmp next_op
|
|
op_TXS: ;transfer X to stack pointer
|
|
mov stack,Xr
|
|
rjmp next_op
|
|
|
|
|
|
op_TAX: ;Transfer A to X
|
|
mov Xr,A ;
|
|
|
|
move_to_reg Xr
|
|
rjmp next_op
|
|
|
|
op_TSX:
|
|
mov Xr,stack ;
|
|
|
|
move_to_reg Xr
|
|
rjmp next_op
|
|
|
|
op_DEX:
|
|
out SREG,Pstat1 ;restor SREG so carry isnt changed
|
|
dec Xr ;perform dec
|
|
in Pstat1,SREG ;save changed N and Z
|
|
rjmp next_op
|
|
op_NOP: ;nopys
|
|
nop
|
|
nop
|
|
rjmp next_op
|
|
;---------------------------
|
|
;---------------------------
|
|
;---------------------------
|
|
get_value_01: ;MEMORY type decoder for xxxxxx01 opcodes
|
|
andi retL,0b00111000 ;retL still contains opcode, but lsl by one, get mask of memory access type
|
|
;should be a fatser way of doing this with jump tables
|
|
;for now, order with most frequently used at top
|
|
|
|
cpi retL,0b00000000
|
|
breq get_value_ZP_inx_X_indirj
|
|
|
|
cpi retL,0b00001000
|
|
breq get_value_ZPj
|
|
|
|
cpi retL,0b00010000
|
|
breq get_value_imedj
|
|
|
|
cpi retL,0b00011000
|
|
breq get_value_absj
|
|
|
|
cpi retL,0b00100000
|
|
breq get_value_ZP_indir_idx_Yj
|
|
|
|
cpi retL,0b00101000
|
|
breq get_value_ZP_idx_Xj
|
|
|
|
|
|
cpi retL,0b00110000
|
|
breq get_value_ZP_abs_idx_Yj
|
|
|
|
cpi retL,0b00111000
|
|
breq get_value_ZP_abs_idx_Xj
|
|
;---------------------------------
|
|
get_value_10: ;MEMORY type decoder for xxxxxx10 opcodes
|
|
andi retL,0b00111000
|
|
|
|
cpi retL,0b00000000
|
|
breq get_value_imedj
|
|
|
|
cpi retL,0b00001000
|
|
breq get_value_ZPj
|
|
|
|
cpi retL,0b00010000
|
|
breq get_value_accumj
|
|
|
|
cpi retL,0b00011000
|
|
breq get_value_absj
|
|
|
|
cpi retL,0b00101000
|
|
breq get_value_ZP_idx_Xj
|
|
|
|
cpi retL,0b00111000
|
|
breq get_value_ZP_abs_idx_Xj
|
|
|
|
get_value_ZP_inx_X_indirj:
|
|
rjmp get_value_ZP_inx_X_indir
|
|
get_value_ZPj:
|
|
rjmp get_value_ZP
|
|
get_value_imedj:
|
|
rjmp get_value_imed
|
|
get_value_absj:
|
|
rjmp get_value_abs
|
|
get_value_ZP_indir_idx_Yj:
|
|
rjmp get_value_ZP_indir_idx_Y
|
|
get_value_ZP_idx_Xj:
|
|
rjmp get_value_ZP_idx_X
|
|
get_value_ZP_idx_Yj:
|
|
rjmp get_value_ZP_idx_Y
|
|
get_value_ZP_abs_idx_Yj:
|
|
rjmp get_value_ZP_abs_idx_Y
|
|
get_value_ZP_abs_idx_Xj:
|
|
rjmp get_value_ZP_abs_idx_X
|
|
get_value_accumj:
|
|
rjmp get_value_accum
|
|
|
|
;----------------------------
|
|
get_value_ZP_inx_X_indir: ;Zero page index X, indirect
|
|
|
|
ldi YH,ZP_offset ;Zero page, so high byte 0
|
|
get_pc_mem YL ;get next byte into YL
|
|
add YL,Xr
|
|
adc YH,zero_reg
|
|
|
|
ld_cpuYp ZL ;now load Z with indrected address Y
|
|
ld_cpuY ZH
|
|
|
|
ld_cpuZ retL ;load actual value!
|
|
ret
|
|
|
|
|
|
get_value_ZP: ;Zero Page
|
|
|
|
ldi ZH,ZP_offset ;Zero page..
|
|
get_pc_mem ZL ;Get pos in ZP
|
|
|
|
ld_cpuZ retL ;load value
|
|
ret
|
|
|
|
|
|
get_value_imed: ;immediate mode
|
|
get_pc_mem retL
|
|
ret
|
|
|
|
get_value_abs: ;get absolute (one byte)
|
|
get_pc_mem ZL
|
|
get_pc_mem ZH
|
|
|
|
ld_cpuZ retL
|
|
ret
|
|
|
|
get_value_ZP_indir_idx_Y: ;Zero page indirect, indexed Y
|
|
ldi YH,ZP_offset
|
|
get_pc_mem YL
|
|
|
|
ld_cpuYp ZL ;now load Z with indrected address Y
|
|
ld_cpuY ZH
|
|
|
|
add ZL,Yr ;add Y reg for indexing
|
|
adc ZH,zero_reg ;no wrap around on this one
|
|
|
|
ld_cpuZ retL ;load value
|
|
ret
|
|
|
|
get_value_ZP_idx_X: ;Zero page indexd X
|
|
ldi ZH,ZP_offset
|
|
get_pc_mem ZL
|
|
|
|
add ZL,Xr ;add index,
|
|
adc ZH,zero_reg
|
|
|
|
ld_cpuZ retL ;get value
|
|
ret
|
|
|
|
|
|
get_value_ZP_idx_Y: ;Zero page indexd Y (only used with LDX and STX)
|
|
ldi ZH,ZP_offset
|
|
get_pc_mem ZL
|
|
|
|
add ZL,Yr ;add index, with wrap around..humm TODO..?
|
|
adc ZH,zero_reg
|
|
|
|
ld_cpuZ retL ;get value
|
|
ret
|
|
|
|
get_value_ZP_abs_idx_Y: ;absolute, indexd with Y
|
|
get_pc_mem ZL ;get absolut value
|
|
get_pc_mem ZH
|
|
|
|
add ZL,Yr
|
|
adc ZH,zero_reg
|
|
|
|
ld_cpuZ retL
|
|
ret
|
|
|
|
get_value_ZP_abs_idx_X: ;absolute, indexd with X
|
|
get_pc_mem ZL ;get absolut value
|
|
get_pc_mem ZH
|
|
|
|
add ZL,Xr
|
|
adc ZH,zero_reg
|
|
|
|
ld_cpuZ retL
|
|
ret
|
|
|
|
get_value_accum: ;accumulator, Should not use this, there should be special cases for A ops
|
|
|
|
mov retL,A
|
|
ret
|
|
|
|
|
|
|
|
;----------------------------------------------------------------------
|
|
;----------------------------------------------------------------------
|
|
;Branch_take
|
|
|
|
;purpose: if a branch is sucessfull
|
|
;Takes:
|
|
;Give:
|
|
;----------------------------------------------------------------------
|
|
;----------------------------------------------------------------------
|
|
|
|
|
|
Branch_take:
|
|
get_pc_mem r18 ;get branch modifiyer
|
|
|
|
sbrc r18,7 ;gotta go signed 8 bit X 16 bit unsigned
|
|
ldi r17,0xff ;todo FIX, DONT USE R16
|
|
sbrs r18,7
|
|
ldi r17,0
|
|
|
|
add PL,r18
|
|
adc PH,r17
|
|
rjmp next_op
|
|
|
|
|
|
;----------------------------------------------------------------------
|
|
;----------------------------------------------------------------------
|
|
;stack_build TODO: make a macro
|
|
|
|
;purpose: Here teh stack is stored as 2 bytes for speed, in order to store on the stack
|
|
;it must be built into one byte
|
|
;Takes:
|
|
;Give: retL as built stack
|
|
;----------------------------------------------------------------------
|
|
;----------------------------------------------------------------------
|
|
stack_build:
|
|
|
|
mov r16,Pstat1 ;copy byte for bottom 3 bits (C,Z,N)
|
|
andi r16,0b00000111 ;clear top bits
|
|
mov r17,Pstat2
|
|
andi r17,0b11111000
|
|
or r16,r17
|
|
mov retL,r16
|
|
ret
|
|
|
|
|
|
;----------------------------------------------------------------------
|
|
;----------------------------------------------------------------------
|
|
;stack_decomp TODO: make a macro
|
|
|
|
;purpose: reverse of stack_build
|
|
|
|
;Takes: retL
|
|
;Give:
|
|
;----------------------------------------------------------------------
|
|
;----------------------------------------------------------------------
|
|
stack_decomp:
|
|
mov Pstat1,retL
|
|
mov Pstat2,retL
|
|
|
|
ret
|
|
op_INVALID:
|
|
ldi r16,'V'
|
|
rcall rs232_0_tx
|
|
rjmp next_op
|
|
|
|
p: rjmp p
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|