1 /* RETRO ------------------------------------------------------ 2 A personal, minimalistic forth 3 Copyright (c) 2016 - 2020 Charles Childers 4 5 This is a minimalist implementation of an interactive 6 RETRO system with an embedded image and the listerner loop 7 being written in RETRO. 8 9 Building: 10 11 cp ngaImage barebones.image 12 retro-extend barebones.image interface/barebones.retro 13 retro-embedimage barebones.image >vm/nga-c/barebones_image.c 14 cd vm/nga-c 15 make barebones 16 ---------------------------------------------------------- */ 17 18 #include <stdio.h> 19 #include <stdint.h> 20 #include <stdlib.h> 21 #include <limits.h> 22 23 #define CELL int32_t 24 #define CELL_MIN INT_MIN + 1 25 #define CELL_MAX INT_MAX - 1 26 27 #define IMAGE_SIZE 242000 /* Amount of RAM. 968kB by default. */ 28 #define ADDRESSES 256 /* Depth of address stack */ 29 #define STACK_DEPTH 128 /* Depth of data stack */ 30 31 CELL memory[IMAGE_SIZE + 1]; /* The memory for the image */ 32 33 #define TOS cpu.data[cpu.sp] /* Shortcut for top item on stack */ 34 #define NOS cpu.data[cpu.sp-1] /* Shortcut for second item on stack */ 35 #define TORS cpu.address[cpu.rp] /* Shortcut for top item on address stack */ 36 37 struct NgaCore { 38 CELL sp, rp, ip; /* Stack & instruction pointers */ 39 CELL data[STACK_DEPTH]; /* The data stack */ 40 CELL address[ADDRESSES]; /* The address stack */ 41 } cpu; 42 43 #define NUM_DEVICES 2 44 45 typedef void (*Handler)(void); 46 47 Handler IO_deviceHandlers[NUM_DEVICES + 1]; 48 Handler IO_queryHandlers[NUM_DEVICES + 1]; 49 50 #include "barebones_image.c" 51 52 CELL stack_pop(); 53 void stack_push(CELL value); 54 void execute(CELL cell); 55 CELL load_image(); 56 void prepare_vm(); 57 void process_opcode(CELL opcode); 58 void process_opcode_bundle(CELL opcode); 59 int validate_opcode_bundle(CELL opcode); 60 stack_pop()61CELL stack_pop() { 62 cpu.sp--; 63 return cpu.data[cpu.sp + 1]; 64 } 65 stack_push(CELL value)66void stack_push(CELL value) { 67 cpu.sp++; 68 cpu.data[cpu.sp] = value; 69 } 70 generic_output()71void generic_output() { 72 putc(stack_pop(), stdout); 73 fflush(stdout); 74 } 75 generic_output_query()76void generic_output_query() { 77 stack_push(0); 78 stack_push(0); 79 } 80 generic_input()81void generic_input() { 82 stack_push(getc(stdin)); 83 if (TOS == 127) TOS = 8; 84 } 85 generic_input_query()86void generic_input_query() { 87 stack_push(0); 88 stack_push(1); 89 } 90 execute(CELL cell)91void execute(CELL cell) { 92 CELL opcode; 93 cpu.rp = 1; 94 cpu.ip = cell; 95 while (cpu.ip < IMAGE_SIZE) { 96 opcode = memory[cpu.ip]; 97 if (validate_opcode_bundle(opcode) != 0) { 98 process_opcode_bundle(opcode); 99 } else { 100 printf("Invalid instruction!\n"); 101 exit(1); 102 } 103 cpu.ip++; 104 if (cpu.rp == 0) 105 cpu.ip = IMAGE_SIZE; 106 } 107 } 108 main(int argc,char ** argv)109int main(int argc, char **argv) { 110 IO_deviceHandlers[0] = generic_output; 111 IO_deviceHandlers[1] = generic_input; 112 IO_queryHandlers[0] = generic_output_query; 113 IO_queryHandlers[1] = generic_input_query; 114 prepare_vm(); 115 load_image(); 116 execute(0); 117 exit(0); 118 } 119 120 #include "nga.c" 121