diff options
Diffstat (limited to 'libraries/embryo/src/lib/embryo_amx.c')
-rw-r--r-- | libraries/embryo/src/lib/embryo_amx.c | 1995 |
1 files changed, 0 insertions, 1995 deletions
diff --git a/libraries/embryo/src/lib/embryo_amx.c b/libraries/embryo/src/lib/embryo_amx.c deleted file mode 100644 index 7a41111..0000000 --- a/libraries/embryo/src/lib/embryo_amx.c +++ /dev/null | |||
@@ -1,1995 +0,0 @@ | |||
1 | /* Abstract Machine for the Small compiler | ||
2 | * | ||
3 | * Copyright (c) ITB CompuPhase, 1997-2003 | ||
4 | * Portions Copyright (c) Carsten Haitzler, 2004-2010 <raster@rasterman.com> | ||
5 | * | ||
6 | * This software is provided "as-is", without any express or implied warranty. | ||
7 | * In no event will the authors be held liable for any damages arising from | ||
8 | * the use of this software. | ||
9 | * | ||
10 | * Permission is granted to anyone to use this software for any purpose, | ||
11 | * including commercial applications, and to alter it and redistribute it | ||
12 | * freely, subject to the following restrictions: | ||
13 | * | ||
14 | * 1. The origin of this software must not be misrepresented; you must not | ||
15 | * claim that you wrote the original software. If you use this software in | ||
16 | * a product, an acknowledgment in the product documentation would be | ||
17 | * appreciated but is not required. | ||
18 | * 2. Altered source versions must be plainly marked as such, and must not be | ||
19 | * misrepresented as being the original software. | ||
20 | * 3. This notice may not be removed or altered from any source distribution. | ||
21 | */ | ||
22 | |||
23 | |||
24 | #ifdef HAVE_CONFIG_H | ||
25 | # include "config.h" | ||
26 | #endif | ||
27 | |||
28 | #include <stdlib.h> | ||
29 | #include <stdio.h> | ||
30 | #include <string.h> | ||
31 | |||
32 | #ifdef HAVE_EXOTIC | ||
33 | # include <Exotic.h> | ||
34 | #endif | ||
35 | |||
36 | #include "Embryo.h" | ||
37 | #include "embryo_private.h" | ||
38 | |||
39 | |||
40 | #define JUMPABS(base, ip) ((Embryo_Cell *)(code + (*ip))) | ||
41 | |||
42 | #ifdef WORDS_BIGENDIAN | ||
43 | static void _embryo_byte_swap_16 (unsigned short *v); | ||
44 | static void _embryo_byte_swap_32 (unsigned int *v); | ||
45 | #endif | ||
46 | static int _embryo_native_call (Embryo_Program *ep, Embryo_Cell index, Embryo_Cell *result, Embryo_Cell *params); | ||
47 | static int _embryo_func_get (Embryo_Program *ep, int index, char *funcname); | ||
48 | static int _embryo_var_get (Embryo_Program *ep, int index, char *varname, Embryo_Cell *ep_addr); | ||
49 | static int _embryo_program_init (Embryo_Program *ep, void *code); | ||
50 | |||
51 | #ifdef WORDS_BIGENDIAN | ||
52 | static void | ||
53 | _embryo_byte_swap_16(unsigned short *v) | ||
54 | { | ||
55 | unsigned char *s, t; | ||
56 | |||
57 | s = (unsigned char *)v; | ||
58 | t = s[0]; s[0] = s[1]; s[1] = t; | ||
59 | } | ||
60 | |||
61 | static void | ||
62 | _embryo_byte_swap_32(unsigned int *v) | ||
63 | { | ||
64 | unsigned char *s, t; | ||
65 | |||
66 | s = (unsigned char *)v; | ||
67 | t = s[0]; s[0] = s[3]; s[3] = t; | ||
68 | t = s[1]; s[1] = s[2]; s[2] = t; | ||
69 | } | ||
70 | #endif | ||
71 | |||
72 | static int | ||
73 | _embryo_native_call(Embryo_Program *ep, Embryo_Cell index, Embryo_Cell *result, Embryo_Cell *params) | ||
74 | { | ||
75 | Embryo_Header *hdr; | ||
76 | Embryo_Func_Stub *func_entry; | ||
77 | Embryo_Native f; | ||
78 | |||
79 | hdr = (Embryo_Header *)ep->base; | ||
80 | func_entry = GETENTRY(hdr, natives, index); | ||
81 | if ((func_entry->address <= 0) || | ||
82 | (func_entry->address > ep->native_calls_size)) | ||
83 | { | ||
84 | ep->error = EMBRYO_ERROR_CALLBACK; | ||
85 | return ep->error; | ||
86 | } | ||
87 | f = ep->native_calls[func_entry->address - 1]; | ||
88 | if (!f) | ||
89 | { | ||
90 | ep->error = EMBRYO_ERROR_CALLBACK; | ||
91 | return ep->error; | ||
92 | } | ||
93 | ep->error = EMBRYO_ERROR_NONE; | ||
94 | *result = f(ep, params); | ||
95 | return ep->error; | ||
96 | } | ||
97 | |||
98 | static int | ||
99 | _embryo_func_get(Embryo_Program *ep, int index, char *funcname) | ||
100 | { | ||
101 | Embryo_Header *hdr; | ||
102 | Embryo_Func_Stub *func; | ||
103 | |||
104 | hdr = (Embryo_Header *)ep->code; | ||
105 | if (index >= (Embryo_Cell)NUMENTRIES(hdr, publics, natives)) | ||
106 | return EMBRYO_ERROR_INDEX; | ||
107 | |||
108 | func = GETENTRY(hdr, publics, index); | ||
109 | strcpy(funcname, GETENTRYNAME(hdr, func)); | ||
110 | return EMBRYO_ERROR_NONE; | ||
111 | } | ||
112 | |||
113 | static int | ||
114 | _embryo_var_get(Embryo_Program *ep, int index, char *varname, Embryo_Cell *ep_addr) | ||
115 | { | ||
116 | |||
117 | Embryo_Header *hdr; | ||
118 | Embryo_Func_Stub *var; | ||
119 | |||
120 | hdr=(Embryo_Header *)ep->base; | ||
121 | if (index >= (Embryo_Cell)NUMENTRIES(hdr, pubvars, tags)) | ||
122 | return EMBRYO_ERROR_INDEX; | ||
123 | |||
124 | var = GETENTRY(hdr, pubvars, index); | ||
125 | strcpy(varname, GETENTRYNAME(hdr, var)); | ||
126 | *ep_addr = var->address; | ||
127 | return EMBRYO_ERROR_NONE; | ||
128 | } | ||
129 | |||
130 | static int | ||
131 | _embryo_program_init(Embryo_Program *ep, void *code) | ||
132 | { | ||
133 | Embryo_Header *hdr; | ||
134 | |||
135 | if ((ep->flags & EMBRYO_FLAG_RELOC)) return 1; | ||
136 | ep->code = (unsigned char *)code; | ||
137 | hdr = (Embryo_Header *)ep->code; | ||
138 | #ifdef WORDS_BIGENDIAN | ||
139 | embryo_swap_32((unsigned int *)&hdr->size); | ||
140 | embryo_swap_16((unsigned short *)&hdr->magic); | ||
141 | embryo_swap_16((unsigned short *)&hdr->flags); | ||
142 | embryo_swap_16((unsigned short *)&hdr->defsize); | ||
143 | embryo_swap_32((unsigned int *)&hdr->cod); | ||
144 | embryo_swap_32((unsigned int *)&hdr->dat); | ||
145 | embryo_swap_32((unsigned int *)&hdr->hea); | ||
146 | embryo_swap_32((unsigned int *)&hdr->stp); | ||
147 | embryo_swap_32((unsigned int *)&hdr->cip); | ||
148 | embryo_swap_32((unsigned int *)&hdr->publics); | ||
149 | embryo_swap_32((unsigned int *)&hdr->natives); | ||
150 | embryo_swap_32((unsigned int *)&hdr->libraries); | ||
151 | embryo_swap_32((unsigned int *)&hdr->pubvars); | ||
152 | embryo_swap_32((unsigned int *)&hdr->tags); | ||
153 | embryo_swap_32((unsigned int *)&hdr->nametable); | ||
154 | #endif | ||
155 | |||
156 | if (hdr->magic != EMBRYO_MAGIC) return 0; | ||
157 | if ((hdr->file_version < MIN_FILE_VERSION) || | ||
158 | (hdr->ep_version > CUR_FILE_VERSION)) return 0; | ||
159 | if ((hdr->defsize != sizeof(Embryo_Func_Stub)) && | ||
160 | (hdr->defsize != (2 * sizeof(unsigned int)))) return 0; | ||
161 | if (hdr->defsize == (2 * sizeof(unsigned int))) | ||
162 | { | ||
163 | unsigned short *len; | ||
164 | |||
165 | len = (unsigned short*)((unsigned char*)ep->code + hdr->nametable); | ||
166 | #ifdef WORDS_BIGENDIAN | ||
167 | embryo_swap_16((unsigned short *)len); | ||
168 | #endif | ||
169 | if (*len > sNAMEMAX) return 0; | ||
170 | } | ||
171 | if (hdr->stp <= 0) return 0; | ||
172 | if ((hdr->flags & EMBRYO_FLAG_COMPACT)) return 0; | ||
173 | |||
174 | #ifdef WORDS_BIGENDIAN | ||
175 | { | ||
176 | Embryo_Func_Stub *fs; | ||
177 | int i, num; | ||
178 | |||
179 | /* also align all addresses in the public function, public variable and */ | ||
180 | /* public tag tables */ | ||
181 | fs = GETENTRY(hdr, publics, 0); | ||
182 | num = NUMENTRIES(hdr, publics, natives); | ||
183 | for (i = 0; i < num; i++) | ||
184 | { | ||
185 | embryo_swap_32(&(fs->address)); | ||
186 | fs = (Embryo_Func_Stub *)((unsigned char *)fs + hdr->defsize); | ||
187 | } | ||
188 | |||
189 | fs = GETENTRY(hdr, pubvars, 0); | ||
190 | num = NUMENTRIES(hdr, pubvars, tags); | ||
191 | for (i = 0; i < num; i++) | ||
192 | { | ||
193 | embryo_swap_32(&(fs->address)); | ||
194 | fs = (Embryo_Func_Stub *)((unsigned char *)fs + hdr->defsize); | ||
195 | } | ||
196 | |||
197 | fs = GETENTRY(hdr, tags, 0); | ||
198 | num = NUMENTRIES(hdr, tags, nametable); | ||
199 | for (i = 0; i < num; i++) | ||
200 | { | ||
201 | embryo_swap_32(&(fs->address)); | ||
202 | fs = (Embryo_Func_Stub *)((unsigned char *)fs + hdr->defsize); | ||
203 | } | ||
204 | } | ||
205 | #endif | ||
206 | ep->flags = EMBRYO_FLAG_RELOC; | ||
207 | |||
208 | { | ||
209 | Embryo_Cell cip, code_size, cip_end; | ||
210 | Embryo_Cell *code; | ||
211 | |||
212 | code_size = hdr->dat - hdr->cod; | ||
213 | code = (Embryo_Cell *)((unsigned char *)ep->code + (int)hdr->cod); | ||
214 | cip_end = code_size / sizeof(Embryo_Cell); | ||
215 | for (cip = 0; cip < cip_end; cip++) | ||
216 | { | ||
217 | /* move this here - later we probably want something that verifies opcodes | ||
218 | * are valid and ok... | ||
219 | */ | ||
220 | #ifdef WORDS_BIGENDIAN | ||
221 | embryo_swap_32(&(code[cip])); | ||
222 | #endif | ||
223 | |||
224 | } | ||
225 | } | ||
226 | /* init native api for handling floating point - default in embryo */ | ||
227 | _embryo_args_init(ep); | ||
228 | _embryo_fp_init(ep); | ||
229 | _embryo_rand_init(ep); | ||
230 | _embryo_str_init(ep); | ||
231 | _embryo_time_init(ep); | ||
232 | return 1; | ||
233 | } | ||
234 | |||
235 | /*** EXPORTED CALLS ***/ | ||
236 | |||
237 | EAPI Embryo_Program * | ||
238 | embryo_program_new(void *data, int size) | ||
239 | { | ||
240 | Embryo_Program *ep; | ||
241 | void *code_data; | ||
242 | |||
243 | if (size < (int)sizeof(Embryo_Header)) return NULL; | ||
244 | |||
245 | ep = calloc(1, sizeof(Embryo_Program)); | ||
246 | if (!ep) return NULL; | ||
247 | |||
248 | code_data = malloc(size); | ||
249 | if (!code_data) | ||
250 | { | ||
251 | free(ep); | ||
252 | return NULL; | ||
253 | } | ||
254 | memcpy(code_data, data, size); | ||
255 | if (_embryo_program_init(ep, code_data)) return ep; | ||
256 | free(code_data); | ||
257 | free(ep); | ||
258 | return NULL; | ||
259 | } | ||
260 | |||
261 | EAPI Embryo_Program * | ||
262 | embryo_program_const_new(void *data, int size) | ||
263 | { | ||
264 | Embryo_Program *ep; | ||
265 | |||
266 | if (size < (int)sizeof(Embryo_Header)) return NULL; | ||
267 | |||
268 | ep = calloc(1, sizeof(Embryo_Program)); | ||
269 | if (!ep) return NULL; | ||
270 | |||
271 | if (_embryo_program_init(ep, data)) | ||
272 | { | ||
273 | ep->dont_free_code = 1; | ||
274 | return ep; | ||
275 | } | ||
276 | free(ep); | ||
277 | return NULL; | ||
278 | } | ||
279 | |||
280 | EAPI Embryo_Program * | ||
281 | embryo_program_load(const char *file) | ||
282 | { | ||
283 | Embryo_Program *ep; | ||
284 | Embryo_Header hdr; | ||
285 | FILE *f; | ||
286 | void *program = NULL; | ||
287 | int program_size = 0; | ||
288 | |||
289 | f = fopen(file, "rb"); | ||
290 | if (!f) return NULL; | ||
291 | fseek(f, 0, SEEK_END); | ||
292 | program_size = ftell(f); | ||
293 | fseek(f, 0L, SEEK_SET); | ||
294 | if (program_size < (int)sizeof(Embryo_Header)) | ||
295 | { | ||
296 | fclose(f); | ||
297 | return NULL; | ||
298 | } | ||
299 | if (fread(&hdr, sizeof(Embryo_Header), 1, f) != 1) | ||
300 | { | ||
301 | fclose(f); | ||
302 | return NULL; | ||
303 | } | ||
304 | fseek(f, 0L, SEEK_SET); | ||
305 | #ifdef WORDS_BIGENDIAN | ||
306 | embryo_swap_32((unsigned int *)(&hdr.size)); | ||
307 | #endif | ||
308 | if ((int)hdr.size < program_size) program_size = hdr.size; | ||
309 | program = malloc(program_size); | ||
310 | if (!program) | ||
311 | { | ||
312 | fclose(f); | ||
313 | return NULL; | ||
314 | } | ||
315 | if (fread(program, program_size, 1, f) != 1) | ||
316 | { | ||
317 | free(program); | ||
318 | fclose(f); | ||
319 | return NULL; | ||
320 | } | ||
321 | ep = embryo_program_new(program, program_size); | ||
322 | free(program); | ||
323 | fclose(f); | ||
324 | return ep; | ||
325 | } | ||
326 | |||
327 | EAPI void | ||
328 | embryo_program_free(Embryo_Program *ep) | ||
329 | { | ||
330 | int i; | ||
331 | |||
332 | if (ep->base) free(ep->base); | ||
333 | if ((!ep->dont_free_code) && (ep->code)) free(ep->code); | ||
334 | if (ep->native_calls) free(ep->native_calls); | ||
335 | for (i = 0; i < ep->params_size; i++) | ||
336 | { | ||
337 | if (ep->params[i].string) free(ep->params[i].string); | ||
338 | if (ep->params[i].cell_array) free(ep->params[i].cell_array); | ||
339 | } | ||
340 | if (ep->params) free(ep->params); | ||
341 | free(ep); | ||
342 | } | ||
343 | |||
344 | |||
345 | EAPI void | ||
346 | embryo_program_native_call_add(Embryo_Program *ep, const char *name, Embryo_Cell (*func) (Embryo_Program *ep, Embryo_Cell *params)) | ||
347 | { | ||
348 | Embryo_Func_Stub *func_entry; | ||
349 | Embryo_Header *hdr; | ||
350 | int i, num; | ||
351 | |||
352 | if ((!ep ) || (!name) || (!func)) return; | ||
353 | if (strlen(name) > sNAMEMAX) return; | ||
354 | |||
355 | hdr = (Embryo_Header *)ep->code; | ||
356 | if (hdr->defsize < 1) return; | ||
357 | num = NUMENTRIES(hdr, natives, libraries); | ||
358 | if (num <= 0) return; | ||
359 | |||
360 | ep->native_calls_size++; | ||
361 | if (ep->native_calls_size > ep->native_calls_alloc) | ||
362 | { | ||
363 | Embryo_Native *calls; | ||
364 | |||
365 | ep->native_calls_alloc += 32; | ||
366 | calls = realloc(ep->native_calls, | ||
367 | ep->native_calls_alloc * sizeof(Embryo_Native)); | ||
368 | if (!calls) | ||
369 | { | ||
370 | ep->native_calls_size--; | ||
371 | ep->native_calls_alloc -= 32; | ||
372 | return; | ||
373 | } | ||
374 | ep->native_calls = calls; | ||
375 | } | ||
376 | ep->native_calls[ep->native_calls_size - 1] = func; | ||
377 | |||
378 | func_entry = GETENTRY(hdr, natives, 0); | ||
379 | for (i = 0; i < num; i++) | ||
380 | { | ||
381 | if (func_entry->address == 0) | ||
382 | { | ||
383 | char *entry_name; | ||
384 | |||
385 | entry_name = GETENTRYNAME(hdr, func_entry); | ||
386 | if ((entry_name) && (!strcmp(entry_name, name))) | ||
387 | { | ||
388 | func_entry->address = ep->native_calls_size; | ||
389 | /* FIXME: embryo_cc is putting in multiple native */ | ||
390 | /* function call entries - so we need to fill in all */ | ||
391 | /* of them!!! */ | ||
392 | /* return; */ | ||
393 | } | ||
394 | } | ||
395 | func_entry = | ||
396 | (Embryo_Func_Stub *)((unsigned char *)func_entry + hdr->defsize); | ||
397 | } | ||
398 | } | ||
399 | |||
400 | |||
401 | EAPI void | ||
402 | embryo_program_vm_reset(Embryo_Program *ep) | ||
403 | { | ||
404 | Embryo_Header *hdr; | ||
405 | |||
406 | if ((!ep) || (!ep->base)) return; | ||
407 | hdr = (Embryo_Header *)ep->code; | ||
408 | memcpy(ep->base, hdr, hdr->size); | ||
409 | *(Embryo_Cell *)(ep->base + (int)hdr->stp - sizeof(Embryo_Cell)) = 0; | ||
410 | |||
411 | ep->hlw = hdr->hea - hdr->dat; /* stack and heap relative to data segment */ | ||
412 | ep->stp = hdr->stp - hdr->dat - sizeof(Embryo_Cell); | ||
413 | ep->hea = ep->hlw; | ||
414 | ep->stk = ep->stp; | ||
415 | } | ||
416 | |||
417 | EAPI void | ||
418 | embryo_program_vm_push(Embryo_Program *ep) | ||
419 | { | ||
420 | Embryo_Header *hdr; | ||
421 | |||
422 | if (!ep) return; | ||
423 | ep->pushes++; | ||
424 | if (ep->pushes > 1) | ||
425 | { | ||
426 | embryo_program_vm_reset(ep); | ||
427 | return; | ||
428 | } | ||
429 | hdr = (Embryo_Header *)ep->code; | ||
430 | ep->base = malloc(hdr->stp); | ||
431 | if (!ep->base) | ||
432 | { | ||
433 | ep->pushes = 0; | ||
434 | return; | ||
435 | } | ||
436 | embryo_program_vm_reset(ep); | ||
437 | } | ||
438 | |||
439 | EAPI void | ||
440 | embryo_program_vm_pop(Embryo_Program *ep) | ||
441 | { | ||
442 | if ((!ep) || (!ep->base)) return; | ||
443 | ep->pushes--; | ||
444 | if (ep->pushes >= 1) return; | ||
445 | free(ep->base); | ||
446 | ep->base = NULL; | ||
447 | } | ||
448 | |||
449 | |||
450 | EAPI void | ||
451 | embryo_swap_16(unsigned short *v | ||
452 | #ifndef WORDS_BIGENDIAN | ||
453 | __UNUSED__ | ||
454 | #endif | ||
455 | ) | ||
456 | { | ||
457 | #ifdef WORDS_BIGENDIAN | ||
458 | _embryo_byte_swap_16(v); | ||
459 | #endif | ||
460 | } | ||
461 | |||
462 | EAPI void | ||
463 | embryo_swap_32(unsigned int *v | ||
464 | #ifndef WORDS_BIGENDIAN | ||
465 | __UNUSED__ | ||
466 | #endif | ||
467 | ) | ||
468 | { | ||
469 | #ifdef WORDS_BIGENDIAN | ||
470 | _embryo_byte_swap_32(v); | ||
471 | #endif | ||
472 | } | ||
473 | |||
474 | EAPI Embryo_Function | ||
475 | embryo_program_function_find(Embryo_Program *ep, const char *name) | ||
476 | { | ||
477 | int first, last, mid, result; | ||
478 | char pname[sNAMEMAX + 1]; | ||
479 | Embryo_Header *hdr; | ||
480 | |||
481 | if (!ep) return EMBRYO_FUNCTION_NONE; | ||
482 | hdr = (Embryo_Header *)ep->code; | ||
483 | last = NUMENTRIES(hdr, publics, natives) - 1; | ||
484 | first = 0; | ||
485 | /* binary search */ | ||
486 | while (first <= last) | ||
487 | { | ||
488 | mid = (first + last) / 2; | ||
489 | if (_embryo_func_get(ep, mid, pname) == EMBRYO_ERROR_NONE) | ||
490 | result = strcmp(pname, name); | ||
491 | else | ||
492 | return EMBRYO_FUNCTION_NONE; | ||
493 | /* result = -1;*/ | ||
494 | if (result > 0) last = mid - 1; | ||
495 | else if (result < 0) first = mid + 1; | ||
496 | else return mid; | ||
497 | } | ||
498 | return EMBRYO_FUNCTION_NONE; | ||
499 | } | ||
500 | |||
501 | |||
502 | EAPI Embryo_Cell | ||
503 | embryo_program_variable_find(Embryo_Program *ep, const char *name) | ||
504 | { | ||
505 | int first, last, mid, result; | ||
506 | char pname[sNAMEMAX + 1]; | ||
507 | Embryo_Cell paddr; | ||
508 | Embryo_Header *hdr; | ||
509 | |||
510 | if (!ep) return EMBRYO_CELL_NONE; | ||
511 | if (!ep->base) return EMBRYO_CELL_NONE; | ||
512 | hdr = (Embryo_Header *)ep->base; | ||
513 | last = NUMENTRIES(hdr, pubvars, tags) - 1; | ||
514 | first = 0; | ||
515 | /* binary search */ | ||
516 | while (first <= last) | ||
517 | { | ||
518 | mid = (first + last) / 2; | ||
519 | if (_embryo_var_get(ep, mid, pname, &paddr) == EMBRYO_ERROR_NONE) | ||
520 | result = strcmp(pname, name); | ||
521 | else | ||
522 | return EMBRYO_CELL_NONE; | ||
523 | /* result = -1;*/ | ||
524 | if (result > 0) last = mid - 1; | ||
525 | else if (result < 0) first = mid + 1; | ||
526 | else return paddr; | ||
527 | } | ||
528 | return EMBRYO_CELL_NONE; | ||
529 | } | ||
530 | |||
531 | EAPI int | ||
532 | embryo_program_variable_count_get(Embryo_Program *ep) | ||
533 | { | ||
534 | Embryo_Header *hdr; | ||
535 | |||
536 | if (!ep) return 0; | ||
537 | if (!ep->base) return 0; | ||
538 | hdr = (Embryo_Header *)ep->base; | ||
539 | return NUMENTRIES(hdr, pubvars, tags); | ||
540 | } | ||
541 | |||
542 | EAPI Embryo_Cell | ||
543 | embryo_program_variable_get(Embryo_Program *ep, int num) | ||
544 | { | ||
545 | Embryo_Cell paddr; | ||
546 | char pname[sNAMEMAX + 1]; | ||
547 | |||
548 | if (!ep) return EMBRYO_CELL_NONE; | ||
549 | if (!ep->base) return EMBRYO_CELL_NONE; | ||
550 | if (_embryo_var_get(ep, num, pname, &paddr) == EMBRYO_ERROR_NONE) | ||
551 | return paddr; | ||
552 | return EMBRYO_CELL_NONE; | ||
553 | } | ||
554 | |||
555 | |||
556 | EAPI void | ||
557 | embryo_program_error_set(Embryo_Program *ep, Embryo_Error error) | ||
558 | { | ||
559 | if (!ep) return; | ||
560 | ep->error = error; | ||
561 | } | ||
562 | |||
563 | EAPI Embryo_Error | ||
564 | embryo_program_error_get(Embryo_Program *ep) | ||
565 | { | ||
566 | if (!ep) return EMBRYO_ERROR_NONE; | ||
567 | return ep->error; | ||
568 | } | ||
569 | |||
570 | |||
571 | EAPI void | ||
572 | embryo_program_data_set(Embryo_Program *ep, void *data) | ||
573 | { | ||
574 | if (!ep) return; | ||
575 | ep->data = data; | ||
576 | } | ||
577 | |||
578 | EAPI void * | ||
579 | embryo_program_data_get(Embryo_Program *ep) | ||
580 | { | ||
581 | if (!ep) return NULL; | ||
582 | return ep->data; | ||
583 | } | ||
584 | |||
585 | EAPI const char * | ||
586 | embryo_error_string_get(Embryo_Error error) | ||
587 | { | ||
588 | const char *messages[] = | ||
589 | { | ||
590 | /* EMBRYO_ERROR_NONE */ "(none)", | ||
591 | /* EMBRYO_ERROR_EXIT */ "Forced exit", | ||
592 | /* EMBRYO_ERROR_ASSERT */ "Assertion failed", | ||
593 | /* EMBRYO_ERROR_STACKERR */ "Stack/heap collision (insufficient stack size)", | ||
594 | /* EMBRYO_ERROR_BOUNDS */ "Array index out of bounds", | ||
595 | /* EMBRYO_ERROR_MEMACCESS */ "Invalid memory access", | ||
596 | /* EMBRYO_ERROR_INVINSTR */ "Invalid instruction", | ||
597 | /* EMBRYO_ERROR_STACKLOW */ "Stack underflow", | ||
598 | /* EMBRYO_ERROR_HEAPLOW */ "Heap underflow", | ||
599 | /* EMBRYO_ERROR_CALLBACK */ "No (valid) native function callback", | ||
600 | /* EMBRYO_ERROR_NATIVE */ "Native function failed", | ||
601 | /* EMBRYO_ERROR_DIVIDE */ "Divide by zero", | ||
602 | /* EMBRYO_ERROR_SLEEP */ "(sleep mode)", | ||
603 | /* 13 */ "(reserved)", | ||
604 | /* 14 */ "(reserved)", | ||
605 | /* 15 */ "(reserved)", | ||
606 | /* EMBRYO_ERROR_MEMORY */ "Out of memory", | ||
607 | /* EMBRYO_ERROR_FORMAT */ "Invalid/unsupported P-code file format", | ||
608 | /* EMBRYO_ERROR_VERSION */ "File is for a newer version of the Embryo_Program", | ||
609 | /* EMBRYO_ERROR_NOTFOUND */ "Native/Public function is not found", | ||
610 | /* EMBRYO_ERROR_INDEX */ "Invalid index parameter (bad entry point)", | ||
611 | /* EMBRYO_ERROR_DEBUG */ "Debugger cannot run", | ||
612 | /* EMBRYO_ERROR_INIT */ "Embryo_Program not initialized (or doubly initialized)", | ||
613 | /* EMBRYO_ERROR_USERDATA */ "Unable to set user data field (table full)", | ||
614 | /* EMBRYO_ERROR_INIT_JIT */ "Cannot initialize the JIT", | ||
615 | /* EMBRYO_ERROR_PARAMS */ "Parameter error", | ||
616 | }; | ||
617 | if (((int)error < 0) || | ||
618 | ((int)error >= (int)(sizeof(messages) / sizeof(messages[0])))) | ||
619 | return (const char *)"(unknown)"; | ||
620 | return messages[error]; | ||
621 | } | ||
622 | |||
623 | |||
624 | EAPI int | ||
625 | embryo_data_string_length_get(Embryo_Program *ep, Embryo_Cell *str_cell) | ||
626 | { | ||
627 | int len; | ||
628 | Embryo_Header *hdr; | ||
629 | |||
630 | if ((!ep) || (!ep->base)) return 0; | ||
631 | hdr = (Embryo_Header *)ep->base; | ||
632 | if ((!str_cell) || | ||
633 | ((void *)str_cell >= (void *)(ep->base + hdr->stp)) || | ||
634 | ((void *)str_cell < (void *)ep->base)) | ||
635 | return 0; | ||
636 | for (len = 0; str_cell[len] != 0; len++); | ||
637 | return len; | ||
638 | } | ||
639 | |||
640 | EAPI void | ||
641 | embryo_data_string_get(Embryo_Program *ep, Embryo_Cell *str_cell, char *dst) | ||
642 | { | ||
643 | int i; | ||
644 | Embryo_Header *hdr; | ||
645 | |||
646 | if (!dst) return; | ||
647 | if ((!ep) || (!ep->base)) | ||
648 | { | ||
649 | dst[0] = 0; | ||
650 | return; | ||
651 | } | ||
652 | hdr = (Embryo_Header *)ep->base; | ||
653 | if ((!str_cell) || | ||
654 | ((void *)str_cell >= (void *)(ep->base + hdr->stp)) || | ||
655 | ((void *)str_cell < (void *)ep->base)) | ||
656 | { | ||
657 | dst[0] = 0; | ||
658 | return; | ||
659 | } | ||
660 | for (i = 0; str_cell[i] != 0; i++) | ||
661 | { | ||
662 | #ifdef WORDS_BIGENDIAN | ||
663 | { | ||
664 | Embryo_Cell tmp; | ||
665 | |||
666 | tmp = str_cell[i]; | ||
667 | _embryo_byte_swap_32(&tmp); | ||
668 | dst[i] = tmp; | ||
669 | } | ||
670 | #else | ||
671 | dst[i] = str_cell[i]; | ||
672 | #endif | ||
673 | } | ||
674 | dst[i] = 0; | ||
675 | } | ||
676 | |||
677 | EAPI void | ||
678 | embryo_data_string_set(Embryo_Program *ep, const char *src, Embryo_Cell *str_cell) | ||
679 | { | ||
680 | int i; | ||
681 | Embryo_Header *hdr; | ||
682 | |||
683 | if (!ep) return; | ||
684 | if (!ep->base) return; | ||
685 | hdr = (Embryo_Header *)ep->base; | ||
686 | if ((!str_cell) || | ||
687 | ((void *)str_cell >= (void *)(ep->base + hdr->stp)) || | ||
688 | ((void *)str_cell < (void *)ep->base)) | ||
689 | return; | ||
690 | if (!src) | ||
691 | { | ||
692 | str_cell[0] = 0; | ||
693 | return; | ||
694 | } | ||
695 | for (i = 0; src[i] != 0; i++) | ||
696 | { | ||
697 | if ((void *)(&(str_cell[i])) >= (void *)(ep->base + hdr->stp)) return; | ||
698 | else if ((void *)(&(str_cell[i])) == (void *)(ep->base + hdr->stp - 1)) | ||
699 | { | ||
700 | str_cell[i] = 0; | ||
701 | return; | ||
702 | } | ||
703 | #ifdef WORDS_BIGENDIAN | ||
704 | { | ||
705 | Embryo_Cell tmp; | ||
706 | |||
707 | tmp = src[i]; | ||
708 | _embryo_byte_swap_32(&tmp); | ||
709 | str_cell[i] = tmp; | ||
710 | } | ||
711 | #else | ||
712 | str_cell[i] = src[i]; | ||
713 | #endif | ||
714 | } | ||
715 | str_cell[i] = 0; | ||
716 | } | ||
717 | |||
718 | EAPI Embryo_Cell * | ||
719 | embryo_data_address_get(Embryo_Program *ep, Embryo_Cell addr) | ||
720 | { | ||
721 | Embryo_Header *hdr; | ||
722 | unsigned char *data; | ||
723 | |||
724 | if ((!ep) || (!ep->base)) return NULL; | ||
725 | hdr = (Embryo_Header *)ep->base; | ||
726 | data = ep->base + (int)hdr->dat; | ||
727 | if ((addr < 0) || (addr >= hdr->stp)) return NULL; | ||
728 | return (Embryo_Cell *)(data + (int)addr); | ||
729 | } | ||
730 | |||
731 | |||
732 | EAPI Embryo_Cell | ||
733 | embryo_data_heap_push(Embryo_Program *ep, int cells) | ||
734 | { | ||
735 | Embryo_Header *hdr; | ||
736 | Embryo_Cell addr; | ||
737 | |||
738 | if ((!ep) || (!ep->base)) return EMBRYO_CELL_NONE; | ||
739 | hdr = (Embryo_Header *)ep->base; | ||
740 | if (ep->stk - ep->hea - (cells * sizeof(Embryo_Cell)) < STKMARGIN) | ||
741 | return EMBRYO_CELL_NONE; | ||
742 | addr = ep->hea; | ||
743 | ep->hea += (cells * sizeof(Embryo_Cell)); | ||
744 | return addr; | ||
745 | } | ||
746 | |||
747 | EAPI void | ||
748 | embryo_data_heap_pop(Embryo_Program *ep, Embryo_Cell down_to) | ||
749 | { | ||
750 | if (!ep) return; | ||
751 | if (down_to < 0) down_to = 0; | ||
752 | if (ep->hea > down_to) ep->hea = down_to; | ||
753 | } | ||
754 | |||
755 | |||
756 | EAPI int | ||
757 | embryo_program_recursion_get(Embryo_Program *ep) | ||
758 | { | ||
759 | return ep->run_count; | ||
760 | } | ||
761 | |||
762 | #ifdef __GNUC__ | ||
763 | #if 1 | ||
764 | #define EMBRYO_EXEC_JUMPTABLE | ||
765 | #endif | ||
766 | #endif | ||
767 | |||
768 | /* jump table optimization - only works for gcc though */ | ||
769 | #ifdef EMBRYO_EXEC_JUMPTABLE | ||
770 | #define SWITCH(x) while (1) { goto *switchtable[x]; | ||
771 | #define SWITCHEND break; } | ||
772 | #define CASE(x) SWITCHTABLE_##x: | ||
773 | #define BREAK break; | ||
774 | #else | ||
775 | #define SWITCH(x) switch (x) { | ||
776 | #define SWITCHEND } | ||
777 | #define CASE(x) case x: | ||
778 | #define BREAK break | ||
779 | #endif | ||
780 | |||
781 | EAPI Embryo_Status | ||
782 | embryo_program_run(Embryo_Program *ep, Embryo_Function fn) | ||
783 | { | ||
784 | Embryo_Header *hdr; | ||
785 | Embryo_Func_Stub *func; | ||
786 | unsigned char *code, *data; | ||
787 | Embryo_Cell pri, alt, stk, frm, hea, hea_start; | ||
788 | Embryo_Cell reset_stk, reset_hea, *cip; | ||
789 | Embryo_UCell codesize; | ||
790 | int i; | ||
791 | unsigned char op; | ||
792 | Embryo_Cell offs; | ||
793 | int num; | ||
794 | int max_run_cycles; | ||
795 | int cycle_count; | ||
796 | #ifdef EMBRYO_EXEC_JUMPTABLE | ||
797 | /* we limit the jumptable to 256 elements. why? above we forced "op" to be | ||
798 | * a unsigned char - that means 256 max values. we limit opcode overflow | ||
799 | * here, so eliminating crashes on table lookups with bad/corrupt bytecode. | ||
800 | * no need to atuall do compares, branches etc. the datatype does the work | ||
801 | * for us. so that means EXCESS elements are all declared as OP_NONE to | ||
802 | * keep them innocuous. | ||
803 | */ | ||
804 | static const void *switchtable[256] = | ||
805 | { | ||
806 | &&SWITCHTABLE_EMBRYO_OP_NONE, | ||
807 | &&SWITCHTABLE_EMBRYO_OP_LOAD_PRI, | ||
808 | &&SWITCHTABLE_EMBRYO_OP_LOAD_ALT, | ||
809 | &&SWITCHTABLE_EMBRYO_OP_LOAD_S_PRI, | ||
810 | &&SWITCHTABLE_EMBRYO_OP_LOAD_S_ALT, | ||
811 | &&SWITCHTABLE_EMBRYO_OP_LREF_PRI, | ||
812 | &&SWITCHTABLE_EMBRYO_OP_LREF_ALT, | ||
813 | &&SWITCHTABLE_EMBRYO_OP_LREF_S_PRI, | ||
814 | &&SWITCHTABLE_EMBRYO_OP_LREF_S_ALT, | ||
815 | &&SWITCHTABLE_EMBRYO_OP_LOAD_I, | ||
816 | &&SWITCHTABLE_EMBRYO_OP_LODB_I, | ||
817 | &&SWITCHTABLE_EMBRYO_OP_CONST_PRI, | ||
818 | &&SWITCHTABLE_EMBRYO_OP_CONST_ALT, | ||
819 | &&SWITCHTABLE_EMBRYO_OP_ADDR_PRI, | ||
820 | &&SWITCHTABLE_EMBRYO_OP_ADDR_ALT, | ||
821 | &&SWITCHTABLE_EMBRYO_OP_STOR_PRI, | ||
822 | &&SWITCHTABLE_EMBRYO_OP_STOR_ALT, | ||
823 | &&SWITCHTABLE_EMBRYO_OP_STOR_S_PRI, | ||
824 | &&SWITCHTABLE_EMBRYO_OP_STOR_S_ALT, | ||
825 | &&SWITCHTABLE_EMBRYO_OP_SREF_PRI, | ||
826 | &&SWITCHTABLE_EMBRYO_OP_SREF_ALT, | ||
827 | &&SWITCHTABLE_EMBRYO_OP_SREF_S_PRI, | ||
828 | &&SWITCHTABLE_EMBRYO_OP_SREF_S_ALT, | ||
829 | &&SWITCHTABLE_EMBRYO_OP_STOR_I, | ||
830 | &&SWITCHTABLE_EMBRYO_OP_STRB_I, | ||
831 | &&SWITCHTABLE_EMBRYO_OP_LIDX, | ||
832 | &&SWITCHTABLE_EMBRYO_OP_LIDX_B, | ||
833 | &&SWITCHTABLE_EMBRYO_OP_IDXADDR, | ||
834 | &&SWITCHTABLE_EMBRYO_OP_IDXADDR_B, | ||
835 | &&SWITCHTABLE_EMBRYO_OP_ALIGN_PRI, | ||
836 | &&SWITCHTABLE_EMBRYO_OP_ALIGN_ALT, | ||
837 | &&SWITCHTABLE_EMBRYO_OP_LCTRL, | ||
838 | &&SWITCHTABLE_EMBRYO_OP_SCTRL, | ||
839 | &&SWITCHTABLE_EMBRYO_OP_MOVE_PRI, | ||
840 | &&SWITCHTABLE_EMBRYO_OP_MOVE_ALT, | ||
841 | &&SWITCHTABLE_EMBRYO_OP_XCHG, | ||
842 | &&SWITCHTABLE_EMBRYO_OP_PUSH_PRI, | ||
843 | &&SWITCHTABLE_EMBRYO_OP_PUSH_ALT, | ||
844 | &&SWITCHTABLE_EMBRYO_OP_PUSH_R, | ||
845 | &&SWITCHTABLE_EMBRYO_OP_PUSH_C, | ||
846 | &&SWITCHTABLE_EMBRYO_OP_PUSH, | ||
847 | &&SWITCHTABLE_EMBRYO_OP_PUSH_S, | ||
848 | &&SWITCHTABLE_EMBRYO_OP_POP_PRI, | ||
849 | &&SWITCHTABLE_EMBRYO_OP_POP_ALT, | ||
850 | &&SWITCHTABLE_EMBRYO_OP_STACK, | ||
851 | &&SWITCHTABLE_EMBRYO_OP_HEAP, | ||
852 | &&SWITCHTABLE_EMBRYO_OP_PROC, | ||
853 | &&SWITCHTABLE_EMBRYO_OP_RET, | ||
854 | &&SWITCHTABLE_EMBRYO_OP_RETN, | ||
855 | &&SWITCHTABLE_EMBRYO_OP_CALL, | ||
856 | &&SWITCHTABLE_EMBRYO_OP_CALL_PRI, | ||
857 | &&SWITCHTABLE_EMBRYO_OP_JUMP, | ||
858 | &&SWITCHTABLE_EMBRYO_OP_JREL, | ||
859 | &&SWITCHTABLE_EMBRYO_OP_JZER, | ||
860 | &&SWITCHTABLE_EMBRYO_OP_JNZ, | ||
861 | &&SWITCHTABLE_EMBRYO_OP_JEQ, | ||
862 | &&SWITCHTABLE_EMBRYO_OP_JNEQ, | ||
863 | &&SWITCHTABLE_EMBRYO_OP_JLESS, | ||
864 | &&SWITCHTABLE_EMBRYO_OP_JLEQ, | ||
865 | &&SWITCHTABLE_EMBRYO_OP_JGRTR, | ||
866 | &&SWITCHTABLE_EMBRYO_OP_JGEQ, | ||
867 | &&SWITCHTABLE_EMBRYO_OP_JSLESS, | ||
868 | &&SWITCHTABLE_EMBRYO_OP_JSLEQ, | ||
869 | &&SWITCHTABLE_EMBRYO_OP_JSGRTR, | ||
870 | &&SWITCHTABLE_EMBRYO_OP_JSGEQ, | ||
871 | &&SWITCHTABLE_EMBRYO_OP_SHL, | ||
872 | &&SWITCHTABLE_EMBRYO_OP_SHR, | ||
873 | &&SWITCHTABLE_EMBRYO_OP_SSHR, | ||
874 | &&SWITCHTABLE_EMBRYO_OP_SHL_C_PRI, | ||
875 | &&SWITCHTABLE_EMBRYO_OP_SHL_C_ALT, | ||
876 | &&SWITCHTABLE_EMBRYO_OP_SHR_C_PRI, | ||
877 | &&SWITCHTABLE_EMBRYO_OP_SHR_C_ALT, | ||
878 | &&SWITCHTABLE_EMBRYO_OP_SMUL, | ||
879 | &&SWITCHTABLE_EMBRYO_OP_SDIV, | ||
880 | &&SWITCHTABLE_EMBRYO_OP_SDIV_ALT, | ||
881 | &&SWITCHTABLE_EMBRYO_OP_UMUL, | ||
882 | &&SWITCHTABLE_EMBRYO_OP_UDIV, | ||
883 | &&SWITCHTABLE_EMBRYO_OP_UDIV_ALT, | ||
884 | &&SWITCHTABLE_EMBRYO_OP_ADD, | ||
885 | &&SWITCHTABLE_EMBRYO_OP_SUB, | ||
886 | &&SWITCHTABLE_EMBRYO_OP_SUB_ALT, | ||
887 | &&SWITCHTABLE_EMBRYO_OP_AND, | ||
888 | &&SWITCHTABLE_EMBRYO_OP_OR, | ||
889 | &&SWITCHTABLE_EMBRYO_OP_XOR, | ||
890 | &&SWITCHTABLE_EMBRYO_OP_NOT, | ||
891 | &&SWITCHTABLE_EMBRYO_OP_NEG, | ||
892 | &&SWITCHTABLE_EMBRYO_OP_INVERT, | ||
893 | &&SWITCHTABLE_EMBRYO_OP_ADD_C, | ||
894 | &&SWITCHTABLE_EMBRYO_OP_SMUL_C, | ||
895 | &&SWITCHTABLE_EMBRYO_OP_ZERO_PRI, | ||
896 | &&SWITCHTABLE_EMBRYO_OP_ZERO_ALT, | ||
897 | &&SWITCHTABLE_EMBRYO_OP_ZERO, | ||
898 | &&SWITCHTABLE_EMBRYO_OP_ZERO_S, | ||
899 | &&SWITCHTABLE_EMBRYO_OP_SIGN_PRI, | ||
900 | &&SWITCHTABLE_EMBRYO_OP_SIGN_ALT, | ||
901 | &&SWITCHTABLE_EMBRYO_OP_EQ, | ||
902 | &&SWITCHTABLE_EMBRYO_OP_NEQ, | ||
903 | &&SWITCHTABLE_EMBRYO_OP_LESS, | ||
904 | &&SWITCHTABLE_EMBRYO_OP_LEQ, | ||
905 | &&SWITCHTABLE_EMBRYO_OP_GRTR, | ||
906 | &&SWITCHTABLE_EMBRYO_OP_GEQ, | ||
907 | &&SWITCHTABLE_EMBRYO_OP_SLESS, | ||
908 | &&SWITCHTABLE_EMBRYO_OP_SLEQ, | ||
909 | &&SWITCHTABLE_EMBRYO_OP_SGRTR, | ||
910 | &&SWITCHTABLE_EMBRYO_OP_SGEQ, | ||
911 | &&SWITCHTABLE_EMBRYO_OP_EQ_C_PRI, | ||
912 | &&SWITCHTABLE_EMBRYO_OP_EQ_C_ALT, | ||
913 | &&SWITCHTABLE_EMBRYO_OP_INC_PRI, | ||
914 | &&SWITCHTABLE_EMBRYO_OP_INC_ALT, | ||
915 | &&SWITCHTABLE_EMBRYO_OP_INC, | ||
916 | &&SWITCHTABLE_EMBRYO_OP_INC_S, | ||
917 | &&SWITCHTABLE_EMBRYO_OP_INC_I, | ||
918 | &&SWITCHTABLE_EMBRYO_OP_DEC_PRI, | ||
919 | &&SWITCHTABLE_EMBRYO_OP_DEC_ALT, | ||
920 | &&SWITCHTABLE_EMBRYO_OP_DEC, | ||
921 | &&SWITCHTABLE_EMBRYO_OP_DEC_S, | ||
922 | &&SWITCHTABLE_EMBRYO_OP_DEC_I, | ||
923 | &&SWITCHTABLE_EMBRYO_OP_MOVS, | ||
924 | &&SWITCHTABLE_EMBRYO_OP_CMPS, | ||
925 | &&SWITCHTABLE_EMBRYO_OP_FILL, | ||
926 | &&SWITCHTABLE_EMBRYO_OP_HALT, | ||
927 | &&SWITCHTABLE_EMBRYO_OP_BOUNDS, | ||
928 | &&SWITCHTABLE_EMBRYO_OP_SYSREQ_PRI, | ||
929 | &&SWITCHTABLE_EMBRYO_OP_SYSREQ_C, | ||
930 | &&SWITCHTABLE_EMBRYO_OP_FILE, | ||
931 | &&SWITCHTABLE_EMBRYO_OP_LINE, | ||
932 | &&SWITCHTABLE_EMBRYO_OP_SYMBOL, | ||
933 | &&SWITCHTABLE_EMBRYO_OP_SRANGE, | ||
934 | &&SWITCHTABLE_EMBRYO_OP_JUMP_PRI, | ||
935 | &&SWITCHTABLE_EMBRYO_OP_SWITCH, | ||
936 | &&SWITCHTABLE_EMBRYO_OP_CASETBL, | ||
937 | &&SWITCHTABLE_EMBRYO_OP_SWAP_PRI, | ||
938 | &&SWITCHTABLE_EMBRYO_OP_SWAP_ALT, | ||
939 | &&SWITCHTABLE_EMBRYO_OP_PUSHADDR, | ||
940 | &&SWITCHTABLE_EMBRYO_OP_NOP, | ||
941 | &&SWITCHTABLE_EMBRYO_OP_SYSREQ_D, | ||
942 | &&SWITCHTABLE_EMBRYO_OP_SYMTAG, | ||
943 | &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, | ||
944 | &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, | ||
945 | &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, | ||
946 | &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, | ||
947 | &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, | ||
948 | &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, | ||
949 | &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, | ||
950 | &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, | ||
951 | &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, | ||
952 | &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, | ||
953 | &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, | ||
954 | &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, | ||
955 | &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, | ||
956 | &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, | ||
957 | &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, | ||
958 | &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, | ||
959 | &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, | ||
960 | &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, | ||
961 | &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, | ||
962 | &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, | ||
963 | &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, | ||
964 | &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, | ||
965 | &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, | ||
966 | &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE | ||
967 | }; | ||
968 | #endif | ||
969 | if (!ep) return EMBRYO_PROGRAM_FAIL; | ||
970 | if (!(ep->flags & EMBRYO_FLAG_RELOC)) | ||
971 | { | ||
972 | ep->error = EMBRYO_ERROR_INIT; | ||
973 | return EMBRYO_PROGRAM_FAIL; | ||
974 | } | ||
975 | if (!ep->base) | ||
976 | { | ||
977 | ep->error = EMBRYO_ERROR_INIT; | ||
978 | return EMBRYO_PROGRAM_FAIL; | ||
979 | } | ||
980 | if (ep->run_count > 0) | ||
981 | { | ||
982 | /* return EMBRYO_PROGRAM_BUSY; */ | ||
983 | /* FIXME: test C->vm->C->vm recursion more fully */ | ||
984 | /* it seems to work... just fine!!! - strange! */ | ||
985 | } | ||
986 | |||
987 | /* set up the registers */ | ||
988 | hdr = (Embryo_Header *)ep->base; | ||
989 | codesize = (Embryo_UCell)(hdr->dat - hdr->cod); | ||
990 | code = ep->base + (int)hdr->cod; | ||
991 | data = ep->base + (int)hdr->dat; | ||
992 | hea_start = hea = ep->hea; | ||
993 | stk = ep->stk; | ||
994 | reset_stk = stk; | ||
995 | reset_hea = hea; | ||
996 | frm = alt = pri = 0; | ||
997 | |||
998 | /* get the start address */ | ||
999 | if (fn == EMBRYO_FUNCTION_MAIN) | ||
1000 | { | ||
1001 | if (hdr->cip < 0) | ||
1002 | { | ||
1003 | ep->error = EMBRYO_ERROR_INDEX; | ||
1004 | return EMBRYO_PROGRAM_FAIL; | ||
1005 | } | ||
1006 | cip = (Embryo_Cell *)(code + (int)hdr->cip); | ||
1007 | } | ||
1008 | else if (fn == EMBRYO_FUNCTION_CONT) | ||
1009 | { | ||
1010 | /* all registers: pri, alt, frm, cip, hea, stk, reset_stk, reset_hea */ | ||
1011 | frm = ep->frm; | ||
1012 | stk = ep->stk; | ||
1013 | hea = ep->hea; | ||
1014 | pri = ep->pri; | ||
1015 | alt = ep->alt; | ||
1016 | reset_stk = ep->reset_stk; | ||
1017 | reset_hea = ep->reset_hea; | ||
1018 | cip = (Embryo_Cell *)(code + (int)ep->cip); | ||
1019 | } | ||
1020 | else if (fn < 0) | ||
1021 | { | ||
1022 | ep->error = EMBRYO_ERROR_INDEX; | ||
1023 | return EMBRYO_PROGRAM_FAIL; | ||
1024 | } | ||
1025 | else | ||
1026 | { | ||
1027 | if (fn >= (Embryo_Cell)NUMENTRIES(hdr, publics, natives)) | ||
1028 | { | ||
1029 | ep->error = EMBRYO_ERROR_INDEX; | ||
1030 | return EMBRYO_PROGRAM_FAIL; | ||
1031 | } | ||
1032 | func = GETENTRY(hdr, publics, fn); | ||
1033 | cip = (Embryo_Cell *)(code + (int)func->address); | ||
1034 | } | ||
1035 | /* check values just copied */ | ||
1036 | CHKSTACK(); | ||
1037 | CHKHEAP(); | ||
1038 | |||
1039 | if (fn != EMBRYO_FUNCTION_CONT) | ||
1040 | { | ||
1041 | int i; | ||
1042 | |||
1043 | for (i = ep->params_size - 1; i >= 0; i--) | ||
1044 | { | ||
1045 | Embryo_Param *pr; | ||
1046 | |||
1047 | pr = &(ep->params[i]); | ||
1048 | if (pr->string) | ||
1049 | { | ||
1050 | int len; | ||
1051 | Embryo_Cell ep_addr, *addr; | ||
1052 | |||
1053 | len = strlen(pr->string); | ||
1054 | ep_addr = embryo_data_heap_push(ep, len + 1); | ||
1055 | if (ep_addr == EMBRYO_CELL_NONE) | ||
1056 | { | ||
1057 | ep->error = EMBRYO_ERROR_HEAPLOW; | ||
1058 | return EMBRYO_PROGRAM_FAIL; | ||
1059 | } | ||
1060 | addr = embryo_data_address_get(ep, ep_addr); | ||
1061 | if (addr) | ||
1062 | embryo_data_string_set(ep, pr->string, addr); | ||
1063 | else | ||
1064 | { | ||
1065 | ep->error = EMBRYO_ERROR_HEAPLOW; | ||
1066 | return EMBRYO_PROGRAM_FAIL; | ||
1067 | } | ||
1068 | PUSH(ep_addr); | ||
1069 | free(pr->string); | ||
1070 | } | ||
1071 | else if (pr->cell_array) | ||
1072 | { | ||
1073 | int len; | ||
1074 | Embryo_Cell ep_addr, *addr; | ||
1075 | |||
1076 | len = pr->cell_array_size; | ||
1077 | ep_addr = embryo_data_heap_push(ep, len + 1); | ||
1078 | if (ep_addr == EMBRYO_CELL_NONE) | ||
1079 | { | ||
1080 | ep->error = EMBRYO_ERROR_HEAPLOW; | ||
1081 | return EMBRYO_PROGRAM_FAIL; | ||
1082 | } | ||
1083 | addr = embryo_data_address_get(ep, ep_addr); | ||
1084 | if (addr) | ||
1085 | memcpy(addr, pr->cell_array, | ||
1086 | pr->cell_array_size * sizeof(Embryo_Cell)); | ||
1087 | else | ||
1088 | { | ||
1089 | ep->error = EMBRYO_ERROR_HEAPLOW; | ||
1090 | return EMBRYO_PROGRAM_FAIL; | ||
1091 | } | ||
1092 | PUSH(ep_addr); | ||
1093 | free(pr->cell_array); | ||
1094 | } | ||
1095 | else | ||
1096 | { | ||
1097 | PUSH(pr->cell); | ||
1098 | } | ||
1099 | } | ||
1100 | PUSH(ep->params_size * sizeof(Embryo_Cell)); | ||
1101 | PUSH(0); | ||
1102 | if (ep->params) | ||
1103 | { | ||
1104 | free(ep->params); | ||
1105 | ep->params = NULL; | ||
1106 | } | ||
1107 | ep->params_size = ep->params_alloc = 0; | ||
1108 | } | ||
1109 | /* check stack/heap before starting to run */ | ||
1110 | CHKMARGIN(); | ||
1111 | |||
1112 | /* track recursion depth */ | ||
1113 | ep->run_count++; | ||
1114 | |||
1115 | max_run_cycles = ep->max_run_cycles; | ||
1116 | /* start running */ | ||
1117 | for (cycle_count = 0;;) | ||
1118 | { | ||
1119 | if (max_run_cycles > 0) | ||
1120 | { | ||
1121 | if (cycle_count >= max_run_cycles) | ||
1122 | { | ||
1123 | TOOLONG(ep); | ||
1124 | } | ||
1125 | cycle_count++; | ||
1126 | } | ||
1127 | op = (Embryo_Opcode)*cip++; | ||
1128 | SWITCH(op); | ||
1129 | CASE(EMBRYO_OP_LOAD_PRI); | ||
1130 | GETPARAM(offs); | ||
1131 | pri = *(Embryo_Cell *)(data + (int)offs); | ||
1132 | BREAK; | ||
1133 | CASE(EMBRYO_OP_LOAD_ALT); | ||
1134 | GETPARAM(offs); | ||
1135 | alt = *(Embryo_Cell *)(data + (int)offs); | ||
1136 | BREAK; | ||
1137 | CASE(EMBRYO_OP_LOAD_S_PRI); | ||
1138 | GETPARAM(offs); | ||
1139 | pri = *(Embryo_Cell *)(data + (int)frm + (int)offs); | ||
1140 | BREAK; | ||
1141 | CASE(EMBRYO_OP_LOAD_S_ALT); | ||
1142 | GETPARAM(offs); | ||
1143 | alt = *(Embryo_Cell *)(data + (int)frm + (int)offs); | ||
1144 | BREAK; | ||
1145 | CASE(EMBRYO_OP_LREF_PRI); | ||
1146 | GETPARAM(offs); | ||
1147 | offs = *(Embryo_Cell *)(data + (int)offs); | ||
1148 | pri = *(Embryo_Cell *)(data + (int)offs); | ||
1149 | BREAK; | ||
1150 | CASE(EMBRYO_OP_LREF_ALT); | ||
1151 | GETPARAM(offs); | ||
1152 | offs = *(Embryo_Cell *)(data + (int)offs); | ||
1153 | alt = *(Embryo_Cell *)(data + (int)offs); | ||
1154 | BREAK; | ||
1155 | CASE(EMBRYO_OP_LREF_S_PRI); | ||
1156 | GETPARAM(offs); | ||
1157 | offs = *(Embryo_Cell *)(data + (int)frm + (int)offs); | ||
1158 | pri = *(Embryo_Cell *)(data + (int)offs); | ||
1159 | BREAK; | ||
1160 | CASE(EMBRYO_OP_LREF_S_ALT); | ||
1161 | GETPARAM(offs); | ||
1162 | offs = *(Embryo_Cell *)(data + (int)frm + (int)offs); | ||
1163 | alt = *(Embryo_Cell *)(data + (int)offs); | ||
1164 | BREAK; | ||
1165 | CASE(EMBRYO_OP_LOAD_I); | ||
1166 | CHKMEM(pri); | ||
1167 | pri = *(Embryo_Cell *)(data + (int)pri); | ||
1168 | BREAK; | ||
1169 | CASE(EMBRYO_OP_LODB_I); | ||
1170 | GETPARAM(offs); | ||
1171 | CHKMEM(pri); | ||
1172 | switch (offs) | ||
1173 | { | ||
1174 | case 1: | ||
1175 | pri = *(data + (int)pri); | ||
1176 | break; | ||
1177 | case 2: | ||
1178 | pri = *(unsigned short *)(data + (int)pri); | ||
1179 | break; | ||
1180 | case 4: | ||
1181 | pri = *(unsigned int *)(data + (int)pri); | ||
1182 | break; | ||
1183 | default: | ||
1184 | ABORT(ep, EMBRYO_ERROR_INVINSTR); | ||
1185 | break; | ||
1186 | } | ||
1187 | BREAK; | ||
1188 | CASE(EMBRYO_OP_CONST_PRI); | ||
1189 | GETPARAM(pri); | ||
1190 | BREAK; | ||
1191 | CASE(EMBRYO_OP_CONST_ALT); | ||
1192 | GETPARAM(alt); | ||
1193 | BREAK; | ||
1194 | CASE(EMBRYO_OP_ADDR_PRI); | ||
1195 | GETPARAM(pri); | ||
1196 | pri += frm; | ||
1197 | BREAK; | ||
1198 | CASE(EMBRYO_OP_ADDR_ALT); | ||
1199 | GETPARAM(alt); | ||
1200 | alt += frm; | ||
1201 | BREAK; | ||
1202 | CASE(EMBRYO_OP_STOR_PRI); | ||
1203 | GETPARAM(offs); | ||
1204 | *(Embryo_Cell *)(data + (int)offs) = pri; | ||
1205 | BREAK; | ||
1206 | CASE(EMBRYO_OP_STOR_ALT); | ||
1207 | GETPARAM(offs); | ||
1208 | *(Embryo_Cell *)(data + (int)offs) = alt; | ||
1209 | BREAK; | ||
1210 | CASE(EMBRYO_OP_STOR_S_PRI); | ||
1211 | GETPARAM(offs); | ||
1212 | *(Embryo_Cell *)(data + (int)frm + (int)offs) = pri; | ||
1213 | BREAK; | ||
1214 | CASE(EMBRYO_OP_STOR_S_ALT); | ||
1215 | GETPARAM(offs); | ||
1216 | *(Embryo_Cell *)(data + (int)frm + (int)offs) = alt; | ||
1217 | BREAK; | ||
1218 | CASE(EMBRYO_OP_SREF_PRI); | ||
1219 | GETPARAM(offs); | ||
1220 | offs = *(Embryo_Cell *)(data + (int)offs); | ||
1221 | *(Embryo_Cell *)(data + (int)offs) = pri; | ||
1222 | BREAK; | ||
1223 | CASE(EMBRYO_OP_SREF_ALT); | ||
1224 | GETPARAM(offs); | ||
1225 | offs = *(Embryo_Cell *)(data + (int)offs); | ||
1226 | *(Embryo_Cell *)(data + (int)offs) = alt; | ||
1227 | BREAK; | ||
1228 | CASE(EMBRYO_OP_SREF_S_PRI); | ||
1229 | GETPARAM(offs); | ||
1230 | offs = *(Embryo_Cell *)(data + (int)frm + (int)offs); | ||
1231 | *(Embryo_Cell *)(data + (int)offs) = pri; | ||
1232 | BREAK; | ||
1233 | CASE(EMBRYO_OP_SREF_S_ALT); | ||
1234 | GETPARAM(offs); | ||
1235 | offs = *(Embryo_Cell *)(data + (int)frm + (int)offs); | ||
1236 | *(Embryo_Cell *)(data + (int)offs) = alt; | ||
1237 | BREAK; | ||
1238 | CASE(EMBRYO_OP_STOR_I); | ||
1239 | CHKMEM(alt); | ||
1240 | *(Embryo_Cell *)(data + (int)alt) = pri; | ||
1241 | BREAK; | ||
1242 | CASE(EMBRYO_OP_STRB_I); | ||
1243 | GETPARAM(offs); | ||
1244 | CHKMEM(alt); | ||
1245 | switch (offs) | ||
1246 | { | ||
1247 | case 1: | ||
1248 | *(data + (int)alt) = (unsigned char)pri; | ||
1249 | break; | ||
1250 | case 2: | ||
1251 | *(unsigned short *)(data + (int)alt) = (unsigned short)pri; | ||
1252 | break; | ||
1253 | case 4: | ||
1254 | *(unsigned int *)(data + (int)alt) = (unsigned int)pri; | ||
1255 | break; | ||
1256 | default: | ||
1257 | ABORT(ep, EMBRYO_ERROR_INVINSTR); | ||
1258 | break; | ||
1259 | } | ||
1260 | BREAK; | ||
1261 | CASE(EMBRYO_OP_LIDX); | ||
1262 | offs = (pri * sizeof(Embryo_Cell)) + alt; | ||
1263 | CHKMEM(offs); | ||
1264 | pri = *(Embryo_Cell *)(data + (int)offs); | ||
1265 | BREAK; | ||
1266 | CASE(EMBRYO_OP_LIDX_B); | ||
1267 | GETPARAM(offs); | ||
1268 | offs = (pri << (int)offs) + alt; | ||
1269 | CHKMEM(offs); | ||
1270 | pri = *(Embryo_Cell *)(data + (int)offs); | ||
1271 | BREAK; | ||
1272 | CASE(EMBRYO_OP_IDXADDR); | ||
1273 | pri = (pri * sizeof(Embryo_Cell)) + alt; | ||
1274 | BREAK; | ||
1275 | CASE(EMBRYO_OP_IDXADDR_B); | ||
1276 | GETPARAM(offs); | ||
1277 | pri = (pri << (int)offs) + alt; | ||
1278 | BREAK; | ||
1279 | CASE(EMBRYO_OP_ALIGN_PRI); | ||
1280 | GETPARAM(offs); | ||
1281 | #ifdef WORDS_BIGENDIAN | ||
1282 | if ((size_t)offs < sizeof(Embryo_Cell)) | ||
1283 | pri ^= sizeof(Embryo_Cell) - offs; | ||
1284 | #endif | ||
1285 | BREAK; | ||
1286 | CASE(EMBRYO_OP_ALIGN_ALT); | ||
1287 | GETPARAM(offs); | ||
1288 | #ifdef WORDS_BIGENDIAN | ||
1289 | if ((size_t)offs < sizeof(Embryo_Cell)) | ||
1290 | alt ^= sizeof(Embryo_Cell) - offs; | ||
1291 | #endif | ||
1292 | BREAK; | ||
1293 | CASE(EMBRYO_OP_LCTRL); | ||
1294 | GETPARAM(offs); | ||
1295 | switch (offs) | ||
1296 | { | ||
1297 | case 0: | ||
1298 | pri = hdr->cod; | ||
1299 | break; | ||
1300 | case 1: | ||
1301 | pri = hdr->dat; | ||
1302 | break; | ||
1303 | case 2: | ||
1304 | pri = hea; | ||
1305 | break; | ||
1306 | case 3: | ||
1307 | pri = ep->stp; | ||
1308 | break; | ||
1309 | case 4: | ||
1310 | pri = stk; | ||
1311 | break; | ||
1312 | case 5: | ||
1313 | pri = frm; | ||
1314 | break; | ||
1315 | case 6: | ||
1316 | pri = (Embryo_Cell)((unsigned char *)cip - code); | ||
1317 | break; | ||
1318 | default: | ||
1319 | ABORT(ep, EMBRYO_ERROR_INVINSTR); | ||
1320 | break; | ||
1321 | } | ||
1322 | BREAK; | ||
1323 | CASE(EMBRYO_OP_SCTRL); | ||
1324 | GETPARAM(offs); | ||
1325 | switch (offs) | ||
1326 | { | ||
1327 | case 0: | ||
1328 | case 1: | ||
1329 | case 2: | ||
1330 | hea = pri; | ||
1331 | break; | ||
1332 | case 3: | ||
1333 | /* cannot change these parameters */ | ||
1334 | break; | ||
1335 | case 4: | ||
1336 | stk = pri; | ||
1337 | break; | ||
1338 | case 5: | ||
1339 | frm = pri; | ||
1340 | break; | ||
1341 | case 6: | ||
1342 | cip = (Embryo_Cell *)(code + (int)pri); | ||
1343 | break; | ||
1344 | default: | ||
1345 | ABORT(ep, EMBRYO_ERROR_INVINSTR); | ||
1346 | break; | ||
1347 | } | ||
1348 | BREAK; | ||
1349 | CASE(EMBRYO_OP_MOVE_PRI); | ||
1350 | pri = alt; | ||
1351 | BREAK; | ||
1352 | CASE(EMBRYO_OP_MOVE_ALT); | ||
1353 | alt = pri; | ||
1354 | BREAK; | ||
1355 | CASE(EMBRYO_OP_XCHG); | ||
1356 | offs = pri; /* offs is a temporary variable */ | ||
1357 | pri = alt; | ||
1358 | alt = offs; | ||
1359 | BREAK; | ||
1360 | CASE(EMBRYO_OP_PUSH_PRI); | ||
1361 | PUSH(pri); | ||
1362 | BREAK; | ||
1363 | CASE(EMBRYO_OP_PUSH_ALT); | ||
1364 | PUSH(alt); | ||
1365 | BREAK; | ||
1366 | CASE(EMBRYO_OP_PUSH_C); | ||
1367 | GETPARAM(offs); | ||
1368 | PUSH(offs); | ||
1369 | BREAK; | ||
1370 | CASE(EMBRYO_OP_PUSH_R); | ||
1371 | GETPARAM(offs); | ||
1372 | while (offs--) PUSH(pri); | ||
1373 | BREAK; | ||
1374 | CASE(EMBRYO_OP_PUSH); | ||
1375 | GETPARAM(offs); | ||
1376 | PUSH(*(Embryo_Cell *)(data + (int)offs)); | ||
1377 | BREAK; | ||
1378 | CASE(EMBRYO_OP_PUSH_S); | ||
1379 | GETPARAM(offs); | ||
1380 | PUSH(*(Embryo_Cell *)(data + (int)frm + (int)offs)); | ||
1381 | BREAK; | ||
1382 | CASE(EMBRYO_OP_POP_PRI); | ||
1383 | POP(pri); | ||
1384 | BREAK; | ||
1385 | CASE(EMBRYO_OP_POP_ALT); | ||
1386 | POP(alt); | ||
1387 | BREAK; | ||
1388 | CASE(EMBRYO_OP_STACK); | ||
1389 | GETPARAM(offs); | ||
1390 | alt = stk; | ||
1391 | stk += offs; | ||
1392 | CHKMARGIN(); | ||
1393 | CHKSTACK(); | ||
1394 | BREAK; | ||
1395 | CASE(EMBRYO_OP_HEAP); | ||
1396 | GETPARAM(offs); | ||
1397 | alt = hea; | ||
1398 | hea += offs; | ||
1399 | CHKMARGIN(); | ||
1400 | CHKHEAP(); | ||
1401 | BREAK; | ||
1402 | CASE(EMBRYO_OP_PROC); | ||
1403 | PUSH(frm); | ||
1404 | frm = stk; | ||
1405 | CHKMARGIN(); | ||
1406 | BREAK; | ||
1407 | CASE(EMBRYO_OP_RET); | ||
1408 | POP(frm); | ||
1409 | POP(offs); | ||
1410 | if ((Embryo_UCell)offs >= codesize) | ||
1411 | ABORT(ep, EMBRYO_ERROR_MEMACCESS); | ||
1412 | cip = (Embryo_Cell *)(code + (int)offs); | ||
1413 | BREAK; | ||
1414 | CASE(EMBRYO_OP_RETN); | ||
1415 | POP(frm); | ||
1416 | POP(offs); | ||
1417 | if ((Embryo_UCell)offs >= codesize) | ||
1418 | ABORT(ep, EMBRYO_ERROR_MEMACCESS); | ||
1419 | cip = (Embryo_Cell *)(code + (int)offs); | ||
1420 | stk += *(Embryo_Cell *)(data + (int)stk) + sizeof(Embryo_Cell); /* remove parameters from the stack */ | ||
1421 | ep->stk = stk; | ||
1422 | BREAK; | ||
1423 | CASE(EMBRYO_OP_CALL); | ||
1424 | PUSH(((unsigned char *)cip - code) + sizeof(Embryo_Cell));/* skip address */ | ||
1425 | cip = JUMPABS(code, cip); /* jump to the address */ | ||
1426 | BREAK; | ||
1427 | CASE(EMBRYO_OP_CALL_PRI); | ||
1428 | PUSH((unsigned char *)cip - code); | ||
1429 | cip = (Embryo_Cell *)(code + (int)pri); | ||
1430 | BREAK; | ||
1431 | CASE(EMBRYO_OP_JUMP); | ||
1432 | /* since the GETPARAM() macro modifies cip, you cannot | ||
1433 | * do GETPARAM(cip) directly */ | ||
1434 | cip = JUMPABS(code, cip); | ||
1435 | BREAK; | ||
1436 | CASE(EMBRYO_OP_JREL); | ||
1437 | offs = *cip; | ||
1438 | cip = (Embryo_Cell *)((unsigned char *)cip + (int)offs + sizeof(Embryo_Cell)); | ||
1439 | BREAK; | ||
1440 | CASE(EMBRYO_OP_JZER); | ||
1441 | if (pri == 0) | ||
1442 | cip = JUMPABS(code, cip); | ||
1443 | else | ||
1444 | cip = (Embryo_Cell *)((unsigned char *)cip + sizeof(Embryo_Cell)); | ||
1445 | BREAK; | ||
1446 | CASE(EMBRYO_OP_JNZ); | ||
1447 | if (pri != 0) | ||
1448 | cip = JUMPABS(code, cip); | ||
1449 | else | ||
1450 | cip = (Embryo_Cell *)((unsigned char *)cip + sizeof(Embryo_Cell)); | ||
1451 | BREAK; | ||
1452 | CASE(EMBRYO_OP_JEQ); | ||
1453 | if (pri==alt) | ||
1454 | cip = JUMPABS(code, cip); | ||
1455 | else | ||
1456 | cip = (Embryo_Cell *)((unsigned char *)cip + sizeof(Embryo_Cell)); | ||
1457 | BREAK; | ||
1458 | CASE(EMBRYO_OP_JNEQ); | ||
1459 | if (pri != alt) | ||
1460 | cip = JUMPABS(code, cip); | ||
1461 | else | ||
1462 | cip = (Embryo_Cell *)((unsigned char *)cip + sizeof(Embryo_Cell)); | ||
1463 | BREAK; | ||
1464 | CASE(EMBRYO_OP_JLESS); | ||
1465 | if ((Embryo_UCell)pri < (Embryo_UCell)alt) | ||
1466 | cip = JUMPABS(code, cip); | ||
1467 | else | ||
1468 | cip = (Embryo_Cell *)((unsigned char *)cip + sizeof(Embryo_Cell)); | ||
1469 | BREAK; | ||
1470 | CASE(EMBRYO_OP_JLEQ); | ||
1471 | if ((Embryo_UCell)pri <= (Embryo_UCell)alt) | ||
1472 | cip = JUMPABS(code, cip); | ||
1473 | else | ||
1474 | cip = (Embryo_Cell *)((unsigned char *)cip + sizeof(Embryo_Cell)); | ||
1475 | BREAK; | ||
1476 | CASE(EMBRYO_OP_JGRTR); | ||
1477 | if ((Embryo_UCell)pri > (Embryo_UCell)alt) | ||
1478 | cip = JUMPABS(code, cip); | ||
1479 | else | ||
1480 | cip = (Embryo_Cell *)((unsigned char *)cip + sizeof(Embryo_Cell)); | ||
1481 | BREAK; | ||
1482 | CASE(EMBRYO_OP_JGEQ); | ||
1483 | if ((Embryo_UCell)pri >= (Embryo_UCell)alt) | ||
1484 | cip = JUMPABS(code, cip); | ||
1485 | else | ||
1486 | cip = (Embryo_Cell *)((unsigned char *)cip + sizeof(Embryo_Cell)); | ||
1487 | BREAK; | ||
1488 | CASE(EMBRYO_OP_JSLESS); | ||
1489 | if (pri < alt) | ||
1490 | cip = JUMPABS(code, cip); | ||
1491 | else | ||
1492 | cip = (Embryo_Cell *)((unsigned char *)cip + sizeof(Embryo_Cell)); | ||
1493 | BREAK; | ||
1494 | CASE(EMBRYO_OP_JSLEQ); | ||
1495 | if (pri <= alt) | ||
1496 | cip = JUMPABS(code, cip); | ||
1497 | else | ||
1498 | cip = (Embryo_Cell *)((unsigned char *)cip + sizeof(Embryo_Cell)); | ||
1499 | BREAK; | ||
1500 | CASE(EMBRYO_OP_JSGRTR); | ||
1501 | if (pri > alt) | ||
1502 | cip = JUMPABS(code, cip); | ||
1503 | else | ||
1504 | cip = (Embryo_Cell *)((unsigned char *)cip + sizeof(Embryo_Cell)); | ||
1505 | BREAK; | ||
1506 | CASE(EMBRYO_OP_JSGEQ); | ||
1507 | if (pri >= alt) | ||
1508 | cip = JUMPABS(code, cip); | ||
1509 | else | ||
1510 | cip = (Embryo_Cell *)((unsigned char *)cip + sizeof(Embryo_Cell)); | ||
1511 | BREAK; | ||
1512 | CASE(EMBRYO_OP_SHL); | ||
1513 | pri <<= alt; | ||
1514 | BREAK; | ||
1515 | CASE(EMBRYO_OP_SHR); | ||
1516 | pri = (Embryo_UCell)pri >> (int)alt; | ||
1517 | BREAK; | ||
1518 | CASE(EMBRYO_OP_SSHR); | ||
1519 | pri >>= alt; | ||
1520 | BREAK; | ||
1521 | CASE(EMBRYO_OP_SHL_C_PRI); | ||
1522 | GETPARAM(offs); | ||
1523 | pri <<= offs; | ||
1524 | BREAK; | ||
1525 | CASE(EMBRYO_OP_SHL_C_ALT); | ||
1526 | GETPARAM(offs); | ||
1527 | alt <<= offs; | ||
1528 | BREAK; | ||
1529 | CASE(EMBRYO_OP_SHR_C_PRI); | ||
1530 | GETPARAM(offs); | ||
1531 | pri = (Embryo_UCell)pri >> (int)offs; | ||
1532 | BREAK; | ||
1533 | CASE(EMBRYO_OP_SHR_C_ALT); | ||
1534 | GETPARAM(offs); | ||
1535 | alt = (Embryo_UCell)alt >> (int)offs; | ||
1536 | BREAK; | ||
1537 | CASE(EMBRYO_OP_SMUL); | ||
1538 | pri *= alt; | ||
1539 | BREAK; | ||
1540 | CASE(EMBRYO_OP_SDIV); | ||
1541 | if (alt == 0) ABORT(ep, EMBRYO_ERROR_DIVIDE); | ||
1542 | /* divide must always round down; this is a bit | ||
1543 | * involved to do in a machine-independent way. | ||
1544 | */ | ||
1545 | offs = ((pri % alt) + alt) % alt; /* true modulus */ | ||
1546 | pri = (pri - offs) / alt; /* division result */ | ||
1547 | alt = offs; | ||
1548 | BREAK; | ||
1549 | CASE(EMBRYO_OP_SDIV_ALT); | ||
1550 | if (pri == 0) ABORT(ep, EMBRYO_ERROR_DIVIDE); | ||
1551 | /* divide must always round down; this is a bit | ||
1552 | * involved to do in a machine-independent way. | ||
1553 | */ | ||
1554 | offs = ((alt % pri) + pri) % pri; /* true modulus */ | ||
1555 | pri = (alt - offs) / pri; /* division result */ | ||
1556 | alt = offs; | ||
1557 | BREAK; | ||
1558 | CASE(EMBRYO_OP_UMUL); | ||
1559 | pri = (Embryo_UCell)pri * (Embryo_UCell)alt; | ||
1560 | BREAK; | ||
1561 | CASE(EMBRYO_OP_UDIV); | ||
1562 | if (alt == 0) ABORT(ep, EMBRYO_ERROR_DIVIDE); | ||
1563 | offs = (Embryo_UCell)pri % (Embryo_UCell)alt; /* temporary storage */ | ||
1564 | pri = (Embryo_UCell)pri / (Embryo_UCell)alt; | ||
1565 | alt = offs; | ||
1566 | BREAK; | ||
1567 | CASE(EMBRYO_OP_UDIV_ALT); | ||
1568 | if (pri == 0) ABORT(ep, EMBRYO_ERROR_DIVIDE); | ||
1569 | offs = (Embryo_UCell)alt % (Embryo_UCell)pri; /* temporary storage */ | ||
1570 | pri = (Embryo_UCell)alt / (Embryo_UCell)pri; | ||
1571 | alt = offs; | ||
1572 | BREAK; | ||
1573 | CASE(EMBRYO_OP_ADD); | ||
1574 | pri += alt; | ||
1575 | BREAK; | ||
1576 | CASE(EMBRYO_OP_SUB); | ||
1577 | pri -= alt; | ||
1578 | BREAK; | ||
1579 | CASE(EMBRYO_OP_SUB_ALT); | ||
1580 | pri = alt - pri; | ||
1581 | BREAK; | ||
1582 | CASE(EMBRYO_OP_AND); | ||
1583 | pri &= alt; | ||
1584 | BREAK; | ||
1585 | CASE(EMBRYO_OP_OR); | ||
1586 | pri |= alt; | ||
1587 | BREAK; | ||
1588 | CASE(EMBRYO_OP_XOR); | ||
1589 | pri ^= alt; | ||
1590 | BREAK; | ||
1591 | CASE(EMBRYO_OP_NOT); | ||
1592 | pri = !pri; | ||
1593 | BREAK; | ||
1594 | CASE(EMBRYO_OP_NEG); | ||
1595 | pri = -pri; | ||
1596 | BREAK; | ||
1597 | CASE(EMBRYO_OP_INVERT); | ||
1598 | pri = ~pri; | ||
1599 | BREAK; | ||
1600 | CASE(EMBRYO_OP_ADD_C); | ||
1601 | GETPARAM(offs); | ||
1602 | pri += offs; | ||
1603 | BREAK; | ||
1604 | CASE(EMBRYO_OP_SMUL_C); | ||
1605 | GETPARAM(offs); | ||
1606 | pri *= offs; | ||
1607 | BREAK; | ||
1608 | CASE(EMBRYO_OP_ZERO_PRI); | ||
1609 | pri = 0; | ||
1610 | BREAK; | ||
1611 | CASE(EMBRYO_OP_ZERO_ALT); | ||
1612 | alt = 0; | ||
1613 | BREAK; | ||
1614 | CASE(EMBRYO_OP_ZERO); | ||
1615 | GETPARAM(offs); | ||
1616 | *(Embryo_Cell *)(data + (int)offs) = 0; | ||
1617 | BREAK; | ||
1618 | CASE(EMBRYO_OP_ZERO_S); | ||
1619 | GETPARAM(offs); | ||
1620 | *(Embryo_Cell *)(data + (int)frm + (int)offs) = 0; | ||
1621 | BREAK; | ||
1622 | CASE(EMBRYO_OP_SIGN_PRI); | ||
1623 | if ((pri & 0xff) >= 0x80) pri |= ~(Embryo_UCell)0xff; | ||
1624 | BREAK; | ||
1625 | CASE(EMBRYO_OP_SIGN_ALT); | ||
1626 | if ((alt & 0xff) >= 0x80) alt |= ~(Embryo_UCell)0xff; | ||
1627 | BREAK; | ||
1628 | CASE(EMBRYO_OP_EQ); | ||
1629 | pri = (pri == alt) ? 1 : 0; | ||
1630 | BREAK; | ||
1631 | CASE(EMBRYO_OP_NEQ); | ||
1632 | pri = (pri != alt) ? 1 : 0; | ||
1633 | BREAK; | ||
1634 | CASE(EMBRYO_OP_LESS); | ||
1635 | pri = ((Embryo_UCell)pri < (Embryo_UCell)alt) ? 1 : 0; | ||
1636 | BREAK; | ||
1637 | CASE(EMBRYO_OP_LEQ); | ||
1638 | pri = ((Embryo_UCell)pri <= (Embryo_UCell)alt) ? 1 : 0; | ||
1639 | BREAK; | ||
1640 | CASE(EMBRYO_OP_GRTR); | ||
1641 | pri = ((Embryo_UCell)pri > (Embryo_UCell)alt) ? 1 : 0; | ||
1642 | BREAK; | ||
1643 | CASE(EMBRYO_OP_GEQ); | ||
1644 | pri = ((Embryo_UCell)pri >= (Embryo_UCell)alt) ? 1 : 0; | ||
1645 | BREAK; | ||
1646 | CASE(EMBRYO_OP_SLESS); | ||
1647 | pri = (pri < alt) ? 1 : 0; | ||
1648 | BREAK; | ||
1649 | CASE(EMBRYO_OP_SLEQ); | ||
1650 | pri = (pri <= alt) ? 1 : 0; | ||
1651 | BREAK; | ||
1652 | CASE(EMBRYO_OP_SGRTR); | ||
1653 | pri = (pri > alt) ? 1 : 0; | ||
1654 | BREAK; | ||
1655 | CASE(EMBRYO_OP_SGEQ); | ||
1656 | pri = (pri >= alt) ? 1 : 0; | ||
1657 | BREAK; | ||
1658 | CASE(EMBRYO_OP_EQ_C_PRI); | ||
1659 | GETPARAM(offs); | ||
1660 | pri = (pri == offs) ? 1 : 0; | ||
1661 | BREAK; | ||
1662 | CASE(EMBRYO_OP_EQ_C_ALT); | ||
1663 | GETPARAM(offs); | ||
1664 | pri = (alt == offs) ? 1 : 0; | ||
1665 | BREAK; | ||
1666 | CASE(EMBRYO_OP_INC_PRI); | ||
1667 | pri++; | ||
1668 | BREAK; | ||
1669 | CASE(EMBRYO_OP_INC_ALT); | ||
1670 | alt++; | ||
1671 | BREAK; | ||
1672 | CASE(EMBRYO_OP_INC); | ||
1673 | GETPARAM(offs); | ||
1674 | *(Embryo_Cell *)(data + (int)offs) += 1; | ||
1675 | BREAK; | ||
1676 | CASE(EMBRYO_OP_INC_S); | ||
1677 | GETPARAM(offs); | ||
1678 | *(Embryo_Cell *)(data + (int)frm + (int)offs) += 1; | ||
1679 | BREAK; | ||
1680 | CASE(EMBRYO_OP_INC_I); | ||
1681 | *(Embryo_Cell *)(data + (int)pri) += 1; | ||
1682 | BREAK; | ||
1683 | CASE(EMBRYO_OP_DEC_PRI); | ||
1684 | pri--; | ||
1685 | BREAK; | ||
1686 | CASE(EMBRYO_OP_DEC_ALT); | ||
1687 | alt--; | ||
1688 | BREAK; | ||
1689 | CASE(EMBRYO_OP_DEC); | ||
1690 | GETPARAM(offs); | ||
1691 | *(Embryo_Cell *)(data + (int)offs) -= 1; | ||
1692 | BREAK; | ||
1693 | CASE(EMBRYO_OP_DEC_S); | ||
1694 | GETPARAM(offs); | ||
1695 | *(Embryo_Cell *)(data + (int)frm + (int)offs) -= 1; | ||
1696 | BREAK; | ||
1697 | CASE(EMBRYO_OP_DEC_I); | ||
1698 | *(Embryo_Cell *)(data + (int)pri) -= 1; | ||
1699 | BREAK; | ||
1700 | CASE(EMBRYO_OP_MOVS); | ||
1701 | GETPARAM(offs); | ||
1702 | CHKMEM(pri); | ||
1703 | CHKMEM(pri + offs); | ||
1704 | CHKMEM(alt); | ||
1705 | CHKMEM(alt + offs); | ||
1706 | memcpy(data+(int)alt, data+(int)pri, (int)offs); | ||
1707 | BREAK; | ||
1708 | CASE(EMBRYO_OP_CMPS); | ||
1709 | GETPARAM(offs); | ||
1710 | CHKMEM(pri); | ||
1711 | CHKMEM(pri + offs); | ||
1712 | CHKMEM(alt); | ||
1713 | CHKMEM(alt + offs); | ||
1714 | pri = memcmp(data + (int)alt, data + (int)pri, (int)offs); | ||
1715 | BREAK; | ||
1716 | CASE(EMBRYO_OP_FILL); | ||
1717 | GETPARAM(offs); | ||
1718 | CHKMEM(alt); | ||
1719 | CHKMEM(alt + offs); | ||
1720 | for (i = (int)alt; | ||
1721 | (size_t)offs >= sizeof(Embryo_Cell); | ||
1722 | i += sizeof(Embryo_Cell), offs -= sizeof(Embryo_Cell)) | ||
1723 | *(Embryo_Cell *)(data + i) = pri; | ||
1724 | BREAK; | ||
1725 | CASE(EMBRYO_OP_HALT); | ||
1726 | GETPARAM(offs); | ||
1727 | ep->retval = pri; | ||
1728 | /* store complete status */ | ||
1729 | ep->frm = frm; | ||
1730 | ep->stk = stk; | ||
1731 | ep->hea = hea; | ||
1732 | ep->pri = pri; | ||
1733 | ep->alt = alt; | ||
1734 | ep->cip = (Embryo_Cell)((unsigned char*)cip - code); | ||
1735 | if (offs == EMBRYO_ERROR_SLEEP) | ||
1736 | { | ||
1737 | ep->reset_stk = reset_stk; | ||
1738 | ep->reset_hea = reset_hea; | ||
1739 | ep->run_count--; | ||
1740 | return EMBRYO_PROGRAM_SLEEP; | ||
1741 | } | ||
1742 | OK(ep, (int)offs); | ||
1743 | CASE(EMBRYO_OP_BOUNDS); | ||
1744 | GETPARAM(offs); | ||
1745 | if ((Embryo_UCell)pri > (Embryo_UCell)offs) | ||
1746 | ABORT(ep, EMBRYO_ERROR_BOUNDS); | ||
1747 | BREAK; | ||
1748 | CASE(EMBRYO_OP_SYSREQ_PRI); | ||
1749 | /* save a few registers */ | ||
1750 | ep->cip = (Embryo_Cell)((unsigned char *)cip - code); | ||
1751 | ep->hea = hea; | ||
1752 | ep->frm = frm; | ||
1753 | ep->stk = stk; | ||
1754 | num = _embryo_native_call(ep, pri, &pri, (Embryo_Cell *)(data + (int)stk)); | ||
1755 | if (num != EMBRYO_ERROR_NONE) | ||
1756 | { | ||
1757 | if (num == EMBRYO_ERROR_SLEEP) | ||
1758 | { | ||
1759 | ep->pri = pri; | ||
1760 | ep->alt = alt; | ||
1761 | ep->reset_stk = reset_stk; | ||
1762 | ep->reset_hea = reset_hea; | ||
1763 | ep->run_count--; | ||
1764 | return EMBRYO_PROGRAM_SLEEP; | ||
1765 | } | ||
1766 | ABORT(ep, num); | ||
1767 | } | ||
1768 | BREAK; | ||
1769 | CASE(EMBRYO_OP_SYSREQ_C); | ||
1770 | GETPARAM(offs); | ||
1771 | /* save a few registers */ | ||
1772 | ep->cip = (Embryo_Cell)((unsigned char *)cip - code); | ||
1773 | ep->hea = hea; | ||
1774 | ep->frm = frm; | ||
1775 | ep->stk = stk; | ||
1776 | num = _embryo_native_call(ep, offs, &pri, (Embryo_Cell *)(data + (int)stk)); | ||
1777 | if (num != EMBRYO_ERROR_NONE) | ||
1778 | { | ||
1779 | if (num == EMBRYO_ERROR_SLEEP) | ||
1780 | { | ||
1781 | ep->pri = pri; | ||
1782 | ep->alt = alt; | ||
1783 | ep->reset_stk = reset_stk; | ||
1784 | ep->reset_hea = reset_hea; | ||
1785 | ep->run_count--; | ||
1786 | return EMBRYO_PROGRAM_SLEEP; | ||
1787 | } | ||
1788 | { | ||
1789 | Embryo_Header *hdr; | ||
1790 | int i, num; | ||
1791 | Embryo_Func_Stub *func_entry; | ||
1792 | |||
1793 | hdr = (Embryo_Header *)ep->code; | ||
1794 | num = NUMENTRIES(hdr, natives, libraries); | ||
1795 | func_entry = GETENTRY(hdr, natives, 0); | ||
1796 | for (i = 0; i < num; i++) | ||
1797 | { | ||
1798 | char *entry_name; | ||
1799 | |||
1800 | entry_name = GETENTRYNAME(hdr, func_entry); | ||
1801 | if (i == offs) | ||
1802 | printf("EMBRYO: CALL [%i] %s() non-existent!\n", i, entry_name); | ||
1803 | func_entry = | ||
1804 | (Embryo_Func_Stub *)((unsigned char *)func_entry + hdr->defsize); | ||
1805 | } | ||
1806 | } | ||
1807 | ABORT(ep, num); | ||
1808 | } | ||
1809 | BREAK; | ||
1810 | CASE(EMBRYO_OP_SYSREQ_D); | ||
1811 | GETPARAM(offs); | ||
1812 | /* save a few registers */ | ||
1813 | ep->cip = (Embryo_Cell)((unsigned char *)cip - code); | ||
1814 | ep->hea = hea; | ||
1815 | ep->frm = frm; | ||
1816 | ep->stk = stk; | ||
1817 | num = _embryo_native_call(ep, offs, &pri, (Embryo_Cell *)(data + (int)stk)); | ||
1818 | if (num != EMBRYO_ERROR_NONE) | ||
1819 | { | ||
1820 | if (num == EMBRYO_ERROR_SLEEP) | ||
1821 | { | ||
1822 | ep->pri = pri; | ||
1823 | ep->alt = alt; | ||
1824 | ep->reset_stk = reset_stk; | ||
1825 | ep->reset_hea = reset_hea; | ||
1826 | ep->run_count--; | ||
1827 | return EMBRYO_PROGRAM_SLEEP; | ||
1828 | } | ||
1829 | ABORT(ep, ep->error); | ||
1830 | } | ||
1831 | BREAK; | ||
1832 | CASE(EMBRYO_OP_JUMP_PRI); | ||
1833 | cip = (Embryo_Cell *)(code + (int)pri); | ||
1834 | BREAK; | ||
1835 | CASE(EMBRYO_OP_SWITCH); | ||
1836 | { | ||
1837 | Embryo_Cell *cptr; | ||
1838 | |||
1839 | /* +1, to skip the "casetbl" opcode */ | ||
1840 | cptr = (Embryo_Cell *)(code + (*cip)) + 1; | ||
1841 | /* number of records in the case table */ | ||
1842 | num = (int)(*cptr); | ||
1843 | /* preset to "none-matched" case */ | ||
1844 | cip = (Embryo_Cell *)(code + *(cptr + 1)); | ||
1845 | for (cptr += 2; | ||
1846 | (num > 0) && (*cptr != pri); | ||
1847 | num--, cptr += 2); | ||
1848 | /* case found */ | ||
1849 | if (num > 0) | ||
1850 | cip = (Embryo_Cell *)(code + *(cptr + 1)); | ||
1851 | } | ||
1852 | BREAK; | ||
1853 | CASE(EMBRYO_OP_SWAP_PRI); | ||
1854 | offs = *(Embryo_Cell *)(data + (int)stk); | ||
1855 | *(Embryo_Cell *)(data + (int)stk) = pri; | ||
1856 | pri = offs; | ||
1857 | BREAK; | ||
1858 | CASE(EMBRYO_OP_SWAP_ALT); | ||
1859 | offs = *(Embryo_Cell *)(data + (int)stk); | ||
1860 | *(Embryo_Cell *)(data + (int)stk) = alt; | ||
1861 | alt = offs; | ||
1862 | BREAK; | ||
1863 | CASE(EMBRYO_OP_PUSHADDR); | ||
1864 | GETPARAM(offs); | ||
1865 | PUSH(frm + offs); | ||
1866 | BREAK; | ||
1867 | CASE(EMBRYO_OP_NOP); | ||
1868 | BREAK; | ||
1869 | CASE(EMBRYO_OP_NONE); | ||
1870 | CASE(EMBRYO_OP_FILE); | ||
1871 | CASE(EMBRYO_OP_LINE); | ||
1872 | CASE(EMBRYO_OP_SYMBOL); | ||
1873 | CASE(EMBRYO_OP_SRANGE); | ||
1874 | CASE(EMBRYO_OP_CASETBL); | ||
1875 | CASE(EMBRYO_OP_SYMTAG); | ||
1876 | BREAK; | ||
1877 | #ifndef EMBRYO_EXEC_JUMPTABLE | ||
1878 | default: | ||
1879 | ABORT(ep, EMBRYO_ERROR_INVINSTR); | ||
1880 | #endif | ||
1881 | SWITCHEND; | ||
1882 | } | ||
1883 | ep->max_run_cycles = max_run_cycles; | ||
1884 | ep->run_count--; | ||
1885 | ep->hea = hea_start; | ||
1886 | return EMBRYO_PROGRAM_OK; | ||
1887 | } | ||
1888 | |||
1889 | EAPI Embryo_Cell | ||
1890 | embryo_program_return_value_get(Embryo_Program *ep) | ||
1891 | { | ||
1892 | if (!ep) return 0; | ||
1893 | return ep->retval; | ||
1894 | } | ||
1895 | |||
1896 | EAPI void | ||
1897 | embryo_program_max_cycle_run_set(Embryo_Program *ep, int max) | ||
1898 | { | ||
1899 | if (!ep) return; | ||
1900 | if (max < 0) max = 0; | ||
1901 | ep->max_run_cycles = max; | ||
1902 | } | ||
1903 | |||
1904 | EAPI int | ||
1905 | embryo_program_max_cycle_run_get(Embryo_Program *ep) | ||
1906 | { | ||
1907 | if (!ep) return 0; | ||
1908 | return ep->max_run_cycles; | ||
1909 | } | ||
1910 | |||
1911 | |||
1912 | EAPI int | ||
1913 | embryo_parameter_cell_push(Embryo_Program *ep, Embryo_Cell cell) | ||
1914 | { | ||
1915 | Embryo_Param *pr; | ||
1916 | |||
1917 | ep->params_size++; | ||
1918 | if (ep->params_size > ep->params_alloc) | ||
1919 | { | ||
1920 | ep->params_alloc += 8; | ||
1921 | pr = realloc(ep->params, ep->params_alloc * sizeof(Embryo_Param)); | ||
1922 | if (!pr) return 0; | ||
1923 | ep->params = pr; | ||
1924 | } | ||
1925 | pr = &(ep->params[ep->params_size - 1]); | ||
1926 | pr->string = NULL; | ||
1927 | pr->cell_array = NULL; | ||
1928 | pr->cell_array_size = 0; | ||
1929 | pr->cell = 0; | ||
1930 | pr->cell = cell; | ||
1931 | return 1; | ||
1932 | } | ||
1933 | |||
1934 | EAPI int | ||
1935 | embryo_parameter_string_push(Embryo_Program *ep, const char *str) | ||
1936 | { | ||
1937 | Embryo_Param *pr; | ||
1938 | char *str_dup; | ||
1939 | |||
1940 | if (!str) | ||
1941 | return embryo_parameter_string_push(ep, ""); | ||
1942 | str_dup = strdup(str); | ||
1943 | if (!str_dup) return 0; | ||
1944 | ep->params_size++; | ||
1945 | if (ep->params_size > ep->params_alloc) | ||
1946 | { | ||
1947 | ep->params_alloc += 8; | ||
1948 | pr = realloc(ep->params, ep->params_alloc * sizeof(Embryo_Param)); | ||
1949 | if (!pr) | ||
1950 | { | ||
1951 | free(str_dup); | ||
1952 | return 0; | ||
1953 | } | ||
1954 | ep->params = pr; | ||
1955 | } | ||
1956 | pr = &(ep->params[ep->params_size - 1]); | ||
1957 | pr->string = NULL; | ||
1958 | pr->cell_array = NULL; | ||
1959 | pr->cell_array_size = 0; | ||
1960 | pr->cell = 0; | ||
1961 | pr->string = str_dup; | ||
1962 | return 1; | ||
1963 | } | ||
1964 | |||
1965 | EAPI int | ||
1966 | embryo_parameter_cell_array_push(Embryo_Program *ep, Embryo_Cell *cells, int num) | ||
1967 | { | ||
1968 | Embryo_Param *pr; | ||
1969 | Embryo_Cell *cell_array; | ||
1970 | |||
1971 | if ((!cells) || (num <= 0)) | ||
1972 | return embryo_parameter_cell_push(ep, 0); | ||
1973 | cell_array = malloc(num * sizeof(Embryo_Cell)); | ||
1974 | ep->params_size++; | ||
1975 | if (ep->params_size > ep->params_alloc) | ||
1976 | { | ||
1977 | ep->params_alloc += 8; | ||
1978 | pr = realloc(ep->params, ep->params_alloc * sizeof(Embryo_Param)); | ||
1979 | if (!pr) | ||
1980 | { | ||
1981 | free(cell_array); | ||
1982 | return 0; | ||
1983 | } | ||
1984 | ep->params = pr; | ||
1985 | } | ||
1986 | pr = &(ep->params[ep->params_size - 1]); | ||
1987 | pr->string = NULL; | ||
1988 | pr->cell_array = NULL; | ||
1989 | pr->cell_array_size = 0; | ||
1990 | pr->cell = 0; | ||
1991 | pr->cell_array = cell_array; | ||
1992 | pr->cell_array_size = num; | ||
1993 | memcpy(pr->cell_array, cells, num * sizeof(Embryo_Cell)); | ||
1994 | return 1; | ||
1995 | } | ||