1.1 --- a/stage2/irq.c Sat Feb 27 23:41:17 2016 +0100
1.2 +++ b/stage2/irq.c Sun Feb 28 01:18:09 2016 +0100
1.3 @@ -47,14 +47,17 @@
1.4
1.5 enum { max_tasks = 3 };
1.6 static u32 stack_pointers[max_tasks];
1.7 -u8 current_task = 0;
1.8 -u32 current_stack_pointer;
1.9 +static u32 registers[max_tasks][32];
1.10 +
1.11 +u8 current_task;
1.12 +u32 *current_stack_pointer;
1.13 +u32 *current_registers;
1.14 +
1.15 extern u32 _got_copy_start;
1.16
1.17 const u32 stack_start = 0x80080000;
1.18 const u32 stack_size = 0x00002000;
1.19 const u32 pagesize = 4 * 1024;
1.20 -const u32 framesize = 120; /* see the handlers */
1.21
1.22 /* Tasks. */
1.23
1.24 @@ -106,6 +109,13 @@
1.25 }
1.26 }
1.27
1.28 +void init_tasks()
1.29 +{
1.30 + current_task = 0;
1.31 + current_stack_pointer = &stack_pointers[current_task];
1.32 + current_registers = registers[current_task];
1.33 +}
1.34 +
1.35 void start_task(unsigned short task)
1.36 {
1.37 u32 args[] = {task, 0, (task - 1) * 60};
1.38 @@ -116,89 +126,30 @@
1.39 physical memory, but at the same address in virtual memory.
1.40 */
1.41
1.42 - physical = stack_start + stack_size * task;
1.43 + physical = stack_start - stack_size * task;
1.44 virtual = physical;
1.45
1.46 init_page_table(page_table_start, virtual - pagesize * 2, physical - pagesize * 2, pagesize, 0x1e, task);
1.47
1.48 + stack_pointers[task] = virtual;
1.49 +
1.50 /*
1.51 - Set the stack for the new task, initialising the global pointer and
1.52 + Set the registers for the new task, initialising the global pointer and
1.53 return address.
1.54 */
1.55
1.56 - init_stack(physical, _got_copy_start, (void (*)()) plot_pattern, args, 3);
1.57 -
1.58 - /* Advance the stack pointer so that the adopted frame will be found. */
1.59 -
1.60 - stack_pointers[task] = virtual - framesize;
1.61 + init_registers(registers[task], _got_copy_start, (void (*)()) plot_pattern, args, 3);
1.62 }
1.63
1.64 void switch_task()
1.65 {
1.66 - /*
1.67 - Get the current stack pointer. This is obtained just after saving the
1.68 - task's state.
1.69 - */
1.70 -
1.71 - stack_pointers[current_task] = current_stack_pointer;
1.72 -
1.73 /* Switch the current task. */
1.74
1.75 current_task++;
1.76 if (current_task == max_tasks) current_task = 1;
1.77
1.78 - /*
1.79 - Set the current stack pointer. This is actually set just before
1.80 - restoring the task's state.
1.81 - */
1.82 -
1.83 - current_stack_pointer = stack_pointers[current_task];
1.84 -}
1.85 -
1.86 -void invoke_task(unsigned short task)
1.87 -{
1.88 - current_task = task;
1.89 - current_stack_pointer = stack_pointers[current_task];
1.90 - set_task(current_task);
1.91 + /* Indicate the current stack pointer and task registers. */
1.92
1.93 - asm volatile(
1.94 - ".set noat\n"
1.95 - "move $sp, %0\n"
1.96 - "addi $sp, $sp, 120\n"
1.97 - "lw $at, -4($sp)\n"
1.98 - "lw $v0, -8($sp)\n"
1.99 - "lw $v1, -12($sp)\n"
1.100 - "lw $a0, -16($sp)\n"
1.101 - "lw $a1, -20($sp)\n"
1.102 - "lw $a2, -24($sp)\n"
1.103 - "lw $a3, -28($sp)\n"
1.104 - "lw $t0, -32($sp)\n"
1.105 - "lw $t1, -36($sp)\n"
1.106 - "lw $t2, -40($sp)\n"
1.107 - "lw $t3, -44($sp)\n"
1.108 - "lw $t4, -48($sp)\n"
1.109 - "lw $t5, -52($sp)\n"
1.110 - "lw $t6, -56($sp)\n"
1.111 - "lw $t7, -60($sp)\n"
1.112 - "lw $s0, -64($sp)\n"
1.113 - "lw $s1, -68($sp)\n"
1.114 - "lw $s2, -72($sp)\n"
1.115 - "lw $s3, -76($sp)\n"
1.116 - "lw $s4, -80($sp)\n"
1.117 - "lw $s5, -84($sp)\n"
1.118 - "lw $s6, -88($sp)\n"
1.119 - "lw $s7, -92($sp)\n"
1.120 - "lw $t8, -96($sp)\n"
1.121 - "lw $t9, -100($sp)\n"
1.122 - "lw $gp, -104($sp)\n"
1.123 - "lw $fp, -108($sp)\n"
1.124 - "lw $ra, -112($sp)\n"
1.125 - "lw $k0, -116($sp)\n"
1.126 - "mtc0 $k0, $14\n" /* CP0_EPC */
1.127 - "nop\n"
1.128 - "jr $ra\n"
1.129 - "nop"
1.130 - :
1.131 - : "r" (current_stack_pointer)
1.132 - );
1.133 + current_stack_pointer = &stack_pointers[current_task];
1.134 + current_registers = registers[current_task];
1.135 }