	.module rlpos.c
	.area data
_main_frame_ptr::
	.blkb 2
	.area idata
	.word 0
	.area data
_main_frame_x_ptr::
	.blkb 2
	.area idata
	.word 0
	.area data
_temp_task_frame_ptr::
	.blkb 2
	.area idata
	.word 0
	.area data
	.area text
;  lreg1 -> -4,x
;  lreg2 -> -8,x
;          ?temp -> -26,x
;          ?temp -> -26,x
;          ?temp -> -26,x
;          ?temp -> -28,x
;          ?temp -> -26,x
;           addr -> -24,x
;             id -> -22,x
;         result -> -20,x
;  temp_heap_ptr -> -18,x
;           temp -> -16,x
; temp_heap_size -> -15,x
; priority_check -> -13,x
;       deadline -> -12,x
;              i -> -10,x
_main::
	pshx
	tfr s,x
	leas -36,sp
; /*	RLPOS: RLPotter Operating System
; 
; 		   Version 0.6 for the 68HC12D60A microcontroller
; 		   by Ryan Potter
; 		   ryan@rlpotter.com
; 	
; 	
; 	v0.6 April 24, 2003: 11042 bytes
; 		   - made the task block and the task control block dynamic, so that
; 		   	 now tasks can create tasks, and can also start/stop them
; 		   - implemented the sysInit() task for kicking off a user system
; 		   - implemented a kernel debug command for tracing code execution
; 		   - implemented small msg box system in kernel for tasks
; 		   - implemented COP watchdog reset timer
; 		   - added system resources to semlib
; 		   - added skeleton ISR_handler() code for the other interrupts
; 		   - implemented _HC12Setup.c to initialize/harden the system
; 		   
; 	v0.5 April 16, 2003:
; 		   - added priority preemption
; 		   - finished kernel task state switcher 
; 		   - it is now officially a legitimate
; 		   	 	rate monotonic
; 				priority preemptive
; 				multitasking
; 				Real Time Operating System  :)
; 		   - made kernel.c and semlib.c consistent with the 
; 		   	 rest of the kernel
; 		   - included the early framework for a msg box system
; 			 
; 	v0.4 April 13, 2003: 8096 bytes
; 		   - gerneralized the shell command-line input parser: 
; 		   	 cmd <arg1, arg2, ... argn> (up to 32 chars)
; 		   - added kernel and shell functions
; 		   
; 	v0.3 April 12, 2003: 6155 bytes
; 		   - added a beginning shell user interface.
; 		   - added a resource control block and basic semaphore functions.
; 		   - added basic kernel functions
; 		   
; 	v0.2 April 9, 2003:
; 	  	   - able to round-robin with RTI interrupt.
; 		   - bonified/certified multitasking with 3 tasks. :)
; 		   
; 	v0.1 April 3, 2003:
; 	  	   - able to round-robin without interrupts.
; 		   - not multitasking, really.
; 		   
; 	v0.0 started April 1, 2003; 0 bytes
; 		   - no idea where to start.
; 		   - don't want to look at anyone else's work. ;0)
; 
; 
; 
; 	
; 	Architecture/C assumptions:
; 		1) 'D' register is the accumulator
; 		2) 'X' register points to the top of the current stack
; 		3) 'Y' register is for general use in indexed operations
; 		4) the heap grows upward and mem segments allocated by malloc,
; 		   realloc, and calloc are linear and contiguous.
; 		5) the stack grows downwards, and there is no boundary checking.
; 		   
; 	Potential problem areas:
; 		1) 'running' section of the kernel get's compiled using extra
; 		   push and pop instructions
; 		2) run out of ram (global + stack + heap)
; 		
; */
; 	
; 	
; 	
; #include <912d60.h>
; #include <stdio.h>
; #include <stdlib.h>
; #include <string.h>
; #include "kernel.h"
; 
; 
; 
; 
; // FUNCTION PROTOTYPES
; void RTI_handler(void);
; void sysInit(void);
; void shell(void);
; void sysTime(void);
; void (*task_ptr[MAXTASKS])(void);
; 
; 
; 
; 
; // GLOBAL VARIABLES
; unsigned char *main_frame_ptr = NULL;	   	// bottom of main() frame
; unsigned char *main_frame_x_ptr = NULL;		// top of main() frame (x-reg ptr)
; unsigned char *temp_task_frame_ptr = NULL;	// temp CCR pointer for RTI
; 
; 
; extern unsigned int current;		   	 		// current task id number
; extern unsigned long int system_tick;
; extern unsigned int cop_cycle;
; 
; 
; // task control block
; extern struct task_block {
; 	 	void (*address)();			   		// Address of the task
; 		unsigned char id; 			  		// ID of task
; 		char name[9];	  					// Name
; 		enum task_state state;				// State
; 		unsigned char priority;				// Priority
; 		unsigned long int period_tick;		// for determining if deadline is up
; 		unsigned int interrupt_msg_box;		// flags for pending interrupts
; 		enum message_box message;			// misc flags
; 		unsigned char message_data[2];		// data for misc_msg_box flags
; 	 	unsigned char *heap_ptr;			// heap addr while not current task
; 		unsigned int heap_size;				// heap size
; 		unsigned char *frame_ptr;			// CCR pointer
; 		};
; 
; 
; // resource control block
; extern struct resource_block {
; 		unsigned char id;	   				// ID of resource
; 		char name[5];	  					// Name of resource
; 		enum resource_state state;			// State (busy, free...)
; 		unsigned char owner;				// Current resource owner
; 		signed char queue[3];				// Tasks waiting on resource
; 		unsigned char queue_ptr;			// Next free spot in queue
; 		};
; 		
; 		
; extern struct task_block *task[MAXTASKS];
; extern struct resource_block resource[NUMRESOURCES];
; 
; 
; extern char error_msg[9][25];
; extern char error_src[5][18];
; 
; 
; extern char kdb_trace;
; 
; 
; 
; 
; 
; main() {
; 
; 	 // LOCAL VARIABLES
; 	 int result, id;
; 	 unsigned int i, addr, temp_heap_size;
; 	 unsigned char *temp_heap_ptr, temp, priority_check;
; 	 unsigned int deadline;
; 	 
; 	 extern int _bss_end, _textmode;		   	 		
; 	  
; 	 _textmode = 1;	 	  // maps '\n' to "CR/LF" for Windows terminals
	ldd #1
	std __textmode
; 	 current = 0;  	 	  // start the shell first
	ldd #0
	std _current
; 	 cop_cycle = 0;		  // fresh watchdog
	ldd #0
	std _cop_cycle
	ldd #0
	std -10,x
	bra L7
L4:
	ldd -10,x
	lsld
	addd #_task_ptr
	xgdy
	ldd #0
	std 0,y
	ldd -10,x
	lsld
	addd #_task
	xgdy
	ldd #0
	std 0,y
L5:
	ldd -10,x
	addd #1
	std -10,x
L7:
; 	 
; 	 
; 	 // initialize the task pointer array and the tcb array.
; 	 for (i=0; i<MAXTASKS; i++) {
	ldd -10,x
	cpd #8
	blo L4
	ldd #0
	std -10,x
	bra L11
L8:
	ldd #12
	ldy -10,x
	emul
	addd #_resource
	xgdy
	ldd -10,x
	stab 0,y
	ldd #12
	ldy -10,x
	emul
	addd #_resource+6
	xgdy
	clr 0,y
	ldd #12
	ldy -10,x
	emul
	addd #_resource+7
	xgdy
	ldab #255
	stab 0,y
	ldd #12
	ldy -10,x
	emul
	addd #_resource+11
	xgdy
	clr 0,y
L9:
	ldd -10,x
	addd #1
	std -10,x
L11:
; 	 	 task_ptr[i] = NULL;
; 		 task[i] = NULL;
; 		 }
; 		 
; 		 
; 		 
; 	 // initialize the rcb pointer block
; 	 for (i=0; i<NUMRESOURCES; i++) {
	ldd -10,x
	cpd #4
	blo L8
; 	 	 resource[i].id = i;
; 		 resource[i].state = NOTBUSY;
; 		 resource[i].owner = 255;
; 		 resource[i].queue_ptr = 0;
; 		 }
; 
; 	 
; 	 
;  	 // save SP value for use in the RTI
; 	 asm("TFR s,d");
		TFR s,d

; 	 asm("STD _main_frame_ptr");
		STD _main_frame_ptr

; 	 // save X reg value for use in the RTI
; 	 asm("TFR x,d");
		TFR x,d

; 	 asm("STD _main_frame_x_ptr");
		STD _main_frame_x_ptr

; 	 
; 	 
; 	 
; 	 
; 	 // START/INITIALIZE the os3
; 		// KDB_TRACE Section 1
; 	 
; 	 // create and initialize the heap (for dynamic (runtime) var allocation)
; 	 _NewHeap(&_bss_end, (char *)(&_bss_end) + (INITIAL_HEAP_SIZE));
	ldd #__bss_end+1372
	std 0,sp
	ldd #__bss_end
	jsr __NewHeap
; 	 
; 	 
; 	 // set up the serial port
; 	 setbaud(BAUD38K);	 	  // actually running at 19K baud due to xtal speed
	ldd #13
	jsr _setbaud
; 	 #ifdef KDB_TRACE_LEVEL_1
; 		if (kdb_trace) puts("kDB1-0");	 
	tst _kdb_trace
	beq L16
	ldd #L18
	jsr _puts
L16:
; 	 #endif
; 	 
; 
; 	 // create the sysInit task
; 	 create_task("sysInit", &sysInit, 1, PENDING);
	ldd #1
	std 4,sp
	ldd #1
	std 2,sp
	ldd #_sysInit
	std 0,sp
	ldd #L19
	jsr _create_task
; 	 #ifdef KDB_TRACE_LEVEL_1
; 		if (kdb_trace) puts("kDB1-1");	 
	tst _kdb_trace
	beq L20
	ldd #L22
	jsr _puts
L20:
; 	 #endif 
; 
; 
; 		
; 	 // create the shell
; 	 create_task("shell", &shell, 2, PENDING);
	ldd #1
	std 4,sp
	ldd #2
	std 2,sp
	ldd #_shell
	std 0,sp
	ldd #L23
	jsr _create_task
; 	 #ifdef KDB_TRACE_LEVEL_1
; 		if (kdb_trace) puts("kDB1-2");	 
	tst _kdb_trace
	beq L24
	ldd #L26
	jsr _puts
L24:
; 	 #endif
; 
; 		
; 		
; 	 /*// create sysTime
; 	 create_task("sysTime", &sysTime, 5, PENDING);
; 	 #ifdef KDB_TRACE_LEVEL_1
; 		if (kdb_trace) puts("kDB1-3");	 
; 	 #endif*/
; 	 
; 
; 	 
; 	 // treat the COP and system tick
; 	 COP_PET(0x55);
	ldab #85
	stab 0x17
; 	 COP_PET(0xAA);
	ldab #170
	stab 0x17
; 	 system_tick = 0;
	ldy #L27
	movw 0,y,-4,x
	movw 2,y,-2,x
	ldy #_system_tick
	movw -4,x,0,y
	movw -2,x,2,y
; 	 
; 	 
; 	 // print the opening comments
; 	 puts("rlpOS v0.6\n\n");
	ldd #L28
	jsr _puts
	lbra L30
L29:
; 
; 	 
; 
; 	 
; 	 // MULTITASKING KERNEL: Priority Preemptive, Real Time, multitasking 
; 		// KDB_TRACE Section 2
; 	 while(1) {	 
; 	 	
; 		//-------------------------------
; 		/* REENTRY POINT after either 
; 		   		   1) task finishes, or 
; 		   		   2) RTI
; 		*/
; 		//-------------------------------
; 		
; 		
; 		#ifdef KDB_TRACE_LEVEL_1
; 			if (kdb_trace) puts("kDB2.1");	 
	tst _kdb_trace
	beq L32
	ldd #L34
	jsr _puts
L32:
; 		#endif
; 		   
; 		   		
; 		/* No interrupts allowed inside of main().  Only allowed
; 		   inside of non-critical sections of tasks */ 
; 	 	INTR_OFF();	
		sei

; 		
; 		
; 		// PET THE DOG: cop watchdog reset timer (pet freq = 2x COP freq)
; 		if (cop_cycle == 4) {
	ldd _cop_cycle
	cpd #4
	bne L35
; 		   COP_PET(0x55);
	ldab #85
	stab 0x17
; 		   COP_PET(0xAA);
	ldab #170
	stab 0x17
; 		   cop_cycle = 0;
	ldd #0
	std _cop_cycle
; 		   }
L35:
; 		#ifdef KDB_TRACE_LEVEL_1
; 			if (kdb_trace) puts("kDB2.2-1");	 
	tst _kdb_trace
	beq L37
	ldd #L39
	jsr _puts
L37:
	ldd #0
	std -10,x
	bra L43
L40:
; 		#endif
; 		
; 		
; 		
; 		// CHANGE STATES ACCORDING TO MESSAGES
; 		// 'waiting' needs to have highest precedence here
; 		for (i=0; i<MAXTASKS; i++) {
; 			if (task[i] == NULL)
	ldd -10,x
	lsld
	addd #_task
	xgdy
	ldd 0,y
	bne L44
; 			   continue;
	bra L41
L44:
; 			if (task[i]->message && STATE_FLAG) {  
	ldd -10,x
	lsld
	addd #_task
	xgdy
	ldy 0,y
	tst 20,y
	beq L46
; 			   // set task state to what the message says
; 		   	   task[i]->state = task[i]->message_data[STATE_BOX];
	ldd -10,x
	lsld
	addd #_task
	xgdy
	ldy 0,y
	sty -26,x
	ldy -26,x
	ldab 21,y
	ldy -26,x
	stab 12,y
; 			   // clear the STATE_FLAG
; 			   task[i]->message &= ~(STATE_FLAG);
	ldd -10,x
	lsld
	addd #_task
	xgdy
	ldd 0,y
	addd #20
	std -28,x
	tfr d,y
	pshy ; spill
	ldy -28,x
	puly ; reload
	bclr 0,y,#0x1
; 			   #ifdef KDB_TRACE_LEVEL_2
; 				if (kdb_trace) puts("kDB2.3-2a");	 
; 			   #endif
; 			   }
L46:
L41:
	ldd -10,x
	addd #1
	std -10,x
L43:
	ldd -10,x
	cpd #8
	blo L40
; 			#ifdef KDB_TRACE_LEVEL_2
; 				if (kdb_trace) puts("kDB2.3-2b");	 
; 			#endif
; 			}
; 		#ifdef KDB_TRACE_LEVEL_1
; 			if (kdb_trace) puts("kDB2.3-1");	 
	tst _kdb_trace
	beq L48
	ldd #L50
	jsr _puts
L48:
	ldd #0
	std -10,x
	bra L54
L51:
; 		#endif
; 		
; 			
; 
; 		// RT PRIORITY BLOCK:
; 		// set the current task id based on priority and deadline
; 		
; 		// determine if the deadline is up for idle tasks
; 		/* deadline, is equal to period plus an initial time (t0) reference
; 		   (t0 = system_tick).  Period = priority + 1.  
; 		   Changing the state from idle to PENDING occurs here.  */
; 		for (i=0; i<MAXTASKS; i++) {
; 			if (task[i]->state == IDLE) {
	ldd -10,x
	lsld
	addd #_task
	xgdy
	ldy 0,y
	tst 12,y
	bne L55
; 			   deadline = task[i]->period_tick + (task[i]->priority + 1);
	ldd -10,x
	lsld
	addd #_task
	xgdy
	ldy 0,y
	sty -26,x
	ldy -26,x
	ldab 13,y
	clra
	addd #1
	jsr __d2lreg2
	ldy -26,x
	leay 14,y
	movw 0,y,-4,x
	movw 2,y,-2,x
	jsr __ladd
	jsr __lreg2d
	std -12,x
; 			   if (system_tick >= deadline) {
	ldy #_system_tick
	movw 0,y,-4,x
	movw 2,y,-2,x
	ldd -12,x
	std -6,x
	movw #0,-8,x
	jsr __lcmp
	blo L57
; 			   	  task[i]->state = PENDING; 	  // change state at deadline
	ldd -10,x
	lsld
	addd #_task
	xgdy
	ldy 0,y
	ldab #1
	stab 12,y
; 				  #ifdef KDB_TRACE_LEVEL_2
; 					if (kdb_trace) puts("kDB2.4-2");	 
; 				  #endif
; 			   	  } 	
L57:
; 				}
L55:
L52:
	ldd -10,x
	addd #1
	std -10,x
L54:
	ldd -10,x
	cpd #8
	blo L51
; 			 // if (task[i]->message) {} ???		
; 			 }
; 		#ifdef KDB_TRACE_LEVEL_1
; 			if (kdb_trace) puts("kDB2.4-1");	 
	tst _kdb_trace
	beq L59
	ldd #L61
	jsr _puts
L59:
; 		#endif			
; 		
; 		
; 		// set current = to highest priority pending/running task.
; 		priority_check = 255;   	  	  // lowest possible
	ldab #255
	stab -13,x
	ldd #0
	std -10,x
	bra L65
L62:
; 		
; 		for (i=0; i<MAXTASKS; i++) {
; 			if (!(task[i] == NULL)) {
	ldd -10,x
	lsld
	addd #_task
	xgdy
	ldd 0,y
	beq L66
	ldd -10,x
	lsld
	addd #_task
	xgdy
	ldy 0,y
	ldab 12,y
	clra
	std -26,x
	cpd #1
	beq L70
	ldd -26,x
	cpd #2
	bne L68
L70:
; 			   if ((task[i]->state == PENDING) || (task[i]->state == RUNNING)) {
; 			   	  if (task[i]->priority <= priority_check) {
	ldd -10,x
	lsld
	addd #_task
	xgdy
	ldy 0,y
	ldab 13,y
	cmpb -13,x
	bhi L71
; 				  	 current = i;
	movw -10,x,_current
; 				 	 priority_check = task[i]->priority;
	ldd -10,x
	lsld
	addd #_task
	xgdy
	ldy 0,y
	ldab 13,y
	stab -13,x
; 				 	 #ifdef KDB_TRACE_LEVEL_2
; 						if (kdb_trace) puts("kDB2.5-2");	 
; 				  	 #endif 
; 			   	 	 }
L71:
; 			   	   }
L68:
; 				}
L66:
L63:
	ldd -10,x
	addd #1
	std -10,x
L65:
	ldd -10,x
	cpd #8
	blo L62
; 			 }
; 		#ifdef KDB_TRACE_LEVEL_1
; 			if (kdb_trace) puts("kDB2.5-1");	 
	tst _kdb_trace
	beq L73
	ldd #L75
	jsr _puts
L73:
	ldd _current
	lsld
	addd #_task
	xgdy
	ldy 0,y
	ldab 12,y
	clra
	std -26,x
	beq L79
	ldd -26,x
	cpd #1
	beq L83
	ldd -26,x
	cpd #2
	lbeq L90
	ldd -26,x
	cpd #3
	lbeq L98
	ldd -26,x
	cpd #4
	lbeq L102
	lbra L76
X0:
; 		#endif
; 		
; 		
; 		
; 		// DISPATCH, or otherwise deal with the current task
; 			// KDB_TRACE Section 3
; 
; 		#ifdef KDB_TRACE_LEVEL_2
; 		if (kdb_trace) {
; 			printf("task[%d]->state = %d\n", current, task[current]->state);
; 			printf("task[%d]->prior = %d\n", current, task[current]->priority);
; 			}
; 		#endif
; 		
; 		switch (task[current]->state) {
L79:
; 			   case IDLE:			   // skip task
; 					#ifdef KDB_TRACE_LEVEL_1
; 						if (kdb_trace) puts("kDB3.1-1");
	tst _kdb_trace
	lbeq L77
	ldd #L82
	jsr _puts
; 					#endif
; 					break;
	lbra L77
L83:
; 			   case PENDING:		   // ready and waiting to run
; 			   		task[current]->state = RUNNING;
	ldd _current
	lsld
	addd #_task
	xgdy
	ldy 0,y
	ldab #2
	stab 12,y
; 					task[current]->period_tick = system_tick;
	ldd _current
	lsld
	addd #_task
	xgdy
	ldy 0,y
	leay 14,y
	pshy ; spill
	ldy #_system_tick
	movw 0,y,-4,x
	movw 2,y,-2,x
	puly ; reload
	movw -4,x,0,y
	movw -2,x,2,y
; 					#ifdef KDB_TRACE_LEVEL_1
; 						if (kdb_trace) puts("kDB3.2-1");
	tst _kdb_trace
	beq L84
	ldd #L86
	jsr _puts
L84:
; 					#endif
; 					#ifdef KDB_TRACE_LEVEL_2
; 						if (kdb_trace) {
; 							//puts("kDB3.2-2");
; 							putchar('S');
; 							putchar(current+48);
; 							putchar('\n');
; 						    }
; 					#endif  
; 			   		(*task_ptr[current])();	 	  			// start the task
	ldd _current
	lsld
	addd #_task_ptr
	xgdy
	ldy 0,y
	jsr 0,y
; 					task[current]->state = IDLE;			// task finished
	ldd _current
	lsld
	addd #_task
	xgdy
	ldy 0,y
	clr 12,y
; 					#ifdef KDB_TRACE_LEVEL_1
; 						if (kdb_trace) puts("kDB3.3-1");
	tst _kdb_trace
	lbeq L77
	ldd #L89
	jsr _puts
; 					#endif
; 					#ifdef KDB_TRACE_LEVEL_2
; 						if (kdb_trace) {
; 							//puts("kDB3.3-2");
; 							putchar('S');
; 							putchar(current+48);
; 							putchar('\n');
; 						    }
; 					#endif  				
; 			   		break;
	lbra L77
L90:
; 			   case RUNNING:			// interrupted. continue running.
; 					// restore the task heap to the stack
; 					#ifdef KDB_TRACE_LEVEL_1
; 						if (kdb_trace) puts("kDB3.4-1");
	tst _kdb_trace
	beq L91
	ldd #L93
	jsr _puts
L91:
; 					#endif
; 					#ifdef KDB_TRACE_LEVEL_2
; 						if (kdb_trace) {
; 							//puts("kDB3.4-2");
; 							putchar('R');
; 							putchar(current+48);
; 							putchar('\n');
; 						    }
; 					#endif  
; 					temp_heap_size = task[current]->heap_size;
	ldd _current
	lsld
	addd #_task
	xgdy
	ldy 0,y
	ldy 25,y
	sty -15,x
; 					temp_heap_ptr = task[current]->heap_ptr;
	ldd _current
	lsld
	addd #_task
	xgdy
	ldy 0,y
	ldy 23,y
	sty -18,x
	ldd #0
	std -10,x
	bra L97
L94:
	ldd -10,x
	addd -18,x
	xgdy
	ldab 0,y
	stab -16,x
	ldd _main_frame_ptr
	subd -15,x
	std -30,x
	ldd -10,x
	addd -30,x
	xgdy
	ldab -16,x
	stab 0,y
L95:
	ldd -10,x
	addd #1
	std -10,x
L97:
; 			   		for (i=0; i<temp_heap_size; i++) {
	ldd -10,x
	cpd -15,x
	blo L94
; 						temp = *(temp_heap_ptr + i);
; 						*(main_frame_ptr - temp_heap_size + i) = temp;
; 						//putchar('.');
; 						}
; 					
; 					// restore context and run
; 					temp_task_frame_ptr = task[current]->frame_ptr;
	ldd _current
	lsld
	addd #_task
	xgdy
	ldy 0,y
	ldy 27,y
	sty _temp_task_frame_ptr
; 					asm("LDS _temp_task_frame_ptr");
		LDS _temp_task_frame_ptr

; 					asm("RTI");
		RTI

; 			   		break;
	bra L77
L98:
; 			   case WAITING:   		   // waiting on a resource
; 					#ifdef KDB_TRACE_LEVEL_1
; 						if (kdb_trace) puts("kDB3.5-1");
	tst _kdb_trace
	beq L77
	ldd #L101
	jsr _puts
; 					#endif
; 			   		break;
	bra L77
L102:
; 			   case STOPPED:		   // done running until later
; 					#ifdef KDB_TRACE_LEVEL_1
; 						if (kdb_trace) puts("kDB3.6-1");
	tst _kdb_trace
	beq L77
	ldd #L105
	jsr _puts
; 					#endif
; 			   		break;
	bra L77
L76:
; 			   default:	  			   // shouldn't happen, but, error if so.
; 			   		puts("KERNEL: task state error\n");
	ldd #L106
	jsr _puts
; 			   		exit(1);
	ldd #1
	jsr _exit
; 				}	// end switch
L77:
L30:
	lbra L29
X1:
; 		
; 	 		}		// end while(1)
; 	 
; 	 return 0;
	ldd #0
L3:
	tfr x,s
	pulx
	.dbline 0 ; func end
	rts
;  lreg1 -> -4,x
;  lreg2 -> -8,x
;          ?temp -> -16,x
;      local_thp -> -14,x
;     frame_size -> -12,x
;              i -> -10,x
_RTI_handler::
	pshx
	tfr s,x
	leas -20,sp
; 	 
; }			 		// end main()
; 
; 
; 
; #pragma interrupt_handler RTI_handler()
; 
; void RTI_handler(void) {
; 
; 	 size_t frame_size;
; 	 unsigned int i;
; 	 unsigned char *local_thp;
; 	 
; 	 
; 	 //ACKNOWLEDGE THE INTERRUPT
; 	 INTR_OFF();  	   	// redundant. automatically done by the processor
		sei

; 	 RTIFLG = 0x0080;  	// acknowledge/clear the interrupt
	ldab #128
	stab 0x15
; 	 
; 	 
; 	 #ifdef KDB_TRACE_LEVEL_1
; 	  	if (kdb_trace) putchar('.');
	tst _kdb_trace
	beq L108
	ldd #46
	jsr _putchar
L108:
; 	 #endif
; 	 
; 	 
; 	 // SET THE FRAME POINTER for the interupted task.
; 	 // should point to the CCR entry on the stack.
; 	 asm("TFR x,d");  		  	  	  	 // start of RTI stack
		TFR x,d

; 	 asm("ADDD #2");				  	 // adjust to CCR stack entry
		ADDD #2

; 	 asm("STD _temp_task_frame_ptr");	 // put into task_frame_ptr
		STD _temp_task_frame_ptr

; 	 task[current]->frame_ptr = temp_task_frame_ptr;
	ldd _current
	lsld
	addd #_task
	xgdy
	ldy 0,y
	ldd _temp_task_frame_ptr
	std 27,y
; 
; 	 
; 	 
; 	 //PLACE CURRENT TASK CONTEXT ONTO THE HEAP
; 	 // determine size of heap segment needed
; 	 frame_size = main_frame_ptr - temp_task_frame_ptr; 	// always positive
	ldd _main_frame_ptr
	subd _temp_task_frame_ptr
	std -12,x
; 	 task[current]->heap_size = (int)frame_size;
	ldd _current
	lsld
	addd #_task
	xgdy
	ldy 0,y
	ldd -12,x
	std 25,y
; 	 //printf("frame size: %d\n", frame_size);
; 	 
; 	 // reallocate heap memory
; 	 //printf("heap_ptr = %d\n", task[current]->heap_ptr);
; 	 task[current]->heap_ptr = realloc(task[current]->heap_ptr, frame_size);
	movw -12,x,0,sp
	ldd _current
	lsld
	addd #_task
	xgdy
	ldd 0,y
	addd #23
	std -16,x
	ldd [-16,x]
	jsr _realloc
	std -18,x
	ldy -16,x
	ldd -18,x
	std 0,y
; 	 local_thp = task[current]->heap_ptr;	
	ldd _current
	lsld
	addd #_task
	xgdy
	ldy 0,y
	ldy 23,y
	sty -14,x
; 
; 
; 	 if (local_thp == NULL) {
	ldd -14,x
	bne L110
; 		#ifdef KERNEL_ERROR_MSGS
; 			//printf("local_thp: %d\n", local_thp);
; 			//printf("heap: %d bytes\n", get_free_memory());
; 	 		puts("out of heap space!");
	ldd #L112
	jsr _puts
; 		#endif
; 		exit(0);
	ldd #0
	jsr _exit
; 	 	}
L110:
	ldd #0
	std -10,x
	bra L116
L113:
	ldd -10,x
	addd _temp_task_frame_ptr
	xgdy
	ldab 0,y
	pshd ; spill
	ldd -10,x
	addd -14,x
	xgdy
	puld ; reload
	stab 0,y
L114:
	ldd -10,x
	addd #1
	std -10,x
L116:
; 	 
; 	 // transfer task frame to the heap one byte at a time.
; 	 // assumes the heap grows from low to high addr.
; 	 for(i=0; i<frame_size; i++) {
	ldd -10,x
	cpd -12,x
	blo L113
; 		*(local_thp + i) = *(temp_task_frame_ptr + i);
; 	 	}
; 	 
; 
; 	 
; 	 // update system time base and cop reset counter
; 	 system_tick++;
	ldy #_system_tick
	movw 0,y,-4,x
	movw 2,y,-2,x
	ldy #L117
	movw 0,y,-8,x
	movw 2,y,-6,x
	jsr __ladd
	ldy #_system_tick
	movw -4,x,0,y
	movw -2,x,2,y
; 	 cop_cycle++;
	ldd _cop_cycle
	addd #1
	std _cop_cycle
; 	 
; 	 
; 	 
; 	 // RETURN: simulate a RTS instruction
; 	 // set stack pointer for main()
; 	 asm("LDS _main_frame_ptr");
		LDS _main_frame_ptr

; 	 asm("LDX _main_frame_x_ptr");
		LDX _main_frame_x_ptr

; 	 /* return to main() at the reentry point
; 	    and must be adjusted after each kernel mod/compilation!!  */
; 	 asm("JMP $114E");
		JMP $114E

; 	 
; 
; 	 // return (0)  -- NOT used 
; 	 /* this ISR should never use the 'return x' command.
; 	    It doesn't make sense since it always interrupts a Task, but
; 	    never returns to it... but to main() instead.  */
; 	 	 
; }
L107:
	tfr x,s
	pulx
	.dbline 0 ; func end
	rti
	.area bss
_task_ptr::
	.blkb 16
	.area text
L117:
	.word 0,1
L112:
	.byte 'o,'u,'t,32,'o,'f,32,'h,'e,'a,'p,32,'s,'p,'a,'c
	.byte 'e,33,0
L106:
	.byte 'K,'E,'R,'N,'E,'L,58,32,'t,'a,'s,'k,32,'s,'t,'a
	.byte 't,'e,32,'e,'r,'r,'o,'r,10,0
L105:
	.byte 'k,'D,'B,51,46,54,45,49,0
L101:
	.byte 'k,'D,'B,51,46,53,45,49,0
L93:
	.byte 'k,'D,'B,51,46,52,45,49,0
L89:
	.byte 'k,'D,'B,51,46,51,45,49,0
L86:
	.byte 'k,'D,'B,51,46,50,45,49,0
L82:
	.byte 'k,'D,'B,51,46,49,45,49,0
L75:
	.byte 'k,'D,'B,50,46,53,45,49,0
L61:
	.byte 'k,'D,'B,50,46,52,45,49,0
L50:
	.byte 'k,'D,'B,50,46,51,45,49,0
L39:
	.byte 'k,'D,'B,50,46,50,45,49,0
L34:
	.byte 'k,'D,'B,50,46,49,0
L28:
	.byte 'r,'l,'p,'O,'S,32,'v,48,46,54,10,10,0
L27:
	.word 0,0
L26:
	.byte 'k,'D,'B,49,45,50,0
L23:
	.byte 's,'h,'e,'l,'l,0
L22:
	.byte 'k,'D,'B,49,45,49,0
L19:
	.byte 's,'y,'s,'I,'n,'i,'t,0
L18:
	.byte 'k,'D,'B,49,45,48,0

