	.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 -> -27,x
;          ?temp -> -27,x
;          ?temp -> -27,x
;          ?temp -> -29,x
;          ?temp -> -27,x
;           addr -> -25,x
;         result -> -23,x
;             id -> -21,x
;  temp_heap_ptr -> -19,x
;           temp -> -17,x
;      cop_cycle -> -16,x
; temp_heap_size -> -15,x
; priority_check -> -13,x
;       deadline -> -12,x
;              i -> -10,x
_main::
	pshx
	tfr s,x
	leas -42,sp
; /*	RLPOS: RLPotter Operating System
; 
; 		   Version 0.5.2 for the 68HC12D60A microcontroller
; 		   by Ryan Potter
; 		   ryan@rlpotter.com
; 	
; 	
; 	v0.5.2:
; 		   - make task_block dynamic
; 		   
; 	v0.5.1:
; 		   - implemented task msg box system for states in kernel
; 		   - 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[NUMTASKS])(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;
; 
; 
; // 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[NUMTASKS];
; 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, cop_cycle;
; 	 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
	clr -16,x
; 	 
; 	 
; 	 // initialize the task block
; 	 for (i=0; i<NUMTASKS; i++)
	ldd #0
	std -10,x
	bra L7
L4:
	ldd -10,x
	lsld
	addd #_task
	xgdy
	ldd #0
	std 0,y
L5:
	ldd -10,x
	addd #1
	std -10,x
L7:
	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[i] = NULL;
; 		 
; 		 
; 	 // initialize the rcb pointer block
; 	 for (i=0; i<NUMRESOURCES; i++) {
	ldd -10,x
	cpd #11
	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+1186
	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
; 	 if ((id = create_task("sysInit", &sysInit, 0)) >= 0) {
	ldd #0
	std 2,sp
	ldd #_sysInit
	std 0,sp
	ldd #L21
	jsr _create_task
	std -32,x
	std -21,x
	ldd -32,x
	blt L19
; 	 	task_ptr[id] = sysInit;
	ldd -21,x
	lsld
	addd #_task_ptr
	xgdy
	ldd #_sysInit
	std 0,y
; 	 	task[id]->state = PENDING;
	ldd -21,x
	lsld
	addd #_task
	xgdy
	ldy 0,y
	ldab #1
	stab 12,y
; 		}
	bra L20
L19:
; 	 else {
; 		if (KERNEL_ERROR_MSGS)
; 			printf("%s %s\n", error_src[0], error_msg[8]);
	ldd #_error_msg+200
	std 2,sp
	ldd #_error_src
	std 0,sp
	ldd #L24
	jsr _printf
L22:
; 	      }
L20:
; 	#ifdef KDB_TRACE_LEVEL_1
; 		if (kdb_trace) puts("kDB1-1");	 
	tst _kdb_trace
	beq L26
	ldd #L28
	jsr _puts
L26:
; 	 #endif 
; 
; 
; 		
; 	 // create the shell
; 	 if ((id = create_task("shell", &shell, 1)) >= 0)
	ldd #1
	std 2,sp
	ldd #_shell
	std 0,sp
	ldd #L31
	jsr _create_task
	std -34,x
	std -21,x
	ldd -34,x
	blt L29
; 	 	set_task_state(id, PENDING);
	ldd #1
	std 0,sp
	ldd -21,x
	clra
	jsr _set_task_state
	bra L30
L29:
; 	 else {
; 		if (KERNEL_ERROR_MSGS)
; 			printf("%s %s\n", error_src[0], error_msg[8]);
	ldd #_error_msg+200
	std 2,sp
	ldd #_error_src
	std 0,sp
	ldd #L24
	jsr _printf
L32:
; 	      }
L30:
; 	#ifdef KDB_TRACE_LEVEL_1
; 		if (kdb_trace) puts("kDB1-2");	 
	tst _kdb_trace
	beq L35
	ldd #L37
	jsr _puts
L35:
; 	 #endif
; 
; 		
; 		
; 	 // create sysTime
; 	 if ((id = create_task("sysTime", &sysTime, 5)) >= 0)
	ldd #5
	std 2,sp
	ldd #_sysTime
	std 0,sp
	ldd #L40
	jsr _create_task
	std -36,x
	std -21,x
	ldd -36,x
	blt L38
; 	 	set_task_state(id, STOPPED);
	ldd #4
	std 0,sp
	ldd -21,x
	clra
	jsr _set_task_state
	bra L39
L38:
; 	 else {
; 		if (KERNEL_ERROR_MSGS)
; 			printf("%s %s\n", error_src[0], error_msg[8]);
	ldd #_error_msg+200
	std 2,sp
	ldd #_error_src
	std 0,sp
	ldd #L24
	jsr _printf
L41:
; 	      }
L39:
; 	#ifdef KDB_TRACE_LEVEL_1
; 		if (kdb_trace) puts("kDB1-3");	 
	tst _kdb_trace
	beq L44
	ldd #L46
	jsr _puts
L44:
; 	 #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 #L47
	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.5.2\n\n");
	ldd #L48
	jsr _puts
	lbra L50
L49:
; 
; 	 
; 
; 	 
; 	 // 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 L52
	ldd #L54
	jsr _puts
L52:
; 		#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) {
	ldab -16,x
	cmpb #4
	bne L55
; 		   COP_PET(0x55);
	ldab #85
	stab 0x17
; 		   COP_PET(0xAA);
	ldab #170
	stab 0x17
; 		   cop_cycle = 0;
	clr -16,x
; 		   }
	bra L56
L55:
; 		else
; 			cop_cycle++;
	ldab -16,x
	clra
	addd #1
	stab -16,x
L56:
; 		#ifdef KDB_TRACE_LEVEL_1
; 			if (kdb_trace) puts("kDB2.2-1");	 
	tst _kdb_trace
	beq L57
	ldd #L59
	jsr _puts
L57:
	ldd #0
	std -10,x
	bra L63
L60:
; 		#endif
; 		
; 		
; 		
; 		
; 		// CHANGE STATES ACCORDING TO MESSAGES
; 		// 'waiting' needs to have highest precedence here
; 		for (i=0; i<NUMTASKS; i++) {
; 			if (task[i]->message && STATE_FLAG) {  
	ldd -10,x
	lsld
	addd #_task
	xgdy
	ldy 0,y
	tst 20,y
	beq L64
; 			   // 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 -27,x
	ldy -27,x
	ldab 21,y
	ldy -27,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 -29,x
	tfr d,y
	pshy ; spill
	ldy -29,x
	puly ; reload
	bclr 0,y,#0x1
; 			   #ifdef KDB_TRACE_LEVEL_2
; 				if (kdb_trace) puts("kDB2.3-2a");	 
	tst _kdb_trace
	beq L66
	ldd #L68
	jsr _puts
L66:
; 			   #endif
; 			   }
L64:
; 			#ifdef KDB_TRACE_LEVEL_2
; 				if (kdb_trace) puts("kDB2.3-2b");	 
	tst _kdb_trace
	beq L69
	ldd #L71
	jsr _puts
L69:
L61:
	ldd -10,x
	addd #1
	std -10,x
L63:
	ldd -10,x
	cpd #8
	blo L60
; 			#endif
; 			}
; 		#ifdef KDB_TRACE_LEVEL_1
; 			if (kdb_trace) puts("kDB2.3-1");	 
	tst _kdb_trace
	beq L72
	ldd #L74
	jsr _puts
L72:
	ldd #0
	std -10,x
	lbra L78
L75:
; 		#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<NUMTASKS; i++) {
; 			if (task[i]->state == IDLE) {
	ldd -10,x
	lsld
	addd #_task
	xgdy
	ldy 0,y
	tst 12,y
	bne L79
; 			   deadline = task[i]->period_tick + (task[i]->priority + 1);
	ldd -10,x
	lsld
	addd #_task
	xgdy
	ldy 0,y
	sty -27,x
	ldy -27,x
	ldab 13,y
	clra
	addd #1
	jsr __d2lreg2
	ldy -27,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 L81
; 			   	  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");	 
	tst _kdb_trace
	beq L83
	ldd #L85
	jsr _puts
L83:
; 				  #endif
; 			   	  } 	
L81:
; 				}
L79:
L76:
	ldd -10,x
	addd #1
	std -10,x
L78:
	ldd -10,x
	cpd #8
	lblo L75
; 			 // if (task[i]->message) {} 		
; 			 }
; 		#ifdef KDB_TRACE_LEVEL_1
; 			if (kdb_trace) puts("kDB2.4-1");	 
	tst _kdb_trace
	beq L86
	ldd #L88
	jsr _puts
L86:
; 		#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 L92
L89:
; 		
; 		for (i=0; i<NUMTASKS; i++) {
; 			if (!(task[i] == NULL)) {
	ldd -10,x
	lsld
	addd #_task
	xgdy
	ldd 0,y
	beq L93
	ldd -10,x
	lsld
	addd #_task
	xgdy
	ldy 0,y
	ldab 12,y
	clra
	std -27,x
	cpd #1
	beq L97
	ldd -27,x
	cpd #2
	bne L95
L97:
; 			   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 L98
; 				  	 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");	 
	tst _kdb_trace
	beq L100
	ldd #L102
	jsr _puts
L100:
; 				  	 #endif 
; 			   	 	 }
L98:
; 			   	   }
L95:
; 				}
L93:
L90:
	ldd -10,x
	addd #1
	std -10,x
L92:
	ldd -10,x
	cpd #8
	blo L89
; 			 }
; 		#ifdef KDB_TRACE_LEVEL_1
; 			if (kdb_trace) puts("kDB2.5-1");	 
	tst _kdb_trace
	beq L103
	ldd #L105
	jsr _puts
L103:
; 		#endif
; 		
; 		
; 		
; 		// DISPATCH, or otherwise deal with the current task
; 			// KDB_TRACE Section 3
; 
; 		#ifdef KDB_TRACE_LEVEL_2
; 		if (kdb_trace) {
	tst _kdb_trace
	beq L106
; 			printf("task[%d]->state = %d\n", current, task[current]->state);
	ldd _current
	lsld
	addd #_task
	xgdy
	ldy 0,y
	ldab 12,y
	clra
	std 2,sp
	movw _current,0,sp
	ldd #L108
	jsr _printf
; 			printf("task[%d]->prior = %d\n", current, task[current]->priority);
	ldd _current
	lsld
	addd #_task
	xgdy
	ldy 0,y
	ldab 13,y
	clra
	std 2,sp
	movw _current,0,sp
	ldd #L109
	jsr _printf
; 			}
L106:
	ldd _current
	lsld
	addd #_task
	xgdy
	ldy 0,y
	ldab 12,y
	clra
	std -27,x
	beq L113
	ldd -27,x
	cpd #1
	beq L117
	ldd -27,x
	cpd #2
	lbeq L128
	ldd -27,x
	cpd #3
	lbeq L138
	ldd -27,x
	cpd #4
	lbeq L142
	lbra L110
X0:
; 		#endif
; 		
; 		switch (task[current]->state) {
L113:
; 			   case IDLE:			   // skip task
; 					#ifdef KDB_TRACE_LEVEL_1
; 						if (kdb_trace) puts("kDB3.1-1");
	tst _kdb_trace
	lbeq L111
	ldd #L116
	jsr _puts
; 					#endif
; 					break;
	lbra L111
L117:
; 			   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 L118
	ldd #L120
	jsr _puts
L118:
; 					#endif
; 					#ifdef KDB_TRACE_LEVEL_2
; 						if (kdb_trace) {
	tst _kdb_trace
	beq L121
; 							//puts("kDB3.2-2");
; 							putchar('S');
	ldd #83
	jsr _putchar
; 							putchar(current+48);
	ldd _current
	addd #48
	clra
	jsr _putchar
; 							putchar('\n');
	ldd #10
	jsr _putchar
; 						    }
L121:
; 					#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
	beq L123
	ldd #L125
	jsr _puts
L123:
; 					#endif
; 					#ifdef KDB_TRACE_LEVEL_2
; 						if (kdb_trace) {
	tst _kdb_trace
	lbeq L111
; 							//puts("kDB3.3-2");
; 							putchar('S');
	ldd #83
	jsr _putchar
; 							putchar(current+48);
	ldd _current
	addd #48
	clra
	jsr _putchar
; 							putchar('\n');
	ldd #10
	jsr _putchar
; 						    }
; 					#endif  				
; 			   		break;
	lbra L111
L128:
; 			   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 L129
	ldd #L131
	jsr _puts
L129:
; 					#endif
; 					#ifdef KDB_TRACE_LEVEL_2
; 						if (kdb_trace) {
	tst _kdb_trace
	beq L132
; 							//puts("kDB3.4-2");
; 							putchar('R');
	ldd #82
	jsr _putchar
; 							putchar(current+48);
	ldd _current
	addd #48
	clra
	jsr _putchar
; 							putchar('\n');
	ldd #10
	jsr _putchar
; 						    }
L132:
; 					#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 -19,x
	ldd #0
	std -10,x
	bra L137
L134:
	ldd -10,x
	addd -19,x
	xgdy
	ldab 0,y
	stab -17,x
	ldd _main_frame_ptr
	subd -15,x
	std -38,x
	ldd -10,x
	addd -38,x
	xgdy
	ldab -17,x
	stab 0,y
L135:
	ldd -10,x
	addd #1
	std -10,x
L137:
; 			   		for (i=0; i<temp_heap_size; i++) {
	ldd -10,x
	cpd -15,x
	blo L134
; 						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 L111
L138:
; 			   case WAITING:   		   // waiting on a resource
; 					#ifdef KDB_TRACE_LEVEL_1
; 						if (kdb_trace) puts("kDB3.5-1");
	tst _kdb_trace
	beq L111
	ldd #L141
	jsr _puts
; 					#endif
; 			   		break;
	bra L111
L142:
; 			   case STOPPED:		   // done running until later
; 					#ifdef KDB_TRACE_LEVEL_1
; 						if (kdb_trace) puts("kDB3.6-1");
	tst _kdb_trace
	beq L111
	ldd #L145
	jsr _puts
; 					#endif
; 			   		break;
	bra L111
L110:
; 			   default:	  			   // shouldn't happen, but, error if so.
; 			   		puts("KERNEL: task state error\n");
	ldd #L146
	jsr _puts
; 			   		exit(1);
	ldd #1
	jsr _exit
; 				}	// end switch
L111:
L50:
	lbra L49
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 KBD_TRACE_LEVEL_1
; 	  	if (kbd_trace) putchar('.');
; 	 #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
; 	 
; 	 // reallocate heap memory
; 	 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 L148
; 		#ifdef KERNEL_ERROR_MSGS
; 	 		puts("out of heap space!");
	ldd #L150
	jsr _puts
; 		#endif
; 		exit(0);
	ldd #0
	jsr _exit
; 	 	}
L148:
	ldd #0
	std -10,x
	bra L154
L151:
	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
L152:
	ldd -10,x
	addd #1
	std -10,x
L154:
; 	 
; 	 // 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 L151
; 		*(local_thp + i) = *(temp_task_frame_ptr + i);
; 	 	}
; 	 
; 
; 	 
; 	 // update system time base
; 	 system_tick++;
	ldy #_system_tick
	movw 0,y,-4,x
	movw 2,y,-2,x
	ldy #L155
	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
; 	 
; 	 
; 	 
; 	 // 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 $119C");
		JMP $119C

; 	 
; 
; 	 // 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.  */
; 	 	 
; }
L147:
	tfr x,s
	pulx
	.dbline 0 ; func end
	rti
	.area bss
_task_ptr::
	.blkb 16
	.area text
L155:
	.word 0,1
L150:
	.byte 'o,'u,'t,32,'o,'f,32,'h,'e,'a,'p,32,'s,'p,'a,'c
	.byte 'e,33,0
L146:
	.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
L145:
	.byte 'k,'D,'B,51,46,54,45,49,0
L141:
	.byte 'k,'D,'B,51,46,53,45,49,0
L131:
	.byte 'k,'D,'B,51,46,52,45,49,0
L125:
	.byte 'k,'D,'B,51,46,51,45,49,0
L120:
	.byte 'k,'D,'B,51,46,50,45,49,0
L116:
	.byte 'k,'D,'B,51,46,49,45,49,0
L109:
	.byte 't,'a,'s,'k,91,37,'d,93,45,62,'p,'r,'i,'o,'r,32
	.byte 61,32,37,'d,10,0
L108:
	.byte 't,'a,'s,'k,91,37,'d,93,45,62,'s,'t,'a,'t,'e,32
	.byte 61,32,37,'d,10,0
L105:
	.byte 'k,'D,'B,50,46,53,45,49,0
L102:
	.byte 'k,'D,'B,50,46,53,45,50,0
L88:
	.byte 'k,'D,'B,50,46,52,45,49,0
L85:
	.byte 'k,'D,'B,50,46,52,45,50,0
L74:
	.byte 'k,'D,'B,50,46,51,45,49,0
L71:
	.byte 'k,'D,'B,50,46,51,45,50,'b,0
L68:
	.byte 'k,'D,'B,50,46,51,45,50,'a,0
L59:
	.byte 'k,'D,'B,50,46,50,45,49,0
L54:
	.byte 'k,'D,'B,50,46,49,0
L48:
	.byte 'r,'l,'p,'O,'S,32,'v,48,46,53,46,50,10,10,0
L47:
	.word 0,0
L46:
	.byte 'k,'D,'B,49,45,51,0
L40:
	.byte 's,'y,'s,'T,'i,'m,'e,0
L37:
	.byte 'k,'D,'B,49,45,50,0
L31:
	.byte 's,'h,'e,'l,'l,0
L28:
	.byte 'k,'D,'B,49,45,49,0
L24:
	.byte 37,'s,32,37,'s,10,0
L21:
	.byte 's,'y,'s,'I,'n,'i,'t,0
L18:
	.byte 'k,'D,'B,49,45,48,0

