mirror of
https://github.com/gbdev/rgbds.git
synced 2025-11-20 18:22:07 +00:00
Dynamically allocate RPN expression buffer
This commit is contained in:
@@ -13,7 +13,8 @@
|
||||
|
||||
struct Expression {
|
||||
int32_t nVal;
|
||||
uint8_t tRPN[256];
|
||||
uint8_t *tRPN;
|
||||
uint32_t nRPNCapacity;
|
||||
uint32_t nRPNLength;
|
||||
uint32_t nRPNOut;
|
||||
uint32_t isReloc;
|
||||
@@ -69,7 +70,8 @@ uint16_t rpn_PopByte(struct Expression *expr);
|
||||
void rpn_BankSymbol(struct Expression *expr, char *tzSym);
|
||||
void rpn_BankSection(struct Expression *expr, char *tzSectionName);
|
||||
void rpn_BankSelf(struct Expression *expr);
|
||||
void rpn_Reset(struct Expression *expr);
|
||||
void rpn_Init(struct Expression *expr);
|
||||
void rpn_Free(struct Expression *expr);
|
||||
void rpn_CheckHRAM(struct Expression *expr, const struct Expression *src);
|
||||
|
||||
#endif /* RGBDS_ASM_RPN_H */
|
||||
|
||||
@@ -1772,6 +1772,7 @@ z80_ld_mem : T_Z80_LD op_mem_ind comma T_MODE_SP
|
||||
(!rpn_isReloc(&$2)) && ($2.nVal >= 0xFF00)) {
|
||||
out_AbsByte(0xE0);
|
||||
out_AbsByte($2.nVal & 0xFF);
|
||||
rpn_Free(&$2);
|
||||
} else {
|
||||
out_AbsByte(0xEA);
|
||||
out_RelWord(&$2);
|
||||
@@ -1826,12 +1827,14 @@ z80_ld_a : T_Z80_LD reg_r comma T_MODE_C_IND
|
||||
(!rpn_isReloc(&$4)) && ($4.nVal >= 0xFF00)) {
|
||||
out_AbsByte(0xF0);
|
||||
out_AbsByte($4.nVal & 0xFF);
|
||||
rpn_Free(&$4);
|
||||
} else {
|
||||
out_AbsByte(0xFA);
|
||||
out_RelWord(&$4);
|
||||
}
|
||||
} else {
|
||||
yyerror("Destination operand must be A");
|
||||
rpn_Free(&$4);
|
||||
}
|
||||
}
|
||||
;
|
||||
@@ -1964,6 +1967,7 @@ z80_rst : T_Z80_RST const_8bit
|
||||
yyerror("Invalid address $%x for RST", $2.nVal);
|
||||
else
|
||||
out_AbsByte(0xC7 | $2.nVal);
|
||||
rpn_Free(&$2);
|
||||
}
|
||||
;
|
||||
|
||||
|
||||
@@ -782,7 +782,7 @@ void out_RelByte(struct Expression *expr)
|
||||
} else {
|
||||
out_AbsByte(expr->nVal);
|
||||
}
|
||||
rpn_Reset(expr);
|
||||
rpn_Free(expr);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -825,7 +825,7 @@ void out_RelWord(struct Expression *expr)
|
||||
} else {
|
||||
out_AbsWord(expr->nVal);
|
||||
}
|
||||
rpn_Reset(expr);
|
||||
rpn_Free(expr);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -871,7 +871,7 @@ void out_RelLong(struct Expression *expr)
|
||||
} else {
|
||||
out_AbsLong(expr->nVal);
|
||||
}
|
||||
rpn_Reset(expr);
|
||||
rpn_Free(expr);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -892,7 +892,7 @@ void out_PCRelByte(struct Expression *expr)
|
||||
nPC += 1;
|
||||
pPCSymbol->nValue += 1;
|
||||
|
||||
rpn_Reset(expr);
|
||||
rpn_Free(expr);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
* Controls RPN expressions for objectfiles
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
@@ -24,12 +25,37 @@
|
||||
void mergetwoexpressions(struct Expression *expr, const struct Expression *src1,
|
||||
const struct Expression *src2)
|
||||
{
|
||||
*expr = *src1;
|
||||
memcpy(&(expr->tRPN[expr->nRPNLength]), src2->tRPN, src2->nRPNLength);
|
||||
assert(src1->tRPN != NULL && src2->tRPN != NULL);
|
||||
|
||||
expr->nRPNLength += src2->nRPNLength;
|
||||
expr->isReloc |= src2->isReloc;
|
||||
expr->isPCRel |= src2->isPCRel;
|
||||
if (src1->nRPNLength > UINT32_MAX - src2->nRPNLength)
|
||||
fatalerror("RPN expression is too large");
|
||||
|
||||
uint32_t len = src1->nRPNLength + src2->nRPNLength;
|
||||
|
||||
expr->tRPN = src1->tRPN;
|
||||
|
||||
if (src1->nRPNCapacity >= len) {
|
||||
expr->nRPNCapacity = src1->nRPNCapacity;
|
||||
} else {
|
||||
uint32_t cap1 = src1->nRPNCapacity;
|
||||
uint32_t cap2 = src2->nRPNCapacity;
|
||||
uint32_t cap = (cap1 > cap2) ? cap1 : cap2;
|
||||
|
||||
if (len > cap)
|
||||
cap = (cap <= UINT32_MAX / 2) ? cap * 2 : len;
|
||||
|
||||
expr->nRPNCapacity = cap;
|
||||
expr->tRPN = realloc(expr->tRPN, expr->nRPNCapacity);
|
||||
if (expr->tRPN == NULL)
|
||||
fatalerror("No memory for RPN expression");
|
||||
}
|
||||
|
||||
memcpy(expr->tRPN + src1->nRPNLength, src2->tRPN, src2->nRPNLength);
|
||||
free(src2->tRPN);
|
||||
|
||||
expr->nRPNLength = len;
|
||||
expr->isReloc = src1->isReloc || src2->isReloc;
|
||||
expr->isPCRel = src1->isPCRel || src2->isPCRel;
|
||||
}
|
||||
|
||||
#define joinexpr() mergetwoexpressions(expr, src1, src2)
|
||||
@@ -39,20 +65,44 @@ void mergetwoexpressions(struct Expression *expr, const struct Expression *src1,
|
||||
*/
|
||||
void pushbyte(struct Expression *expr, int b)
|
||||
{
|
||||
if (expr->nRPNLength == expr->nRPNCapacity) {
|
||||
if (expr->nRPNCapacity == 0)
|
||||
expr->nRPNCapacity = 256;
|
||||
else if (expr->nRPNCapacity > UINT32_MAX / 2)
|
||||
fatalerror("RPN expression is too large");
|
||||
else
|
||||
expr->nRPNCapacity *= 2;
|
||||
expr->tRPN = realloc(expr->tRPN, expr->nRPNCapacity);
|
||||
|
||||
if (expr->tRPN == NULL)
|
||||
fatalerror("No memory for RPN expression");
|
||||
}
|
||||
|
||||
expr->tRPN[expr->nRPNLength++] = b & 0xFF;
|
||||
}
|
||||
|
||||
/*
|
||||
* Reset the RPN module
|
||||
* Init the RPN expression
|
||||
*/
|
||||
void rpn_Reset(struct Expression *expr)
|
||||
void rpn_Init(struct Expression *expr)
|
||||
{
|
||||
expr->tRPN = NULL;
|
||||
expr->nRPNCapacity = 0;
|
||||
expr->nRPNLength = 0;
|
||||
expr->nRPNOut = 0;
|
||||
expr->isReloc = 0;
|
||||
expr->isPCRel = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Free the RPN expression
|
||||
*/
|
||||
void rpn_Free(struct Expression *expr)
|
||||
{
|
||||
free(expr->tRPN);
|
||||
rpn_Init(expr);
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the next rpn byte in expression
|
||||
*/
|
||||
@@ -85,7 +135,7 @@ uint32_t rpn_isPCRelative(const struct Expression *expr)
|
||||
*/
|
||||
void rpn_Number(struct Expression *expr, uint32_t i)
|
||||
{
|
||||
rpn_Reset(expr);
|
||||
rpn_Init(expr);
|
||||
pushbyte(expr, RPN_CONST);
|
||||
pushbyte(expr, i);
|
||||
pushbyte(expr, i >> 8);
|
||||
@@ -99,7 +149,7 @@ void rpn_Symbol(struct Expression *expr, char *tzSym)
|
||||
if (!sym_isConstant(tzSym)) {
|
||||
const struct sSymbol *psym;
|
||||
|
||||
rpn_Reset(expr);
|
||||
rpn_Init(expr);
|
||||
|
||||
psym = sym_FindSymbol(tzSym);
|
||||
|
||||
@@ -118,7 +168,7 @@ void rpn_Symbol(struct Expression *expr, char *tzSym)
|
||||
|
||||
void rpn_BankSelf(struct Expression *expr)
|
||||
{
|
||||
rpn_Reset(expr);
|
||||
rpn_Init(expr);
|
||||
|
||||
/*
|
||||
* This symbol is not really relocatable, but this makes the assembler
|
||||
@@ -138,7 +188,7 @@ void rpn_BankSymbol(struct Expression *expr, char *tzSym)
|
||||
}
|
||||
|
||||
if (!sym_isConstant(tzSym)) {
|
||||
rpn_Reset(expr);
|
||||
rpn_Init(expr);
|
||||
|
||||
/*
|
||||
* Check that the symbol exists by evaluating and discarding the
|
||||
@@ -158,7 +208,7 @@ void rpn_BankSymbol(struct Expression *expr, char *tzSym)
|
||||
|
||||
void rpn_BankSection(struct Expression *expr, char *tzSectionName)
|
||||
{
|
||||
rpn_Reset(expr);
|
||||
rpn_Init(expr);
|
||||
|
||||
/*
|
||||
* This symbol is not really relocatable, but this makes the assembler
|
||||
|
||||
Reference in New Issue
Block a user