DataMuseum.dk

Presents historical artifacts from the history of:

Rational R1000/400

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about Rational R1000/400

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - download

⟦cf55d27b2⟧ TextFile

    Length: 11646 (0x2d7e)
    Types: TextFile
    Notes: R1k Text-file segment

Derivation

└─⟦8527c1e9b⟧ Bits:30000544 8mm tape, Rational 1000, Arrival backup of disks in PAM's R1000
    └─ ⟦cfc2e13cd⟧ »Space Info Vol 2« 
        └─⟦29ed5d28b⟧ 
            └─⟦this⟧ 

TextFile

-------------------------------------------------------------------------------
-------------------------------------------------------------------------------
--
--   VERDIX CORPORATION                               (C) COPYRIGHT 1988
--   14130-A Sullyfield Circle                        Proprietary Information
--   Chantilly, Virginia 22021                        Not to be Disclosed
--
--  FILE:     V_INTR_B.A
--
--  UNITS:    VADS/EXEC Interrupts Package Body.  This version is for
--            the M68000 Processor Family Cross Targets.
--
--  PURPOSE:  This file contains the body for the interrupt services supporting
--            user-defined interrupt service routines (ISR's) and the
--            getting/setting of interrupt status.
--
--            Refer to V_INTERRUPTS package specification in V_VADS_EXEC.A for
--            a detailed description of each service.
--
--            Do not modify or recompile this package body.
--
-------------------------------------------------------------------------------
-------------------------------------------------------------------------------
--
--  Revision History:
--
--  880306:1430     B01
--
-------------------------------------------------------------------------------
-------------------------------------------------------------------------------

-- TARGET IS MC68020

with Machine_Code;
with V_Cpu_Conf;
with Link_Block;
with V_I_Types;
with Ada_Krn_I;
with Ada_Krn_Defs;
with System;
use System;
package body V_Interrupts is

    pragma Suppress (All_Checks);

    Stack_Limit : Address;
    pragma Interface_Name (Stack_Limit, "STACK_LIMIT");
    -- Current task's bottom of stack limit.

    Debug_Block : Link_Block.Debug_Block_T;
    pragma Interface_Name (Debug_Block, "DEBUG_BLOCK");
    -- Contains addresses of variables and ISR services in the kernel
    -- program.


    procedure Isr is
        pragma Implicit_Code (Off);
        use Machine_Code;
    begin
        -- Save scratch registers
        Code_2'(Movem_L, A0 / A1 / D0 / D1 / D2 / D3, Decr (Sp));

        --
        -- Enter ISR.
        --
        -- The ENTER_ISR service
        -- increments the interrupt depth and switches to the interrupt stack
        -- if the depth was incremented from 0 to 1.
        --
        -- Note: if MASTER_STATE is enabled for mc68020, the CPU already did
        -- a switch from master to interrupt stack for an external interrupt.
        --
        -- The scratch registers (d0/d1/d2/d3/a0/a1) must be saved before calling
        -- the ENTER_ISR service.
        --
        -- Upon return, the address of the previous
        -- stack is pushed on the new stack. This address is also pushed
        -- for nested interrupts. The address points to the last entry
        -- pushed on the stack before the call.
        --

        -- Get address of ENTER_ISR service in the kernel program
        Code_2'(Movea_L, Debug_Block.Intr_Enter'Ref, A0);
        Code_1'(Jsr, Indr (A0));

        -- Set up the frame pointer register (a6) so that the debugger and
        -- exception unwinding can deduce this is the top of the stack
        -- for an ISR.
        --
        -- By convention a6 = 0, => top of user program stack,
        --   a6 = odd address => top of ISR stack
        --
        -- Furthermore, a6 = sp + 1. This allows the debugger to find the
        -- saved value for a6 and the ISR's exception frame.
        Code_2'(Move_L, A6, Decr (Sp));
        Code_2'(Movea_L, Sp, A6);
        Code_2'(Addq_L, +1, A6);

        -- The stack looks as follows:
        --   0 - saved a6           <-- a6 - 1
        --   4 - pointer to previous stack
        --
        -- Where previous stack is as follows:
        --   0 - d0/d1/d2/d3/a0/a1 (saved scratch registers)
        --  24 - ISR's exception stack frame

        -- Switch stack limit to bottom of interrupt stack.
        Code_2'(Move_L, Stack_Limit'Ref, Decr (Sp));
        Code_2'(Movea_L, Debug_Block.Intr_Stack_Limit'Ref, A0);
        Code_2'(Move_L, Indr (A0), Stack_Limit'Ref);

        -- Process interrupt
        Call_0'(Subp => Interrupt_Handler'Ref);

        -- Restore stack limit
        Code_2'(Move_L, Incr (Sp), Stack_Limit'Ref);

        -- Restore frame pointer
        Code_2'(Movea_L, Incr (Sp), A6);

        -- Complete ISR
        --
        -- complete_isr expects stack to look as follows
        --     0 - return pc back to ISR
        --     4 - pointer to previous stack (see below) (normally, the
        --         address pushed on the new stack by ENTER_ISR)
        --
        --  where previous stack looks as follows:
        --     0 - a0/a1/d0/d1/d2/d3 (saved scratch registers)
        --    24 - ISR's exception stack frame
        --
        -- Note: enter_isr must have been previosuly called for this ISR.
        --

        -- Get address of COMPLETE_ISR service in kernel program
        Code_2'(Movea_L, Debug_Block.Intr_Complete'Ref, A0);
        Code_1'(Jsr, Indr (A0));
        -- No return back here
    end Isr;



    procedure Fast_Isr is
        pragma Implicit_Code (Off);
        use Machine_Code;

        -- Fast version of ISR wrapper.
        --
        -- This version is made faster by eliminating the call to the
        -- kernel service, ENTER_ISR, which switches to the the interrupt
        -- stack and increments the interrupt depth. Also the logic for
        -- saving, setting and restoring the current stack limit has been
        -- omitted.
        --
        -- Restriction:
        --  The INTERRUPT_HANDLER procedure and the subprograms it calls
        --  must be compiled with "pragma suppress(ALL_CHECKS)" to suppress
        --  stack limit checking.
        --
        --  If the kernel is configured to use the m68k's master state, then,
        --  FAST_ISR can not be used for software traps. It can still
        --  be used for external interrupts.

    begin
        -- Save scratch registers
        Code_2'(Movem_L, A0 / A1 / D0 / D1 / D2 / D3, Decr (Sp));

        -- Emulate the omitted ENTER_ISR kernel service call by incrementing
        -- the kernel's interrupt depth count and pushing the current sp
        -- as the address of the previous stack.
        Code_2'(Movea_L, Debug_Block.Intr_Depth'Ref, A0);
        Code_2'(Addq_L, +1, Indr (A0));
        Code_2'(Move_L, Sp, Decr (Sp));

        -- Set up the frame pointer register (a6) so that the debugger and
        -- exception unwinding can deduce this is the top of the stack
        -- for an ISR.
        --
        -- By convention a6 = 0, => top of user program stack,
        --   a6 = odd address => top of ISR stack
        --
        -- Furthermore, a6 = sp + 1. This allows the debugger to find the
        -- saved value for a6 and the ISR's exception frame.
        --
        Code_2'(Move_L, A6, Decr (Sp));
        Code_2'(Movea_L, Sp, A6);
        Code_2'(Addq_L, +1, A6);

        -- The stack looks as follows:
        --   0 - saved a6           <-- a6 - 1
        --   4 - pointer to previous stack
        --
        -- Where previous stack is as follows:
        --   0 - d0/d1/d2/d3/a0/a1 (saved scratch registers)
        --  24 - ISR's exception stack frame

        -- Process interrupt
        Call_0'(Subp => Interrupt_Handler'Ref);

        -- Restore frame pointer
        Code_2'(Movea_L, Incr (Sp), A6);

        -- Complete ISR
        --
        -- complete_isr expects stack to look as follows
        --     0 - return pc back to ISR
        --     4 - pointer to previous stack (see below) (normally, the
        --         address pushed on the new stack by ENTER_ISR)
        --
        --  where previous stack looks as follows:
        --     0 - a0/a1/d0/d1/d2/d3 (saved scratch registers)
        --    24 - ISR's exception stack frame
        --
        -- Note: intr_depth must have been previosuly incremented for this ISR.
        --

        -- Get address of COMPLETE_ISR service in kernel program
        Code_2'(Movea_L, Debug_Block.Intr_Complete'Ref, A0);
        Code_1'(Jsr, Indr (A0));
        -- No return back here
    end Fast_Isr;

    procedure Float_Wrapper is
        pragma Implicit_Code (Off);
        use Machine_Code;
    begin
        -- No floating-point state save or restore for this target

        -- Process interrupt
        Call_0'(Subp => Float_Handler'Ref);

        Code_0'(Op => Rts);
    end Float_Wrapper;


    function Attach_Isr (Vector : in Vector_Id; Isr : in System.Address)
                        return System.Address is
        use System;
        Prev_Vector : Address;
    begin
        Prev_Vector := Ada_Krn_I.Isr_Attach
                          (Ada_Krn_Defs.Intr_Vector_Id_T (Vector), Isr);
        if Prev_Vector = Ada_Krn_Defs.Bad_Intr_Vector then
            raise Invalid_Interrupt_Vector;
        end if;
        return Prev_Vector;
    end Attach_Isr;

    procedure Attach_Isr (Vector : in Vector_Id; Isr : in System.Address) is
        use System;
        Prev_Vector : Address;
    begin
        Prev_Vector := Attach_Isr (Vector, Isr);
    end Attach_Isr;

    function Detach_Isr (Vector : in Vector_Id) return System.Address is
        use System;
        Prev_Vector : Address;
    begin
        Prev_Vector := Ada_Krn_I.Isr_Detach
                          (Ada_Krn_Defs.Intr_Vector_Id_T (Vector));
        if Prev_Vector = Ada_Krn_Defs.Bad_Intr_Vector then
            raise Invalid_Interrupt_Vector;
        end if;
        return Prev_Vector;
    end Detach_Isr;

    procedure Detach_Isr (Vector : in Vector_Id) is
        use System;
        Prev_Vector : Address;
    begin
        Prev_Vector := Detach_Isr (Vector);
    end Detach_Isr;

    function Get_Isr (Vector : in Vector_Id) return System.Address is
        use System;
        Isr : Address;
    begin
        Isr := Ada_Krn_I.Isr_Get (Ada_Krn_Defs.Intr_Vector_Id_T (Vector));
        if Isr = Ada_Krn_Defs.Bad_Intr_Vector then
            raise Invalid_Interrupt_Vector;
        end if;
        return Isr;
    end Get_Isr;

    function Get_Ivt return System.Address is
    begin
        return Ada_Krn_I.Isr_Get_Ivt;
    end Get_Ivt;

    function Current_Interrupt_Status return Interrupt_Status_T is
        Status : Ada_Krn_Defs.Intr_Status_T;
    begin
        Ada_Krn_I.Interrupts_Get_Status (Status);
        return Interrupt_Status_T (Status);
    end Current_Interrupt_Status;

    function Set_Interrupt_Status (New_Status : in Interrupt_Status_T)
                                  return Interrupt_Status_T is
        Old_Status : Ada_Krn_Defs.Intr_Status_T;
    begin
        Ada_Krn_I.Interrupts_Set_Status
           (Old_Status, Ada_Krn_Defs.Intr_Status_T (New_Status));
        return Interrupt_Status_T (Old_Status);
    end Set_Interrupt_Status;

    function Current_Supervisor_State return Boolean is
    begin
        return Ada_Krn_I.Task_Get_Supervisor_State;
    end Current_Supervisor_State;

    procedure Enter_Supervisor_State is
    begin
        Ada_Krn_I.Task_Enter_Supervisor_State;
    end Enter_Supervisor_State;

    procedure Leave_Supervisor_State is
    begin
        Ada_Krn_I.Task_Leave_Supervisor_State;
    end Leave_Supervisor_State;

    function Set_Supervisor_State (New_State : in Boolean) return Boolean is
        Old_State : Boolean := Ada_Krn_I.Task_Get_Supervisor_State;
    begin
        if New_State /= Old_State then
            if New_State then
                Ada_Krn_I.Task_Enter_Supervisor_State;
            else
                Ada_Krn_I.Task_Leave_Supervisor_State;
            end if;
        end if;
        return Old_State;
    end Set_Supervisor_State;


end V_Interrupts;