]> git.sur5r.net Git - freertos/blob
12bbf2c6c84beeb34348c37e14cbcbe48152a233
[freertos] /
1 /******************************************************************************
2 *
3 * Copyright (C) 2004 - 2014 Xilinx, Inc.  All rights reserved.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a copy
6 * of this software and associated documentation files (the "Software"), to deal
7 * in the Software without restriction, including without limitation the rights
8 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 * copies of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
14 *
15 * Use of the Software is limited solely to applications:
16 * (a) running on a Xilinx device, or
17 * (b) that interact with a Xilinx device through a bus or interconnect.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * XILINX  BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
23 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
24 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25 * SOFTWARE.
26 *
27 * Except as contained in this notice, the name of the Xilinx shall not be used
28 * in advertising or otherwise to promote the sale, use or other dealings in
29 * this Software without prior written authorization from Xilinx.
30 *
31 ******************************************************************************/
32 /*
33  * Microblaze HW Exception Handler
34  * - Non self-modifying exception handler for the following exception conditions
35  *   - Unalignment
36  *   - Instruction bus error
37  *   - Data bus error
38  *   - Illegal instruction opcode
39  *   - Divide-by-zero
40  *   - Stack protection violation
41  */
42
43 #include "microblaze_exceptions_g.h"
44 #include "xparameters.h"
45
46 /* Helpful Macros */
47 #define EX_HANDLER_STACK_SIZ            (4*21)
48 #define RMSR_OFFSET                     (20 * 4)
49 #define R17_OFFSET                      (0)    
50 #define REG_OFFSET(regnum)              (4 * (regnum + 1))
51 #define NUM_TO_REG(num)                 r ## num
52
53 #define R3_TO_STACK(regnum)             swi     r3, r1, REG_OFFSET(regnum)
54 #define R3_FROM_STACK(regnum)           lwi     r3, r1, REG_OFFSET(regnum)      
55
56 #define PUSH_REG(regnum)                swi     NUM_TO_REG(regnum), r1, REG_OFFSET(regnum)
57 #define POP_REG(regnum)                 lwi     NUM_TO_REG(regnum), r1, REG_OFFSET(regnum)
58         
59 /* Uses r5 */
60 #define PUSH_MSR                                                                \
61         mfs     r5, rmsr;                                                       \
62         swi     r5, r1, RMSR_OFFSET;
63    
64 #define PUSH_MSR_AND_ENABLE_EXC                                                 \
65         mfs     r5, rmsr;                                                       \
66         swi     r5, r1, RMSR_OFFSET;                                            \
67         ori     r5, r5, 0x100;                          /* Turn ON the EE bit*/ \
68         mts     rmsr, r5;
69     
70 /* Uses r5 */
71 #define POP_MSR                                                                 \
72         lwi     r5, r1, RMSR_OFFSET;                                            \
73         mts     rmsr, r5;       
74
75 /* Push r17 */    
76 #define PUSH_R17                swi     r17, r1, R17_OFFSET
77 /* Pop r17 */        
78 #define POP_R17                 lwi     r17, r1, R17_OFFSET
79        
80 #define LWREG_NOP                                                               \
81         bri     ex_handler_unhandled;                                           \
82         nop;
83
84 #define SWREG_NOP                                                               \
85         bri     ex_handler_unhandled;                                           \
86         nop;        
87         
88 /* r3 is the source */
89 #define R3_TO_LWREG_V(regnum)                                                   \
90         R3_TO_STACK (regnum);                                                   \
91         bri     ex_handler_done; 
92
93 /* r3 is the source */
94 #define R3_TO_LWREG(regnum)                                                     \
95         or      NUM_TO_REG (regnum), r0, r3;                                    \
96         bri     ex_handler_done;                        
97
98 /* r3 is the target */          
99 #define SWREG_TO_R3_V(regnum)                                                   \
100         R3_FROM_STACK (regnum);                                                 \
101         bri     ex_sw_tail;                                                     
102                 
103 /* r3 is the target */  
104 #define SWREG_TO_R3(regnum)                                                     \
105         or      r3, r0, NUM_TO_REG (regnum);                                    \
106         bri     ex_sw_tail; 
107
108 /* regnum is the source */  
109 #define FP_EX_OPB_SAVE(regnum)                                                  \
110         swi     NUM_TO_REG (regnum), r0, mb_fpex_op_b;                          \
111         nop;                                                                    \
112         bri     handle_fp_ex_opa; 
113
114 /* regnum is the source */  
115 #define FP_EX_OPB_SAVE_V(regnum)                                                \
116         R3_FROM_STACK (regnum);                                                 \
117         swi     r3, r0, mb_fpex_op_b;                                           \
118         bri     handle_fp_ex_opa; 
119         
120 /* regnum is the source */  
121 #define FP_EX_OPA_SAVE(regnum)                                                  \
122         swi     NUM_TO_REG (regnum), r0, mb_fpex_op_a;                          \
123         nop;                                                                    \
124         bri     handle_fp_ex_done; 
125     
126 /* regnum is the source */  
127 #define FP_EX_OPA_SAVE_V(regnum)                                                \
128         R3_FROM_STACK (regnum);                                                 \
129         swi     r3, r0, mb_fpex_op_a;                                           \
130         bri     handle_fp_ex_done; 
131
132 #define FP_EX_UNHANDLED                                                         \
133         bri     fp_ex_unhandled;                                                \
134         nop;                                                                    \
135         nop;
136
137 /* ESR masks */    
138 #define ESR_EXC_MASK            0x0000001F
139 #define ESR_REG_MASK            0x000003E0
140 #define ESR_LW_SW_MASK          0x00000400
141 #define ESR_WORD_MASK           0x00000800
142 #define ESR_DS_MASK             0x00001000
143         
144 /* Extern declarations */
145 .extern XNullHandler
146
147
148 #ifdef MICROBLAZE_EXCEPTIONS_ENABLED                    /* If exceptions are enabled in the processor */
149                 
150 /* 
151  * hw_exception_handler - Handler for unaligned exceptions
152  * Exception handler notes:     
153  * - Does not handle exceptions other than unaligned exceptions
154  * - Does not handle exceptions during load into r17, r1, r0.
155  * - Does not handle exceptions during store from r17 (cannot be done) and r1 (slows down common case)
156  *
157  *  Relevant register structures
158  *        
159  *  EAR - |----|----|----|----|----|----|----|----|      
160  *      - <  ##   32 bit faulting address     ##  >      
161  *       
162  *  ESR - |----|----|----|----|----| - | - |-----|-----| 
163  *      -                            W   S   REG   EXC
164  *
165  *        
166  * STACK FRAME STRUCTURE
167  * ---------------------
168  *
169  *      +-------------+         + 0
170  *      |     r17     |
171  *      +-------------+         + 4                    
172  *      |  Args for   |
173  *      |  next func  |
174  *      +-------------+         + 8
175  *      |     r1      |
176  *      |      .      |
177  *      |      .      |
178  *      |      .      |
179  *      |      .      |
180  *      |     r18     |
181  *      +-------------+         + 80
182  *      |     MSR     |         
183  *      +-------------+         + 84    
184  *      |      .      | 
185  *      |      .      |           
186  */        
187
188          
189 .global _hw_exception_handler                               
190 .section .text                                          
191 .align 2
192 .ent _hw_exception_handler
193 .type _hw_exception_handler, @function    
194 _hw_exception_handler:                      
195
196 #if defined(XPAR_MICROBLAZE_USE_STACK_PROTECTION) && (XPAR_MICROBLAZE_USE_STACK_PROTECTION == 1)
197         /* Immediately halt for stack protection violation exception without using any stack       */
198         swi     r3, r0, mb_sp_save_r3;                  /* Save temporary register                 */
199         mfs     r3, resr;                               /* Extract ESR[DS]                         */
200         andi    r3, r3, ESR_EXC_MASK;
201         xori    r3, r3, 0x7;                            /* Check for stack protection violation    */
202         bnei    r3, ex_handler_not_sp_violation;
203 ex_handler_sp_violation:
204         bri     0;                                      /* Halt here if stack protection violation */
205 ex_handler_not_sp_violation:
206         lwi     r3, r0, mb_sp_save_r3;                  /* Restore temporary register              */
207 #endif /* defined(XPAR_MICROBLAZE_USE_STACK_PROTECTION) && (XPAR_MICROBLAZE_USE_STACK_PROTECTION == 1) */
208
209         addik   r1, r1, -(EX_HANDLER_STACK_SIZ);        /* Create stack frame */
210         PUSH_REG(3);              
211         PUSH_REG(4);              
212         PUSH_REG(5);              
213         PUSH_REG(6);
214 #ifdef MICROBLAZE_CAN_HANDLE_EXCEPTIONS_IN_DELAY_SLOTS
215         mfs     r6, resr;
216         andi    r6, r6, ESR_DS_MASK;
217         beqi    r6, ex_handler_no_ds;
218         mfs     r17, rbtr;
219 ex_handler_no_ds:       
220 #endif
221         PUSH_R17;    
222         PUSH_MSR_AND_ENABLE_EXC;                        /* Exceptions enabled here. This will allow nested exceptions */
223                 
224         mfs     r3, resr;    
225         andi    r5, r3, ESR_EXC_MASK;                   /* Extract ESR[EXC]                     */
226 #ifndef NO_UNALIGNED_EXCEPTIONS
227         xori    r6, r5, 1;                              /* 00001 = Unaligned Exception          */  
228         bnei    r6, handle_ex_regular;               
229
230         la      r4, r0, MB_ExceptionVectorTable;        /* Check if user has registered an unaligned exception handler */
231         lwi     r4, r4, 8; 
232         la      r6, r0, XNullHandler;                   /* If exceptionvectortable entry is still XNullHandler, use */
233         xor     r6, r4, r6;                             /* the default exception handler */
234         beqi    r6, handle_unaligned_ex ;           
235     
236 handle_ex_regular:      
237 #endif  /* ! NO_UNALIGNED_EXCEPTIONS */
238
239 #if defined (MICROBLAZE_FP_EXCEPTION_ENABLED) && defined (MICROBLAZE_FP_EXCEPTION_DECODE)
240         xori   r6, r5, 6;                               /* 00110 = FPU exception */
241         beqi   r6, handle_fp_ex;                        /* Go and decode the FP exception */
242 #endif  /* defined (MICROBLAZE_FP_EXCEPTION_ENABLED) && defined (MICROBLAZE_FP_EXCEPTION_DECODE) */
243
244 handle_other_ex:                                        /* Handle Other exceptions here         */        
245         ori     r6, r0, 20; 
246         cmp     r6, r5, r6;                             /* >= 20 are exceptions we do not handle. */
247         blei    r6, ex_handler_unhandled;
248
249         ori     r6, r0, 7;
250         cmp     r6, r5, r6;                             /* Convert MMU exception indices into an ordinal of 7 */
251         bgti    r6, handle_other_ex_tail;
252         ori     r5, r0, 0x7; 
253                 
254 handle_other_ex_tail:       
255         PUSH_REG(7);                                    /* Save other volatiles before we make procedure calls below   */
256         PUSH_REG(8);             
257         PUSH_REG(9);              
258         PUSH_REG(10);             
259         PUSH_REG(11);             
260         PUSH_REG(12);
261         PUSH_REG(15);
262         PUSH_REG(18);        
263
264         la      r4, r0, MB_ExceptionVectorTable;        /* Load the Exception vector table base address         */
265         addk    r7, r5, r5;                             /* Calculate exception vector offset = r5 * 8           */
266         addk    r7, r7, r7;         
267         addk    r7, r7, r7;
268         addk    r7, r7, r4;                             /* Get pointer to exception vector               */
269         lwi     r5, r7, 4;                              /* Load argument to exception handler from table */
270         lw      r7, r7, r0;                             /* Load vector itself here                       */
271
272         brald   r15, r7;                                /* Branch to handler                             */
273         nop;
274         
275         POP_REG(7);                                     /* Restore other volatiles */
276         POP_REG(8);              
277         POP_REG(9);               
278         POP_REG(10);              
279         POP_REG(11);              
280         POP_REG(12);
281         POP_REG(15);
282         POP_REG(18);        
283
284         bri     ex_handler_done;                        /* Complete exception handling       */        
285
286 #ifndef NO_UNALIGNED_EXCEPTIONS
287 handle_unaligned_ex:    
288         andi    r6, r3, ESR_REG_MASK;                   /* Mask and extract the register operand */
289         srl     r6, r6;                                 /* r6 >> 5 */
290         srl     r6, r6;
291         srl     r6, r6;
292         srl     r6, r6;
293         srl     r6, r6;
294         sbi     r6, r0, ex_reg_op;                      /* Store the register operand in a temporary location */
295         mfs     r4, rear;                              
296         andi    r6, r3, ESR_LW_SW_MASK;                 /* Extract ESR[S]               */
297         bnei    r6, ex_sw;
298 ex_lw:  
299         andi    r6, r3, ESR_WORD_MASK;                  /* Extract ESR[W]               */
300         beqi    r6, ex_lhw;
301         lbui    r5, r4, 0;                              /* Exception address in r4      */
302         sbi     r5, r0, ex_tmp_data_loc_0;              /* Load a word, byte-by-byte from destination address and save it in tmp space  */              
303         lbui    r5, r4, 1;
304         sbi     r5, r0, ex_tmp_data_loc_1;
305         lbui    r5, r4, 2;
306         sbi     r5, r0, ex_tmp_data_loc_2;
307         lbui    r5, r4, 3;
308         sbi     r5, r0, ex_tmp_data_loc_3;
309         lwi     r3, r0, ex_tmp_data_loc_0;              /* Get the destination register value into r3   */
310         bri     ex_lw_tail;      
311 ex_lhw: 
312         lbui    r5, r4, 0;                              /* Exception address in r4                      */
313         sbi     r5, r0, ex_tmp_data_loc_0;              /* Load a half-word, byte-by-byte from destination address and save it in tmp space */  
314         lbui    r5, r4, 1;                               
315         sbi     r5, r0, ex_tmp_data_loc_1;
316         lhui    r3, r0, ex_tmp_data_loc_0;              /* Get the destination register value into r3   */
317 ex_lw_tail:
318         lbui    r5, r0, ex_reg_op;                      /* Get the destination register number into r5  */
319         la      r6, r0, lw_table;                       /* Form load_word jump table offset (lw_table + (8 * regnum)) */
320         addk    r5, r5, r5;                              
321         addk    r5, r5, r5;
322         addk    r5, r5, r5;
323         addk    r5, r5, r6;
324         bra     r5;
325 ex_lw_end:                                              /* Exception handling of load word, ends */
326 ex_sw:          
327         lbui    r5, r0, ex_reg_op;                      /* Get the destination register number into r5 */
328         la      r6, r0, sw_table;                       /* Form store_word jump table offset (sw_table + (8 * regnum)) */
329         add     r5, r5, r5;                             
330         add     r5, r5, r5;
331         add     r5, r5, r5;
332         add     r5, r5, r6;
333         bra     r5;
334 ex_sw_tail:             
335         mfs     r6, resr;                               
336         andi    r6, r6, ESR_WORD_MASK;                  /* Extract ESR[W]       */
337         beqi    r6, ex_shw;
338         swi     r3, r0, ex_tmp_data_loc_0;
339         lbui    r3, r0, ex_tmp_data_loc_0;              /* Store the word, byte-by-byte into destination address                */
340         sbi     r3, r4, 0;
341         lbui    r3, r0, ex_tmp_data_loc_1;
342         sbi     r3, r4, 1;
343         lbui    r3, r0, ex_tmp_data_loc_2;
344         sbi     r3, r4, 2;       
345         lbui    r3, r0, ex_tmp_data_loc_3;
346         sbi     r3, r4, 3;                      
347         bri     ex_handler_done;
348 ex_shw:         
349         swi     r3, r0, ex_tmp_data_loc_0;              /* Store the lower half-word, byte-by-byte into destination address      */
350         
351 #ifdef __LITTLE_ENDIAN__
352         lbui    r3, r0, ex_tmp_data_loc_0;
353 #else
354         lbui    r3, r0, ex_tmp_data_loc_2;
355 #endif
356         sbi     r3, r4, 0;
357 #ifdef __LITTLE_ENDIAN__
358         lbui    r3, r0, ex_tmp_data_loc_1;
359 #else
360         lbui    r3, r0, ex_tmp_data_loc_3;
361 #endif
362         sbi     r3, r4, 1;
363 ex_sw_end:                                              /* Exception handling of store word, ends. */
364         bri     ex_handler_done; 
365 #endif  /* !NO_UNALIGNED_EXCEPTIONS */
366
367 #if defined (MICROBLAZE_FP_EXCEPTION_ENABLED) && defined (MICROBLAZE_FP_EXCEPTION_DECODE)
368 handle_fp_ex:
369         addik   r3, r17, -4;                            /* r17 contains (addr of exception causing FP instruction + 4) */
370         lw      r4, r0, r3;                             /* We might find ourselves in a spot here. Unguaranteed load   */
371
372 handle_fp_ex_opb:
373         la      r6, r0, fp_table_opb;                   /* Decode opB and store its value in mb_fpex_op_b */
374         srl     r4, r4; 
375         srl     r4, r4; 
376         srl     r4, r4; 
377         srl     r4, r4; 
378         srl     r4, r4; 
379         srl     r4, r4; 
380         srl     r4, r4; 
381         srl     r4, r4; 
382         srl     r4, r4; 
383         srl     r4, r4; 
384         srl     r4, r4; 
385         andi    r3, r4, 0x1F;
386         add     r3, r3, r3;                             /* Calculate (fp_table_opb + (regno * 12)) in r5 */
387         add     r3, r3, r3;
388         add     r5, r3, r3;
389         add     r5, r5, r3;
390         add     r5, r5, r6;
391         bra     r5; 
392
393 handle_fp_ex_opa:
394         la      r6, r0, fp_table_opa;                   /* Decode opA and store its value in mb_fpex_op_a */
395         srl     r4, r4; 
396         srl     r4, r4; 
397         srl     r4, r4; 
398         srl     r4, r4; 
399         srl     r4, r4; 
400         andi    r3, r4, 0x1F;
401         add     r3, r3, r3;                             /* Calculate (fp_table_opb + (regno * 12)) in r5 */
402         add     r3, r3, r3;
403         add     r5, r3, r3;
404         add     r5, r5, r3;
405         add     r5, r5, r6;
406         bra     r5; 
407
408 handle_fp_ex_done:
409         ori     r5, r0, 6;                              /* Set exception number back to 6 */
410         bri     handle_other_ex_tail; 
411     
412 fp_ex_unhandled:    
413         bri     0; 
414 #endif  /* defined (MICROBLAZE_FP_EXCEPTION_ENABLED) && defined (MICROBLAZE_FP_EXCEPTION_DECODE) */
415                      
416 ex_handler_done:
417         POP_R17;
418         POP_MSR;
419         POP_REG(3);               
420         POP_REG(4);               
421         POP_REG(5);               
422         POP_REG(6); 
423
424         rted    r17, 0
425         addik   r1, r1, (EX_HANDLER_STACK_SIZ);         /* Restore stack frame  */        
426 ex_handler_unhandled:   
427         bri 0                                           /* UNHANDLED. TRAP HERE */                                                 
428 .end _hw_exception_handler  
429
430 #ifndef NO_UNALIGNED_EXCEPTIONS        
431
432 /* 
433  * hw_exception_handler Jump Table
434  * - Contains code snippets for each register that caused the unaligned exception.
435  * - Hence exception handler is NOT self-modifying
436  * - Separate table for load exceptions and store exceptions.
437  * - Each table is of size:   (8 * 32) = 256 bytes
438  */
439                 
440 .section .text
441 .align  4
442 lw_table:
443 lw_r0:  R3_TO_LWREG   (0); 
444 lw_r1:  LWREG_NOP;
445 lw_r2:  R3_TO_LWREG   (2);
446 lw_r3:  R3_TO_LWREG_V (3);
447 lw_r4:  R3_TO_LWREG_V (4);
448 lw_r5:  R3_TO_LWREG_V (5);
449 lw_r6:  R3_TO_LWREG_V (6);
450 lw_r7:  R3_TO_LWREG   (7);
451 lw_r8:  R3_TO_LWREG   (8);
452 lw_r9:  R3_TO_LWREG   (9);
453 lw_r10: R3_TO_LWREG   (10);
454 lw_r11: R3_TO_LWREG   (11);                             
455 lw_r12: R3_TO_LWREG   (12);
456 lw_r13: R3_TO_LWREG   (13);
457 lw_r14: R3_TO_LWREG   (14);                                                     
458 lw_r15: R3_TO_LWREG   (15);                                                     
459 lw_r16: R3_TO_LWREG   (16);                                                     
460 lw_r17: LWREG_NOP;
461 lw_r18: R3_TO_LWREG   (18);                                                     
462 lw_r19: R3_TO_LWREG   (19);                                                     
463 lw_r20: R3_TO_LWREG   (20);                                                     
464 lw_r21: R3_TO_LWREG   (21);
465 lw_r22: R3_TO_LWREG   (22);
466 lw_r23: R3_TO_LWREG   (23);                                                     
467 lw_r24: R3_TO_LWREG   (24);                                                     
468 lw_r25: R3_TO_LWREG   (25);                                                     
469 lw_r26: R3_TO_LWREG   (26);                                                     
470 lw_r27: R3_TO_LWREG   (27);                                                     
471 lw_r28: R3_TO_LWREG   (28);                                                     
472 lw_r29: R3_TO_LWREG   (29);                                                     
473 lw_r30: R3_TO_LWREG   (30);
474 lw_r31: R3_TO_LWREG   (31);
475
476 sw_table:
477 sw_r0:  SWREG_TO_R3   (0); 
478 sw_r1:  SWREG_NOP;
479 sw_r2:  SWREG_TO_R3   (2);
480 sw_r3:  SWREG_TO_R3_V (3);
481 sw_r4:  SWREG_TO_R3_V (4);
482 sw_r5:  SWREG_TO_R3_V (5);
483 sw_r6:  SWREG_TO_R3_V (6);
484 sw_r7:  SWREG_TO_R3   (7);
485 sw_r8:  SWREG_TO_R3   (8);
486 sw_r9:  SWREG_TO_R3   (9);
487 sw_r10: SWREG_TO_R3   (10);
488 sw_r11: SWREG_TO_R3   (11);                             
489 sw_r12: SWREG_TO_R3   (12);
490 sw_r13: SWREG_TO_R3   (13);
491 sw_r14: SWREG_TO_R3   (14);                                                     
492 sw_r15: SWREG_TO_R3   (15);                                                     
493 sw_r16: SWREG_TO_R3   (16);                                                     
494 sw_r17: SWREG_NOP; 
495 sw_r18: SWREG_TO_R3   (18);                                                     
496 sw_r19: SWREG_TO_R3   (19);                                                     
497 sw_r20: SWREG_TO_R3   (20);                                                     
498 sw_r21: SWREG_TO_R3   (21);
499 sw_r22: SWREG_TO_R3   (22);
500 sw_r23: SWREG_TO_R3   (23);                                                     
501 sw_r24: SWREG_TO_R3   (24);                                                     
502 sw_r25: SWREG_TO_R3   (25);                                                     
503 sw_r26: SWREG_TO_R3   (26);                                                     
504 sw_r27: SWREG_TO_R3   (27);                                                     
505 sw_r28: SWREG_TO_R3   (28);                                                     
506 sw_r29: SWREG_TO_R3   (29);                                                     
507 sw_r30: SWREG_TO_R3   (30);
508 sw_r31: SWREG_TO_R3   (31);
509
510 /* Temporary data structures used in the handler */
511 .section .data
512 .align 2
513 ex_tmp_data_loc_0:      
514         .byte 0
515 ex_tmp_data_loc_1:      
516         .byte 0
517 ex_tmp_data_loc_2:      
518         .byte 0
519 ex_tmp_data_loc_3:      
520         .byte 0                 
521 ex_reg_op:
522         .byte 0
523     
524 #endif /* ! NO_UNALIGNED_EXCEPTIONS */
525     
526 #if defined (MICROBLAZE_FP_EXCEPTION_ENABLED) && defined (MICROBLAZE_FP_EXCEPTION_DECODE)
527 /* 
528  * FP exception decode jump table.
529  * - Contains code snippets for each register that could have been a source operand for an excepting FP instruction
530  * - Hence exception handler is NOT self-modifying
531  * - Separate table for opA and opB
532  * - Each table is of size:   (12 * 32) = 384 bytes
533  */
534     
535 .section .text
536 .align  4
537 fp_table_opa:
538 opa_r0: FP_EX_OPA_SAVE (0); 
539 opa_r1: FP_EX_UNHANDLED; 
540 opa_r2: FP_EX_OPA_SAVE (2);     
541 opa_r3: FP_EX_OPA_SAVE_V (3);     
542 opa_r4: FP_EX_OPA_SAVE_V (4);     
543 opa_r5: FP_EX_OPA_SAVE_V (5);     
544 opa_r6: FP_EX_OPA_SAVE_V (6);     
545 opa_r7: FP_EX_OPA_SAVE (7);     
546 opa_r8: FP_EX_OPA_SAVE (8);     
547 opa_r9: FP_EX_OPA_SAVE (9);     
548 opa_r10: FP_EX_OPA_SAVE (10);     
549 opa_r11: FP_EX_OPA_SAVE (11);     
550 opa_r12: FP_EX_OPA_SAVE (12);     
551 opa_r13: FP_EX_OPA_SAVE (13);     
552 opa_r14: FP_EX_UNHANDLED; 
553 opa_r15: FP_EX_UNHANDLED; 
554 opa_r16: FP_EX_UNHANDLED; 
555 opa_r17: FP_EX_UNHANDLED; 
556 opa_r18: FP_EX_OPA_SAVE (18);     
557 opa_r19: FP_EX_OPA_SAVE (19);     
558 opa_r20: FP_EX_OPA_SAVE (20);     
559 opa_r21: FP_EX_OPA_SAVE (21);     
560 opa_r22: FP_EX_OPA_SAVE (22);     
561 opa_r23: FP_EX_OPA_SAVE (23);     
562 opa_r24: FP_EX_OPA_SAVE (24);     
563 opa_r25: FP_EX_OPA_SAVE (25);     
564 opa_r26: FP_EX_OPA_SAVE (26);     
565 opa_r27: FP_EX_OPA_SAVE (27);     
566 opa_r28: FP_EX_OPA_SAVE (28);     
567 opa_r29: FP_EX_OPA_SAVE (29);     
568 opa_r30: FP_EX_OPA_SAVE (30);     
569 opa_r31: FP_EX_OPA_SAVE (31);     
570
571 fp_table_opb:   
572 opb_r0: FP_EX_OPB_SAVE (0); 
573 opb_r1: FP_EX_UNHANDLED; 
574 opb_r2: FP_EX_OPB_SAVE (2);     
575 opb_r3: FP_EX_OPB_SAVE_V (3);     
576 opb_r4: FP_EX_OPB_SAVE_V (4);     
577 opb_r5: FP_EX_OPB_SAVE_V (5);     
578 opb_r6: FP_EX_OPB_SAVE_V (6);     
579 opb_r7: FP_EX_OPB_SAVE (7);     
580 opb_r8: FP_EX_OPB_SAVE (8);     
581 opb_r9: FP_EX_OPB_SAVE (9);     
582 opb_r10: FP_EX_OPB_SAVE (10);     
583 opb_r11: FP_EX_OPB_SAVE (11);     
584 opb_r12: FP_EX_OPB_SAVE (12);     
585 opb_r13: FP_EX_OPB_SAVE (13);     
586 opb_r14: FP_EX_UNHANDLED; 
587 opb_r15: FP_EX_UNHANDLED; 
588 opb_r16: FP_EX_UNHANDLED; 
589 opb_r17: FP_EX_UNHANDLED; 
590 opb_r18: FP_EX_OPB_SAVE (18);     
591 opb_r19: FP_EX_OPB_SAVE (19);     
592 opb_r20: FP_EX_OPB_SAVE (20);     
593 opb_r21: FP_EX_OPB_SAVE (21);     
594 opb_r22: FP_EX_OPB_SAVE (22);     
595 opb_r23: FP_EX_OPB_SAVE (23);     
596 opb_r24: FP_EX_OPB_SAVE (24);     
597 opb_r25: FP_EX_OPB_SAVE (25);     
598 opb_r26: FP_EX_OPB_SAVE (26);     
599 opb_r27: FP_EX_OPB_SAVE (27);     
600 opb_r28: FP_EX_OPB_SAVE (28);     
601 opb_r29: FP_EX_OPB_SAVE (29);     
602 opb_r30: FP_EX_OPB_SAVE (30);     
603 opb_r31: FP_EX_OPB_SAVE (31);     
604     
605 #endif  /* defined (MICROBLAZE_FP_EXCEPTION_ENABLED) && defined (MICROBLAZE_FP_EXCEPTION_DECODE) */
606     
607 #if defined(MICROBLAZE_FP_EXCEPTION_ENABLED) && defined(MICROBLAZE_FP_EXCEPTION_DECODE)
608 /* This is where we store the opA and opB of the last excepting FP instruction */
609 .section .data    
610 .align 2
611 .global mb_fpex_op_a
612 .global mb_fpex_op_b
613 mb_fpex_op_a:
614         .long 0
615 mb_fpex_op_b:
616         .long 0
617 #endif /* defined (MICROBLAZE_FP_EXCEPTION_ENABLED) && defined (MICROBLAZE_FP_EXCEPTION_DECODE) */
618
619 #if defined(XPAR_MICROBLAZE_USE_STACK_PROTECTION) && (XPAR_MICROBLAZE_USE_STACK_PROTECTION == 1)
620 /* This is where we store the register used to check which exception occurred */
621         .section .data
622         .align 2
623 mb_sp_save_r3:
624         .long 0
625 #endif /* defined(XPAR_MICROBLAZE_USE_STACK_PROTECTION) && (XPAR_MICROBLAZE_USE_STACK_PROTECTION == 1) */
626
627 /* The exception vector table */
628 .section .data
629 .align 2
630 .global MB_ExceptionVectorTable
631 MB_ExceptionVectorTable:
632     .long XNullHandler
633     .long 0                                 /* --          FSL Exception         -- */
634     .long XNullHandler
635     .long 1                                 /* -- Unaligned Access Exception     -- */
636     .long XNullHandler
637     .long 2                                 /* --   Illegal Opcode Exception     -- */
638     .long XNullHandler
639     .long 3                                 /* --      Instruction Bus Exception -- */
640     .long XNullHandler
641     .long 4                                 /* --     Data Bus Exception         -- */
642     .long XNullHandler
643     .long 5                                 /* --       Div-by-0 Exception       -- */
644     .long XNullHandler
645     .long 6                                 /* --         FPU  Exception         -- */
646     .long XNullHandler
647     .long 7                                 /* --         MMU  Exceptions        -- */    
648
649 #else                                       /* Dummy exception handler, in case exceptions are not present in the processor */
650
651 .global _hw_exception_handler                               
652 .section .text                                          
653 .align 2
654 .ent _hw_exception_handler
655 _hw_exception_handler:
656         bri     0; 
657 .end _hw_exception_handler        
658                                 
659 #endif  /* MICROBLAZE_EXCEPTIONS_ENABLED */
660
661
662