From 2ed937db2cd1a6b9b4251bd316a4f336f3d02191 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antonio=20Ni=C3=B1o=20D=C3=ADaz?= Date: Thu, 22 Feb 2018 23:39:41 +0000 Subject: [PATCH] Allow JR between sections MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Previously, JR was only allowed if the destination label was in the same section as the JR. This patch removes this restriction. The check to see if the relative value overflows is now done when linking the ROM. Signed-off-by: Antonio Niño Díaz --- docs/rgbds.5.html | 1 + include/linkdefs.h | 3 ++- src/asm/asmy.y | 13 ++----------- src/asm/output.c | 34 +++++++++++++++++++++++----------- src/link/patch.c | 19 +++++++++++++++++++ src/rgbds.5 | 1 + 6 files changed, 48 insertions(+), 23 deletions(-) diff --git a/docs/rgbds.5.html b/docs/rgbds.5.html index 4ea892e5..93a6f218 100644 --- a/docs/rgbds.5.html +++ b/docs/rgbds.5.html @@ -121,6 +121,7 @@ REPT NumberOfSections BYTE Type ; 0 = BYTE patch. ; 1 = little endian WORD patch. ; 2 = little endian LONG patch. + ; 3 = JR offset value BYTE patch. LONG RPNSize ; Size of the buffer with the RPN. ; expression. diff --git a/include/linkdefs.h b/include/linkdefs.h index 3fb5c0a7..b0ec4ee9 100644 --- a/include/linkdefs.h +++ b/include/linkdefs.h @@ -66,7 +66,8 @@ enum eSymbolType { enum ePatchType { PATCH_BYTE = 0x00, PATCH_WORD_L = 0x01, - PATCH_LONG_L = 0x02 + PATCH_LONG_L = 0x02, + PATCH_BYTE_JR = 0x03 }; #endif /* RGBDS_LINKDEFS_H */ diff --git a/src/asm/asmy.y b/src/asm/asmy.y index accfd083..ab7769df 100644 --- a/src/asm/asmy.y +++ b/src/asm/asmy.y @@ -455,7 +455,6 @@ static void updateUnion(void) %type const_3bit %type const_8bit %type const_16bit -%type const_PCrel %type sectiontype %type string @@ -1116,14 +1115,6 @@ constlist_32bit_entry_single : /* empty */ } ; -const_PCrel : relocconst - { - if (!rpn_isPCRelative(&$1)) - yyerror("Expression must be PC-relative"); - $$ = $1; - } -; - const_8bit : relocconst { if( (!rpn_isReloc(&$1)) && (($1.nVal < -128) || ($1.nVal > 255)) ) @@ -1612,12 +1603,12 @@ z80_jp : T_Z80_JP const_16bit } ; -z80_jr : T_Z80_JR const_PCrel +z80_jr : T_Z80_JR const_16bit { out_AbsByte(0x18); out_PCRelByte(&$2); } - | T_Z80_JR ccode comma const_PCrel + | T_Z80_JR ccode comma const_16bit { out_AbsByte(0x20 | ($2 << 3)); out_PCRelByte(&$4); diff --git a/src/asm/output.c b/src/asm/output.c index 53569eb3..db85c0d7 100644 --- a/src/asm/output.c +++ b/src/asm/output.c @@ -593,7 +593,7 @@ void out_SetFileName(char *s) } /* - * Find a section by name and type. If it doesn't exist, create it + * Find a section by name and type. If it doesn't exist, create it */ struct Section *out_FindSection(char *pzName, uint32_t secttype, int32_t org, int32_t bank, int32_t alignment) @@ -764,7 +764,7 @@ void out_String(char *s) } /* - * Output a relocatable byte. Checking will be done to see if it + * Output a relocatable byte. Checking will be done to see if it * is an absolute value in disguise. */ void out_RelByte(struct Expression *expr) @@ -803,7 +803,7 @@ void out_AbsWord(int32_t b) } /* - * Output a relocatable word. Checking will be done to see if + * Output a relocatable word. Checking will be done to see if * it's an absolute value in disguise. */ void out_RelWord(struct Expression *expr) @@ -847,7 +847,7 @@ void out_AbsLong(int32_t b) } /* - * Output a relocatable longword. Checking will be done to see if + * Output a relocatable longword. Checking will be done to see if * is an absolute value in disguise. */ void out_RelLong(struct Expression *expr) @@ -875,19 +875,31 @@ void out_RelLong(struct Expression *expr) } /* - * Output a PC-relative byte + * Output a PC-relative relocatable byte. Checking will be done to see if it + * is an absolute value in disguise. */ void out_PCRelByte(struct Expression *expr) { - int32_t b = expr->nVal; - checkcodesection(); checksectionoverflow(1); - b = (b & 0xFFFF) - (nPC + 1); - if (nPass == 2 && (b < -128 || b > 127)) - yyerror("PC-relative value must be 8-bit"); + if (rpn_isReloc(expr)) { + if (nPass == 2) { + pCurrentSection->tData[nPC] = 0; + createpatch(PATCH_BYTE_JR, expr); + } + pCurrentSection->nPC += 1; + nPC += 1; + pPCSymbol->nValue += 1; + } else { + int32_t b = expr->nVal; - out_AbsByte(b); + b = (int16_t)((b & 0xFFFF) - (nPC + 1)); + + if (nPass == 2 && ((b < -128) || (b > 127))) + yyerror("PC-relative value must be 8-bit"); + + out_AbsByte(b & 0xFF); + } rpn_Reset(expr); } diff --git a/src/link/patch.c b/src/link/patch.c index e8f405b6..3c600a91 100644 --- a/src/link/patch.c +++ b/src/link/patch.c @@ -267,6 +267,7 @@ void Patch(void) pPatch = pSect->pPatches; while (pPatch) { int32_t t; + int32_t nPatchOrg; nPC = pSect->nOrg + pPatch->nOffset; t = calcrpn(pPatch); @@ -306,6 +307,24 @@ void Patch(void) pSect->pData[pPatch->nOffset + 3] = (t >> 24) & 0xFF; break; + case PATCH_BYTE_JR: + /* Calculate absolute address of the patch */ + nPatchOrg = pSect->nOrg + pPatch->nOffset; + + /* t contains the destination of the jump */ + t = (int16_t)((t & 0xFFFF) - (nPatchOrg + 1)); + + if (t >= -128 && t <= 255) { + t &= 0xFF; + pSect->pData[pPatch->nOffset] = + (uint8_t)t; + } else { + errx(1, + "%s(%ld) : Value must be 8-bit", + pPatch->pzFilename, + pPatch->nLineNo); + } + break; } pPatch = pPatch->pNext; diff --git a/src/rgbds.5 b/src/rgbds.5 index 30d80743..8bfa3dab 100644 --- a/src/rgbds.5 +++ b/src/rgbds.5 @@ -113,6 +113,7 @@ REPT NumberOfSections BYTE Type ; 0 = BYTE patch. ; 1 = little endian WORD patch. ; 2 = little endian LONG patch. + ; 3 = JR offset value BYTE patch. LONG RPNSize ; Size of the buffer with the RPN. ; expression.