diff --git a/src/link/patch.cpp b/src/link/patch.cpp index 8a0e43f7..4efca6a3 100644 --- a/src/link/patch.cpp +++ b/src/link/patch.cpp @@ -585,12 +585,15 @@ static void applyFilePatches(Section §ion, Section &dataSection) { rpnErrorAt(patch, "PC has no value outside of a section"); dataSection.data[offset] = 0; } else { + // A `jr` is *encoded* in ROM as a 1-byte (8-bit) offset, so here `typeSize == 8`, + // but the object's *value* size is a 16-bit absolute address, so we pass 16 here. + checkPatchSize(patch, value, 16); // Offset is relative to the byte *after* the operand // PC as operand to `jr` is lower than reference PC by 2 uint16_t address = patch.pcSection->org + patch.pcOffset + 2; - // The truncation of `value - address` is intentional, since - // a low ROM0 address may `jr` to a high HRAM one. - int16_t jumpOffset = value - address; + // The 16-bit truncation of `value - address` is intentional, since + // a low ROM0 address may `jr` backwards to a high HRAM one. + int16_t jumpOffset = static_cast(value - address); if (jumpOffset < -128 || jumpOffset > 127) { firstErrorAt( diff --git a/test/link/jr-truncation/a.asm b/test/link/jr-truncation/a.asm new file mode 100644 index 00000000..59313abc --- /dev/null +++ b/test/link/jr-truncation/a.asm @@ -0,0 +1,2 @@ +SECTION "jr", ROM0 + jr CONSTANT diff --git a/test/link/jr-truncation/b.asm b/test/link/jr-truncation/b.asm new file mode 100644 index 00000000..be516d73 --- /dev/null +++ b/test/link/jr-truncation/b.asm @@ -0,0 +1 @@ +EXPORT DEF CONSTANT EQU $1234_0078 diff --git a/test/link/jr-truncation/out.err b/test/link/jr-truncation/out.err new file mode 100644 index 00000000..4f2e1af8 --- /dev/null +++ b/test/link/jr-truncation/out.err @@ -0,0 +1,2 @@ +warning: Value $12340078 is not 16-bit [-Wtruncation] + at jr-truncation/a.asm(2) diff --git a/test/link/jr-truncation/ref.out.bin b/test/link/jr-truncation/ref.out.bin new file mode 100644 index 00000000..2d59eb93 Binary files /dev/null and b/test/link/jr-truncation/ref.out.bin differ diff --git a/test/link/jr-truncation/ref.out.sym b/test/link/jr-truncation/ref.out.sym new file mode 100644 index 00000000..d05a90ab --- /dev/null +++ b/test/link/jr-truncation/ref.out.sym @@ -0,0 +1,2 @@ +; File generated by rgblink +12340078 CONSTANT diff --git a/test/link/test.sh b/test/link/test.sh index cb30efc3..f1f48656 100755 --- a/test/link/test.sh +++ b/test/link/test.sh @@ -201,6 +201,17 @@ tryCmpRom "$test"/ref.out.bin tryDiff "$test"/ref.out.sym "$outtemp2" evaluateTest +test="jr-truncation" +startTest +"$RGBASM" -o "$otemp" "$test"/a.asm +"$RGBASM" -o "$outtemp" "$test"/b.asm +continueTest +rgblinkQuiet -o "$gbtemp" -n "$outtemp2" "$otemp" "$outtemp" 2>"$outtemp3" +tryDiff "$test"/out.err "$outtemp3" +tryCmpRom "$test"/ref.out.bin +tryDiff "$test"/ref.out.sym "$outtemp2" +evaluateTest + test="high-low" startTest "$RGBASM" -o "$otemp" "$test"/a.asm