summaryrefslogtreecommitdiff
path: root/nuttx/arch/z80/src/ez80/ez80_vectors.asm
blob: 3e3d44ced678a6618f6592ebc2fb6947e0aa9fa1 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
;**************************************************************************
; arch/z80/src/ez80/ez80_vectors.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.
;
;**************************************************************************

;**************************************************************************
; Constants
;**************************************************************************

NVECTORS	EQU	64		; max possible interrupt vectors

;* Bits in the Z80 FLAGS register *****************************************

EZ80_C_FLAG	EQU	01h		; Bit 0: Carry flag
EZ80_N_FLAG	EQU	02h		; Bit 1: Add/Subtract flag
EZ80_PV_FLAG	EQU	04h		; Bit 2: Parity/Overflow flag
EZ80_H_FLAG	EQU	10h		; Bit 4: Half carry flag
EZ80_Z_FLAG	EQU	40h		; Bit 5: Zero flag
EZ80_S_FLAG	EQU	80h		; Bit 7: Sign flag

;* The IRQ number to use for unused vectors

EZ80_UNUSED	EQU	40h

;**************************************************************************
; 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

;**************************************************************************
; 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
;**************************************************************************

					; Symbol           Val VecNo Addr
					;----------------- --- ----- -----
_ez80_handlers:
	irqhandler	 0		; EZ80_EMACRX_IRQ   0    0   0x040   
	handlersize equ $-_ez80handlers
	irqhandler	 1		; EZ80_EMACTX_IRQ   1    1   0x044   
	irqhandler	 2		; EZ80_EMACSYS_IRQ  2    2   0x048   
	irqhandler	 3		; EZ80_PLL_IRQ      3    3   0x04c   
	irqhandler	 4		; EZ80_FLASH_IRQ    4    4   0x050   
	irqhandler	 5		; EZ80_TIMER0_IRQ   5    5   0x054   
	irqhandler	 6		; EZ80_TIMER1_IRQ   6    6   0x058   
	irqhandler	 7		; EZ80_TIMER2_IRQ   7    7   0x05c   
	irqhandler	 8		; EZ80_TIMER3_IRQ   8    8   0x060   
	irqhandler	EZ80_UNUSED	;                        9   0x064   
	irqhandler	EZ80_UNUSED+1	;                       10   0x068   
	irqhandler	 9		; EZ80_RTC_IRQ      9   11   0x06C   
	irqhandler	10		; EZ80_UART0_IRQ   10   12   0x070   
	irqhandler	11		; EZ80_UART1_IRQ   11   13   0x074   
	irqhandler	12		; EZ80_I2C_IRQ     12   14   0x078   
	irqhandler	13		; EZ80_SPI_IRQ     13   15   0x07c   
	irqhandler	14		; EZ80_PORTA0_IRQ  14   16   0x080   
	irqhandler	15		; EZ80_PORTA1_IRQ  15   17   0x084   
	irqhandler	16		; EZ80_PORTA2_IRQ  16   18   0x088   
	irqhandler	17		; EZ80_PORTA3_IRQ  17   19   0x08c   
	irqhandler	18		; EZ80_PORTA4_IRQ  18   20   0x090   
	irqhandler	19		; EZ80_PORTA5_IRQ  19   21   0x094   
	irqhandler	20		; EZ80_PORTA6_IRQ  20   22   0x098   
	irqhandler	21		; EZ80_PORTA7_IRQ  21   23   0x09c   
	irqhandler	22		; EZ80_PORTB0_IRQ  22   24   0x0a0   
	irqhandler	23		; EZ80_PORTB1_IRQ  23   25   0x0a4   
	irqhandler	24		; EZ80_PORTB2_IRQ  24   26   0x0a8   
	irqhandler	25		; EZ80_PORTB3_IRQ  25   27   0x0ac   
	irqhandler	26		; EZ80_PORTB4_IRQ  26   28   0x0b0   
	irqhandler	27		; EZ80_PORTB5_IRQ  27   29   0x0b4   
	irqhandler	28		; EZ80_PORTB6_IRQ  28   20   0x0b8   
	irqhandler	29		; EZ80_PORTB7_IRQ  29   21   0x0bc   
	irqhandler	30		; EZ80_PORTC0_IRQ  30   22   0x0c0   
	irqhandler	31		; EZ80_PORTC1_IRQ  31   23   0x0c4   
	irqhandler	32		; EZ80_PORTC2_IRQ  32   24   0x0c8   
	irqhandler	33		; EZ80_PORTC3_IRQ  33   25   0x0cc   
	irqhandler	34		; EZ80_PORTC4_IRQ  34   26   0x0d0   
	irqhandler	35		; EZ80_PORTC5_IRQ  35   27   0x0d4   
	irqhandler	36		; EZ80_PORTC6_IRQ  36   28   0x0d8   
	irqhandler	37		; EZ80_PORTC7_IRQ  37   29   0x0dc   
	irqhandler	38		; EZ80_PORTD0_IRQ  38   40   0x0e0   
	irqhandler	39		; EZ80_PORTD1_IRQ  39   41   0x0e4   
	irqhandler	40		; EZ80_PORTD2_IRQ  40   42   0x0e8   
	irqhandler	41		; EZ80_PORTD3_IRQ  41   43   0x0ec   
	irqhandler	42		; EZ80_PORTD4_IRQ  42   44   0x0f0   
	irqhandler	43		; EZ80_PORTD5_IRQ  43   45   0x0f4   
	irqhandler	44		; EZ80_PORTD6_IRQ  44   46   0x0f8   
	irqhandler	45		; EZ80_PORTD7_IRQ  45   47   0x0fc   
	irqhandler	EZ80_UNUSED+1	;                       48   0x100   
	irqhandler	EZ80_UNUSED+2	;                       49   0x104   
	irqhandler	EZ80_UNUSED+3	;                       50   0x108   
	irqhandler	EZ80_UNUSED+4	;                       51   0x10c   
	irqhandler	EZ80_UNUSED+5	;                       52   0x110   
	irqhandler	EZ80_UNUSED+6	;                       53   0x114   
	irqhandler	EZ80_UNUSED+7	;                       54   0x118   
	irqhandler	EZ80_UNUSED+8	;                       55   0x11c   
	irqhandler	EZ80_UNUSED+9	;                       56   0x120   
	irqhandler	EZ80_UNUSED+10	;                       57   0x124   
	irqhandler	EZ80_UNUSED+11	;                       58   0x128   
	irqhandler	EZ80_UNUSED+12	;                       59   0x12c   
	irqhandler	EZ80_UNUSED+13	;                       60   0x130   
	irqhandler	EZ80_UNUSED+14	;                       61   0x134   
	irqhandler	EZ80_UNUSED+15	;                       62   0x138   
	irqhandler	EZ80_UNUSED+16	;                       63   0x13c   

;**************************************************************************
; 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*3)		;    HL is the value of the stack pointer before
	add	hl, sp			;    the interrupt occurred (3 for PC, AF, HL)
	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

	; At this point, we know that interrupts were enabled (or we wouldn't be here
	; so we can save a fake indicationn that will cause interrupts to restored when
	; this context is restored

	ld	bc, #EZ80_PV_FLAG	; Parity bit.  1=parity odd, IEF2=1
	push	bc			; Offset 0: I with interrupt state in parity
	di				; (not necessary)

	; 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
        ld      bc, #0			; BC = reset number
	ld	c, a			;   Save the reset number in C
	push	bc			; Argument #1 is the Reset number
	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 were 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
	pop	hl			; Offset 5: HL' = Stack pointer after 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
	pop	de			; Offset 8: Return address
	ld	sp, hl			; Set SP = saved stack pointer value before return
	push	de			; Set up for reti
	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

;**************************************************************************
; Vector Setup Logic
;**************************************************************************

_ez80_initvectors:
	; Initialize the vector table

	ld	iy, _ez80_vectable
	ld	ix, 4
	ld	bc, 4
	ld	b, NVECTORS
	xor	a, a			; Clear carry
	ld	hl, handlersize
	ld	de, _ez80_handlers
	sbc	hl, de			; Length of irq handler in hl
	ld	d, h
	ld	e, l
	ld	hl, _ez80_handlers 	; Start of handlers in hl

	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
	push	de
	ld	de, 4
	add	iy, de			; Point to next entry in vector table
	pop	de
	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

	; The first 64 bytes are not used... the vectors actually start at +0x40
_ez80_vecreserve:
	ds	64
_ez80_vectable:
	ds	NVECTORS * 4