/* * Definitions for implementing CoCo ISRs in C * * Copyright 2013 by John W. Linville */ /* * INTERRUPT * * This macro is used to declare an ISR handler in C. * * Inline assembly language is used to define a 'trampoline' * entry point for the ISR. The trampoline saves the ?temp value * used in code generated by the compiler, calls the handler, * then restores the ?temp value and executes an RTI instruction * to resume normal execution. * * The macro munges the passed-in ISR label to create separate * labels for the trampoline and for the C-language ISR. * These labels are used by the GET*() and SET*() macros defined * later in this file. * * Example: INTERRUPT(vsync_handler) { ... }; */ #define _SP_ #define INTERRUPT(isr) \ extern unsigned _/**/isr/**/VEC; \ asm { \ $SE:0 /* Insure code goes in code segment */ \ _/**/isr/**/VEC EQU _SP_* \ LDD _SP_?temp \ PSHS D \ BSR _/**/isr/**/ISR \ PULS D \ STD _SP_?temp \ RTI \ } \ void _/**/isr/**/ISR(void) #undef _SP_ /* * EXTERN_INTERRUPT * * This macro is used to make external declarations for a * C-language ISR defined in a separate source file than where * the ISR is defined. It uses the label munging mentioned above to * make the declarations required for use of the GET*() and SET*() * macros defined below. * * Example: EXTERN_INTERRUPT(vsync_handler); */ #define EXTERN_INTERRUPT(isr) extern unsigned _/**/isr/**/VEC /* * Addresses of ISRs in CoCo interrupt hooks in RAM */ #define SW3VEC 0x0101 #define SW2VEC 0x0104 #define SWIVEC 0x0107 #define NMIVEC 0x010a #define IRQVEC 0x010d #define FIRQVEC 0x0110 /* * GETSW3, GETSW2, GETSWI, GETNMI, GETIRQ, GETFIRQ * * Get the current vector address for a given interrupt type. * * SETSW3, SETSW2, SETSWI, SETNMI, SETIRQ, SETFIRQ * * Set the vector address for a given interrupt type to * point at the passed-in ISR. */ #define GETSW3() ((const)*((unsigned *)SW3VEC)) #define SETSW3(isr) (*((unsigned *)SW3VEC) = (unsigned *)&_/**/isr/**/VEC) #define GETSW2() ((const)*((unsigned *)SW2VEC)) #define SETSW2(isr) (*((unsigned *)SW2VEC) = (unsigned *)&_/**/isr/**/VEC) #define GETSWI() ((const)*((unsigned *)SWIVEC)) #define SETSWI(isr) (*((unsigned *)SWIVEC) = (unsigned *)&_/**/isr/**/VEC) #define GETNMI() ((const)*((unsigned *)NMIVEC)) #define SETNMI(isr) (*((unsigned *)NMIVEC) = (unsigned *)&_/**/isr/**/VEC) #define GETIRQ() ((const)*((unsigned *)IRQVEC)) #define SETIRQ(isr) (*((unsigned *)IRQVEC) = (unsigned *)&_/**/isr/**/VEC) #define GETFIRQ() ((const)*((unsigned *)FIRQVEC)) #define SETFIRQ(isr) (*((unsigned *)FIRQVEC) = (unsigned *)&_/**/isr/**/VEC)