aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/libraries/embryo/src/lib/embryo_amx.c
diff options
context:
space:
mode:
Diffstat (limited to 'libraries/embryo/src/lib/embryo_amx.c')
-rw-r--r--libraries/embryo/src/lib/embryo_amx.c1991
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
39static void _embryo_byte_swap_16 (unsigned short *v);
40static void _embryo_byte_swap_32 (unsigned int *v);
41#endif
42static int _embryo_native_call (Embryo_Program *ep, Embryo_Cell index, Embryo_Cell *result, Embryo_Cell *params);
43static int _embryo_func_get (Embryo_Program *ep, int index, char *funcname);
44static int _embryo_var_get (Embryo_Program *ep, int index, char *varname, Embryo_Cell *ep_addr);
45static int _embryo_program_init (Embryo_Program *ep, void *code);
46
47#ifdef WORDS_BIGENDIAN
48static 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
57static 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
68static 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
94static 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
109static 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
126static 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
233EAPI Embryo_Program *
234embryo_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
257EAPI Embryo_Program *
258embryo_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
276EAPI Embryo_Program *
277embryo_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
323EAPI void
324embryo_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
341EAPI void
342embryo_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
397EAPI void
398embryo_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
413EAPI void
414embryo_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
435EAPI void
436embryo_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
446EAPI void
447embryo_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
458EAPI void
459embryo_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
470EAPI Embryo_Function
471embryo_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
498EAPI Embryo_Cell
499embryo_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
527EAPI int
528embryo_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
538EAPI Embryo_Cell
539embryo_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
552EAPI void
553embryo_program_error_set(Embryo_Program *ep, Embryo_Error error)
554{
555 if (!ep) return;
556 ep->error = error;
557}
558
559EAPI Embryo_Error
560embryo_program_error_get(Embryo_Program *ep)
561{
562 if (!ep) return EMBRYO_ERROR_NONE;
563 return ep->error;
564}
565
566
567EAPI void
568embryo_program_data_set(Embryo_Program *ep, void *data)
569{
570 if (!ep) return;
571 ep->data = data;
572}
573
574EAPI void *
575embryo_program_data_get(Embryo_Program *ep)
576{
577 if (!ep) return NULL;
578 return ep->data;
579}
580
581EAPI const char *
582embryo_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
620EAPI int
621embryo_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
636EAPI void
637embryo_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
673EAPI void
674embryo_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
714EAPI Embryo_Cell *
715embryo_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
728EAPI Embryo_Cell
729embryo_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
743EAPI void
744embryo_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
752EAPI int
753embryo_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
777EAPI Embryo_Status
778embryo_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
1885EAPI Embryo_Cell
1886embryo_program_return_value_get(Embryo_Program *ep)
1887{
1888 if (!ep) return 0;
1889 return ep->retval;
1890}
1891
1892EAPI void
1893embryo_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
1900EAPI int
1901embryo_program_max_cycle_run_get(Embryo_Program *ep)
1902{
1903 if (!ep) return 0;
1904 return ep->max_run_cycles;
1905}
1906
1907
1908EAPI int
1909embryo_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
1930EAPI int
1931embryo_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
1961EAPI int
1962embryo_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}