mirror of
https://github.com/gbdev/rgbds.git
synced 2025-11-20 10:12:06 +00:00
Remove "EOF-newline" lexer hack
In preparation for an upcoming change Makes for nicer error messages, complaining about EOF instead of newlines The hack had to be kept for the lexer raw mode to avoid a bug; see the relevant code comment for more info.
This commit is contained in:
@@ -22,8 +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,
|
void out_CreatePatch(uint32_t type, struct Expression const *expr, uint32_t ofs, bool isOperand);
|
||||||
uint32_t ofs);
|
|
||||||
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);
|
void out_RelByte(struct Expression *expr, bool isOperand);
|
||||||
void out_RelBytes(struct Expression *expr, uint32_t n);
|
void out_RelBytes(struct Expression *expr, uint32_t n);
|
||||||
void out_RelWord(struct Expression *expr);
|
void out_RelWord(struct Expression *expr, bool isOperand);
|
||||||
void out_RelLong(struct Expression *expr);
|
void out_RelLong(struct Expression *expr, bool isOperand);
|
||||||
void out_PCRelByte(struct Expression *expr);
|
void out_PCRelByte(struct Expression *expr, bool isOperand);
|
||||||
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,6 +34,7 @@ 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,6 +99,8 @@ 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,
|
||||||
|
|||||||
@@ -341,7 +341,6 @@ struct LexerState {
|
|||||||
bool atLineStart;
|
bool atLineStart;
|
||||||
uint32_t lineNo;
|
uint32_t lineNo;
|
||||||
uint32_t colNo;
|
uint32_t colNo;
|
||||||
int lastToken;
|
|
||||||
|
|
||||||
bool capturing; /* Whether the text being lexed should be captured */
|
bool capturing; /* Whether the text being lexed should be captured */
|
||||||
size_t captureSize; /* Amount of text captured */
|
size_t captureSize; /* Amount of text captured */
|
||||||
@@ -363,7 +362,6 @@ static void initState(struct LexerState *state)
|
|||||||
{
|
{
|
||||||
state->mode = LEXER_NORMAL;
|
state->mode = LEXER_NORMAL;
|
||||||
state->atLineStart = true; /* yylex() will init colNo due to this */
|
state->atLineStart = true; /* yylex() will init colNo due to this */
|
||||||
state->lastToken = 0;
|
|
||||||
|
|
||||||
state->capturing = false;
|
state->capturing = false;
|
||||||
state->captureBuf = NULL;
|
state->captureBuf = NULL;
|
||||||
@@ -1921,9 +1919,13 @@ static int yylex_RAW(void)
|
|||||||
i--;
|
i--;
|
||||||
/* Empty macro args break their expansion, so prevent that */
|
/* Empty macro args break their expansion, so prevent that */
|
||||||
if (i == 0) {
|
if (i == 0) {
|
||||||
/* Return the EOF token, and don't shift a non-existent char! */
|
// If at EOF, don't shift a non-existent chat
|
||||||
|
// However, don't return EOF, as this might cause a bug...
|
||||||
|
// If a macro is invoked on the last line of a file, with no blank
|
||||||
|
// line afterwards, returning EOF here will cause Bison to stop
|
||||||
|
// parsing, despite the lexer being ready to output more.
|
||||||
if (c == EOF)
|
if (c == EOF)
|
||||||
return 0;
|
return T_NEWLINE;
|
||||||
shiftChars(1);
|
shiftChars(1);
|
||||||
if (c == '\r' && peek(0) == '\n')
|
if (c == '\r' && peek(0) == '\n')
|
||||||
shiftChars(1);
|
shiftChars(1);
|
||||||
@@ -2163,21 +2165,16 @@ restart:
|
|||||||
|
|
||||||
/* Make sure to terminate files with a line feed */
|
/* Make sure to terminate files with a line feed */
|
||||||
if (token == 0) {
|
if (token == 0) {
|
||||||
if (lexerState->lastToken != T_NEWLINE) {
|
/* Try to switch to new buffer; if it succeeds, scan again */
|
||||||
dbgPrint("Forcing EOL at EOF\n");
|
dbgPrint("Reached EOF!\n");
|
||||||
token = T_NEWLINE;
|
/* Captures end at their buffer's boundary no matter what */
|
||||||
} else { /* Try to switch to new buffer; if it succeeds, scan again */
|
if (!lexerState->capturing) {
|
||||||
dbgPrint("Reached EOF!\n");
|
if (!yywrap())
|
||||||
/* Captures end at their buffer's boundary no matter what */
|
goto restart;
|
||||||
if (!lexerState->capturing) {
|
dbgPrint("Reached end of input.");
|
||||||
if (!yywrap())
|
return 0;
|
||||||
goto restart;
|
|
||||||
dbgPrint("Reached end of input.");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
lexerState->lastToken = token;
|
|
||||||
|
|
||||||
lexerState->atLineStart = false;
|
lexerState->atLineStart = false;
|
||||||
if (token == T_NEWLINE)
|
if (token == T_NEWLINE)
|
||||||
@@ -2238,7 +2235,6 @@ void lexer_CaptureRept(struct CaptureBody *capture)
|
|||||||
* We know we have read exactly "ENDR", not e.g. an EQUS
|
* We know we have read exactly "ENDR", not e.g. an EQUS
|
||||||
*/
|
*/
|
||||||
lexerState->captureSize -= strlen("ENDR");
|
lexerState->captureSize -= strlen("ENDR");
|
||||||
lexerState->lastToken = T_POP_ENDR; // Force EOL at EOF
|
|
||||||
goto finish;
|
goto finish;
|
||||||
}
|
}
|
||||||
level--;
|
level--;
|
||||||
@@ -2301,7 +2297,6 @@ void lexer_CaptureMacroBody(struct CaptureBody *capture)
|
|||||||
* We know we have read exactly "ENDM", not e.g. an EQUS
|
* We know we have read exactly "ENDM", not e.g. an EQUS
|
||||||
*/
|
*/
|
||||||
lexerState->captureSize -= strlen("ENDM");
|
lexerState->captureSize -= strlen("ENDM");
|
||||||
lexerState->lastToken = T_POP_ENDM; // Force EOL at EOF
|
|
||||||
goto finish;
|
goto finish;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ 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;
|
||||||
@@ -203,13 +204,17 @@ 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(patch->type, f);
|
putc(type, f);
|
||||||
putlong(patch->nRPNSize, f);
|
putlong(patch->nRPNSize, f);
|
||||||
fwrite(patch->pRPN, 1, patch->nRPNSize, f);
|
fwrite(patch->pRPN, 1, patch->nRPNSize, f);
|
||||||
}
|
}
|
||||||
@@ -382,6 +387,7 @@ 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();
|
||||||
@@ -410,10 +416,11 @@ 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)
|
void out_CreatePatch(uint32_t type, struct Expression const *expr, uint32_t ofs, bool isOperand)
|
||||||
{
|
{
|
||||||
struct Patch *patch = allocpatch(type, expr, ofs);
|
struct Patch *patch = allocpatch(type, expr, ofs);
|
||||||
|
|
||||||
|
patch->isOperand = isOperand;
|
||||||
patch->next = pCurrentSection->patches;
|
patch->next = pCurrentSection->patches;
|
||||||
pCurrentSection->patches = patch;
|
pCurrentSection->patches = patch;
|
||||||
}
|
}
|
||||||
|
|||||||
164
src/asm/parser.y
164
src/asm/parser.y
@@ -36,9 +36,6 @@
|
|||||||
#include "linkdefs.h"
|
#include "linkdefs.h"
|
||||||
#include "platform.h" // strncasecmp, strdup
|
#include "platform.h" // strncasecmp, strdup
|
||||||
|
|
||||||
int32_t nPCOffset; /* Read by rpn_Symbol */
|
|
||||||
|
|
||||||
static uint32_t nListCountEmpty;
|
|
||||||
static bool executeElseBlock; /* If this is set, ELIFs cannot be executed anymore */
|
static bool executeElseBlock; /* If this is set, ELIFs cannot be executed anymore */
|
||||||
static struct CaptureBody captureBody; /* Captures a REPT/FOR or MACRO */
|
static struct CaptureBody captureBody; /* Captures a REPT/FOR or MACRO */
|
||||||
|
|
||||||
@@ -406,6 +403,7 @@ enum {
|
|||||||
int32_t step;
|
int32_t step;
|
||||||
} forArgs;
|
} forArgs;
|
||||||
struct StrFmtArgList strfmtArgs;
|
struct StrFmtArgList strfmtArgs;
|
||||||
|
bool hasEmpty; // Whether `db`, `dw`, `dl` argument lists contain any empty entries
|
||||||
}
|
}
|
||||||
|
|
||||||
%type <sVal> relocexpr
|
%type <sVal> relocexpr
|
||||||
@@ -420,6 +418,9 @@ enum {
|
|||||||
%type <sVal> reloc_16bit
|
%type <sVal> reloc_16bit
|
||||||
%type <sVal> reloc_16bit_no_str
|
%type <sVal> reloc_16bit_no_str
|
||||||
%type <nConstValue> sectiontype
|
%type <nConstValue> sectiontype
|
||||||
|
%type <hasEmpty> constlist_8bit constlist_8bit_entry
|
||||||
|
%type <hasEmpty> constlist_16bit constlist_16bit_entry
|
||||||
|
%type <hasEmpty> constlist_32bit constlist_32bit_entry
|
||||||
|
|
||||||
%type <tzString> string
|
%type <tzString> string
|
||||||
%type <tzString> strcat_args
|
%type <tzString> strcat_args
|
||||||
@@ -584,21 +585,21 @@ enum {
|
|||||||
|
|
||||||
%%
|
%%
|
||||||
|
|
||||||
asmfile : lines;
|
asmfile : lines last_line
|
||||||
|
;
|
||||||
|
|
||||||
/* Note: The lexer adds T_NEWLINE at the end of the input */
|
/* Note: The lexer adds T_NEWLINE at the end of the input */
|
||||||
lines : %empty
|
lines : %empty
|
||||||
| lines {
|
| lines line
|
||||||
nListCountEmpty = 0;
|
|
||||||
nPCOffset = 0;
|
|
||||||
} line
|
|
||||||
;
|
;
|
||||||
|
|
||||||
line : label T_NEWLINE
|
last_line : label
|
||||||
| label cpu_command T_NEWLINE
|
| label cpu_command
|
||||||
| label macro T_NEWLINE
|
| label macro
|
||||||
| label directive T_NEWLINE
|
| label directive
|
||||||
| assignment_directive T_NEWLINE
|
| assignment_directive
|
||||||
|
;
|
||||||
|
line : last_line T_NEWLINE
|
||||||
| line_directive /* Directives that manage newlines themselves */
|
| line_directive /* Directives that manage newlines themselves */
|
||||||
| error T_NEWLINE { /* Continue parsing the next line on a syntax error */
|
| error T_NEWLINE { /* Continue parsing the next line on a syntax error */
|
||||||
fstk_StopRept();
|
fstk_StopRept();
|
||||||
@@ -951,7 +952,7 @@ ds : T_POP_DS uconst { out_Skip($2, true); }
|
|||||||
|
|
||||||
/* Authorize empty entries if there is only one */
|
/* Authorize empty entries if there is only one */
|
||||||
db : T_POP_DB constlist_8bit_entry T_COMMA constlist_8bit {
|
db : T_POP_DB constlist_8bit_entry T_COMMA constlist_8bit {
|
||||||
if (nListCountEmpty > 0)
|
if ($2 || $4)
|
||||||
warning(WARNING_EMPTY_ENTRY,
|
warning(WARNING_EMPTY_ENTRY,
|
||||||
"Empty entry in list of 8-bit elements (treated as padding).\n");
|
"Empty entry in list of 8-bit elements (treated as padding).\n");
|
||||||
}
|
}
|
||||||
@@ -959,7 +960,7 @@ db : T_POP_DB constlist_8bit_entry T_COMMA constlist_8bit {
|
|||||||
;
|
;
|
||||||
|
|
||||||
dw : T_POP_DW constlist_16bit_entry T_COMMA constlist_16bit {
|
dw : T_POP_DW constlist_16bit_entry T_COMMA constlist_16bit {
|
||||||
if (nListCountEmpty > 0)
|
if ($2 || $4)
|
||||||
warning(WARNING_EMPTY_ENTRY,
|
warning(WARNING_EMPTY_ENTRY,
|
||||||
"Empty entry in list of 16-bit elements (treated as padding).\n");
|
"Empty entry in list of 16-bit elements (treated as padding).\n");
|
||||||
}
|
}
|
||||||
@@ -967,7 +968,7 @@ dw : T_POP_DW constlist_16bit_entry T_COMMA constlist_16bit {
|
|||||||
;
|
;
|
||||||
|
|
||||||
dl : T_POP_DL constlist_32bit_entry T_COMMA constlist_32bit {
|
dl : T_POP_DL constlist_32bit_entry T_COMMA constlist_32bit {
|
||||||
if (nListCountEmpty > 0)
|
if ($2 || $4)
|
||||||
warning(WARNING_EMPTY_ENTRY,
|
warning(WARNING_EMPTY_ENTRY,
|
||||||
"Empty entry in list of 32-bit elements (treated as padding).\n");
|
"Empty entry in list of 32-bit elements (treated as padding).\n");
|
||||||
}
|
}
|
||||||
@@ -1110,56 +1111,74 @@ const_3bit : const {
|
|||||||
;
|
;
|
||||||
|
|
||||||
constlist_8bit : constlist_8bit_entry
|
constlist_8bit : constlist_8bit_entry
|
||||||
| constlist_8bit T_COMMA constlist_8bit_entry
|
| constlist_8bit T_COMMA constlist_8bit_entry {
|
||||||
|
$$ = $1 || $3;
|
||||||
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
constlist_8bit_entry : %empty {
|
constlist_8bit_entry : %empty {
|
||||||
out_Skip(1, false);
|
out_Skip(1, false);
|
||||||
nListCountEmpty++;
|
$$ = true;
|
||||||
|
}
|
||||||
|
| reloc_8bit_no_str {
|
||||||
|
out_RelByte(&$1, false);
|
||||||
|
$$ = false;
|
||||||
}
|
}
|
||||||
| reloc_8bit_no_str { out_RelByte(&$1); }
|
|
||||||
| string {
|
| string {
|
||||||
uint8_t *output = malloc(strlen($1)); /* Cannot be larger than that */
|
uint8_t *output = malloc(strlen($1)); /* Cannot be larger than that */
|
||||||
int32_t length = charmap_Convert($1, output);
|
int32_t length = charmap_Convert($1, output);
|
||||||
|
|
||||||
out_AbsByteGroup(output, length);
|
out_AbsByteGroup(output, length);
|
||||||
free(output);
|
free(output);
|
||||||
|
$$ = false;
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
constlist_16bit : constlist_16bit_entry
|
constlist_16bit : constlist_16bit_entry
|
||||||
| constlist_16bit T_COMMA constlist_16bit_entry
|
| constlist_16bit T_COMMA constlist_16bit_entry {
|
||||||
|
$$ = $1 || $3;
|
||||||
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
constlist_16bit_entry : %empty {
|
constlist_16bit_entry : %empty {
|
||||||
out_Skip(2, false);
|
out_Skip(2, false);
|
||||||
nListCountEmpty++;
|
$$ = true;
|
||||||
|
}
|
||||||
|
| reloc_16bit_no_str {
|
||||||
|
out_RelWord(&$1, false);
|
||||||
|
$$ = false;
|
||||||
}
|
}
|
||||||
| reloc_16bit_no_str { out_RelWord(&$1); }
|
|
||||||
| string {
|
| string {
|
||||||
uint8_t *output = malloc(strlen($1)); /* Cannot be larger than that */
|
uint8_t *output = malloc(strlen($1)); /* Cannot be larger than that */
|
||||||
int32_t length = charmap_Convert($1, output);
|
int32_t length = charmap_Convert($1, output);
|
||||||
|
|
||||||
out_AbsWordGroup(output, length);
|
out_AbsWordGroup(output, length);
|
||||||
free(output);
|
free(output);
|
||||||
|
$$ = false;
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
constlist_32bit : constlist_32bit_entry
|
constlist_32bit : constlist_32bit_entry
|
||||||
| constlist_32bit T_COMMA constlist_32bit_entry
|
| constlist_32bit T_COMMA constlist_32bit_entry {
|
||||||
|
$$ = $1 || $3;
|
||||||
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
constlist_32bit_entry : %empty {
|
constlist_32bit_entry : %empty {
|
||||||
out_Skip(4, false);
|
out_Skip(4, false);
|
||||||
nListCountEmpty++;
|
$$ = true;
|
||||||
|
}
|
||||||
|
| relocexpr_no_str {
|
||||||
|
out_RelLong(&$1, false);
|
||||||
|
$$ = false;
|
||||||
}
|
}
|
||||||
| relocexpr_no_str { out_RelLong(&$1); }
|
|
||||||
| string {
|
| string {
|
||||||
uint8_t *output = malloc(strlen($1)); /* Cannot be larger than that */
|
uint8_t *output = malloc(strlen($1)); /* Cannot be larger than that */
|
||||||
int32_t length = charmap_Convert($1, output);
|
int32_t length = charmap_Convert($1, output);
|
||||||
|
|
||||||
out_AbsLongGroup(output, length);
|
out_AbsLongGroup(output, length);
|
||||||
free(output);
|
free(output);
|
||||||
|
$$ = false;
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
@@ -1500,31 +1519,31 @@ sectattrs : %empty {
|
|||||||
;
|
;
|
||||||
|
|
||||||
|
|
||||||
cpu_command : { nPCOffset = 1; } z80_adc
|
cpu_command : z80_adc
|
||||||
| { nPCOffset = 1; } z80_add
|
| z80_add
|
||||||
| { nPCOffset = 1; } z80_and
|
| z80_and
|
||||||
| { nPCOffset = 1; } z80_bit
|
| z80_bit
|
||||||
| { nPCOffset = 1; } z80_call
|
| z80_call
|
||||||
| z80_ccf
|
| z80_ccf
|
||||||
| { nPCOffset = 1; } z80_cp
|
| z80_cp
|
||||||
| z80_cpl
|
| z80_cpl
|
||||||
| z80_daa
|
| z80_daa
|
||||||
| { nPCOffset = 1; } z80_dec
|
| z80_dec
|
||||||
| z80_di
|
| z80_di
|
||||||
| z80_ei
|
| z80_ei
|
||||||
| z80_halt
|
| z80_halt
|
||||||
| z80_inc
|
| z80_inc
|
||||||
| { nPCOffset = 1; } z80_jp
|
| z80_jp
|
||||||
| { nPCOffset = 1; } z80_jr
|
| z80_jr
|
||||||
| { nPCOffset = 1; } z80_ld
|
| z80_ld
|
||||||
| z80_ldd
|
| z80_ldd
|
||||||
| z80_ldi
|
| z80_ldi
|
||||||
| { nPCOffset = 1; } z80_ldio
|
| z80_ldio
|
||||||
| z80_nop
|
| z80_nop
|
||||||
| { nPCOffset = 1; } z80_or
|
| z80_or
|
||||||
| z80_pop
|
| z80_pop
|
||||||
| z80_push
|
| z80_push
|
||||||
| { nPCOffset = 1; } z80_res
|
| z80_res
|
||||||
| z80_ret
|
| z80_ret
|
||||||
| z80_reti
|
| z80_reti
|
||||||
| z80_rl
|
| z80_rl
|
||||||
@@ -1536,41 +1555,41 @@ cpu_command : { nPCOffset = 1; } z80_adc
|
|||||||
| z80_rrc
|
| z80_rrc
|
||||||
| z80_rrca
|
| z80_rrca
|
||||||
| /*{ nPCOffset = 0; }*/ z80_rst
|
| /*{ nPCOffset = 0; }*/ z80_rst
|
||||||
| { nPCOffset = 1; } z80_sbc
|
| z80_sbc
|
||||||
| z80_scf
|
| z80_scf
|
||||||
| { nPCOffset = 1; } z80_set
|
| z80_set
|
||||||
| z80_sla
|
| z80_sla
|
||||||
| z80_sra
|
| z80_sra
|
||||||
| z80_srl
|
| z80_srl
|
||||||
| { nPCOffset = 1; } z80_stop
|
| z80_stop
|
||||||
| { nPCOffset = 1; } z80_sub
|
| z80_sub
|
||||||
| z80_swap
|
| z80_swap
|
||||||
| { nPCOffset = 1; } z80_xor
|
| z80_xor
|
||||||
;
|
;
|
||||||
|
|
||||||
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);
|
out_RelByte(&$2, true);
|
||||||
}
|
}
|
||||||
| 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);
|
out_RelByte(&$2, true);
|
||||||
}
|
}
|
||||||
| 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);
|
out_RelByte(&$4, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
;
|
;
|
||||||
|
|
||||||
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);
|
out_RelByte(&$2, true);
|
||||||
}
|
}
|
||||||
| T_Z80_AND op_a_r { out_AbsByte(0xA0 | $2); }
|
| T_Z80_AND op_a_r { out_AbsByte(0xA0 | $2); }
|
||||||
;
|
;
|
||||||
@@ -1583,11 +1602,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);
|
out_RelWord(&$2, true);
|
||||||
}
|
}
|
||||||
| 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);
|
out_RelWord(&$4, true);
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
@@ -1596,7 +1615,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);
|
out_RelByte(&$2, true);
|
||||||
}
|
}
|
||||||
| T_Z80_CP op_a_r { out_AbsByte(0xB8 | $2); }
|
| T_Z80_CP op_a_r { out_AbsByte(0xB8 | $2); }
|
||||||
;
|
;
|
||||||
@@ -1630,11 +1649,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);
|
out_RelWord(&$2, true);
|
||||||
}
|
}
|
||||||
| 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);
|
out_RelWord(&$4, true);
|
||||||
}
|
}
|
||||||
| T_Z80_JP T_MODE_HL {
|
| T_Z80_JP T_MODE_HL {
|
||||||
out_AbsByte(0xE9);
|
out_AbsByte(0xE9);
|
||||||
@@ -1643,11 +1662,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);
|
out_PCRelByte(&$2, true);
|
||||||
}
|
}
|
||||||
| 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);
|
out_PCRelByte(&$4, true);
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
@@ -1671,13 +1690,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);
|
out_RelByte(&$4, true);
|
||||||
}
|
}
|
||||||
| 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);
|
out_RelByte(&$2, true);
|
||||||
}
|
}
|
||||||
| 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);
|
||||||
@@ -1703,24 +1722,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);
|
out_RelByte(&$5, true);
|
||||||
}
|
}
|
||||||
| 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);
|
out_RelWord(&$4, true);
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
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);
|
out_RelWord(&$4, true);
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
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);
|
out_RelWord(&$2, true);
|
||||||
}
|
}
|
||||||
| 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)
|
||||||
@@ -1730,7 +1749,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);
|
out_RelWord(&$2, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
@@ -1747,7 +1766,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);
|
out_RelByte(&$4, true);
|
||||||
}
|
}
|
||||||
| 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))
|
||||||
@@ -1778,7 +1797,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);
|
out_RelWord(&$4, true);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
error("Destination operand must be A\n");
|
error("Destination operand must be A\n");
|
||||||
@@ -1789,11 +1808,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);
|
out_RelWord(&$4, true);
|
||||||
}
|
}
|
||||||
| 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);
|
out_RelWord(&$4, true);
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
* HL is taken care of in z80_ld_hl
|
* HL is taken care of in z80_ld_hl
|
||||||
@@ -1806,7 +1825,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);
|
out_RelByte(&$2, true);
|
||||||
}
|
}
|
||||||
| T_Z80_OR op_a_r { out_AbsByte(0xB0 | $2); }
|
| T_Z80_OR op_a_r { out_AbsByte(0xB0 | $2); }
|
||||||
;
|
;
|
||||||
@@ -1870,7 +1889,10 @@ 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))
|
||||||
out_RelByte(&$2);
|
// This could be considered as an "operand", but the purpose of the
|
||||||
|
// "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);
|
||||||
@@ -1879,7 +1901,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);
|
out_RelByte(&$2, true);
|
||||||
}
|
}
|
||||||
| T_Z80_SBC op_a_r { out_AbsByte(0x98 | $2); }
|
| T_Z80_SBC op_a_r { out_AbsByte(0x98 | $2); }
|
||||||
;
|
;
|
||||||
@@ -1917,13 +1939,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);
|
out_RelByte(&$2, true);
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
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);
|
out_RelByte(&$2, true);
|
||||||
}
|
}
|
||||||
| T_Z80_SUB op_a_r { out_AbsByte(0x90 | $2);
|
| T_Z80_SUB op_a_r { out_AbsByte(0x90 | $2);
|
||||||
}
|
}
|
||||||
@@ -1937,7 +1959,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);
|
out_RelByte(&$2, true);
|
||||||
}
|
}
|
||||||
| T_Z80_XOR op_a_r { out_AbsByte(0xA8 | $2); }
|
| T_Z80_XOR op_a_r { out_AbsByte(0xA8 | $2); }
|
||||||
;
|
;
|
||||||
|
|||||||
@@ -125,16 +125,6 @@ void rpn_Symbol(struct Expression *expr, char const *tzSym)
|
|||||||
uint8_t *ptr = reserveSpace(expr, nameLen + 1);
|
uint8_t *ptr = reserveSpace(expr, nameLen + 1);
|
||||||
*ptr++ = RPN_SYM;
|
*ptr++ = RPN_SYM;
|
||||||
memcpy(ptr, sym->name, nameLen);
|
memcpy(ptr, sym->name, nameLen);
|
||||||
|
|
||||||
/* RGBLINK assumes PC is at the byte being computed... */
|
|
||||||
if (sym_IsPC(sym) && nPCOffset) {
|
|
||||||
struct Expression pc = *expr, offset;
|
|
||||||
|
|
||||||
rpn_Number(&offset, nPCOffset);
|
|
||||||
rpn_BinaryOp(RPN_SUB, expr, &pc, &offset);
|
|
||||||
if (!rpn_isKnown(expr))
|
|
||||||
expr->isSymbol = true;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
rpn_Number(expr, sym_GetConstantValue(tzSym));
|
rpn_Number(expr, sym_GetConstantValue(tzSym));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -488,10 +488,9 @@ static inline void writelong(uint32_t b)
|
|||||||
writebyte(b >> 24);
|
writebyte(b >> 24);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void createPatch(enum PatchType type,
|
static inline void createPatch(enum PatchType type, struct Expression const *expr, bool isOperand)
|
||||||
struct Expression const *expr)
|
|
||||||
{
|
{
|
||||||
out_CreatePatch(type, expr, sect_GetOutputOffset());
|
out_CreatePatch(type, expr, sect_GetOutputOffset(), isOperand);
|
||||||
}
|
}
|
||||||
|
|
||||||
void sect_StartUnion(void)
|
void sect_StartUnion(void)
|
||||||
@@ -618,13 +617,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)
|
void out_RelByte(struct Expression *expr, bool isOperand)
|
||||||
{
|
{
|
||||||
checkcodesection();
|
checkcodesection();
|
||||||
reserveSpace(1);
|
reserveSpace(1);
|
||||||
|
|
||||||
if (!rpn_isKnown(expr)) {
|
if (!rpn_isKnown(expr)) {
|
||||||
createPatch(PATCHTYPE_BYTE, expr);
|
createPatch(PATCHTYPE_BYTE, expr, isOperand);
|
||||||
writebyte(0);
|
writebyte(0);
|
||||||
} else {
|
} else {
|
||||||
writebyte(expr->nVal);
|
writebyte(expr->nVal);
|
||||||
@@ -643,7 +642,7 @@ void out_RelBytes(struct Expression *expr, uint32_t n)
|
|||||||
|
|
||||||
while (n--) {
|
while (n--) {
|
||||||
if (!rpn_isKnown(expr)) {
|
if (!rpn_isKnown(expr)) {
|
||||||
createPatch(PATCHTYPE_BYTE, expr);
|
createPatch(PATCHTYPE_BYTE, expr, false);
|
||||||
writebyte(0);
|
writebyte(0);
|
||||||
} else {
|
} else {
|
||||||
writebyte(expr->nVal);
|
writebyte(expr->nVal);
|
||||||
@@ -656,13 +655,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)
|
void out_RelWord(struct Expression *expr, bool isOperand)
|
||||||
{
|
{
|
||||||
checkcodesection();
|
checkcodesection();
|
||||||
reserveSpace(2);
|
reserveSpace(2);
|
||||||
|
|
||||||
if (!rpn_isKnown(expr)) {
|
if (!rpn_isKnown(expr)) {
|
||||||
createPatch(PATCHTYPE_WORD, expr);
|
createPatch(PATCHTYPE_WORD, expr, isOperand);
|
||||||
writeword(0);
|
writeword(0);
|
||||||
} else {
|
} else {
|
||||||
writeword(expr->nVal);
|
writeword(expr->nVal);
|
||||||
@@ -674,13 +673,13 @@ void out_RelWord(struct Expression *expr)
|
|||||||
* 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)
|
void out_RelLong(struct Expression *expr, bool isOperand)
|
||||||
{
|
{
|
||||||
checkcodesection();
|
checkcodesection();
|
||||||
reserveSpace(2);
|
reserveSpace(2);
|
||||||
|
|
||||||
if (!rpn_isKnown(expr)) {
|
if (!rpn_isKnown(expr)) {
|
||||||
createPatch(PATCHTYPE_LONG, expr);
|
createPatch(PATCHTYPE_LONG, expr, isOperand);
|
||||||
writelong(0);
|
writelong(0);
|
||||||
} else {
|
} else {
|
||||||
writelong(expr->nVal);
|
writelong(expr->nVal);
|
||||||
@@ -692,14 +691,14 @@ void out_RelLong(struct Expression *expr)
|
|||||||
* 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)
|
void out_PCRelByte(struct Expression *expr, bool isOperand)
|
||||||
{
|
{
|
||||||
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);
|
createPatch(PATCHTYPE_JR, expr, isOperand);
|
||||||
writebyte(0);
|
writebyte(0);
|
||||||
} else {
|
} else {
|
||||||
struct Symbol const *sym = rpn_SymbolOf(expr);
|
struct Symbol const *sym = rpn_SymbolOf(expr);
|
||||||
|
|||||||
@@ -260,11 +260,11 @@ static void readSymbol(FILE *file, struct Symbol *symbol,
|
|||||||
* @param fileName The filename to report in errors
|
* @param fileName The filename to report in errors
|
||||||
* @param i The number of the patch to report in errors
|
* @param i The number of the patch to report in errors
|
||||||
*/
|
*/
|
||||||
static void readPatch(FILE *file, struct Patch *patch, char const *fileName,
|
static void readPatch(FILE *file, struct Patch *patch, char const *fileName, char const *sectName,
|
||||||
char const *sectName, uint32_t i,
|
uint32_t i, struct Section *fileSections[], struct FileStackNode fileNodes[])
|
||||||
struct Section *fileSections[], struct FileStackNode fileNodes[])
|
|
||||||
{
|
{
|
||||||
uint32_t nodeID;
|
uint32_t nodeID;
|
||||||
|
uint8_t type;
|
||||||
|
|
||||||
tryReadlong(nodeID, file,
|
tryReadlong(nodeID, file,
|
||||||
"%s: Unable to read \"%s\"'s patch #%" PRIu32 "'s node ID: %s",
|
"%s: Unable to read \"%s\"'s patch #%" PRIu32 "'s node ID: %s",
|
||||||
@@ -279,14 +279,15 @@ static void readPatch(FILE *file, struct Patch *patch, char const *fileName,
|
|||||||
tryReadlong(patch->pcSectionID, file,
|
tryReadlong(patch->pcSectionID, file,
|
||||||
"%s: Unable to read \"%s\"'s patch #%" PRIu32 "'s PC offset: %s",
|
"%s: Unable to read \"%s\"'s patch #%" PRIu32 "'s PC offset: %s",
|
||||||
fileName, sectName, i);
|
fileName, sectName, i);
|
||||||
patch->pcSection = patch->pcSectionID == -1 ? NULL
|
patch->pcSection = patch->pcSectionID == -1 ? NULL : fileSections[patch->pcSectionID];
|
||||||
: fileSections[patch->pcSectionID];
|
|
||||||
tryReadlong(patch->pcOffset, file,
|
tryReadlong(patch->pcOffset, file,
|
||||||
"%s: Unable to read \"%s\"'s patch #%" PRIu32 "'s PC offset: %s",
|
"%s: Unable to read \"%s\"'s patch #%" PRIu32 "'s PC offset: %s",
|
||||||
fileName, sectName, i);
|
fileName, sectName, i);
|
||||||
tryGetc(patch->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->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,6 +421,10 @@ 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);
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
ERROR: block-comment-termination-error.asm(1):
|
ERROR: block-comment-termination-error.asm(1):
|
||||||
Unterminated block comment
|
Unterminated block comment
|
||||||
ERROR: block-comment-termination-error.asm(1):
|
ERROR: block-comment-termination-error.asm(1):
|
||||||
syntax error, unexpected newline
|
syntax error, unexpected end of file
|
||||||
error: Assembly aborted (2 errors)!
|
error: Assembly aborted (2 errors)!
|
||||||
|
|||||||
6
test/asm/macro-eof.asm
Normal file
6
test/asm/macro-eof.asm
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
; Macro invocations not followed by a newline may scan an EOF;
|
||||||
|
; If this is the case, it shouldn't cause the parse to end before the macro is expanded
|
||||||
|
mac: macro
|
||||||
|
PRINTLN "Hi beautiful"
|
||||||
|
endm
|
||||||
|
mac
|
||||||
0
test/asm/macro-eof.err
Normal file
0
test/asm/macro-eof.err
Normal file
1
test/asm/macro-eof.out
Normal file
1
test/asm/macro-eof.out
Normal file
@@ -0,0 +1 @@
|
|||||||
|
Hi beautiful
|
||||||
Binary file not shown.
@@ -3,11 +3,13 @@ SECTION "fixed", ROM0[0]
|
|||||||
rst @ ; rst 0
|
rst @ ; rst 0
|
||||||
ld de, @ ; ld de, 1
|
ld de, @ ; ld de, 1
|
||||||
bit @, h ; bit 4, h
|
bit @, h ; bit 4, h
|
||||||
db @, @ ; db 6, 7
|
jr @ ; jr 6
|
||||||
|
|
||||||
SECTION "floating", ROM0
|
SECTION "floating", ROM0
|
||||||
|
|
||||||
rst @ ; rst 8
|
rst @ ; rst 8
|
||||||
ld l, @ ; ld l, 9
|
ld l, @ ; ld l, 9
|
||||||
dw @, @ ; dw 11, 13
|
db @, @ ; db 11, 12
|
||||||
dl @, @ ; dl 15, 19
|
dw @, @ ; dw 13, 15
|
||||||
|
dl @, @ ; dl 17, 21
|
||||||
|
jr @ ; jr 25
|
||||||
|
|||||||
Binary file not shown.
Reference in New Issue
Block a user