1d2912cb1SThomas Gleixner/* SPDX-License-Identifier: GPL-2.0-only */
2c4df4bc1SMichal Simek/*
3c4df4bc1SMichal Simek * Exception handling for Microblaze
4c4df4bc1SMichal Simek *
5c4df4bc1SMichal Simek * Rewriten interrupt handling
6c4df4bc1SMichal Simek *
7c4df4bc1SMichal Simek * Copyright (C) 2008-2009 Michal Simek <[email protected]>
8c4df4bc1SMichal Simek * Copyright (C) 2008-2009 PetaLogix
9c4df4bc1SMichal Simek *
10c4df4bc1SMichal Simek * uClinux customisation (C) 2005 John Williams
11c4df4bc1SMichal Simek *
12c4df4bc1SMichal Simek * MMU code derived from arch/ppc/kernel/head_4xx.S:
13c4df4bc1SMichal Simek *	Copyright (C) 1995-1996 Gary Thomas <[email protected]>
14c4df4bc1SMichal Simek *		Initial PowerPC version.
15c4df4bc1SMichal Simek *	Copyright (C) 1996 Cort Dougan <[email protected]>
16c4df4bc1SMichal Simek *		Rewritten for PReP
17c4df4bc1SMichal Simek *	Copyright (C) 1996 Paul Mackerras <[email protected]>
18c4df4bc1SMichal Simek *		Low-level exception handers, MMU support, and rewrite.
19c4df4bc1SMichal Simek *	Copyright (C) 1997 Dan Malek <[email protected]>
20c4df4bc1SMichal Simek *		PowerPC 8xx modifications.
21c4df4bc1SMichal Simek *	Copyright (C) 1998-1999 TiVo, Inc.
22c4df4bc1SMichal Simek *		PowerPC 403GCX modifications.
23c4df4bc1SMichal Simek *	Copyright (C) 1999 Grant Erickson <[email protected]>
24c4df4bc1SMichal Simek *		PowerPC 403GCX/405GP modifications.
25c4df4bc1SMichal Simek *	Copyright 2000 MontaVista Software Inc.
26c4df4bc1SMichal Simek *		PPC405 modifications
27c4df4bc1SMichal Simek *	PowerPC 403GCX/405GP modifications.
28c4df4bc1SMichal Simek *		Author: MontaVista Software, Inc.
29c4df4bc1SMichal Simek *		[email protected] or [email protected]
30c4df4bc1SMichal Simek *		[email protected]
31c4df4bc1SMichal Simek *
32c4df4bc1SMichal Simek * Original code
33c4df4bc1SMichal Simek * Copyright (C) 2004 Xilinx, Inc.
34c4df4bc1SMichal Simek */
35c4df4bc1SMichal Simek
36c4df4bc1SMichal Simek/*
37c4df4bc1SMichal Simek * Here are the handlers which don't require enabling translation
38c4df4bc1SMichal Simek * and calling other kernel code thus we can keep their design very simple
39c4df4bc1SMichal Simek * and do all processing in real mode. All what they need is a valid current
40c4df4bc1SMichal Simek * (that is an issue for the CONFIG_REGISTER_TASK_PTR case)
41c4df4bc1SMichal Simek * This handlers use r3,r4,r5,r6 and optionally r[current] to work therefore
42c4df4bc1SMichal Simek * these registers are saved/restored
43c4df4bc1SMichal Simek * The handlers which require translation are in entry.S --KAA
44c4df4bc1SMichal Simek *
45c4df4bc1SMichal Simek * Microblaze HW Exception Handler
46c4df4bc1SMichal Simek * - Non self-modifying exception handler for the following exception conditions
47c4df4bc1SMichal Simek *   - Unalignment
48c4df4bc1SMichal Simek *   - Instruction bus error
49c4df4bc1SMichal Simek *   - Data bus error
50c4df4bc1SMichal Simek *   - Illegal instruction opcode
51c4df4bc1SMichal Simek *   - Divide-by-zero
52c4df4bc1SMichal Simek *
537db29ddeSMichal Simek *   - Privileged instruction exception (MMU)
547db29ddeSMichal Simek *   - Data storage exception (MMU)
557db29ddeSMichal Simek *   - Instruction storage exception (MMU)
567db29ddeSMichal Simek *   - Data TLB miss exception (MMU)
577db29ddeSMichal Simek *   - Instruction TLB miss exception (MMU)
587db29ddeSMichal Simek *
59c4df4bc1SMichal Simek * Note we disable interrupts during exception handling, otherwise we will
60c4df4bc1SMichal Simek * possibly get multiple re-entrancy if interrupt handles themselves cause
61c4df4bc1SMichal Simek * exceptions. JW
62c4df4bc1SMichal Simek */
63c4df4bc1SMichal Simek
64c4df4bc1SMichal Simek#include <asm/exceptions.h>
65c4df4bc1SMichal Simek#include <asm/unistd.h>
66c4df4bc1SMichal Simek#include <asm/page.h>
67c4df4bc1SMichal Simek
68c4df4bc1SMichal Simek#include <asm/entry.h>
69c4df4bc1SMichal Simek#include <asm/current.h>
70c4df4bc1SMichal Simek#include <linux/linkage.h>
7165fddcfcSMike Rapoport#include <linux/pgtable.h>
72c4df4bc1SMichal Simek
73c4df4bc1SMichal Simek#include <asm/mmu.h>
743863dbceSMichal Simek#include <asm/signal.h>
7591836710SMichal Simek#include <asm/registers.h>
76c4df4bc1SMichal Simek#include <asm/asm-offsets.h>
77c4df4bc1SMichal Simek
78c06b3a06SMichal Simek#undef DEBUG
79c06b3a06SMichal Simek
80c4df4bc1SMichal Simek/* Helpful Macros */
81c4df4bc1SMichal Simek#define NUM_TO_REG(num)		r ## num
82c4df4bc1SMichal Simek
837db29ddeSMichal Simek	#define RESTORE_STATE			\
84ac854ff1SMichal Simek		lwi	r5, r1, 0;		\
85ac854ff1SMichal Simek		mts	rmsr, r5;		\
86ac854ff1SMichal Simek		nop;				\
877db29ddeSMichal Simek		lwi	r3, r1, PT_R3;		\
887db29ddeSMichal Simek		lwi	r4, r1, PT_R4;		\
897db29ddeSMichal Simek		lwi	r5, r1, PT_R5;		\
907db29ddeSMichal Simek		lwi	r6, r1, PT_R6;		\
917db29ddeSMichal Simek		lwi	r11, r1, PT_R11;	\
927db29ddeSMichal Simek		lwi	r31, r1, PT_R31;	\
936e83557cSMichal Simek		lwi	r1, r1, PT_R1;
947db29ddeSMichal Simek
95c4df4bc1SMichal Simek#define LWREG_NOP			\
96c4df4bc1SMichal Simek	bri	ex_handler_unhandled;	\
97c4df4bc1SMichal Simek	nop;
98c4df4bc1SMichal Simek
99c4df4bc1SMichal Simek#define SWREG_NOP			\
100c4df4bc1SMichal Simek	bri	ex_handler_unhandled;	\
101c4df4bc1SMichal Simek	nop;
102c4df4bc1SMichal Simek
103c4df4bc1SMichal Simek/* r3 is the source */
104c4df4bc1SMichal Simek#define R3_TO_LWREG_V(regnum)				\
105c4df4bc1SMichal Simek	swi	r3, r1, 4 * regnum;				\
106c4df4bc1SMichal Simek	bri	ex_handler_done;
107c4df4bc1SMichal Simek
108c4df4bc1SMichal Simek/* r3 is the source */
109c4df4bc1SMichal Simek#define R3_TO_LWREG(regnum)				\
110c4df4bc1SMichal Simek	or	NUM_TO_REG (regnum), r0, r3;		\
111c4df4bc1SMichal Simek	bri	ex_handler_done;
112c4df4bc1SMichal Simek
113c4df4bc1SMichal Simek/* r3 is the target */
114c4df4bc1SMichal Simek#define SWREG_TO_R3_V(regnum)				\
115c4df4bc1SMichal Simek	lwi	r3, r1, 4 * regnum;				\
116c4df4bc1SMichal Simek	bri	ex_sw_tail;
117c4df4bc1SMichal Simek
118c4df4bc1SMichal Simek/* r3 is the target */
119c4df4bc1SMichal Simek#define SWREG_TO_R3(regnum)				\
120c4df4bc1SMichal Simek	or	r3, r0, NUM_TO_REG (regnum);		\
121c4df4bc1SMichal Simek	bri	ex_sw_tail;
122c4df4bc1SMichal Simek
1237db29ddeSMichal Simek	#define R3_TO_LWREG_VM_V(regnum)		\
1247db29ddeSMichal Simek		brid	ex_lw_end_vm;			\
1257db29ddeSMichal Simek		swi	r3, r7, 4 * regnum;
1267db29ddeSMichal Simek
1277db29ddeSMichal Simek	#define R3_TO_LWREG_VM(regnum)			\
1287db29ddeSMichal Simek		brid	ex_lw_end_vm;			\
1297db29ddeSMichal Simek		or	NUM_TO_REG (regnum), r0, r3;
1307db29ddeSMichal Simek
1317db29ddeSMichal Simek	#define SWREG_TO_R3_VM_V(regnum)		\
1327db29ddeSMichal Simek		brid	ex_sw_tail_vm;			\
1337db29ddeSMichal Simek		lwi	r3, r7, 4 * regnum;
1347db29ddeSMichal Simek
1357db29ddeSMichal Simek	#define SWREG_TO_R3_VM(regnum)			\
1367db29ddeSMichal Simek		brid	ex_sw_tail_vm;			\
1377db29ddeSMichal Simek		or	r3, r0, NUM_TO_REG (regnum);
1387db29ddeSMichal Simek
1397db29ddeSMichal Simek	/* Shift right instruction depending on available configuration */
14052ade599SMichal Simek	#if CONFIG_XILINX_MICROBLAZE0_USE_BARREL == 0
1417db29ddeSMichal Simek	/* Only the used shift constants defined here - add more if needed */
1427db29ddeSMichal Simek	#define BSRLI2(rD, rA)				\
1437db29ddeSMichal Simek		srl rD, rA;		/* << 1 */	\
1447db29ddeSMichal Simek		srl rD, rD;		/* << 2 */
14552ade599SMichal Simek	#define BSRLI4(rD, rA)		\
14652ade599SMichal Simek		BSRLI2(rD, rA);		\
14752ade599SMichal Simek		BSRLI2(rD, rD)
1487db29ddeSMichal Simek	#define BSRLI10(rD, rA)				\
1497db29ddeSMichal Simek		srl rD, rA;		/* << 1 */	\
1507db29ddeSMichal Simek		srl rD, rD;		/* << 2 */	\
1517db29ddeSMichal Simek		srl rD, rD;		/* << 3 */	\
1527db29ddeSMichal Simek		srl rD, rD;		/* << 4 */	\
1537db29ddeSMichal Simek		srl rD, rD;		/* << 5 */	\
1547db29ddeSMichal Simek		srl rD, rD;		/* << 6 */	\
1557db29ddeSMichal Simek		srl rD, rD;		/* << 7 */	\
1567db29ddeSMichal Simek		srl rD, rD;		/* << 8 */	\
1577db29ddeSMichal Simek		srl rD, rD;		/* << 9 */	\
1587db29ddeSMichal Simek		srl rD, rD		/* << 10 */
1597db29ddeSMichal Simek	#define BSRLI20(rD, rA)		\
1607db29ddeSMichal Simek		BSRLI10(rD, rA);	\
1617db29ddeSMichal Simek		BSRLI10(rD, rD)
16252ade599SMichal Simek
16352ade599SMichal Simek	.macro	bsrli, rD, rA, IMM
16452ade599SMichal Simek	.if (\IMM) == 2
16552ade599SMichal Simek		BSRLI2(\rD, \rA)
16652ade599SMichal Simek	.elseif (\IMM) == 10
16752ade599SMichal Simek		BSRLI10(\rD, \rA)
16852ade599SMichal Simek	.elseif (\IMM) == 12
16952ade599SMichal Simek		BSRLI2(\rD, \rA)
17052ade599SMichal Simek		BSRLI10(\rD, \rD)
17152ade599SMichal Simek	.elseif (\IMM) == 14
17252ade599SMichal Simek		BSRLI4(\rD, \rA)
17352ade599SMichal Simek		BSRLI10(\rD, \rD)
17452ade599SMichal Simek	.elseif (\IMM) == 20
17552ade599SMichal Simek		BSRLI20(\rD, \rA)
17652ade599SMichal Simek	.elseif (\IMM) == 24
17752ade599SMichal Simek		BSRLI4(\rD, \rA)
17852ade599SMichal Simek		BSRLI20(\rD, \rD)
17952ade599SMichal Simek	.elseif (\IMM) == 28
18052ade599SMichal Simek		BSRLI4(\rD, \rA)
18152ade599SMichal Simek		BSRLI4(\rD, \rD)
18252ade599SMichal Simek		BSRLI20(\rD, \rD)
18352ade599SMichal Simek	.else
18452ade599SMichal Simek	.error "BSRLI shift macros \IMM"
18552ade599SMichal Simek	.endif
18652ade599SMichal Simek	.endm
1877db29ddeSMichal Simek	#endif
18852ade599SMichal Simek
1897db29ddeSMichal Simek
190c4df4bc1SMichal Simek.extern other_exception_handler /* Defined in exception.c */
191c4df4bc1SMichal Simek
192c4df4bc1SMichal Simek/*
193c4df4bc1SMichal Simek * hw_exception_handler - Handler for exceptions
194c4df4bc1SMichal Simek *
195c4df4bc1SMichal Simek * Exception handler notes:
196c4df4bc1SMichal Simek * - Handles all exceptions
197c4df4bc1SMichal Simek * - Does not handle unaligned exceptions during load into r17, r1, r0.
198c4df4bc1SMichal Simek * - Does not handle unaligned exceptions during store from r17 (cannot be
199c4df4bc1SMichal Simek *   done) and r1 (slows down common case)
200c4df4bc1SMichal Simek *
201c4df4bc1SMichal Simek *  Relevant register structures
202c4df4bc1SMichal Simek *
203c4df4bc1SMichal Simek *  EAR - |----|----|----|----|----|----|----|----|
204c4df4bc1SMichal Simek *      - <  ##   32 bit faulting address     ##  >
205c4df4bc1SMichal Simek *
206c4df4bc1SMichal Simek *  ESR - |----|----|----|----|----| - | - |-----|-----|
207c4df4bc1SMichal Simek *      -                            W   S   REG   EXC
208c4df4bc1SMichal Simek *
209c4df4bc1SMichal Simek *
210edf6844eSMichael Opdenacker * STACK FRAME STRUCTURE (for CONFIG_MMU=n)
211edf6844eSMichael Opdenacker * ----------------------------------------
212c4df4bc1SMichal Simek *
213c4df4bc1SMichal Simek *      +-------------+         + 0
214c4df4bc1SMichal Simek *      |     MSR     |
215c4df4bc1SMichal Simek *      +-------------+         + 4
216c4df4bc1SMichal Simek *      |     r1      |
217c4df4bc1SMichal Simek *      |      .      |
218c4df4bc1SMichal Simek *      |      .      |
219c4df4bc1SMichal Simek *      |      .      |
220c4df4bc1SMichal Simek *      |      .      |
221c4df4bc1SMichal Simek *      |     r18     |
222c4df4bc1SMichal Simek *      +-------------+         + 76
223c4df4bc1SMichal Simek *      |      .      |
224c4df4bc1SMichal Simek *      |      .      |
225c4df4bc1SMichal Simek *
2266e83557cSMichal Simek * MMU kernel uses the same 'pt_pool_space' pointed space
2276e83557cSMichal Simek * which is used for storing register values - noMMu style was, that values were
228c4df4bc1SMichal Simek * stored in stack but in case of failure you lost information about register.
229c4df4bc1SMichal Simek * Currently you can see register value in memory in specific place.
230c4df4bc1SMichal Simek * In compare to with previous solution the speed should be the same.
231c4df4bc1SMichal Simek *
232c4df4bc1SMichal Simek * MMU exception handler has different handling compare to no MMU kernel.
233c4df4bc1SMichal Simek * Exception handler use jump table for directing of what happen. For MMU kernel
234c4df4bc1SMichal Simek * is this approach better because MMU relate exception are handled by asm code
235c4df4bc1SMichal Simek * in this file. In compare to with MMU expect of unaligned exception
236c4df4bc1SMichal Simek * is everything handled by C code.
237c4df4bc1SMichal Simek */
238c4df4bc1SMichal Simek
239c4df4bc1SMichal Simek/*
240c4df4bc1SMichal Simek * every of these handlers is entered having R3/4/5/6/11/current saved on stack
241c4df4bc1SMichal Simek * and clobbered so care should be taken to restore them if someone is going to
242c4df4bc1SMichal Simek * return from exception
243c4df4bc1SMichal Simek */
244c4df4bc1SMichal Simek
245c4df4bc1SMichal Simek/* wrappers to restore state before coming to entry.S */
2466e83557cSMichal Simek.section .data
2476e83557cSMichal Simek.align 4
2486e83557cSMichal Simekpt_pool_space:
2496e83557cSMichal Simek	.space	PT_SIZE
2506e83557cSMichal Simek
251c06b3a06SMichal Simek#ifdef DEBUG
252c06b3a06SMichal Simek/* Create space for exception counting. */
253c06b3a06SMichal Simek.section .data
254c06b3a06SMichal Simek.global exception_debug_table
255c06b3a06SMichal Simek.align 4
256c06b3a06SMichal Simekexception_debug_table:
257c06b3a06SMichal Simek	/* Look at exception vector table. There is 32 exceptions * word size */
258c06b3a06SMichal Simek	.space	(32 * 4)
259c06b3a06SMichal Simek#endif /* DEBUG */
260c06b3a06SMichal Simek
2617db29ddeSMichal Simek.section .rodata
2627db29ddeSMichal Simek.align 4
2637db29ddeSMichal Simek_MB_HW_ExceptionVectorTable:
2647db29ddeSMichal Simek/*  0 - Undefined */
2657db29ddeSMichal Simek	.long	TOPHYS(ex_handler_unhandled)
2667db29ddeSMichal Simek/*  1 - Unaligned data access exception */
2677db29ddeSMichal Simek	.long	TOPHYS(handle_unaligned_ex)
2687db29ddeSMichal Simek/*  2 - Illegal op-code exception */
2697db29ddeSMichal Simek	.long	TOPHYS(full_exception_trapw)
2707db29ddeSMichal Simek/*  3 - Instruction bus error exception */
2717db29ddeSMichal Simek	.long	TOPHYS(full_exception_trapw)
2727db29ddeSMichal Simek/*  4 - Data bus error exception */
2737db29ddeSMichal Simek	.long	TOPHYS(full_exception_trapw)
2747db29ddeSMichal Simek/*  5 - Divide by zero exception */
2757db29ddeSMichal Simek	.long	TOPHYS(full_exception_trapw)
2767db29ddeSMichal Simek/*  6 - Floating point unit exception */
2777db29ddeSMichal Simek	.long	TOPHYS(full_exception_trapw)
2787db29ddeSMichal Simek/*  7 - Privileged instruction exception */
2797db29ddeSMichal Simek	.long	TOPHYS(full_exception_trapw)
2807db29ddeSMichal Simek/*  8 - 15 - Undefined */
2817db29ddeSMichal Simek	.long	TOPHYS(ex_handler_unhandled)
2827db29ddeSMichal Simek	.long	TOPHYS(ex_handler_unhandled)
2837db29ddeSMichal Simek	.long	TOPHYS(ex_handler_unhandled)
2847db29ddeSMichal Simek	.long	TOPHYS(ex_handler_unhandled)
2857db29ddeSMichal Simek	.long	TOPHYS(ex_handler_unhandled)
2867db29ddeSMichal Simek	.long	TOPHYS(ex_handler_unhandled)
2877db29ddeSMichal Simek	.long	TOPHYS(ex_handler_unhandled)
2887db29ddeSMichal Simek	.long	TOPHYS(ex_handler_unhandled)
2897db29ddeSMichal Simek/* 16 - Data storage exception */
2907db29ddeSMichal Simek	.long	TOPHYS(handle_data_storage_exception)
2917db29ddeSMichal Simek/* 17 - Instruction storage exception */
2927db29ddeSMichal Simek	.long	TOPHYS(handle_instruction_storage_exception)
2937db29ddeSMichal Simek/* 18 - Data TLB miss exception */
2947db29ddeSMichal Simek	.long	TOPHYS(handle_data_tlb_miss_exception)
2957db29ddeSMichal Simek/* 19 - Instruction TLB miss exception */
2967db29ddeSMichal Simek	.long	TOPHYS(handle_instruction_tlb_miss_exception)
2977db29ddeSMichal Simek/* 20 - 31 - Undefined */
2987db29ddeSMichal Simek	.long	TOPHYS(ex_handler_unhandled)
2997db29ddeSMichal Simek	.long	TOPHYS(ex_handler_unhandled)
3007db29ddeSMichal Simek	.long	TOPHYS(ex_handler_unhandled)
3017db29ddeSMichal Simek	.long	TOPHYS(ex_handler_unhandled)
3027db29ddeSMichal Simek	.long	TOPHYS(ex_handler_unhandled)
3037db29ddeSMichal Simek	.long	TOPHYS(ex_handler_unhandled)
3047db29ddeSMichal Simek	.long	TOPHYS(ex_handler_unhandled)
3057db29ddeSMichal Simek	.long	TOPHYS(ex_handler_unhandled)
3067db29ddeSMichal Simek	.long	TOPHYS(ex_handler_unhandled)
3077db29ddeSMichal Simek	.long	TOPHYS(ex_handler_unhandled)
3087db29ddeSMichal Simek	.long	TOPHYS(ex_handler_unhandled)
3097db29ddeSMichal Simek	.long	TOPHYS(ex_handler_unhandled)
3107db29ddeSMichal Simek
311c4df4bc1SMichal Simek.global _hw_exception_handler
312c4df4bc1SMichal Simek.section .text
313c4df4bc1SMichal Simek.align 4
314c4df4bc1SMichal Simek.ent _hw_exception_handler
315c4df4bc1SMichal Simek_hw_exception_handler:
3166e83557cSMichal Simek	swi	r1, r0, TOPHYS(pt_pool_space + PT_R1); /* GET_SP */
3177db29ddeSMichal Simek	/* Save date to kernel memory. Here is the problem
3187db29ddeSMichal Simek	 * when you came from user space */
3196e83557cSMichal Simek	ori	r1, r0, TOPHYS(pt_pool_space);
320c4df4bc1SMichal Simek	swi	r3, r1, PT_R3
321c4df4bc1SMichal Simek	swi	r4, r1, PT_R4
322c4df4bc1SMichal Simek	swi	r5, r1, PT_R5
323c4df4bc1SMichal Simek	swi	r6, r1, PT_R6
324c4df4bc1SMichal Simek
3257db29ddeSMichal Simek	swi	r11, r1, PT_R11
3267db29ddeSMichal Simek	swi	r31, r1, PT_R31
3277db29ddeSMichal Simek	lwi	r31, r0, TOPHYS(PER_CPU(CURRENT_SAVE)) /* get saved current */
3287db29ddeSMichal Simek
329ac854ff1SMichal Simek	mfs	r5, rmsr;
330ac854ff1SMichal Simek	nop
331ac854ff1SMichal Simek	swi	r5, r1, 0;
332b175bcfeSMichal Simek	mfs	r4, resr
333c4df4bc1SMichal Simek	nop
334b175bcfeSMichal Simek	mfs	r3, rear;
3357db29ddeSMichal Simek	nop
336c4df4bc1SMichal Simek
337b175bcfeSMichal Simek	andi	r5, r4, 0x1F;		/* Extract ESR[EXC] */
338c4df4bc1SMichal Simek
3397db29ddeSMichal Simek	/* Calculate exception vector offset = r5 << 2 */
3407db29ddeSMichal Simek	addk	r6, r5, r5; /* << 1 */
3417db29ddeSMichal Simek	addk	r6, r6, r6; /* << 2 */
3427db29ddeSMichal Simek
343708e7153SMichal Simek#ifdef DEBUG
3447db29ddeSMichal Simek/* counting which exception happen */
345c06b3a06SMichal Simek	lwi	r5, r0, TOPHYS(exception_debug_table)
3467db29ddeSMichal Simek	addi	r5, r5, 1
347c06b3a06SMichal Simek	swi	r5, r0, TOPHYS(exception_debug_table)
348c06b3a06SMichal Simek	lwi	r5, r6, TOPHYS(exception_debug_table)
3497db29ddeSMichal Simek	addi	r5, r5, 1
350c06b3a06SMichal Simek	swi	r5, r6, TOPHYS(exception_debug_table)
351708e7153SMichal Simek#endif
3527db29ddeSMichal Simek/* end */
3537db29ddeSMichal Simek	/* Load the HW Exception vector */
3547db29ddeSMichal Simek	lwi	r6, r6, TOPHYS(_MB_HW_ExceptionVectorTable)
3557db29ddeSMichal Simek	bra	r6
3567db29ddeSMichal Simek
3577db29ddeSMichal Simekfull_exception_trapw:
3587db29ddeSMichal Simek	RESTORE_STATE
3597db29ddeSMichal Simek	bri	full_exception_trap
360c4df4bc1SMichal Simek
361c4df4bc1SMichal Simek/* 0x01 - Unaligned data access exception
362c4df4bc1SMichal Simek * This occurs when a word access is not aligned on a word boundary,
363c4df4bc1SMichal Simek * or when a 16-bit access is not aligned on a 16-bit boundary.
364c4df4bc1SMichal Simek * This handler perform the access, and returns, except for MMU when
365c4df4bc1SMichal Simek * the unaligned address is last on a 4k page or the physical address is
366c4df4bc1SMichal Simek * not found in the page table, in which case unaligned_data_trap is called.
367c4df4bc1SMichal Simek */
368c4df4bc1SMichal Simekhandle_unaligned_ex:
369c4df4bc1SMichal Simek	/* Working registers already saved: R3, R4, R5, R6
370b175bcfeSMichal Simek	 *  R4 = ESR
371b175bcfeSMichal Simek	 *  R3 = EAR
372c4df4bc1SMichal Simek	 */
373b175bcfeSMichal Simek	andi	r6, r4, 0x1000			/* Check ESR[DS] */
3747db29ddeSMichal Simek	beqi	r6, _no_delayslot		/* Branch if ESR[DS] not set */
3757db29ddeSMichal Simek	mfs	r17, rbtr;	/* ESR[DS] set - return address in BTR */
376c4df4bc1SMichal Simek	nop
3777db29ddeSMichal Simek_no_delayslot:
3783863dbceSMichal Simek	/* jump to high level unaligned handler */
3797db29ddeSMichal Simek	RESTORE_STATE;
3807db29ddeSMichal Simek	bri	unaligned_data_trap
381*05cdf457SMichal Simek
382b175bcfeSMichal Simek	andi	r6, r4, 0x3E0; /* Mask and extract the register operand */
383c4df4bc1SMichal Simek	srl	r6, r6; /* r6 >> 5 */
384c4df4bc1SMichal Simek	srl	r6, r6;
385c4df4bc1SMichal Simek	srl	r6, r6;
386c4df4bc1SMichal Simek	srl	r6, r6;
387c4df4bc1SMichal Simek	srl	r6, r6;
388c4df4bc1SMichal Simek	/* Store the register operand in a temporary location */
389c4df4bc1SMichal Simek	sbi	r6, r0, TOPHYS(ex_reg_op);
390c4df4bc1SMichal Simek
391b175bcfeSMichal Simek	andi	r6, r4, 0x400; /* Extract ESR[S] */
392c4df4bc1SMichal Simek	bnei	r6, ex_sw;
393c4df4bc1SMichal Simekex_lw:
394b175bcfeSMichal Simek	andi	r6, r4, 0x800; /* Extract ESR[W] */
395c4df4bc1SMichal Simek	beqi	r6, ex_lhw;
396b175bcfeSMichal Simek	lbui	r5, r3, 0; /* Exception address in r3 */
397c4df4bc1SMichal Simek	/* Load a word, byte-by-byte from destination address
398c4df4bc1SMichal Simek		and save it in tmp space */
399c4df4bc1SMichal Simek	sbi	r5, r0, TOPHYS(ex_tmp_data_loc_0);
400b175bcfeSMichal Simek	lbui	r5, r3, 1;
401c4df4bc1SMichal Simek	sbi	r5, r0, TOPHYS(ex_tmp_data_loc_1);
402b175bcfeSMichal Simek	lbui	r5, r3, 2;
403c4df4bc1SMichal Simek	sbi	r5, r0, TOPHYS(ex_tmp_data_loc_2);
404b175bcfeSMichal Simek	lbui	r5, r3, 3;
405c4df4bc1SMichal Simek	sbi	r5, r0, TOPHYS(ex_tmp_data_loc_3);
406b175bcfeSMichal Simek	/* Get the destination register value into r4 */
407b175bcfeSMichal Simek	lwi	r4, r0, TOPHYS(ex_tmp_data_loc_0);
408c4df4bc1SMichal Simek	bri	ex_lw_tail;
409c4df4bc1SMichal Simekex_lhw:
410b175bcfeSMichal Simek	lbui	r5, r3, 0; /* Exception address in r3 */
411c4df4bc1SMichal Simek	/* Load a half-word, byte-by-byte from destination
412c4df4bc1SMichal Simek		address and save it in tmp space */
413c4df4bc1SMichal Simek	sbi	r5, r0, TOPHYS(ex_tmp_data_loc_0);
414b175bcfeSMichal Simek	lbui	r5, r3, 1;
415c4df4bc1SMichal Simek	sbi	r5, r0, TOPHYS(ex_tmp_data_loc_1);
416b175bcfeSMichal Simek	/* Get the destination register value into r4 */
417b175bcfeSMichal Simek	lhui	r4, r0, TOPHYS(ex_tmp_data_loc_0);
418c4df4bc1SMichal Simekex_lw_tail:
419c4df4bc1SMichal Simek	/* Get the destination register number into r5 */
420c4df4bc1SMichal Simek	lbui	r5, r0, TOPHYS(ex_reg_op);
421c4df4bc1SMichal Simek	/* Form load_word jump table offset (lw_table + (8 * regnum)) */
422cd341577SMichal Simek	addik	r6, r0, TOPHYS(lw_table);
423c4df4bc1SMichal Simek	addk	r5, r5, r5;
424c4df4bc1SMichal Simek	addk	r5, r5, r5;
425c4df4bc1SMichal Simek	addk	r5, r5, r5;
426c4df4bc1SMichal Simek	addk	r5, r5, r6;
427c4df4bc1SMichal Simek	bra	r5;
428c4df4bc1SMichal Simekex_lw_end: /* Exception handling of load word, ends */
429c4df4bc1SMichal Simekex_sw:
430c4df4bc1SMichal Simek	/* Get the destination register number into r5 */
431c4df4bc1SMichal Simek	lbui	r5, r0, TOPHYS(ex_reg_op);
432c4df4bc1SMichal Simek	/* Form store_word jump table offset (sw_table + (8 * regnum)) */
433cd341577SMichal Simek	addik	r6, r0, TOPHYS(sw_table);
434c4df4bc1SMichal Simek	add	r5, r5, r5;
435c4df4bc1SMichal Simek	add	r5, r5, r5;
436c4df4bc1SMichal Simek	add	r5, r5, r5;
437c4df4bc1SMichal Simek	add	r5, r5, r6;
438c4df4bc1SMichal Simek	bra	r5;
439c4df4bc1SMichal Simekex_sw_tail:
440c4df4bc1SMichal Simek	mfs	r6, resr;
441c4df4bc1SMichal Simek	nop
442c4df4bc1SMichal Simek	andi	r6, r6, 0x800; /* Extract ESR[W] */
443c4df4bc1SMichal Simek	beqi	r6, ex_shw;
444c4df4bc1SMichal Simek	/* Get the word - delay slot */
445b175bcfeSMichal Simek	swi	r4, r0, TOPHYS(ex_tmp_data_loc_0);
446c4df4bc1SMichal Simek	/* Store the word, byte-by-byte into destination address */
447b175bcfeSMichal Simek	lbui	r4, r0, TOPHYS(ex_tmp_data_loc_0);
448b175bcfeSMichal Simek	sbi	r4, r3, 0;
449b175bcfeSMichal Simek	lbui	r4, r0, TOPHYS(ex_tmp_data_loc_1);
450b175bcfeSMichal Simek	sbi	r4, r3, 1;
451b175bcfeSMichal Simek	lbui	r4, r0, TOPHYS(ex_tmp_data_loc_2);
452b175bcfeSMichal Simek	sbi	r4, r3, 2;
453b175bcfeSMichal Simek	lbui	r4, r0, TOPHYS(ex_tmp_data_loc_3);
454b175bcfeSMichal Simek	sbi	r4, r3, 3;
455c4df4bc1SMichal Simek	bri	ex_handler_done;
456c4df4bc1SMichal Simek
457c4df4bc1SMichal Simekex_shw:
458c4df4bc1SMichal Simek	/* Store the lower half-word, byte-by-byte into destination address */
459b175bcfeSMichal Simek	swi	r4, r0, TOPHYS(ex_tmp_data_loc_0);
460b175bcfeSMichal Simek	lbui	r4, r0, TOPHYS(ex_tmp_data_loc_2);
461b175bcfeSMichal Simek	sbi	r4, r3, 0;
462b175bcfeSMichal Simek	lbui	r4, r0, TOPHYS(ex_tmp_data_loc_3);
463b175bcfeSMichal Simek	sbi	r4, r3, 1;
464c4df4bc1SMichal Simekex_sw_end: /* Exception handling of store word, ends. */
465c4df4bc1SMichal Simek
466c4df4bc1SMichal Simekex_handler_done:
4677db29ddeSMichal Simek	RESTORE_STATE;
4687db29ddeSMichal Simek	rted	r17, 0
4697db29ddeSMichal Simek	nop
470c4df4bc1SMichal Simek
4717db29ddeSMichal Simek	/* Exception vector entry code. This code runs with address translation
4727db29ddeSMichal Simek	 * turned off (i.e. using physical addresses). */
4737db29ddeSMichal Simek
4747db29ddeSMichal Simek	/* Exception vectors. */
4757db29ddeSMichal Simek
4767db29ddeSMichal Simek	/* 0x10 - Data Storage Exception
4777db29ddeSMichal Simek	 * This happens for just a few reasons. U0 set (but we don't do that),
4787db29ddeSMichal Simek	 * or zone protection fault (user violation, write to protected page).
4797db29ddeSMichal Simek	 * If this is just an update of modified status, we do that quickly
4807db29ddeSMichal Simek	 * and exit. Otherwise, we call heavyweight functions to do the work.
4817db29ddeSMichal Simek	 */
4827db29ddeSMichal Simek	handle_data_storage_exception:
4837db29ddeSMichal Simek		/* Working registers already saved: R3, R4, R5, R6
4847db29ddeSMichal Simek		 * R3 = ESR
4857db29ddeSMichal Simek		 */
4867db29ddeSMichal Simek		mfs	r11, rpid
4877db29ddeSMichal Simek		nop
4887db29ddeSMichal Simek		/* If we are faulting a kernel address, we have to use the
4897db29ddeSMichal Simek		 * kernel page tables.
4907db29ddeSMichal Simek		 */
491bd1637d6SMichal Simek		ori	r5, r0, CONFIG_KERNEL_START
492bd1637d6SMichal Simek		cmpu	r5, r3, r5
493bd1637d6SMichal Simek		bgti	r5, ex3
4947db29ddeSMichal Simek		/* First, check if it was a zone fault (which means a user
4957db29ddeSMichal Simek		 * tried to access a kernel or read-protected page - always
4967db29ddeSMichal Simek		 * a SEGV). All other faults here must be stores, so no
4977db29ddeSMichal Simek		 * need to check ESR_S as well. */
49891836710SMichal Simek		andi	r4, r4, ESR_DIZ		/* ESR_Z - zone protection */
4997db29ddeSMichal Simek		bnei	r4, ex2
5007db29ddeSMichal Simek
5017db29ddeSMichal Simek		ori	r4, r0, swapper_pg_dir
5027db29ddeSMichal Simek		mts	rpid, r0		/* TLB will have 0 TID */
5037db29ddeSMichal Simek		nop
5047db29ddeSMichal Simek		bri	ex4
5057db29ddeSMichal Simek
5067db29ddeSMichal Simek		/* Get the PGD for the current thread. */
5077db29ddeSMichal Simek	ex3:
5087db29ddeSMichal Simek		/* First, check if it was a zone fault (which means a user
5097db29ddeSMichal Simek		 * tried to access a kernel or read-protected page - always
5107db29ddeSMichal Simek		 * a SEGV). All other faults here must be stores, so no
5117db29ddeSMichal Simek		 * need to check ESR_S as well. */
51291836710SMichal Simek		andi	r4, r4, ESR_DIZ		/* ESR_Z */
5137db29ddeSMichal Simek		bnei	r4, ex2
5147db29ddeSMichal Simek		/* get current task address */
5157db29ddeSMichal Simek		addi	r4 ,CURRENT_TASK, TOPHYS(0);
5167db29ddeSMichal Simek		lwi	r4, r4, TASK_THREAD+PGDIR
5177db29ddeSMichal Simek	ex4:
5187db29ddeSMichal Simek		tophys(r4,r4)
5199f78d3b5SMichal Simek		/* Create L1 (pgdir/pmd) address */
52052ade599SMichal Simek		bsrli	r5, r3, PGDIR_SHIFT - 2
5219f78d3b5SMichal Simek		andi	r5, r5, PAGE_SIZE - 4
5227db29ddeSMichal Simek/* Assume pgdir aligned on 4K boundary, no need for "andi r4,r4,0xfffff003" */
5237db29ddeSMichal Simek		or	r4, r4, r5
5247db29ddeSMichal Simek		lwi	r4, r4, 0		/* Get L1 entry */
5259f78d3b5SMichal Simek		andi	r5, r4, PAGE_MASK /* Extract L2 (pte) base address */
5267db29ddeSMichal Simek		beqi	r5, ex2			/* Bail if no table */
5277db29ddeSMichal Simek
5287db29ddeSMichal Simek		tophys(r5,r5)
52952ade599SMichal Simek		bsrli	r6, r3, PTE_SHIFT /* Compute PTE address */
5309f78d3b5SMichal Simek		andi	r6, r6, PAGE_SIZE - 4
5317db29ddeSMichal Simek		or	r5, r5, r6
5327db29ddeSMichal Simek		lwi	r4, r5, 0		/* Get Linux PTE */
5337db29ddeSMichal Simek
5347db29ddeSMichal Simek		andi	r6, r4, _PAGE_RW	/* Is it writeable? */
5357db29ddeSMichal Simek		beqi	r6, ex2			/* Bail if not */
5367db29ddeSMichal Simek
5377db29ddeSMichal Simek		/* Update 'changed' */
5387db29ddeSMichal Simek		ori	r4, r4, _PAGE_DIRTY|_PAGE_ACCESSED|_PAGE_HWWRITE
5397db29ddeSMichal Simek		swi	r4, r5, 0		/* Update Linux page table */
5407db29ddeSMichal Simek
5417db29ddeSMichal Simek		/* Most of the Linux PTE is ready to load into the TLB LO.
5427db29ddeSMichal Simek		 * We set ZSEL, where only the LS-bit determines user access.
5437db29ddeSMichal Simek		 * We set execute, because we don't have the granularity to
5447db29ddeSMichal Simek		 * properly set this at the page level (Linux problem).
5457db29ddeSMichal Simek		 * If shared is set, we cause a zero PID->TID load.
5467db29ddeSMichal Simek		 * Many of these bits are software only. Bits we don't set
5477db29ddeSMichal Simek		 * here we (properly should) assume have the appropriate value.
5487db29ddeSMichal Simek		 */
5499f78d3b5SMichal Simek/* Ignore memory coherent, just LSB on ZSEL is used + EX/WR */
5509f78d3b5SMichal Simek		andi	r4, r4, PAGE_MASK | TLB_EX | TLB_WR | \
5519f78d3b5SMichal Simek						TLB_ZSEL(1) | TLB_ATTR_MASK
5527db29ddeSMichal Simek		ori	r4, r4, _PAGE_HWEXEC	/* make it executable */
5537db29ddeSMichal Simek
5547db29ddeSMichal Simek		/* find the TLB index that caused the fault. It has to be here*/
5557db29ddeSMichal Simek		mts	rtlbsx, r3
5567db29ddeSMichal Simek		nop
5577db29ddeSMichal Simek		mfs	r5, rtlbx		/* DEBUG: TBD */
5587db29ddeSMichal Simek		nop
5597db29ddeSMichal Simek		mts	rtlblo, r4		/* Load TLB LO */
5607db29ddeSMichal Simek		nop
5617db29ddeSMichal Simek						/* Will sync shadow TLBs */
5627db29ddeSMichal Simek
5637db29ddeSMichal Simek		/* Done...restore registers and get out of here. */
5647db29ddeSMichal Simek		mts	rpid, r11
5657db29ddeSMichal Simek		nop
5667db29ddeSMichal Simek		bri 4
5677db29ddeSMichal Simek
5687db29ddeSMichal Simek		RESTORE_STATE;
5697db29ddeSMichal Simek		rted	r17, 0
5707db29ddeSMichal Simek		nop
5717db29ddeSMichal Simek	ex2:
5727db29ddeSMichal Simek		/* The bailout. Restore registers to pre-exception conditions
5737db29ddeSMichal Simek		 * and call the heavyweights to help us out. */
5747db29ddeSMichal Simek		mts	rpid, r11
5757db29ddeSMichal Simek		nop
5767db29ddeSMichal Simek		bri 4
5777db29ddeSMichal Simek		RESTORE_STATE;
5787db29ddeSMichal Simek		bri	page_fault_data_trap
5797db29ddeSMichal Simek
5807db29ddeSMichal Simek
5817db29ddeSMichal Simek	/* 0x11 - Instruction Storage Exception
5827db29ddeSMichal Simek	 * This is caused by a fetch from non-execute or guarded pages. */
5837db29ddeSMichal Simek	handle_instruction_storage_exception:
5847db29ddeSMichal Simek		/* Working registers already saved: R3, R4, R5, R6
5857db29ddeSMichal Simek		 * R3 = ESR
5867db29ddeSMichal Simek		 */
5877db29ddeSMichal Simek
5887db29ddeSMichal Simek		RESTORE_STATE;
5897db29ddeSMichal Simek		bri	page_fault_instr_trap
5907db29ddeSMichal Simek
5917db29ddeSMichal Simek	/* 0x12 - Data TLB Miss Exception
5927db29ddeSMichal Simek	 * As the name implies, translation is not in the MMU, so search the
5937db29ddeSMichal Simek	 * page tables and fix it. The only purpose of this function is to
5947db29ddeSMichal Simek	 * load TLB entries from the page table if they exist.
5957db29ddeSMichal Simek	 */
5967db29ddeSMichal Simek	handle_data_tlb_miss_exception:
5977db29ddeSMichal Simek		/* Working registers already saved: R3, R4, R5, R6
5987a6bbdc9SMichal Simek		 * R3 = EAR, R4 = ESR
5997db29ddeSMichal Simek		 */
6007db29ddeSMichal Simek		mfs	r11, rpid
6017db29ddeSMichal Simek		nop
6027db29ddeSMichal Simek
6037db29ddeSMichal Simek		/* If we are faulting a kernel address, we have to use the
6047db29ddeSMichal Simek		 * kernel page tables. */
6057a6bbdc9SMichal Simek		ori	r6, r0, CONFIG_KERNEL_START
6067a6bbdc9SMichal Simek		cmpu	r4, r3, r6
6077db29ddeSMichal Simek		bgti	r4, ex5
6087db29ddeSMichal Simek		ori	r4, r0, swapper_pg_dir
6097db29ddeSMichal Simek		mts	rpid, r0		/* TLB will have 0 TID */
6107db29ddeSMichal Simek		nop
6117db29ddeSMichal Simek		bri	ex6
6127db29ddeSMichal Simek
6137db29ddeSMichal Simek		/* Get the PGD for the current thread. */
6147db29ddeSMichal Simek	ex5:
6157db29ddeSMichal Simek		/* get current task address */
6167db29ddeSMichal Simek		addi	r4 ,CURRENT_TASK, TOPHYS(0);
6177db29ddeSMichal Simek		lwi	r4, r4, TASK_THREAD+PGDIR
6187db29ddeSMichal Simek	ex6:
6197db29ddeSMichal Simek		tophys(r4,r4)
6209f78d3b5SMichal Simek		/* Create L1 (pgdir/pmd) address */
62152ade599SMichal Simek		bsrli	r5, r3, PGDIR_SHIFT - 2
6229f78d3b5SMichal Simek		andi	r5, r5, PAGE_SIZE - 4
6237db29ddeSMichal Simek/* Assume pgdir aligned on 4K boundary, no need for "andi r4,r4,0xfffff003" */
6247db29ddeSMichal Simek		or	r4, r4, r5
6257db29ddeSMichal Simek		lwi	r4, r4, 0		/* Get L1 entry */
6269f78d3b5SMichal Simek		andi	r5, r4, PAGE_MASK /* Extract L2 (pte) base address */
6277db29ddeSMichal Simek		beqi	r5, ex7			/* Bail if no table */
6287db29ddeSMichal Simek
6297db29ddeSMichal Simek		tophys(r5,r5)
63052ade599SMichal Simek		bsrli	r6, r3, PTE_SHIFT /* Compute PTE address */
6319f78d3b5SMichal Simek		andi	r6, r6, PAGE_SIZE - 4
6327db29ddeSMichal Simek		or	r5, r5, r6
6337db29ddeSMichal Simek		lwi	r4, r5, 0		/* Get Linux PTE */
6347db29ddeSMichal Simek
6357db29ddeSMichal Simek		andi	r6, r4, _PAGE_PRESENT
6367db29ddeSMichal Simek		beqi	r6, ex7
6377db29ddeSMichal Simek
6387db29ddeSMichal Simek		ori	r4, r4, _PAGE_ACCESSED
6397db29ddeSMichal Simek		swi	r4, r5, 0
6407db29ddeSMichal Simek
6417db29ddeSMichal Simek		/* Most of the Linux PTE is ready to load into the TLB LO.
6427db29ddeSMichal Simek		 * We set ZSEL, where only the LS-bit determines user access.
6437db29ddeSMichal Simek		 * We set execute, because we don't have the granularity to
6447db29ddeSMichal Simek		 * properly set this at the page level (Linux problem).
6457db29ddeSMichal Simek		 * If shared is set, we cause a zero PID->TID load.
6467db29ddeSMichal Simek		 * Many of these bits are software only. Bits we don't set
6477db29ddeSMichal Simek		 * here we (properly should) assume have the appropriate value.
6487db29ddeSMichal Simek		 */
6493765d695SMichal Simek		brid	finish_tlb_load
6509f78d3b5SMichal Simek		andi	r4, r4, PAGE_MASK | TLB_EX | TLB_WR | \
6519f78d3b5SMichal Simek						TLB_ZSEL(1) | TLB_ATTR_MASK
6527db29ddeSMichal Simek	ex7:
6537db29ddeSMichal Simek		/* The bailout. Restore registers to pre-exception conditions
6547db29ddeSMichal Simek		 * and call the heavyweights to help us out.
6557db29ddeSMichal Simek		 */
6567db29ddeSMichal Simek		mts	rpid, r11
6577db29ddeSMichal Simek		nop
6587db29ddeSMichal Simek		bri	4
6597db29ddeSMichal Simek		RESTORE_STATE;
6607db29ddeSMichal Simek		bri	page_fault_data_trap
6617db29ddeSMichal Simek
6627db29ddeSMichal Simek	/* 0x13 - Instruction TLB Miss Exception
6637db29ddeSMichal Simek	 * Nearly the same as above, except we get our information from
6647db29ddeSMichal Simek	 * different registers and bailout to a different point.
6657db29ddeSMichal Simek	 */
6667db29ddeSMichal Simek	handle_instruction_tlb_miss_exception:
6677db29ddeSMichal Simek		/* Working registers already saved: R3, R4, R5, R6
6687db29ddeSMichal Simek		 *  R3 = ESR
6697db29ddeSMichal Simek		 */
6707db29ddeSMichal Simek		mfs	r11, rpid
6717db29ddeSMichal Simek		nop
6727db29ddeSMichal Simek
6737db29ddeSMichal Simek		/* If we are faulting a kernel address, we have to use the
6747db29ddeSMichal Simek		 * kernel page tables.
6757db29ddeSMichal Simek		 */
6767db29ddeSMichal Simek		ori	r4, r0, CONFIG_KERNEL_START
6777db29ddeSMichal Simek		cmpu	r4, r3, r4
6787db29ddeSMichal Simek		bgti	r4, ex8
6797db29ddeSMichal Simek		ori	r4, r0, swapper_pg_dir
6807db29ddeSMichal Simek		mts	rpid, r0		/* TLB will have 0 TID */
6817db29ddeSMichal Simek		nop
6827db29ddeSMichal Simek		bri	ex9
6837db29ddeSMichal Simek
6847db29ddeSMichal Simek		/* Get the PGD for the current thread. */
6857db29ddeSMichal Simek	ex8:
6867db29ddeSMichal Simek		/* get current task address */
6877db29ddeSMichal Simek		addi	r4 ,CURRENT_TASK, TOPHYS(0);
6887db29ddeSMichal Simek		lwi	r4, r4, TASK_THREAD+PGDIR
6897db29ddeSMichal Simek	ex9:
6907db29ddeSMichal Simek		tophys(r4,r4)
6919f78d3b5SMichal Simek		/* Create L1 (pgdir/pmd) address */
69252ade599SMichal Simek		bsrli	r5, r3, PGDIR_SHIFT - 2
6939f78d3b5SMichal Simek		andi	r5, r5, PAGE_SIZE - 4
6947db29ddeSMichal Simek/* Assume pgdir aligned on 4K boundary, no need for "andi r4,r4,0xfffff003" */
6957db29ddeSMichal Simek		or	r4, r4, r5
6967db29ddeSMichal Simek		lwi	r4, r4, 0		/* Get L1 entry */
6979f78d3b5SMichal Simek		andi	r5, r4, PAGE_MASK /* Extract L2 (pte) base address */
6987db29ddeSMichal Simek		beqi	r5, ex10		/* Bail if no table */
6997db29ddeSMichal Simek
7007db29ddeSMichal Simek		tophys(r5,r5)
70152ade599SMichal Simek		bsrli	r6, r3, PTE_SHIFT /* Compute PTE address */
7029f78d3b5SMichal Simek		andi	r6, r6, PAGE_SIZE - 4
7037db29ddeSMichal Simek		or	r5, r5, r6
7047db29ddeSMichal Simek		lwi	r4, r5, 0		/* Get Linux PTE */
7057db29ddeSMichal Simek
7067db29ddeSMichal Simek		andi	r6, r4, _PAGE_PRESENT
7073765d695SMichal Simek		beqi	r6, ex10
7087db29ddeSMichal Simek
7097db29ddeSMichal Simek		ori	r4, r4, _PAGE_ACCESSED
7107db29ddeSMichal Simek		swi	r4, r5, 0
7117db29ddeSMichal Simek
7127db29ddeSMichal Simek		/* Most of the Linux PTE is ready to load into the TLB LO.
7137db29ddeSMichal Simek		 * We set ZSEL, where only the LS-bit determines user access.
7147db29ddeSMichal Simek		 * We set execute, because we don't have the granularity to
7157db29ddeSMichal Simek		 * properly set this at the page level (Linux problem).
7167db29ddeSMichal Simek		 * If shared is set, we cause a zero PID->TID load.
7177db29ddeSMichal Simek		 * Many of these bits are software only. Bits we don't set
7187db29ddeSMichal Simek		 * here we (properly should) assume have the appropriate value.
7197db29ddeSMichal Simek		 */
7203765d695SMichal Simek		brid	finish_tlb_load
7219f78d3b5SMichal Simek		andi	r4, r4, PAGE_MASK | TLB_EX | TLB_WR | \
7229f78d3b5SMichal Simek						TLB_ZSEL(1) | TLB_ATTR_MASK
7237db29ddeSMichal Simek	ex10:
7247db29ddeSMichal Simek		/* The bailout. Restore registers to pre-exception conditions
7257db29ddeSMichal Simek		 * and call the heavyweights to help us out.
7267db29ddeSMichal Simek		 */
7277db29ddeSMichal Simek		mts	rpid, r11
7287db29ddeSMichal Simek		nop
7297db29ddeSMichal Simek		bri 4
7307db29ddeSMichal Simek		RESTORE_STATE;
7317db29ddeSMichal Simek		bri	page_fault_instr_trap
7327db29ddeSMichal Simek
7337db29ddeSMichal Simek/* Both the instruction and data TLB miss get to this point to load the TLB.
7347db29ddeSMichal Simek *	r3 - EA of fault
7357db29ddeSMichal Simek *	r4 - TLB LO (info from Linux PTE)
7367db29ddeSMichal Simek *	r5, r6 - available to use
7377db29ddeSMichal Simek *	PID - loaded with proper value when we get here
7387db29ddeSMichal Simek *	Upon exit, we reload everything and RFI.
7397db29ddeSMichal Simek * A common place to load the TLB.
7407db29ddeSMichal Simek */
741e02db0aaSMichal Simek.section .data
742e02db0aaSMichal Simek.align 4
743e02db0aaSMichal Simek.global tlb_skip
744e02db0aaSMichal Simek	tlb_skip:
745e02db0aaSMichal Simek		.long	MICROBLAZE_TLB_SKIP
7467db29ddeSMichal Simek	tlb_index:
7471451d1d8SMichal Simek		/* MS: storing last used tlb index */
748e02db0aaSMichal Simek		.long	MICROBLAZE_TLB_SIZE/2
749e02db0aaSMichal Simek.previous
7507db29ddeSMichal Simek	finish_tlb_load:
7517db29ddeSMichal Simek		/* MS: load the last used TLB index. */
7527db29ddeSMichal Simek		lwi	r5, r0, TOPHYS(tlb_index)
7537db29ddeSMichal Simek		addik	r5, r5, 1 /* MS: inc tlb_index -> use next one */
7547db29ddeSMichal Simek
7557db29ddeSMichal Simek/* MS: FIXME this is potential fault, because this is mask not count */
7561451d1d8SMichal Simek		andi	r5, r5, MICROBLAZE_TLB_SIZE - 1
7577db29ddeSMichal Simek		ori	r6, r0, 1
7587db29ddeSMichal Simek		cmp	r31, r5, r6
7593765d695SMichal Simek		blti	r31, ex12
760e02db0aaSMichal Simek		lwi	r5, r0, TOPHYS(tlb_skip)
7613765d695SMichal Simek	ex12:
7627db29ddeSMichal Simek		/* MS: save back current TLB index */
7637db29ddeSMichal Simek		swi	r5, r0, TOPHYS(tlb_index)
7647db29ddeSMichal Simek
7657db29ddeSMichal Simek		ori	r4, r4, _PAGE_HWEXEC	/* make it executable */
7667db29ddeSMichal Simek		mts	rtlbx, r5		/* MS: save current TLB */
7677db29ddeSMichal Simek		nop
7687db29ddeSMichal Simek		mts	rtlblo,	r4		/* MS: save to TLB LO */
7697db29ddeSMichal Simek		nop
7707db29ddeSMichal Simek
7717db29ddeSMichal Simek		/* Create EPN. This is the faulting address plus a static
7727db29ddeSMichal Simek		 * set of bits. These are size, valid, E, U0, and ensure
7737db29ddeSMichal Simek		 * bits 20 and 21 are zero.
7747db29ddeSMichal Simek		 */
7759f78d3b5SMichal Simek		andi	r3, r3, PAGE_MASK
7769f78d3b5SMichal Simek		ori	r3, r3, TLB_VALID | TLB_PAGESZ(PAGESZ_4K)
7777db29ddeSMichal Simek		mts	rtlbhi,	r3		/* Load TLB HI */
7787db29ddeSMichal Simek		nop
7797db29ddeSMichal Simek
7807db29ddeSMichal Simek		/* Done...restore registers and get out of here. */
7817db29ddeSMichal Simek		mts	rpid, r11
7827db29ddeSMichal Simek		nop
7837db29ddeSMichal Simek		bri 4
7847db29ddeSMichal Simek		RESTORE_STATE;
7857db29ddeSMichal Simek		rted	r17, 0
7867db29ddeSMichal Simek		nop
7877db29ddeSMichal Simek
7887db29ddeSMichal Simek	/* extern void giveup_fpu(struct task_struct *prev)
7897db29ddeSMichal Simek	 *
7907db29ddeSMichal Simek	 * The MicroBlaze processor may have an FPU, so this should not just
7917db29ddeSMichal Simek	 * return: TBD.
7927db29ddeSMichal Simek	 */
7937db29ddeSMichal Simek	.globl giveup_fpu;
7947db29ddeSMichal Simek	.align 4;
7957db29ddeSMichal Simek	giveup_fpu:
7967db29ddeSMichal Simek		bralid	r15,0			/* TBD */
7977db29ddeSMichal Simek		nop
7987db29ddeSMichal Simek
7997db29ddeSMichal Simek	/* At present, this routine just hangs. - extern void abort(void) */
8007db29ddeSMichal Simek	.globl abort;
8017db29ddeSMichal Simek	.align 4;
8027db29ddeSMichal Simek	abort:
8037db29ddeSMichal Simek		br	r0
8047db29ddeSMichal Simek
8057db29ddeSMichal Simek	.globl set_context;
8067db29ddeSMichal Simek	.align 4;
8077db29ddeSMichal Simek	set_context:
8087db29ddeSMichal Simek		mts	rpid, r5	/* Shadow TLBs are automatically */
8097db29ddeSMichal Simek		nop
8107db29ddeSMichal Simek		bri	4		/* flushed by changing PID */
8117db29ddeSMichal Simek		rtsd	r15,8
8127db29ddeSMichal Simek		nop
8137db29ddeSMichal Simek
814c4df4bc1SMichal Simek.end _hw_exception_handler
815c4df4bc1SMichal Simek
8167db29ddeSMichal Simek/* Unaligned data access exception last on a 4k page for MMU.
8177db29ddeSMichal Simek * When this is called, we are in virtual mode with exceptions enabled
8187db29ddeSMichal Simek * and registers 1-13,15,17,18 saved.
8197db29ddeSMichal Simek *
8207db29ddeSMichal Simek * R3 = ESR
8217db29ddeSMichal Simek * R4 = EAR
8227db29ddeSMichal Simek * R7 = pointer to saved registers (struct pt_regs *regs)
8237db29ddeSMichal Simek *
8247db29ddeSMichal Simek * This handler perform the access, and returns via ret_from_exc.
8257db29ddeSMichal Simek */
8267db29ddeSMichal Simek.global _unaligned_data_exception
8277db29ddeSMichal Simek.ent _unaligned_data_exception
8287db29ddeSMichal Simek_unaligned_data_exception:
8297db29ddeSMichal Simek	andi	r8, r3, 0x3E0;	/* Mask and extract the register operand */
83052ade599SMichal Simek	bsrli   r8, r8, 2;		/* r8 >> 2 = register operand * 8 */
8317db29ddeSMichal Simek	andi	r6, r3, 0x400;	/* Extract ESR[S] */
8327db29ddeSMichal Simek	bneid	r6, ex_sw_vm;
8337db29ddeSMichal Simek	andi	r6, r3, 0x800;	/* Extract ESR[W] - delay slot */
8347db29ddeSMichal Simekex_lw_vm:
8357db29ddeSMichal Simek	beqid	r6, ex_lhw_vm;
8363863dbceSMichal Simekload1:	lbui	r5, r4, 0;	/* Exception address in r4 - delay slot */
8377db29ddeSMichal Simek/* Load a word, byte-by-byte from destination address and save it in tmp space*/
838cd341577SMichal Simek	addik	r6, r0, ex_tmp_data_loc_0;
8397db29ddeSMichal Simek	sbi	r5, r6, 0;
8403863dbceSMichal Simekload2:	lbui	r5, r4, 1;
8417db29ddeSMichal Simek	sbi	r5, r6, 1;
8423863dbceSMichal Simekload3:	lbui	r5, r4, 2;
8437db29ddeSMichal Simek	sbi	r5, r6, 2;
8443863dbceSMichal Simekload4:	lbui	r5, r4, 3;
8457db29ddeSMichal Simek	sbi	r5, r6, 3;
8467db29ddeSMichal Simek	brid	ex_lw_tail_vm;
8477db29ddeSMichal Simek/* Get the destination register value into r3 - delay slot */
8487db29ddeSMichal Simek	lwi	r3, r6, 0;
8497db29ddeSMichal Simekex_lhw_vm:
8507db29ddeSMichal Simek	/* Load a half-word, byte-by-byte from destination address and
8517db29ddeSMichal Simek	 * save it in tmp space */
852cd341577SMichal Simek	addik	r6, r0, ex_tmp_data_loc_0;
8537db29ddeSMichal Simek	sbi	r5, r6, 0;
8543863dbceSMichal Simekload5:	lbui	r5, r4, 1;
8557db29ddeSMichal Simek	sbi	r5, r6, 1;
8567db29ddeSMichal Simek	lhui	r3, r6, 0;	/* Get the destination register value into r3 */
8577db29ddeSMichal Simekex_lw_tail_vm:
8587db29ddeSMichal Simek	/* Form load_word jump table offset (lw_table_vm + (8 * regnum)) */
8597db29ddeSMichal Simek	addik	r5, r8, lw_table_vm;
8607db29ddeSMichal Simek	bra	r5;
8617db29ddeSMichal Simekex_lw_end_vm:			/* Exception handling of load word, ends */
8627db29ddeSMichal Simek	brai	ret_from_exc;
8637db29ddeSMichal Simekex_sw_vm:
8647db29ddeSMichal Simek/* Form store_word jump table offset (sw_table_vm + (8 * regnum)) */
8657db29ddeSMichal Simek	addik	r5, r8, sw_table_vm;
8667db29ddeSMichal Simek	bra	r5;
8677db29ddeSMichal Simekex_sw_tail_vm:
868cd341577SMichal Simek	addik	r5, r0, ex_tmp_data_loc_0;
8697db29ddeSMichal Simek	beqid	r6, ex_shw_vm;
8707db29ddeSMichal Simek	swi	r3, r5, 0;	/* Get the word - delay slot */
8717db29ddeSMichal Simek	/* Store the word, byte-by-byte into destination address */
8727db29ddeSMichal Simek	lbui	r3, r5, 0;
8733863dbceSMichal Simekstore1:	sbi	r3, r4, 0;
8747db29ddeSMichal Simek	lbui	r3, r5, 1;
8753863dbceSMichal Simekstore2:	sbi	r3, r4, 1;
8767db29ddeSMichal Simek	lbui	r3, r5, 2;
8773863dbceSMichal Simekstore3:	sbi	r3, r4, 2;
8787db29ddeSMichal Simek	lbui	r3, r5, 3;
8797db29ddeSMichal Simek	brid	ret_from_exc;
8803863dbceSMichal Simekstore4:	sbi	r3, r4, 3;	/* Delay slot */
8817db29ddeSMichal Simekex_shw_vm:
8827db29ddeSMichal Simek	/* Store the lower half-word, byte-by-byte into destination address */
883e3288f31SMichal Simek#ifdef __MICROBLAZEEL__
884e3288f31SMichal Simek	lbui	r3, r5, 0;
885e3288f31SMichal Simekstore5:	sbi	r3, r4, 0;
886e3288f31SMichal Simek	lbui	r3, r5, 1;
887e3288f31SMichal Simek	brid	ret_from_exc;
888e3288f31SMichal Simekstore6:	sbi	r3, r4, 1;	/* Delay slot */
889e3288f31SMichal Simek#else
8907db29ddeSMichal Simek	lbui	r3, r5, 2;
8913863dbceSMichal Simekstore5:	sbi	r3, r4, 0;
8927db29ddeSMichal Simek	lbui	r3, r5, 3;
8937db29ddeSMichal Simek	brid	ret_from_exc;
8943863dbceSMichal Simekstore6:	sbi	r3, r4, 1;	/* Delay slot */
895e3288f31SMichal Simek#endif
896e3288f31SMichal Simek
8977db29ddeSMichal Simekex_sw_end_vm:			/* Exception handling of store word, ends. */
8983863dbceSMichal Simek
8993863dbceSMichal Simek/* We have to prevent cases that get/put_user macros get unaligned pointer
9003863dbceSMichal Simek * to bad page area. We have to find out which origin instruction caused it
9013863dbceSMichal Simek * and called fixup for that origin instruction not instruction in unaligned
9023863dbceSMichal Simek * handler */
9033863dbceSMichal Simekex_unaligned_fixup:
9043863dbceSMichal Simek	ori	r5, r7, 0 /* setup pointer to pt_regs */
9053863dbceSMichal Simek	lwi	r6, r7, PT_PC; /* faulting address is one instruction above */
9063863dbceSMichal Simek	addik	r6, r6, -4 /* for finding proper fixup */
9073863dbceSMichal Simek	swi	r6, r7, PT_PC; /* a save back it to PT_PC */
9083863dbceSMichal Simek	addik	r7, r0, SIGSEGV
9093863dbceSMichal Simek	/* call bad_page_fault for finding aligned fixup, fixup address is saved
9103863dbceSMichal Simek	 * in PT_PC which is used as return address from exception */
911cd341577SMichal Simek	addik	r15, r0, ret_from_exc-8 /* setup return address */
9123863dbceSMichal Simek	brid	bad_page_fault
9133863dbceSMichal Simek	nop
9143863dbceSMichal Simek
9153863dbceSMichal Simek/* We prevent all load/store because it could failed any attempt to access */
9163863dbceSMichal Simek.section __ex_table,"a";
9173863dbceSMichal Simek	.word	load1,ex_unaligned_fixup;
9183863dbceSMichal Simek	.word	load2,ex_unaligned_fixup;
9193863dbceSMichal Simek	.word	load3,ex_unaligned_fixup;
9203863dbceSMichal Simek	.word	load4,ex_unaligned_fixup;
9213863dbceSMichal Simek	.word	load5,ex_unaligned_fixup;
9223863dbceSMichal Simek	.word	store1,ex_unaligned_fixup;
9233863dbceSMichal Simek	.word	store2,ex_unaligned_fixup;
9243863dbceSMichal Simek	.word	store3,ex_unaligned_fixup;
9253863dbceSMichal Simek	.word	store4,ex_unaligned_fixup;
9263863dbceSMichal Simek	.word	store5,ex_unaligned_fixup;
9273863dbceSMichal Simek	.word	store6,ex_unaligned_fixup;
9283863dbceSMichal Simek.previous;
9297db29ddeSMichal Simek.end _unaligned_data_exception
9307db29ddeSMichal Simek
931ce3266c0SSteven J. Magnani.global ex_handler_unhandled
932c4df4bc1SMichal Simekex_handler_unhandled:
933c4df4bc1SMichal Simek/* FIXME add handle function for unhandled exception - dump register */
934c4df4bc1SMichal Simek	bri 0
935c4df4bc1SMichal Simek
9367db29ddeSMichal Simek/*
9377db29ddeSMichal Simek * hw_exception_handler Jump Table
9387db29ddeSMichal Simek * - Contains code snippets for each register that caused the unalign exception
9397db29ddeSMichal Simek * - Hence exception handler is NOT self-modifying
9407db29ddeSMichal Simek * - Separate table for load exceptions and store exceptions.
9417db29ddeSMichal Simek * - Each table is of size: (8 * 32) = 256 bytes
9427db29ddeSMichal Simek */
9437db29ddeSMichal Simek
944c4df4bc1SMichal Simek.section .text
945c4df4bc1SMichal Simek.align 4
946c4df4bc1SMichal Simeklw_table:
947c4df4bc1SMichal Simeklw_r0:		R3_TO_LWREG	(0);
948c4df4bc1SMichal Simeklw_r1:		LWREG_NOP;
949c4df4bc1SMichal Simeklw_r2:		R3_TO_LWREG	(2);
950c4df4bc1SMichal Simeklw_r3:		R3_TO_LWREG_V	(3);
951c4df4bc1SMichal Simeklw_r4:		R3_TO_LWREG_V	(4);
952c4df4bc1SMichal Simeklw_r5:		R3_TO_LWREG_V	(5);
953c4df4bc1SMichal Simeklw_r6:		R3_TO_LWREG_V	(6);
954c4df4bc1SMichal Simeklw_r7:		R3_TO_LWREG	(7);
955c4df4bc1SMichal Simeklw_r8:		R3_TO_LWREG	(8);
956c4df4bc1SMichal Simeklw_r9:		R3_TO_LWREG	(9);
957c4df4bc1SMichal Simeklw_r10:		R3_TO_LWREG	(10);
958c4df4bc1SMichal Simeklw_r11:		R3_TO_LWREG	(11);
959c4df4bc1SMichal Simeklw_r12:		R3_TO_LWREG	(12);
960c4df4bc1SMichal Simeklw_r13:		R3_TO_LWREG	(13);
961c4df4bc1SMichal Simeklw_r14:		R3_TO_LWREG	(14);
962c4df4bc1SMichal Simeklw_r15:		R3_TO_LWREG	(15);
963c4df4bc1SMichal Simeklw_r16:		R3_TO_LWREG	(16);
964c4df4bc1SMichal Simeklw_r17:		LWREG_NOP;
965c4df4bc1SMichal Simeklw_r18:		R3_TO_LWREG	(18);
966c4df4bc1SMichal Simeklw_r19:		R3_TO_LWREG	(19);
967c4df4bc1SMichal Simeklw_r20:		R3_TO_LWREG	(20);
968c4df4bc1SMichal Simeklw_r21:		R3_TO_LWREG	(21);
969c4df4bc1SMichal Simeklw_r22:		R3_TO_LWREG	(22);
970c4df4bc1SMichal Simeklw_r23:		R3_TO_LWREG	(23);
971c4df4bc1SMichal Simeklw_r24:		R3_TO_LWREG	(24);
972c4df4bc1SMichal Simeklw_r25:		R3_TO_LWREG	(25);
973c4df4bc1SMichal Simeklw_r26:		R3_TO_LWREG	(26);
974c4df4bc1SMichal Simeklw_r27:		R3_TO_LWREG	(27);
975c4df4bc1SMichal Simeklw_r28:		R3_TO_LWREG	(28);
976c4df4bc1SMichal Simeklw_r29:		R3_TO_LWREG	(29);
977c4df4bc1SMichal Simeklw_r30:		R3_TO_LWREG	(30);
9787db29ddeSMichal Simeklw_r31: 	R3_TO_LWREG_V	(31);
979c4df4bc1SMichal Simek
980c4df4bc1SMichal Simeksw_table:
981c4df4bc1SMichal Simeksw_r0:		SWREG_TO_R3	(0);
982c4df4bc1SMichal Simeksw_r1:		SWREG_NOP;
983c4df4bc1SMichal Simeksw_r2:		SWREG_TO_R3	(2);
984c4df4bc1SMichal Simeksw_r3:		SWREG_TO_R3_V	(3);
985c4df4bc1SMichal Simeksw_r4:		SWREG_TO_R3_V	(4);
986c4df4bc1SMichal Simeksw_r5:		SWREG_TO_R3_V	(5);
987c4df4bc1SMichal Simeksw_r6:		SWREG_TO_R3_V	(6);
988c4df4bc1SMichal Simeksw_r7:		SWREG_TO_R3	(7);
989c4df4bc1SMichal Simeksw_r8:		SWREG_TO_R3	(8);
990c4df4bc1SMichal Simeksw_r9:		SWREG_TO_R3	(9);
991c4df4bc1SMichal Simeksw_r10:		SWREG_TO_R3	(10);
992c4df4bc1SMichal Simeksw_r11:		SWREG_TO_R3	(11);
993c4df4bc1SMichal Simeksw_r12:		SWREG_TO_R3	(12);
994c4df4bc1SMichal Simeksw_r13:		SWREG_TO_R3	(13);
995c4df4bc1SMichal Simeksw_r14:		SWREG_TO_R3	(14);
996c4df4bc1SMichal Simeksw_r15:		SWREG_TO_R3	(15);
997c4df4bc1SMichal Simeksw_r16:		SWREG_TO_R3	(16);
998c4df4bc1SMichal Simeksw_r17:		SWREG_NOP;
999c4df4bc1SMichal Simeksw_r18:		SWREG_TO_R3	(18);
1000c4df4bc1SMichal Simeksw_r19:		SWREG_TO_R3	(19);
1001c4df4bc1SMichal Simeksw_r20:		SWREG_TO_R3	(20);
1002c4df4bc1SMichal Simeksw_r21:		SWREG_TO_R3	(21);
1003c4df4bc1SMichal Simeksw_r22:		SWREG_TO_R3	(22);
1004c4df4bc1SMichal Simeksw_r23:		SWREG_TO_R3	(23);
1005c4df4bc1SMichal Simeksw_r24:		SWREG_TO_R3	(24);
1006c4df4bc1SMichal Simeksw_r25:		SWREG_TO_R3	(25);
1007c4df4bc1SMichal Simeksw_r26:		SWREG_TO_R3	(26);
1008c4df4bc1SMichal Simeksw_r27:		SWREG_TO_R3	(27);
1009c4df4bc1SMichal Simeksw_r28:		SWREG_TO_R3	(28);
1010c4df4bc1SMichal Simeksw_r29:		SWREG_TO_R3	(29);
1011c4df4bc1SMichal Simeksw_r30:		SWREG_TO_R3	(30);
10127db29ddeSMichal Simeksw_r31:		SWREG_TO_R3_V	(31);
10137db29ddeSMichal Simek
10147db29ddeSMichal Simeklw_table_vm:
10157db29ddeSMichal Simeklw_r0_vm:	R3_TO_LWREG_VM		(0);
10167db29ddeSMichal Simeklw_r1_vm:	R3_TO_LWREG_VM_V	(1);
10177db29ddeSMichal Simeklw_r2_vm:	R3_TO_LWREG_VM_V	(2);
10187db29ddeSMichal Simeklw_r3_vm:	R3_TO_LWREG_VM_V	(3);
10197db29ddeSMichal Simeklw_r4_vm:	R3_TO_LWREG_VM_V	(4);
10207db29ddeSMichal Simeklw_r5_vm:	R3_TO_LWREG_VM_V	(5);
10217db29ddeSMichal Simeklw_r6_vm:	R3_TO_LWREG_VM_V	(6);
10227db29ddeSMichal Simeklw_r7_vm:	R3_TO_LWREG_VM_V	(7);
10237db29ddeSMichal Simeklw_r8_vm:	R3_TO_LWREG_VM_V	(8);
10247db29ddeSMichal Simeklw_r9_vm:	R3_TO_LWREG_VM_V	(9);
10257db29ddeSMichal Simeklw_r10_vm:	R3_TO_LWREG_VM_V	(10);
10267db29ddeSMichal Simeklw_r11_vm:	R3_TO_LWREG_VM_V	(11);
10277db29ddeSMichal Simeklw_r12_vm:	R3_TO_LWREG_VM_V	(12);
10287db29ddeSMichal Simeklw_r13_vm:	R3_TO_LWREG_VM_V	(13);
1029c1138940SMichal Simeklw_r14_vm:	R3_TO_LWREG_VM_V	(14);
10307db29ddeSMichal Simeklw_r15_vm:	R3_TO_LWREG_VM_V	(15);
1031c1138940SMichal Simeklw_r16_vm:	R3_TO_LWREG_VM_V	(16);
10327db29ddeSMichal Simeklw_r17_vm:	R3_TO_LWREG_VM_V	(17);
10337db29ddeSMichal Simeklw_r18_vm:	R3_TO_LWREG_VM_V	(18);
1034c1138940SMichal Simeklw_r19_vm:	R3_TO_LWREG_VM_V	(19);
1035c1138940SMichal Simeklw_r20_vm:	R3_TO_LWREG_VM_V	(20);
1036c1138940SMichal Simeklw_r21_vm:	R3_TO_LWREG_VM_V	(21);
1037c1138940SMichal Simeklw_r22_vm:	R3_TO_LWREG_VM_V	(22);
1038c1138940SMichal Simeklw_r23_vm:	R3_TO_LWREG_VM_V	(23);
1039c1138940SMichal Simeklw_r24_vm:	R3_TO_LWREG_VM_V	(24);
1040c1138940SMichal Simeklw_r25_vm:	R3_TO_LWREG_VM_V	(25);
1041c1138940SMichal Simeklw_r26_vm:	R3_TO_LWREG_VM_V	(26);
1042c1138940SMichal Simeklw_r27_vm:	R3_TO_LWREG_VM_V	(27);
1043c1138940SMichal Simeklw_r28_vm:	R3_TO_LWREG_VM_V	(28);
1044c1138940SMichal Simeklw_r29_vm:	R3_TO_LWREG_VM_V	(29);
1045c1138940SMichal Simeklw_r30_vm:	R3_TO_LWREG_VM_V	(30);
10467db29ddeSMichal Simeklw_r31_vm:	R3_TO_LWREG_VM_V	(31);
10477db29ddeSMichal Simek
10487db29ddeSMichal Simeksw_table_vm:
10497db29ddeSMichal Simeksw_r0_vm:	SWREG_TO_R3_VM		(0);
10507db29ddeSMichal Simeksw_r1_vm:	SWREG_TO_R3_VM_V	(1);
10517db29ddeSMichal Simeksw_r2_vm:	SWREG_TO_R3_VM_V	(2);
10527db29ddeSMichal Simeksw_r3_vm:	SWREG_TO_R3_VM_V	(3);
10537db29ddeSMichal Simeksw_r4_vm:	SWREG_TO_R3_VM_V	(4);
10547db29ddeSMichal Simeksw_r5_vm:	SWREG_TO_R3_VM_V	(5);
10557db29ddeSMichal Simeksw_r6_vm:	SWREG_TO_R3_VM_V	(6);
10567db29ddeSMichal Simeksw_r7_vm:	SWREG_TO_R3_VM_V	(7);
10577db29ddeSMichal Simeksw_r8_vm:	SWREG_TO_R3_VM_V	(8);
10587db29ddeSMichal Simeksw_r9_vm:	SWREG_TO_R3_VM_V	(9);
10597db29ddeSMichal Simeksw_r10_vm:	SWREG_TO_R3_VM_V	(10);
10607db29ddeSMichal Simeksw_r11_vm:	SWREG_TO_R3_VM_V	(11);
10617db29ddeSMichal Simeksw_r12_vm:	SWREG_TO_R3_VM_V	(12);
10627db29ddeSMichal Simeksw_r13_vm:	SWREG_TO_R3_VM_V	(13);
1063c1138940SMichal Simeksw_r14_vm:	SWREG_TO_R3_VM_V	(14);
10647db29ddeSMichal Simeksw_r15_vm:	SWREG_TO_R3_VM_V	(15);
1065c1138940SMichal Simeksw_r16_vm:	SWREG_TO_R3_VM_V	(16);
10667db29ddeSMichal Simeksw_r17_vm:	SWREG_TO_R3_VM_V	(17);
10677db29ddeSMichal Simeksw_r18_vm:	SWREG_TO_R3_VM_V	(18);
1068c1138940SMichal Simeksw_r19_vm:	SWREG_TO_R3_VM_V	(19);
1069c1138940SMichal Simeksw_r20_vm:	SWREG_TO_R3_VM_V	(20);
1070c1138940SMichal Simeksw_r21_vm:	SWREG_TO_R3_VM_V	(21);
1071c1138940SMichal Simeksw_r22_vm:	SWREG_TO_R3_VM_V	(22);
1072c1138940SMichal Simeksw_r23_vm:	SWREG_TO_R3_VM_V	(23);
1073c1138940SMichal Simeksw_r24_vm:	SWREG_TO_R3_VM_V	(24);
1074c1138940SMichal Simeksw_r25_vm:	SWREG_TO_R3_VM_V	(25);
1075c1138940SMichal Simeksw_r26_vm:	SWREG_TO_R3_VM_V	(26);
1076c1138940SMichal Simeksw_r27_vm:	SWREG_TO_R3_VM_V	(27);
1077c1138940SMichal Simeksw_r28_vm:	SWREG_TO_R3_VM_V	(28);
1078c1138940SMichal Simeksw_r29_vm:	SWREG_TO_R3_VM_V	(29);
1079c1138940SMichal Simeksw_r30_vm:	SWREG_TO_R3_VM_V	(30);
10807db29ddeSMichal Simeksw_r31_vm:	SWREG_TO_R3_VM_V	(31);
1081c4df4bc1SMichal Simek
1082c4df4bc1SMichal Simek/* Temporary data structures used in the handler */
1083c4df4bc1SMichal Simek.section .data
1084c4df4bc1SMichal Simek.align 4
1085c4df4bc1SMichal Simekex_tmp_data_loc_0:
1086c4df4bc1SMichal Simek	.byte 0
1087c4df4bc1SMichal Simekex_tmp_data_loc_1:
1088c4df4bc1SMichal Simek	.byte 0
1089c4df4bc1SMichal Simekex_tmp_data_loc_2:
1090c4df4bc1SMichal Simek	.byte 0
1091c4df4bc1SMichal Simekex_tmp_data_loc_3:
1092c4df4bc1SMichal Simek	.byte 0
1093c4df4bc1SMichal Simekex_reg_op:
1094c4df4bc1SMichal Simek	.byte 0
1095