1 /* DLIFE Copyright (C) 2000 Richard W.M. Jones <rich@annexia.org>
2 * and other authors listed in the ``AUTHORS'' file.
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 * $Id: exec.c,v 1.2 2002/04/05 16:47:12 rich Exp $
33 static void trace (const struct cell *cell, int insn);
36 unsigned long long cell_cycle = 0;
39 get_pattern_length (struct state *state, const struct cell *cell)
44 /* XXX Maximum pattern length? */
45 /* XXX What if pattern exceeds limits of the cell? */
46 while ((c = get_soup (state, cell->frag, p) & 0x3F) == 0 || c == 1)
55 check_access (struct state *state, const struct cell *cell, reg_t raddr)
57 if (raddr >= 0 && raddr < cell->frag->len) /* In mother? */
59 if (cell->daughter) /* In daughter? */
61 int offset = cell->daughter->frag->base - cell->frag->base;
63 /* Be careful with the wrap-around case here. */
64 if (((raddr - offset) & (state->soup_size - 1)) >= 0 &&
65 ((raddr - offset) & (state->soup_size - 1)) < cell->daughter->frag->len)
72 check_exec_access (struct state *state, const struct cell *cell, reg_t raddr)
74 if (raddr >= 0 && raddr < cell->frag->len) /* In mother? */
80 push (struct cell *cell, reg_t v)
82 cell->sp = (cell->sp+1) & (STACK_SIZE-1);
83 cell->stack[cell->sp] = v;
87 pop (struct cell *cell, reg_t *va)
89 *va = cell->stack[cell->sp];
90 cell->sp = (cell->sp-1) & (STACK_SIZE-1);
94 exec_insn (struct state *state, struct cell *cell)
96 /* Increment cycle counters. */
101 if (cell->state == state_exec)
106 /* Fetch next insn. */
107 if (check_exec_access (state, cell, cell->p) ||
108 chance (access_control_failure))
110 insn = get_soup (state, cell->frag, cell->p);
114 INC_ERRORS (state, cell);
122 /* By doing this we allow the cell to use the top two bits of
123 * each instruction byte for its own purposes. DNA uses a similar
124 * technique - it can mark up basic sequences by adding its
125 * own arbitrary chemical markers to each base.
133 if (chance (soup_fetch_failure))
135 insn = get_rand_byte () & 0x3f;
139 if (!chance (inc_pc_failure))
144 /* Is this insn going to generate an error? Handle that case
145 * separately (don't disturb the fast path).
147 error = chance (insn_exec_failure);
155 return; /* Ignore. */
167 goto next; /* Fetch and execute next instruction. */
168 /* Else skip next insn. */
172 if ((cell->plen = get_pattern_length (state, cell)) > 0)
174 cell->state = state_find;
176 cell->i = cell->p - 2;
177 cell->lim = FIND_LENGTH_LIMIT;
181 INC_ERRORS (state, cell);
186 if ((cell->plen = get_pattern_length (state, cell)) > 0)
188 cell->state = state_find;
190 cell->i = cell->p + cell->plen + 1;
191 cell->lim = FIND_LENGTH_LIMIT;
195 INC_ERRORS (state, cell);
199 case 0x0a: /* MALLOC */
200 if (!cell->daughter &&
201 cell->a >= MIN_CELL_SIZE && cell->a <= MAX_CELL_SIZE)
203 struct soup_frag *frag
204 = soup_frag_malloc (state, cell->frag, cell->a);
208 = cell_malloc (state, cell, frag);
209 /* Calculate relative address of daughter */
211 = cell->daughter->frag->base
214 printf ("MALLOC: dfb = %d, fb = %d, i = %d\n",
215 cell->daughter->frag->base,
222 /* INC_ERRORS (state, cell); -- Dubious? */
228 INC_ERRORS (state, cell);
232 case 0x0b: /* DIVIDE */
235 cell_divide (state, cell, cell->daughter);
236 cell_activate (state, cell->daughter);
241 INC_ERRORS (state, cell);
245 case 0x0c: /* MOVE [I],A */
246 cell->a = get_soup (state, cell->frag, cell->i);
248 case 0x0d: /* MOVE A,[I] */
249 if (check_access (state, cell, cell->i) ||
250 chance (access_control_failure))
252 set_soup (state, cell->frag, cell->a, cell->i);
256 INC_ERRORS (state, cell);
259 case 0x0e: /* DMOVE [I],A */
260 cell->a = get_soup (state, cell->frag, cell->i) << 8;
261 cell->a |= get_soup (state, cell->frag, cell->i+1);
263 case 0x0f: /* DMOVE A,[I] */
264 if ((check_access (state, cell, cell->i) &&
265 check_access (state, cell, cell->i+1)) ||
266 chance (access_control_failure))
268 set_soup (state, cell->frag, cell->a >> 8, cell->i);
269 set_soup (state, cell->frag, cell->a & 0xff, cell->i+1);
273 INC_ERRORS (state, cell);
276 case 0x10: /* XOR A,A (ie. ZERO A) */
278 case 0x11: /* XOR B,A */
279 cell->a ^= cell->b; return;
280 case 0x12: /* XOR I,A */
281 cell->a ^= cell->i; return;
282 case 0x13: /* XOR P,A */
283 cell->a ^= cell->p; return;
284 case 0x14: /* XOR A,B */
285 cell->b ^= cell->a; return;
286 case 0x15: /* XOR B,B (ie. ZERO B) */
288 case 0x16: /* XOR I,B */
289 cell->b ^= cell->i; return;
290 case 0x17: /* XOR P,B */
291 cell->b ^= cell->p; return;
292 case 0x18: /* XOR A,I */
293 cell->i ^= cell->a; return;
294 case 0x19: /* XOR B,I */
295 cell->i ^= cell->b; return;
296 case 0x1a: /* XOR I,I (ie. ZERO I) */
298 case 0x1b: /* XOR P,I */
299 cell->i ^= cell->p; return;
300 /* Surely these next three instructions will never be used ... */
301 case 0x1c: /* XOR A,P */
302 cell->p ^= cell->a; return;
303 case 0x1d: /* XOR B,P */
304 cell->p ^= cell->b; return;
305 case 0x1e: /* XOR I,P */
306 cell->p ^= cell->i; return;
307 case 0x1f: /* XOR P,P (ie. ZERO P) */
309 case 0x20: /* PUSH A */
310 push (cell, cell->a);
312 case 0x21: /* PUSH B */
313 push (cell, cell->b);
315 case 0x22: /* PUSH I */
316 push (cell, cell->i);
318 case 0x23: /* PUSH P */
319 push (cell, cell->p);
321 case 0x24: /* POP A */
322 pop (cell, &cell->a);
324 case 0x25: /* POP B */
325 pop (cell, &cell->b);
327 case 0x26: /* POP I */
328 pop (cell, &cell->i);
330 case 0x27: /* POP P */
331 pop (cell, &cell->p);
334 default: /* Unknown instruction. */
335 INC_ERRORS (state, cell);
341 /* Slow path: insn will execute in error. */
358 goto next; /* Fetch and execute next instruction. */
359 /* Else skip next insn. */
370 case 0x0c: /* MOVE [I],A */
371 cell->a = get_soup (state, cell->frag, cell->i);
377 case 0x0d: /* MOVE A,[I] */
383 set_soup (state, cell->frag, cell->a+1, cell->i);
386 set_soup (state, cell->frag, cell->a-1, cell->i);
389 set_soup (state, cell->frag, cell->a, cell->i+1);
392 set_soup (state, cell->frag, cell->a, cell->i-1);
397 case 0x0e: /* DMOVE [I],A */
398 cell->a = get_soup (state, cell->frag, cell->i) << 8;
399 cell->a |= get_soup (state, cell->frag, cell->i+1);
405 case 0x0f: /* DMOVE A,[I] */
411 set_soup (state, cell->frag, (cell->a+1) >> 8, cell->i);
412 set_soup (state, cell->frag, (cell->a+1) & 0xFF, cell->i+1);
415 set_soup (state, cell->frag, (cell->a-1) >> 8, cell->i);
416 set_soup (state, cell->frag, (cell->a-1) & 0xFF, cell->i+1);
419 set_soup (state, cell->frag, cell->a >> 8, cell->i+1);
420 set_soup (state, cell->frag, cell->a & 0xFF, cell->i+2);
423 set_soup (state, cell->frag, cell->a >> 8, cell->i-1);
424 set_soup (state, cell->frag, cell->a & 0xFF, cell->i);
429 case 0x10: /* XOR ... */
432 cell->a = cell->b; return;
434 cell->a = cell->i; return;
436 cell->a = cell->p; return;
438 cell->b = cell->a; return;
442 cell->b = cell->i; return;
444 cell->b = cell->p; return;
446 cell->i = cell->a; return;
448 cell->i = cell->b; return;
452 cell->i = cell->p; return;
454 cell->p = cell->a; return;
456 cell->p = cell->b; return;
458 cell->p = cell->i; return;
464 else /* cell->state == state_find */
467 * cell->p == address of pattern complement to match
468 * cell->plen == length of pattern
469 * cell->i == current address of search
470 * cell->dir == direction of search (-1 or 1)
471 * cell->lim == number of steps before we give up
479 for (i = 0; i < cell->plen; ++i)
481 int pat = get_soup (state, cell->frag, cell->p+i);
482 int mat = get_soup (state, cell->frag, cell->i+i);
483 if (pat > 1 || mat > 1 || pat == mat)
485 /* Not matched: continue searching. */
486 cell->i += cell->dir;
492 INC_ERRORS (state, cell);
493 cell->state = state_exec;
494 cell->p += cell->plen;
501 /* Pattern matched! */
502 cell->p += cell->plen;
503 cell->state = state_exec;
510 trace (const struct cell *cell, int insn)
512 if (cell->state == state_exec)
514 printf ("x %p A:%d B:%d I:%d P:%d St:[%d %d %d..] e:%d [%p] ",
515 cell, cell->a, cell->b, cell->i, cell->p,
516 cell->stack[cell->sp],
517 cell->stack[(cell->sp-1) & (STACK_SIZE-1)],
518 cell->stack[(cell->sp-2) & (STACK_SIZE-1)],
523 case 0: printf ("NOP0"); break;
524 case 1: printf ("NOP1"); break;
525 case 2: printf ("INC A"); break;
526 case 3: printf ("DEC A"); break;
527 case 4: printf ("SHL A"); break;
528 case 7: printf ("IFZ"); break;
529 case 8: printf ("FINDB"); break;
530 case 9: printf ("FINDF"); break;
531 case 10: printf ("MALLOC"); break;
532 case 11: printf ("DIVIDE"); break;
533 case 12: printf ("MOVE [I],A"); break;
534 case 13: printf ("MOVE A,[I]"); break;
535 case 14: printf ("DMOVE [I],A"); break;
536 case 15: printf ("DMOVE A,[I]"); break;
537 case 16: case 17: case 18: case 19:
538 case 20: case 21: case 22: case 23:
539 case 24: case 25: case 26: case 27:
540 case 28: case 29: case 30: case 31:
541 printf ("XOR %c,%c", "ABIP"[insn&3], "ABIP"[(insn>>2)&3]); break;
542 case 32: case 33: case 34: case 35:
543 printf ("PUSH %c", "ABIP"[insn&3]); break;
544 case 36: case 37: case 38: case 39:
545 printf ("POP %c", "ABIP"[insn&3]); break;
546 default: printf ("unknown %d", insn); break;
552 printf ("f %p I:%d P:%d dir:%d plen:%d lim:%d\n",
553 cell, cell->i, cell->p, cell->dir, cell->plen, cell->lim);