diff --git a/include/asm/rpn.h b/include/asm/rpn.h index 348f0333..e06fb09c 100644 --- a/include/asm/rpn.h +++ b/include/asm/rpn.h @@ -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 */ diff --git a/src/asm/asmy.y b/src/asm/asmy.y index e3a3bcdb..ea11d5c9 100644 --- a/src/asm/asmy.y +++ b/src/asm/asmy.y @@ -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); } ; diff --git a/src/asm/output.c b/src/asm/output.c index ed0ae51a..76064599 100644 --- a/src/asm/output.c +++ b/src/asm/output.c @@ -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); } /* diff --git a/src/asm/rpn.c b/src/asm/rpn.c index 508a563d..c15ed0e8 100644 --- a/src/asm/rpn.c +++ b/src/asm/rpn.c @@ -10,6 +10,7 @@ * Controls RPN expressions for objectfiles */ +#include #include #include #include @@ -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