From 84e3acae643a6b96798a73d3b7ce0067db8fc61d Mon Sep 17 00:00:00 2001 From: ketmar Date: Tue, 27 Mar 2012 21:31:56 +0300 Subject: [PATCH] BSR and RST now takes infinite number of arguments and pushes 'em in pascal style --- src/awasm.c | 111 ++++++++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 79 insertions(+), 32 deletions(-) diff --git a/src/awasm.c b/src/awasm.c index 5fca247..2f7be24 100644 --- a/src/awasm.c +++ b/src/awasm.c @@ -56,7 +56,8 @@ enum { VMX_DRP = 600, VMX_DUP, VMX_RTN, - VMX_RETURN + VMX_RETURN, + VMX_SAJ }; @@ -502,6 +503,7 @@ static int nextToken (void) { if (strcmp(tstr, "drp") == 0) token = VMX_DRP; else if (strcmp(tstr, "dup") == 0) token = VMX_DUP; else if (strcmp(tstr, "rtn") == 0) token = VMX_RTN; + else if (strcmp(tstr, "saj") == 0) token = VMX_SAJ; } } else if (strcmp(tstr, "return") == 0) { token = VMX_RETURN; @@ -572,7 +574,6 @@ typedef struct VarFixup { static VarFixup *gvfixes = NULL; static VarFixup *tvfixes = NULL; - static VarFixup *addVarFixup (VarFixup *list, int pc) { VarFixup *res = calloc(1, sizeof(VarFixup)); // @@ -807,14 +808,18 @@ static void newTempLabel (void) { //////////////////////////////////////////////////////////////////////////////// -typedef struct { +typedef struct OperandInfo { LabelInfo *l; // !=NULL: label int var; // [...] int value; // if l==NULL int vartype; // 0: global; 1: tlocal; 2: stack + struct OperandInfo *next; } OperandInfo; +static int stackAdj = 0; + + static void setIntOperand (OperandInfo *op, int value) { op->l = NULL; op->var = 0; @@ -944,8 +949,13 @@ static void emitOperand (OperandInfo *op) { break; case LB_SVAR: emitByte(127); // special - emitByte(op->l->value&0xff); - emitByte((op->l->value>>8)&0xff); + if (op->l->value < 0) { + emitByte((op->l->value-stackAdj)&0xff); + emitByte(((op->l->value-stackAdj)>>8)&0xff); + } else { + emitByte(op->l->value&0xff); + emitByte((op->l->value>>8)&0xff); + } addLabelRef(op->l, pc-2); break; default: fatal("internal error"); @@ -957,15 +967,20 @@ static void emitOperand (OperandInfo *op) { case 1: emitByte(op->value); break; // tlocal case 2: // stack emitByte(127); // special - emitByte(op->value&0xff); - emitByte((op->value>>8)&0xff); + if (op->value < 0) { + emitByte((op->value-stackAdj)&0xff); + emitByte(((op->value-stackAdj)>>8)&0xff); + } else { + emitByte(op->value&0xff); + emitByte((op->value>>8)&0xff); + } break; default: fatal("internal error"); } } return; } - // + // code label if (op->var == 0) { // immediate emitByte(255); // special @@ -1057,21 +1072,57 @@ static void doBranch (int opcode) { static void doBSR (int opcode) { - OperandInfo op0, op1, op2; + OperandInfo op0, *op1 = NULL, *op2 = NULL, *olist = NULL, *c = NULL; + int osadj = stackAdj, ocnt = 0;; // - op0.var = op1.var = op2.var = -1; + op0.var = -1; if (hasOperand()) { - getOperand(&op0, 1); - if (token == ',') { + getOperand(&op0, (opcode == VM_BSR) ? 1 : 0); + // collect other operands + while (token == ',') { + OperandInfo *o = calloc(sizeof(OperandInfo), 1); + // + if (o == NULL) fatal("out of memory"); nextToken(); - getOperand(&op1, 0); - if (token == ',') { - nextToken(); - getOperand(&op2, 0); + getOperand(o, 0); + if (olist != NULL) c->next = o; else olist = o; + c = o; + o->next = NULL; + ++ocnt; + } + // + switch (ocnt) { + case 1: + op1 = olist; + olist = NULL; + break; + case 2: + op1 = olist; + op2 = olist->next; + olist = NULL; + break; + } + // generate pushes + while (olist != NULL) { + OperandInfo *o = olist; + // + if (o->next->next == NULL) { + // last 2 operands + op1 = olist; + op2 = olist->next; + olist = NULL; + break; } + olist = o->next; + emitInstruction(VM_PSH, o, NULL, NULL); + ++stackAdj; + free(o); } } - emitInstruction(opcode, &op0, &op1, &op2); + emitInstruction(opcode, &op0, op1, op2); + if (op2 != NULL) free(op2); + if (op1 != NULL) free(op1); + stackAdj = osadj; } @@ -1095,21 +1146,7 @@ static void doMap (int opcode, int lastMBV) { static void doRST (int opcode) { - OperandInfo op0, op1, op2; - // - op0.var = op1.var = op2.var = -1; - if (hasOperand()) { - getOperand(&op0, 0); - if (token == ',') { - nextToken(); - getOperand(&op1, 0); - if (token == ',') { - nextToken(); - getOperand(&op2, 0); - } - } - } - emitInstruction(opcode, &op0, &op1, &op2); + doBSR(opcode); } @@ -1333,6 +1370,13 @@ static void doRet (int opcode) { } +static void doSAj (int opcode) { + if (token != TK_NUM) fatal("number expected"); + stackAdj += tint; + nextToken(); +} + + //////////////////////////////////////////////////////////////////////////////// static void parseInlcude (void) { static char fname[8192], *t; @@ -2273,6 +2317,9 @@ static void process (void) { case VMX_RETURN: doReturn(); break; + case VMX_SAJ: + doSAj(opc); + break; default: fatal("not yet"); } -- 2.11.4.GIT