Add unsigned right shift operator

This commit is contained in:
ISSOtm
2022-02-05 11:27:41 +01:00
committed by Eldred Habert
parent cf19879281
commit eb5af70d79
13 changed files with 60 additions and 8 deletions

View File

@@ -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,

View File

@@ -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 */

View File

@@ -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;
}

View File

@@ -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);
}

View File

@@ -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

View File

@@ -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;

View File

@@ -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;

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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:

View File

@@ -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

View File

@@ -10,3 +10,5 @@
-4 >> 1 = $FFFFFFFE
-4 >> 2 = $FFFFFFFF
-1 >> -9001 = $0
$DEADBEEF >> 1 = $EF56DF77
$DEADBEEF >>> 1 = $6F56DF77

Binary file not shown.