#include <vstypes.h>
#include <vsrv.h>


/*
   UARTTX interrupt routine.
   Never call explicitly!
   This routine calls void IntUartTxC(void);

   Set the interrupt vector from C as follows:

   extern u_int16 IntUartTxVector;
   [...]
   WriteIMem((void *)(0x20+INTV_UARTTX), ReadIMem((void *)(&IntUartTxVector)));

   After setting the interrupt vector, activate the interrupt as follows
     (example for interrupt priority 1):
   PERIP(INT_ENABLE0_LP) |= INTF_UARTTX;
   PERIP(INT_ENABLE0_HP) &= ~INTF_UARTTX;

   Before exiting your application, deactivate the interrupt as follows:
   PERIP(INT_ENABLE0_LP) &= ~INTF_UARTTX;
   PERIP(INT_ENABLE0_HP) &= ~INTF_UARTTX;
*/
	.sect code,IntUartTxVector
	.export _IntUartTxVector
_IntUartTxVector:
	jmpi _IntUartTxAsm,(i6)+1

#if 1
	.sect code,IntUartTxAsm
	.export _IntUartTxAsm
_IntUartTxAsm:
	stx i7,(i6)+1;	sty lr0,(i6)
	STNP lr1,(i6)+1
	stx le,(i6)+1;	sty lc,(i6)
	stx mr1,(i6)+2;	sty i5,(i6)	// Save MR1, align pad
	ldc MR_INT|MR_LONG,mr0
	stx a2,(i6)+2;	sty b2,(i6)
	stx c2,(i6)+2;	sty d2,(i6)
	stx a0,(i6)+2;	sty a1,(i6)	// i7,i5,lr0 i0,i1,a0,a1,P
	stx b0,(i6)+2;	sty b1,(i6)
	stx c0,(i6)+2;	sty c1,(i6)
	stx d0,(i6)+2;	sty d1,(i6)
	add null,p,a
	stx a0,(i6)+2;	sty a1,(i6)
	stx i0,(i6)+1;	sty i1,(i6)
	.import _IntUartTxC
#if 1
	call _IntUartTxC
	ldc MR_INT,mr0

	ldx (i6)-1,null
	ldx (i6)-2,i0;	ldy (i6),i1
	ldc MR_INT|MR_LONG,mr0	//wide mode, restore all bits
	ldx (i6)-2,a0;	ldy (i6),a1
	resp a0,a1
	ldx (i6)-2,d0;	ldy (i6),d1
	ldx (i6)-2,c0;	ldy (i6),c1
	ldx (i6)-2,b0;	ldy (i6),b1
	ldx (i6)-2,a0;	ldy (i6),a1
	ldx (i6)-2,c2;	ldy (i6),d2
	ldx (i6)-2,a2;	ldy (i6),b2
	//no ALU regs afterwards, so wide mode doesn't affect it
	ldx (i6)-1,mr0;	ldy (i6),i5
	ldx (i6)-1,le;	ldy (i6),lc
	ldc INT_GLOB_ENA,i7
	STP i7,(i7);	LDNP (i6)-1,lr0   // lr1
	jr
        ldx (i6)-1,i7   ; ldy (i6),lr0  // i7  lr0
#else
	.import _IntUartRxAsmEpilogue
	ldc _IntUartRxAsmEpilogue,lr0
	j _IntUartTxC
	ldc MR_INT,mr0
#endif
#else
/*
	2024-03-25: Even this short version would be usable in the
	case it can be guaranteed that the C function never calls any
	subfunction that would use wide mode(s) in any ways.
	At the moment of writing this text, this would often be the
	case, but it will almost certainly change in the future as
	more and more support functions start to make use of wide
	modes. So, use only if you are absolutely sure what you are doing!
*/
	.sect code,IntUartTxAsm
	.export _IntUartTxAsm
_IntUartTxAsm:
	STNP i7,(i6)+1;	STP mr1,(i6)
	stx lr0,(i6)+1;	sty i5,(i6)
	stx a2,(i6)+1;	sty b2,(i6)
	stx c2,(i6)+1;	sty d2,(i6)
	stx a1,(i6)+1;	sty a0,(i6)
	add null,p,a
	stx a1,(i6);	sty a0,(i6)

	.import _IntUartTxC
#if 0
	call _IntUartTxC
	ldc MR_INT,mr0

	ldx (i6)-1,a1;	ldy (i6),a0
	resp a0,a1
	ldx (i6)-1,a1;	ldy (i6),a0
	ldx (i6)-1,c2;	ldy (i6),d2
	ldx (i6)-1,a2;	ldy (i6),b2
	ldx (i6)-1,lr0;	ldy (i6),i5
	LDP (I6),mr0
	ldc INT_GLOB_ENA,i7
	reti
	LDNP (i6)-1,I7;	STP i7,(i7)
#else
	.import _IntUartRxShortAsmEpilogue
	ldc _IntUartRxShortAsmEpilogue,lr0
	j _IntUartTxC
	ldc MR_INT,mr0
#endif
#endif


	.end
