source: trunk/softs/giet_tsar/giet.S

Last change on this file was 744, checked in by cfuguet, 12 years ago

giet_tsar: using CLUSTER_IO constant in stdio functions

  • Erasing also extra end-of-line spaces
File size: 17.4 KB
Line 
1/********************************************************************************
2* File : giet.S
3* Author : Alain Greiner
4* Date : 15/01/2014
5*********************************************************************************
6* This is a very simple Interrupts/Exception/Traps handler for a generic
7* multi-clusters / multi-processors TSAR architecture (up to 256 clusters,
8* up to 4 processors per cluster).
9* The physical address is 40 bits, and the 8 MSB bits A[39:32] define the
10* cluster index.
11********************************************************************************/
12
13#include "hard_config.h"
14
15 .section .giet,"ax",@progbits
16 .align 2
17 .global _interrupt_vector
18
19 .extern seg_xcu_base
20 .extern seg_tty_base
21
22 .extern _procid
23 .extern _proctime
24 .extern _tty_write
25 .extern _tty_read
26 .extern _tty_read_irq
27 .extern _locks_read
28 .extern _locks_write
29 .extern _exit
30 .extern _fb_sync_write
31 .extern _fb_sync_read
32 .extern _ioc_write
33 .extern _ioc_read
34 .extern _ioc_completed
35 .extern _itoa_hex
36 .extern _barrier_init
37 .extern _barrier_wait
38
39 .ent _giet
40
41/****************************************************************
42* Cause Table (indexed by the Cause register)
43****************************************************************/
44tab_causes:
45 .word _int_handler /* 0000 : external interrupt */
46 .word _cause_ukn /* 0001 : undefined exception */
47 .word _cause_ukn /* 0010 : undefined exception */
48 .word _cause_ukn /* 0011 : undefined exception */
49 .word _cause_adel /* 0100 : illegal address read exception */
50 .word _cause_ades /* 0101 : illegal address write exception */
51 .word _cause_ibe /* 0110 : instruction bus error exception */
52 .word _cause_dbe /* 0111 : data bus error exception */
53 .word _sys_handler /* 1000 : system call */
54 .word _cause_bp /* 1001 : breakpoint exception */
55 .word _cause_ri /* 1010 : illegal codop exception */
56 .word _cause_cpu /* 1011 : illegal coprocessor access */
57 .word _cause_ovf /* 1100 : arithmetic overflow exception */
58 .word _cause_ukn /* 1101 : undefined exception */
59 .word _cause_ukn /* 1110 : undefined exception */
60 .word _cause_ukn /* 1111 : undefined exception */
61
62 .space 320
63
64/****************************************************************
65* Entry point (base + 0x180)
66****************************************************************/
67_giet:
68 mfc0 $27, $13 /* Cause Register analysis */
69 la $26, seg_kcode_base /* $26 <= tab_causes */
70 andi $27, $27, 0x3c
71 addu $26, $26, $27 /* $26 <= &tab_causes[XCODE] */
72 lw $26, ($26)
73 jr $26 /* Jump to tab_causes[XCODE] */
74
75 .end _giet
76
77/****************************************************************
78* System Call Handler
79*
80* As the GIET_TSAR does not support system calls,
81* an error message is displayed on TTY0, the program is killed.
82****************************************************************/
83 .ent _sys_handler
84
85_sys_handler:
86 la $4, _msg_uknsyscall /* $4 <= message address */
87 li $5, 36 /* $5 <= message length */
88 li $6, 0 /* $6 <= TTY0 */
89 jal _tty_write /* print unknown message */
90 nop
91
92 la $4, _msg_epc /* $4 <= message address */
93 li $5, 8 /* $5 <= message length */
94 li $6, 0 /* $6 <= TTY0 */
95 jal _tty_write /* print EPC message */
96 nop
97
98 mfc0 $4, $14 /* $4 <= EPC */
99 la $5, _itoa_buffer /* $5 <= buffer address */
100 addiu $5, $5, 2 /* skip the 0x prefix */
101 jal _itoa_hex /* fill the buffer */
102 nop
103
104 la $4, _itoa_buffer /* $4 <= buffer address */
105 li $5, 10 /* $5 <= buffer length */
106 li $6, 0 /* $6 <= TTY0 */
107 jal _tty_write /* print EPC value */
108 nop
109
110 j _exit /* end of program */
111
112_itoa_buffer: .ascii "0x00000000"
113
114 .align 2
115
116 .end _sys_handler
117
118/****************************************************************
119* Interrupt Handler
120* This simple interrupt handler cannot be interrupted.
121* It uses the SoCLib VCI_XICU component.
122* It makes the assumption that there is only one interrupt per
123* entry in the interrupt vector (it can be PTI, HWI, or WTI).
124* In case of a multi-clusters architecture, it exist one XCU
125* per cluster, and the base address of the ICU segment depends
126* on both the cluster_xy and the proc_id:
127* - base_address = seg_xcu_base + (32*local_id) + (4G*cluster_xy)
128* - cluster_xy = proc_id / NB_PROCS_MAX
129* - local_id = proc_id % NB_PROCS_MAX
130* If no active interrupt is found in the PRIO register,
131* nothing is done.
132* The interrupt vector (32 ISR addresses array stored at
133* _interrupt_vector address) is initialised with the default
134* ISR address. The actual ISR addresses are supposed to be written
135* in the interrupt vector array by the boot code.
136* All non persistant registers, such as $1 to $15, and $24 to $25,
137* as well as register $31 and EPC, are saved in the interrupted
138* program stack, before calling the Interrupt Service Routine.
139* These registers can be used by the ISR code.
140***************************************************************/
141 .ent _int_handler
142
143_int_handler:
144 addiu $29, $29, -23*4 /* stack space reservation */
145 .set noat
146 sw $1, 4*4($29) /* save $1 */
147 .set at
148 sw $2, 4*5($29) /* save $2 */
149 sw $3, 4*6($29) /* save $3 */
150 sw $4, 4*7($29) /* save $4 */
151 sw $5, 4*8($29) /* save $5 */
152 sw $6, 4*9($29) /* save $6 */
153 sw $7, 4*10($29) /* save $7 */
154 sw $8, 4*11($29) /* save $8 */
155 sw $9, 4*12($29) /* save $9 */
156 sw $10, 4*13($29) /* save $10 */
157 sw $11, 4*14($29) /* save $11 */
158 sw $12, 4*15($29) /* save $12 */
159 sw $13, 4*16($29) /* save $13 */
160 sw $14, 4*17($29) /* save $14 */
161 sw $15, 4*18($29) /* save $15 */
162 sw $24, 4*19($29) /* save $24 */
163 sw $25, 4*20($29) /* save $25 */
164 sw $31, 4*21($29) /* save $31 */
165 mfc0 $27, $14
166 sw $27, 4*22($29) /* save EPC */
167
168 /* XICU PRIO register address computation */
169 /* It depends on both the cluster_xy & local_id, */
170 /* and we must use the physical address extension */
171 mfc0 $10, $15, 1 /* $10 <= proc_id */
172 andi $10, $10, 0x3FF /* at most 1024 processors */
173 li $11, NB_PROCS_MAX
174 divu $10, $11
175 mflo $12 /* $12 <= cluster_xy */
176 mfhi $13 /* $13 <= local_id */
177 la $14, seg_xcu_base /* $14 <= seg_xcu_base */
178
179 li $7, 0b011110000000 /* $7 <= PRIO offset */
180 sll $8, $13, 2 /* $8 <= local_id*4 */
181 addu $9, $7, $8 /* $9 <= PRIO offset + local_id*4 */
182 addu $26, $9, $14 /* $26 <= seg_icu_base + PRIO offset + local_id*4 */
183
184 /* XCU[cluster_xy] access to get PRIO register value */
185 mtc2 $12, $24 /* set PADDR extension */
186 lw $15, 0($26) /* $15 <= PRIO register value */
187 mtc2 $0, $24 /* reset PADDR extension */
188
189 /* test PTI, then HWI, then WTI */
190 andi $27, $15, 0x1 /* test bit T in PRIO register */
191 bne $27, $0, _int_PTI /* branch to PTI handler */
192 andi $27, $15, 0x2 /* test bit W in PRIO register */
193 bne $27, $0, _int_HWI /* branch to HWI handler */
194 andi $27, $15, 0x4 /* test bit W in PRIO register */
195 bne $27, $0, _int_WTI /* branch to WTI handler */
196
197 /* exit interrupt handler: restore registers */
198_int_restore:
199 .set noat
200 lw $1, 4*4($29)
201 .set at
202 lw $2, 4*5($29)
203 lw $3, 4*6($29)
204 lw $4, 4*7($29)
205 lw $5, 4*8($29)
206 lw $6, 4*9($29)
207 lw $7, 4*10($29)
208 lw $8, 4*11($29)
209 lw $9, 4*12($29)
210 lw $10, 4*13($29)
211 lw $11, 4*14($29)
212 lw $12, 4*15($29)
213 lw $13, 4*16($29)
214 lw $14, 4*17($29)
215 lw $15, 4*18($29)
216 lw $24, 4*19($29)
217 lw $25, 4*20($29)
218 lw $31, 4*21($29)
219 lw $27, 4*22($29) /* get EPC */
220 addiu $29, $29, 23*4 /* restore SP */
221 mtc0 $27, $14 /* restore EPC */
222 eret /* exit GIET */
223
224 /* The PTI handler get PTI index, */
225 /* acknowledge the PTI register */
226 /* and call the corresponding ISR */
227_int_PTI:
228 srl $26, $15, 6 /* $26 <= PRIO >> 6 */
229 andi $26, $26, 0x7C /* $26 <= PTI_INDEX * 4 */
230 addi $27, $14, 0x180 /* $27 <= &PTI_ACK[0] */
231 add $27, $27, $26 /* $27 <= &PTI_ACK[PTI_INDEX] */
232 lw $0, ($27) /* acknowledge XICU PTI */
233 la $27, _interrupt_vector
234 addu $26, $26, $27
235 lw $26, ($26) /* read ISR address */
236 jalr $26 /* call ISR */
237 nop
238 j _int_restore /* return from INT handler */
239 nop
240
241 /* The HWI handler get HWI index */
242 /* and call the corresponding ISR */
243_int_HWI:
244 srl $26, $15, 14 /* $26 <= PRIO >> 14 */
245 andi $26, $26, 0x7C /* $26 <= HWI_INDEX * 4 */
246 la $27, _interrupt_vector
247 addu $26, $26, $27 /* $26 <= &ISR[HWI_INDEX */
248 lw $26, ($26) /* read ISR address */
249 jalr $26 /* call ISR */
250 nop
251 j _int_restore /* return from INT handler */
252 nop
253
254 /* The WTI handler get WTI index, */
255 /* acknowledge the WTI register */
256 /* and call the corresponding ISR */
257_int_WTI:
258 srl $26, $15, 22 /* $26 <= PRIO >> 22 */
259 andi $26, $26, 0x7C /* $26 <= WTI_INDEX * 4 */
260 add $27, $14, $26 /* $27 <= &WTI_REG[WTI_INDEX] */
261 lw $0, ($27) /* acknowledge XICU WTI */
262 la $27, _interrupt_vector
263 addu $26, $26, $27 /* $26 <= &ISR[WTI_INDEX] */
264 lw $26, ($26) /* read ISR address */
265 jalr $26 /* call ISR */
266 nop
267 j _int_restore /* return from INT handler */
268 nop
269
270/* The default ISR is called when no specific ISR has been installed */
271/* in the interrupt vector. It simply displays a message on TTY0 */
272
273isr_default:
274 addiu $29, $29, -20 /* get space in stack */
275 sw $31, 16($29) /* to save the return address */
276 la $4, _msg_default /* $4 <= string address */
277 addi $5, $0, 36 /* $5 <= string length */
278 li $6, 0 /* $6 <= TTY0 */
279 jal _tty_write
280 lw $31, 16($29) /* restore return address */
281 addiu $29, $29, 20 /* free space */
282 jr $31 /* returns to interrupt handler */
283
284/****************************************************************
285* Interrupt Vector Table (indexed by interrupt index)
286* 32 words corresponding to 32 ISR addresses
287****************************************************************/
288_interrupt_vector:
289 .word isr_default /* ISR 0 */
290 .word isr_default /* ISR 1 */
291 .word isr_default /* ISR 2 */
292 .word isr_default /* ISR 3 */
293 .word isr_default /* ISR 4 */
294 .word isr_default /* ISR 5 */
295 .word isr_default /* ISR 6 */
296 .word isr_default /* ISR 7 */
297 .word isr_default /* ISR 8 */
298 .word isr_default /* ISR 9 */
299 .word isr_default /* ISR 10 */
300 .word isr_default /* ISR 11 */
301 .word isr_default /* ISR 12 */
302 .word isr_default /* ISR 13 */
303 .word isr_default /* ISR 14 */
304 .word isr_default /* ISR 15 */
305 .word isr_default /* ISR 16 */
306 .word isr_default /* ISR 17 */
307 .word isr_default /* ISR 18 */
308 .word isr_default /* ISR 19 */
309 .word isr_default /* ISR 20 */
310 .word isr_default /* ISR 21 */
311 .word isr_default /* ISR 22 */
312 .word isr_default /* ISR 23 */
313 .word isr_default /* ISR 24 */
314 .word isr_default /* ISR 25 */
315 .word isr_default /* ISR 26 */
316 .word isr_default /* ISR 27 */
317 .word isr_default /* ISR 28 */
318 .word isr_default /* ISR 29 */
319 .word isr_default /* ISR 30 */
320 .word isr_default /* ISR 31 */
321
322 .end _int_handler
323
324/****************************************************************
325* Exception Handler
326* Same code for all fatal exceptions :
327* Print the exception type and the values of EPC & BAR
328* on the TTY correspondintg to the processor PROCID,
329* and the user program is killed.
330****************************************************************/
331 .ent _exc_handler
332
333_exc_handler:
334_cause_bp:
335_cause_ukn:
336_cause_ri:
337_cause_ovf:
338_cause_adel:
339_cause_ades:
340_cause_ibe:
341_cause_dbe:
342_cause_cpu:
343 mfc0 $26, $13 /* $26 <= CR */
344 andi $26, $26, 0x3C /* $26 <= _cause_index * 4 */
345 la $27, _mess_causes /* mess_cause table base address */
346 addu $27, $26, $27 /* $26 <= message base address */
347
348 /* take the lock on TTY0 */
349 li $4, 0
350 jal _tty_get_lock
351 nop
352
353 /* display exception type */
354 lw $4, ($27) /* $4 <= message address */
355 li $5, 36 /* $5 <= message length */
356 li $6, 0 /* $6 <= TTY0 */
357 jal _tty_write
358 nop
359
360 /* display EPC value */
361 la $4, _msg_epc /* $4 <= message address */
362 li $5, 8 /* $5 <= message length */
363 li $6, 0 /* $6 <= TTY0 */
364 jal _tty_write
365 nop
366
367 mfc0 $4, $14 /* $4 <= EPC value */
368 la $5, _itoa_buffer /* $5 <= buffer address */
369 addiu $5, $5, 2 /* skip 0x prefix */
370 jal _itoa_hex /* fill buffer */
371 nop
372
373 la $4, _itoa_buffer /* $4 <= buffer address */
374 li $5, 10 /* $5 <= buffer length */
375 li $6, 0 /* $6 <= TTY0 */
376 jal _tty_write
377 nop
378
379 /* display BAR value */
380 la $4, _msg_bar /* $4 <= message address */
381 li $5, 8 /* $5 <= message length */
382 li $6, 0 /* $6 <= TTY0 */
383 jal _tty_write
384 nop
385
386 mfc0 $4, $8 /* $4 <= BAR value */
387 la $5, _itoa_buffer /* $5 <= buffer address */
388 addiu $5, $5, 2 /* skip 0x prefix */
389 jal _itoa_hex /* fill buffer */
390 nop
391
392 la $4, _itoa_buffer /* $4 <= message address */
393 li $5, 10 /* $5 <= message length */
394 li $6, 0 /* $6 <= TTY0 */
395 jal _tty_write
396 nop
397
398
399 /* release the lock on TTY0 */
400 li $4, 0
401 jal _tty_get_lock
402 nop
403
404 j _exit /* kill user program */
405
406/* Exceptions Messages table (indexed by XCODE) */
407_mess_causes:
408 .word _msg_ukncause
409 .word _msg_ukncause
410 .word _msg_ukncause
411 .word _msg_ukncause
412 .word _msg_adel
413 .word _msg_ades
414 .word _msg_ibe
415 .word _msg_dbe
416 .word _msg_ukncause
417 .word _msg_bp
418 .word _msg_ri
419 .word _msg_cpu
420 .word _msg_ovf
421 .word _msg_ukncause
422 .word _msg_ukncause
423 .word _msg_ukncause
424
425/********************************************************************
426* All messages
427* Messages length are fixed : 8 or 36 characters...
428********************************************************************/
429_msg_bar: .asciiz "\nBAR = "
430_msg_epc: .asciiz "\nEPC = "
431_msg_default: .asciiz "\n\n !!! Default ISR !!! \n"
432_msg_uknsyscall: .asciiz "\n\n !!! Undefined System Call !!! \n"
433_msg_ukncause: .asciiz "\n\nException : strange unknown cause\n"
434_msg_adel: .asciiz "\n\nException : illegal read address \n"
435_msg_ades: .asciiz "\n\nException : illegal write address\n"
436_msg_ibe: .asciiz "\n\nException : inst bus error \n"
437_msg_dbe: .asciiz "\n\nException : data bus error \n"
438_msg_bp: .asciiz "\n\nException : breakpoint \n"
439_msg_ri: .asciiz "\n\nException : reserved instruction \n"
440_msg_ovf: .asciiz "\n\nException : arithmetic overflow \n"
441_msg_cpu: .asciiz "\n\nException : illegal coproc access\n"
442
443 .end _exc_handler
444
445
Note: See TracBrowser for help on using the repository browser.