Allow JR between sections

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 <antonio_nd@outlook.com>
This commit is contained in:
Antonio Niño Díaz
2018-02-22 23:39:41 +00:00
parent d243bd04ef
commit 2ed937db2c
6 changed files with 48 additions and 23 deletions

View File

@@ -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.

View File

@@ -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 */

View File

@@ -455,7 +455,6 @@ static void updateUnion(void)
%type <nConstValue> const_3bit
%type <sVal> const_8bit
%type <sVal> const_16bit
%type <sVal> const_PCrel
%type <nConstValue> sectiontype
%type <tzString> 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);

View File

@@ -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))
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;
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);
out_AbsByte(b & 0xFF);
}
rpn_Reset(expr);
}

View File

@@ -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;

View File

@@ -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.