 // This file contains the interrupt table for the ADSP-2136x

// When the C program exits either by returning from main() or by an
// explicit or implicit call to exit(), control will transfer to the
// label ___lib_prog_term.  Currently, the ___lib_prog_term label is
// defined at the end of the reset vector as an IDLE instruction.
// If your application needs to perform some operation AFTER the C
// program has finished executing, remove the ___lib_prog_term label
// from the runtime header, and place it at the beginning of your
// code. 

/**************************************************************************
Changes made January 2001.

The run-time model states that i0 can't be used in the run-time libs.
Use i2 for interrupt handling instead.

**************************************************************************/

.file_attr libGroup="startup";
.file_attr libName="libc";
.file_attr libFunc="___lib_prog_term";
.file_attr FuncName="___lib_prog_term";
#if defined(_ADI_THREADS)
.file_attr libFunc="___lib_start";
.file_attr FuncName="___lib_start";
#endif
.file_attr prefersMem="any";
.file_attr prefersMemNum="50";

#include "sig_glob.h"
#include "lib_glob.h"

.extern ___lib_int_table;
.extern _main;
.global ___lib_RSTI;

#ifdef ARGV_SUPPORT
.extern __getargv;
.extern __Argv;
#endif

#ifdef __cplusplus
.EXTERN  _atexit;
.EXTERN  ___process_needed_destructions__Fv;
.EXTERN  __ctors;        // CPP: this id is defined in ldf file
                         // which points to start of seg_ctdm section
.EXTERN  __ctorsize;

.SEGMENT/DM .gdt;
.GLOBAL  ___eh_gdt;
.VAR     ___eh_gdt[1];

#endif

.GLOBAL  ___lib_prog_term;          // Termination address
.GLOBAL  __done_execution;
.EXTERN  ___lib_setup_c;

#if defined(_ADI_THREADS)
.GLOBAL  ___lib_start;
#endif

#if !defined(_ADI_THREADS)

#define  INT(irp) \
   push sts;                        /* Disable interrupts          */ \
   JUMP ___z3_int_determiner(DB);   /* jmp to finish setting up    */ \
   DM(I7,M7)=R2;                    /* Save r2 (scratch dreg)      */ \
   R2=SIGMASK(SIG_##irp);           /* Base of int table           */

#define RESERVED_INTERRUPT NOP;NOP;NOP;NOP

.SEGMENT/PM            seg_rth;     // Runtime header segment

            RESERVED_INTERRUPT;

___lib_RSTI: NOP;                   // Not really executed
_st:          JUMP ___lib_start;
             NOP;
             NOP;
___lib_IICDI:        INT(IICDI);    // Access to illegal IOP space
___lib_SOVFI:        INT(SOVF);     // status/loop/PC stack overflow
___lib_TMZHI:        INT(TMZ0);     // high priority timer
#if defined(__ADSP21367__) || defined(__ADSP21368__) || \
    defined(__ADSP21369__) || defined(__ADSP21371__) || \
    defined(__ADSP21375__) 
___lib_SPERRI:         INT(SPERRI); // SPORT Error interrupt
#else
            RESERVED_INTERRUPT;
#endif            
___lib_BKPI:         INT(BKP);      // Hardware breakpoint interrupt
            RESERVED_INTERRUPT;
___lib_IRQ2I:        INT(IRQ2);
___lib_IRQ1I:        INT(IRQ1);
___lib_IRQ0I:        INT(IRQ0);
___lib_P0I:          INT(P0);       // Peripheral interrupt 0
___lib_P1I:          INT(P1);       // Peripheral interrupt 1
___lib_P2I:          INT(P2);       // Peripheral interrupt 2
___lib_P3I:          INT(P3);       // Peripheral interrupt 3
___lib_P4I:          INT(P4);       // Peripheral interrupt 4
___lib_P5I:          INT(P5);       // Peripheral interrupt 5
___lib_P6I:          INT(P6);       // Peripheral interrupt 6
___lib_P7I:          INT(P7);       // Peripheral interrupt 7
___lib_P8I:          INT(P8);       // Peripheral interrupt 8
___lib_P9I:          rti;nop;nop;nop;       // Peripheral interrupt 9
___lib_P10I:         INT(P10);      // Peripheral interrupt 10
#if defined(__ADSP21367__) || defined(__ADSP21368__) || \
    defined(__ADSP21369__) || defined(__ADSP21371__) || \
    defined(__ADSP21375__) 
___lib_P11I:         INT(P11);      // Peripheral interrupt 11
#else
        RESERVED_INTERRUPT;
#endif
___lib_P12I:         INT(P12);      // Peripheral interrupt 12
___lib_P13I:         INT(P13);      // Peripheral interrupt 13
#if defined(__ADSP21367__) || defined(__ADSP21368__) || \
    defined(__ADSP21369__) || defined(__ADSP21371__) || \
    defined(__ADSP21375__) 
___lib_P14I:         INT(P14);      // Peripheral interrupt 14
#else
        RESERVED_INTERRUPT;
#endif
___lib_P15I:         INT(P15);      // Peripheral interrupt 15
#if defined(__ADSP21367__) || defined(__ADSP21368__) || \
    defined(__ADSP21369__) || defined(__ADSP21371__) || \
    defined(__ADSP21375__) 
___lib_P16I:         INT(P16);      // Peripheral interrupt 16
#else
        RESERVED_INTERRUPT;
#endif
___lib_P17I:         INT(P17);      // Peripheral interrupt 17
___lib_P18I:         INT(P18);      // Peripheral interrupt 18
___lib_CB7I:         INT(CB7);      // circular buffer #7 overflow
___lib_CB15I:        INT(CB15);     // circular buffer #15 overflow
___lib_TMZLI:        INT(TMZ);      // low priority timer
___lib_FIXI:         INT(FIX);      // fixed point overflow
___lib_FLTOI:        INT(FLTO);     // floating point overflow
___lib_FLTUI:        INT(FLTU);     // floating point underflow
___lib_FLTII:        INT(FLTI);     // floating point invalid
___lib_EMULI:        INT(EMUL);     // Emulator low priority interrupt
___lib_SFT0I:        INT(USR0);     // user interrupts 0..3
___lib_SFT1I:        INT(USR1);
___lib_SFT2I:        INT(USR2);
___lib_SFT3I:        INT(USR3);
            RESERVED_INTERRUPT;

___z3_int_determiner:    
            DM(I7,M7)=R1;                    
            R1=I2;
            DM(I7,M7)=R1;           // Save I2 (scratch reg)
            I2=R2;
            DM(I7,M7)=I13;          // Save I13 (scratch reg)
            I13=DM(5,I2);           // get disp to jump to
            JUMP (M13, I13) (DB);   // Jump to dispatcher
            NOP;                    // in place of freeze cache
            I13=DM(2,I2);           // rd handler addr (base+2)

#else /* _ADI_THREADS */

.section/pm seg_pmco;

#endif /* _ADI_THREADS */


___lib_start:        
            CALL ___lib_setup_c;    // Setup C runtime model

#ifdef __cplusplus
# ifndef ARGV_SUPPORT
         put(r4);
         put(r8);
         put(r12);
# endif

// _lib_call_ctors is the added code to support the constructor calls
// before the main call. if we are using __ctorsize, then we have to change
// this code.

         i0 = __ctors;
_lib_call_ctors:
         r0 = dm(i0,m6);      // get the address of constructor function.
         r0 = pass r0;
         if eq jump _lib_call_ctors_exit; // check if null
         i13=r0;
// next 5 lines are for call of the constructor
         r2 = i6;
         i6 = i7;
         jump(m13,i13) (db);
         dm(i7,m7)=r2;
         dm(i7,m7)=pc;
         jump _lib_call_ctors;
_lib_call_ctors_exit:

         // perform static c++ destructors at exit of main
         r4=___process_needed_destructions__Fv;
         r2 = i6;
         i6 = i7;
         JUMP  _atexit (DB);
         dm(i7,m7)=r2;
         dm(i7,m7)=pc;

# ifndef ARGV_SUPPORT
         get(r12,1);    // Restore the param regs
         get(r8,2);
         get(r4,3);
         modify(i7,3);
# endif
#endif // __cplusplus

#ifdef ARGV_SUPPORT
         // Initialise argc and argv for the call to main()
         R2=I6;
         I6=I7;
         JUMP __getargv (DB); DM(I7,M7)=R2; DM(I7,M7)=PC;
         R4 = R0;
         R8 =  __Argv;
#endif

// **IMPORTANT**  The compiler assumes that i6-2==i7 when main starts. (i.e.
// the stack pointer, i7 has been decremented by two from it's first value,
// NOT that the frame pointer i6 has been incremented by 2).  This normally
// happens in ___lib_setup_args, but if you change this startup file,
//  ___lib_setup_args might not be called. In this case, add a
// MODIFY(i7,-2) instruction before _main is called

#ifdef MAIN_RTS
            CJUMP _main (DB);             // Begin C program
            DM(I7,M7)=R2;
            DM(I7,M7)=PC;
#else
            JUMP _main;                   // Begin C program
#endif
.___lib_start.end:

// Setting the __done_execution flag indicates that this processor is
// finished executing, for the benefit of anyone who may be watching.

___lib_prog_term:    PM(__done_execution)=PC;
            IDLE;
            JUMP ___lib_prog_term;        // Stay put
.___lib_prog_term.end:

.VAR __done_execution = 0;

.ENDSEG;

#ifdef _ADI_SWFA
.SEGMENT/PM       seg_pmda;
.GLOBAL __21160_anomaly_write_location;
.VAR __21160_anomaly_write_location;      // A memory location we can write to
                                          // to flush the FIFO.
#endif
.ENDSEG;
