Trampolines For Embedded Systems
by Joseph M. Link

Listing One
   .text
 _Trampoline:
     moveml      #0xC0C0,a7@-        /* save d0,d1,a0,a1 on the stack */
     movel       #0xF0F0F0F0,a7@-    /* save spot for passed int and */
     movel       #0xF0F0F0F0,a7@-    /* pointer */
     jsr         0xA0A0A0A0          /* call respective IrqHandler */
     addql       #8,a7               /* toss parm 1 and 2 */
     moveml      a7@+,#0x0303        /* restore d0,d1,a0,a1 from the stack */
     rte

 TrampolineEnd:
     .globl      _TRAMP_SIZE,_Trampoline
 _TRAMP_SIZE:
     .long       TrampolineEnd-_Trampoline
 /***************************************************************/
 extern char Trampoline[];

 void IrqRegisterTramp(void (*func)(void *, int), void *arg1,
                       int arg2, int vector)
 {
   unsigned char *p;
   p = malloc(TRAMP_SIZE);
   bcopy(Trampoline, p, TRAMP_SIZE);

   *((void *)(p + TRAMP_PARM1_OFFSET)) = arg1;  /* plug in vales for handler */
   *((int *)(p + TRAMP_PARM2_OFFSET))  = arg2;
   *((void *)(p + TRAMP_FUNC_OFFSET))  = func;
   vbr[vector] = (void *) p;      /* register handler */
 }
Listing Two
volatile unsigned long astRegister = 0;
 #define register_ast(mask)                           \
   __asm__ volatile ("oril %1,%0"                     \
                     : /* no output */                \
                     : "m" (astRegister), "i" (mask))
 /**********************************/
 #define TICK  0x0001   /* bit mask to first bit of register */
 void timerHandler(void *p, int i)
 {
   register_ast(TICK);
 }
Listing Three
/* if running in a loop, need to retrieve AST register and clear
  while IRQs disabled--else, we will pass astRegisterCopy as arg
 */
 /* BEGIN loop only section */
 IRQ_disable();
 astRegisterCopy = astRegister;
 astRegister = 0;
 IRQ_enable();
 /* END loop only section */
 if(astRegisterCopy & TICK)
 {
   if(!unsleep()) /* wake up any tasks whose time is up */
     tasks_rotate();  /* if no sleepers, round robin */
 }
 if(astRegisterCopy & ETHERTXRDY)
 {
   /* any more data to send on ether?? */
   . . .
 }
 if(astRegisterCopy & ETHERRXRDY)
 {
   /* we got data on ether, handle it */
   . . .
 }
Listing Four
  .text
 _Trampoline:
     moveml      #0xC0C0,a7@-        /* save d0,d1,a0,a1 on the stack */
     movel       #0xF0F0F0F0,a7@-    /* save spot for passed int and */
     movel       #0xF0F0F0F0,a7@-    /* pointer */
     jsr         0xA0A0A0A0          /* call respective IrqHandler */
     jmp         common
 TrampolineEnd:

 common:
     addql       #8,a7               /* toss parm1 and 2 */
     movew       a7@(16),d0          /* get sr from excep frame */
     andiw       #0x0700,d0          /* and skip asts if */
     bneb        DontSwitch          /* there are pending interrupts */
     tasb        doingASTS           /* or if */
     bneb        DontSwitch          /* someone esle is handling asts */
 testast:
     movew       #0x2700,sr          /* disable irqs */
     tstl        _astRegister        /* any jobs to run? */
     beqb        NoASTs              /* nope */
     movel       _astRegister,a7@-   /* pass copy of astRegister */
     clrl       _astRegister         /* and clear it */
     movew       #0x2000,sr          /* enable all interrupts */
      jsr         _astHandler
     addql       #4,a7               /* pop astRegister copy */
     brab        testast
 NoASTs:
     clrb        doingASTS           /* ok.. irqs still disabled */
     moveal      _pRunningTask,a0    /* get pointer to current task */
     moveal      _readyList,a1       /* get pointer to ptop */
     cmpal       a0,a1               /* and dont save if */
     beqb        DontSwitch          /* pRunningTask == ptop */
 SaveContext:
     moveml      #0x3F3E,a7@-        /* save d2-d7,a2-a6 on the stack */
     movel       a7,a0@              /* save stack pointer
 RestoreContext:                        first item in task struct */
moveal      a1@,a7              /* point to ptops stack */
     movel       a1,_pRunningTask    /* set runningTask to new task */
     moveml      a7@+,#0x7CFC        /* restore d2-d7,a2-a6 from the stack */
 DontSwitch:
     moveml      a7@+,#0x0303        /* restore d0,d1,a0,a1 from the stack */
     rte

 doingASTS:
     .byte       0x00
     .globl      _TRAMP_SIZE,_Trampoline
 _TRAMP_SIZE:
     .long       TrampolineEnd-_Trampoline


