File : s-bcpith-bb-sparc.adb
1 ------------------------------------------------------------------------------
2 -- --
3 -- GNAT RUN-TIME LIBRARY (GNARL) COMPONENTS --
4 -- --
5 -- SYSTEM.BB.CPU_PRIMITIVES.INSTALL_TRAP_HANDLER --
6 -- --
7 -- B o d y --
8 -- --
9 -- Copyright (C) 1999-2002 Universidad Politecnica de Madrid --
10 -- Copyright (C) 2003-2005 The European Space Agency --
11 -- Copyright (C) 2003-2015, AdaCore --
12 -- --
13 -- GNARL is free software; you can redistribute it and/or modify it under --
14 -- terms of the GNU General Public License as published by the Free Soft- --
15 -- ware Foundation; either version 3, or (at your option) any later ver- --
16 -- sion. GNARL is distributed in the hope that it will be useful, but WITH- --
17 -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
18 -- or FITNESS FOR A PARTICULAR PURPOSE. --
19 -- --
20 -- --
21 -- --
22 -- --
23 -- --
24 -- You should have received a copy of the GNU General Public License and --
25 -- a copy of the GCC Runtime Library Exception along with this program; --
26 -- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
27 -- <http://www.gnu.org/licenses/>. --
28 -- --
29 ------------------------------------------------------------------------------
30
31 -- This is a SPARC (ERC32/LEON2/LEON3) bare board version of this procedure
32
33 with System.Machine_Code; use System.Machine_Code;
34
35 separate (System.BB.CPU_Primitives)
36 procedure Install_Trap_Handler
37 (Service_Routine : Address;
38 Vector : Vector_Id;
39 Synchronous : Boolean := False)
40 is
41 begin
42 -- The start up routine (crt0) has already installed entries in the trap
43 -- table for external interrupts (16#11# .. 16#1F#), and the following
44 -- synchronous traps mapped to Ada exceptions:
45
46 -- instruction access exception (16#01#)
47 -- illegal instruction (16#02#)
48 -- address not aligned (16#07#)
49 -- FP exception (16#08#)
50 -- data access exception (16#09#)
51 -- instruction access error (16#21#)
52 -- data access error (16#29#)
53 -- hardware division by zero (16#2A#)
54 -- data store error (16#2B#)
55 -- software division by zero (16#82#)
56
57 -- This way the trap table can be put in ROM.
58
59 if Vector not in
60 16#11# .. 16#1F# | 16#01# | 16#02# | 16#07# | 16#08# | 16#09# | 16#21#
61 | 16#29# | 16#2A# | 16#2B# | 16#82#
62 then
63 -- Install the 4 instructions in the SPARC trap table to point to the
64 -- shared interrupt service routine (Common_Handler).
65
66 -- mov Vector, %l3
67
68 Trap_Table (Vector).First_Instr :=
69 16#A6102000# + SSE.Integer_Address (Vector);
70
71 -- If the handler is for a synchronous trap then we set bit number
72 -- 8 (in l3) to 1. This bit indicates to the underlying trap handler
73 -- (common_handler) that this is a synchronous trap and it must return
74 -- to the instruction following the trap.
75
76 if Synchronous then
77 Trap_Table (Vector).First_Instr :=
78 Trap_Table (Vector).First_Instr + SSE.Integer_Address (16#100#);
79 end if;
80
81 -- sethi %hi(Common_Handler), %l4
82
83 -- The 22 most significant bits of Common_Handler are obtained shifting
84 -- 10 times to the right, which is equivalent to divide by 2**10.
85
86 Trap_Table (Vector).Second_Instr :=
87 16#29000000# + SSE.To_Integer (Common_Handler'Address) / 2**10;
88
89 -- jmp %l4 + %lo(Common_Handler)
90
91 -- The 10 least significant bits of Common_Handler are obtained by
92 -- masking, which is equivalent to mod by 2**10.
93
94 Trap_Table (Vector).Third_Instr :=
95 16#81C52000# + SSE.To_Integer (Common_Handler'Address) mod 2**10;
96
97 -- mov %psr, %l0
98
99 -- Note that reading the psr at the first instruction of the trap
100 -- handler would not be a good idea, because the trap may have happened
101 -- just after changing the psr.
102
103 Trap_Table (Vector).Fourth_Instr := 16#A1480000#;
104
105 -- Flush the instruction cache since we are modifying the memory area
106 -- corresponding to instructions (trap table). This is a good idea even
107 -- for systems where we don't support cache control, such as ERC32, as
108 -- there still may be variants with cache.
109
110 -- As installing interrupt handlers is not time critical, the few extra
111 -- instructions do not matter much.
112
113 Asm ("flush %0" & ASCII.LF & ASCII.HT &
114 "flush %0 + 4" & ASCII.LF & ASCII.HT &
115 "flush %0 + 8" & ASCII.LF & ASCII.HT &
116 "flush %0 + 12",
117 Outputs => No_Output_Operands,
118 Inputs => Address'Asm_Input ("r", Trap_Table (Vector)'Address),
119 Volatile => True);
120 end if;
121
122 -- Put the address of the user handler in the User_Vector_Table, so that
123 -- the Common_Handler can know where to jump when a trap (synchronous or
124 -- asynchronous) occurs.
125
126 User_Vector_Table (Vector) := Service_Routine;
127 end Install_Trap_Handler;