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.