equi

A self-descriptive stack-based PC platform
git clone git://git.luxferre.top/equi.git
Log | Files | Refs | README | LICENSE

commit 898f1f22d340085c7f1b42398c3a7f581ae858ad
parent d2f4b058d26f1c624d7108a2a712f468ac6ae49c
Author: Luxferre <lux@ferre>
Date:   Mon,  8 Aug 2022 11:07:24 +0300

some instruction progress

Diffstat:
Mequi.c | 137++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------
1 file changed, 122 insertions(+), 15 deletions(-)

diff --git a/equi.c b/equi.c @@ -245,35 +245,61 @@ uchar popLit() { return ram.literal_stack[--ram.lsp]; } -/* check literal stack and push 4 top values as hex short literal if not empty and discard the rest of the stack */ -void attemptPushNumericLiteral() { +/* clear the literal stack */ +void clearLit() { + ram.lsp = 0; /* clear the literal stack */ +} +/* shape 2-byte vlaue on the main stack from the 4 values of the literal stack */ +void pushLitVal(strict) { + uchar p1, p2, p3, p4; + if(ram.lsp < 4) { /* if we don't strictly expect 4 bytes, do nothing */ + if(strict) trapout(STACK_UNDERFLOW); + else { + ram.lsp = 0; /* clear the literal stack */ + return; + } + } + else { + p4 = popLit(); + p3 = popLit(); + p2 = popLit(); + p1 = popLit(); + pushMain((p1<<12) | (p2<<8) | (p3<<4) | p4); + ram.lsp = 0; /* clear the literal stack */ + } } /* Main interpreter loop */ void equi_main_loop() { - uchar instr; + uchar instr, i; + /* reset all stacks before running and reinit CLT */ + ram.msp = ram.rsp = ram.lsp = ram.cltp = 0; + /* reset pc */ + ram.pc = 65535; while(1) { /* iterate over the instructions in the command buffer */ instr = ram.cmdbuf[++ram.pc]; /* first, check for II mode */ if(ram.II) { - if(instr == ')') + if(instr == INS_IIEND) ram.II = 0; /* unset instruction ignore mode flag */ continue; } /* then, check for compilation mode */ if(ram.CM) { - if(instr == ';') { /* trigger word compilation logic as per the spec */ - ram.cmdbuf[ram.pc] = 'R'; /* in-place patch this instruction to R */ - + if(instr == INS_CMEND) { /* trigger word compilation logic as per the spec */ + ram.cmdbuf[ram.pc] = INS_RET; /* in-place patch this instruction to R */ + /* compiled words are saved vice versa to save code size */ + for(i=0;i<CLT_ENTRY_LEN;++i) + ram.clt[ram.cltp].name[i] = popLit(); + ram.lsp = 0; /* clear the literal stack */ ram.clt[ram.cltp].loc = ram.cbp; /* stored the compiled code location from the most recent CBP value */ ++ram.cltp; /* increase the word */ if(ram.cltp == CLT_ENTRIES_MAX) { trapout(CLT_OVERFLOW); break; } - ram.CM = 0; /* unset compilation mode flag */ } continue; @@ -285,11 +311,92 @@ void equi_main_loop() { continue; } /* then trigger literal auto-push if applicable */ - if(instr != '"' && instr != '\'' && instr != '#' && instr != ':') - attemptPushNumericLiteral(); - switch(instr) { - - default: + if(ram.lsp > 0 && instr != INS_LITSTR && instr != INS_LITCALL && instr != INS_LITINT && instr != INS_CMSTART) + pushLitVal(0); + switch(instr) { /* then perform all main interpretation logic */ + case INS_IISTART: /* instruction ignore start */ + ram.II = 1; /* raise II flag */ + break; + case INS_CMSTART: /* compilation start */ + ram.cbp = ram.pc + 1; /* save CBP */ + ram.CM = 1; /* raise CM flag */ + break; + case INS_QUIT: /* gracefully quit the interpretation mode */ + goto brx; + case INS_LITINT: /* literal stack -> main stack as short */ + pushLitVal(1); + break; + case INS_LITSTR: + break; + case INS_LITCALL: + break; + case INS_RET: + ram.pc = popRet(); + break; + case INS_M2R: + break; + case INS_R2M: + break; + case INS_LOAD: + break; + case INS_STORE: + break; + case INS_STOREBYTE: + break; + case INS_DROP: + break; + case INS_DUP: + break; + case INS_SWAP: + break; + case INS_ROT: + break; + case INS_OVER: + break; + case INS_JUMP: + break; + case INS_IF: + break; + case INS_EXPOINT: /* Locate execution point */ + pushMain(ram.pc + 1); + break; + case INS_GT: + break; + case INS_LT: + break; + case INS_EQ: + break; + case INS_ADD: + break; + case INS_SUB: + break; + case INS_MUL: + break; + case INS_DIV: + break; + case INS_NEG: + break; + case INS_NOT: + break; + case INS_AND: + break; + case INS_OR: + break; + case INS_XOR: + break; + case INS_COUT: + break; + case INS_NBKIN: + case INS_BKIN: + break; + case INS_PORTIO: + break; + case INS_PERSIST_READ: + break; + case INS_PERSIST_WRITE: + break; + default: /* all characters not processed before are invalid instructions */ + trapout(INVALID_INSTRUCTION); goto brx; } continue; @@ -333,12 +440,12 @@ int main(int argc, char* argv[]) { cputc(instr); /* echo it */ #endif --ram.ibp; - } else if(instr == '(') { /* process II just to avoid quitting in command mode */ + } else if(instr == INS_IISTART) { /* process II just to avoid quitting in command mode */ #ifdef __CC65__ cputc(instr); /* echo it */ #endif ram.II = 1; - } else if(instr == ')') { /* process II just to avoid quitting in command mode */ + } else if(instr == INS_IIEND) { /* process II just to avoid quitting in command mode */ #ifdef __CC65__ cputc(instr); /* echo it */ #endif