	.module kernel.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
_kdb_trace::
	.blkb 2
	.area idata
	.word 1
	.area data
_kdb_trace_cycle::
	.blkb 2
	.area idata
	.word 0
	.area data
	.area text
_error_msg::
	.byte 'u,'n,'i,'m,'p,'l,'i,'m,'e,'n,'t,'e,'d,32,'f,'u
	.byte 'n,'c,'t,'i,'o,'n,0
	.byte 0,0
	.byte 's,'y,'n,'t,'a,'x,32,'e,'r,'r,'o,'r,0
	.word 0,0,0,0,0
	.byte 0,0
	.byte 'i,'l,'l,'e,'g,'a,'l,32,'t,'a,'s,'k,32,'I,'D,0
	.byte 0,0,0,0,0,0,0,0,0
	.byte 'i,'l,'l,'e,'g,'a,'l,32,'t,'a,'s,'k,32,'s,'t,'a
	.byte 't,'e,0
	.byte 0,0,0,0,0,0
	.byte 'i,'l,'l,'e,'g,'a,'l,32,'t,'a,'s,'k,32,'p,'r,'i
	.byte 'o,'r,'i,'t,'y,0
	.byte 0,0,0
	.byte 'o,'u,'t,32,'o,'f,32,'m,'e,'m,'o,'r,'y,0
	.word 0,0,0,0,0
	.byte 0
	.byte 'i,'l,'l,'e,'g,'a,'l,32,'r,'e,'s,'o,'u,'r,'c,'e
	.byte 32,'I,'D,0
	.byte 0,0,0,0,0
	.byte 'i,'l,'l,'e,'g,'a,'l,32,'r,'e,'s,'o,'u,'r,'c,'e
	.byte 32,'s,'t,'a,'t,'e,0
	.byte 0,0
	.byte 'c,'a,'n,'n,'o,'t,32,'c,'r,'e,'a,'t,'e,32,'t,'a
	.byte 's,'k,0
	.byte 0,0,0,0,0,0
_error_src::
	.byte 'k,'e,'r,'n,'e,'l,32,'e,'r,'r,'o,'r,58,0
	.byte 0,0,0,0
	.byte 'k,'e,'r,'n,'e,'l,46,'c,32,'e,'r,'r,'o,'r,58,0
	.byte 0,0
	.byte 'k,'e,'r,'n,'e,'l,32,'R,'T,'I,32,'e,'r,'r,'o,'r
	.byte 58,0
	.byte 's,'h,'e,'l,'l,32,'e,'r,'r,'o,'r,58,0
	.byte 0,0,0,0,0
	.byte 's,'e,'m,'l,'i,'b,46,'c,32,'e,'r,'r,'o,'r,58,0
	.byte 0,0
;  lreg1 -> -4,x
;  lreg2 -> -8,x
;          ?temp -> -19,x
;          ?temp -> -19,x
;          ?temp -> -19,x
;          ?temp -> -21,x
;          ?temp -> -19,x
;             id -> -17,x
;         result -> -15,x
; priority_check -> -13,x
;       deadline -> -12,x
;              i -> -10,x
_main::
	pshx
	tfr s,x
	leas -22,sp
; /*	RLPOS: RLPotter Operating System
; 
; 		   Version 0.7.1 for the 68HC12D60A microcontroller
; 		   by Ryan Potter
; 		   ryan@rlpotter.com
; 		   
; 		   Compiled with the ImageCraft ICC12 compiler v6.15A
; 		   			- 912D60 Single Chip Mode
; 					- printf option: long
; 	
;    
; 	v0.7.1 April 27, 2003:  
; 		   - implemented the TOF_handler interrupt for use with sysTime.  
; 		   	 brings time resolution from 64 ms to 16 ms.
; 		   - added kernel funct: get_sysTime(), set_sysTime(); shell cmd: time.
; 		   - now tasks are 'int f()', and must return a value to the kernel 
; 		   	 when exiting.  kernel doesn't handle it yet, though.
; 		   - in shell, now names of tasks are shell commands (dynamic).
; 		   - put all kernel initialization code into kernel_init().
; 		   - added kernel funct: remove_task().
; 		   
; 	
; 	v0.7 April 25, 2003: 11174 bytes:
; 		   - combined kernel.c & semlib.c with rlpos.c to make one big kernel.c.
; 		   - changed context switch mechanism to give each task a dedicated
; 		   	 stack, making the kernel context switches >400% faster.
; 		   - added a basic timer task that will eventually keep system time/date.
; 		   
; 	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.
; 		6) chars are one byte
; 		   ints are two bytes
; 		   longs are 4 bytes
; 		7) only 1536 (1.5k) of the 2k ram are available
; 		8) register base is 0x0000
; 		   
; 	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);
; int sysInit(void);
; int shell(void);
; int idleTask(void);
; int sysTime(void);
; int (*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
; 
; 
; unsigned int current;		   	 		    // current task id number
; unsigned long int system_tick;
; unsigned int cop_cycle;
; 
; unsigned long int time_tick;  				// one tick every x microseconds
; 
; 
; // task control block
; typedef struct task_block {
; 	 	int (*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 int stack_size;			// heap allocated for task stack
; 	 	unsigned char *top_of_stack;		// top of task stack in the heap
; 		unsigned char *frame_ptr;			// CCR pointer in idle stack
; 		};
; 
; 
; // resource control block
; typedef 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
; 		};
; 		
; 		
; struct task_block *task[MAXTASKS];
; struct resource_block resource[NUMRESOURCES];
; 
; 
; int kdb_trace = 1;
; int kdb_trace_cycle = 0;
; 			  
; 
; struct time {
; 	   char hours;
; 	   char minutes;
; 	   char seconds;
; 	   int milliseconds;
; 	   };
; 	   
; int exit_status;
; 			  
; 			  
; 
; // global interrupt flags
; //unsigned int interrupt_flags_ADC;
; //unsigned int interrupt_flags_TC;
; 
; 
; 
; 
; // error massages
; const char error_msg[][25] = {"unimplimented function",	// error 0 
; 	 				  	"syntax error",				// error 1 
; 						"illegal task ID",			// error 2 
; 						"illegal task state",		// error 3 
; 						"illegal task priority",	// error 4 
; 						"out of memory",			// error 5 
; 						"illegal resource ID",		// error 6
; 						"illegal resource state",	// error 7
; 						"cannot create task"		// error 8
; 						};
; const char error_src[][18] = {"kernel error:",			// source 0
; 	 				  	"kernel.c error:",			// source 1
; 						"kernel RTI error:",		// source 2
; 						"shell error:",				// source 3
; 						"semlib.c error:"			// source 4
; 						};
; 						
; 						
; 
; 
; 
; main() {
; 
; 	 // LOCAL VARIABLES
; 	 int result, id, i;
; 	 unsigned char priority_check;
; 	 unsigned int deadline;	   	 		
; 
; 	 
; 	 
; 	 // INITIALIZE the kernel
; 	 kernel_init();
	jsr _kernel_init
; 	 
; 	 
;  	 // 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

	lbra L5
L4:
; 	 
; 	 
; 	 
; 	 // MULTITASKING KERNEL: Priority Preemptive, Real Time, multitasking 
; 		// KDB_TRACE Section 2
; 	 while(1) {	 
; 	 	
; 		//-------------------------------
; 		/* REENTRY POINT after either 
; 		   	   1) task finishes, or 
; 		   	   2) RTI
; 		*/
; 		//-------------------------------
; 		
; 		
; 		if (kdb_trace_cycle >= KDB_CYCLES)
	ldd _kdb_trace_cycle
	cpd #4
	blt L7
; 		   kdb_trace = 0;
	ldd #0
	std _kdb_trace
L7:
; 		
; 		#ifdef KDB_TRACE_LEVEL_1
; 			if (kdb_trace) puts("kDB2.1");	 
; 		#endif
; 		   
; 		   		
; 		/* No RTI interrupts allowed inside of main().  Only allowed
; 		   inside of non-critical sections of tasks */ 
; 	 	//INTR_OFF();	
; 		
; 		
; 		// PET THE DOG: cop watchdog reset timer (pet freq = 2x COP freq)
; 		if (cop_cycle == 4) {
	ldd _cop_cycle
	cpd #4
	bne L9
; 		   COP_PET(0x55);
	ldab #85
	stab 0x17
; 		   COP_PET(0xAA);
	ldab #170
	stab 0x17
; 		   cop_cycle = 0;
	ldd #0
	std _cop_cycle
; 		   //putchar(':');
; 		   }
L9:
	ldd #0
	std -10,x
L11:
; 		#ifdef KDB_TRACE_LEVEL_1
; 			if (kdb_trace) puts("kDB2.2-1");	 
; 		#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 L15
; 			   continue;
	bra L12
L15:
; 			if (task[i]->message && STATE_FLAG) {  
	ldd -10,x
	lsld
	addd #_task
	xgdy
	ldy 0,y
	tst 20,y
	beq L17
; 			   // 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 -19,x
	ldy -19,x
	ldab 21,y
	ldy -19,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 -21,x
	tfr d,y
	pshy ; spill
	ldy -21,x
	puly ; reload
	bclr 0,y,#0x1
; 			   #ifdef KDB_TRACE_LEVEL_2
; 				if (kdb_trace) puts("kDB2.3-2a");	 
; 			   #endif
; 			   }
L17:
L12:
	ldd -10,x
	addd #1
	std -10,x
	ldd -10,x
	cpd #8
	blt L11
	ldd #0
	std -10,x
L19:
; 			#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");	 
; 		#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 L23
; 			   deadline = task[i]->period_tick + (task[i]->priority + 1);
	ldd -10,x
	lsld
	addd #_task
	xgdy
	ldy 0,y
	sty -19,x
	ldy -19,x
	ldab 13,y
	clra
	addd #1
	jsr __d2lreg2
	ldy -19,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 L25
; 			   	  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
; 			   	  } 	
L25:
; 				}
L23:
L20:
	ldd -10,x
	addd #1
	std -10,x
	ldd -10,x
	cpd #8
	blt L19
; 			 // if (task[i]->message) {} ???		
; 			 }
; 		#ifdef KDB_TRACE_LEVEL_1
; 			if (kdb_trace) puts("kDB2.4-1");	 
; 		#endif			
; 		
; 		
; 		// set current = to highest priority pending/running task.
; 		priority_check = 255;   	  	  // lowest possible
	ldab #255
	stab -13,x
	ldd #0
	std -10,x
L27:
; 		
; 		for (i=0; i<MAXTASKS; i++) {
; 			if (!(task[i] == NULL)) {
	ldd -10,x
	lsld
	addd #_task
	xgdy
	ldd 0,y
	beq L31
	ldd -10,x
	lsld
	addd #_task
	xgdy
	ldy 0,y
	ldab 12,y
	clra
	std -19,x
	cpd #1
	beq L35
	ldd -19,x
	cpd #2
	bne L33
L35:
; 			   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 L36
; 				  	 current = i;
	ldd -10,x
	std _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 
; 			   	 	 }
L36:
; 			   	   }
L33:
; 				}
L31:
L28:
	ldd -10,x
	addd #1
	std -10,x
	ldd -10,x
	cpd #8
	blt L27
	ldd _current
	lsld
	addd #_task
	xgdy
	ldy 0,y
	ldab 12,y
	clra
	std -19,x
	lbeq L39
	ldd -19,x
	cpd #1
	beq L42
	ldd -19,x
	cpd #2
	lbeq L43
	ldd -19,x
	cpd #3
	lbeq L39
	ldd -19,x
	cpd #4
	lbeq L39
	lbra L38
X0:
; 			 }
; 		#ifdef KDB_TRACE_LEVEL_1
; 			if (kdb_trace) puts("kDB2.5-1");	 
; 		#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) {
; 			   case IDLE:			   // skip task
; 					#ifdef KDB_TRACE_LEVEL_1
; 						if (kdb_trace) puts("kDB3.1-1");
; 					#endif
; 					break;
L42:
; 			   case PENDING:		   // ready and waiting to run
; 					#ifdef KDB_TRACE_LEVEL_1
; 						if (kdb_trace) puts("kDB3.2-1");
; 					#endif
; 					#ifdef KDB_TRACE_LEVEL_2
; 						if (kdb_trace) {
; 							//puts("kDB3.2-2");
; 							putchar('S');
; 							putchar(current+48);
; 							putchar('\n');
; 						    }
; 					#endif  
; 					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
; 					temp_task_frame_ptr = task[current]->top_of_stack;
	ldd _current
	lsld
	addd #_task
	xgdy
	ldy 0,y
	ldy 25,y
	sty _temp_task_frame_ptr
; 					asm("LDS _temp_task_frame_ptr");		// set the SP
		LDS _temp_task_frame_ptr

; 			   		exit_status = (*task_ptr[current])();	// start the task
	ldd _current
	lsld
	addd #_task_ptr
	xgdy
	ldy 0,y
	jsr 0,y
	std _exit_status
; 					asm("LDS _main_frame_ptr");				// reset the SP
		LDS _main_frame_ptr

; 					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");
; 					#endif
; 					#ifdef KDB_TRACE_LEVEL_2
; 						if (kdb_trace) {
; 							//puts("kDB3.3-2");
; 							putchar('F');
; 							putchar(current+48);
; 							putchar('\n');
; 						    }
; 					#endif  				
; 			   		break;
	bra L39
L43:
; 			   case RUNNING:			// interrupted. continue running.
; 					// 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 L39
X1:
; 			   case WAITING:   		   // waiting on a resource
; 					#ifdef KDB_TRACE_LEVEL_1
; 						if (kdb_trace) puts("kDB3.5-1");
; 					#endif
; 			   		break;
; 			   case STOPPED:		   // done running until later
; 					#ifdef KDB_TRACE_LEVEL_1
; 						if (kdb_trace) puts("kDB3.6-1");
; 					#endif
; 			   		break;
L38:
; 			   default:	  			   // shouldn't happen, but, error if so.
; 			   		puts("KERNEL: task state error\n");
	ldd #L46
	jsr _puts
; 			   		exit(1);
	ldd #1
	jsr _exit
; 				}	// end switch
L39:
L5:
	lbra L4
X2:
; 		
; 		
; 		
; 			// exit_status HANDLER
; 			//...
; 			
; 			
; 			
; 	 		}		// end while(1)
; 	 
; 	 return 0;
	ldd #0
L3:
	tfr x,s
	pulx
	.dbline 0 ; func end
	rts
;  lreg1 -> -4,x
;  lreg2 -> -8,x
;      local_thp -> -14,x
;              i -> -12,x
;     frame_size -> -10,x
_RTI_handler::
	pshx
	tfr s,x
	leas -14,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
; 	 RTIFLG = 0x0080;  	// acknowledge/clear the interrupt
	ldab #128
	stab 0x15
; 	 
; 	 
; 	 #ifdef KDB_TRACE_LEVEL_1
; 	  	if (kdb_trace) putchar('.');
; 	 #endif
; 	 //putchar('.');
; 	 
; 	 
; 	 // 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
; 	 
; 
; 	 
; 	 // update system time base and cop reset counter
; 	 system_tick++;
	ldy #_system_tick
	movw 0,y,-4,x
	movw 2,y,-2,x
	ldy #L48
	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
;  	 if (time_tick > TIME_TICKS_PER_DAY) {
	ldy #_time_tick
	movw 0,y,-4,x
	movw 2,y,-2,x
	ldy #L51
	movw 0,y,-8,x
	movw 2,y,-6,x
	jsr __lcmp
	bls L49
; 	 	time_tick = 0;
	ldy #L52
	movw 0,y,-4,x
	movw 2,y,-2,x
	ldy #_time_tick
	movw -4,x,0,y
	movw -2,x,2,y
; 		}
L49:
; 	 
; 	 
; 	 
; 	 // 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 $117C");
		JMP $117C

; 	 	 
; }
L47:
	tfr x,s
	pulx
	.dbline 0 ; func end
	rti
;  lreg1 -> -4,x
;  lreg2 -> -8,x
;              i -> -10,x
_kernel_init::
	pshx
	tfr s,x
	leas -18,sp
; 
; 
; 
; 
; void kernel_init(void) {
	ldd #0
	std -10,x
L54:
	ldd #12
	ldy -10,x
	emuls
	addd #_resource
	xgdy
	ldd -10,x
	stab 0,y
	ldd #12
	ldy -10,x
	emuls
	addd #_resource+6
	xgdy
	clr 0,y
	ldd #12
	ldy -10,x
	emuls
	addd #_resource+7
	xgdy
	ldab #255
	stab 0,y
	ldd #12
	ldy -10,x
	emuls
	addd #_resource+11
	xgdy
	clr 0,y
L55:
; 
; 	 // LOCAL VARIABLES
; 	 extern int _bss_end, _textmode;
; 	 int i;
; 	 
; 	 
; 	 	
; 	 // START/INITIALIZE the os
; 		// KDB_TRACE Section 1
; 	 
; 	 // initialize the rcb pointer block
; 	 for (i=0; i<NUMRESOURCES; i++) {
	ldd -10,x
	addd #1
	std -10,x
	ldd -10,x
	cpd #4
	blt L54
; 	 	 resource[i].id = i;
; 		 resource[i].state = NOTBUSY;
; 		 resource[i].owner = 255;
; 		 resource[i].queue_ptr = 0;
; 		 }
; 	
; 	
; 	 // initialize globals	
; 	 _textmode = 1;	 	  // maps '\n' to "CR/LF" for Windows terminals
	ldd #1
	std __textmode
; 		 
; 		 
; 	 // create and initialize the heap (for dynamic (runtime) var allocation)
; 	 _NewHeap(&_bss_end, (char *)(&_bss_end) + (INITIAL_HEAP_SIZE));
	ldd #__bss_end+1274
	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");	 
; 	 #endif
; 
; 		
; 	 // create the shell
; 	 if (create_task("shell", &shell, 1, PENDING, DEFAULT_SHELL_STACK_SIZE) < 0)
	ldd #350
	std 6,sp
	ldd #1
	std 4,sp
	ldd #1
	std 2,sp
	ldd #_shell
	std 0,sp
	ldd #L64
	jsr _create_task
	cpd #0
	bge L62
; 	 	puts("shell failure");
	ldd #L65
	jsr _puts
L62:
; 	 #ifdef KDB_TRACE_LEVEL_1
; 		if (kdb_trace) puts("kDB1-2");	 
; 	 #endif
; 	 
; 	 
; 	 /*if (create_task("idleTask", &idleTask, 255, PENDING, 32) < 0)
; 	 	puts("idleTask failure");
; 	 #ifdef KDB_TRACE_LEVEL_1
; 		if (kdb_trace) puts("kDB1-2");	 
; 	 #endif */
; 	 
; 	 
; 	 // create the sysInit task
; 	 if (create_task("sysInit", &sysInit, 0, PENDING, 0) < 0)
	ldd #0
	std 6,sp
	ldd #1
	std 4,sp
	ldd #0
	std 2,sp
	ldd #_sysInit
	std 0,sp
	ldd #L68
	jsr _create_task
	cpd #0
	bge L66
; 	 	puts("sysInit failure");
	ldd #L69
	jsr _puts
L66:
; 	 #ifdef KDB_TRACE_LEVEL_1
; 		if (kdb_trace) puts("kDB1-1");	 
; 	 #endif
; 	 
; 	 
; 	 // print the opening comments
; 	 puts("rlpOS v0.7.1\n\n");
	ldd #L70
	jsr _puts
; 	 
; 	 
; 	 system_tick = 0;
	ldy #L52
	movw 0,y,-4,x
	movw 2,y,-2,x
	ldy #_system_tick
	movw -4,x,0,y
	movw -2,x,2,y
; 	 current = 0;
	ldd #0
	std _current
; 	 cop_cycle = 0;
	ldd #0
	std _cop_cycle
; 	 COP_PET(0x55);
	ldab #85
	stab 0x17
; 	 COP_PET(0xAA);
	ldab #170
	stab 0x17
; 
; }
L53:
	tfr x,s
	pulx
	.dbline 0 ; func end
	rts
;             id -> 3,x
_if_task_exists::
	pshd
	pshx
	tfr s,x
; 
; 
; 
; // KERNEL FUNCTIONS
; 
; int if_task_exists(unsigned char id) {
; 
; 	if (task[id] == NULL)
	ldab 3,x
	clra
	lsld
	addd #_task
	xgdy
	ldd 0,y
	bne L72
; 	   return -1;
	ldd #-1
	bra L71
L72:
; 	else
; 	   return task[id]->id;
	ldab 3,x
	clra
	lsld
	addd #_task
	xgdy
	ldy 0,y
	ldab 2,y
	clra
L71:
	tfr x,s
	pulx
	leas 2,sp
	.dbline 0 ; func end
	rts
;             id -> 3,x
_get_task_address::
	pshd
	pshx
	tfr s,x
; 
; }
; 
; 
; 
; 
; int get_task_address(unsigned char id) {
; 
; 	return (int)task[id]->address;
	ldab 3,x
	clra
	lsld
	addd #_task
	xgdy
	ldd [0,y]
L74:
	tfr x,s
	pulx
	leas 2,sp
	.dbline 0 ; func end
	rts
_get_task_id::
; 
; }
; 
; 
; 
; 
; char get_task_id() { 
; 	 
; 	 return task[current]->id;
	ldd _current
	lsld
	addd #_task
	xgdy
	ldy 0,y
	ldab 2,y
	clra
L75:
	.dbline 0 ; func end
	rts
;             id -> 3,x
_get_task_name::
	pshd
	pshx
	tfr s,x
; }
; 
; 
; 
; char *get_task_name(unsigned char id) {
; 	 if (task[id] == NULL)
	ldab 3,x
	clra
	lsld
	addd #_task
	xgdy
	ldd 0,y
	bne L77
; 	 	return NULL;
	ldd #0
	bra L76
L77:
; 	 else
; 	 	return task[id]->name; 
	ldab 3,x
	clra
	lsld
	addd #_task
	xgdy
	ldd 0,y
	addd #3
L76:
	tfr x,s
	pulx
	leas 2,sp
	.dbline 0 ; func end
	rts
;             id -> 3,x
_get_task_state::
	pshd
	pshx
	tfr s,x
; }
; 
; 
; 
; 
; int get_task_state(unsigned char id) { 
; 
; 	if (task[id] == NULL)
	ldab 3,x
	clra
	lsld
	addd #_task
	xgdy
	ldd 0,y
	bne L80
; 	   return -1;
	ldd #-1
	bra L79
L80:
; 	else if (id < MAXTASKS)
	ldab 3,x
	cmpb #8
	bhs L82
; 	 	return task[id]->state;
	ldab 3,x
	clra
	lsld
	addd #_task
	xgdy
	ldy 0,y
	ldab 12,y
	clra
	bra L79
L82:
; 	else {
; 	 	  #ifdef KERNEL_ERROR_MSG
; 	 	  puts(error_src[1]); puts(error_msg[3]);
; 		  #endif
; 		  return -1;
	ldd #-1
L79:
	tfr x,s
	pulx
	leas 2,sp
	.dbline 0 ; func end
	rts
;             id -> 3,x
_get_task_messages::
	pshd
	pshx
	tfr s,x
; 		  }
; 		  
; }
; 
; 
; 
; int get_task_messages(unsigned char id) {
; 
; 	if (task[id] == NULL)
	ldab 3,x
	clra
	lsld
	addd #_task
	xgdy
	ldd 0,y
	bne L85
; 	   return -1;
	ldd #-1
	bra L84
L85:
; 	else if (id < MAXTASKS)
	ldab 3,x
	cmpb #8
	bhs L87
; 	   return task[id]->message;
	ldab 3,x
	clra
	lsld
	addd #_task
	xgdy
	ldy 0,y
	ldab 20,y
	clra
	bra L84
L87:
; 	else {
; 		 #ifdef KERNEL_ERROR_MSG
; 	 	 puts(error_src[1]); puts(error_msg[3]);
; 		 #endif
; 		 return -1;
	ldd #-1
L84:
	tfr x,s
	pulx
	leas 2,sp
	.dbline 0 ; func end
	rts
;             id -> 3,x
_get_task_priority::
	pshd
	pshx
	tfr s,x
; 		 }
; 
; }
; 
; 
; 
; int get_task_priority(unsigned char id) { 
; 
; 		 INTR_OFF();
		sei

; 		 
; 		 if (id < MAXTASKS) {
	ldab 3,x
	cmpb #8
	bhs L90
; 		 	INTR_ON();
		cli

; 		 	return task[id]->priority;
	ldab 3,x
	clra
	lsld
	addd #_task
	xgdy
	ldy 0,y
	ldab 13,y
	clra
	bra L89
L90:
; 			}
; 		 else {
; 	 	 	#ifdef KERNEL_ERROR_MSG
; 	 	 	puts(error_src[1]); puts(error_msg[4]);
; 			#endif
; 			INTR_ON();
		cli

; 			return -1;
	ldd #-1
L89:
	tfr x,s
	pulx
	leas 2,sp
	.dbline 0 ; func end
	rts
;          ?temp -> -4,x
;          ?temp -> -4,x
;          ?temp -> -4,x
;          ?temp -> -4,x
;          ?temp -> -4,x
;          ?temp -> -2,x
;       newstate -> 7,x
;             id -> 3,x
_set_task_state::
	pshd
	pshx
	tfr s,x
	leas -4,sp
; 		 	}
; 
; }
; 
; 
; 
; int set_task_state(unsigned char id, unsigned char newstate) {
; 	
; 	
; 	INTR_OFF();
		sei

; 	
; 	
; 	// check id validity
; 	if (id < MAXTASKS) {
	ldab 3,x
	cmpb #8
	lbhs L93
; 
; 	   if (task[id] == NULL) {
	ldab 3,x
	clra
	lsld
	addd #_task
	xgdy
	ldd 0,y
	bne L95
; 	   	  #ifdef KERNEL_ERROR_MSG
; 	 	  puts(error_src[1]); puts(error_msg[2]);
; 		  #endif
; 		  INTR_ON();
		cli

; 	 	  return -1;
	ldd #-1
	lbra L92
L95:
; 	   	  }
; 		  
; 		  
; 	   // check newstate validity
; 	   if ((newstate == RUNNING) || 
	ldab 7,x
	cmpb #2
	beq L100
	ldab 7,x
	cmpb #3
	beq L100
	ldab 7,x
	cmpb #4
	bls L97
L100:
; 	   	  (newstate == WAITING)  ||
; 	   	  (newstate > STOPPED)) { 
; 	      		 #ifdef KERNEL_ERROR_MSG
; 	 	 	  	 puts(error_src[1]); puts(error_msg[3]);
; 			  	 #endif
; 				 INTR_ON();
		cli

; 	 	  		 return -1;
	ldd #-1
	lbra L92
L97:
	ldab 3,x
	clra
	lsld
	addd #_task
	xgdy
	ldy 0,y
	ldab 12,y
	clra
	std -2,x
	beq L104
	ldd -2,x
	cpd #1
	lbeq L111
	ldd -2,x
	cpd #2
	lbeq L118
	ldd -2,x
	cpd #4
	lbeq L121
	lbra L101
X3:
; 	   			 }
; 	 
; 	 		// referenced to the task's current state:
; 	   		switch (task[id]->state) {
L104:
; 		   	  	   case IDLE:
; 				   		if (newstate == IDLE) {	   // no change
	tst 7,x
	bne L105
; 						   INTR_ON();
		cli

; 				 		   return 0;
	ldd #0
	lbra L92
L105:
; 						   }
; 				 		else if (newstate == PENDING) {
	ldab 7,x
	cmpb #1
	bne L107
; 				 		   // pass msg to task[id]->msgbox;
; 						   task[id]->message |= STATE_FLAG;
	ldab 3,x
	clra
	lsld
	addd #_task
	xgdy
	ldd 0,y
	addd #20
	std -4,x
	tfr d,y
	pshy ; spill
	ldy -4,x
	puly ; reload
	bset 0,y,#1
; 		  				   task[id]->message_data[STATE_BOX] = PENDING;
	ldab 3,x
	clra
	lsld
	addd #_task
	xgdy
	ldy 0,y
	ldab #1
	stab 21,y
; 						   INTR_ON();
		cli

; 					  	   return 0;
	ldd #0
	lbra L92
L107:
; 				 		   }
; 						else if (newstate == STOPPED) {
	ldab 7,x
	cmpb #4
	bne L109
; 							// pass msg to task[id]->msgbox;
; 						    task[id]->message |= STATE_FLAG;
	ldab 3,x
	clra
	lsld
	addd #_task
	xgdy
	ldd 0,y
	addd #20
	std -4,x
	tfr d,y
	pshy ; spill
	ldy -4,x
	puly ; reload
	bset 0,y,#1
; 		  					task[id]->message_data[STATE_BOX] = STOPPED;
	ldab 3,x
	clra
	lsld
	addd #_task
	xgdy
	ldy 0,y
	ldab #4
	stab 21,y
; 							INTR_ON();
		cli

; 					  		return 0; 
	ldd #0
	lbra L92
L109:
; 						    }
; 				 		else {	  // nothing else is legal;
; 						   	 #ifdef KERNEL_ERROR_MSG
; 	 	 	  			   	 puts(error_src[1]); puts(error_msg[3]);
; 			  			   	 #endif
; 							 INTR_ON();
		cli

; 					  		 return -1;
	ldd #-1
	lbra L92
X4:
; 				 			 }
; 				 		break;
L111:
; 		   			case PENDING:
; 						 if (newstate == PENDING) {	// no change
	ldab 7,x
	cmpb #1
	bne L112
; 						 	INTR_ON();
		cli

; 				 		 	return 0;
	ldd #0
	lbra L92
L112:
; 							}
; 						 else if (newstate == IDLE) {
	tst 7,x
	bne L114
; 				   		 	  // pass msg to task[id]->msgbox;
; 						   	  #ifdef KERNEL_ERROR_MSG
; 	 	 	  			   	  puts(error_src[1]); puts(error_msg[0]);
; 			  			   	  #endif
; 							  INTR_ON();
		cli

; 					  		  return -1;
	ldd #-1
	lbra L92
L114:
; 							  }
; 						 else if (newstate == STOPPED) {
	ldab 7,x
	cmpb #4
	bne L116
; 				   		 	  	 // pass msg to task[id]->msgbox;
; 							  	 task[id]->message |= STATE_FLAG;
	ldab 3,x
	clra
	lsld
	addd #_task
	xgdy
	ldd 0,y
	addd #20
	std -4,x
	tfr d,y
	pshy ; spill
	ldy -4,x
	puly ; reload
	bset 0,y,#1
; 		  					  	 task[id]->message_data[STATE_BOX] = STOPPED;
	ldab 3,x
	clra
	lsld
	addd #_task
	xgdy
	ldy 0,y
	ldab #4
	stab 21,y
; 							  	 INTR_ON();
		cli

; 					  		  	 return 0;
	ldd #0
	lbra L92
L116:
; 						 	  	 }	
; 						 else {
; 				   		 	  #ifdef KERNEL_ERROR_MSG
; 							  puts(error_src[1]); puts(error_msg[3]);
; 							  #endif
; 							  INTR_ON();
		cli

; 							  return -1;
	ldd #-1
	lbra L92
X5:
; 						 	  }
; 						 break;
L118:
; 					case RUNNING:
; 						 if (newstate == STOPPED) {
	ldab 7,x
	cmpb #4
	bne L119
; 						 	// pass msg to task[id]->msgbox;
; 							task[id]->message |= STATE_FLAG;
	ldab 3,x
	clra
	lsld
	addd #_task
	xgdy
	ldd 0,y
	addd #20
	std -4,x
	tfr d,y
	pshy ; spill
	ldy -4,x
	puly ; reload
	bset 0,y,#1
; 		  					task[id]->message_data[STATE_BOX] = STOPPED;
	ldab 3,x
	clra
	lsld
	addd #_task
	xgdy
	ldy 0,y
	ldab #4
	stab 21,y
; 							
; 							INTR_ON();
		cli

; 					  		return 0;
	ldd #0
	lbra L92
L119:
; 						 	}
; 						 else {
; 				   		 	  #ifdef KERNEL_ERROR_MSG
; 							  puts(error_src[1]); puts(error_msg[3]);
; 							  #endif
; 							  INTR_ON();
		cli

; 							  return -1;
	ldd #-1
	lbra L92
X6:
; 						 	  }
; 						 break;
L121:
; 		   			case STOPPED:
; 		   				 if (newstate == STOPPED)	{ 	// no change
	ldab 7,x
	cmpb #4
	bne L122
; 				   		 	INTR_ON();
		cli

; 							return 0;
	ldd #0
	lbra L92
L122:
; 							}
; 						 else if (newstate == PENDING) {
	ldab 7,x
	cmpb #1
	bne L124
; 				   		 	  // pass msg to task[id]->msgbox;
; 							  task[id]->message |= STATE_FLAG;
	ldab 3,x
	clra
	lsld
	addd #_task
	xgdy
	ldd 0,y
	addd #20
	std -4,x
	tfr d,y
	pshy ; spill
	ldy -4,x
	puly ; reload
	bset 0,y,#1
; 		  					  task[id]->message_data[STATE_BOX] = PENDING;
	ldab 3,x
	clra
	lsld
	addd #_task
	xgdy
	ldy 0,y
	ldab #1
	stab 21,y
; 							  INTR_ON();
		cli

; 					  		  return 0;
	ldd #0
	bra L92
L124:
; 							  }
; 						 else {
; 					 	 	  #ifdef KERNEL_ERROR_MSG
; 							  puts(error_src[1]); puts(error_msg[3]);
; 							  #endif
; 							  INTR_ON();
		cli

; 							  return -1;
	ldd #-1
	bra L92
X7:
; 							  }
; 						 break;
L101:
; 		   			default:
; 		   		   			#ifdef KERNEL_ERROR_MSG
; 							puts(error_src[1]); puts(error_msg[3]);
; 							#endif
; 							INTR_ON();
		cli

; 							return -1;
	ldd #-1
	bra L92
X8:
; 				   			break;
L93:
; 							
; 	 				}	// end switch (task[id]->state)
; 					
; 	 		}		// if (id < MAXTASKS)
; 			
; 		   else {
; 		   		#ifdef KERNEL_ERROR_MSG
; 				puts(error_src[1]); puts(error_msg[2]);
; 				#endif
; 				INTR_ON();
		cli

; 				return -1;
	ldd #-1
	bra L92
X9:
; 				}
; 
; 	 INTR_ON();
		cli

; 	 return 0;
	ldd #0
L92:
	tfr x,s
	pulx
	leas 2,sp
	.dbline 0 ; func end
	rts
;       priority -> 7,x
;             id -> 3,x
_set_task_priority::
	pshd
	pshx
	tfr s,x
; 
; }
; 
; 
; 
; int set_task_priority(unsigned char id, unsigned char priority) {
; 
; 	 if (priority == 0) 			 // priority 0 is reserved for the shell
	tst 7,x
	bne L127
; 	 	priority = 1;
	ldab #1
	stab 7,x
L127:
; 		
; 	 if (id >= (MAXTASKS)) {
	ldab 3,x
	cmpb #8
	blo L129
; 	 	#ifdef KERNEL_ERROR_MSG
; 		puts(error_src[1]); puts(error_msg[4]);
; 		#endif
; 		return -1;
	ldd #-1
	bra L126
L129:
	ldab 7,x
	cmpb #255
	bhi L133
	tst 7,x
	bhs L131
L133:
; 		}
; 	 else if ((priority > 255) || (priority < 0)) {
; 	 	#ifdef KERNEL_ERROR_MSG
; 		puts(error_src[1]); puts(error_msg[4]);
; 		#endif
; 		return -1;
	ldd #-1
	bra L126
L131:
; 		}
; 	 else {
; 	 	 task[id]->priority = priority;
	ldab 3,x
	clra
	lsld
	addd #_task
	xgdy
	ldy 0,y
	ldab 7,x
	stab 13,y
; 		 return 0;
	ldd #0
L126:
	tfr x,s
	pulx
	leas 2,sp
	.dbline 0 ; func end
	rts
;  lreg1 -> -4,x
;  lreg2 -> -8,x
;          ?temp -> -15,x
;          ?temp -> -13,x
;          ?temp -> -11,x
;             id -> -9,x
;     stack_size -> 12,x
;          state -> 10,x
;       priority -> 9,x
;           addr -> 6,x
;           name -> 2,x
_create_task::
	pshd
	pshx
	tfr s,x
	leas -22,sp
; 		 }
; }
; 
; 
; 
; 
; int create_task(char *name, 
; 				int (*addr)(), 
; 				unsigned char priority, 
; 				int state,
; 				int stack_size) {
; 
; 	// LOCAL VARIABLES
; 	unsigned char id;
; 	
; 	
; 	INTR_OFF();	  // critical section	  
		sei

	clr -9,x
	bra L138
L135:
	ldab -9,x
	clra
	lsld
	addd #_task_ptr
	xgdy
	ldd 0,y
	beq L137
L136:
	ldab -9,x
	clra
	addd #1
	stab -9,x
L138:
; 	
; 	
; 	//if (get_free_memory() > 64) {
; 	
; 	// determine lowest free id available to assign to this task
; 	for (id=0; id<MAXTASKS; id++) {
	ldab -9,x
	cmpb #8
	blo L135
L137:
; 		if (task_ptr[id] != NULL)
; 		   continue;
; 		else
; 		   break;
; 		 }
; 
; 	
; 	// create task block
; 	if ((task[id] = malloc(sizeof(struct task_block))) == NULL) {
	ldd #29
	jsr _malloc
	std -18,x
	ldab -9,x
	clra
	lsld
	addd #_task
	xgdy
	ldd -18,x
	std 0,y
	ldd -18,x
	bne L141
; 	   #ifdef KERNEL_ERROR_MSG
; 	   puts(error_src[1]); puts(error_msg[5]);
; 	   #endif
; 	   return -1;
	ldd #-1
	lbra L134
L141:
; 	   }
; 	else { 
; 	 	 // put addr entry into task_ptr[]
; 		 task_ptr[id] = addr;
	ldab -9,x
	clra
	lsld
	addd #_task_ptr
	xgdy
	ldd 6,x
	std 0,y
; 		 
; 		 
; 	 	 // initialize the task structures
; 	 	 task[id]->address = addr;
	ldab -9,x
	clra
	lsld
	addd #_task
	xgdy
	ldy 0,y
	ldd 6,x
	std 0,y
; 		 task[id]->id = id;
	ldab -9,x
	clra
	lsld
	addd #_task
	xgdy
	ldy 0,y
	ldab -9,x
	stab 2,y
; 		 strcpy(task[id]->name, name);
	movw 2,x,0,sp
	ldab -9,x
	clra
	lsld
	addd #_task
	xgdy
	ldd 0,y
	addd #3
	jsr _strcpy
;  		 task[id]->state = state;
	ldab -9,x
	clra
	lsld
	addd #_task
	xgdy
	ldy 0,y
	ldd 10,x
	stab 12,y
; 		 task[id]->priority = priority;
	ldab -9,x
	clra
	lsld
	addd #_task
	xgdy
	ldy 0,y
	ldab 9,x
	stab 13,y
; 		 task[id]->period_tick = 0;
	ldab -9,x
	clra
	lsld
	addd #_task
	xgdy
	ldy 0,y
	leay 14,y
	pshy ; spill
	ldy #L52
	movw 0,y,-4,x
	movw 2,y,-2,x
	puly ; reload
	movw -4,x,0,y
	movw -2,x,2,y
; 		 task[id]->interrupt_msg_box = NULL;
	ldab -9,x
	clra
	lsld
	addd #_task
	xgdy
	ldy 0,y
	ldd #0
	std 18,y
; 		 task[id]->message = NULL;
	ldab -9,x
	clra
	lsld
	addd #_task
	xgdy
	ldy 0,y
	clr 20,y
; 		 task[id]->message_data[0] = NULL;
	ldab -9,x
	clra
	lsld
	addd #_task
	xgdy
	ldy 0,y
	clr 21,y
; 		 task[id]->message_data[1] = NULL;
	ldab -9,x
	clra
	lsld
	addd #_task
	xgdy
	ldy 0,y
	clr 22,y
; 		 if (stack_size <= 0) 
	ldd 12,x
	bgt L143
; 		 	stack_size = DEFAULT_STACK_SIZE; 
	ldd #64
	std 12,x
L143:
; 		 task[id]->stack_size = stack_size;
	ldab -9,x
	clra
	lsld
	addd #_task
	xgdy
	ldy 0,y
	ldd 12,x
	std 23,y
; 		 task[id]->top_of_stack = malloc(task[id]->stack_size); 
	ldab -9,x
	clra
	lsld
	addd #_task
	xgdy
	ldy 0,y
	sty -11,x
	ldy -11,x
	ldd 23,y
	jsr _malloc
	std -20,x
	ldy -11,x
	ldd -20,x
	std 25,y
; 		 task[id]->top_of_stack += task[id]->stack_size;
	ldab -9,x
	clra
	lsld
	addd #_task
	xgdy
	ldy 0,y
	sty -13,x
	ldd -13,x
	addd #25
	std -15,x
	ldy -13,x
	ldd 23,y
	addd [-15,x]
	ldy -15,x
	std 0,y
; 		 task[id]->frame_ptr = NULL;
	ldab -9,x
	clra
	lsld
	addd #_task
	xgdy
	ldy 0,y
	ldd #0
	std 27,y
; 	
; 	}
; 	//}
; 	INTR_ON();
		cli

; 	 
; 	return id;
	ldab -9,x
	clra
L134:
	tfr x,s
	pulx
	leas 2,sp
	.dbline 0 ; func end
	rts
;          ?temp -> -2,x
;             id -> 3,x
_remove_task::
	pshd
	pshx
	tfr s,x
	leas -2,sp
; 	 
; }
; 
; 
; 
; int remove_task(unsigned char id) {
; 
; 	if (task[id] == NULL)
	ldab 3,x
	clra
	lsld
	addd #_task
	xgdy
	ldd 0,y
	bne L146
; 	   return -1;
	ldd #-1
	bra L145
L146:
; 	   
; 
; 	free(task[id]->top_of_stack - task[id]->stack_size);
	ldab 3,x
	clra
	lsld
	addd #_task
	xgdy
	ldy 0,y
	sty -2,x
	ldy -2,x
	ldd 25,y
	ldy -2,x
	subd 23,y
	jsr _free
; 	free(task[id]);
	ldab 3,x
	clra
	lsld
	addd #_task
	xgdy
	ldd 0,y
	jsr _free
; 	task[id] = NULL;
	ldab 3,x
	clra
	lsld
	addd #_task
	xgdy
	ldd #0
	std 0,y
; 	task_ptr[id] = NULL;
	ldab 3,x
	clra
	lsld
	addd #_task_ptr
	xgdy
	ldd #0
	std 0,y
; 	
; 	return 0;
	ldd #0
L145:
	tfr x,s
	pulx
	leas 2,sp
	.dbline 0 ; func end
	rts
;            rid -> 3,x
_get_resource_state::
	pshd
	pshx
	tfr s,x
; 
; }
; 
; 
; 
; int get_resource_state(unsigned char rid) {
; 
; 	if (rid < NUMRESOURCES) {
	ldab 3,x
	cmpb #4
	bhs L149
; 	 	return resource[rid].state;
	ldab 3,x
	clra
	xgdy
	ldd #12
	emuls
	addd #_resource+6
	xgdy
	ldab 0,y
	clra
	bra L148
L149:
; 		}
; 	else {
; 		 #ifdef KERNEL_ERROR_MSG
; 	 	 puts(error_src[1]); puts(error_msg[6]);
; 		 #endif
; 		 return -1;
	ldd #-1
L148:
	tfr x,s
	pulx
	leas 2,sp
	.dbline 0 ; func end
	rts
;            rid -> 3,x
_get_resource_owner::
	pshd
	pshx
	tfr s,x
; 		 }
; 
; }
; 
; 
; 
; 
; 
; int get_resource_owner(unsigned char rid) {
; 
; 	if (rid < NUMRESOURCES) {
	ldab 3,x
	cmpb #4
	bhs L153
; 	 	return resource[rid].owner;
	ldab 3,x
	clra
	xgdy
	ldd #12
	emuls
	addd #_resource+7
	xgdy
	ldab 0,y
	clra
	bra L152
L153:
; 		}
; 	else {
; 		 #ifdef KERNEL_ERROR_MSG
; 	 	 puts(error_src[1]); puts(error_msg[6]);
; 		 #endif
; 		 return -1;
	ldd #-1
L152:
	tfr x,s
	pulx
	leas 2,sp
	.dbline 0 ; func end
	rts
;            rid -> 3,x
_get_resource_queuelen::
	pshd
	pshx
	tfr s,x
; 		 }
; 
; }
; 
; 
; 
; 
; int get_resource_queuelen(unsigned char rid) {
; 
; 	if (rid < NUMRESOURCES) {
	ldab 3,x
	cmpb #4
	bhs L157
; 	 	return resource[rid].queue_ptr;
	ldab 3,x
	clra
	xgdy
	ldd #12
	emuls
	addd #_resource+11
	xgdy
	ldab 0,y
	clra
	bra L156
L157:
; 		}
; 	else {
; 		 #ifdef KERNEL_ERROR_MSG
; 	 	 puts(error_src[1]); puts(error_msg[6]);
; 		 #endif
; 		 return -1;
	ldd #-1
L156:
	tfr x,s
	pulx
	leas 2,sp
	.dbline 0 ; func end
	rts
;           last -> -6,x
;         memory -> -4,x
;              i -> -2,x
_get_free_memory::
	pshx
	tfr s,x
	leas -8,sp
; 		 }
; 
; }
; 
; 
; 
; 
; int get_free_memory(void) {
; 
; 	// LOCAL VARIABLES
; 	char *memory, *last;
; 	int i;
; 	
; 	
; 	INTR_OFF();
		sei

	ldd #0
	std -2,x
L161:
; 	// check for largest free memory block
; 	for (i=0; i<INITIAL_HEAP_SIZE; i+=32) {
; 		if ((memory = malloc(i)) != NULL)
	ldd -2,x
	jsr _malloc
	std -8,x
	std -4,x
	ldd -8,x
	beq L163
; 		   last = memory;
	movw -4,x,-6,x
; 		else
; 		   break;
L166:
	ldd -6,x
	jsr _free
L162:
	ldd -2,x
	addd #32
	std -2,x
	ldd -2,x
	cpd #1274
	blt L161
L163:
; 		free(last);
; 		}
; 		
; 	INTR_ON();
		cli

; 	//printf("%d bytes\n", i);
; 	
; 	return (i-32);
	ldd -2,x
	subd #32
L160:
	tfr x,s
	pulx
	.dbline 0 ; func end
	rts
;          ?temp -> -6,x
;          ?temp -> -4,x
;          ?temp -> -2,x
;            rid -> 3,x
_sem_get::
	pshd
	pshx
	tfr s,x
	leas -8,sp
; 
; }
; 
; 
; 
; 
; int sem_get(char rid) {
; 
; 	 /* Gives a resource to a requesting task.
; 	 	returns the resource id number (0,1,2,...) if free.
; 	 	otherwise returns -1.
; 		
; 		At this point, semaphores are a procedural control
; 		that the tasks have to follow to avoid resource contention.
; 		There is no kernel control over resources yet.  */
; 	 
; 	 
; 	 // critical section
; 	 INTR_OFF();
		sei

; 	 
; 	 
; 	 
; 	 // GET SEMAPHORE
; 	 // give semaphore to task
; 	 if (resource[rid].state == NOTBUSY) {
	ldab 3,x
	clra
	xgdy
	ldd #12
	emuls
	addd #_resource+6
	xgdy
	tst 0,y
	bne L168
; 	 	resource[rid].state = BUSY;
	ldab 3,x
	clra
	xgdy
	ldd #12
	emuls
	addd #_resource+6
	xgdy
	ldab #1
	stab 0,y
; 		resource[rid].owner = current;
	ldab 3,x
	clra
	xgdy
	ldd #12
	emuls
	addd #_resource+7
	xgdy
	ldd _current
	stab 0,y
; 		
; 		INTR_ON();
		cli

; 		return rid;
	ldab 3,x
	clra
	lbra L167
L168:
; 	 	}
; 	 
; 	 // resource is taken/busy so make task wait
; 	 else {
; 		  task[current]->message |= STATE_FLAG;
	ldd _current
	lsld
	addd #_task
	xgdy
	ldd 0,y
	addd #20
	std -2,x
	tfr d,y
	pshy ; spill
	ldy -2,x
	puly ; reload
	bset 0,y,#1
; 		  task[current]->message_data[STATE_BOX] = WAITING;
	ldd _current
	lsld
	addd #_task
	xgdy
	ldy 0,y
	ldab #3
	stab 21,y
; 		
; 		  // put waiting task into the resources queue if there's space
; 		  if (resource[rid].queue_ptr < 3) {
	ldab 3,x
	clra
	xgdy
	ldd #12
	emuls
	addd #_resource+11
	xgdy
	ldab 0,y
	cmpb #3
	bhs L173
; 		   	 resource[rid].queue[resource[rid].queue_ptr] = current;
	ldab 3,x
	clra
	xgdy
	ldd #12
	emuls
	std -4,x
	addd #_resource+11
	xgdy
	ldab 0,y
	clra
	pshd ; spill
	ldd -4,x
	addd #_resource+8
	std -8,x
	puld ; reload
	addd -8,x
	xgdy
	ldab _current+1
	stab 0,y
; 		   	 resource[rid].queue_ptr++;
	ldab 3,x
	clra
	xgdy
	ldd #12
	emuls
	addd #_resource+11
	std -6,x
	tfr d,y
	ldab 0,y
	clra
	addd #1
	ldy -6,x
	stab 0,y
; 		   	 }
L173:
; 		
; 		  INTR_ON();
		cli

; 		  return -1;
	ldd #-1
L167:
	tfr x,s
	pulx
	leas 2,sp
	.dbline 0 ; func end
	rts
;            rid -> 3,x
_sem_give::
	pshd
	pshx
	tfr s,x
; 	 	  } 	 
; 		
; }
; 
; 
; 
; 
; int sem_give(char rid) {
; 
; 	/* Takes a resource back from a task.
; 	   will (eventually) pass a message to a waiting task.  
; 	   
; 	   	At this point, semaphores are a procedural control
; 		that the tasks have to follow to avoid resource contention.
; 		There is no kernel control over resources yet.  */
; 	
; 	
; 	// critical section
; 	INTR_OFF();
		sei

; 	
; 	
; 	// return the resource
; 	resource[rid].state = NOTBUSY;
	ldab 3,x
	clra
	xgdy
	ldd #12
	emuls
	addd #_resource+6
	xgdy
	clr 0,y
; 	//resource[rid].owner = NULL;
; 	
; 	INTR_ON();
		cli

; 	
; 	return 0;
	ldd #0
L179:
	tfr x,s
	pulx
	leas 2,sp
	.dbline 0 ; func end
	rts
;  lreg1 -> -4,x
;  lreg2 -> -8,x
;           slop -> -12,x
_get_sysTime::
	pshx
	tfr s,x
	leas -12,sp
; 	  
; }
; 
; 
; 
; unsigned long int get_sysTime(void) { 
; 			
; 	   // LOCAL VARIABLES
; 	   unsigned long int slop;
; 	   
; 	     
; 	   // returns the number of milliseconds since midnight (time_tick=0);
; 	   slop = time_tick / 40;
	ldy #_time_tick
	movw 0,y,-4,x
	movw 2,y,-2,x
	ldy #L182
	movw 0,y,-8,x
	movw 2,y,-6,x
	jsr __ludiv
	leay -12,x
	movw -4,x,0,y
	movw -2,x,2,y
; 	   return (time_tick * ms_PER_TIME_TICK + slop);
	ldy #L183
	movw 0,y,-4,x
	movw 2,y,-2,x
	ldy #_time_tick
	movw 0,y,-8,x
	movw 2,y,-6,x
	jsr __lmul
	leay -12,x
	movw 0,y,-8,x
	movw 2,y,-6,x
	jsr __ladd
	jsr __lret
L181:
	tfr x,s
	pulx
	.dbline 0 ; func end
	rts
;  lreg1 -> -4,x
;  lreg2 -> -8,x
;        seconds -> 8,x
;        minutes -> 6,x
;          hours -> 2,x
_set_sysTime::
	pshd
	pshx
	tfr s,x
	leas -10,sp
; 	   
; }
; 
; 
; 
; void set_sysTime(unsigned int hours, unsigned int minutes, unsigned int seconds) {
; 
; 	 // LOCAL VARIABLES
; 	 extern unsigned long int time_tick;
; 	 
; 	 
; 	 time_tick = ((hours*3600)+(minutes*60)+(seconds)) * TIME_TICKS_PER_SECOND;
	ldd #60
	ldy 6,x
	emul
	std -10,x
	ldd #3600
	ldy 2,x
	emul
	addd -10,x
	addd 8,x
	std -6,x
	movw #0,-8,x
	ldy #L185
	movw 0,y,-4,x
	movw 2,y,-2,x
	jsr __lmul
	ldy #_time_tick
	movw -4,x,0,y
	movw -2,x,2,y
; 
; }
L184:
	tfr x,s
	pulx
	leas 2,sp
	.dbline 0 ; func end
	rts
	.area bss
_exit_status::
	.blkb 2
_resource::
	.blkb 48
_task::
	.blkb 16
_time_tick::
	.blkb 4
_cop_cycle::
	.blkb 2
_system_tick::
	.blkb 4
_current::
	.blkb 2
_task_ptr::
	.blkb 16
	.area text
L185:
	.word 0,61
L183:
	.word 0,16
L182:
	.word 0,40
L70:
	.byte 'r,'l,'p,'O,'S,32,'v,48,46,55,46,49,10,10,0
L69:
	.byte 's,'y,'s,'I,'n,'i,'t,32,'f,'a,'i,'l,'u,'r,'e,0
L68:
	.byte 's,'y,'s,'I,'n,'i,'t,0
L65:
	.byte 's,'h,'e,'l,'l,32,'f,'a,'i,'l,'u,'r,'e,0
L64:
	.byte 's,'h,'e,'l,'l,0
L52:
	.word 0,0
L51:
	.word 80,27520
L48:
	.word 0,1
L46:
	.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

