mirror of
https://github.com/gbdev/rgbds.git
synced 2025-11-20 18:22:07 +00:00
@@ -22,7 +22,7 @@ extern struct Section *pSectionList, *pCurrentSection;
|
|||||||
void out_RegisterNode(struct FileStackNode *node);
|
void out_RegisterNode(struct FileStackNode *node);
|
||||||
void out_ReplaceNode(struct FileStackNode *node);
|
void out_ReplaceNode(struct FileStackNode *node);
|
||||||
void out_SetFileName(char *s);
|
void out_SetFileName(char *s);
|
||||||
void out_CreatePatch(uint32_t type, struct Expression const *expr, uint32_t ofs, bool isOperand);
|
void out_CreatePatch(uint32_t type, struct Expression const *expr, uint32_t ofs, uint32_t pcShift);
|
||||||
bool out_CreateAssert(enum AssertionType type, struct Expression const *expr,
|
bool out_CreateAssert(enum AssertionType type, struct Expression const *expr,
|
||||||
char const *message, uint32_t ofs);
|
char const *message, uint32_t ofs);
|
||||||
void out_WriteObject(void);
|
void out_WriteObject(void);
|
||||||
|
|||||||
@@ -62,11 +62,11 @@ void out_AbsWordGroup(uint8_t const *s, int32_t length);
|
|||||||
void out_AbsLongGroup(uint8_t const *s, int32_t length);
|
void out_AbsLongGroup(uint8_t const *s, int32_t length);
|
||||||
void out_Skip(int32_t skip, bool ds);
|
void out_Skip(int32_t skip, bool ds);
|
||||||
void out_String(char const *s);
|
void out_String(char const *s);
|
||||||
void out_RelByte(struct Expression *expr, bool isOperand);
|
void out_RelByte(struct Expression *expr, uint32_t pcShift);
|
||||||
void out_RelBytes(struct Expression *expr, uint32_t n);
|
void out_RelBytes(struct Expression *expr, uint32_t n);
|
||||||
void out_RelWord(struct Expression *expr, bool isOperand);
|
void out_RelWord(struct Expression *expr, uint32_t pcShift);
|
||||||
void out_RelLong(struct Expression *expr, bool isOperand);
|
void out_RelLong(struct Expression *expr, uint32_t pcShift);
|
||||||
void out_PCRelByte(struct Expression *expr, bool isOperand);
|
void out_PCRelByte(struct Expression *expr, uint32_t pcShift);
|
||||||
void out_BinaryFile(char const *s, int32_t startPos);
|
void out_BinaryFile(char const *s, int32_t startPos);
|
||||||
void out_BinaryFileSlice(char const *s, int32_t start_pos, int32_t length);
|
void out_BinaryFileSlice(char const *s, int32_t start_pos, int32_t length);
|
||||||
|
|
||||||
|
|||||||
@@ -34,7 +34,6 @@ struct Patch {
|
|||||||
uint32_t pcSectionID;
|
uint32_t pcSectionID;
|
||||||
uint32_t pcOffset;
|
uint32_t pcOffset;
|
||||||
enum PatchType type;
|
enum PatchType type;
|
||||||
bool isOperand;
|
|
||||||
int32_t rpnSize;
|
int32_t rpnSize;
|
||||||
uint8_t *rpnExpression;
|
uint8_t *rpnExpression;
|
||||||
|
|
||||||
|
|||||||
@@ -99,8 +99,6 @@ enum ExportLevel {
|
|||||||
SYMTYPE_EXPORT
|
SYMTYPE_EXPORT
|
||||||
};
|
};
|
||||||
|
|
||||||
// Bit 7 is special, not part of the actual patch type
|
|
||||||
#define PATCH_ISOPERAND 0x80
|
|
||||||
enum PatchType {
|
enum PatchType {
|
||||||
PATCHTYPE_BYTE,
|
PATCHTYPE_BYTE,
|
||||||
PATCHTYPE_WORD,
|
PATCHTYPE_WORD,
|
||||||
|
|||||||
@@ -39,7 +39,6 @@ struct Patch {
|
|||||||
struct Section *pcSection;
|
struct Section *pcSection;
|
||||||
uint32_t pcOffset;
|
uint32_t pcOffset;
|
||||||
uint8_t type;
|
uint8_t type;
|
||||||
bool isOperand; // If set, PC is not at the patch's address, but at the byte before
|
|
||||||
uint32_t nRPNSize;
|
uint32_t nRPNSize;
|
||||||
uint8_t *pRPN;
|
uint8_t *pRPN;
|
||||||
struct Patch *next;
|
struct Patch *next;
|
||||||
@@ -204,17 +203,12 @@ static uint32_t getSectIDIfAny(struct Section const *sect)
|
|||||||
static void writepatch(struct Patch const *patch, FILE *f)
|
static void writepatch(struct Patch const *patch, FILE *f)
|
||||||
{
|
{
|
||||||
assert(patch->src->ID != -1);
|
assert(patch->src->ID != -1);
|
||||||
uint8_t type = patch->type;
|
|
||||||
|
|
||||||
if (patch->isOperand)
|
|
||||||
type |= PATCH_ISOPERAND;
|
|
||||||
|
|
||||||
putlong(patch->src->ID, f);
|
putlong(patch->src->ID, f);
|
||||||
putlong(patch->lineNo, f);
|
putlong(patch->lineNo, f);
|
||||||
putlong(patch->nOffset, f);
|
putlong(patch->nOffset, f);
|
||||||
putlong(getSectIDIfAny(patch->pcSection), f);
|
putlong(getSectIDIfAny(patch->pcSection), f);
|
||||||
putlong(patch->pcOffset, f);
|
putlong(patch->pcOffset, f);
|
||||||
putc(type, f);
|
putc(patch->type, f);
|
||||||
putlong(patch->nRPNSize, f);
|
putlong(patch->nRPNSize, f);
|
||||||
fwrite(patch->pRPN, 1, patch->nRPNSize, f);
|
fwrite(patch->pRPN, 1, patch->nRPNSize, f);
|
||||||
}
|
}
|
||||||
@@ -387,7 +381,6 @@ static struct Patch *allocpatch(uint32_t type, struct Expression const *expr, ui
|
|||||||
fatalerror("No memory for patch's RPN expression: %s\n", strerror(errno));
|
fatalerror("No memory for patch's RPN expression: %s\n", strerror(errno));
|
||||||
|
|
||||||
patch->type = type;
|
patch->type = type;
|
||||||
patch->isOperand = false;
|
|
||||||
patch->src = node;
|
patch->src = node;
|
||||||
out_RegisterNode(node);
|
out_RegisterNode(node);
|
||||||
patch->lineNo = lexer_GetLineNo();
|
patch->lineNo = lexer_GetLineNo();
|
||||||
@@ -416,11 +409,15 @@ static struct Patch *allocpatch(uint32_t type, struct Expression const *expr, ui
|
|||||||
/*
|
/*
|
||||||
* Create a new patch (includes the rpn expr)
|
* Create a new patch (includes the rpn expr)
|
||||||
*/
|
*/
|
||||||
void out_CreatePatch(uint32_t type, struct Expression const *expr, uint32_t ofs, bool isOperand)
|
void out_CreatePatch(uint32_t type, struct Expression const *expr, uint32_t ofs, uint32_t pcShift)
|
||||||
{
|
{
|
||||||
struct Patch *patch = allocpatch(type, expr, ofs);
|
struct Patch *patch = allocpatch(type, expr, ofs);
|
||||||
|
|
||||||
patch->isOperand = isOperand;
|
// If the patch had a quantity of bytes output before it,
|
||||||
|
// PC is not at the patch's location, but at the location
|
||||||
|
// before those bytes.
|
||||||
|
patch->pcOffset -= pcShift;
|
||||||
|
|
||||||
patch->next = pCurrentSection->patches;
|
patch->next = pCurrentSection->patches;
|
||||||
pCurrentSection->patches = patch;
|
pCurrentSection->patches = patch;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1122,7 +1122,7 @@ constlist_8bit_entry : %empty {
|
|||||||
$$ = true;
|
$$ = true;
|
||||||
}
|
}
|
||||||
| reloc_8bit_no_str {
|
| reloc_8bit_no_str {
|
||||||
out_RelByte(&$1, false);
|
out_RelByte(&$1, 0);
|
||||||
$$ = false;
|
$$ = false;
|
||||||
}
|
}
|
||||||
| string {
|
| string {
|
||||||
@@ -1146,7 +1146,7 @@ constlist_16bit_entry : %empty {
|
|||||||
$$ = true;
|
$$ = true;
|
||||||
}
|
}
|
||||||
| reloc_16bit_no_str {
|
| reloc_16bit_no_str {
|
||||||
out_RelWord(&$1, false);
|
out_RelWord(&$1, 0);
|
||||||
$$ = false;
|
$$ = false;
|
||||||
}
|
}
|
||||||
| string {
|
| string {
|
||||||
@@ -1170,7 +1170,7 @@ constlist_32bit_entry : %empty {
|
|||||||
$$ = true;
|
$$ = true;
|
||||||
}
|
}
|
||||||
| relocexpr_no_str {
|
| relocexpr_no_str {
|
||||||
out_RelLong(&$1, false);
|
out_RelLong(&$1, 0);
|
||||||
$$ = false;
|
$$ = false;
|
||||||
}
|
}
|
||||||
| string {
|
| string {
|
||||||
@@ -1570,27 +1570,27 @@ cpu_command : z80_adc
|
|||||||
|
|
||||||
z80_adc : T_Z80_ADC op_a_n {
|
z80_adc : T_Z80_ADC op_a_n {
|
||||||
out_AbsByte(0xCE);
|
out_AbsByte(0xCE);
|
||||||
out_RelByte(&$2, true);
|
out_RelByte(&$2, 1);
|
||||||
}
|
}
|
||||||
| T_Z80_ADC op_a_r { out_AbsByte(0x88 | $2); }
|
| T_Z80_ADC op_a_r { out_AbsByte(0x88 | $2); }
|
||||||
;
|
;
|
||||||
|
|
||||||
z80_add : T_Z80_ADD op_a_n {
|
z80_add : T_Z80_ADD op_a_n {
|
||||||
out_AbsByte(0xC6);
|
out_AbsByte(0xC6);
|
||||||
out_RelByte(&$2, true);
|
out_RelByte(&$2, 1);
|
||||||
}
|
}
|
||||||
| T_Z80_ADD op_a_r { out_AbsByte(0x80 | $2); }
|
| T_Z80_ADD op_a_r { out_AbsByte(0x80 | $2); }
|
||||||
| T_Z80_ADD op_hl_ss { out_AbsByte(0x09 | ($2 << 4)); }
|
| T_Z80_ADD op_hl_ss { out_AbsByte(0x09 | ($2 << 4)); }
|
||||||
| T_Z80_ADD T_MODE_SP T_COMMA reloc_8bit {
|
| T_Z80_ADD T_MODE_SP T_COMMA reloc_8bit {
|
||||||
out_AbsByte(0xE8);
|
out_AbsByte(0xE8);
|
||||||
out_RelByte(&$4, true);
|
out_RelByte(&$4, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
;
|
;
|
||||||
|
|
||||||
z80_and : T_Z80_AND op_a_n {
|
z80_and : T_Z80_AND op_a_n {
|
||||||
out_AbsByte(0xE6);
|
out_AbsByte(0xE6);
|
||||||
out_RelByte(&$2, true);
|
out_RelByte(&$2, 1);
|
||||||
}
|
}
|
||||||
| T_Z80_AND op_a_r { out_AbsByte(0xA0 | $2); }
|
| T_Z80_AND op_a_r { out_AbsByte(0xA0 | $2); }
|
||||||
;
|
;
|
||||||
@@ -1603,11 +1603,11 @@ z80_bit : T_Z80_BIT const_3bit T_COMMA reg_r {
|
|||||||
|
|
||||||
z80_call : T_Z80_CALL reloc_16bit {
|
z80_call : T_Z80_CALL reloc_16bit {
|
||||||
out_AbsByte(0xCD);
|
out_AbsByte(0xCD);
|
||||||
out_RelWord(&$2, true);
|
out_RelWord(&$2, 1);
|
||||||
}
|
}
|
||||||
| T_Z80_CALL ccode T_COMMA reloc_16bit {
|
| T_Z80_CALL ccode T_COMMA reloc_16bit {
|
||||||
out_AbsByte(0xC4 | ($2 << 3));
|
out_AbsByte(0xC4 | ($2 << 3));
|
||||||
out_RelWord(&$4, true);
|
out_RelWord(&$4, 1);
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
@@ -1616,7 +1616,7 @@ z80_ccf : T_Z80_CCF { out_AbsByte(0x3F); }
|
|||||||
|
|
||||||
z80_cp : T_Z80_CP op_a_n {
|
z80_cp : T_Z80_CP op_a_n {
|
||||||
out_AbsByte(0xFE);
|
out_AbsByte(0xFE);
|
||||||
out_RelByte(&$2, true);
|
out_RelByte(&$2, 1);
|
||||||
}
|
}
|
||||||
| T_Z80_CP op_a_r { out_AbsByte(0xB8 | $2); }
|
| T_Z80_CP op_a_r { out_AbsByte(0xB8 | $2); }
|
||||||
;
|
;
|
||||||
@@ -1650,11 +1650,11 @@ z80_inc : T_Z80_INC reg_r { out_AbsByte(0x04 | ($2 << 3)); }
|
|||||||
|
|
||||||
z80_jp : T_Z80_JP reloc_16bit {
|
z80_jp : T_Z80_JP reloc_16bit {
|
||||||
out_AbsByte(0xC3);
|
out_AbsByte(0xC3);
|
||||||
out_RelWord(&$2, true);
|
out_RelWord(&$2, 1);
|
||||||
}
|
}
|
||||||
| T_Z80_JP ccode T_COMMA reloc_16bit {
|
| T_Z80_JP ccode T_COMMA reloc_16bit {
|
||||||
out_AbsByte(0xC2 | ($2 << 3));
|
out_AbsByte(0xC2 | ($2 << 3));
|
||||||
out_RelWord(&$4, true);
|
out_RelWord(&$4, 1);
|
||||||
}
|
}
|
||||||
| T_Z80_JP T_MODE_HL {
|
| T_Z80_JP T_MODE_HL {
|
||||||
out_AbsByte(0xE9);
|
out_AbsByte(0xE9);
|
||||||
@@ -1663,11 +1663,11 @@ z80_jp : T_Z80_JP reloc_16bit {
|
|||||||
|
|
||||||
z80_jr : T_Z80_JR reloc_16bit {
|
z80_jr : T_Z80_JR reloc_16bit {
|
||||||
out_AbsByte(0x18);
|
out_AbsByte(0x18);
|
||||||
out_PCRelByte(&$2, true);
|
out_PCRelByte(&$2, 1);
|
||||||
}
|
}
|
||||||
| T_Z80_JR ccode T_COMMA reloc_16bit {
|
| T_Z80_JR ccode T_COMMA reloc_16bit {
|
||||||
out_AbsByte(0x20 | ($2 << 3));
|
out_AbsByte(0x20 | ($2 << 3));
|
||||||
out_PCRelByte(&$4, true);
|
out_PCRelByte(&$4, 1);
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
@@ -1691,13 +1691,13 @@ z80_ldio : T_Z80_LDH T_MODE_A T_COMMA op_mem_ind {
|
|||||||
rpn_CheckHRAM(&$4, &$4);
|
rpn_CheckHRAM(&$4, &$4);
|
||||||
|
|
||||||
out_AbsByte(0xF0);
|
out_AbsByte(0xF0);
|
||||||
out_RelByte(&$4, true);
|
out_RelByte(&$4, 1);
|
||||||
}
|
}
|
||||||
| T_Z80_LDH op_mem_ind T_COMMA T_MODE_A {
|
| T_Z80_LDH op_mem_ind T_COMMA T_MODE_A {
|
||||||
rpn_CheckHRAM(&$2, &$2);
|
rpn_CheckHRAM(&$2, &$2);
|
||||||
|
|
||||||
out_AbsByte(0xE0);
|
out_AbsByte(0xE0);
|
||||||
out_RelByte(&$2, true);
|
out_RelByte(&$2, 1);
|
||||||
}
|
}
|
||||||
| T_Z80_LDH T_MODE_A T_COMMA c_ind {
|
| T_Z80_LDH T_MODE_A T_COMMA c_ind {
|
||||||
out_AbsByte(0xF2);
|
out_AbsByte(0xF2);
|
||||||
@@ -1723,24 +1723,24 @@ z80_ld : z80_ld_mem
|
|||||||
|
|
||||||
z80_ld_hl : T_Z80_LD T_MODE_HL T_COMMA T_MODE_SP reloc_8bit {
|
z80_ld_hl : T_Z80_LD T_MODE_HL T_COMMA T_MODE_SP reloc_8bit {
|
||||||
out_AbsByte(0xF8);
|
out_AbsByte(0xF8);
|
||||||
out_RelByte(&$5, true);
|
out_RelByte(&$5, 1);
|
||||||
}
|
}
|
||||||
| T_Z80_LD T_MODE_HL T_COMMA reloc_16bit {
|
| T_Z80_LD T_MODE_HL T_COMMA reloc_16bit {
|
||||||
out_AbsByte(0x01 | (REG_HL << 4));
|
out_AbsByte(0x01 | (REG_HL << 4));
|
||||||
out_RelWord(&$4, true);
|
out_RelWord(&$4, 1);
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
z80_ld_sp : T_Z80_LD T_MODE_SP T_COMMA T_MODE_HL { out_AbsByte(0xF9); }
|
z80_ld_sp : T_Z80_LD T_MODE_SP T_COMMA T_MODE_HL { out_AbsByte(0xF9); }
|
||||||
| T_Z80_LD T_MODE_SP T_COMMA reloc_16bit {
|
| T_Z80_LD T_MODE_SP T_COMMA reloc_16bit {
|
||||||
out_AbsByte(0x01 | (REG_SP << 4));
|
out_AbsByte(0x01 | (REG_SP << 4));
|
||||||
out_RelWord(&$4, true);
|
out_RelWord(&$4, 1);
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
z80_ld_mem : T_Z80_LD op_mem_ind T_COMMA T_MODE_SP {
|
z80_ld_mem : T_Z80_LD op_mem_ind T_COMMA T_MODE_SP {
|
||||||
out_AbsByte(0x08);
|
out_AbsByte(0x08);
|
||||||
out_RelWord(&$2, true);
|
out_RelWord(&$2, 1);
|
||||||
}
|
}
|
||||||
| T_Z80_LD op_mem_ind T_COMMA T_MODE_A {
|
| T_Z80_LD op_mem_ind T_COMMA T_MODE_A {
|
||||||
if (optimizeloads && rpn_isKnown(&$2)
|
if (optimizeloads && rpn_isKnown(&$2)
|
||||||
@@ -1750,7 +1750,7 @@ z80_ld_mem : T_Z80_LD op_mem_ind T_COMMA T_MODE_SP {
|
|||||||
rpn_Free(&$2);
|
rpn_Free(&$2);
|
||||||
} else {
|
} else {
|
||||||
out_AbsByte(0xEA);
|
out_AbsByte(0xEA);
|
||||||
out_RelWord(&$2, true);
|
out_RelWord(&$2, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
@@ -1767,7 +1767,7 @@ z80_ld_rr : T_Z80_LD reg_rr T_COMMA T_MODE_A {
|
|||||||
|
|
||||||
z80_ld_r : T_Z80_LD reg_r T_COMMA reloc_8bit {
|
z80_ld_r : T_Z80_LD reg_r T_COMMA reloc_8bit {
|
||||||
out_AbsByte(0x06 | ($2 << 3));
|
out_AbsByte(0x06 | ($2 << 3));
|
||||||
out_RelByte(&$4, true);
|
out_RelByte(&$4, 1);
|
||||||
}
|
}
|
||||||
| T_Z80_LD reg_r T_COMMA reg_r {
|
| T_Z80_LD reg_r T_COMMA reg_r {
|
||||||
if (($2 == REG_HL_IND) && ($4 == REG_HL_IND))
|
if (($2 == REG_HL_IND) && ($4 == REG_HL_IND))
|
||||||
@@ -1798,7 +1798,7 @@ z80_ld_a : T_Z80_LD reg_r T_COMMA c_ind {
|
|||||||
rpn_Free(&$4);
|
rpn_Free(&$4);
|
||||||
} else {
|
} else {
|
||||||
out_AbsByte(0xFA);
|
out_AbsByte(0xFA);
|
||||||
out_RelWord(&$4, true);
|
out_RelWord(&$4, 1);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
error("Destination operand must be A\n");
|
error("Destination operand must be A\n");
|
||||||
@@ -1809,11 +1809,11 @@ z80_ld_a : T_Z80_LD reg_r T_COMMA c_ind {
|
|||||||
|
|
||||||
z80_ld_ss : T_Z80_LD T_MODE_BC T_COMMA reloc_16bit {
|
z80_ld_ss : T_Z80_LD T_MODE_BC T_COMMA reloc_16bit {
|
||||||
out_AbsByte(0x01 | (REG_BC << 4));
|
out_AbsByte(0x01 | (REG_BC << 4));
|
||||||
out_RelWord(&$4, true);
|
out_RelWord(&$4, 1);
|
||||||
}
|
}
|
||||||
| T_Z80_LD T_MODE_DE T_COMMA reloc_16bit {
|
| T_Z80_LD T_MODE_DE T_COMMA reloc_16bit {
|
||||||
out_AbsByte(0x01 | (REG_DE << 4));
|
out_AbsByte(0x01 | (REG_DE << 4));
|
||||||
out_RelWord(&$4, true);
|
out_RelWord(&$4, 1);
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
* HL is taken care of in z80_ld_hl
|
* HL is taken care of in z80_ld_hl
|
||||||
@@ -1826,7 +1826,7 @@ z80_nop : T_Z80_NOP { out_AbsByte(0x00); }
|
|||||||
|
|
||||||
z80_or : T_Z80_OR op_a_n {
|
z80_or : T_Z80_OR op_a_n {
|
||||||
out_AbsByte(0xF6);
|
out_AbsByte(0xF6);
|
||||||
out_RelByte(&$2, true);
|
out_RelByte(&$2, 1);
|
||||||
}
|
}
|
||||||
| T_Z80_OR op_a_r { out_AbsByte(0xB0 | $2); }
|
| T_Z80_OR op_a_r { out_AbsByte(0xB0 | $2); }
|
||||||
;
|
;
|
||||||
@@ -1890,10 +1890,7 @@ z80_rrca : T_Z80_RRCA { out_AbsByte(0x0F); }
|
|||||||
z80_rst : T_Z80_RST reloc_8bit {
|
z80_rst : T_Z80_RST reloc_8bit {
|
||||||
rpn_CheckRST(&$2, &$2);
|
rpn_CheckRST(&$2, &$2);
|
||||||
if (!rpn_isKnown(&$2))
|
if (!rpn_isKnown(&$2))
|
||||||
// This could be considered as an "operand", but the purpose of the
|
out_RelByte(&$2, 0);
|
||||||
// "operand" flag is to signal to RGBLINK to correct PC,
|
|
||||||
// which we don't want here.
|
|
||||||
out_RelByte(&$2, false);
|
|
||||||
else
|
else
|
||||||
out_AbsByte(0xC7 | $2.nVal);
|
out_AbsByte(0xC7 | $2.nVal);
|
||||||
rpn_Free(&$2);
|
rpn_Free(&$2);
|
||||||
@@ -1902,7 +1899,7 @@ z80_rst : T_Z80_RST reloc_8bit {
|
|||||||
|
|
||||||
z80_sbc : T_Z80_SBC op_a_n {
|
z80_sbc : T_Z80_SBC op_a_n {
|
||||||
out_AbsByte(0xDE);
|
out_AbsByte(0xDE);
|
||||||
out_RelByte(&$2, true);
|
out_RelByte(&$2, 1);
|
||||||
}
|
}
|
||||||
| T_Z80_SBC op_a_r { out_AbsByte(0x98 | $2); }
|
| T_Z80_SBC op_a_r { out_AbsByte(0x98 | $2); }
|
||||||
;
|
;
|
||||||
@@ -1940,13 +1937,13 @@ z80_stop : T_Z80_STOP {
|
|||||||
}
|
}
|
||||||
| T_Z80_STOP reloc_8bit {
|
| T_Z80_STOP reloc_8bit {
|
||||||
out_AbsByte(0x10);
|
out_AbsByte(0x10);
|
||||||
out_RelByte(&$2, true);
|
out_RelByte(&$2, 1);
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
z80_sub : T_Z80_SUB op_a_n {
|
z80_sub : T_Z80_SUB op_a_n {
|
||||||
out_AbsByte(0xD6);
|
out_AbsByte(0xD6);
|
||||||
out_RelByte(&$2, true);
|
out_RelByte(&$2, 1);
|
||||||
}
|
}
|
||||||
| T_Z80_SUB op_a_r { out_AbsByte(0x90 | $2);
|
| T_Z80_SUB op_a_r { out_AbsByte(0x90 | $2);
|
||||||
}
|
}
|
||||||
@@ -1960,7 +1957,7 @@ z80_swap : T_Z80_SWAP reg_r {
|
|||||||
|
|
||||||
z80_xor : T_Z80_XOR op_a_n {
|
z80_xor : T_Z80_XOR op_a_n {
|
||||||
out_AbsByte(0xEE);
|
out_AbsByte(0xEE);
|
||||||
out_RelByte(&$2, true);
|
out_RelByte(&$2, 1);
|
||||||
}
|
}
|
||||||
| T_Z80_XOR op_a_r { out_AbsByte(0xA8 | $2); }
|
| T_Z80_XOR op_a_r { out_AbsByte(0xA8 | $2); }
|
||||||
;
|
;
|
||||||
|
|||||||
@@ -488,9 +488,10 @@ static inline void writelong(uint32_t b)
|
|||||||
writebyte(b >> 24);
|
writebyte(b >> 24);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void createPatch(enum PatchType type, struct Expression const *expr, bool isOperand)
|
static inline void createPatch(enum PatchType type, struct Expression const *expr,
|
||||||
|
uint32_t pcShift)
|
||||||
{
|
{
|
||||||
out_CreatePatch(type, expr, sect_GetOutputOffset(), isOperand);
|
out_CreatePatch(type, expr, sect_GetOutputOffset(), pcShift);
|
||||||
}
|
}
|
||||||
|
|
||||||
void sect_StartUnion(void)
|
void sect_StartUnion(void)
|
||||||
@@ -617,13 +618,13 @@ void out_String(char const *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.
|
* is an absolute value in disguise.
|
||||||
*/
|
*/
|
||||||
void out_RelByte(struct Expression *expr, bool isOperand)
|
void out_RelByte(struct Expression *expr, uint32_t pcShift)
|
||||||
{
|
{
|
||||||
checkcodesection();
|
checkcodesection();
|
||||||
reserveSpace(1);
|
reserveSpace(1);
|
||||||
|
|
||||||
if (!rpn_isKnown(expr)) {
|
if (!rpn_isKnown(expr)) {
|
||||||
createPatch(PATCHTYPE_BYTE, expr, isOperand);
|
createPatch(PATCHTYPE_BYTE, expr, pcShift);
|
||||||
writebyte(0);
|
writebyte(0);
|
||||||
} else {
|
} else {
|
||||||
writebyte(expr->nVal);
|
writebyte(expr->nVal);
|
||||||
@@ -640,9 +641,9 @@ void out_RelBytes(struct Expression *expr, uint32_t n)
|
|||||||
checkcodesection();
|
checkcodesection();
|
||||||
reserveSpace(n);
|
reserveSpace(n);
|
||||||
|
|
||||||
while (n--) {
|
for (uint32_t i = 0; i < n; i++) {
|
||||||
if (!rpn_isKnown(expr)) {
|
if (!rpn_isKnown(expr)) {
|
||||||
createPatch(PATCHTYPE_BYTE, expr, false);
|
createPatch(PATCHTYPE_BYTE, expr, i);
|
||||||
writebyte(0);
|
writebyte(0);
|
||||||
} else {
|
} else {
|
||||||
writebyte(expr->nVal);
|
writebyte(expr->nVal);
|
||||||
@@ -655,13 +656,13 @@ void out_RelBytes(struct Expression *expr, uint32_t n)
|
|||||||
* 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.
|
* it's an absolute value in disguise.
|
||||||
*/
|
*/
|
||||||
void out_RelWord(struct Expression *expr, bool isOperand)
|
void out_RelWord(struct Expression *expr, uint32_t pcShift)
|
||||||
{
|
{
|
||||||
checkcodesection();
|
checkcodesection();
|
||||||
reserveSpace(2);
|
reserveSpace(2);
|
||||||
|
|
||||||
if (!rpn_isKnown(expr)) {
|
if (!rpn_isKnown(expr)) {
|
||||||
createPatch(PATCHTYPE_WORD, expr, isOperand);
|
createPatch(PATCHTYPE_WORD, expr, pcShift);
|
||||||
writeword(0);
|
writeword(0);
|
||||||
} else {
|
} else {
|
||||||
writeword(expr->nVal);
|
writeword(expr->nVal);
|
||||||
@@ -673,13 +674,13 @@ void out_RelWord(struct Expression *expr, bool isOperand)
|
|||||||
* 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.
|
* is an absolute value in disguise.
|
||||||
*/
|
*/
|
||||||
void out_RelLong(struct Expression *expr, bool isOperand)
|
void out_RelLong(struct Expression *expr, uint32_t pcShift)
|
||||||
{
|
{
|
||||||
checkcodesection();
|
checkcodesection();
|
||||||
reserveSpace(2);
|
reserveSpace(2);
|
||||||
|
|
||||||
if (!rpn_isKnown(expr)) {
|
if (!rpn_isKnown(expr)) {
|
||||||
createPatch(PATCHTYPE_LONG, expr, isOperand);
|
createPatch(PATCHTYPE_LONG, expr, pcShift);
|
||||||
writelong(0);
|
writelong(0);
|
||||||
} else {
|
} else {
|
||||||
writelong(expr->nVal);
|
writelong(expr->nVal);
|
||||||
@@ -691,14 +692,14 @@ void out_RelLong(struct Expression *expr, bool isOperand)
|
|||||||
* Output a PC-relative relocatable byte. Checking will be done to see if it
|
* Output a PC-relative relocatable byte. Checking will be done to see if it
|
||||||
* is an absolute value in disguise.
|
* is an absolute value in disguise.
|
||||||
*/
|
*/
|
||||||
void out_PCRelByte(struct Expression *expr, bool isOperand)
|
void out_PCRelByte(struct Expression *expr, uint32_t pcShift)
|
||||||
{
|
{
|
||||||
checkcodesection();
|
checkcodesection();
|
||||||
reserveSpace(1);
|
reserveSpace(1);
|
||||||
struct Symbol const *pc = sym_GetPC();
|
struct Symbol const *pc = sym_GetPC();
|
||||||
|
|
||||||
if (!rpn_IsDiffConstant(expr, pc)) {
|
if (!rpn_IsDiffConstant(expr, pc)) {
|
||||||
createPatch(PATCHTYPE_JR, expr, isOperand);
|
createPatch(PATCHTYPE_JR, expr, pcShift);
|
||||||
writebyte(0);
|
writebyte(0);
|
||||||
} else {
|
} else {
|
||||||
struct Symbol const *sym = rpn_SymbolOf(expr);
|
struct Symbol const *sym = rpn_SymbolOf(expr);
|
||||||
|
|||||||
@@ -286,8 +286,7 @@ static void readPatch(FILE *file, struct Patch *patch, char const *fileName, cha
|
|||||||
tryGetc(type, file,
|
tryGetc(type, file,
|
||||||
"%s: Unable to read \"%s\"'s patch #%" PRIu32 "'s type: %s",
|
"%s: Unable to read \"%s\"'s patch #%" PRIu32 "'s type: %s",
|
||||||
fileName, sectName, i);
|
fileName, sectName, i);
|
||||||
patch->type = type & 0x7F;
|
patch->type = type;
|
||||||
patch->isOperand = type & PATCH_ISOPERAND;
|
|
||||||
tryReadlong(patch->rpnSize, file,
|
tryReadlong(patch->rpnSize, file,
|
||||||
"%s: Unable to read \"%s\"'s patch #%" PRIu32 "'s RPN size: %s",
|
"%s: Unable to read \"%s\"'s patch #%" PRIu32 "'s RPN size: %s",
|
||||||
fileName, sectName, i);
|
fileName, sectName, i);
|
||||||
|
|||||||
@@ -421,10 +421,6 @@ static int32_t computeRPNExpr(struct Patch const *patch,
|
|||||||
isError = true;
|
isError = true;
|
||||||
} else {
|
} else {
|
||||||
value = patch->pcOffset + patch->pcSection->org;
|
value = patch->pcOffset + patch->pcSection->org;
|
||||||
// If the patch is an operand, PC is not at the patch's
|
|
||||||
// location, but at the (opcode) byte right before it
|
|
||||||
if (patch->isOperand)
|
|
||||||
value--;
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
symbol = getSymbol(fileSymbols, value);
|
symbol = getSymbol(fileSymbols, value);
|
||||||
@@ -520,9 +516,10 @@ static void applyFilePatches(struct Section *section, struct Section *dataSectio
|
|||||||
|
|
||||||
/* `jr` is quite unlike the others... */
|
/* `jr` is quite unlike the others... */
|
||||||
if (patch->type == PATCHTYPE_JR) {
|
if (patch->type == PATCHTYPE_JR) {
|
||||||
/* Target is relative to the byte *after* the operand */
|
// 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
|
uint16_t address = patch->pcSection->org
|
||||||
+ patch->pcOffset + 1;
|
+ patch->pcOffset + 2;
|
||||||
int16_t jumpOffset = value - address;
|
int16_t jumpOffset = value - address;
|
||||||
|
|
||||||
if (!isError && (jumpOffset < -128 || jumpOffset > 127))
|
if (!isError && (jumpOffset < -128 || jumpOffset > 127))
|
||||||
|
|||||||
14
test/asm/ds-@.asm
Normal file
14
test/asm/ds-@.asm
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
SECTION "test fixed", ROM0[0]
|
||||||
|
|
||||||
|
FixedStart:
|
||||||
|
ds 8, (@ - FixedStart) * 2 + zero
|
||||||
|
ds 8, (@ - FixedStart) * 2 + zero
|
||||||
|
|
||||||
|
SECTION "test floating", ROM0
|
||||||
|
|
||||||
|
FloatingStart:
|
||||||
|
ds 8, (@ - FloatingStart) * 2 + zero
|
||||||
|
ds 8, (@ - FloatingStart) * 2 + zero
|
||||||
|
|
||||||
|
SECTION "zero", ROM0[0]
|
||||||
|
zero:
|
||||||
0
test/asm/ds-@.err
Normal file
0
test/asm/ds-@.err
Normal file
0
test/asm/ds-@.out
Normal file
0
test/asm/ds-@.out
Normal file
BIN
test/asm/ds-@.out.bin
Normal file
BIN
test/asm/ds-@.out.bin
Normal file
Binary file not shown.
Reference in New Issue
Block a user