ref: 9fb9e63554aa536c3028f59e349f9663e6c22c15
parent: 9ce8a9f5f09d126a7885c500df108cf98b157e57
author: ISSOtm <eldredhabert0@gmail.com>
date: Mon Jan 20 10:26:52 EST 2020
Reserve space for RPN expressions in a single call This should mean less overhead with some commands
--- a/src/asm/rpn.c
+++ b/src/asm/rpn.c
@@ -11,6 +11,7 @@
*/
#include <assert.h>
+#include <errno.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
@@ -22,16 +23,20 @@
#include "asm/output.h"
#include "asm/warning.h"
-/*
- * Add a byte to the RPN expression
- */
-static void pushbyte(struct Expression *expr, uint8_t b)
+static uint8_t *reserveSpace(struct Expression *expr, uint32_t size)
{
- if (expr->nRPNLength == expr->nRPNCapacity) {
- if (expr->nRPNCapacity == 0)
- expr->nRPNCapacity = 256;
- else if (expr->nRPNCapacity == MAXRPNLEN)
- fatalerror("RPN expression is too large");
+ /* This assumes the RPN length is always less than the capacity */
+ if (expr->nRPNCapacity - expr->nRPNLength < size) {
+ /* If there isn't enough room to reserve the space, realloc */
+ if (!expr->tRPN)
+ 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)
expr->nRPNCapacity = MAXRPNLEN;
else
@@ -38,11 +43,15 @@
expr->nRPNCapacity *= 2;
expr->tRPN = realloc(expr->tRPN, expr->nRPNCapacity);
- if (expr->tRPN == NULL)
- fatalerror("No memory for RPN expression");
+ if (!expr->tRPN)
+ 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 @@
*/
void rpn_Number(struct Expression *expr, uint32_t i)
{
+ uint8_t bytes[] = {RPN_CONST, i, i >> 8, i >> 16, i >> 24};
+
rpn_Init(expr);
- pushbyte(expr, RPN_CONST);
- pushbyte(expr, i);
- pushbyte(expr, i >> 8);
- pushbyte(expr, i >> 16);
- pushbyte(expr, i >> 24);
+ expr->nRPNPatchSize += sizeof(bytes);
+ memcpy(reserveSpace(expr, sizeof(bytes)), bytes, sizeof(bytes));
expr->nVal = i;
- expr->nRPNPatchSize += 5;
}
void rpn_Symbol(struct Expression *expr, char *tzSym)
@@ -109,12 +116,13 @@
rpn_Init(expr);
sym_Ref(tzSym);
expr->isKnown = false;
- pushbyte(expr, RPN_SYM);
- while (*tzSym)
- pushbyte(expr, *tzSym++);
- pushbyte(expr, 0);
- expr->nRPNPatchSize += 5;
+ expr->nRPNPatchSize += 5; /* 1-byte opcode + 4-byte symbol ID */
+ size_t nameLen = strlen(tzSym) + 1; /* Don't forget NUL! */
+ uint8_t *ptr = reserveSpace(expr, nameLen + 1);
+ *ptr++ = RPN_SYM;
+ memcpy(ptr, tzSym, nameLen);
+
/* RGBLINK assumes PC is at the byte being computed... */
if (sym == pPCSymbol && nPCOffset) {
struct Expression pc = *expr, offset;
@@ -136,7 +144,7 @@
else
expr->nVal = pCurrentSection->nBank;
- pushbyte(expr, RPN_BANK_SELF);
+ *reserveSpace(expr, 1) = RPN_BANK_SELF;
expr->nRPNPatchSize++;
}
@@ -155,17 +163,18 @@
yyerror("BANK argument must be a relocatable identifier");
} else {
sym_Ref(tzSym);
- pushbyte(expr, RPN_BANK_SYM);
- for (unsigned int i = 0; tzSym[i]; i++)
- pushbyte(expr, tzSym[i]);
- pushbyte(expr, 0);
- expr->nRPNPatchSize += 5;
+ expr->nRPNPatchSize += 5; /* 1-byte opcode + 4-byte sect ID */
+ size_t nameLen = strlen(tzSym) + 1; /* Don't forget NUL! */
+ uint8_t *ptr = reserveSpace(expr, nameLen + 1);
+ *ptr++ = RPN_BANK_SYM;
+ memcpy(ptr, tzSym, nameLen);
+
/* If the symbol didn't exist, `sym_Ref` created it */
struct sSymbol *pSymbol = sym_FindSymbol(tzSym);
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;
else
expr->isKnown = false;
@@ -183,29 +192,25 @@
else
expr->isKnown = false;
- pushbyte(expr, RPN_BANK_SECT);
- expr->nRPNPatchSize++;
+ size_t nameLen = strlen(tzSectionName) + 1; /* Don't forget NUL! */
+ uint8_t *ptr = reserveSpace(expr, nameLen + 1);
- while (*tzSectionName) {
- pushbyte(expr, *tzSectionName++);
- expr->nRPNPatchSize++;
- }
-
- pushbyte(expr, 0);
- expr->nRPNPatchSize++;
+ expr->nRPNPatchSize += nameLen + 1;
+ *ptr++ = RPN_BANK_SECT;
+ memcpy(ptr, tzSectionName, nameLen);
}
void rpn_CheckHRAM(struct Expression *expr, const struct Expression *src)
{
*expr = *src;
- pushbyte(expr, RPN_HRAM);
expr->nRPNPatchSize++;
+ *reserveSpace(expr, 1) = RPN_HRAM;
}
void rpn_CheckRST(struct Expression *expr, const struct Expression *src)
{
*expr = *src;
- pushbyte(expr, RPN_RST);
+ *reserveSpace(expr, 1) = RPN_RST;
expr->nRPNPatchSize++;
}
@@ -213,8 +218,8 @@
{
*expr = *src;
expr->nVal = !expr->nVal;
- pushbyte(expr, RPN_LOGUNNOT);
expr->nRPNPatchSize++;
+ *reserveSpace(expr, 1) = RPN_LOGUNNOT;
}
static int32_t shift(int32_t shiftee, int32_t amount)
@@ -291,10 +296,11 @@
memcpy(expr->tRPN + src1->nRPNLength, src2->tRPN, src2->nRPNLength);
free(src2->tRPN);
- expr->nRPNLength = len;
- expr->nRPNPatchSize = src1->nRPNPatchSize + src2->nRPNPatchSize;
- expr->nRPNOut = 0;
+ expr->nRPNOut = 0; // FIXME: is this necessary?
expr->isKnown = src1->isKnown && src2->isKnown;
+ expr->nRPNLength = len;
+ expr->nRPNPatchSize = src1->nRPNPatchSize + src2->nRPNPatchSize + 1;
+ *reserveSpace(expr, 1) = op;
switch (op) {
case RPN_LOGOR:
@@ -325,6 +331,7 @@
expr->nVal = (uint32_t)src1->nVal + (uint32_t)src2->nVal;
break;
case RPN_SUB:
+ // FIXME: under certain conditions, this might be actually known
expr->nVal = (uint32_t)src1->nVal - (uint32_t)src2->nVal;
break;
case RPN_XOR:
@@ -394,9 +401,6 @@
case RPN_SYM:
fatalerror("%d is no binary operator", op);
}
-
- pushbyte(expr, op);
- expr->nRPNPatchSize++;
}
void rpn_HIGH(struct Expression *expr, const struct Expression *src)
@@ -405,23 +409,11 @@
expr->nVal = (expr->nVal >> 8) & 0xFF;
- pushbyte(expr, RPN_CONST);
- pushbyte(expr, 8);
- pushbyte(expr, 0);
- pushbyte(expr, 0);
- pushbyte(expr, 0);
+ uint8_t bytes[] = {RPN_CONST, 8, 0, 0, 0, RPN_SHR,
+ RPN_CONST, 0xFF, 0, 0, 0, RPN_AND};
+ expr->nRPNPatchSize += sizeof(bytes);
- pushbyte(expr, RPN_SHR);
-
- pushbyte(expr, RPN_CONST);
- pushbyte(expr, 0xFF);
- pushbyte(expr, 0);
- pushbyte(expr, 0);
- pushbyte(expr, 0);
-
- pushbyte(expr, RPN_AND);
-
- expr->nRPNPatchSize += 12;
+ memcpy(reserveSpace(expr, sizeof(bytes)), bytes, sizeof(bytes));
}
void rpn_LOW(struct Expression *expr, const struct Expression *src)
@@ -430,15 +422,10 @@
expr->nVal = expr->nVal & 0xFF;
- pushbyte(expr, RPN_CONST);
- pushbyte(expr, 0xFF);
- pushbyte(expr, 0);
- pushbyte(expr, 0);
- pushbyte(expr, 0);
+ uint8_t bytes[] = {RPN_CONST, 0xFF, 0, 0, 0, RPN_AND};
- pushbyte(expr, RPN_AND);
-
- expr->nRPNPatchSize += 6;
+ expr->nRPNPatchSize += sizeof(bytes);
+ memcpy(reserveSpace(expr, sizeof(bytes)), bytes, sizeof(bytes));
}
void rpn_UNNEG(struct Expression *expr, const struct Expression *src)
@@ -445,8 +432,8 @@
{
*expr = *src;
expr->nVal = -(uint32_t)expr->nVal;
- pushbyte(expr, RPN_UNSUB);
expr->nRPNPatchSize++;
+ *reserveSpace(expr, 1) = RPN_UNSUB;
}
void rpn_UNNOT(struct Expression *expr, const struct Expression *src)
@@ -453,6 +440,6 @@
{
*expr = *src;
expr->nVal = ~expr->nVal;
- pushbyte(expr, RPN_UNNOT);
expr->nRPNPatchSize++;
+ *reserveSpace(expr, 1) = RPN_UNNOT;
}