Reserve space for RPN expressions in a single call

This should mean less overhead with some commands
This commit is contained in:
ISSOtm
2020-01-20 15:26:52 +01:00
parent 9ce8a9f5f0
commit 9fb9e63554

View File

@@ -11,6 +11,7 @@
*/ */
#include <assert.h> #include <assert.h>
#include <errno.h>
#include <stdint.h> #include <stdint.h>
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
@@ -22,27 +23,35 @@
#include "asm/output.h" #include "asm/output.h"
#include "asm/warning.h" #include "asm/warning.h"
/* static uint8_t *reserveSpace(struct Expression *expr, uint32_t size)
* Add a byte to the RPN expression
*/
static void pushbyte(struct Expression *expr, uint8_t b)
{ {
if (expr->nRPNLength == expr->nRPNCapacity) { /* This assumes the RPN length is always less than the capacity */
if (expr->nRPNCapacity == 0) if (expr->nRPNCapacity - expr->nRPNLength < size) {
expr->nRPNCapacity = 256; /* If there isn't enough room to reserve the space, realloc */
else if (expr->nRPNCapacity == MAXRPNLEN) if (!expr->tRPN)
fatalerror("RPN expression is too large"); expr->nRPNCapacity = 256; /* Initial size */
else if (expr->nRPNCapacity >= MAXRPNLEN)
/*
* To avoid generating humongous object files, cap the
* size of RPN expressions
*/
fatalerror("RPN expression cannot grow larger than %d bytes",
MAXRPNLEN);
else if (expr->nRPNCapacity > MAXRPNLEN / 2) else if (expr->nRPNCapacity > MAXRPNLEN / 2)
expr->nRPNCapacity = MAXRPNLEN; expr->nRPNCapacity = MAXRPNLEN;
else else
expr->nRPNCapacity *= 2; expr->nRPNCapacity *= 2;
expr->tRPN = realloc(expr->tRPN, expr->nRPNCapacity); expr->tRPN = realloc(expr->tRPN, expr->nRPNCapacity);
if (expr->tRPN == NULL) if (!expr->tRPN)
fatalerror("No memory for RPN expression"); fatalerror("Failed to grow RPN expression: %s",
strerror(errno));
} }
expr->tRPN[expr->nRPNLength++] = b; uint8_t *ptr = expr->tRPN + expr->nRPNLength;
expr->nRPNLength += size;
return ptr;
} }
/* /*
@@ -91,14 +100,12 @@ bool rpn_isKnown(const struct Expression *expr)
*/ */
void rpn_Number(struct Expression *expr, uint32_t i) void rpn_Number(struct Expression *expr, uint32_t i)
{ {
uint8_t bytes[] = {RPN_CONST, i, i >> 8, i >> 16, i >> 24};
rpn_Init(expr); rpn_Init(expr);
pushbyte(expr, RPN_CONST); expr->nRPNPatchSize += sizeof(bytes);
pushbyte(expr, i); memcpy(reserveSpace(expr, sizeof(bytes)), bytes, sizeof(bytes));
pushbyte(expr, i >> 8);
pushbyte(expr, i >> 16);
pushbyte(expr, i >> 24);
expr->nVal = i; expr->nVal = i;
expr->nRPNPatchSize += 5;
} }
void rpn_Symbol(struct Expression *expr, char *tzSym) void rpn_Symbol(struct Expression *expr, char *tzSym)
@@ -109,11 +116,12 @@ void rpn_Symbol(struct Expression *expr, char *tzSym)
rpn_Init(expr); rpn_Init(expr);
sym_Ref(tzSym); sym_Ref(tzSym);
expr->isKnown = false; expr->isKnown = false;
pushbyte(expr, RPN_SYM); expr->nRPNPatchSize += 5; /* 1-byte opcode + 4-byte symbol ID */
while (*tzSym)
pushbyte(expr, *tzSym++); size_t nameLen = strlen(tzSym) + 1; /* Don't forget NUL! */
pushbyte(expr, 0); uint8_t *ptr = reserveSpace(expr, nameLen + 1);
expr->nRPNPatchSize += 5; *ptr++ = RPN_SYM;
memcpy(ptr, tzSym, nameLen);
/* RGBLINK assumes PC is at the byte being computed... */ /* RGBLINK assumes PC is at the byte being computed... */
if (sym == pPCSymbol && nPCOffset) { if (sym == pPCSymbol && nPCOffset) {
@@ -136,7 +144,7 @@ void rpn_BankSelf(struct Expression *expr)
else else
expr->nVal = pCurrentSection->nBank; expr->nVal = pCurrentSection->nBank;
pushbyte(expr, RPN_BANK_SELF); *reserveSpace(expr, 1) = RPN_BANK_SELF;
expr->nRPNPatchSize++; expr->nRPNPatchSize++;
} }
@@ -155,17 +163,18 @@ void rpn_BankSymbol(struct Expression *expr, char *tzSym)
yyerror("BANK argument must be a relocatable identifier"); yyerror("BANK argument must be a relocatable identifier");
} else { } else {
sym_Ref(tzSym); sym_Ref(tzSym);
pushbyte(expr, RPN_BANK_SYM); expr->nRPNPatchSize += 5; /* 1-byte opcode + 4-byte sect ID */
for (unsigned int i = 0; tzSym[i]; i++)
pushbyte(expr, tzSym[i]); size_t nameLen = strlen(tzSym) + 1; /* Don't forget NUL! */
pushbyte(expr, 0); uint8_t *ptr = reserveSpace(expr, nameLen + 1);
expr->nRPNPatchSize += 5; *ptr++ = RPN_BANK_SYM;
memcpy(ptr, tzSym, nameLen);
/* If the symbol didn't exist, `sym_Ref` created it */ /* If the symbol didn't exist, `sym_Ref` created it */
struct sSymbol *pSymbol = sym_FindSymbol(tzSym); struct sSymbol *pSymbol = sym_FindSymbol(tzSym);
if (pSymbol->pSection && pSymbol->pSection->nBank != -1) if (pSymbol->pSection && pSymbol->pSection->nBank != -1)
/* Symbol's section is known and bank's fixed */ /* Symbol's section is known and bank is fixed */
expr->nVal = pSymbol->pSection->nBank; expr->nVal = pSymbol->pSection->nBank;
else else
expr->isKnown = false; expr->isKnown = false;
@@ -183,29 +192,25 @@ void rpn_BankSection(struct Expression *expr, char *tzSectionName)
else else
expr->isKnown = false; expr->isKnown = false;
pushbyte(expr, RPN_BANK_SECT); size_t nameLen = strlen(tzSectionName) + 1; /* Don't forget NUL! */
expr->nRPNPatchSize++; uint8_t *ptr = reserveSpace(expr, nameLen + 1);
while (*tzSectionName) { expr->nRPNPatchSize += nameLen + 1;
pushbyte(expr, *tzSectionName++); *ptr++ = RPN_BANK_SECT;
expr->nRPNPatchSize++; memcpy(ptr, tzSectionName, nameLen);
}
pushbyte(expr, 0);
expr->nRPNPatchSize++;
} }
void rpn_CheckHRAM(struct Expression *expr, const struct Expression *src) void rpn_CheckHRAM(struct Expression *expr, const struct Expression *src)
{ {
*expr = *src; *expr = *src;
pushbyte(expr, RPN_HRAM);
expr->nRPNPatchSize++; expr->nRPNPatchSize++;
*reserveSpace(expr, 1) = RPN_HRAM;
} }
void rpn_CheckRST(struct Expression *expr, const struct Expression *src) void rpn_CheckRST(struct Expression *expr, const struct Expression *src)
{ {
*expr = *src; *expr = *src;
pushbyte(expr, RPN_RST); *reserveSpace(expr, 1) = RPN_RST;
expr->nRPNPatchSize++; expr->nRPNPatchSize++;
} }
@@ -213,8 +218,8 @@ void rpn_LOGNOT(struct Expression *expr, const struct Expression *src)
{ {
*expr = *src; *expr = *src;
expr->nVal = !expr->nVal; expr->nVal = !expr->nVal;
pushbyte(expr, RPN_LOGUNNOT);
expr->nRPNPatchSize++; expr->nRPNPatchSize++;
*reserveSpace(expr, 1) = RPN_LOGUNNOT;
} }
static int32_t shift(int32_t shiftee, int32_t amount) static int32_t shift(int32_t shiftee, int32_t amount)
@@ -291,10 +296,11 @@ void rpn_BinaryOp(enum RPNCommand op, struct Expression *expr,
memcpy(expr->tRPN + src1->nRPNLength, src2->tRPN, src2->nRPNLength); memcpy(expr->tRPN + src1->nRPNLength, src2->tRPN, src2->nRPNLength);
free(src2->tRPN); free(src2->tRPN);
expr->nRPNLength = len; expr->nRPNOut = 0; // FIXME: is this necessary?
expr->nRPNPatchSize = src1->nRPNPatchSize + src2->nRPNPatchSize;
expr->nRPNOut = 0;
expr->isKnown = src1->isKnown && src2->isKnown; expr->isKnown = src1->isKnown && src2->isKnown;
expr->nRPNLength = len;
expr->nRPNPatchSize = src1->nRPNPatchSize + src2->nRPNPatchSize + 1;
*reserveSpace(expr, 1) = op;
switch (op) { switch (op) {
case RPN_LOGOR: case RPN_LOGOR:
@@ -325,6 +331,7 @@ void rpn_BinaryOp(enum RPNCommand op, struct Expression *expr,
expr->nVal = (uint32_t)src1->nVal + (uint32_t)src2->nVal; expr->nVal = (uint32_t)src1->nVal + (uint32_t)src2->nVal;
break; break;
case RPN_SUB: case RPN_SUB:
// FIXME: under certain conditions, this might be actually known
expr->nVal = (uint32_t)src1->nVal - (uint32_t)src2->nVal; expr->nVal = (uint32_t)src1->nVal - (uint32_t)src2->nVal;
break; break;
case RPN_XOR: case RPN_XOR:
@@ -394,9 +401,6 @@ void rpn_BinaryOp(enum RPNCommand op, struct Expression *expr,
case RPN_SYM: case RPN_SYM:
fatalerror("%d is no binary operator", op); fatalerror("%d is no binary operator", op);
} }
pushbyte(expr, op);
expr->nRPNPatchSize++;
} }
void rpn_HIGH(struct Expression *expr, const struct Expression *src) void rpn_HIGH(struct Expression *expr, const struct Expression *src)
@@ -405,23 +409,11 @@ void rpn_HIGH(struct Expression *expr, const struct Expression *src)
expr->nVal = (expr->nVal >> 8) & 0xFF; expr->nVal = (expr->nVal >> 8) & 0xFF;
pushbyte(expr, RPN_CONST); uint8_t bytes[] = {RPN_CONST, 8, 0, 0, 0, RPN_SHR,
pushbyte(expr, 8); RPN_CONST, 0xFF, 0, 0, 0, RPN_AND};
pushbyte(expr, 0); expr->nRPNPatchSize += sizeof(bytes);
pushbyte(expr, 0);
pushbyte(expr, 0);
pushbyte(expr, RPN_SHR); memcpy(reserveSpace(expr, sizeof(bytes)), bytes, sizeof(bytes));
pushbyte(expr, RPN_CONST);
pushbyte(expr, 0xFF);
pushbyte(expr, 0);
pushbyte(expr, 0);
pushbyte(expr, 0);
pushbyte(expr, RPN_AND);
expr->nRPNPatchSize += 12;
} }
void rpn_LOW(struct Expression *expr, const struct Expression *src) void rpn_LOW(struct Expression *expr, const struct Expression *src)
@@ -430,29 +422,24 @@ void rpn_LOW(struct Expression *expr, const struct Expression *src)
expr->nVal = expr->nVal & 0xFF; expr->nVal = expr->nVal & 0xFF;
pushbyte(expr, RPN_CONST); uint8_t bytes[] = {RPN_CONST, 0xFF, 0, 0, 0, RPN_AND};
pushbyte(expr, 0xFF);
pushbyte(expr, 0);
pushbyte(expr, 0);
pushbyte(expr, 0);
pushbyte(expr, RPN_AND); expr->nRPNPatchSize += sizeof(bytes);
memcpy(reserveSpace(expr, sizeof(bytes)), bytes, sizeof(bytes));
expr->nRPNPatchSize += 6;
} }
void rpn_UNNEG(struct Expression *expr, const struct Expression *src) void rpn_UNNEG(struct Expression *expr, const struct Expression *src)
{ {
*expr = *src; *expr = *src;
expr->nVal = -(uint32_t)expr->nVal; expr->nVal = -(uint32_t)expr->nVal;
pushbyte(expr, RPN_UNSUB);
expr->nRPNPatchSize++; expr->nRPNPatchSize++;
*reserveSpace(expr, 1) = RPN_UNSUB;
} }
void rpn_UNNOT(struct Expression *expr, const struct Expression *src) void rpn_UNNOT(struct Expression *expr, const struct Expression *src)
{ {
*expr = *src; *expr = *src;
expr->nVal = ~expr->nVal; expr->nVal = ~expr->nVal;
pushbyte(expr, RPN_UNNOT);
expr->nRPNPatchSize++; expr->nRPNPatchSize++;
*reserveSpace(expr, 1) = RPN_UNNOT;
} }