mirror of
https://github.com/gbdev/rgbds.git
synced 2025-11-20 10:12:06 +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
|
This is generally always the case, unless a label is involved, as explained in the
|
||||||
.Sx SYMBOLS
|
.Sx SYMBOLS
|
||||||
section.
|
section.
|
||||||
|
However, some operators can be constant even with non-constant operands, as explained in
|
||||||
|
.Sx Operators
|
||||||
|
further below.
|
||||||
.Pp
|
.Pp
|
||||||
The instructions in the macro-language generally require constant expressions.
|
The instructions in the macro-language generally require constant expressions.
|
||||||
.Ss Numeric formats
|
.Ss Numeric formats
|
||||||
@@ -306,13 +309,21 @@ equivalent to multiplying and dividing by 2 to the power of b, respectively.
|
|||||||
.Pp
|
.Pp
|
||||||
Comparison operators return 0 if the comparison is false, and 1 otherwise.
|
Comparison operators return 0 if the comparison is false, and 1 otherwise.
|
||||||
.Pp
|
.Pp
|
||||||
Unlike in a lot of languages, and for technical reasons,
|
Unlike in many other languages, and for technical reasons,
|
||||||
.Nm
|
.Nm
|
||||||
still evaluates both operands of
|
still evaluates both operands of
|
||||||
.Sq &&
|
.Sq &&
|
||||||
and
|
and
|
||||||
.Sq || .
|
.Sq || .
|
||||||
.Pp
|
.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 \&!
|
.Ic \&!
|
||||||
returns 1 if the operand was 0, and 0 otherwise.
|
returns 1 if the operand was 0, and 0 otherwise.
|
||||||
.Ss Fixed-point expressions
|
.Ss Fixed-point expressions
|
||||||
|
|||||||
@@ -197,6 +197,16 @@ void Expression::makeStartOfSectionType(SectionType type) {
|
|||||||
*ptr = 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
|
* 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
|
* 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())) {
|
} else if (op == RPN_SUB && src1.isDiffConstant(src2.symbolOf())) {
|
||||||
data = src1.symbolOf()->getValue() - src2.symbolOf()->getValue();
|
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) {
|
} else if (int32_t constVal; op == RPN_AND && (constVal = tryConstMask(src1, src2)) != -1) {
|
||||||
data = constVal;
|
data = constVal;
|
||||||
} else {
|
} 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)
|
DEF IS_CONST = ISCONST(\1)
|
||||||
PRINTLN "Test #{d:TEST_NUM}: ISCONST reports {IS_CONST}"
|
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"
|
WARN "Test #{d:TEST_NUM}: Compile-time constant"
|
||||||
ENDC
|
ENDC
|
||||||
ENDM
|
ENDM
|
||||||
|
|||||||
Reference in New Issue
Block a user