mirror of
https://github.com/gbdev/rgbds.git
synced 2025-11-21 18:52:07 +00:00
Add unsigned right shift operator
This commit is contained in:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user