Revisión | 7e5a6010f234caa8d9ba8aa2af10e4cfc4ae224b (tree) |
---|---|
Tiempo | 2014-06-06 23:09:56 |
Autor | hikarupsp <hikarupsp@user...> |
Commiter | hikarupsp |
LIMMが動くようになった
@@ -18,6 +18,7 @@ int main(int argc, const char * argv[]) | ||
18 | 18 | } |
19 | 19 | env = CHNCPU_CreateRuntimeEnvironment(); |
20 | 20 | CHNCPU_LoadBinaryFromHexStringFilePath(env, argv[1]); |
21 | + CHNCPU_Execute(env); | |
21 | 22 | return 0; |
22 | 23 | } |
23 | 24 |
@@ -119,6 +120,20 @@ CHNCPU_RuntimeEnvironment *CHNCPU_CreateRuntimeEnvironment(void) | ||
119 | 120 | |
120 | 121 | env->appbinReader = malloc(sizeof(CH4Reader)); |
121 | 122 | |
123 | + // bindOpFuncTable | |
124 | + for(i = 0; i <= CHNCPU_OPECODE_MAX; i++){ | |
125 | + env->bindOpFuncTable[i] = NULL; | |
126 | + } | |
127 | + env->bindOpFuncTable[0x02] = CHNCPU_Op_LIMM_BindOperand; | |
128 | + | |
129 | + // execOpFuncTable | |
130 | + for(i = 0; i <= CHNCPU_OPECODE_MAX; i++){ | |
131 | + env->execOpFuncTable[i] = NULL; | |
132 | + } | |
133 | + env->execOpFuncTable[0x02] = CHNCPU_Op_LIMM_Execute; | |
134 | + | |
135 | + env->errFlags = 0; | |
136 | + | |
122 | 137 | return env; |
123 | 138 | } |
124 | 139 |
@@ -159,6 +174,7 @@ int CHNCPU_PrepareBinaryForExecution(CHNCPU_RuntimeEnvironment *env) | ||
159 | 174 | int index, page; |
160 | 175 | CHNCPU_OpTag *op; |
161 | 176 | int breakFlag = 0; |
177 | + int retv; | |
162 | 178 | |
163 | 179 | // env->appbinReaderから読み込んで、実行可能な状態にする。 |
164 | 180 | // これはコンパイラ版におけるコンパイルに相当する。 |
@@ -169,7 +185,7 @@ int CHNCPU_PrepareBinaryForExecution(CHNCPU_RuntimeEnvironment *env) | ||
169 | 185 | for(index = 0; index < CHNCPU_NUMBER_OF_OP_TAG; index++){ |
170 | 186 | opcode = CH4Reader_ReadNextAsUINT(env->appbinReader); |
171 | 187 | if(CH4Reader_IsEndOfBinary(env->appbinReader)){ |
172 | - puts("< End of binary > \n"); | |
188 | + puts("< End of binary >"); | |
173 | 189 | breakFlag = 1; |
174 | 190 | break; |
175 | 191 | } |
@@ -180,32 +196,106 @@ int CHNCPU_PrepareBinaryForExecution(CHNCPU_RuntimeEnvironment *env) | ||
180 | 196 | switch(opcode){ |
181 | 197 | case 0x00: |
182 | 198 | // NOP |
183 | - puts("NOP();"); | |
184 | - break; | |
185 | - case 0x02: | |
186 | - // LIMM | |
187 | - CHNCPU_Op_LIMM_BindOperand(env, op); | |
199 | + puts("NOP();\n"); | |
200 | + index--; | |
188 | 201 | break; |
189 | 202 | default: |
190 | - // Undefined | |
191 | - op->opCode = CHNCPU_OPCODE_INVALID; | |
192 | - puts("Undefined Opcode. \n"); | |
193 | - breakFlag = 1; | |
203 | + // ごく一部の特殊な命令以外は、命令テーブルを参照する | |
204 | + if(opcode <= CHNCPU_OPECODE_MAX && env->bindOpFuncTable[opcode]){ | |
205 | + retv = env->bindOpFuncTable[opcode](env, op); | |
206 | + if(retv){ | |
207 | + opcode = CHNCPU_OPCODE_INVALID; | |
208 | + } | |
209 | + } else{ | |
210 | + opcode = CHNCPU_OPCODE_INVALID; | |
211 | + } | |
212 | + if(opcode == CHNCPU_OPCODE_INVALID){ | |
213 | + op->opCode = CHNCPU_OPCODE_INVALID; | |
214 | + env->errFlags |= CHNCPU_ERR_C_OPCODE; | |
215 | + breakFlag = 1; | |
216 | + } | |
194 | 217 | break; |
195 | 218 | } |
196 | 219 | if(breakFlag == 1){ |
197 | 220 | break; |
198 | 221 | } |
199 | - putchar('\n'); | |
200 | 222 | } |
201 | 223 | if(breakFlag){ |
202 | 224 | break; |
203 | 225 | } |
204 | 226 | } |
227 | + if(env->errFlags){ | |
228 | + putchar('\n'); | |
229 | + if(env->errFlags & CHNCPU_ERR_C_REGNUM){ | |
230 | + puts("INVALID-C: Invalid register number."); | |
231 | + } | |
232 | + if(env->errFlags & CHNCPU_ERR_C_BITS){ | |
233 | + puts("INVALID-C: Not supported bit width."); | |
234 | + } | |
235 | + if(env->errFlags & CHNCPU_ERR_C_OPCODE){ | |
236 | + puts("INVALID-C: Unknown opCode."); | |
237 | + } | |
238 | + } | |
205 | 239 | |
206 | 240 | return 0; |
207 | 241 | } |
208 | 242 | |
243 | +int CHNCPU_Execute(CHNCPU_RuntimeEnvironment *env) | |
244 | +{ | |
245 | + int breakFlag = 0; | |
246 | + int count = 0; | |
247 | + int retv; | |
248 | + CHNCPU_OpTag *op; | |
249 | + | |
250 | + puts("< Beginning of execution >"); | |
251 | + for(; env->currentPage < CHNCPU_NUMBER_OF_MEMORY_PAGE; env->currentPage++){ | |
252 | + op = &env->mainmemory[env->currentPage].data[0]; | |
253 | + if(op->opCode == CHNCPU_OPCODE_INVALID){ | |
254 | + // 空白のメモリページ:バイナリの末端 | |
255 | + puts(">>> Control reached end of binary."); | |
256 | + breakFlag = 1; | |
257 | + break; | |
258 | + } | |
259 | + for(; env->currentIndex < CHNCPU_NUMBER_OF_OP_TAG; env->currentIndex++){ | |
260 | + op = &env->mainmemory[env->currentPage].data[env->currentIndex]; | |
261 | + if(op->opCode == CHNCPU_OPCODE_INVALID){ | |
262 | + // このページはここでおしまい | |
263 | + break; | |
264 | + } | |
265 | + if(op->opCode <= CHNCPU_OPECODE_MAX && env->bindOpFuncTable[op->opCode]){ | |
266 | + retv = env->execOpFuncTable[op->opCode](env, op); | |
267 | + } else{ | |
268 | + // すでにチェックしたはずなのに不明な命令が来た | |
269 | + env->errFlags |= CHNCPU_ERR_X_INTERNAL; | |
270 | + breakFlag = 1; | |
271 | + break; | |
272 | + } | |
273 | + if(retv){ | |
274 | + breakFlag = 1; | |
275 | + break; | |
276 | + } | |
277 | + | |
278 | + } | |
279 | + if(breakFlag){ | |
280 | + break; | |
281 | + } | |
282 | + count++; | |
283 | + env->currentIndex = 0; | |
284 | + } | |
285 | + if(env->errFlags){ | |
286 | + putchar('\n'); | |
287 | + if(env->errFlags & CHNCPU_ERR_X_INTERNAL){ | |
288 | + puts("INVALID-X: Internal error."); | |
289 | + } | |
290 | + } | |
291 | + | |
292 | + CHNCPU_DumpIReg(env); | |
293 | + | |
294 | + puts("< End of execution >"); | |
295 | + | |
296 | + return count; | |
297 | +} | |
298 | + | |
209 | 299 | void CHNCPU_DumpAppBin(CHNCPU_RuntimeEnvironment *env) |
210 | 300 | { |
211 | 301 | int i; |
@@ -221,4 +311,24 @@ void CHNCPU_DumpAppBin(CHNCPU_RuntimeEnvironment *env) | ||
221 | 311 | } |
222 | 312 | } |
223 | 313 | |
314 | +void CHNCPU_DumpIReg(CHNCPU_RuntimeEnvironment *env) | |
315 | +{ | |
316 | + int i, regs = 0; | |
317 | + | |
318 | + puts(">>> Integer registers"); | |
319 | + | |
320 | + for(i = 0; i < CHNCPU_NUMBER_OF_IREG; i++){ | |
321 | + if(env->iRegBits[i]){ | |
322 | + printf("R%02X:0x%08X(%2d) ", i, env->iReg[i], env->iRegBits[i]); | |
323 | + if((regs & 0xF) == 0xF){ | |
324 | + putchar('\n'); | |
325 | + } | |
326 | + regs++; | |
327 | + } | |
328 | + } | |
329 | + if(((regs - 1) & 0xF) != 0xF){ | |
330 | + putchar('\n'); | |
331 | + } | |
332 | +} | |
333 | + | |
224 | 334 |
@@ -15,6 +15,7 @@ | ||
15 | 15 | |
16 | 16 | #define SIZE_TMPDATA (1024 * 1024 * 1) |
17 | 17 | |
18 | +#define CHNCPU_OPECODE_MAX 0xFF | |
18 | 19 | #define CHNCPU_BITS_MAX 32 |
19 | 20 | #define CHNCPU_BITS_DEFAULT 32 |
20 | 21 | #define CHNCPU_NUMBER_OF_IREG 64 |
@@ -25,6 +26,9 @@ | ||
25 | 26 | |
26 | 27 | #define CHNCPU_ERR_C_REGNUM 1 |
27 | 28 | #define CHNCPU_ERR_C_BITS 2 |
29 | +#define CHNCPU_ERR_C_OPCODE 4 | |
30 | + | |
31 | +#define CHNCPU_ERR_X_INTERNAL 1 | |
28 | 32 | |
29 | 33 | typedef struct CHNCPU_OP_TAG CHNCPU_OpTag; |
30 | 34 | struct CHNCPU_OP_TAG { |
@@ -40,12 +44,16 @@ struct CHNCPU_MEMORY_PAGE { | ||
40 | 44 | |
41 | 45 | typedef struct CHNCPU_RUN_TIME_ENVIRONMENT CHNCPU_RuntimeEnvironment; |
42 | 46 | struct CHNCPU_RUN_TIME_ENVIRONMENT { |
47 | + int (*bindOpFuncTable[CHNCPU_OPECODE_MAX])(CHNCPU_RuntimeEnvironment *env, CHNCPU_OpTag *op); | |
48 | + int (*execOpFuncTable[CHNCPU_OPECODE_MAX])(CHNCPU_RuntimeEnvironment *env, CHNCPU_OpTag *op); | |
43 | 49 | int iReg[CHNCPU_NUMBER_OF_IREG]; |
44 | 50 | int iRegBits[CHNCPU_NUMBER_OF_IREG]; |
45 | 51 | CHNCPU_MemoryPage mainmemory[CHNCPU_NUMBER_OF_MEMORY_PAGE]; |
46 | 52 | unsigned char *appbin0; |
47 | 53 | int appbinsize; |
48 | 54 | CH4Reader *appbinReader; |
55 | + unsigned int errFlags; | |
56 | + int currentPage, currentIndex; | |
49 | 57 | }; |
50 | 58 | |
51 | 59 | typedef struct CHNCPU_OP_CACHE_LIMM CHNCPU_OpCache_LIMM; |
@@ -60,9 +68,12 @@ int decodeHexString(char *src0, char *src1, unsigned char *dst0, unsigned char * | ||
60 | 68 | CHNCPU_RuntimeEnvironment *CHNCPU_CreateRuntimeEnvironment(void); |
61 | 69 | int CHNCPU_LoadBinaryFromHexStringFilePath(CHNCPU_RuntimeEnvironment *env, const char *path); |
62 | 70 | int CHNCPU_PrepareBinaryForExecution(CHNCPU_RuntimeEnvironment *env); |
71 | +int CHNCPU_Execute(CHNCPU_RuntimeEnvironment *env); | |
63 | 72 | void CHNCPU_DumpAppBin(CHNCPU_RuntimeEnvironment *env); |
73 | +void CHNCPU_DumpIReg(CHNCPU_RuntimeEnvironment *env); | |
64 | 74 | |
65 | 75 | // @opcode.c |
66 | 76 | int CHNCPU_Op_LIMM_BindOperand(CHNCPU_RuntimeEnvironment *env, CHNCPU_OpTag *op); |
77 | +int CHNCPU_Op_LIMM_Execute(CHNCPU_RuntimeEnvironment *env, CHNCPU_OpTag *op); | |
67 | 78 | |
68 | 79 | #endif |
@@ -19,16 +19,35 @@ int CHNCPU_Op_LIMM_BindOperand(CHNCPU_RuntimeEnvironment *env, CHNCPU_OpTag *op) | ||
19 | 19 | opCache->r = CH4Reader_ReadNextAsUINT(env->appbinReader); |
20 | 20 | opCache->bit = CH4Reader_ReadNextAsUINT(env->appbinReader); |
21 | 21 | |
22 | - printf("LIMM(imm:0x%X r:%d bit:%d);", opCache->imm, opCache->r, opCache->bit); | |
22 | + printf("LIMM(imm:0x%X r:%d bit:%d);\n", opCache->imm, opCache->r, opCache->bit); | |
23 | 23 | |
24 | 24 | if(opCache->r >= CHNCPU_NUMBER_OF_IREG){ |
25 | - puts("INVALID-C: register number."); | |
26 | - return CHNCPU_ERR_C_REGNUM; | |
25 | + env->errFlags |= CHNCPU_ERR_C_REGNUM; | |
26 | + return -1; | |
27 | 27 | } |
28 | 28 | if(opCache->bit > CHNCPU_BITS_MAX){ |
29 | - puts("INVALID-C: bits."); | |
30 | - return CHNCPU_ERR_C_BITS; | |
29 | + env->errFlags |= CHNCPU_ERR_C_BITS; | |
30 | + return -1; | |
31 | 31 | } |
32 | 32 | return 0; |
33 | 33 | } |
34 | 34 | |
35 | +int CHNCPU_Op_LIMM_Execute(CHNCPU_RuntimeEnvironment *env, CHNCPU_OpTag *op) | |
36 | +{ | |
37 | + CHNCPU_OpCache_LIMM *opCache; | |
38 | + | |
39 | + opCache = op->opCache; | |
40 | + | |
41 | + printf("LIMM(imm:0x%X r:%d bit:%d);\n", opCache->imm, opCache->r, opCache->bit); | |
42 | + | |
43 | + env->iReg[opCache->r] = opCache->imm; | |
44 | + if(opCache->bit){ | |
45 | + env->iRegBits[opCache->r] = opCache->bit; | |
46 | + } else{ | |
47 | + env->iRegBits[opCache->r] = CHNCPU_BITS_DEFAULT; | |
48 | + } | |
49 | + | |
50 | + return 0; | |
51 | +} | |
52 | + | |
53 | + |
@@ -1 +1 @@ | ||
1 | -2 E123 0 0 | |
\ No newline at end of file | ||
1 | +2 E123 0 0 2 E365 1 0 | |
\ No newline at end of file |