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