nuttx/arch/z80/src/ez80/ez80_vectors.asm
patacongo f44cb412d1 More ez80 files compile
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@739 42af7a65-404d-4744-a932-0658087f49c3
2008-03-18 01:40:12 +00:00

323 lines
9.1 KiB
NASM

;**************************************************************************
; arch/z80/src/ez80/ez80_vectors.asm
;
; Copyright (C) 2008 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.
;
;**************************************************************************
;**************************************************************************
; Constants
;**************************************************************************
NVECTORS EQU 64 ; max possible interrupt vectors
;**************************************************************************
; Global Symbols Imported
;**************************************************************************
xref _ez80_startup
xref _up_doirq
;**************************************************************************
; Global Symbols Exported
;**************************************************************************
xdef _ez80_reset
xdef _ez80_initvectors
xdef _ez80_handlers
xdef _ez80_rstcommon
xdef _ez80_initvectors
xdef _ez80_vectable
;**************************************************************************
; Macros
;**************************************************************************
; Define one reset handler
; 1. Disable interrupts
; 2. Dlear mixed memory mode (MADL) flag
; 3. jump to initialization procedure with jp.lil to set ADL
rstvector: macro
di
rsmix
jp.lil _ez80_startup
endmac rstvector
; Define one interrupt handler
irqhandler: macro vectno
; 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, #vectno ; A = vector number
jp _ez80_rstcommon ; Remaining RST handling is common
endmac irqhandler
; Save Interrupt State
irqsave: macro
ld a, i ; sets parity bit to value of IEF2
push af
di ; disable interrupts while loading table
endmac irqsave
; Restore Interrupt State
irqrestore: macro
pop af
jp po, $+5 ; parity bit is IEF2
ei
endmac irqrestore
;**************************************************************************
; Reset entry points
;**************************************************************************
define .RESET, space = ROM
segment .RESET
_ez80_reset:
_rst0:
rstvector
_rst8:
rstvector
_rst10:
rstvector
_rst18:
rstvector
_rst20:
rstvector
_rst28:
rstvector
_rst30:
rstvector
_rst38:
rstvector
ds %26
_nmi:
retn
;**************************************************************************
; Startup logic
;**************************************************************************
define .STARTUP, space = ROM
segment .STARTUP
.assume ADL=1
;**************************************************************************
; Interrupt Vector Handling
;**************************************************************************
_ez80_handlers:
irqhandler 0
handlersize equ $-_ez80handlers
irqhandler 1
irqhandler 2
irqhandler 3
irqhandler 4
irqhandler 5
irqhandler 6
irqhandler 7
irqhandler 8
irqhandler 9
irqhandler 10
irqhandler 11
irqhandler 12
irqhandler 13
irqhandler 14
irqhandler 15
irqhandler 16
irqhandler 17
irqhandler 18
irqhandler 19
irqhandler 20
irqhandler 21
irqhandler 22
irqhandler 23
irqhandler 24
irqhandler 25
irqhandler 26
irqhandler 27
irqhandler 28
irqhandler 29
irqhandler 30
irqhandler 31
irqhandler 32
irqhandler 33
irqhandler 34
irqhandler 35
irqhandler 36
irqhandler 37
irqhandler 38
irqhandler 39
irqhandler 40
irqhandler 41
irqhandler 42
irqhandler 43
irqhandler 44
irqhandler 45
irqhandler 46
irqhandler 47
irqhandler 48
irqhandler 49
irqhandler 50
irqhandler 51
irqhandler 52
irqhandler 53
irqhandler 54
irqhandler 55
irqhandler 56
irqhandler 57
irqhandler 58
irqhandler 59
irqhandler 60
irqhandler 61
irqhandler 62
irqhandler 63
;**************************************************************************
; Common Interrupt handler
;**************************************************************************
_ez80_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 ; Carry bit holds interrupt state
push af ; Offset 0: I with interrupt state in carry
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 carry
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
jr nc, nointenable ; No carry, IFF2=0, means disabled
ex af, af' ; Restore AF (before enabling interrupts)
ei ; yes
reti
nointenable:
ex af, af' ; Restore AF
reti
;**************************************************************************
; Vector Setup Logic
;**************************************************************************
_ez80_initvectors:
; Initialize the vector table
ld iy, _ez80_vectable
ld bc, 4
ld b, NVECTORS
ld hl, _ez80_handlers
ld de, handlersize
ld a, 0
$1:
ld (iy), hl ; Store IRQ handler
ld (iy+3), a ; Pad to 4 bytes
add hl, de ; Point to next handler
add iy, bc ; Point to next entry in vector table
djnz $1 ; Loop until all vectors have been written
; Select interrupt mode 2
im 2 ; Interrupt mode 2
; Write the address of the vector table into the interrupt vector base
ld hl, _ez80_vectable >> 8
ld i, hl
ret
;**************************************************************************
; Vector Table
;**************************************************************************
; This segment must be aligned on a 512 byte boundary anywhere in RAM
; Each entry will be a 3-byte address in a 4-byte space
define .IVECTS, space = RAM, align = 200h
segment .IVECTS
_ez80_vectable:
ds NVECTORS * 4