Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // XMega65 Kernal Development Template
- // Each function of the kernal is a no-args function
- // The functions are placed in the SYSCALLS table surrounded by JMP and NOP
- #pragma cpu(rom6502)
- import "string"
- #pragma link("mega65hyper.ld")
- const char* RASTER = 0xd012;
- const char* VIC_MEMORY = 0xd018;
- const char* SCREEN = 0x0400;
- const char* BGCOL = 0xd021;
- const char* COLS = 0xd800;
- const char BLACK = 0;
- const char BLUE = 6;
- const char WHITE = 1;
- char[] MESSAGE = "checkpoint 5.2";
- char[] FIRST = "checkpoint 5.2 berr0185";
- const unsigned char STATE_NOTRUNNING = $00;
- const unsigned char STATE_RUNNING = $01;
- unsigned char pid_counter = 0;
- // Process Descriptor Block definition
- struct process_descriptor_block
- {
- // Unique identifier for the process
- unsigned char process_id;
- // Current state of the process
- unsigned char process_state;
- // Human readable name of the process
- char* process_name;
- // Where this process is stored when not running
- // i.e., where in the $20000-$5FFFF memory range the
- // process is stored when not running.
- unsigned long storage_start_address;
- unsigned long storage_end_address;
- // Stored registers and related machine state for this
- // process (for the $D640-$D67E machine state registers)
- unsigned char* stored_state;
- };
- // Process stored state will live at $C000-$C7FF, with 256 bytes
- // for each process reserved
- const unsigned char *stored_pdbs = $C000;
- // 8 processes x 16 bytes = 128 bytes for names
- const char *process_names = $C800;
- // 8 processes x 64 bytes context state = 512 bytes
- const unsigned char *process_context_states = $C900;
- volatile unsigned char *current_screen_line = SCREEN;
- volatile unsigned char current_screen_x = 0;
- unsigned char next_free_pid()
- {
- unsigned short i;
- // Start with the next process ID
- unsigned char pid=++pid_counter;
- // then make sure that it isn't currently in use by another process
- // This loop must terminate according to the Pigeon Hole Principlle,
- // i.e., there are more possible PIDs than there are processes, so
- // iterating through them will find at least one.
- unsigned char stepped=1;
- while(stepped) {
- stepped=0;
- for(i=0;i<8;i++) {
- struct process_descriptor_block *p
- =(struct process_descriptor_block*)((unsigned short)stored_pdbs+(i<<8));
- if (pid==p->process_id) { pid++; stepped=1; }
- }
- }
- return pid;
- }
- void print_char(char c)
- {
- current_screen_line[current_screen_x++]=c;
- }
- void print_to_screen(char *message)
- {
- char *c=message;
- while(*c) {
- current_screen_line[current_screen_x++]=*c;
- c++;
- }
- }
- void print_newline()
- {
- current_screen_line+=40;
- current_screen_x=0;
- }
- void print_hex(unsigned word value)
- {
- char[5] hex;
- unsigned char i;
- for(i=0;i<8;i++) {
- if (value<0xa000) hex[i]='0'+(char)(value>>12);
- else hex[i]=(char)(value>>12)-9;
- value<<=4;
- }
- hex[4]=0;
- print_to_screen(hex);
- }
- void print_dhex(unsigned dword value)
- {
- print_hex((word)(value>>16));
- print_hex((unsigned word)value);
- }
- void describe_pdb(unsigned char pdb_number)
- {
- unsigned char i;
- struct process_descriptor_block *p
- =(struct process_descriptor_block *)(((unsigned short)stored_pdbs)+(((unsigned short)pdb_number)<<8));
- print_to_screen("pdb#");
- print_hex((word)pdb_number);
- print_to_screen(":");
- print_newline();
- print_to_screen(" pid: ");
- print_hex((word)p->process_id);
- print_newline();
- print_to_screen(" process name: ");
- char *n=p->process_name;
- for(i=0;n[i]&&(i<17);i++) {
- print_char(n[i]);
- }
- print_newline();
- print_to_screen(" mem start: $");
- print_dhex(p->storage_start_address);
- print_newline();
- print_to_screen(" mem end: $");
- print_dhex(p->storage_end_address);
- print_newline();
- print_to_screen(" pc: $");
- unsigned short *ss=p->stored_state;
- print_hex(ss[4]);
- print_newline();
- }
- // Setup a new process descriptor block
- void initialise_pdb(unsigned char pdb_number,char *name)
- {
- unsigned char i;
- struct process_descriptor_block *p
- =(struct process_descriptor_block *)(((unsigned short)stored_pdbs)+(((unsigned short)pdb_number)<<8));
- // Setup process ID
- p->process_id = next_free_pid();
- //XXX - Call the function next_free_pid() to get a process ID for the
- //process in this PDB, and store it in p->process_id
- // Setup process name
- // (32 bytes space for each to fit 16 chars + nul)
- // (we could just use 17 bytes, but kickc can't multiply by 17)
- p->process_name=process_names+(((short)i)<<5);
- char *pn=p->process_name;
- for(int i = 0; i < 17; i++)
- {
- pn[i]=name[i];
- }
- //XXX - copy the string in the array 'name' into the array 'p->process_name'
- //XXX - To make your life easier, do something like char *pn=p->process_name
- // Then you can just do something along the lines of pn[...]=name[...]
- // in a loop to copy the name into place.
- // (The arrays are both 17 bytes long)
- // Set process state as not running.
- //XXX - Put the value STATE_NOTRUNNING into p->process_state
- p->process_state = STATE_NOTRUNNING;
- // Set stored memory area
- // (for now, we just use fixed 8KB steps from $30000-$3FFFF
- // corresponding to the PDB number
- //XXX - Set p->storage_start_address to the correct start address
- //for a process that is in this PDB.
- //The correct address is $30000 + (((unsigned dword)pdb_number)*$2000);
- p->storage_start_address = $30000 + (((unsigned dword)pdb_number)*$2000);
- //XXX - Then do the same for the end address of the process
- //This gets stored into p->storage_end_address and the correct
- //address is $31FFF + (((unsigned dword)pdb_number)*$2000);
- p->storage_end_address = $31FFF + (((unsigned dword)pdb_number)*$2000);
- // Initialise processor state for standard entry at $080D
- // Everything to zero, except for a few things we will set manually
- // 64 bytes context switching state for each process
- p->stored_state=process_context_states+(((unsigned short)pdb_number)<<6);
- unsigned char *ss=p->stored_state;
- //XXX - Set all 64 bytes of the array 'ss' to zero, to clear the context
- //switching state
- for(i=0;i<63;i++)
- {
- ss[i] = $00;
- }
- // Set tandard CPU flags (8-bit stack, interrupts disabled)
- ss[7] = $24;
- //XXX - Set the stack pointer to $01FF
- //(This requires a bit of fiddly pointer arithmetic, so to save you
- //the trouble working it out, you can use the following as the left
- //side of the expression: *(unsigned short *)&ss[x] = ...
- //where x is the offset of the stack pointer low byte (SPL) in the
- //Hypervisor saved state registers in Appendix D of the MEGA65 User's
- //Guide. i.e., if it were at $D640, x would be replaced with 0, and
- //if it were at $D641, x would be replaced with 1, and so on.
- //XXX - Note that the MEGA65 User's Guide has been updated on FLO.
- //You will required the latest version, as otherwise SPL is not listed.
- int x = 5;
- *(unsigned short *)&ss[x] = $01FF;
- //XXX - Set the program counter to $080D
- //(This requires a bit of fiddly pointer arithmetic, so to save you
- //the trouble working it out, you can use the following as the left
- //side of the expression: *(unsigned short *)&ss[x] = ...
- //where x is the offset of the program counter low byte (PCL) in the
- //Hypervisor saved state registers in Appendix D of the MEGA65 User's
- //Guide.
- x = 8;
- *(unsigned short *)&ss[x] = $080D;
- return;
- }
- void main() {
- }
- void exit_hypervisor()
- {
- // Exit hypervisor
- *(char *)$D67F = $01;
- }
- //Sample sys calls to display a character on screen
- void syscall00()
- {
- exit_hypervisor();
- }
- void syscall01()
- {
- exit_hypervisor();
- }
- void syscall02()
- {
- exit_hypervisor();
- }
- void syscall03()
- {
- exit_hypervisor();
- }
- void syscall04()
- {
- exit_hypervisor();
- }
- void syscall05()
- {
- exit_hypervisor();
- }
- void syscall06()
- {
- exit_hypervisor();
- }
- void syscall07()
- {
- exit_hypervisor();
- }
- void syscall08()
- {
- exit_hypervisor();
- }
- void syscall09()
- {
- exit_hypervisor();
- }
- void syscall0A()
- {
- exit_hypervisor();
- }
- void syscall0B()
- {
- exit_hypervisor();
- }
- void syscall0C()
- {
- exit_hypervisor();
- }
- void syscall0D()
- {
- exit_hypervisor();
- }
- void syscall0E()
- {
- exit_hypervisor();
- }
- void syscall0F()
- {
- exit_hypervisor();
- }
- void syscall10()
- {
- exit_hypervisor();
- }
- void SECURENTR()
- {
- exit_hypervisor();
- }
- void SECUREXIT()
- {
- exit_hypervisor();
- }
- void syscall13()
- {
- exit_hypervisor();
- }
- void syscall14()
- {
- exit_hypervisor();
- }
- void syscall15()
- {
- exit_hypervisor();
- }
- void syscall16()
- {
- exit_hypervisor();
- }
- void syscall17()
- {
- exit_hypervisor();
- }
- void syscall18()
- {
- exit_hypervisor();
- }
- void syscall19()
- {
- exit_hypervisor();
- }
- void syscall1A()
- {
- exit_hypervisor();
- }
- void syscall1B()
- {
- exit_hypervisor();
- }
- void syscall1C()
- {
- exit_hypervisor();
- }
- void syscall1D()
- {
- exit_hypervisor();
- }
- void syscall1E()
- {
- exit_hypervisor();
- }
- void syscall1F()
- {
- exit_hypervisor();
- }
- void syscall20()
- {
- exit_hypervisor();
- }
- void syscall21()
- {
- exit_hypervisor();
- }
- void syscall22()
- {
- exit_hypervisor();
- }
- void syscall23()
- {
- exit_hypervisor();
- }
- void syscall24()
- {
- exit_hypervisor();
- }
- void syscall25()
- {
- exit_hypervisor();
- }
- void syscall26()
- {
- exit_hypervisor();
- }
- void syscall27()
- {
- exit_hypervisor();
- }
- void syscall28()
- {
- exit_hypervisor();
- }
- void syscall29()
- {
- exit_hypervisor();
- }
- void syscall2A()
- {
- exit_hypervisor();
- }
- void syscall2B()
- {
- exit_hypervisor();
- }
- void syscall2C()
- {
- exit_hypervisor();
- }
- void syscall2D()
- {
- exit_hypervisor();
- }
- void syscall2E()
- {
- exit_hypervisor();
- }
- void syscall2F()
- {
- exit_hypervisor();
- }
- void syscall30()
- {
- exit_hypervisor();
- }
- void syscall31()
- {
- exit_hypervisor();
- }
- void syscall32()
- {
- exit_hypervisor();
- }
- void syscall33()
- {
- exit_hypervisor();
- }
- void syscall34()
- {
- exit_hypervisor();
- }
- void syscall35()
- {
- exit_hypervisor();
- }
- void syscall36()
- {
- exit_hypervisor();
- }
- void syscall37()
- {
- exit_hypervisor();
- }
- void syscall38()
- {
- exit_hypervisor();
- }
- void syscall39()
- {
- exit_hypervisor();
- }
- void syscall3A()
- {
- exit_hypervisor();
- }
- void syscall3B()
- {
- exit_hypervisor();
- }
- void syscall3C()
- {
- exit_hypervisor();
- }
- void syscall3D()
- {
- exit_hypervisor();
- }
- void syscall3E()
- {
- exit_hypervisor();
- }
- void syscall3F()
- {
- exit_hypervisor();
- }
- void RESET()
- {
- //Initializes screen memory
- *VIC_MEMORY = 0x14;
- //Fill the screen
- memset(SCREEN, ' ', 40*25);
- //Sets the colour of every char on screen (white)
- memset(COLS, WHITE, 40*25);
- //Print the message
- char* sc = SCREEN+40; //one line down
- char* msg = FIRST; //the msg to display
- //copy routine that copies the string
- while(*msg)
- {
- *sc++ = *msg++;
- }
- current_screen_line = SCREEN;
- print_newline();
- print_newline();
- print_newline();
- initialise_pdb(0,"program1.prg");
- describe_pdb(0);
- //Forever loop displaying two white lines
- while(true)
- {
- if(*RASTER==54 || *RASTER==66)
- {
- *BGCOL = WHITE;
- }
- else
- {
- *BGCOL = BLACK;
- }
- }
- exit_hypervisor();
- }
- void PAGFAULT()
- {
- exit_hypervisor();
- }
- void RESTORKEY()
- {
- exit_hypervisor();
- }
- void ALTTABKEY()
- {
- exit_hypervisor();
- }
- void VF011RD()
- {
- exit_hypervisor();
- }
- void VF011WR()
- {
- exit_hypervisor();
- }
- void RESERVED()
- {
- exit_hypervisor();
- }
- void CPUKIL()
- {
- exit_hypervisor();
- }
- //Now we select the SYSCALL segment to hold the SYSCALL/trap entry point table.
- #pragma data_seg(Syscall)
- //The structure of each entry point is JMP (handler address) + NOP,
- // We have a char (xjmp) to hold the opcode for the JMP instruction,
- //and then put the address of the SYSCALL/trap handler in the next
- //two points as a pointer, and end with the NOP instruction opcode.
- struct SysCall
- {
- char xjmp; //Holds $4C, the JMP $nnnn opcode
- void()* syscall; //Holds handler address, will be the target of the JMP
- char xnop; //Holds $EA, the NOP opcode
- };
- //To save writing 0x4c and 0xEA all the time, we define them as constants
- const char JMP = 0x4c;
- const char NOP = 0xea;
- //Each line is an instance of the struct SysCall from above, with the JMP
- //opcode value, the address of the handler routine and the NOP opcode.
- export struct SysCall[] SYSCALLS =
- {
- { JMP, &syscall00, NOP },
- { JMP, &syscall01, NOP },
- { JMP, &syscall02, NOP },
- { JMP, &syscall03, NOP },
- { JMP, &syscall04, NOP },
- { JMP, &syscall05, NOP },
- { JMP, &syscall06, NOP },
- { JMP, &syscall07, NOP },
- { JMP, &syscall08, NOP },
- { JMP, &syscall09, NOP },
- { JMP, &syscall0A, NOP },
- { JMP, &syscall0B, NOP },
- { JMP, &syscall0C, NOP },
- { JMP, &syscall0D, NOP },
- { JMP, &syscall0E, NOP },
- { JMP, &syscall0F, NOP },
- { JMP, &syscall10, NOP },
- { JMP, &SECURENTR, NOP },
- { JMP, &SECUREXIT, NOP },
- { JMP, &syscall13, NOP },
- { JMP, &syscall14, NOP },
- { JMP, &syscall15, NOP },
- { JMP, &syscall16, NOP },
- { JMP, &syscall17, NOP },
- { JMP, &syscall18, NOP },
- { JMP, &syscall19, NOP },
- { JMP, &syscall1A, NOP },
- { JMP, &syscall1B, NOP },
- { JMP, &syscall1C, NOP },
- { JMP, &syscall1D, NOP },
- { JMP, &syscall1E, NOP },
- { JMP, &syscall1F, NOP },
- { JMP, &syscall20, NOP },
- { JMP, &syscall21, NOP },
- { JMP, &syscall22, NOP },
- { JMP, &syscall23, NOP },
- { JMP, &syscall24, NOP },
- { JMP, &syscall25, NOP },
- { JMP, &syscall26, NOP },
- { JMP, &syscall27, NOP },
- { JMP, &syscall28, NOP },
- { JMP, &syscall29, NOP },
- { JMP, &syscall2A, NOP },
- { JMP, &syscall2B, NOP },
- { JMP, &syscall2C, NOP },
- { JMP, &syscall2D, NOP },
- { JMP, &syscall2E, NOP },
- { JMP, &syscall2F, NOP },
- { JMP, &syscall30, NOP },
- { JMP, &syscall31, NOP },
- { JMP, &syscall32, NOP },
- { JMP, &syscall33, NOP },
- { JMP, &syscall34, NOP },
- { JMP, &syscall35, NOP },
- { JMP, &syscall36, NOP },
- { JMP, &syscall37, NOP },
- { JMP, &syscall38, NOP },
- { JMP, &syscall39, NOP },
- { JMP, &syscall3A, NOP },
- { JMP, &syscall3B, NOP },
- { JMP, &syscall3C, NOP },
- { JMP, &syscall3D, NOP },
- { JMP, &syscall3E, NOP },
- { JMP, &syscall3F, NOP }
- };
- //Function for undefined traps
- void undefined_trap()
- {
- }
- //IN this example we only had 2 syscalls defined, so rather than having
- //another 62 lines, we can just ask KickC to make the TRAP table begin
- //at the next mulitple of $100, ie at $8100
- export align(0x100) struct SysCall[] SYSCALL_RESET =
- {
- { JMP, &RESET, NOP },
- { JMP, &undefined_trap, NOP },
- { JMP, &undefined_trap, NOP },
- { JMP, &undefined_trap, NOP },
- { JMP, &undefined_trap, NOP },
- { JMP, &undefined_trap, NOP },
- { JMP, &undefined_trap, NOP },
- { JMP, &undefined_trap, NOP },
- { JMP, &undefined_trap, NOP },
- { JMP, &undefined_trap, NOP },
- { JMP, &undefined_trap, NOP },
- { JMP, &undefined_trap, NOP },
- { JMP, &undefined_trap, NOP },
- { JMP, &undefined_trap, NOP },
- { JMP, &undefined_trap, NOP },
- { JMP, &undefined_trap, NOP },
- { JMP, &undefined_trap, NOP },
- { JMP, &undefined_trap, NOP },
- { JMP, &undefined_trap, NOP },
- { JMP, &undefined_trap, NOP },
- { JMP, &undefined_trap, NOP },
- { JMP, &undefined_trap, NOP },
- { JMP, &undefined_trap, NOP },
- { JMP, &undefined_trap, NOP },
- { JMP, &undefined_trap, NOP },
- { JMP, &undefined_trap, NOP },
- { JMP, &undefined_trap, NOP },
- { JMP, &undefined_trap, NOP },
- { JMP, &undefined_trap, NOP },
- { JMP, &undefined_trap, NOP },
- { JMP, &undefined_trap, NOP },
- { JMP, &undefined_trap, NOP },
- { JMP, &undefined_trap, NOP },
- { JMP, &undefined_trap, NOP },
- { JMP, &undefined_trap, NOP },
- { JMP, &undefined_trap, NOP },
- { JMP, &undefined_trap, NOP },
- { JMP, &undefined_trap, NOP },
- { JMP, &undefined_trap, NOP },
- { JMP, &undefined_trap, NOP },
- { JMP, &undefined_trap, NOP },
- { JMP, &undefined_trap, NOP },
- { JMP, &undefined_trap, NOP },
- { JMP, &undefined_trap, NOP },
- { JMP, &undefined_trap, NOP },
- { JMP, &undefined_trap, NOP },
- { JMP, &undefined_trap, NOP },
- { JMP, &undefined_trap, NOP },
- { JMP, &undefined_trap, NOP }
- };
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement