/* * Equi platform reference implementation * * Created in 2022 by Luxferre, released into public domain * * See equi.md file for the specification and manual * * @license Unlicense * @author Luxferre */ /* Standard includes with size optimizations for TCC */ #ifdef __TINYC__ #include #else #include #include #endif /* * Non-standard includes * To save space, we emulate necessary conio functions on non-6502 systems, not vice versa */ #ifdef __CC65__ #include #else #define cgetc() (fgetc(stdin)) #define cputc(c) (fputc(c, stdout)) #endif /* Definitions section */ #define EQUI_VER "0.0.1" #define ushort unsigned short /* basic 16-bit integer */ #define uchar unsigned char /* basic 8-bit integer */ #define WS sizeof(ushort) /* Equi word size in bytes */ #define CLT_ENTRY_LEN 6u /* Amount of significant compiled word characters */ #define CLT_ENTRY_SIZE (CLT_ENTRY_LEN + WS) /* Full size in bytes taken by one CLT entry */ #define BS 8u /* Backspace character code */ /* Configuration section (constants overridable at compile-time) */ /* Main and return stack size in bytes */ #ifndef STACK_SIZE #define STACK_SIZE 256u #endif /* Literal stack size in bytes */ #ifndef LIT_STACK_SIZE #define LIT_STACK_SIZE 32u #endif /* Command buffer size in bytes */ #ifndef GPD_AREA_SIZE #define GPD_AREA_SIZE 6400u #endif /* Command buffer size in bytes */ #ifndef CMD_BUF_SIZE #define CMD_BUF_SIZE 15600u #endif /* Maximum amount of CLT entries */ #ifndef CLT_ENTRIES_MAX #define CLT_ENTRIES_MAX 512u #endif /* Some necessary constants and offsets derived from the above values */ #define STACK_SIZE_WORDS (STACK_SIZE / WS) /* Main and return stack size in words */ /* * Structures that describe Equi machine RAM using the above configuration */ struct CLTEntry { uchar name[CLT_ENTRY_LEN]; /* compiled word name */ ushort loc; /* compiled word location */ }; struct EquiRAM { ushort main_stack[STACK_SIZE_WORDS]; ushort return_stack[STACK_SIZE_WORDS]; uchar literal_stack[LIT_STACK_SIZE]; ushort pc; /* program counter */ ushort msp; /* main stack pointer */ ushort rsp; /* return stack pointer */ uchar lsp; /* literal stack pointer */ ushort cbp; /* compilation buffer pointer */ ushort cltp; /* compilation lookup table pointer */ unsigned int II:1; /* instruction ignore mode */ unsigned int CM:1; /* compilation mode */ unsigned int IM:1; /* interpretation mode */ ushort gpd_start; ushort cmd_start; ushort cmd_size; ushort ibp; /* input buffer pointer */ struct CLTEntry clt[CLT_ENTRIES_MAX]; /* compilation lookup table */ uchar gpd[GPD_AREA_SIZE]; uchar cmdbuf[CMD_BUF_SIZE]; }; /* Before running the main code, instantiate the machine RAM */ static struct EquiRAM ram; /* Also create an alternative view of the same RAM area for direct offset-based access */ static uchar* flatram = (uchar *)&ram; int main(int argc, char* argv[]) { /* initialize the RAM in the most standard way */ ram.gpd_start = (uchar *)&ram.gpd - (uchar *)&ram.main_stack; ram.cmd_start = (uchar *)&ram.cmdbuf - (uchar *)&ram.main_stack; ram.cmd_size = CMD_BUF_SIZE; ram.pc = ram.cmd_start; /* Start execution from the start of command buffer */ ram.ibp = ram.cmd_start; /* Start input buffering from the start of command buffer */ printf("Welcome to Equi v" EQUI_VER " by Luxferre, 2022\n\nCLT: 0x%X (%d bytes)\nGPD: 0x%X (%d bytes)\nCommand buffer: 0x%X (%d bytes)\nEqui ready\n\n", (uchar *)&ram.clt - (uchar *)&ram.main_stack, (uchar *)&ram.gpd - (uchar *)&ram.clt, ram.gpd_start, ram.cmd_start - ram.gpd_start, ram.cmd_start, ram.cmd_size); cputc('>'); cgetc(); return 0; }