1 package com.tapina.robe.swi.clib;
2
3 import com.tapina.robe.runtime.*;
4 import com.tapina.robe.runtime.instruction.SWI;
5 import com.tapina.robe.swi.OS;
6
7 import java.io.IOException;
8
9 /***
10 * Class to hold the kernel stubs.
11 */
12 public class Kernel {
13 private final static Kernel ourInstance = new Kernel();
14 static final int STACK_SIZE = 65536;
15
16 public static Kernel getInstance() {
17 return ourInstance;
18 }
19
20 private Kernel() {
21 }
22
23 public final Stub dummy(final int stubId) {
24 return new Stub() {
25 public void executeStub(Environment environment) {
26 log.warning("Attempt to call unknown kernel shared library stub &" + Integer.toHexString(stubId));
27 throw new UnknownSharedLibraryCall(1, stubId);
28 }
29 };
30 }
31
32 public final Stub init() {
33 return new Stub() {
34 /***
35 * This taken from riscose:
36 * <pre>
37 * WORD *kernel_init = (WORD*) MEM_TOHOST(ARM_R0);
38 * //WORD image_base = kernel_init[0];
39 * WORD c = 0, limit = kernel_init[2] - kernel_init[1];
40 * WORD *language_description = (WORD*) MEM_TOHOST(kernel_init[1]);
41 * ARM_SET_R10(MMAP_USRSTACK_BASE+768);
42 * ARM_SET_R11(0);
43 * ARM_SET_R12(0);
44 * ARM_SET_R13(MMAP_USRSTACK_BASE+ MMAP_USRSTACK_SIZE);
45 * while (c != limit)
46 * {
47 * if (language_description[c + 4] != 0) {
48 * arm_run_routine(language_description[c + 4]);
49 * arm_set_pc(ARM_R0);
50 * return SWIH_EXIT_HANDLED; // BODGE!
51 * }
52 * c += language_description[c] >> 2;
53 * printf("%li\n", c);
54 * }
55 * </pre>
56 */
57 public void execute(Environment environment) {
58
59
60
61
62
63 final MemoryMap memoryMap = environment.getMemoryMap();
64 final int[] R = environment.getCpu().R;
65 int imageBase = memoryMap.getWord(R[0]);
66 int c = 0;
67 int languageDescription = memoryMap.getWord(R[0] + 4);
68 int limit = memoryMap.getWord(R[0] + 8) - languageDescription;
69
70 RawDataBlock stack = memoryMap.createSystemDataBlock(STACK_SIZE);
71 R[10] = stack.getAddress() + 768;
72 R[11] = R[12] = 0;
73 R[13] = stack.getAddress() + stack.getSize();
74 while (c != limit) {
75 final int routineAddress = memoryMap.getWord(languageDescription + (c + 4) * 4);
76 if (routineAddress != 0) {
77 CodeBlock codeBlock = memoryMap.addEntryPoint(routineAddress);
78 executeSubroutine(environment, codeBlock);
79 environment.getCpu().setPC(R[0]);
80 return;
81 }
82 c += memoryMap.getWord(languageDescription + c * 4) >> 2;
83 }
84 unwind(environment);
85 }
86
87 public void executeStub(Environment environment) {
88 }
89 };
90 }
91
92 public final Stub exit() {
93 return new Stub() {
94 public void executeStub(Environment environment) {
95 System.exit(environment.getCpu().R[0]);
96 }
97 };
98 }
99
100 public final Stub setreturncode() {
101 return new Stub() {
102 public void executeStub(Environment environment) {
103 log.warning("setreturncode() not implemented");
104 }
105 };
106 }
107
108 public Stub commandString() {
109 return new Stub() {
110 public void executeStub(Environment environment) {
111 OS.getInstance().GetEnv(environment);
112 }
113 };
114 }
115
116 public Stub swi() {
117 return new Stub() {
118 public void executeStub(Environment environment) {
119 final int[] R = environment.getCpu().R;
120 final int swiNumber = R[0];
121 final int[] R4to9save = new int[6];
122 final int[] R0to9in = environment.getMemoryMap().getWords(R[1], 10);
123 final int[] R0to9out = new int[10];
124 final int outAddress = R[2];
125 System.arraycopy(R, 4, R4to9save, 0, 6);
126 System.arraycopy(R0to9in, 0, R, 0, 10);
127 try {
128 SWI swi = new SWI(Condition.AL, swiNumber);
129 swi.checkAndExecute(environment);
130 System.arraycopy(R, 0, R0to9out, 0, 10);
131 environment.getMemoryMap().storeWords(outAddress, R0to9out);
132 R[0] = 0;
133 } catch (UnknownSWIException e) {
134 environment.returnError(e);
135 } finally {
136 System.arraycopy(R4to9save, 0, R, 4,6);
137 }
138 }
139 };
140 }
141
142 public Stub os_get() {
143 return new Stub() {
144 public void executeStub(Environment environment) {
145 try {
146 environment.getCpu().R[0] = System.in.read();
147 } catch (IOException e) {
148 environment.getCpu().R[0] = 256;
149 }
150 }
151 };
152 }
153
154 /***
155 * This function calls the OS_Byte SWI with the register R0 set to the value passed in a1, and registers R1 and R2
156 * set to the values pointed to by a2 and a3.
157 * The int returned contains R1 in its bottom byte, R2 in the second byte, and 1 in the third byte if the carry
158 * flag is set.
159 * Returns: Values returned, or error as follows: (-1) Carry flag is set (call failed), (-2) OS error occurs.
160 * @return Stub implementing desired functionality
161 */
162 public Stub osbyte() {
163 return new Stub() {
164 public void executeStub(Environment environment) {
165 final int[] R = environment.getCpu().R;
166 try {
167 final int[] result = OS.getInstance().osByte(R[0], R[1], R[2]);
168 R[0] = result[0] | (result[1] << 8);
169 } catch (Exception e) {
170 R[0] = -2;
171 }
172 }
173 };
174 }
175
176 /***
177 * This function tests for the presence of either the floating point co-processor or the floating point emulator
178 * module (FPE).
179 * Returns: 0 if floating point is not available.
180 * @return Stub implementing desired functionality
181 */
182 public Stub fpavailable() {
183 return new Stub() {
184 public void executeStub(Environment environment) {
185 environment.getCpu().R[0] = 0;
186 log.warning("_kernel_fpavailable() returns 0, which is a lie");
187 }
188 };
189 }
190 }