aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/libraries/embryo/src/lib/embryo_amx.c
diff options
context:
space:
mode:
authorDavid Walter Seikel2013-01-13 17:29:19 +1000
committerDavid Walter Seikel2013-01-13 17:29:19 +1000
commit07274513e984f0b5544586c74508ccd16e7dcafa (patch)
treeb32ff2a9136fbc1a4a6a0ed1e4d79cde0f5f16d9 /libraries/embryo/src/lib/embryo_amx.c
parentAdded Irrlicht 1.8, but without all the Windows binaries. (diff)
downloadSledjHamr-07274513e984f0b5544586c74508ccd16e7dcafa.zip
SledjHamr-07274513e984f0b5544586c74508ccd16e7dcafa.tar.gz
SledjHamr-07274513e984f0b5544586c74508ccd16e7dcafa.tar.bz2
SledjHamr-07274513e984f0b5544586c74508ccd16e7dcafa.tar.xz
Remove EFL, since it's been released now.
Diffstat (limited to '')
-rw-r--r--libraries/embryo/src/lib/embryo_amx.c1995
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
43static void _embryo_byte_swap_16 (unsigned short *v);
44static void _embryo_byte_swap_32 (unsigned int *v);
45#endif
46static int _embryo_native_call (Embryo_Program *ep, Embryo_Cell index, Embryo_Cell *result, Embryo_Cell *params);
47static int _embryo_func_get (Embryo_Program *ep, int index, char *funcname);
48static int _embryo_var_get (Embryo_Program *ep, int index, char *varname, Embryo_Cell *ep_addr);
49static int _embryo_program_init (Embryo_Program *ep, void *code);
50
51#ifdef WORDS_BIGENDIAN
52static 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
61static 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
72static 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
98static 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
113static 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
130static 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
237EAPI Embryo_Program *
238embryo_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
261EAPI Embryo_Program *
262embryo_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
280EAPI Embryo_Program *
281embryo_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
327EAPI void
328embryo_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
345EAPI void
346embryo_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
401EAPI void
402embryo_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
417EAPI void
418embryo_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
439EAPI void
440embryo_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
450EAPI void
451embryo_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
462EAPI void
463embryo_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
474EAPI Embryo_Function
475embryo_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
502EAPI Embryo_Cell
503embryo_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
531EAPI int
532embryo_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
542EAPI Embryo_Cell
543embryo_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
556EAPI void
557embryo_program_error_set(Embryo_Program *ep, Embryo_Error error)
558{
559 if (!ep) return;
560 ep->error = error;
561}
562
563EAPI Embryo_Error
564embryo_program_error_get(Embryo_Program *ep)
565{
566 if (!ep) return EMBRYO_ERROR_NONE;
567 return ep->error;
568}
569
570
571EAPI void
572embryo_program_data_set(Embryo_Program *ep, void *data)
573{
574 if (!ep) return;
575 ep->data = data;
576}
577
578EAPI void *
579embryo_program_data_get(Embryo_Program *ep)
580{
581 if (!ep) return NULL;
582 return ep->data;
583}
584
585EAPI const char *
586embryo_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
624EAPI int
625embryo_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
640EAPI void
641embryo_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
677EAPI void
678embryo_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
718EAPI Embryo_Cell *
719embryo_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
732EAPI Embryo_Cell
733embryo_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
747EAPI void
748embryo_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
756EAPI int
757embryo_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
781EAPI Embryo_Status
782embryo_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
1889EAPI Embryo_Cell
1890embryo_program_return_value_get(Embryo_Program *ep)
1891{
1892 if (!ep) return 0;
1893 return ep->retval;
1894}
1895
1896EAPI void
1897embryo_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
1904EAPI int
1905embryo_program_max_cycle_run_get(Embryo_Program *ep)
1906{
1907 if (!ep) return 0;
1908 return ep->max_run_cycles;
1909}
1910
1911
1912EAPI int
1913embryo_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
1934EAPI int
1935embryo_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
1965EAPI int
1966embryo_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}