⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 arch_a.s

📁 picoos源码。The RTOS and the TCP/IP stack will be built automatically.
💻 S
📖 第 1 页 / 共 2 页
字号:
;
; ---------------------------------------------------------------

.proc  _p_pos_intContextSwitch

    ; -- swap context variable --

    ; posCurrentTask_g = posNextTask_g
    lda     _posNextTask_g
    ldx     _posNextTask_g+1
    sta     _posCurrentTask_g
    stx     _posCurrentTask_g+1

    ; -- restore context of next task --

    ; load  sp = posCurrentTask_g
    sta     sp
    stx     sp+1

    ; load new csp
    ldy     #$00
    lda     (sp),y
    tax
    txs

    ; load new dsp to temp
    iny
    lda     (sp),y
    sta     _saved_sp
    iny
    lda     (sp),y
    sta     _saved_sp+1

    ; copy cstack frame from dstack when slow task is detected

    ; test task->cstacknbr
    ldy     #$05
    lda     (sp),y
    cmp     #snbr_sflag
    bne     ics05

    ; get ptr to save area on dstack
    ; ptr1 = task->dstackroot - csp
    dey
    lda     (sp),y
    sta     ptr1+1
    dey
    lda     (sp),y
;    tsx  - x has still the value of sp
    stx     ptr1
    sec
    sbc     ptr1
    sta     ptr1
    bcs     ics06
    dec     ptr1+1
ics06:

    ; calculate count of bytes to copy
    txa
    tay
    and     #cstacksize - 1
    eor     #cstacksize - 1
    beq     ics05
    tax

    ; copy bytes
ics07:
    lda     (ptr1),y
    sta     $0101,y
    iny
    dex
    bne     ics07

ics05:
    jmp     return_from_irq

.endproc



; ---------------------------------------------------------------
;
; Return from interrupt (finally do a context switch)
;
; This function does:
;   -  restore the zeropage environment
;   -  return from interrupt (=context switch)  OR
;   -  call original C64 timer interrupt and do the ctx switch
;
; Note: 
;   -  _saved_sp must point to original sp
;   -  sp must point to current task environment
;
; ---------------------------------------------------------------

.proc  return_from_irq

    ; get ptr:  sp = task->savedzp
    lda     sp
    clc
    adc     #$07
    sta     sp
    bcc     rfi01
    inc     sp+1
rfi01:

    ; store zero page content
    ldy     #zpsize-3
rfi02:
    lda     (sp),y
    sta     sp+2,y
    dey
    bpl     rfi02

    ; set dsp
    lda     _saved_sp
    ldx     _saved_sp+1
    sta     sp
    stx     sp+1

    ; back to next context
    lda     _doorgirq
    bne     rfi03
    pla
    tay
    pla
    tax
    pla
    rti

    ;C64: call original irq handler if requested
rfi03:
    lda     #$00
    sta     _doorgirq
    jmp     (_orgC64irqvect)

.endproc



; ---------------------------------------------------------------
;
; Timer interrupt service routine
;
; Steps that are performed:
;   1. save flags and CPU registers to processor stack
;   2. if we are not yet in an interrupt (_posInInterrupt_g == 0),
;      we save the context of the current task:
;        - save processor stack pointer
;        - save data stack pointer
;        - save current zeropage environment
;        - save processor stack frame into data stack
;          if the currently running task has no own
;          dedicated processor stack
;   3. call _c_pos_intEnter
;   4. call _c_pos_timerInterrupt
;   5. call original interrupt handler (C64 only)
;   6. call _c_pos_intExit
;   7. restore last context and return from interrupt
;
; ---------------------------------------------------------------

.proc  p_timerisr

;-> This code is left out on a C64, since it is
;   already done by the isr in the kernal
;    pha
;    txa
;    pha
;    tya
;    pha

    ; -- test if we are not in an interrupt --
    ; Note:
    ; On C64 posInInterrupt_g is always 0.
    ; With the CC65 compiler we have a stack problem:
    ; When this ISR is interrupted, the stack will be destroyed.
    ; So we optimize this code for C64 w/ CC65: simply remove it.

;    lda     _posInInterrupt_g
;    bne     tmi02

    ; -- save context of current task --

    ; save sp
    lda     sp
    ldy     sp+1
    sta     _saved_sp
    sty     _saved_sp+1

    ; get ptr:  sp = task->cstackptr
    lda     _posCurrentTask_g
    ldy     _posCurrentTask_g+1
    sta     sp
    sty     sp+1
    ldy     #$00

    ; store current csp:  *sp = csp
    tsx
    txa
    sta     (sp),y

    ; get ptr:  sp = task->dstackptr
    iny

    ; store current dsp:  *sp = dsp
    lda     _saved_sp
    sta     (sp),y
    iny
    lda     _saved_sp+1
    sta     (sp),y

    ; x = task->cstacknbr
    ldy     #$05
    lda     (sp),y
    tax

    ; get ptr:  sp = task->savedzp
    lda     sp
    clc
    adc     #$07
    sta     sp
    bcc     tmi00
    inc     sp+1
tmi00:

    ; store zero page content
    ldy     #zpsize-3
tmi01:
    lda     sp+2,y
    sta     (sp),y
    dey
    bpl     tmi01

    ; copy cstack frame to dstack when slow task is detected

    ; test task->cstacknbr
    cpx     #snbr_sflag
    bne     tmi02

    ; get ptr to save area on dstack
    ; ptr1 = task->dstackroot - csp
    lda     _posCurrentTask_g
    ldy     _posCurrentTask_g+1
    sta     sp
    sty     sp+1
    ldy     #$04
    lda     (sp),y
    sta     ptr1+1
    dey
    lda     (sp),y
    tsx
    stx     ptr1
    sec
    sbc     ptr1
    sta     ptr1
    bcs     tmi03
    dec     ptr1+1
tmi03:

    ; calculate count of bytes to copy
    txa
    tay
    and     #cstacksize - 1
    eor     #cstacksize - 1
    beq     tmi02
    tax

    ; copy bytes
tmi04:
    lda     $0101,y
    sta     (ptr1),y
    iny
    dex
    bne     tmi04

tmi02:

    ; Set up a data stack for the isr.
    ; This is required for the CC65 compiler.
    lda     #<(_isrstack + (isrstacksize - 1))
    ldx     #>(_isrstack + (isrstacksize - 1))
    sta     sp
    stx     sp+1

    ; -- pico]OS interrupt code --

    ; call pico]OS:  c_pos_intEnter()
    jsr     _c_pos_intEnter

    ; get character from keyboard buffer
.IF NOS_KEYINPUT
    lda     KEY_COUNT
    beq     tmi05
    dec     KEY_COUNT
    lda     KEY_BUF
    ldx     KEY_BUF+1
    stx     KEY_BUF
    jsr     pusha
    jsr     _c_nos_keyinput
tmi05:
.ENDIF

    ; call pico]OS:  c_pos_timerInterrupt()
    jsr     _c_pos_timerInterrupt

    ; only C64: remember to call original timer irq handler
    inc     _doorgirq

    ; call pico]OS:  c_pos_intExit()
    jsr     _c_pos_intExit

    ; -- leave interrupt --

    ; we must restore the zeropage environment here

    ; get ptr
    lda     _posCurrentTask_g
    ldx     _posCurrentTask_g+1
    sta     sp
    stx     sp+1

    ; load dsp to temp
    ldy     #$01
    lda     (sp),y
    sta     _saved_sp
    iny
    lda     (sp),y
    sta     _saved_sp+1

    ; return
    jmp     return_from_irq

.endproc



; ---------------------------------------------------------------
;
; Initialize timer interrupt.
;
; This function is special to the C64.
; The timer is executed 60 times per second.
; The ISR will divide it down to 30 timer interrupts per second.
;
; ---------------------------------------------------------------

.proc  _p_start_timer

    ; disable interrupts
    php
    sei

    ; save original interrupt vector
    lda     C64IRQVECT
    ldx     C64IRQVECT+1
    sta     _orgC64irqvect
    stx     _orgC64irqvect+1

    ; set new vector
    lda     #<mytimerisr
    ldx     #>mytimerisr
    sta     C64IRQVECT
    stx     C64IRQVECT+1

    ; clear flag
    lda     #$00
    sta     _doorgirq

.IF NOS_KEYINPUT
    ; clear keyboard buffer
    sta     KEY_COUNT
.ENDIF

    ; enable interrupts and return
    plp
    rts


    ; timer interrupt service routine
mytimerisr:

    ; divide timer ticks by 2
    inc     _tmrdiv
    lda     _tmrdiv
    lsr
    bcc     orgisr

    ; call timer isr 30 times per second
    jmp     p_timerisr

orgisr:
    jmp     (_orgC64irqvect)

.endproc



; ---------------------------------------------------------------
; UVAR_t p_pos_findbit (const UVAR_t bitfield, UVAR_t rrOffset)
; ---------------------------------------------------------------

.proc _p_pos_findbit
    ldy     #$00
    lda     (sp),y
    tax
    iny
    lda     (sp),y
    ;accu = bitfield
    ;x = offset

    stx     ptr1   ;store to temp. memory
    inx
    clc

offsetLoop:
    ror
    dex
    bne     offsetLoop

    ldx     ptr1
    bcs     bitFound

nextBitLoop:
    inx
    ror
    bcc     nextBitLoop

bitFound:
    txa
    cmp     #8
    bcs     correctOffset

    ; return a
    jmp     incsp2
         
correctOffset:  
    sbc     #9
    ; return a
    jmp     incsp2

.endproc

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -