mirror of
https://github.com/gbdev/rgbds.git
synced 2025-11-20 10:12:06 +00:00
Add unsigned right shift operator
This commit is contained in:
@@ -14,7 +14,7 @@
|
||||
|
||||
#define RGBDS_OBJECT_VERSION_STRING "RGB%1u"
|
||||
#define RGBDS_OBJECT_VERSION_NUMBER 9U
|
||||
#define RGBDS_OBJECT_REV 8U
|
||||
#define RGBDS_OBJECT_REV 9U
|
||||
|
||||
enum AssertionType {
|
||||
ASSERT_WARN,
|
||||
@@ -49,6 +49,7 @@ enum RPNCommand {
|
||||
|
||||
RPN_SHL = 0x40,
|
||||
RPN_SHR = 0x41,
|
||||
RPN_USHR = 0x42,
|
||||
|
||||
RPN_BANK_SYM = 0x50,
|
||||
RPN_BANK_SECT = 0x51,
|
||||
|
||||
@@ -16,5 +16,6 @@ int32_t op_modulo(int32_t dividend, int32_t divisor);
|
||||
int32_t op_exponent(int32_t base, uint32_t power);
|
||||
int32_t op_shift_left(int32_t value, int32_t amount);
|
||||
int32_t op_shift_right(int32_t value, int32_t amount);
|
||||
int32_t op_shift_right_unsigned(int32_t value, int32_t amount);
|
||||
|
||||
#endif /* RGBDS_OP_MATH_H */
|
||||
|
||||
@@ -1890,18 +1890,23 @@ static int yylex_NORMAL(void)
|
||||
return T_OP_LOGICLT;
|
||||
}
|
||||
|
||||
case '>': /* Either >>=, GT, GTE, or right shift */
|
||||
case '>': /* Either >>=, GT, GTE, or either kind of right shift */
|
||||
switch (peek()) {
|
||||
case '=':
|
||||
shiftChar();
|
||||
return T_OP_LOGICGE;
|
||||
case '>':
|
||||
shiftChar();
|
||||
if (peek() == '=') {
|
||||
switch (peek()) {
|
||||
case '=':
|
||||
shiftChar();
|
||||
return T_POP_SHREQ;
|
||||
case '>':
|
||||
shiftChar();
|
||||
return T_OP_USHR;
|
||||
default:
|
||||
return T_OP_SHR;
|
||||
}
|
||||
return T_OP_SHR;
|
||||
default:
|
||||
return T_OP_LOGICGT;
|
||||
}
|
||||
|
||||
@@ -534,7 +534,7 @@ enum {
|
||||
%token T_OP_LOGICNE "!=" T_OP_LOGICEQU "=="
|
||||
%token T_OP_ADD "+" T_OP_SUB "-"
|
||||
%token T_OP_OR "|" T_OP_XOR "^" T_OP_AND "&"
|
||||
%token T_OP_SHL "<<" T_OP_SHR ">>"
|
||||
%token T_OP_SHL "<<" T_OP_SHR ">>" T_OP_USHR ">>>"
|
||||
%token T_OP_MUL "*" T_OP_DIV "/" T_OP_MOD "%"
|
||||
%token T_OP_NOT "~"
|
||||
%left T_OP_LOGICOR
|
||||
@@ -542,7 +542,7 @@ enum {
|
||||
%left T_OP_LOGICGT T_OP_LOGICLT T_OP_LOGICGE T_OP_LOGICLE T_OP_LOGICNE T_OP_LOGICEQU
|
||||
%left T_OP_ADD T_OP_SUB
|
||||
%left T_OP_OR T_OP_XOR T_OP_AND
|
||||
%left T_OP_SHL T_OP_SHR
|
||||
%left T_OP_SHL T_OP_SHR T_OP_USHR
|
||||
%left T_OP_MUL T_OP_DIV T_OP_MOD
|
||||
|
||||
%precedence NEG /* negation -- unary minus */
|
||||
@@ -1477,6 +1477,9 @@ relocexpr_no_str : scoped_anon_id { rpn_Symbol(&$$, $1); }
|
||||
| relocexpr T_OP_SHR relocexpr {
|
||||
rpn_BinaryOp(RPN_SHR, &$$, &$1, &$3);
|
||||
}
|
||||
| relocexpr T_OP_USHR relocexpr {
|
||||
rpn_BinaryOp(RPN_USHR, &$$, &$1, &$3);
|
||||
}
|
||||
| relocexpr T_OP_MUL relocexpr {
|
||||
rpn_BinaryOp(RPN_MUL, &$$, &$1, &$3);
|
||||
}
|
||||
|
||||
@@ -251,7 +251,9 @@ A great number of operators you can use in expressions are available (listed fro
|
||||
.It Li ** Ta Exponent
|
||||
.It Li ~ + - Ta Unary complement/plus/minus
|
||||
.It Li * / % Ta Multiply/divide/modulo
|
||||
.It Li << >> Ta Shift left/right
|
||||
.It Li << Ta Shift left
|
||||
.It Li >> Ta Signed shift right (sign-extension)
|
||||
.It Li >>> Ta Unsigned shift right (zero-extension)
|
||||
.It Li & \&| ^ Ta Binary and/or/xor
|
||||
.It Li + - Ta Add/subtract
|
||||
.It Li != == <= >= < > Ta Comparison
|
||||
|
||||
@@ -421,6 +421,19 @@ void rpn_BinaryOp(enum RPNCommand op, struct Expression *expr,
|
||||
|
||||
expr->val = op_shift_right(src1->val, src2->val);
|
||||
break;
|
||||
case RPN_USHR:
|
||||
if (src2->val < 0)
|
||||
warning(WARNING_SHIFT_AMOUNT,
|
||||
"Shifting right by negative amount %" PRId32 "\n",
|
||||
src2->val);
|
||||
|
||||
if (src2->val >= 32)
|
||||
warning(WARNING_SHIFT_AMOUNT,
|
||||
"Shifting right by large amount %" PRId32 "\n",
|
||||
src2->val);
|
||||
|
||||
expr->val = op_shift_right_unsigned(src1->val, src2->val);
|
||||
break;
|
||||
case RPN_MUL:
|
||||
expr->val = uleft * uright;
|
||||
break;
|
||||
|
||||
@@ -265,6 +265,10 @@ static int32_t computeRPNExpr(struct Patch const *patch,
|
||||
value = popRPN();
|
||||
value = op_shift_right(popRPN(), value);
|
||||
break;
|
||||
case RPN_USHR:
|
||||
value = popRPN();
|
||||
value = op_shift_right_unsigned(popRPN(), value);
|
||||
break;
|
||||
|
||||
case RPN_BANK_SYM:
|
||||
value = 0;
|
||||
|
||||
15
src/opmath.c
15
src/opmath.c
@@ -86,3 +86,18 @@ int32_t op_shift_right(int32_t value, int32_t amount)
|
||||
// undefined, so use a left shift manually sign-extended
|
||||
return ((uint32_t)value >> amount) | amount_high_bits;
|
||||
}
|
||||
|
||||
int32_t op_shift_right_unsigned(int32_t value, int32_t amount)
|
||||
{
|
||||
// Repeat the easy cases here to avoid INT_MIN funny business
|
||||
if (amount == 0)
|
||||
return value;
|
||||
if (value == 0 || amount <= -32)
|
||||
return 0;
|
||||
if (amount > 31)
|
||||
return (value < 0) ? -1 : 0;
|
||||
if (amount < 0)
|
||||
return op_shift_left(value, -amount);
|
||||
|
||||
return (uint32_t)value >> amount;
|
||||
}
|
||||
|
||||
@@ -241,6 +241,7 @@ with some bytes being special prefixes for integers and symbols.
|
||||
.It Li $35 Ta Li <= comparison
|
||||
.It Li $40 Ta Li << operator
|
||||
.It Li $41 Ta Li >> operator
|
||||
.It Li $42 Ta Li >>> operator
|
||||
.It Li $50 Ta Li BANK(symbol) ,
|
||||
a
|
||||
.Ar LONG
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
macro test
|
||||
; Test the rpn system, as well as the linker...
|
||||
DEF expr EQUS STRRPL(STRRPL("\1 + zero)", "<<", "<< ("), ">>", ">> (")
|
||||
DEF expr EQUS STRRPL(STRRPL("\1 + zero)", "<< ", "<< ("), ">> ", ">> (")
|
||||
dl expr
|
||||
PURGE expr
|
||||
|
||||
@@ -24,5 +24,8 @@ section "test", ROM0[0]
|
||||
test -4 >> 2
|
||||
test -1 >> -9001
|
||||
|
||||
test $DEADBEEF >> 1
|
||||
test $DEADBEEF >>> 1
|
||||
|
||||
SECTION "Zero", ROM0[0]
|
||||
zero:
|
||||
|
||||
@@ -24,3 +24,5 @@ warning: shift.asm(25) -> shift.asm::test(8): [-Wshift]
|
||||
Shifting right negative value -1
|
||||
warning: shift.asm(25) -> shift.asm::test(8): [-Wshift-amount]
|
||||
Shifting right by negative amount -9001
|
||||
warning: shift.asm(27) -> shift.asm::test(8): [-Wshift]
|
||||
Shifting right negative value -559038737
|
||||
|
||||
@@ -10,3 +10,5 @@
|
||||
-4 >> 1 = $FFFFFFFE
|
||||
-4 >> 2 = $FFFFFFFF
|
||||
-1 >> -9001 = $0
|
||||
$DEADBEEF >> 1 = $EF56DF77
|
||||
$DEADBEEF >>> 1 = $6F56DF77
|
||||
|
||||
Binary file not shown.
Reference in New Issue
Block a user