1 /* Abstract Machine for the Small compiler
3 * Copyright (c) ITB CompuPhase, 1997-2003
4 * Portions Copyright (c) Carsten Haitzler, 2004-2010 <raster@rasterman.com>
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.
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:
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.
37 #include "embryo_private.h"
40 #define JUMPABS(base, ip) ((Embryo_Cell *)(code + (*ip)))
42 #ifdef WORDS_BIGENDIAN
43 static void _embryo_byte_swap_16 (unsigned short *v);
44 static void _embryo_byte_swap_32 (unsigned int *v);
46 static int _embryo_native_call (Embryo_Program *ep, Embryo_Cell idx, Embryo_Cell *result, Embryo_Cell *params);
47 static int _embryo_func_get (Embryo_Program *ep, int idx, char *funcname);
48 static int _embryo_var_get (Embryo_Program *ep, int idx, char *varname, Embryo_Cell *ep_addr);
49 static int _embryo_program_init (Embryo_Program *ep, void *code);
51 #ifdef WORDS_BIGENDIAN
53 _embryo_byte_swap_16(unsigned short *v)
57 s = (unsigned char *)v;
58 t = s[0]; s[0] = s[1]; s[1] = t;
62 _embryo_byte_swap_32(unsigned int *v)
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;
73 _embryo_native_call(Embryo_Program *ep, Embryo_Cell idx, Embryo_Cell *result, Embryo_Cell *params)
76 Embryo_Func_Stub *func_entry;
79 hdr = (Embryo_Header *)ep->base;
80 func_entry = GETENTRY(hdr, natives, idx);
81 if ((func_entry->address <= 0) ||
82 (func_entry->address > ep->native_calls_size))
84 ep->error = EMBRYO_ERROR_CALLBACK;
87 f = ep->native_calls[func_entry->address - 1];
90 ep->error = EMBRYO_ERROR_CALLBACK;
93 ep->error = EMBRYO_ERROR_NONE;
94 *result = f(ep, params);
99 _embryo_func_get(Embryo_Program *ep, int idx, char *funcname)
102 Embryo_Func_Stub *func;
104 hdr = (Embryo_Header *)ep->code;
105 if (idx >= (Embryo_Cell)NUMENTRIES(hdr, publics, natives))
106 return EMBRYO_ERROR_INDEX;
108 func = GETENTRY(hdr, publics, idx);
109 strcpy(funcname, GETENTRYNAME(hdr, func));
110 return EMBRYO_ERROR_NONE;
114 _embryo_var_get(Embryo_Program *ep, int idx, char *varname, Embryo_Cell *ep_addr)
118 Embryo_Func_Stub *var;
120 hdr=(Embryo_Header *)ep->base;
121 if (idx >= (Embryo_Cell)NUMENTRIES(hdr, pubvars, tags))
122 return EMBRYO_ERROR_INDEX;
124 var = GETENTRY(hdr, pubvars, idx);
125 strcpy(varname, GETENTRYNAME(hdr, var));
126 *ep_addr = var->address;
127 return EMBRYO_ERROR_NONE;
131 _embryo_program_init(Embryo_Program *ep, void *code)
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);
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)))
165 len = (unsigned short*)((unsigned char*)ep->code + hdr->nametable);
166 #ifdef WORDS_BIGENDIAN
167 embryo_swap_16((unsigned short *)len);
169 if (*len > sNAMEMAX) return 0;
171 if (hdr->stp <= 0) return 0;
172 if ((hdr->flags & EMBRYO_FLAG_COMPACT)) return 0;
174 #ifdef WORDS_BIGENDIAN
176 Embryo_Func_Stub *fs;
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++)
185 embryo_swap_32(&(fs->address));
186 fs = (Embryo_Func_Stub *)((unsigned char *)fs + hdr->defsize);
189 fs = GETENTRY(hdr, pubvars, 0);
190 num = NUMENTRIES(hdr, pubvars, tags);
191 for (i = 0; i < num; i++)
193 embryo_swap_32(&(fs->address));
194 fs = (Embryo_Func_Stub *)((unsigned char *)fs + hdr->defsize);
197 fs = GETENTRY(hdr, tags, 0);
198 num = NUMENTRIES(hdr, tags, nametable);
199 for (i = 0; i < num; i++)
201 embryo_swap_32(&(fs->address));
202 fs = (Embryo_Func_Stub *)((unsigned char *)fs + hdr->defsize);
206 ep->flags = EMBRYO_FLAG_RELOC;
208 #ifdef WORDS_BIGENDIAN
209 /* until we do more... this is only used for bigendian */
211 Embryo_Cell cip, code_size, cip_end;
214 code_size = hdr->dat - hdr->cod;
215 code = (Embryo_Cell *)((unsigned char *)ep->code + (int)hdr->cod);
216 cip_end = code_size / sizeof(Embryo_Cell);
217 for (cip = 0; cip < cip_end; cip++)
219 /* move this here - later we probably want something that verifies opcodes
220 * are valid and ok...
222 #ifdef WORDS_BIGENDIAN
223 embryo_swap_32(&(code[cip]));
229 /* init native api for handling floating point - default in embryo */
230 _embryo_args_init(ep);
232 _embryo_rand_init(ep);
233 _embryo_str_init(ep);
234 _embryo_time_init(ep);
238 /*** EXPORTED CALLS ***/
240 EAPI Embryo_Program *
241 embryo_program_new(void *data, int size)
246 if (size < (int)sizeof(Embryo_Header)) return NULL;
248 ep = calloc(1, sizeof(Embryo_Program));
249 if (!ep) return NULL;
251 code_data = malloc(size);
257 memcpy(code_data, data, size);
258 if (_embryo_program_init(ep, code_data)) return ep;
264 EAPI Embryo_Program *
265 embryo_program_const_new(void *data, int size)
269 if (size < (int)sizeof(Embryo_Header)) return NULL;
271 ep = calloc(1, sizeof(Embryo_Program));
272 if (!ep) return NULL;
274 if (_embryo_program_init(ep, data))
276 ep->dont_free_code = 1;
283 EAPI Embryo_Program *
284 embryo_program_load(const char *file)
289 void *program = NULL;
290 int program_size = 0;
292 f = fopen(file, "rb");
294 fseek(f, 0, SEEK_END);
295 program_size = ftell(f);
296 fseek(f, 0L, SEEK_SET);
297 if (program_size < (int)sizeof(Embryo_Header))
302 if (fread(&hdr, sizeof(Embryo_Header), 1, f) != 1)
307 fseek(f, 0L, SEEK_SET);
308 #ifdef WORDS_BIGENDIAN
309 embryo_swap_32((unsigned int *)(&hdr.size));
311 if ((int)hdr.size < program_size) program_size = hdr.size;
312 program = malloc(program_size);
318 if (fread(program, program_size, 1, f) != 1)
324 ep = embryo_program_new(program, program_size);
331 embryo_program_free(Embryo_Program *ep)
335 if (ep->base) free(ep->base);
336 if ((!ep->dont_free_code) && (ep->code)) free(ep->code);
337 if (ep->native_calls) free(ep->native_calls);
338 for (i = 0; i < ep->params_size; i++)
340 if (ep->params[i].string) free(ep->params[i].string);
341 if (ep->params[i].cell_array) free(ep->params[i].cell_array);
343 if (ep->params) free(ep->params);
349 embryo_program_native_call_add(Embryo_Program *ep, const char *name, Embryo_Cell (*func) (Embryo_Program *ep, Embryo_Cell *params))
351 Embryo_Func_Stub *func_entry;
355 if ((!ep ) || (!name) || (!func)) return;
356 if (strlen(name) > sNAMEMAX) return;
358 hdr = (Embryo_Header *)ep->code;
359 if (hdr->defsize < 1) return;
360 num = NUMENTRIES(hdr, natives, libraries);
361 if (num <= 0) return;
363 ep->native_calls_size++;
364 if (ep->native_calls_size > ep->native_calls_alloc)
366 Embryo_Native *calls;
368 ep->native_calls_alloc += 32;
369 calls = realloc(ep->native_calls,
370 ep->native_calls_alloc * sizeof(Embryo_Native));
373 ep->native_calls_size--;
374 ep->native_calls_alloc -= 32;
377 ep->native_calls = calls;
379 ep->native_calls[ep->native_calls_size - 1] = func;
381 func_entry = GETENTRY(hdr, natives, 0);
382 for (i = 0; i < num; i++)
384 if (func_entry->address == 0)
388 entry_name = GETENTRYNAME(hdr, func_entry);
389 if ((entry_name) && (!strcmp(entry_name, name)))
391 func_entry->address = ep->native_calls_size;
392 /* FIXME: embryo_cc is putting in multiple native */
393 /* function call entries - so we need to fill in all */
399 (Embryo_Func_Stub *)((unsigned char *)func_entry + hdr->defsize);
405 embryo_program_vm_reset(Embryo_Program *ep)
409 if ((!ep) || (!ep->base)) return;
410 hdr = (Embryo_Header *)ep->code;
411 memcpy(ep->base, hdr, hdr->size);
412 *(Embryo_Cell *)(ep->base + (int)hdr->stp - sizeof(Embryo_Cell)) = 0;
414 ep->hlw = hdr->hea - hdr->dat; /* stack and heap relative to data segment */
415 ep->stp = hdr->stp - hdr->dat - sizeof(Embryo_Cell);
421 embryo_program_vm_push(Embryo_Program *ep)
429 embryo_program_vm_reset(ep);
432 hdr = (Embryo_Header *)ep->code;
433 ep->base = calloc(1, hdr->stp);
439 embryo_program_vm_reset(ep);
443 embryo_program_vm_pop(Embryo_Program *ep)
445 if ((!ep) || (!ep->base)) return;
447 if (ep->pushes >= 1) return;
454 embryo_swap_16(unsigned short *v
455 #ifndef WORDS_BIGENDIAN
460 #ifdef WORDS_BIGENDIAN
461 _embryo_byte_swap_16(v);
466 embryo_swap_32(unsigned int *v
467 #ifndef WORDS_BIGENDIAN
472 #ifdef WORDS_BIGENDIAN
473 _embryo_byte_swap_32(v);
478 embryo_program_function_find(Embryo_Program *ep, const char *name)
480 int first, last, mid, result;
481 char pname[sNAMEMAX + 1];
484 if (!ep) return EMBRYO_FUNCTION_NONE;
485 hdr = (Embryo_Header *)ep->code;
486 last = NUMENTRIES(hdr, publics, natives) - 1;
489 while (first <= last)
491 mid = (first + last) / 2;
492 if (_embryo_func_get(ep, mid, pname) == EMBRYO_ERROR_NONE)
493 result = strcmp(pname, name);
495 return EMBRYO_FUNCTION_NONE;
497 if (result > 0) last = mid - 1;
498 else if (result < 0) first = mid + 1;
501 return EMBRYO_FUNCTION_NONE;
506 embryo_program_variable_find(Embryo_Program *ep, const char *name)
508 int first, last, mid, result;
509 char pname[sNAMEMAX + 1];
513 if (!ep) return EMBRYO_CELL_NONE;
514 if (!ep->base) return EMBRYO_CELL_NONE;
515 hdr = (Embryo_Header *)ep->base;
516 last = NUMENTRIES(hdr, pubvars, tags) - 1;
519 while (first <= last)
521 mid = (first + last) / 2;
522 if (_embryo_var_get(ep, mid, pname, &paddr) == EMBRYO_ERROR_NONE)
523 result = strcmp(pname, name);
525 return EMBRYO_CELL_NONE;
527 if (result > 0) last = mid - 1;
528 else if (result < 0) first = mid + 1;
531 return EMBRYO_CELL_NONE;
535 embryo_program_variable_count_get(Embryo_Program *ep)
540 if (!ep->base) return 0;
541 hdr = (Embryo_Header *)ep->base;
542 return NUMENTRIES(hdr, pubvars, tags);
546 embryo_program_variable_get(Embryo_Program *ep, int num)
549 char pname[sNAMEMAX + 1];
551 if (!ep) return EMBRYO_CELL_NONE;
552 if (!ep->base) return EMBRYO_CELL_NONE;
553 if (_embryo_var_get(ep, num, pname, &paddr) == EMBRYO_ERROR_NONE)
555 return EMBRYO_CELL_NONE;
560 embryo_program_error_set(Embryo_Program *ep, Embryo_Error error)
567 embryo_program_error_get(Embryo_Program *ep)
569 if (!ep) return EMBRYO_ERROR_NONE;
575 embryo_program_data_set(Embryo_Program *ep, void *data)
582 embryo_program_data_get(Embryo_Program *ep)
584 if (!ep) return NULL;
589 embryo_error_string_get(Embryo_Error error)
591 const char *messages[] =
593 /* EMBRYO_ERROR_NONE */ "(none)",
594 /* EMBRYO_ERROR_EXIT */ "Forced exit",
595 /* EMBRYO_ERROR_ASSERT */ "Assertion failed",
596 /* EMBRYO_ERROR_STACKERR */ "Stack/heap collision (insufficient stack size)",
597 /* EMBRYO_ERROR_BOUNDS */ "Array index out of bounds",
598 /* EMBRYO_ERROR_MEMACCESS */ "Invalid memory access",
599 /* EMBRYO_ERROR_INVINSTR */ "Invalid instruction",
600 /* EMBRYO_ERROR_STACKLOW */ "Stack underflow",
601 /* EMBRYO_ERROR_HEAPLOW */ "Heap underflow",
602 /* EMBRYO_ERROR_CALLBACK */ "No (valid) native function callback",
603 /* EMBRYO_ERROR_NATIVE */ "Native function failed",
604 /* EMBRYO_ERROR_DIVIDE */ "Divide by zero",
605 /* EMBRYO_ERROR_SLEEP */ "(sleep mode)",
606 /* 13 */ "(reserved)",
607 /* 14 */ "(reserved)",
608 /* 15 */ "(reserved)",
609 /* EMBRYO_ERROR_MEMORY */ "Out of memory",
610 /* EMBRYO_ERROR_FORMAT */ "Invalid/unsupported P-code file format",
611 /* EMBRYO_ERROR_VERSION */ "File is for a newer version of the Embryo_Program",
612 /* EMBRYO_ERROR_NOTFOUND */ "Native/Public function is not found",
613 /* EMBRYO_ERROR_INDEX */ "Invalid index parameter (bad entry point)",
614 /* EMBRYO_ERROR_DEBUG */ "Debugger cannot run",
615 /* EMBRYO_ERROR_INIT */ "Embryo_Program not initialized (or doubly initialized)",
616 /* EMBRYO_ERROR_USERDATA */ "Unable to set user data field (table full)",
617 /* EMBRYO_ERROR_INIT_JIT */ "Cannot initialize the JIT",
618 /* EMBRYO_ERROR_PARAMS */ "Parameter error",
620 if (((int)error < 0) ||
621 ((int)error >= (int)(sizeof(messages) / sizeof(messages[0]))))
622 return (const char *)"(unknown)";
623 return messages[error];
628 embryo_data_string_length_get(Embryo_Program *ep, Embryo_Cell *str_cell)
633 if ((!ep) || (!ep->base)) return 0;
634 hdr = (Embryo_Header *)ep->base;
636 ((void *)str_cell >= (void *)(ep->base + hdr->stp)) ||
637 ((void *)str_cell < (void *)ep->base))
639 for (len = 0; str_cell[len] != 0; len++);
644 embryo_data_string_get(Embryo_Program *ep, Embryo_Cell *str_cell, char *dst)
650 if ((!ep) || (!ep->base))
655 hdr = (Embryo_Header *)ep->base;
657 ((void *)str_cell >= (void *)(ep->base + hdr->stp)) ||
658 ((void *)str_cell < (void *)ep->base))
663 for (i = 0; str_cell[i] != 0; i++)
665 #ifdef WORDS_BIGENDIAN
670 _embryo_byte_swap_32(&tmp);
674 dst[i] = str_cell[i];
681 embryo_data_string_set(Embryo_Program *ep, const char *src, Embryo_Cell *str_cell)
687 if (!ep->base) return;
688 hdr = (Embryo_Header *)ep->base;
690 ((void *)str_cell >= (void *)(ep->base + hdr->stp)) ||
691 ((void *)str_cell < (void *)ep->base))
698 for (i = 0; src[i] != 0; i++)
700 if ((void *)(&(str_cell[i])) >= (void *)(ep->base + hdr->stp)) return;
701 else if ((void *)(&(str_cell[i])) == (void *)(ep->base + hdr->stp - 1))
706 #ifdef WORDS_BIGENDIAN
711 _embryo_byte_swap_32(&tmp);
715 str_cell[i] = src[i];
722 embryo_data_address_get(Embryo_Program *ep, Embryo_Cell addr)
727 if ((!ep) || (!ep->base)) return NULL;
728 hdr = (Embryo_Header *)ep->base;
729 data = ep->base + (int)hdr->dat;
730 if ((addr < 0) || (addr >= hdr->stp)) return NULL;
731 return (Embryo_Cell *)(data + (int)addr);
736 embryo_data_heap_push(Embryo_Program *ep, int cells)
741 if ((!ep) || (!ep->base)) return EMBRYO_CELL_NONE;
742 hdr = (Embryo_Header *)ep->base;
743 if (ep->stk - ep->hea - (cells * sizeof(Embryo_Cell)) < STKMARGIN)
744 return EMBRYO_CELL_NONE;
746 ep->hea += (cells * sizeof(Embryo_Cell));
751 embryo_data_heap_pop(Embryo_Program *ep, Embryo_Cell down_to)
754 if (down_to < 0) down_to = 0;
755 if (ep->hea > down_to) ep->hea = down_to;
760 embryo_program_recursion_get(Embryo_Program *ep)
762 return ep->run_count;
767 #define EMBRYO_EXEC_JUMPTABLE
771 /* jump table optimization - only works for gcc though */
772 #ifdef EMBRYO_EXEC_JUMPTABLE
773 #define SWITCH(x) while (1) { goto *switchtable[x];
774 #define SWITCHEND break; }
775 #define CASE(x) SWITCHTABLE_##x:
778 #define SWITCH(x) switch (x) {
780 #define CASE(x) case x:
785 embryo_program_run(Embryo_Program *ep, Embryo_Function fn)
788 Embryo_Func_Stub *func;
789 unsigned char *code, *data;
790 Embryo_Cell pri, alt, stk, frm, hea, hea_start;
791 Embryo_Cell reset_stk, reset_hea, *cip;
792 Embryo_UCell codesize;
799 #ifdef EMBRYO_EXEC_JUMPTABLE
800 /* we limit the jumptable to 256 elements. why? above we forced "op" to be
801 * a unsigned char - that means 256 max values. we limit opcode overflow
802 * here, so eliminating crashes on table lookups with bad/corrupt bytecode.
803 * no need to atuall do compares, branches etc. the datatype does the work
804 * for us. so that means EXCESS elements are all declared as OP_NONE to
805 * keep them innocuous.
807 static const void *switchtable[256] =
809 &&SWITCHTABLE_EMBRYO_OP_NONE,
810 &&SWITCHTABLE_EMBRYO_OP_LOAD_PRI,
811 &&SWITCHTABLE_EMBRYO_OP_LOAD_ALT,
812 &&SWITCHTABLE_EMBRYO_OP_LOAD_S_PRI,
813 &&SWITCHTABLE_EMBRYO_OP_LOAD_S_ALT,
814 &&SWITCHTABLE_EMBRYO_OP_LREF_PRI,
815 &&SWITCHTABLE_EMBRYO_OP_LREF_ALT,
816 &&SWITCHTABLE_EMBRYO_OP_LREF_S_PRI,
817 &&SWITCHTABLE_EMBRYO_OP_LREF_S_ALT,
818 &&SWITCHTABLE_EMBRYO_OP_LOAD_I,
819 &&SWITCHTABLE_EMBRYO_OP_LODB_I,
820 &&SWITCHTABLE_EMBRYO_OP_CONST_PRI,
821 &&SWITCHTABLE_EMBRYO_OP_CONST_ALT,
822 &&SWITCHTABLE_EMBRYO_OP_ADDR_PRI,
823 &&SWITCHTABLE_EMBRYO_OP_ADDR_ALT,
824 &&SWITCHTABLE_EMBRYO_OP_STOR_PRI,
825 &&SWITCHTABLE_EMBRYO_OP_STOR_ALT,
826 &&SWITCHTABLE_EMBRYO_OP_STOR_S_PRI,
827 &&SWITCHTABLE_EMBRYO_OP_STOR_S_ALT,
828 &&SWITCHTABLE_EMBRYO_OP_SREF_PRI,
829 &&SWITCHTABLE_EMBRYO_OP_SREF_ALT,
830 &&SWITCHTABLE_EMBRYO_OP_SREF_S_PRI,
831 &&SWITCHTABLE_EMBRYO_OP_SREF_S_ALT,
832 &&SWITCHTABLE_EMBRYO_OP_STOR_I,
833 &&SWITCHTABLE_EMBRYO_OP_STRB_I,
834 &&SWITCHTABLE_EMBRYO_OP_LIDX,
835 &&SWITCHTABLE_EMBRYO_OP_LIDX_B,
836 &&SWITCHTABLE_EMBRYO_OP_IDXADDR,
837 &&SWITCHTABLE_EMBRYO_OP_IDXADDR_B,
838 &&SWITCHTABLE_EMBRYO_OP_ALIGN_PRI,
839 &&SWITCHTABLE_EMBRYO_OP_ALIGN_ALT,
840 &&SWITCHTABLE_EMBRYO_OP_LCTRL,
841 &&SWITCHTABLE_EMBRYO_OP_SCTRL,
842 &&SWITCHTABLE_EMBRYO_OP_MOVE_PRI,
843 &&SWITCHTABLE_EMBRYO_OP_MOVE_ALT,
844 &&SWITCHTABLE_EMBRYO_OP_XCHG,
845 &&SWITCHTABLE_EMBRYO_OP_PUSH_PRI,
846 &&SWITCHTABLE_EMBRYO_OP_PUSH_ALT,
847 &&SWITCHTABLE_EMBRYO_OP_PUSH_R,
848 &&SWITCHTABLE_EMBRYO_OP_PUSH_C,
849 &&SWITCHTABLE_EMBRYO_OP_PUSH,
850 &&SWITCHTABLE_EMBRYO_OP_PUSH_S,
851 &&SWITCHTABLE_EMBRYO_OP_POP_PRI,
852 &&SWITCHTABLE_EMBRYO_OP_POP_ALT,
853 &&SWITCHTABLE_EMBRYO_OP_STACK,
854 &&SWITCHTABLE_EMBRYO_OP_HEAP,
855 &&SWITCHTABLE_EMBRYO_OP_PROC,
856 &&SWITCHTABLE_EMBRYO_OP_RET,
857 &&SWITCHTABLE_EMBRYO_OP_RETN,
858 &&SWITCHTABLE_EMBRYO_OP_CALL,
859 &&SWITCHTABLE_EMBRYO_OP_CALL_PRI,
860 &&SWITCHTABLE_EMBRYO_OP_JUMP,
861 &&SWITCHTABLE_EMBRYO_OP_JREL,
862 &&SWITCHTABLE_EMBRYO_OP_JZER,
863 &&SWITCHTABLE_EMBRYO_OP_JNZ,
864 &&SWITCHTABLE_EMBRYO_OP_JEQ,
865 &&SWITCHTABLE_EMBRYO_OP_JNEQ,
866 &&SWITCHTABLE_EMBRYO_OP_JLESS,
867 &&SWITCHTABLE_EMBRYO_OP_JLEQ,
868 &&SWITCHTABLE_EMBRYO_OP_JGRTR,
869 &&SWITCHTABLE_EMBRYO_OP_JGEQ,
870 &&SWITCHTABLE_EMBRYO_OP_JSLESS,
871 &&SWITCHTABLE_EMBRYO_OP_JSLEQ,
872 &&SWITCHTABLE_EMBRYO_OP_JSGRTR,
873 &&SWITCHTABLE_EMBRYO_OP_JSGEQ,
874 &&SWITCHTABLE_EMBRYO_OP_SHL,
875 &&SWITCHTABLE_EMBRYO_OP_SHR,
876 &&SWITCHTABLE_EMBRYO_OP_SSHR,
877 &&SWITCHTABLE_EMBRYO_OP_SHL_C_PRI,
878 &&SWITCHTABLE_EMBRYO_OP_SHL_C_ALT,
879 &&SWITCHTABLE_EMBRYO_OP_SHR_C_PRI,
880 &&SWITCHTABLE_EMBRYO_OP_SHR_C_ALT,
881 &&SWITCHTABLE_EMBRYO_OP_SMUL,
882 &&SWITCHTABLE_EMBRYO_OP_SDIV,
883 &&SWITCHTABLE_EMBRYO_OP_SDIV_ALT,
884 &&SWITCHTABLE_EMBRYO_OP_UMUL,
885 &&SWITCHTABLE_EMBRYO_OP_UDIV,
886 &&SWITCHTABLE_EMBRYO_OP_UDIV_ALT,
887 &&SWITCHTABLE_EMBRYO_OP_ADD,
888 &&SWITCHTABLE_EMBRYO_OP_SUB,
889 &&SWITCHTABLE_EMBRYO_OP_SUB_ALT,
890 &&SWITCHTABLE_EMBRYO_OP_AND,
891 &&SWITCHTABLE_EMBRYO_OP_OR,
892 &&SWITCHTABLE_EMBRYO_OP_XOR,
893 &&SWITCHTABLE_EMBRYO_OP_NOT,
894 &&SWITCHTABLE_EMBRYO_OP_NEG,
895 &&SWITCHTABLE_EMBRYO_OP_INVERT,
896 &&SWITCHTABLE_EMBRYO_OP_ADD_C,
897 &&SWITCHTABLE_EMBRYO_OP_SMUL_C,
898 &&SWITCHTABLE_EMBRYO_OP_ZERO_PRI,
899 &&SWITCHTABLE_EMBRYO_OP_ZERO_ALT,
900 &&SWITCHTABLE_EMBRYO_OP_ZERO,
901 &&SWITCHTABLE_EMBRYO_OP_ZERO_S,
902 &&SWITCHTABLE_EMBRYO_OP_SIGN_PRI,
903 &&SWITCHTABLE_EMBRYO_OP_SIGN_ALT,
904 &&SWITCHTABLE_EMBRYO_OP_EQ,
905 &&SWITCHTABLE_EMBRYO_OP_NEQ,
906 &&SWITCHTABLE_EMBRYO_OP_LESS,
907 &&SWITCHTABLE_EMBRYO_OP_LEQ,
908 &&SWITCHTABLE_EMBRYO_OP_GRTR,
909 &&SWITCHTABLE_EMBRYO_OP_GEQ,
910 &&SWITCHTABLE_EMBRYO_OP_SLESS,
911 &&SWITCHTABLE_EMBRYO_OP_SLEQ,
912 &&SWITCHTABLE_EMBRYO_OP_SGRTR,
913 &&SWITCHTABLE_EMBRYO_OP_SGEQ,
914 &&SWITCHTABLE_EMBRYO_OP_EQ_C_PRI,
915 &&SWITCHTABLE_EMBRYO_OP_EQ_C_ALT,
916 &&SWITCHTABLE_EMBRYO_OP_INC_PRI,
917 &&SWITCHTABLE_EMBRYO_OP_INC_ALT,
918 &&SWITCHTABLE_EMBRYO_OP_INC,
919 &&SWITCHTABLE_EMBRYO_OP_INC_S,
920 &&SWITCHTABLE_EMBRYO_OP_INC_I,
921 &&SWITCHTABLE_EMBRYO_OP_DEC_PRI,
922 &&SWITCHTABLE_EMBRYO_OP_DEC_ALT,
923 &&SWITCHTABLE_EMBRYO_OP_DEC,
924 &&SWITCHTABLE_EMBRYO_OP_DEC_S,
925 &&SWITCHTABLE_EMBRYO_OP_DEC_I,
926 &&SWITCHTABLE_EMBRYO_OP_MOVS,
927 &&SWITCHTABLE_EMBRYO_OP_CMPS,
928 &&SWITCHTABLE_EMBRYO_OP_FILL,
929 &&SWITCHTABLE_EMBRYO_OP_HALT,
930 &&SWITCHTABLE_EMBRYO_OP_BOUNDS,
931 &&SWITCHTABLE_EMBRYO_OP_SYSREQ_PRI,
932 &&SWITCHTABLE_EMBRYO_OP_SYSREQ_C,
933 &&SWITCHTABLE_EMBRYO_OP_FILE,
934 &&SWITCHTABLE_EMBRYO_OP_LINE,
935 &&SWITCHTABLE_EMBRYO_OP_SYMBOL,
936 &&SWITCHTABLE_EMBRYO_OP_SRANGE,
937 &&SWITCHTABLE_EMBRYO_OP_JUMP_PRI,
938 &&SWITCHTABLE_EMBRYO_OP_SWITCH,
939 &&SWITCHTABLE_EMBRYO_OP_CASETBL,
940 &&SWITCHTABLE_EMBRYO_OP_SWAP_PRI,
941 &&SWITCHTABLE_EMBRYO_OP_SWAP_ALT,
942 &&SWITCHTABLE_EMBRYO_OP_PUSHADDR,
943 &&SWITCHTABLE_EMBRYO_OP_NOP,
944 &&SWITCHTABLE_EMBRYO_OP_SYSREQ_D,
945 &&SWITCHTABLE_EMBRYO_OP_SYMTAG,
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, &&SWITCHTABLE_EMBRYO_OP_NONE,
967 &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE,
968 &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE,
969 &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE
972 if (!ep) return EMBRYO_PROGRAM_FAIL;
973 if (!(ep->flags & EMBRYO_FLAG_RELOC))
975 ep->error = EMBRYO_ERROR_INIT;
976 return EMBRYO_PROGRAM_FAIL;
980 ep->error = EMBRYO_ERROR_INIT;
981 return EMBRYO_PROGRAM_FAIL;
983 if (ep->run_count > 0)
985 /* return EMBRYO_PROGRAM_BUSY; */
986 /* FIXME: test C->vm->C->vm recursion more fully */
987 /* it seems to work... just fine!!! - strange! */
990 /* set up the registers */
991 hdr = (Embryo_Header *)ep->base;
992 codesize = (Embryo_UCell)(hdr->dat - hdr->cod);
993 code = ep->base + (int)hdr->cod;
994 data = ep->base + (int)hdr->dat;
995 hea_start = hea = ep->hea;
1001 /* get the start address */
1002 if (fn == EMBRYO_FUNCTION_MAIN)
1006 ep->error = EMBRYO_ERROR_INDEX;
1007 return EMBRYO_PROGRAM_FAIL;
1009 cip = (Embryo_Cell *)(code + (int)hdr->cip);
1011 else if (fn == EMBRYO_FUNCTION_CONT)
1013 /* all registers: pri, alt, frm, cip, hea, stk, reset_stk, reset_hea */
1019 reset_stk = ep->reset_stk;
1020 reset_hea = ep->reset_hea;
1021 cip = (Embryo_Cell *)(code + (int)ep->cip);
1025 ep->error = EMBRYO_ERROR_INDEX;
1026 return EMBRYO_PROGRAM_FAIL;
1030 if (fn >= (Embryo_Cell)NUMENTRIES(hdr, publics, natives))
1032 ep->error = EMBRYO_ERROR_INDEX;
1033 return EMBRYO_PROGRAM_FAIL;
1035 func = GETENTRY(hdr, publics, fn);
1036 cip = (Embryo_Cell *)(code + (int)func->address);
1038 /* check values just copied */
1042 if (fn != EMBRYO_FUNCTION_CONT)
1046 for (i = ep->params_size - 1; i >= 0; i--)
1050 pr = &(ep->params[i]);
1054 Embryo_Cell ep_addr, *addr;
1056 len = strlen(pr->string);
1057 ep_addr = embryo_data_heap_push(ep, len + 1);
1058 if (ep_addr == EMBRYO_CELL_NONE)
1060 ep->error = EMBRYO_ERROR_HEAPLOW;
1061 return EMBRYO_PROGRAM_FAIL;
1063 addr = embryo_data_address_get(ep, ep_addr);
1065 embryo_data_string_set(ep, pr->string, addr);
1068 ep->error = EMBRYO_ERROR_HEAPLOW;
1069 return EMBRYO_PROGRAM_FAIL;
1074 else if (pr->cell_array)
1077 Embryo_Cell ep_addr, *addr;
1079 len = pr->cell_array_size;
1080 ep_addr = embryo_data_heap_push(ep, len + 1);
1081 if (ep_addr == EMBRYO_CELL_NONE)
1083 ep->error = EMBRYO_ERROR_HEAPLOW;
1084 return EMBRYO_PROGRAM_FAIL;
1086 addr = embryo_data_address_get(ep, ep_addr);
1088 memcpy(addr, pr->cell_array,
1089 pr->cell_array_size * sizeof(Embryo_Cell));
1092 ep->error = EMBRYO_ERROR_HEAPLOW;
1093 return EMBRYO_PROGRAM_FAIL;
1096 free(pr->cell_array);
1103 PUSH(ep->params_size * sizeof(Embryo_Cell));
1110 ep->params_size = ep->params_alloc = 0;
1112 /* check stack/heap before starting to run */
1115 /* track recursion depth */
1118 max_run_cycles = ep->max_run_cycles;
1120 for (cycle_count = 0;;)
1122 if (max_run_cycles > 0)
1124 if (cycle_count >= max_run_cycles)
1130 op = (Embryo_Opcode)*cip++;
1132 CASE(EMBRYO_OP_LOAD_PRI);
1134 pri = *(Embryo_Cell *)(data + (int)offs);
1136 CASE(EMBRYO_OP_LOAD_ALT);
1138 alt = *(Embryo_Cell *)(data + (int)offs);
1140 CASE(EMBRYO_OP_LOAD_S_PRI);
1142 pri = *(Embryo_Cell *)(data + (int)frm + (int)offs);
1144 CASE(EMBRYO_OP_LOAD_S_ALT);
1146 alt = *(Embryo_Cell *)(data + (int)frm + (int)offs);
1148 CASE(EMBRYO_OP_LREF_PRI);
1150 offs = *(Embryo_Cell *)(data + (int)offs);
1151 pri = *(Embryo_Cell *)(data + (int)offs);
1153 CASE(EMBRYO_OP_LREF_ALT);
1155 offs = *(Embryo_Cell *)(data + (int)offs);
1156 alt = *(Embryo_Cell *)(data + (int)offs);
1158 CASE(EMBRYO_OP_LREF_S_PRI);
1160 offs = *(Embryo_Cell *)(data + (int)frm + (int)offs);
1161 pri = *(Embryo_Cell *)(data + (int)offs);
1163 CASE(EMBRYO_OP_LREF_S_ALT);
1165 offs = *(Embryo_Cell *)(data + (int)frm + (int)offs);
1166 alt = *(Embryo_Cell *)(data + (int)offs);
1168 CASE(EMBRYO_OP_LOAD_I);
1170 pri = *(Embryo_Cell *)(data + (int)pri);
1172 CASE(EMBRYO_OP_LODB_I);
1178 pri = *(data + (int)pri);
1181 pri = *(unsigned short *)(data + (int)pri);
1184 pri = *(unsigned int *)(data + (int)pri);
1187 ABORT(ep, EMBRYO_ERROR_INVINSTR);
1191 CASE(EMBRYO_OP_CONST_PRI);
1194 CASE(EMBRYO_OP_CONST_ALT);
1197 CASE(EMBRYO_OP_ADDR_PRI);
1201 CASE(EMBRYO_OP_ADDR_ALT);
1205 CASE(EMBRYO_OP_STOR_PRI);
1207 *(Embryo_Cell *)(data + (int)offs) = pri;
1209 CASE(EMBRYO_OP_STOR_ALT);
1211 *(Embryo_Cell *)(data + (int)offs) = alt;
1213 CASE(EMBRYO_OP_STOR_S_PRI);
1215 *(Embryo_Cell *)(data + (int)frm + (int)offs) = pri;
1217 CASE(EMBRYO_OP_STOR_S_ALT);
1219 *(Embryo_Cell *)(data + (int)frm + (int)offs) = alt;
1221 CASE(EMBRYO_OP_SREF_PRI);
1223 offs = *(Embryo_Cell *)(data + (int)offs);
1224 *(Embryo_Cell *)(data + (int)offs) = pri;
1226 CASE(EMBRYO_OP_SREF_ALT);
1228 offs = *(Embryo_Cell *)(data + (int)offs);
1229 *(Embryo_Cell *)(data + (int)offs) = alt;
1231 CASE(EMBRYO_OP_SREF_S_PRI);
1233 offs = *(Embryo_Cell *)(data + (int)frm + (int)offs);
1234 *(Embryo_Cell *)(data + (int)offs) = pri;
1236 CASE(EMBRYO_OP_SREF_S_ALT);
1238 offs = *(Embryo_Cell *)(data + (int)frm + (int)offs);
1239 *(Embryo_Cell *)(data + (int)offs) = alt;
1241 CASE(EMBRYO_OP_STOR_I);
1243 *(Embryo_Cell *)(data + (int)alt) = pri;
1245 CASE(EMBRYO_OP_STRB_I);
1251 *(data + (int)alt) = (unsigned char)pri;
1254 *(unsigned short *)(data + (int)alt) = (unsigned short)pri;
1257 *(unsigned int *)(data + (int)alt) = (unsigned int)pri;
1260 ABORT(ep, EMBRYO_ERROR_INVINSTR);
1264 CASE(EMBRYO_OP_LIDX);
1265 offs = (pri * sizeof(Embryo_Cell)) + alt;
1267 pri = *(Embryo_Cell *)(data + (int)offs);
1269 CASE(EMBRYO_OP_LIDX_B);
1271 offs = (pri << (int)offs) + alt;
1273 pri = *(Embryo_Cell *)(data + (int)offs);
1275 CASE(EMBRYO_OP_IDXADDR);
1276 pri = (pri * sizeof(Embryo_Cell)) + alt;
1278 CASE(EMBRYO_OP_IDXADDR_B);
1280 pri = (pri << (int)offs) + alt;
1282 CASE(EMBRYO_OP_ALIGN_PRI);
1284 #ifdef WORDS_BIGENDIAN
1285 if ((size_t)offs < sizeof(Embryo_Cell))
1286 pri ^= sizeof(Embryo_Cell) - offs;
1289 CASE(EMBRYO_OP_ALIGN_ALT);
1291 #ifdef WORDS_BIGENDIAN
1292 if ((size_t)offs < sizeof(Embryo_Cell))
1293 alt ^= sizeof(Embryo_Cell) - offs;
1296 CASE(EMBRYO_OP_LCTRL);
1319 pri = (Embryo_Cell)((unsigned char *)cip - code);
1322 ABORT(ep, EMBRYO_ERROR_INVINSTR);
1326 CASE(EMBRYO_OP_SCTRL);
1336 /* cannot change these parameters */
1345 cip = (Embryo_Cell *)(code + (int)pri);
1348 ABORT(ep, EMBRYO_ERROR_INVINSTR);
1352 CASE(EMBRYO_OP_MOVE_PRI);
1355 CASE(EMBRYO_OP_MOVE_ALT);
1358 CASE(EMBRYO_OP_XCHG);
1359 offs = pri; /* offs is a temporary variable */
1363 CASE(EMBRYO_OP_PUSH_PRI);
1366 CASE(EMBRYO_OP_PUSH_ALT);
1369 CASE(EMBRYO_OP_PUSH_C);
1373 CASE(EMBRYO_OP_PUSH_R);
1375 while (offs--) PUSH(pri);
1377 CASE(EMBRYO_OP_PUSH);
1379 PUSH(*(Embryo_Cell *)(data + (int)offs));
1381 CASE(EMBRYO_OP_PUSH_S);
1383 PUSH(*(Embryo_Cell *)(data + (int)frm + (int)offs));
1385 CASE(EMBRYO_OP_POP_PRI);
1388 CASE(EMBRYO_OP_POP_ALT);
1391 CASE(EMBRYO_OP_STACK);
1398 CASE(EMBRYO_OP_HEAP);
1405 CASE(EMBRYO_OP_PROC);
1410 CASE(EMBRYO_OP_RET);
1413 if ((Embryo_UCell)offs >= codesize)
1414 ABORT(ep, EMBRYO_ERROR_MEMACCESS);
1415 cip = (Embryo_Cell *)(code + (int)offs);
1417 CASE(EMBRYO_OP_RETN);
1420 if ((Embryo_UCell)offs >= codesize)
1421 ABORT(ep, EMBRYO_ERROR_MEMACCESS);
1422 cip = (Embryo_Cell *)(code + (int)offs);
1423 stk += *(Embryo_Cell *)(data + (int)stk) + sizeof(Embryo_Cell); /* remove parameters from the stack */
1426 CASE(EMBRYO_OP_CALL);
1427 PUSH(((unsigned char *)cip - code) + sizeof(Embryo_Cell));/* skip address */
1428 cip = JUMPABS(code, cip); /* jump to the address */
1430 CASE(EMBRYO_OP_CALL_PRI);
1431 PUSH((unsigned char *)cip - code);
1432 cip = (Embryo_Cell *)(code + (int)pri);
1434 CASE(EMBRYO_OP_JUMP);
1435 /* since the GETPARAM() macro modifies cip, you cannot
1436 * do GETPARAM(cip) directly */
1437 cip = JUMPABS(code, cip);
1439 CASE(EMBRYO_OP_JREL);
1441 cip = (Embryo_Cell *)((unsigned char *)cip + (int)offs + sizeof(Embryo_Cell));
1443 CASE(EMBRYO_OP_JZER);
1445 cip = JUMPABS(code, cip);
1447 cip = (Embryo_Cell *)((unsigned char *)cip + sizeof(Embryo_Cell));
1449 CASE(EMBRYO_OP_JNZ);
1451 cip = JUMPABS(code, cip);
1453 cip = (Embryo_Cell *)((unsigned char *)cip + sizeof(Embryo_Cell));
1455 CASE(EMBRYO_OP_JEQ);
1457 cip = JUMPABS(code, cip);
1459 cip = (Embryo_Cell *)((unsigned char *)cip + sizeof(Embryo_Cell));
1461 CASE(EMBRYO_OP_JNEQ);
1463 cip = JUMPABS(code, cip);
1465 cip = (Embryo_Cell *)((unsigned char *)cip + sizeof(Embryo_Cell));
1467 CASE(EMBRYO_OP_JLESS);
1468 if ((Embryo_UCell)pri < (Embryo_UCell)alt)
1469 cip = JUMPABS(code, cip);
1471 cip = (Embryo_Cell *)((unsigned char *)cip + sizeof(Embryo_Cell));
1473 CASE(EMBRYO_OP_JLEQ);
1474 if ((Embryo_UCell)pri <= (Embryo_UCell)alt)
1475 cip = JUMPABS(code, cip);
1477 cip = (Embryo_Cell *)((unsigned char *)cip + sizeof(Embryo_Cell));
1479 CASE(EMBRYO_OP_JGRTR);
1480 if ((Embryo_UCell)pri > (Embryo_UCell)alt)
1481 cip = JUMPABS(code, cip);
1483 cip = (Embryo_Cell *)((unsigned char *)cip + sizeof(Embryo_Cell));
1485 CASE(EMBRYO_OP_JGEQ);
1486 if ((Embryo_UCell)pri >= (Embryo_UCell)alt)
1487 cip = JUMPABS(code, cip);
1489 cip = (Embryo_Cell *)((unsigned char *)cip + sizeof(Embryo_Cell));
1491 CASE(EMBRYO_OP_JSLESS);
1493 cip = JUMPABS(code, cip);
1495 cip = (Embryo_Cell *)((unsigned char *)cip + sizeof(Embryo_Cell));
1497 CASE(EMBRYO_OP_JSLEQ);
1499 cip = JUMPABS(code, cip);
1501 cip = (Embryo_Cell *)((unsigned char *)cip + sizeof(Embryo_Cell));
1503 CASE(EMBRYO_OP_JSGRTR);
1505 cip = JUMPABS(code, cip);
1507 cip = (Embryo_Cell *)((unsigned char *)cip + sizeof(Embryo_Cell));
1509 CASE(EMBRYO_OP_JSGEQ);
1511 cip = JUMPABS(code, cip);
1513 cip = (Embryo_Cell *)((unsigned char *)cip + sizeof(Embryo_Cell));
1515 CASE(EMBRYO_OP_SHL);
1518 CASE(EMBRYO_OP_SHR);
1519 pri = (Embryo_UCell)pri >> (int)alt;
1521 CASE(EMBRYO_OP_SSHR);
1524 CASE(EMBRYO_OP_SHL_C_PRI);
1528 CASE(EMBRYO_OP_SHL_C_ALT);
1532 CASE(EMBRYO_OP_SHR_C_PRI);
1534 pri = (Embryo_UCell)pri >> (int)offs;
1536 CASE(EMBRYO_OP_SHR_C_ALT);
1538 alt = (Embryo_UCell)alt >> (int)offs;
1540 CASE(EMBRYO_OP_SMUL);
1543 CASE(EMBRYO_OP_SDIV);
1544 if (alt == 0) ABORT(ep, EMBRYO_ERROR_DIVIDE);
1545 /* divide must always round down; this is a bit
1546 * involved to do in a machine-independent way.
1548 offs = ((pri % alt) + alt) % alt; /* true modulus */
1549 pri = (pri - offs) / alt; /* division result */
1552 CASE(EMBRYO_OP_SDIV_ALT);
1553 if (pri == 0) ABORT(ep, EMBRYO_ERROR_DIVIDE);
1554 /* divide must always round down; this is a bit
1555 * involved to do in a machine-independent way.
1557 offs = ((alt % pri) + pri) % pri; /* true modulus */
1558 pri = (alt - offs) / pri; /* division result */
1561 CASE(EMBRYO_OP_UMUL);
1562 pri = (Embryo_UCell)pri * (Embryo_UCell)alt;
1564 CASE(EMBRYO_OP_UDIV);
1565 if (alt == 0) ABORT(ep, EMBRYO_ERROR_DIVIDE);
1566 offs = (Embryo_UCell)pri % (Embryo_UCell)alt; /* temporary storage */
1567 pri = (Embryo_UCell)pri / (Embryo_UCell)alt;
1570 CASE(EMBRYO_OP_UDIV_ALT);
1571 if (pri == 0) ABORT(ep, EMBRYO_ERROR_DIVIDE);
1572 offs = (Embryo_UCell)alt % (Embryo_UCell)pri; /* temporary storage */
1573 pri = (Embryo_UCell)alt / (Embryo_UCell)pri;
1576 CASE(EMBRYO_OP_ADD);
1579 CASE(EMBRYO_OP_SUB);
1582 CASE(EMBRYO_OP_SUB_ALT);
1585 CASE(EMBRYO_OP_AND);
1591 CASE(EMBRYO_OP_XOR);
1594 CASE(EMBRYO_OP_NOT);
1597 CASE(EMBRYO_OP_NEG);
1600 CASE(EMBRYO_OP_INVERT);
1603 CASE(EMBRYO_OP_ADD_C);
1607 CASE(EMBRYO_OP_SMUL_C);
1611 CASE(EMBRYO_OP_ZERO_PRI);
1614 CASE(EMBRYO_OP_ZERO_ALT);
1617 CASE(EMBRYO_OP_ZERO);
1619 *(Embryo_Cell *)(data + (int)offs) = 0;
1621 CASE(EMBRYO_OP_ZERO_S);
1623 *(Embryo_Cell *)(data + (int)frm + (int)offs) = 0;
1625 CASE(EMBRYO_OP_SIGN_PRI);
1626 if ((pri & 0xff) >= 0x80) pri |= ~(Embryo_UCell)0xff;
1628 CASE(EMBRYO_OP_SIGN_ALT);
1629 if ((alt & 0xff) >= 0x80) alt |= ~(Embryo_UCell)0xff;
1632 pri = (pri == alt) ? 1 : 0;
1634 CASE(EMBRYO_OP_NEQ);
1635 pri = (pri != alt) ? 1 : 0;
1637 CASE(EMBRYO_OP_LESS);
1638 pri = ((Embryo_UCell)pri < (Embryo_UCell)alt) ? 1 : 0;
1640 CASE(EMBRYO_OP_LEQ);
1641 pri = ((Embryo_UCell)pri <= (Embryo_UCell)alt) ? 1 : 0;
1643 CASE(EMBRYO_OP_GRTR);
1644 pri = ((Embryo_UCell)pri > (Embryo_UCell)alt) ? 1 : 0;
1646 CASE(EMBRYO_OP_GEQ);
1647 pri = ((Embryo_UCell)pri >= (Embryo_UCell)alt) ? 1 : 0;
1649 CASE(EMBRYO_OP_SLESS);
1650 pri = (pri < alt) ? 1 : 0;
1652 CASE(EMBRYO_OP_SLEQ);
1653 pri = (pri <= alt) ? 1 : 0;
1655 CASE(EMBRYO_OP_SGRTR);
1656 pri = (pri > alt) ? 1 : 0;
1658 CASE(EMBRYO_OP_SGEQ);
1659 pri = (pri >= alt) ? 1 : 0;
1661 CASE(EMBRYO_OP_EQ_C_PRI);
1663 pri = (pri == offs) ? 1 : 0;
1665 CASE(EMBRYO_OP_EQ_C_ALT);
1667 pri = (alt == offs) ? 1 : 0;
1669 CASE(EMBRYO_OP_INC_PRI);
1672 CASE(EMBRYO_OP_INC_ALT);
1675 CASE(EMBRYO_OP_INC);
1677 *(Embryo_Cell *)(data + (int)offs) += 1;
1679 CASE(EMBRYO_OP_INC_S);
1681 *(Embryo_Cell *)(data + (int)frm + (int)offs) += 1;
1683 CASE(EMBRYO_OP_INC_I);
1684 *(Embryo_Cell *)(data + (int)pri) += 1;
1686 CASE(EMBRYO_OP_DEC_PRI);
1689 CASE(EMBRYO_OP_DEC_ALT);
1692 CASE(EMBRYO_OP_DEC);
1694 *(Embryo_Cell *)(data + (int)offs) -= 1;
1696 CASE(EMBRYO_OP_DEC_S);
1698 *(Embryo_Cell *)(data + (int)frm + (int)offs) -= 1;
1700 CASE(EMBRYO_OP_DEC_I);
1701 *(Embryo_Cell *)(data + (int)pri) -= 1;
1703 CASE(EMBRYO_OP_MOVS);
1709 memcpy(data+(int)alt, data+(int)pri, (int)offs);
1711 CASE(EMBRYO_OP_CMPS);
1717 pri = memcmp(data + (int)alt, data + (int)pri, (int)offs);
1719 CASE(EMBRYO_OP_FILL);
1724 (size_t)offs >= sizeof(Embryo_Cell);
1725 i += sizeof(Embryo_Cell), offs -= sizeof(Embryo_Cell))
1726 *(Embryo_Cell *)(data + i) = pri;
1728 CASE(EMBRYO_OP_HALT);
1731 /* store complete status */
1737 ep->cip = (Embryo_Cell)((unsigned char*)cip - code);
1738 if (offs == EMBRYO_ERROR_SLEEP)
1740 ep->reset_stk = reset_stk;
1741 ep->reset_hea = reset_hea;
1743 return EMBRYO_PROGRAM_SLEEP;
1746 CASE(EMBRYO_OP_BOUNDS);
1748 if ((Embryo_UCell)pri > (Embryo_UCell)offs)
1749 ABORT(ep, EMBRYO_ERROR_BOUNDS);
1751 CASE(EMBRYO_OP_SYSREQ_PRI);
1752 /* save a few registers */
1753 ep->cip = (Embryo_Cell)((unsigned char *)cip - code);
1757 num = _embryo_native_call(ep, pri, &pri, (Embryo_Cell *)(data + (int)stk));
1758 if (num != EMBRYO_ERROR_NONE)
1760 if (num == EMBRYO_ERROR_SLEEP)
1764 ep->reset_stk = reset_stk;
1765 ep->reset_hea = reset_hea;
1767 return EMBRYO_PROGRAM_SLEEP;
1772 CASE(EMBRYO_OP_SYSREQ_C);
1774 /* save a few registers */
1775 ep->cip = (Embryo_Cell)((unsigned char *)cip - code);
1779 num = _embryo_native_call(ep, offs, &pri, (Embryo_Cell *)(data + (int)stk));
1780 if (num != EMBRYO_ERROR_NONE)
1782 if (num == EMBRYO_ERROR_SLEEP)
1786 ep->reset_stk = reset_stk;
1787 ep->reset_hea = reset_hea;
1789 return EMBRYO_PROGRAM_SLEEP;
1794 Embryo_Func_Stub *func_entry;
1796 hdr = (Embryo_Header *)ep->code;
1797 num = NUMENTRIES(hdr, natives, libraries);
1798 func_entry = GETENTRY(hdr, natives, 0);
1799 for (i = 0; i < num; i++)
1803 entry_name = GETENTRYNAME(hdr, func_entry);
1805 printf("EMBRYO: CALL [%i] %s() non-existent!\n", i, entry_name);
1807 (Embryo_Func_Stub *)((unsigned char *)func_entry + hdr->defsize);
1813 CASE(EMBRYO_OP_SYSREQ_D);
1815 /* save a few registers */
1816 ep->cip = (Embryo_Cell)((unsigned char *)cip - code);
1820 num = _embryo_native_call(ep, offs, &pri, (Embryo_Cell *)(data + (int)stk));
1821 if (num != EMBRYO_ERROR_NONE)
1823 if (num == EMBRYO_ERROR_SLEEP)
1827 ep->reset_stk = reset_stk;
1828 ep->reset_hea = reset_hea;
1830 return EMBRYO_PROGRAM_SLEEP;
1832 ABORT(ep, ep->error);
1835 CASE(EMBRYO_OP_JUMP_PRI);
1836 cip = (Embryo_Cell *)(code + (int)pri);
1838 CASE(EMBRYO_OP_SWITCH);
1842 /* +1, to skip the "casetbl" opcode */
1843 cptr = (Embryo_Cell *)(code + (*cip)) + 1;
1844 /* number of records in the case table */
1846 /* preset to "none-matched" case */
1847 cip = (Embryo_Cell *)(code + *(cptr + 1));
1849 (num > 0) && (*cptr != pri);
1853 cip = (Embryo_Cell *)(code + *(cptr + 1));
1856 CASE(EMBRYO_OP_SWAP_PRI);
1857 offs = *(Embryo_Cell *)(data + (int)stk);
1858 *(Embryo_Cell *)(data + (int)stk) = pri;
1861 CASE(EMBRYO_OP_SWAP_ALT);
1862 offs = *(Embryo_Cell *)(data + (int)stk);
1863 *(Embryo_Cell *)(data + (int)stk) = alt;
1866 CASE(EMBRYO_OP_PUSHADDR);
1870 CASE(EMBRYO_OP_NOP);
1872 CASE(EMBRYO_OP_NONE);
1873 CASE(EMBRYO_OP_FILE);
1874 CASE(EMBRYO_OP_LINE);
1875 CASE(EMBRYO_OP_SYMBOL);
1876 CASE(EMBRYO_OP_SRANGE);
1877 CASE(EMBRYO_OP_CASETBL);
1878 CASE(EMBRYO_OP_SYMTAG);
1880 #ifndef EMBRYO_EXEC_JUMPTABLE
1882 ABORT(ep, EMBRYO_ERROR_INVINSTR);
1886 ep->max_run_cycles = max_run_cycles;
1888 ep->hea = hea_start;
1889 return EMBRYO_PROGRAM_OK;
1893 embryo_program_return_value_get(Embryo_Program *ep)
1900 embryo_program_max_cycle_run_set(Embryo_Program *ep, int max)
1903 if (max < 0) max = 0;
1904 ep->max_run_cycles = max;
1908 embryo_program_max_cycle_run_get(Embryo_Program *ep)
1911 return ep->max_run_cycles;
1916 embryo_parameter_cell_push(Embryo_Program *ep, Embryo_Cell cell)
1921 if (ep->params_size > ep->params_alloc)
1923 ep->params_alloc += 8;
1924 pr = realloc(ep->params, ep->params_alloc * sizeof(Embryo_Param));
1928 pr = &(ep->params[ep->params_size - 1]);
1930 pr->cell_array = NULL;
1931 pr->cell_array_size = 0;
1938 embryo_parameter_string_push(Embryo_Program *ep, const char *str)
1944 return embryo_parameter_string_push(ep, "");
1945 str_dup = strdup(str);
1946 if (!str_dup) return 0;
1948 if (ep->params_size > ep->params_alloc)
1950 ep->params_alloc += 8;
1951 pr = realloc(ep->params, ep->params_alloc * sizeof(Embryo_Param));
1959 pr = &(ep->params[ep->params_size - 1]);
1961 pr->cell_array = NULL;
1962 pr->cell_array_size = 0;
1964 pr->string = str_dup;
1969 embryo_parameter_cell_array_push(Embryo_Program *ep, Embryo_Cell *cells, int num)
1972 Embryo_Cell *cell_array;
1974 if ((!cells) || (num <= 0))
1975 return embryo_parameter_cell_push(ep, 0);
1976 cell_array = malloc(num * sizeof(Embryo_Cell));
1978 if (ep->params_size > ep->params_alloc)
1980 ep->params_alloc += 8;
1981 pr = realloc(ep->params, ep->params_alloc * sizeof(Embryo_Param));
1989 pr = &(ep->params[ep->params_size - 1]);
1991 pr->cell_array = NULL;
1992 pr->cell_array_size = 0;
1994 pr->cell_array = cell_array;
1995 pr->cell_array_size = num;
1996 memcpy(pr->cell_array, cells, num * sizeof(Embryo_Cell));