ref: 762474d3ac55df88584a4e663ad3b4f73304671e
parent: b1adbcc77c5ca8f5fbc8d52150979777560565ba
author: ISSOtm <[email protected]>
date: Mon Jul 27 14:11:42 EDT 2020
Let RGBASM write JR offsets in floating sections This requires some special-casing for `jr @` because the `jr` opcode has already been emitted, but not the operand, so PC points to the middle. Moved the RGBLINK test to RGBASM's folder, and created a new RGBLINK test.
--- a/include/asm/rpn.h
+++ b/include/asm/rpn.h
@@ -49,6 +49,8 @@
void rpn_Symbol(struct Expression *expr, char *tzSym);
void rpn_Number(struct Expression *expr, uint32_t i);
void rpn_LOGNOT(struct Expression *expr, const struct Expression *src);
+struct Symbol const *rpn_SymbolOf(struct Expression const *expr);
+bool rpn_IsDiffConstant(struct Expression const *src, struct Symbol const *sym);
void rpn_BinaryOp(enum RPNCommand op, struct Expression *expr,
const struct Expression *src1,
const struct Expression *src2);
--- a/src/asm/rpn.c
+++ b/src/asm/rpn.c
@@ -297,7 +297,7 @@
}
}
-static struct Symbol const *symbolOf(struct Expression const *expr)
+struct Symbol const *rpn_SymbolOf(struct Expression const *expr)
{
if (!rpn_isSymbol(expr))
return NULL;
@@ -304,20 +304,23 @@
return sym_FindSymbol((char *)expr->tRPN + 1);
}
-static bool isDiffConstant(struct Expression const *src1,
- struct Expression const *src2)
+bool rpn_IsDiffConstant(struct Expression const *src, struct Symbol const *sym)
{
/* Check if both expressions only refer to a single symbol */
- struct Symbol const *symbol1 = symbolOf(src1);
- struct Symbol const *symbol2 = symbolOf(src2);
+ struct Symbol const *sym1 = rpn_SymbolOf(src);
- if (!symbol1 || !symbol2
- || symbol1->type != SYM_LABEL || symbol2->type != SYM_LABEL)
+ if (!sym1 || !sym || sym1->type != SYM_LABEL || sym->type != SYM_LABEL)
return false;
- return sym_GetSection(symbol1) == sym_GetSection(symbol2);
+ return sym_GetSection(sym1) == sym_GetSection(sym);
}
+static bool isDiffConstant(struct Expression const *src1,
+ struct Expression const *src2)
+{
+ return rpn_IsDiffConstant(src1, rpn_SymbolOf(src2));
+}
+
void rpn_BinaryOp(enum RPNCommand op, struct Expression *expr,
const struct Expression *src1, const struct Expression *src2)
{
@@ -428,8 +431,8 @@
}
} else if (op == RPN_SUB && isDiffConstant(src1, src2)) {
- struct Symbol const *symbol1 = symbolOf(src1);
- struct Symbol const *symbol2 = symbolOf(src2);
+ struct Symbol const *symbol1 = rpn_SymbolOf(src1);
+ struct Symbol const *symbol2 = rpn_SymbolOf(src2);
expr->nVal = sym_GetValue(symbol1) - sym_GetValue(symbol2);
expr->isKnown = true;
--- a/src/asm/section.c
+++ b/src/asm/section.c
@@ -553,15 +553,21 @@
{
checkcodesection();
reserveSpace(1);
+ struct Symbol const *pc = sym_FindSymbol("@");
- if (!rpn_isKnown(expr) || pCurrentSection->nOrg == -1) {
+ if (!rpn_IsDiffConstant(expr, pc)) {
createPatch(PATCHTYPE_JR, expr);
writebyte(0);
} else {
- /* Target is relative to the byte *after* the operand */
- uint16_t address = sym_GetPCValue() + 1;
- /* The offset wraps (jump from ROM to HRAM, for loopexample) */
- int16_t offset = expr->nVal - address;
+ struct Symbol const *sym = rpn_SymbolOf(expr);
+ /* The offset wraps (jump from ROM to HRAM, for example) */
+ int16_t offset;
+
+ /* Offset is relative to the byte *after* the operand */
+ if (sym == pc)
+ offset = -2; /* PC as operand to `jr` is lower than reference PC by 2 */
+ else
+ offset = sym_GetValue(sym) - (sym_GetValue(pc) + 1);
if (offset < -128 || offset > 127) {
yyerror("jr target out of reach (expected -129 < %" PRId16 " < 128)",
--- /dev/null
+++ b/test/asm/[email protected]
@@ -1,0 +1,7 @@
+SECTION "fixed", ROM0[0]
+ jr @
+; We need this section to be floating because RGBASM can know the value of PC
+; otherwise, leading to different behavior
+; FIXME: we rely on this landing at address 2, which isn't *guaranteed*...
+SECTION "floating", ROM0
+ jr @
--- /dev/null
+++ b/test/asm/[email protected]
@@ -1,0 +1,1 @@
+
\ No newline at end of file
--- /dev/null
+++ b/test/asm/jr-section.asm
@@ -1,0 +1,5 @@
+SECTION "Test", ROM0
+
+Label:
+ jr Label
+ PRINTV Label - @
--- /dev/null
+++ b/test/asm/jr-section.out
@@ -1,0 +1,1 @@
+$FFFFFFFE
\ No newline at end of file
--- /dev/null
+++ b/test/asm/jr-section.out.bin
@@ -1,0 +1,1 @@
+
\ No newline at end of file
--- a/test/link/[email protected]
+++ b/test/link/[email protected]
@@ -1,7 +1,3 @@
-SECTION "fixed", ROM0[0]
- jr @
-; We need this section to be floating because RGBASM can know the value of PC
-; otherwise, leading to different behavior
-; FIXME: we rely on this landing at address 2, which isn't *guaranteed*...
-SECTION "floating", ROM0
- jr @
+SECTION "Floating", ROM0
+ ; RGBASM knows how to compute `jr @` by itself, but this will evade it
+ jr @ - 1 + 1
--- a/test/link/[email protected]
+++ b/test/link/[email protected]
@@ -1,1 +1,1 @@
-
\ No newline at end of file
+
\ No newline at end of file