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