00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00022
00023 #include "crogue.h"
00024 #ifdef INTERPRETER_DEBUG
00025 #include <assert.h>
00026 #endif
00027
00028 #ifdef INTERPRETER_DEBUG
00029 #ifndef INLINE
00030 #define INLINE
00031 #endif
00032 #else
00033 #ifndef INLINE
00034 #define INLINE inline
00035 #endif
00036 #endif
00037
00038
00039 #define OP_NOP 0x00
00040 #define OP_HALT 0x01
00041 #define OP_DISC 0x02
00042 #define OP_DISCN 0x03
00043 #define OP_DUP 0x04
00044 #define OP_ALLOCA 0x05
00045
00046
00047 #define OP_RET 0x10
00048 #define OP_CALL 0x11
00049 #define OP_STA 0x12
00050 #define OP_MVA 0x13
00051 #define OP_LINK 0x14
00052 #define OP_CCALL 0x15
00053
00054
00055 #define OP_LDR 0x20
00056 #define OP_LDR2 0x21
00057 #define OP_STR 0x22
00058 #define OP_MOV 0x23
00059 #define OP_LDIB 0x24
00060 #define OP_LDIW 0x25
00061 #define OP_LDIL 0x26
00062 #define OP_LDIZ 0x27
00063 #define OP_LDIO 0x28
00064
00065
00066 #define OP_ADD 0x30
00067 #define OP_SUB 0x31
00068 #define OP_MUL 0x32
00069 #define OP_DIV 0x33
00070 #define OP_MOD 0x34
00071 #define OP_ASL 0x35
00072 #define OP_ASR 0x36
00073 #define OP_AND 0x37
00074 #define OP_OR 0x38
00075 #define OP_XOR 0x39
00076 #define OP_NEG 0x3A
00077 #define OP_INCR 0x3B
00078 #define OP_DECR 0x3C
00079
00080
00081 #define OP_BOOL 0x40
00082 #define OP_BOOL2 0x41
00083 #define OP_NOT 0x42
00084 #define OP_TEQ 0x43
00085 #define OP_TLT 0x44
00086 #define OP_TGT 0x45
00087
00088
00089 #define OP_JMPB 0x50
00090 #define OP_JMPW 0x51
00091 #define OP_JMPL 0x52
00092 #define OP_BRAB 0x53
00093 #define OP_BRAW 0x54
00094 #define OP_BRAL 0x55
00095
00096
00097 #define OP_DEREFB 0x60
00098 #define OP_DEREFW 0x61
00099 #define OP_DEREFL 0x62
00100 #define OP_POKEB 0x63
00101 #define OP_POKEW 0x64
00102 #define OP_POKEL 0x65
00103 #define OP_LDLBL 0x66
00104
00105
00106
00107 typedef union instruction_args
00108 {
00109 signed char bytes[6];
00110 unsigned char ubytes[4];
00111 signed short words[2];
00112 signed long dword;
00113 } instruction_args_t;
00114
00115
00116 static const char *interpreter_call_stack[32];
00117 static int interpreter_call_stack_pos = 0;
00118
00119 #define pop_stack() (*(--stack_pos))
00120 #define push_stack(n) (*(stack_pos++) = (n))
00121 #define write_arg(v) (*(arg_pos++) = (v))
00122 #define load_register(n) (register_pos[n])
00123 #define save_register(n,v) (register_pos[n] = (v))
00124 #define start_args() (arg_pos = register_pos + register_used + 1)
00125
00126
00127 static const char *interp_func_name(const char *pos)
00128 {
00129 pos--;
00130 do {
00131 pos--;
00132 } while(*pos != '\0');
00133 pos++;
00134 return pos;
00135 }
00136
00137
00138
00139
00140
00141
00142 long run_program(const unsigned char *program_data, int num_params, va_list params)
00143 {
00144 int ii;
00145 long new_pc;
00146 long param1, param2;
00147 const unsigned char *execution_pos;
00148 instruction_args_t args;
00149 return_info_t ret;
00150
00151 long *stack_pos;
00152 long *register_pos;
00153 long *arg_pos;
00154 long pc;
00155 short call_pos;
00156 short register_used;
00157 long active_stack[ACTIVE_STACK_DEPTH];
00158 long register_stack[REGISTER_STACK_DEPTH];
00159 short call_stack[CALL_STACK_DEPTH];
00160
00161 pc = 0;
00162 register_used = 0;
00163 stack_pos = active_stack;
00164 register_pos = register_stack;
00165 call_pos = 0;
00166
00167 start_args();
00168
00169 for(ii=0; ii<num_params; ii++)
00170 write_arg(va_arg(params, long));
00171 va_end(params);
00172
00173 new_pc = pc;
00174
00175 while(1)
00176 {
00177 pc = new_pc;
00178 new_pc++;
00179 execution_pos = program_data + pc;
00180
00181 args.bytes[0] = execution_pos[1];
00182 args.bytes[1] = execution_pos[2];
00183 args.bytes[2] = execution_pos[3];
00184 args.bytes[3] = execution_pos[4];
00185
00186 switch(*execution_pos)
00187 {
00188
00189 case OP_NOP:
00190 break;
00191 case OP_HALT:
00192 return 0;
00193 case OP_DISC:
00194 (void)pop_stack();
00195 break;
00196 case OP_DISCN:
00197 new_pc++;
00198 for(ii=0; ii<args.ubytes[0]; ii++)
00199 (void)pop_stack();
00200 break;
00201 case OP_DUP:
00202 param1 = pop_stack();
00203 push_stack(param1);
00204 push_stack(param1);
00205 break;
00206 case OP_ALLOCA:
00207 param1 = pop_stack();
00208 push_stack( (long)(register_pos + register_used) );
00209 register_used += ((param1+3) & (~3)) >> 2;
00210
00211 start_args();
00212 break;
00213
00214
00215 case OP_RET:
00216 interpreter_call_stack_pos--;
00217 if(call_pos == 0)
00218 {
00219 if(stack_pos > active_stack) {
00220 param1 = pop_stack();
00221 return param1;
00222 }
00223 else {
00224 return 0;
00225 }
00226 }
00227
00228
00229 register_pos--;
00230 register_used = *register_pos;
00231 register_pos -= register_used;
00232
00233 new_pc = call_stack[--call_pos];
00234 start_args();
00235 interpreter_call_stack[interpreter_call_stack_pos] = NULL;
00236 break;
00237 case OP_CALL:
00238 new_pc += 2;
00239 call_stack[call_pos++] = new_pc;
00240 new_pc = pc + args.words[0];
00241 break;
00242 case OP_STA:
00243 write_arg(pop_stack());
00244 break;
00245 case OP_MVA:
00246 new_pc++;
00247 write_arg(load_register(args.ubytes[0]));
00248 break;
00249 case OP_LINK:
00250 new_pc++;
00251
00252
00253 register_pos[register_used] = register_used;
00254 register_pos += register_used + 1;
00255 register_used = args.ubytes[0];
00256
00257 start_args();
00258 interpreter_call_stack[interpreter_call_stack_pos++] = interp_func_name(execution_pos);
00259 break;
00260 case OP_CCALL:
00261 new_pc += 2;
00262
00263 ret = interpret_call(args.words[0],
00264 register_pos + register_used + 1);
00265 if(ret.returns)
00266 push_stack( ret.retval );
00267 start_args();
00268 break;
00269
00270
00271 case OP_LDR2:
00272 new_pc+=2;
00273 push_stack(load_register(args.ubytes[0]));
00274 push_stack(load_register(args.ubytes[1]));
00275 break;
00276
00277 case OP_LDR:
00278 new_pc++;
00279 push_stack(load_register(args.ubytes[0]));
00280 break;
00281 case OP_STR:
00282 new_pc++;
00283 save_register(args.ubytes[0], pop_stack());
00284 break;
00285 case OP_MOV:
00286 new_pc += 2;
00287 save_register(args.ubytes[1], load_register(args.ubytes[0]));
00288 break;
00289 case OP_LDIB:
00290 new_pc++;
00291 push_stack((long)(args.bytes[0]));
00292 break;
00293 case OP_LDIW:
00294 new_pc += 2;
00295 push_stack((long)(args.words[0]));
00296 break;
00297 case OP_LDIL:
00298 new_pc += 4;
00299 push_stack( args.dword );
00300 break;
00301 case OP_LDIZ:
00302 push_stack(0);
00303 break;
00304 case OP_LDIO:
00305 push_stack(1);
00306 break;
00307
00308
00309 case OP_ADD:
00310 param2 = pop_stack();
00311 param1 = pop_stack();
00312 push_stack(param1 + param2);
00313 break;
00314 case OP_SUB:
00315 param2 = pop_stack();
00316 param1 = pop_stack();
00317 push_stack(param1 - param2);
00318 break;
00319 case OP_MUL:
00320 param2 = pop_stack();
00321 param1 = pop_stack();
00322 push_stack(param1 * param2);
00323 break;
00324 case OP_DIV:
00325 param2 = pop_stack();
00326 param1 = pop_stack();
00327 push_stack(param1 / param2);
00328 break;
00329 case OP_MOD:
00330 param2 = pop_stack();
00331 param1 = pop_stack();
00332 push_stack(param1 % param2);
00333 break;
00334 case OP_ASL:
00335 param2 = pop_stack();
00336 param1 = pop_stack();
00337 push_stack(param1 << param2);
00338 break;
00339 case OP_ASR:
00340 param2 = pop_stack();
00341 param1 = pop_stack();
00342 push_stack(param1 >> param2);
00343 break;
00344 case OP_AND:
00345 param2 = pop_stack();
00346 param1 = pop_stack();
00347 push_stack(param1 & param2);
00348 break;
00349 case OP_OR:
00350 param2 = pop_stack();
00351 param1 = pop_stack();
00352 push_stack(param1 | param2);
00353 break;
00354 case OP_XOR:
00355 param2 = pop_stack();
00356 param1 = pop_stack();
00357 push_stack(param1 ^ param2);
00358 break;
00359 case OP_NEG:
00360 param1 = -pop_stack();
00361 push_stack(param1);
00362 break;
00363 case OP_INCR:
00364 new_pc++;
00365 save_register(args.ubytes[0], load_register(args.ubytes[0]) + 1);
00366 break;
00367 case OP_DECR:
00368 new_pc++;
00369 save_register(args.ubytes[0], load_register(args.ubytes[0]) - 1);
00370 break;
00371
00372
00373 case OP_BOOL:
00374 param1 = !!pop_stack();
00375 push_stack(param1);
00376 break;
00377 case OP_BOOL2:
00378 param1 = pop_stack();
00379 param2 = pop_stack();
00380 push_stack(!!param2);
00381 push_stack(!!param1);
00382 break;
00383 case OP_NOT:
00384 param1 = pop_stack();
00385 push_stack(!param1);
00386 break;
00387 case OP_TEQ:
00388 param2 = pop_stack();
00389 param1 = pop_stack();
00390 push_stack(param1 == param2);
00391 break;
00392 case OP_TLT:
00393 param2 = pop_stack();
00394 param1 = pop_stack();
00395 push_stack(param1 < param2);
00396 break;
00397 case OP_TGT:
00398 param2 = pop_stack();
00399 param1 = pop_stack();
00400 push_stack(param1 > param2);
00401 break;
00402
00403
00404 case OP_JMPB:
00405 new_pc = pc + args.bytes[0];
00406 break;
00407 case OP_JMPW:
00408 new_pc = pc + args.words[0];
00409 break;
00410 case OP_JMPL:
00411 new_pc = pc + args.dword;
00412 break;
00413 case OP_BRAB:
00414 if(pop_stack())
00415 new_pc = pc + args.bytes[0];
00416 else
00417 new_pc++;
00418 break;
00419 case OP_BRAW:
00420 if(pop_stack()) {
00421 new_pc = pc + args.words[0];
00422 } else {
00423 new_pc+=2;
00424 }
00425 break;
00426 case OP_BRAL:
00427 if(pop_stack())
00428 new_pc = pc + args.dword;
00429 else
00430 new_pc+=4;
00431 break;
00432
00433
00434 case OP_DEREFB:
00435 param1 = pop_stack();
00436 #ifdef INTERPRETER_DEBUG
00437 assert(param1 > 1024);
00438 #endif
00439 push_stack( *((char*)param1) );
00440 break;
00441 case OP_DEREFW:
00442 param1 = pop_stack();
00443 #ifdef INTERPRETER_DEBUG
00444 assert(param1 > 1024);
00445 #endif
00446 push_stack( *((short*)param1) );
00447 break;
00448 case OP_DEREFL:
00449 param1 = pop_stack();
00450 #ifdef INTERPRETER_DEBUG
00451 assert(param1 > 1024);
00452 #endif
00453 push_stack( *((long*)param1) );
00454 break;
00455 case OP_POKEB:
00456 param1 = pop_stack();
00457 param2 = pop_stack();
00458 #ifdef INTERPRETER_DEBUG
00459 assert(param2 > 1024);
00460 #endif
00461 *((char*)param2) = param1;
00462 break;
00463 case OP_POKEW:
00464 param1 = pop_stack();
00465 param2 = pop_stack();
00466 #ifdef INTERPRETER_DEBUG
00467 assert(param2 > 1024);
00468 #endif
00469 *((short*)param2) = param1;
00470 break;
00471 case OP_POKEL:
00472 param1 = pop_stack();
00473 param2 = pop_stack();
00474 #ifdef INTERPRETER_DEBUG
00475 assert(param2 > 1024);
00476 #endif
00477 *((long*)param2) = param1;
00478 break;
00479 case OP_LDLBL:
00480 push_stack((long)(execution_pos + args.dword));
00481 new_pc += 4;
00482 break;
00483
00484
00485 default:
00486 break;
00487
00488 }
00489 }
00490 }
00491
00492