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_STRING "RGB%1u"
#define RGBDS_OBJECT_VERSION_NUMBER 9U #define RGBDS_OBJECT_VERSION_NUMBER 9U
#define RGBDS_OBJECT_REV 8U #define RGBDS_OBJECT_REV 9U
enum AssertionType { enum AssertionType {
ASSERT_WARN, ASSERT_WARN,
@@ -49,6 +49,7 @@ enum RPNCommand {
RPN_SHL = 0x40, RPN_SHL = 0x40,
RPN_SHR = 0x41, RPN_SHR = 0x41,
RPN_USHR = 0x42,
RPN_BANK_SYM = 0x50, RPN_BANK_SYM = 0x50,
RPN_BANK_SECT = 0x51, 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_exponent(int32_t base, uint32_t power);
int32_t op_shift_left(int32_t value, int32_t amount); 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(int32_t value, int32_t amount);
int32_t op_shift_right_unsigned(int32_t value, int32_t amount);
#endif /* RGBDS_OP_MATH_H */ #endif /* RGBDS_OP_MATH_H */

View File

@@ -1890,18 +1890,23 @@ static int yylex_NORMAL(void)
return T_OP_LOGICLT; return T_OP_LOGICLT;
} }
case '>': /* Either >>=, GT, GTE, or right shift */ case '>': /* Either >>=, GT, GTE, or either kind of right shift */
switch (peek()) { switch (peek()) {
case '=': case '=':
shiftChar(); shiftChar();
return T_OP_LOGICGE; return T_OP_LOGICGE;
case '>': case '>':
shiftChar(); shiftChar();
if (peek() == '=') { switch (peek()) {
case '=':
shiftChar(); shiftChar();
return T_POP_SHREQ; return T_POP_SHREQ;
} case '>':
shiftChar();
return T_OP_USHR;
default:
return T_OP_SHR; return T_OP_SHR;
}
default: default:
return T_OP_LOGICGT; return T_OP_LOGICGT;
} }

View File

@@ -534,7 +534,7 @@ enum {
%token T_OP_LOGICNE "!=" T_OP_LOGICEQU "==" %token T_OP_LOGICNE "!=" T_OP_LOGICEQU "=="
%token T_OP_ADD "+" T_OP_SUB "-" %token T_OP_ADD "+" T_OP_SUB "-"
%token T_OP_OR "|" T_OP_XOR "^" T_OP_AND "&" %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_MUL "*" T_OP_DIV "/" T_OP_MOD "%"
%token T_OP_NOT "~" %token T_OP_NOT "~"
%left T_OP_LOGICOR %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_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_ADD T_OP_SUB
%left T_OP_OR T_OP_XOR T_OP_AND %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 %left T_OP_MUL T_OP_DIV T_OP_MOD
%precedence NEG /* negation -- unary minus */ %precedence NEG /* negation -- unary minus */
@@ -1477,6 +1477,9 @@ relocexpr_no_str : scoped_anon_id { rpn_Symbol(&$$, $1); }
| relocexpr T_OP_SHR relocexpr { | relocexpr T_OP_SHR relocexpr {
rpn_BinaryOp(RPN_SHR, &$$, &$1, &$3); rpn_BinaryOp(RPN_SHR, &$$, &$1, &$3);
} }
| relocexpr T_OP_USHR relocexpr {
rpn_BinaryOp(RPN_USHR, &$$, &$1, &$3);
}
| relocexpr T_OP_MUL relocexpr { | relocexpr T_OP_MUL relocexpr {
rpn_BinaryOp(RPN_MUL, &$$, &$1, &$3); 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 Exponent
.It Li ~ + - Ta Unary complement/plus/minus .It Li ~ + - Ta Unary complement/plus/minus
.It Li * / % Ta Multiply/divide/modulo .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 Binary and/or/xor
.It Li + - Ta Add/subtract .It Li + - Ta Add/subtract
.It Li != == <= >= < > Ta Comparison .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); expr->val = op_shift_right(src1->val, src2->val);
break; 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: case RPN_MUL:
expr->val = uleft * uright; expr->val = uleft * uright;
break; break;

View File

@@ -265,6 +265,10 @@ static int32_t computeRPNExpr(struct Patch const *patch,
value = popRPN(); value = popRPN();
value = op_shift_right(popRPN(), value); value = op_shift_right(popRPN(), value);
break; break;
case RPN_USHR:
value = popRPN();
value = op_shift_right_unsigned(popRPN(), value);
break;
case RPN_BANK_SYM: case RPN_BANK_SYM:
value = 0; 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 // undefined, so use a left shift manually sign-extended
return ((uint32_t)value >> amount) | amount_high_bits; 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 $35 Ta Li <= comparison
.It Li $40 Ta Li << operator .It Li $40 Ta Li << operator
.It Li $41 Ta Li >> operator .It Li $41 Ta Li >> operator
.It Li $42 Ta Li >>> operator
.It Li $50 Ta Li BANK(symbol) , .It Li $50 Ta Li BANK(symbol) ,
a a
.Ar LONG .Ar LONG

View File

@@ -1,6 +1,6 @@
macro test macro test
; Test the rpn system, as well as the linker... ; 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 dl expr
PURGE expr PURGE expr
@@ -24,5 +24,8 @@ section "test", ROM0[0]
test -4 >> 2 test -4 >> 2
test -1 >> -9001 test -1 >> -9001
test $DEADBEEF >> 1
test $DEADBEEF >>> 1
SECTION "Zero", ROM0[0] SECTION "Zero", ROM0[0]
zero: zero:

View File

@@ -24,3 +24,5 @@ warning: shift.asm(25) -> shift.asm::test(8): [-Wshift]
Shifting right negative value -1 Shifting right negative value -1
warning: shift.asm(25) -> shift.asm::test(8): [-Wshift-amount] warning: shift.asm(25) -> shift.asm::test(8): [-Wshift-amount]
Shifting right by negative amount -9001 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 >> 1 = $FFFFFFFE
-4 >> 2 = $FFFFFFFF -4 >> 2 = $FFFFFFFF
-1 >> -9001 = $0 -1 >> -9001 = $0
$DEADBEEF >> 1 = $EF56DF77
$DEADBEEF >>> 1 = $6F56DF77

Binary file not shown.