Files
super6502/sw/kernel/devices/interrupt_controller.s
2023-11-21 08:17:36 -08:00

134 lines
2.3 KiB
ArmAsm

.MACPACK generic
.autoimport
.importzp tmp1, tmp2
.export _init_interrupt_controller
.export _enable_irq
.export _disable_irq
.export _send_eoi
IRQ_CMD_ADDR = $effc
IRQ_DAT_ADDR = $effd
IRQ_CMD_MASK = $e0
IRQ_REG_MASK = $1f
IRQ_CMD_READIRQ = $00
IRQ_CMD_ENABLE = $20
IRQ_CMD_TYPE = $40
IRQ_CMD_EOI = $ff
.code
; void init_irq();
; mask all IRQs, set all type to edge.
.proc _init_interrupt_controller
ldx #$20 ; enable
ldy #00
jsr cmd_all
ldx #$40 ; edge type
ldy #$00
jsr cmd_all
rts
cmd_all: ; Send the same value to all 32 bytes
txa
add #$10
sta tmp1
loop:
txa
sta IRQ_CMD_ADDR
tya
sta IRQ_DAT_ADDR
inx
cpx tmp1
blt loop
rts
.endproc
; void enable_irq(uint8_t type, uint8_t irqnum);
; in A:
.proc _enable_irq
; Decide which byte we need to modify by dividing by 8 (>> 3)
pha
lsr
lsr
lsr ; A is now bytesel
sta tmp2 ; tmp2 is now bytesel
add #IRQ_CMD_ENABLE
sta IRQ_CMD_ADDR
lda IRQ_DAT_ADDR
sta tmp1
pla
and #$07 ; A is now 0-7
tax
inx ; X is now 1-8
lda #$01
L1: dex
beq L2
asl
bra L1
L2: pha ; Push bit mask to stack
ora tmp1 ; A is now 1 << (0-7) | enable
sta IRQ_DAT_ADDR
lda tmp2
add #IRQ_CMD_TYPE
sta IRQ_CMD_ADDR
lda IRQ_DAT_ADDR
sta tmp1
jsr popa ; A is now type
beq bit0
bit1: ; set `bit` to 1
pla
ora tmp1
bra L3
bit0: ; set `bit` to 0
pla
eor #$ff
and tmp1
L3: sta IRQ_DAT_ADDR
rts
.endproc
; TODO this is mostly the same as enable, why copy?
.proc _disable_irq
; Decide which byte we need to modify by dividing by 32 (>> 5)
pha
lsr
lsr
lsr ; A is now bytesel
add #IRQ_CMD_ENABLE
sta IRQ_CMD_ADDR
lda IRQ_DAT_ADDR
sta tmp1
pla
and $07 ; A is now 0-7
tax
inx ; X is now 1-8
lda #$01
L1: dex
beq L2
asl
bra L1
L2: eor #$ff ; Invert to set enable to 0
and tmp1 ; a is now ~(1 << (0-7)) & enable
sta IRQ_DAT_ADDR
rts
.endproc
; This should accept irqnum later.
; void send_eoi();
.proc _send_eoi
lda #IRQ_CMD_EOI
sta IRQ_CMD_ADDR
lda #$1
sta IRQ_DAT_ADDR
rts
.endproc