shithub: rgbds

Download patch

ref: 2ed937db2cd1a6b9b4251bd316a4f336f3d02191
parent: d243bd04ef929aa99158496c6f5fb048ec55ffa1
author: Antonio Niño Díaz <[email protected]>
date: Thu Feb 22 18:39:41 EST 2018

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 <[email protected]>

--- a/docs/rgbds.5.html
+++ b/docs/rgbds.5.html
@@ -121,6 +121,7 @@
             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. 
--- a/include/linkdefs.h
+++ b/include/linkdefs.h
@@ -66,7 +66,8 @@
 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 */
--- a/src/asm/asmy.y
+++ b/src/asm/asmy.y
@@ -455,7 +455,6 @@
 %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 @@
 		}
 ;
 
-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_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);
--- a/src/asm/output.c
+++ b/src/asm/output.c
@@ -593,7 +593,7 @@
 }
 
 /*
- * 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 @@
 }
 
 /*
- * 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 @@
 }
 
 /*
- * 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 @@
 }
 
 /*
- * 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 @@
 }
 
 /*
- * 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);
 }
 
--- a/src/link/patch.c
+++ b/src/link/patch.c
@@ -267,6 +267,7 @@
 		pPatch = pSect->pPatches;
 		while (pPatch) {
 			int32_t t;
+			int32_t nPatchOrg;
 
 			nPC = pSect->nOrg + pPatch->nOffset;
 			t = calcrpn(pPatch);
@@ -305,6 +306,24 @@
 					(t >> 16) & 0xFF;
 				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;
 			}
 
--- a/src/rgbds.5
+++ b/src/rgbds.5
@@ -113,6 +113,7 @@
             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.