mirror of
https://github.com/gbdev/rgbds.git
synced 2025-11-23 19:42:08 +00:00
Allow the bit/res/set bit index to be determined at link time (#1654)
This increments the object file revision number from 11 to 12 since it adds a new `RPN_BIT_INDEX` command.
This commit is contained in:
@@ -325,6 +325,7 @@
|
||||
// `relocexpr_no_str` exists because strings usually count as numeric expressions, but some
|
||||
// contexts treat numbers and strings differently, e.g. `db "string"` or `print "string"`.
|
||||
%type <Expression> relocexpr_no_str
|
||||
%type <Expression> reloc_3bit
|
||||
%type <Expression> reloc_8bit
|
||||
%type <Expression> reloc_8bit_offset
|
||||
%type <Expression> reloc_16bit
|
||||
@@ -333,7 +334,6 @@
|
||||
%type <int32_t> iconst
|
||||
%type <int32_t> uconst
|
||||
// Constant numbers used only in specific contexts
|
||||
%type <int32_t> bit_const
|
||||
%type <int32_t> precision_arg
|
||||
%type <int32_t> rs_uconst
|
||||
%type <int32_t> sect_org
|
||||
@@ -1214,13 +1214,10 @@ print_expr:
|
||||
}
|
||||
;
|
||||
|
||||
bit_const:
|
||||
iconst {
|
||||
$$ = $1;
|
||||
if ($$ < 0 || $$ > 7) {
|
||||
::error("Bit number must be between 0 and 7, not %" PRId32 "\n", $$);
|
||||
$$ = 0;
|
||||
}
|
||||
reloc_3bit:
|
||||
relocexpr {
|
||||
$$ = std::move($1);
|
||||
$$.checkNBit(3);
|
||||
}
|
||||
;
|
||||
|
||||
@@ -1789,9 +1786,15 @@ sm83_and:
|
||||
;
|
||||
|
||||
sm83_bit:
|
||||
SM83_BIT bit_const COMMA reg_r {
|
||||
SM83_BIT reloc_3bit COMMA reg_r {
|
||||
uint8_t mask = static_cast<uint8_t>(0x40 | $4);
|
||||
$2.makeCheckBitIndex(mask);
|
||||
sect_ConstByte(0xCB);
|
||||
sect_ConstByte(0x40 | ($2 << 3) | $4);
|
||||
if (!$2.isKnown()) {
|
||||
sect_RelByte($2, 0);
|
||||
} else {
|
||||
sect_ConstByte(mask | ($2.value() << 3));
|
||||
}
|
||||
}
|
||||
;
|
||||
|
||||
@@ -2103,9 +2106,15 @@ sm83_push:
|
||||
;
|
||||
|
||||
sm83_res:
|
||||
SM83_RES bit_const COMMA reg_r {
|
||||
SM83_RES reloc_3bit COMMA reg_r {
|
||||
uint8_t mask = static_cast<uint8_t>(0x80 | $4);
|
||||
$2.makeCheckBitIndex(mask);
|
||||
sect_ConstByte(0xCB);
|
||||
sect_ConstByte(0x80 | ($2 << 3) | $4);
|
||||
if (!$2.isKnown()) {
|
||||
sect_RelByte($2, 0);
|
||||
} else {
|
||||
sect_ConstByte(mask | ($2.value() << 3));
|
||||
}
|
||||
}
|
||||
;
|
||||
|
||||
@@ -2204,9 +2213,15 @@ sm83_scf:
|
||||
;
|
||||
|
||||
sm83_set:
|
||||
SM83_SET bit_const COMMA reg_r {
|
||||
SM83_SET reloc_3bit COMMA reg_r {
|
||||
uint8_t mask = static_cast<uint8_t>(0xC0 | $4);
|
||||
$2.makeCheckBitIndex(mask);
|
||||
sect_ConstByte(0xCB);
|
||||
sect_ConstByte(0xC0 | ($2 << 3) | $4);
|
||||
if (!$2.isKnown()) {
|
||||
sect_RelByte($2, 0);
|
||||
} else {
|
||||
sect_ConstByte(mask | ($2.value() << 3));
|
||||
}
|
||||
}
|
||||
;
|
||||
|
||||
|
||||
@@ -355,6 +355,7 @@ void Expression::makeUnaryOp(RPNCommand op, Expression &&src) {
|
||||
case RPN_STARTOF_SECTTYPE:
|
||||
case RPN_HRAM:
|
||||
case RPN_RST:
|
||||
case RPN_BIT_INDEX:
|
||||
case RPN_CONST:
|
||||
case RPN_SYM:
|
||||
fatalerror("%d is not an unary operator\n", op);
|
||||
@@ -514,6 +515,7 @@ void Expression::makeBinaryOp(RPNCommand op, Expression &&src1, Expression const
|
||||
case RPN_STARTOF_SECTTYPE:
|
||||
case RPN_HRAM:
|
||||
case RPN_RST:
|
||||
case RPN_BIT_INDEX:
|
||||
case RPN_HIGH:
|
||||
case RPN_LOW:
|
||||
case RPN_BITWIDTH:
|
||||
@@ -608,6 +610,20 @@ void Expression::makeCheckRST() {
|
||||
}
|
||||
}
|
||||
|
||||
void Expression::makeCheckBitIndex(uint8_t mask) {
|
||||
assume((mask & 0xC0) != 0x00); // The high two bits must correspond to BIT, RES, or SET
|
||||
|
||||
if (!isKnown()) {
|
||||
uint8_t *ptr = reserveSpace(2);
|
||||
*ptr++ = RPN_BIT_INDEX;
|
||||
*ptr = mask;
|
||||
} else if (int32_t val = value(); val & ~0x07) {
|
||||
// A valid bit index must be masked with 0x07
|
||||
static char const *instructions[4] = {"instruction", "BIT", "RES", "SET"};
|
||||
error("Invalid bit index %" PRId32 " for %s\n", val, instructions[mask >> 6]);
|
||||
}
|
||||
}
|
||||
|
||||
// Checks that an RPN expression's value fits within N bits (signed or unsigned)
|
||||
void Expression::checkNBit(uint8_t n) const {
|
||||
if (isKnown()) {
|
||||
|
||||
Reference in New Issue
Block a user