mirror of
https://github.com/gbdev/rgbds.git
synced 2025-11-20 18:22:07 +00:00
X && 0 and X & 0 are constant 0; X || 1 is constant 1 (#1399)
Fixes #977
This commit is contained in:
13
man/rgbasm.5
13
man/rgbasm.5
@@ -218,6 +218,9 @@ knows its value.
|
||||
This is generally always the case, unless a label is involved, as explained in the
|
||||
.Sx SYMBOLS
|
||||
section.
|
||||
However, some operators can be constant even with non-constant operands, as explained in
|
||||
.Sx Operators
|
||||
further below.
|
||||
.Pp
|
||||
The instructions in the macro-language generally require constant expressions.
|
||||
.Ss Numeric formats
|
||||
@@ -306,13 +309,21 @@ equivalent to multiplying and dividing by 2 to the power of b, respectively.
|
||||
.Pp
|
||||
Comparison operators return 0 if the comparison is false, and 1 otherwise.
|
||||
.Pp
|
||||
Unlike in a lot of languages, and for technical reasons,
|
||||
Unlike in many other languages, and for technical reasons,
|
||||
.Nm
|
||||
still evaluates both operands of
|
||||
.Sq &&
|
||||
and
|
||||
.Sq || .
|
||||
.Pp
|
||||
The operators
|
||||
.Sq &&
|
||||
and
|
||||
.Sq &
|
||||
with a zero constant as either operand will be constant 0, and
|
||||
.Sq ||
|
||||
with a non-zero constant as either operand will be constant 1, even if the other operand is non-constant.
|
||||
.Pp
|
||||
.Ic \&!
|
||||
returns 1 if the operand was 0, and 0 otherwise.
|
||||
.Ss Fixed-point expressions
|
||||
|
||||
@@ -197,6 +197,16 @@ void Expression::makeStartOfSectionType(SectionType type) {
|
||||
*ptr = type;
|
||||
}
|
||||
|
||||
static bool tryConstZero(Expression const &lhs, Expression const &rhs) {
|
||||
Expression const &expr = lhs.isKnown() ? lhs : rhs;
|
||||
return expr.isKnown() && expr.value() == 0;
|
||||
}
|
||||
|
||||
static bool tryConstNonzero(Expression const &lhs, Expression const &rhs) {
|
||||
Expression const &expr = lhs.isKnown() ? lhs : rhs;
|
||||
return expr.isKnown() && expr.value() != 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Attempts to compute a constant binary AND from non-constant operands
|
||||
* This is possible if one operand is a symbol belonging to an `ALIGN[N]` section, and the other is
|
||||
@@ -422,6 +432,10 @@ void Expression::makeBinaryOp(RPNCommand op, Expression &&src1, Expression const
|
||||
}
|
||||
} else if (op == RPN_SUB && src1.isDiffConstant(src2.symbolOf())) {
|
||||
data = src1.symbolOf()->getValue() - src2.symbolOf()->getValue();
|
||||
} else if ((op == RPN_LOGAND || op == RPN_AND) && tryConstZero(src1, src2)) {
|
||||
data = 0;
|
||||
} else if (op == RPN_LOGOR && tryConstNonzero(src1, src2)) {
|
||||
data = 1;
|
||||
} else if (int32_t constVal; op == RPN_AND && (constVal = tryConstMask(src1, src2)) != -1) {
|
||||
data = constVal;
|
||||
} else {
|
||||
|
||||
29
test/asm/const-zero.asm
Normal file
29
test/asm/const-zero.asm
Normal file
@@ -0,0 +1,29 @@
|
||||
MACRO test_and
|
||||
if DEF(foo) && foo == 42
|
||||
println "Life, the Universe, and Everything!"
|
||||
else
|
||||
println "What do you get if you multiply six by seven?"
|
||||
endc
|
||||
ENDM
|
||||
test_and
|
||||
DEF foo = 42
|
||||
test_and
|
||||
|
||||
|
||||
MACRO test_or
|
||||
if DEF(DEBUG) || @ == $4567
|
||||
println "Here we are!"
|
||||
else
|
||||
println "Where are we?"
|
||||
endc
|
||||
ENDM
|
||||
SECTION "Test OR", ROMX
|
||||
test_or ; Not constant
|
||||
DEF DEBUG EQU 1
|
||||
test_or
|
||||
|
||||
|
||||
SECTION "Test arithmetic", ROM0
|
||||
Floating:
|
||||
println Floating & 0
|
||||
println 0 & Floating
|
||||
3
test/asm/const-zero.err
Normal file
3
test/asm/const-zero.err
Normal file
@@ -0,0 +1,3 @@
|
||||
error: const-zero.asm(21) -> const-zero.asm::test_or(14):
|
||||
Expected constant expression: PC is not constant at assembly time
|
||||
error: Assembly aborted (1 error)!
|
||||
6
test/asm/const-zero.out
Normal file
6
test/asm/const-zero.out
Normal file
@@ -0,0 +1,6 @@
|
||||
What do you get if you multiply six by seven?
|
||||
Life, the Universe, and Everything!
|
||||
Where are we?
|
||||
Here we are!
|
||||
$0
|
||||
$0
|
||||
@@ -6,7 +6,7 @@ MACRO test_expr
|
||||
|
||||
DEF IS_CONST = ISCONST(\1)
|
||||
PRINTLN "Test #{d:TEST_NUM}: ISCONST reports {IS_CONST}"
|
||||
IF (\1) || 1 ; Only test if the expression can be evaluated
|
||||
IF (\1) || IS_CONST ; Only test if the expression can be evaluated
|
||||
WARN "Test #{d:TEST_NUM}: Compile-time constant"
|
||||
ENDC
|
||||
ENDM
|
||||
|
||||
Reference in New Issue
Block a user