mirror of
https://github.com/gbdev/rgbds.git
synced 2025-11-20 18:22:07 +00:00
@@ -143,9 +143,16 @@ A great number of operators you can use in expressions are available (listed fro
|
|||||||
complements a value by inverting all its bits.
|
complements a value by inverting all its bits.
|
||||||
.Pp
|
.Pp
|
||||||
.Ic %
|
.Ic %
|
||||||
is used to get the remainder of the corresponding division.
|
is used to get the remainder of the corresponding division, so that
|
||||||
.Sq 5 % 2
|
.Sq a / b * b + a % b == a
|
||||||
is 1.
|
is always true.
|
||||||
|
The result has the same sign as the divisor.
|
||||||
|
This makes
|
||||||
|
.Sq a % b .
|
||||||
|
equal to
|
||||||
|
.Sq (a + b) % b
|
||||||
|
or
|
||||||
|
.Sq (a - b) % b .
|
||||||
.Pp
|
.Pp
|
||||||
Shifting works by shifting all bits in the left operand either left
|
Shifting works by shifting all bits in the left operand either left
|
||||||
.Pq Sq <<
|
.Pq Sq <<
|
||||||
@@ -168,7 +175,8 @@ still evaluates both operands of
|
|||||||
and
|
and
|
||||||
.Sq || .
|
.Sq || .
|
||||||
.Pp
|
.Pp
|
||||||
! returns 1 if the operand was 0, and 0 otherwise.
|
.Ic \&!
|
||||||
|
returns 1 if the operand was 0, and 0 otherwise.
|
||||||
.Ss Fixed‐point Expressions
|
.Ss Fixed‐point Expressions
|
||||||
Fixed-point numbers are basically normal (32-bit) integers, which count 65536th's instead of entire units, offering better precision than integers but limiting the range of values.
|
Fixed-point numbers are basically normal (32-bit) integers, which count 65536th's instead of entire units, offering better precision than integers but limiting the range of values.
|
||||||
The upper 16 bits are used for the integer part and the lower 16 bits are used for the fraction (65536ths).
|
The upper 16 bits are used for the integer part and the lower 16 bits are used for the fraction (65536ths).
|
||||||
|
|||||||
@@ -283,6 +283,22 @@ static int32_t shift(int32_t shiftee, int32_t amount)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int32_t divide(int32_t dividend, int32_t divisor)
|
||||||
|
{
|
||||||
|
// Adjust division to floor toward negative infinity,
|
||||||
|
// not truncate toward zero
|
||||||
|
return dividend / divisor - ((dividend % divisor < 0) != (divisor < 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
static int32_t modulo(int32_t dividend, int32_t divisor)
|
||||||
|
{
|
||||||
|
int32_t remainder = dividend % divisor;
|
||||||
|
|
||||||
|
// Adjust modulo to have the sign of the divisor,
|
||||||
|
// not the sign of the dividend
|
||||||
|
return remainder + divisor * ((remainder < 0) != (divisor < 0));
|
||||||
|
}
|
||||||
|
|
||||||
static int32_t exponent(int32_t base, uint32_t power)
|
static int32_t exponent(int32_t base, uint32_t power)
|
||||||
{
|
{
|
||||||
int32_t result = 1;
|
int32_t result = 1;
|
||||||
@@ -410,17 +426,17 @@ void rpn_BinaryOp(enum RPNCommand op, struct Expression *expr,
|
|||||||
PRId32 "\n", INT32_MIN, INT32_MIN);
|
PRId32 "\n", INT32_MIN, INT32_MIN);
|
||||||
expr->nVal = INT32_MIN;
|
expr->nVal = INT32_MIN;
|
||||||
} else {
|
} else {
|
||||||
expr->nVal = src1->nVal / src2->nVal;
|
expr->nVal = divide(src1->nVal, src2->nVal);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case RPN_MOD:
|
case RPN_MOD:
|
||||||
if (src2->nVal == 0)
|
if (src2->nVal == 0)
|
||||||
fatalerror("Division by zero\n");
|
fatalerror("Modulo by zero\n");
|
||||||
|
|
||||||
if (src1->nVal == INT32_MIN && src2->nVal == -1)
|
if (src1->nVal == INT32_MIN && src2->nVal == -1)
|
||||||
expr->nVal = 0;
|
expr->nVal = 0;
|
||||||
else
|
else
|
||||||
expr->nVal = src1->nVal % src2->nVal;
|
expr->nVal = modulo(src1->nVal, src2->nVal);
|
||||||
break;
|
break;
|
||||||
case RPN_EXP:
|
case RPN_EXP:
|
||||||
if (src2->nVal < 0)
|
if (src2->nVal < 0)
|
||||||
|
|||||||
@@ -21,6 +21,22 @@
|
|||||||
|
|
||||||
#include "extern/err.h"
|
#include "extern/err.h"
|
||||||
|
|
||||||
|
static int32_t divide(int32_t dividend, int32_t divisor)
|
||||||
|
{
|
||||||
|
// Adjust division to floor toward negative infinity,
|
||||||
|
// not truncate toward zero
|
||||||
|
return dividend / divisor - ((dividend % divisor < 0) != (divisor < 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
static int32_t modulo(int32_t dividend, int32_t divisor)
|
||||||
|
{
|
||||||
|
int32_t remainder = dividend % divisor;
|
||||||
|
|
||||||
|
// Adjust modulo to have the sign of the divisor,
|
||||||
|
// not the sign of the dividend
|
||||||
|
return remainder + divisor * ((remainder < 0) != (divisor < 0));
|
||||||
|
}
|
||||||
|
|
||||||
static int32_t exponent(int32_t base, uint32_t power)
|
static int32_t exponent(int32_t base, uint32_t power)
|
||||||
{
|
{
|
||||||
int32_t result = 1;
|
int32_t result = 1;
|
||||||
@@ -235,7 +251,7 @@ static int32_t computeRPNExpr(struct Patch const *patch,
|
|||||||
popRPN();
|
popRPN();
|
||||||
value = INT32_MAX;
|
value = INT32_MAX;
|
||||||
} else {
|
} else {
|
||||||
value = popRPN() / value;
|
value = divide(popRPN(), value);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case RPN_MOD:
|
case RPN_MOD:
|
||||||
@@ -247,7 +263,7 @@ static int32_t computeRPNExpr(struct Patch const *patch,
|
|||||||
popRPN();
|
popRPN();
|
||||||
value = 0;
|
value = 0;
|
||||||
} else {
|
} else {
|
||||||
value = popRPN() % value;
|
value = modulo(popRPN(), value);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case RPN_UNSUB:
|
case RPN_UNSUB:
|
||||||
|
|||||||
36
test/asm/div-mod.asm
Normal file
36
test/asm/div-mod.asm
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
_ASM equ 0
|
||||||
|
|
||||||
|
test: MACRO
|
||||||
|
; Test RGBASM
|
||||||
|
V equs "_ASM +"
|
||||||
|
static_assert \#
|
||||||
|
PURGE V
|
||||||
|
; Test RGBLINK
|
||||||
|
V equs "_LINK +"
|
||||||
|
assert \#
|
||||||
|
PURGE V
|
||||||
|
ENDM
|
||||||
|
|
||||||
|
for x, -300, 301
|
||||||
|
for y, -x - 1, x + 2
|
||||||
|
if y != 0
|
||||||
|
q = x / y
|
||||||
|
r = x % y
|
||||||
|
test (V (q * y + r)) == (V x)
|
||||||
|
test (V (x + y) % y) == (V r)
|
||||||
|
test (V (x - y) % y) == (V r)
|
||||||
|
endc
|
||||||
|
endr
|
||||||
|
endr
|
||||||
|
|
||||||
|
for x, -300, 301
|
||||||
|
for p, 31
|
||||||
|
y = 2 ** p
|
||||||
|
r = x % y
|
||||||
|
m = x & (y - 1)
|
||||||
|
test (V r) == (V m)
|
||||||
|
endr
|
||||||
|
endr
|
||||||
|
|
||||||
|
SECTION "LINK", ROM0
|
||||||
|
_LINK::
|
||||||
0
test/asm/div-mod.err
Normal file
0
test/asm/div-mod.err
Normal file
0
test/asm/div-mod.out
Normal file
0
test/asm/div-mod.out
Normal file
0
test/asm/div-mod.out.bin
Normal file
0
test/asm/div-mod.out.bin
Normal file
0
test/asm/math.out.bin
Normal file
0
test/asm/math.out.bin
Normal file
Reference in New Issue
Block a user