~crc_/retro-napia

2022e8a80c20d6ba8a420f6fe73d3b45b9c41a49 — crc 9 days ago 78c13cc master
factor out io; stubs for core-related instructions added

FossilOrigin-Name: a050da6e15fb41cde1bbe240bcca1ac1bd4867518b24c306e9434f05f1a09dbf
2 files changed, 146 insertions(+), 22 deletions(-)

M Makefile
M napia-mt.c
M Makefile => Makefile +1 -1
@@ 1,5 1,5 @@
default: napia-st napia-mt

napia-mt:
napia-mt: napia-mt.c
	cc -O2 -s -lpthread napia-mt.c -o napia-mt


M napia-mt.c => napia-mt.c +145 -21
@@ 816,6 816,150 @@ inst(cy)
  }
  end

/* -------------------------------------------------------------
  29  1D  io    n-    perform i/o operation

  I/O operations are somewhat dependent on the underlying host.

    I/O Device   Action
    ----------   -----------------------------------------
    0            Display a character. Consumes a character
                 from the stack.
    1            Read a character from the input device.
                 Character is pushed to the stack.
    2            Read a block into memory.
    3            Write memory to a block.
    4            Write all memory to an image/rom.
    5            Reload the image/rom, and jump to address 0.
                 Also resets the stack pointers to empty.
    6            End execution. On a hosted system, exit napia.
                 If native, suspend execution.
    7            Obtain stack depths. Pushes the data depth then
                 the address depth.
    8            Return current time as a unix timestamp

  I/O numbers below 64 are reserved. For custom I/O extensions,
  use a number 64 or above.
  ----------------------------------------------------------- */

inst(io)
  guard(z, 1, 0, 0);
  switch (pop(z)) {
    case 0: guard(z, 1, 0, 0);
            putc(pop(z), stdout); break;
    case 1: guard(z, 0, 1, 0);
            push(z, getc(stdin)); break;
    case 2: guard(z, 2, 0, 0);
            read_block(z); break;
    case 3: guard(z, 2, 0, 0);
            write_block(z); break;
    case 4: save_image(); break;
    case 5: restart_system(); break;
    case 6: z->ip = 65536; break;
    case 7: guard(z, 0, 2, 0);
            push(z, z->sp); push(z, z->rp); break;
    case 8: guard(z, 0, 1, 0);
            push(z, timestamp());
    default: break;
  }
  end

/* -------------------------------------------------------------
  30  1E  ic    n-    initialize a core

  Initialize a processor core. This will zero out all internal
  registers and empty the stacks.
  ----------------------------------------------------------- */

inst(ic)
  guard(z, 1, 0, 0);
  end

/* -------------------------------------------------------------
 31  1F  ac   an-    activate a core, sets core ip to a

  Set the IP of a core (n) to address (a). This does not alter
  the stacks or registers.
  ----------------------------------------------------------- */

inst(ac)
  guard(z, 2, 0, 0);
  end

/* -------------------------------------------------------------
  32  20  pc    n-    pause a core

  Pause a core.
  ----------------------------------------------------------- */

inst(pc)
  guard(z, 1, 0, 0);
  end

/* -------------------------------------------------------------
  33  21  sc    n-    resume/start a core

  Resume a paused core.
  ----------------------------------------------------------- */

inst(sc)
  guard(z, 1, 0, 0);
  end

/* -------------------------------------------------------------
  34  22  rr    n-n   read register n of current core

  Read register n (0-23) of the current core, and push the value
  to the stack.
  ----------------------------------------------------------- */

inst(rr)
  guard(z, 1, 1, 0);
  end

/* -------------------------------------------------------------
  35  23  wr   vn-    write value v to regster n of current core

  Write value (v) to register n (0-23) on the current core.
  ----------------------------------------------------------- */

inst(wr)
  guard(z, 2, 0, 0);
  end

/* -------------------------------------------------------------
  36  24  mx   a-     run code at address a on a solitary core

  Force a piece of code to run in a single core, suspending
  switching cores until done. (Does not affect interrputs)
  ----------------------------------------------------------- */

inst(mx)
  guard(z, 1, 0, 0);
  end

/* -------------------------------------------------------------
  37  25  sv   an-    set interrupt handler for n to addr. a

  Set the handler for interrupt n to function at address a.
  ----------------------------------------------------------- */

inst(sv)
  guard(z, 2, 0, 0);
  end

/* -------------------------------------------------------------
  38  26  ti    n-    trigger interrupt n

  Trigger execution of interrupt handler for interrupt n.
  ----------------------------------------------------------- */

inst(ti)
  guard(z, 1, 0, 0);
  end

// -------------------------------------------------------------

void process(CPU *z, int o) {
  int a, b, target, flag;
  int src, dest, len;


@@ 831,27 975,7 @@ void process(CPU *z, int o) {
    dispatch(18, ad)   dispatch(19, su)   dispatch(20, mu)
    dispatch(21, di)   dispatch(22, an)   dispatch(23, or)
    dispatch(24, xo)   dispatch(25, sl)   dispatch(26, sr)
    dispatch(27, cp)   dispatch(28, cy)
    case 29: guard(z, 1, 0, 0);
                switch (pop(z)) {
                  case 0: guard(z, 1, 0, 0);
                    putc(pop(z), stdout);break;
                  case 1: guard(z, 0, 1, 0);
                    push(z, getc(stdin)); break;
                  case 2: guard(z, 2, 0, 0);
                    read_block(z); break;
                  case 3: guard(z, 2, 0, 0);
                    write_block(z); break;
                  case 4: save_image(); break;
                  case 5: restart_system(); break;
                  case 6: z->ip = 65536; break;
                  case 7: guard(z, 0, 2, 0);
                    push(z, z->sp); push(z, z->rp); break;
                  case 8: guard(z, 0, 1, 0);
                    push(z, timestamp());
                  default: break;
                }
                break;
    dispatch(27, cp)   dispatch(28, cy)   dispatch(29, io)

    /* Cores (ic, ac, pc, sc, rr, wr */
    case 30: guard(z, 1, 0, 0);