From 2eeb333be0842cc2ace832929f9ce859a413d4fd Mon Sep 17 00:00:00 2001 From: Rangi42 Date: Sat, 2 Aug 2025 19:35:26 -0400 Subject: [PATCH] Factor out more shared math operations between RGBASM and RGBLINK --- include/opmath.hpp | 9 +++++++++ src/asm/rpn.cpp | 29 ++++++++--------------------- src/link/patch.cpp | 16 +++++++--------- src/opmath.cpp | 23 +++++++++++++++++++++++ 4 files changed, 47 insertions(+), 30 deletions(-) diff --git a/include/opmath.hpp b/include/opmath.hpp index 2c1433ca..c4dac167 100644 --- a/include/opmath.hpp +++ b/include/opmath.hpp @@ -8,8 +8,17 @@ int32_t op_divide(int32_t dividend, int32_t divisor); 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); +int32_t op_neg(int32_t value); + +int32_t op_high(int32_t value); +int32_t op_low(int32_t value); + +int32_t op_bitwidth(int32_t value); +int32_t op_tzcount(int32_t value); + #endif // RGBDS_OP_MATH_HPP diff --git a/src/asm/rpn.cpp b/src/asm/rpn.cpp index 74a0f782..b2b60496 100644 --- a/src/asm/rpn.cpp +++ b/src/asm/rpn.cpp @@ -10,7 +10,7 @@ #include #include -#include "helpers.hpp" // assume, clz, ctz +#include "helpers.hpp" // assume #include "opmath.hpp" #include "asm/output.hpp" @@ -253,7 +253,7 @@ static int32_t tryConstLow(Expression const &expr) { assume(sect.org == UINT32_MAX); int32_t symbolOfs = sym->getValue() + 1; - return (symbolOfs + sect.alignOfs) & 0xFF; + return op_low(symbolOfs + sect.alignOfs); } // Returns a constant binary AND with one non-constant operand, or -1 if it cannot be computed. @@ -301,12 +301,9 @@ void Expression::makeUnaryOp(RPNCommand op, Expression &&src) { // First, check if the expression is known if (src.isKnown()) { // If the expressions is known, just compute the value - int32_t val = src.value(); - uint32_t uval = static_cast(val); - - switch (op) { + switch (int32_t val = src.value(); op) { case RPN_NEG: - data = static_cast(-uval); + data = op_neg(val); break; case RPN_NOT: data = ~val; @@ -315,16 +312,16 @@ void Expression::makeUnaryOp(RPNCommand op, Expression &&src) { data = !val; break; case RPN_HIGH: - data = static_cast(uval >> 8 & 0xFF); + data = op_high(val); break; case RPN_LOW: - data = val & 0xFF; + data = op_low(val); break; case RPN_BITWIDTH: - data = val != 0 ? 32 - clz(uval) : 0; + data = op_bitwidth(val); break; case RPN_TZCOUNT: - data = val != 0 ? ctz(uval) : 32; + data = op_tzcount(val); break; // LCOV_EXCL_START default: @@ -397,37 +394,30 @@ void Expression::makeBinaryOp(RPNCommand op, Expression &&src1, Expression const if (rval < 0) { warning(WARNING_SHIFT_AMOUNT, "Shifting left by negative amount %" PRId32, rval); } - if (rval >= 32) { warning(WARNING_SHIFT_AMOUNT, "Shifting left by large amount %" PRId32, rval); } - data = op_shift_left(lval, rval); break; case RPN_SHR: if (lval < 0) { warning(WARNING_SHIFT, "Shifting right negative value %" PRId32, lval); } - if (rval < 0) { warning(WARNING_SHIFT_AMOUNT, "Shifting right by negative amount %" PRId32, rval); } - if (rval >= 32) { warning(WARNING_SHIFT_AMOUNT, "Shifting right by large amount %" PRId32, rval); } - data = op_shift_right(lval, rval); break; case RPN_USHR: if (rval < 0) { warning(WARNING_SHIFT_AMOUNT, "Shifting right by negative amount %" PRId32, rval); } - if (rval >= 32) { warning(WARNING_SHIFT_AMOUNT, "Shifting right by large amount %" PRId32, rval); } - data = op_shift_right_unsigned(lval, rval); break; case RPN_MUL: @@ -437,7 +427,6 @@ void Expression::makeBinaryOp(RPNCommand op, Expression &&src1, Expression const if (rval == 0) { fatal("Division by zero"); } - if (lval == INT32_MIN && rval == -1) { warning( WARNING_DIV, @@ -454,7 +443,6 @@ void Expression::makeBinaryOp(RPNCommand op, Expression &&src1, Expression const if (rval == 0) { fatal("Modulo by zero"); } - if (lval == INT32_MIN && rval == -1) { data = 0; } else { @@ -465,7 +453,6 @@ void Expression::makeBinaryOp(RPNCommand op, Expression &&src1, Expression const if (rval < 0) { fatal("Exponentiation by negative power"); } - data = op_exponent(lval, rval); break; // LCOV_EXCL_START diff --git a/src/link/patch.cpp b/src/link/patch.cpp index 796633e4..23488156 100644 --- a/src/link/patch.cpp +++ b/src/link/patch.cpp @@ -7,7 +7,7 @@ #include #include -#include "helpers.hpp" // assume, clz, ctz +#include "helpers.hpp" // assume #include "linkdefs.hpp" #include "opmath.hpp" #include "verbosity.hpp" @@ -96,7 +96,6 @@ static int32_t computeRPNExpr(Patch const &patch, std::vector const &fil while (size > 0) { RPNCommand command = static_cast(getRPNByte(expression, size, patch)); - int32_t value; isError = false; @@ -104,6 +103,7 @@ static int32_t computeRPNExpr(Patch const &patch, std::vector const &fil // C++ does not guarantee order of evaluation of operands! // So, if there are two `popRPN` in the same expression, make // sure the operation is commutative. + int32_t value; switch (command) { case RPN_ADD: value = popRPN(patch) + popRPN(patch); @@ -145,7 +145,7 @@ static int32_t computeRPNExpr(Patch const &patch, std::vector const &fil } break; case RPN_NEG: - value = -popRPN(patch); + value = op_neg(popRPN(patch)); break; case RPN_EXP: value = popRPN(patch); @@ -159,19 +159,17 @@ static int32_t computeRPNExpr(Patch const &patch, std::vector const &fil break; case RPN_HIGH: - value = (popRPN(patch) >> 8) & 0xFF; + value = op_high(popRPN(patch)); break; case RPN_LOW: - value = popRPN(patch) & 0xFF; + value = op_low(popRPN(patch)); break; case RPN_BITWIDTH: - value = popRPN(patch); - value = value != 0 ? 32 - clz(static_cast(value)) : 0; + value = op_bitwidth(popRPN(patch)); break; case RPN_TZCOUNT: - value = popRPN(patch); - value = value != 0 ? ctz(static_cast(value)) : 32; + value = op_tzcount(popRPN(patch)); break; case RPN_OR: diff --git a/src/opmath.cpp b/src/opmath.cpp index 061d17b2..bbc6e35c 100644 --- a/src/opmath.cpp +++ b/src/opmath.cpp @@ -6,6 +6,8 @@ #include +#include "helpers.hpp" // clz, ctz + int32_t op_divide(int32_t dividend, int32_t divisor) { // Adjust division to floor toward negative infinity, // not truncate toward zero @@ -96,3 +98,24 @@ int32_t op_shift_right_unsigned(int32_t value, int32_t amount) { return static_cast(value) >> amount; } + +int32_t op_neg(int32_t value) { + // Avoid negating signed INT_MIN + return static_cast(-static_cast(value)); +} + +int32_t op_high(int32_t value) { + return static_cast(static_cast(value) >> 8 & 0xFF); +} + +int32_t op_low(int32_t value) { + return value & 0xFF; +} + +int32_t op_bitwidth(int32_t value) { + return value != 0 ? 32 - clz(static_cast(value)) : 0; +} + +int32_t op_tzcount(int32_t value) { + return value != 0 ? ctz(static_cast(value)) : 32; +}