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;