9
0
Fork 0
nuttx-bb/nuttx/configs/xtrs/src/xtrs_head.asm

277 lines
9.3 KiB
NASM

;**************************************************************************
; configs/xtrs/src/xtrs_head.asm
;
; Copyright (C) 2008-2009 Gregory Nutt. All rights reserved.
; Author: Gregory Nutt <spudmonkey@racsa.co.cr>
;
; Redistribution and use in source and binary forms, with or without
; modification, are permitted provided that the following conditions
; are met:
;
; 1. Redistributions of source code must retain the above copyright
; notice, this list of conditions and the following disclaimer.
; 2. Redistributions in binary form must reproduce the above copyright
; notice, this list of conditions and the following disclaimer in
; the documentation and/or other materials provided with the
; distribution.
; 3. Neither the name NuttX nor the names of its contributors may be
; used to endorse or promote products derived from this software
; without specific prior written permission.
;
; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
; FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
; COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
; INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
; BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
; OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
; AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
; LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
; ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
; POSSIBILITY OF SUCH DAMAGE.
;
;**************************************************************************
.title NuttX for the Z80
.module xtrs_head
;**************************************************************************
; Constants
;**************************************************************************
; Register save area layout
XCPT_I == 0 ; Offset 0: Saved I w/interrupt state in parity
XCPT_BC == 2 ; Offset 1: Saved BC register
XCPT_DE == 4 ; Offset 2: Saved DE register
XCPT_IX == 6 ; Offset 3: Saved IX register
XCPT_IY == 8 ; Offset 4: Saved IY register
XCPT_SP == 10 ; Offset 5: Offset to SP at time of interrupt
XCPT_HL == 12 ; Offset 6: Saved HL register
XCPT_AF == 14 ; Offset 7: Saved AF register
XCPT_PC == 16 ; Offset 8: Offset to PC at time of interrupt
; Default stack base (needs to be fixed)
.include "asm_mem.h"
;**************************************************************************
; Global symbols used
;**************************************************************************
.globl _os_start ; OS entry point
.globl _up_doirq ; Interrupt decoding logic
;**************************************************************************
; System start logic
;**************************************************************************
_up_reset:
; Set up the stack pointer at the location determined the Makefile
; and stored in asm_mem.h
ld SP, #CONFIG_STACK_END ; Set stack pointer
; Performed initialization unique to the SDCC toolchain
call gsinit ; Initialize the data section
; Copy the reset vectors
ld hl, #_up_rstvectors ; code for RAM
ld de, #0x4000 ; move it here
ld bc, #3*7 ; 7 vectors / 3 bytes each
ldir
; Then start NuttX
call _os_start ; jump to the OS entry point
; NuttX will never return, but just in case...
_up_halt::
halt ; We should never get here
jp _up_halt
; Data to copy to address 0x4000
_up_rstvectors:
jp _up_rst1 ; 0x4000 : RST 1
jp _up_rst2 ; 0x4003 : RST 2
jp _up_rst3 ; 0x4006 : RST 3
jp _up_rst4 ; 0x4009 : RST 4
jp _up_rst5 ; 0x400c : RST 5
jp _up_rst6 ; 0x400f : RST 6
jp _up_rst7 ; 0x4012 : RST 7
;**************************************************************************
; Other reset handlers
;
; Interrupt mode 1 behavior:
;
; 1. M1 cycle: 7 ticks
; Acknowledge interrupt and decrements SP
; 2. M2 cycle: 3 ticks
; Writes the MS byte of the PC onto the stack and decrements SP
; 3. M3 cycle: 3 ticks
; Writes the LS byte of the PC onto the stack and sets the PC to 0x0038.
;
;**************************************************************************
_up_rst1: ; RST 1
; Save AF on the stack, set the interrupt number and jump to the
; common reset handling logic.
; Offset 8: Return PC is already on the stack
push af ; Offset 7: AF (retaining flags)
ld a, #1 ; 1 = Z80_RST1
jr _up_rstcommon ; Remaining RST handling is common
_up_rst2: ; RST 2
; Save AF on the stack, set the interrupt number and jump to the
; common reset handling logic.
; Offset 8: Return PC is already on the stack
push af ; Offset 7: AF (retaining flags)
ld a, #2 ; 2 = Z80_RST2
jr _up_rstcommon ; Remaining RST handling is common
_up_rst3: ; RST 3
; Save AF on the stack, set the interrupt number and jump to the
; common reset handling logic.
; Offset 8: Return PC is already on the stack
push af ; Offset 7: AF (retaining flags)
ld a, #3 ; 1 = Z80_RST3
jr _up_rstcommon ; Remaining RST handling is common
_up_rst4: ; RST 4
; Save AF on the stack, set the interrupt number and jump to the
; common reset handling logic.
; Offset 8: Return PC is already on the stack
push af ; Offset 7: AF (retaining flags)
ld a, #4 ; 1 = Z80_RST4
jr _up_rstcommon ; Remaining RST handling is common
_up_rst5: ; RST 5
; Save AF on the stack, set the interrupt number and jump to the
; common reset handling logic.
; Offset 8: Return PC is already on the stack
push af ; Offset 7: AF (retaining flags)
ld a, #5 ; 1 = Z80_RST5
jr _up_rstcommon ; Remaining RST handling is common
_up_rst6: ; RST 6
; Save AF on the stack, set the interrupt number and jump to the
; common reset handling logic.
; Offset 8: Return PC is already on the stack
push af ; Offset 7: AF (retaining flags)
ld a, #6 ; 1 = Z80_RST6
jr _up_rstcommon ; Remaining RST handling is common
_up_rst7: ; RST 7
; Save AF on the stack, set the interrupt number and jump to the
; common reset handling logic.
; Offset 8: Return PC is already on the stack
push af ; Offset 7: AF (retaining flags)
ld a, #7 ; 7 = Z80_RST7
jr _up_rstcommon ; Remaining RST handling is common
;**************************************************************************
; Common Interrupt handler
;**************************************************************************
_up_rstcommon:
; Create a register frame. SP points to top of frame + 4, pushes
; decrement the stack pointer. Already have
;
; Offset 8: Return PC is already on the stack
; Offset 7: AF (retaining flags)
;
; IRQ number is in A
push hl ; Offset 6: HL
ld hl, #(3*2) ; HL is the value of the stack pointer before
add hl, sp ; the interrupt occurred
push hl ; Offset 5: Stack pointer
push iy ; Offset 4: IY
push ix ; Offset 3: IX
push de ; Offset 2: DE
push bc ; Offset 1: BC
ld b, a ; Save the reset number in B
ld a, i ; Parity bit holds interrupt state
push af ; Offset 0: I with interrupt state in parity
di
; Call the interrupt decode logic. SP points to the beggining of the reg structure
ld hl, #0 ; Argument #2 is the beginning of the reg structure
add hl, sp ;
push hl ; Place argument #2 at the top of stack
push bc ; Argument #1 is the Reset number
inc sp ; (make byte sized)
call _up_doirq ; Decode the IRQ
; On return, HL points to the beginning of the reg structure to restore
; Note that (1) the arguments pushed on the stack are not popped, and (2) the
; original stack pointer is lost. In the normal case (no context switch),
; HL will contain the value of the SP before the arguments wer pushed.
ld sp, hl ; Use the new stack pointer
; Restore registers. HL points to the beginning of the reg structure to restore
ex af, af' ; Select alternate AF
pop af ; Offset 0: AF' = I with interrupt state in parity
ex af, af' ; Restore original AF
pop bc ; Offset 1: BC
pop de ; Offset 2: DE
pop ix ; Offset 3: IX
pop iy ; Offset 4: IY
exx ; Use alternate BC/DE/HL
ld hl, #-2 ; Offset of SP to account for ret addr on stack
pop de ; Offset 5: HL' = Stack pointer after return
add hl, de ; HL = Stack pointer value before return
exx ; Restore original BC/DE/HL
pop hl ; Offset 6: HL
pop af ; Offset 7: AF
; Restore the stack pointer
exx ; Use alternate BC/DE/HL
ld sp, hl ; Set SP = saved stack pointer value before return
exx ; Restore original BC/DE/HL
; Restore interrupt state
ex af, af' ; Recover interrupt state
jp po, nointenable ; Odd parity, IFF2=0, means disabled
ex af, af' ; Restore AF (before enabling interrupts)
ei ; yes
reti
nointenable::
ex af, af' ; Restore AF
reti
;**************************************************************************
; Ordering of segments for the linker (SDCC only)
;**************************************************************************
.area _HOME
.area _CODE
.area _GSINIT
.area _GSFINAL
.area _DATA
.area _BSS
.area _HEAP
;**************************************************************************
; Global data initialization logic (SDCC only)
;**************************************************************************
.area _GSINIT
gsinit::
.area _GSFINAL
ret