1
0
mirror of https://github.com/KarolS/millfork.git synced 2024-12-23 08:29:35 +00:00

nonet() operator

This commit is contained in:
Karol Stasiak 2018-03-10 00:08:13 +01:00
parent e95d403752
commit 59cf1e06b4
5 changed files with 59 additions and 5 deletions

View File

@ -19,7 +19,7 @@
* Removed command line flag `--detailed-flow`.
Detailed flow analysis was slow, broken, hard to maintain, and didn't even help that much.
* Added `*'=` and `<<<<` operators.
* Added `*'=` and `nonet` operators. (Also, the `<<<<` operator, but it will be phased out before 0.2 and replaced by `nonet(a << b)`.)
* Added support for zeropage pseudoregisters, allowing for some operators work with more types of operands.

View File

@ -36,6 +36,8 @@ where `11111` is a sequential number and `xx` is the type:
* `is` optimized addition of carry using undocumented instructions
* `no` nonet to word extension caused by the `nonet` operator
* `od` end of a `do-while` statement
* `or` logical alternative short-circuiting

View File

@ -39,6 +39,7 @@ object ExpressionCompiler {
if (getExpressionType(ctx, lo).size > 1) ErrorReporting.error("Lo byte too large", lo.position)
w
case SumExpression(params, _) => b
case FunctionCallExpression("nonet", params) => w
case FunctionCallExpression("not", params) => bool
case FunctionCallExpression("hi", params) => bool
case FunctionCallExpression("lo", params) => bool
@ -805,6 +806,32 @@ object ExpressionCompiler {
} else compilation
}
}
case "nonet" =>
if (params.length != 1) {
ErrorReporting.error("Invalid number of parameters", f.position)
Nil
} else {
assertAllBytes("Nonet argument has to be a byte", ctx, params)
params.head match {
case SumExpression(addends, _) =>
if (addends.exists(a => !a._1)) {
ErrorReporting.warn("Nonet subtraction may not work as expected", ctx.options, expr.position)
}
if (addends.size > 2) {
ErrorReporting.warn("Nonet addition works correctly only for two operands", ctx.options, expr.position)
}
case FunctionCallExpression("+" | "+'" | "<<" | "<<<<" | "<<'" | "nonet", _) => // ok
case _ =>
ErrorReporting.warn("Unspecified nonet operation, results might be unpredictable", ctx.options, expr.position)
}
val label = MfCompiler.nextLabel("no")
compile(ctx, params.head, Some(b -> RegisterVariable(Register.A, b)), BranchSpec.None) ++ List(
AssemblyLine.immediate(LDX, 0),
AssemblyLine.relative(BCC, label),
AssemblyLine.implied(INX),
AssemblyLine.label(label)
) ++ expressionStorageFromAX(ctx, exprTypeAndVariable, expr.position)
}
case "&&" =>
assertBool(ctx, params, 2)
val a = params.head
@ -851,6 +878,7 @@ object ExpressionCompiler {
BuiltIns.compileNonetOps(ctx, v, r)
}
case "<<<<" =>
ErrorReporting.warn("`x <<<< y` is obsolete, use `nonet(x << y)`", ctx.options, expr.position)
assertAllBytes("Long shift ops not supported", ctx, params)
val (l, r, 1) = assertBinary(ctx, params)
BuiltIns.compileNonetLeftShift(ctx, l, r)

View File

@ -841,5 +841,5 @@ class Environment(val parent: Option[Environment], val prefix: String) {
}
object Environment {
val predefinedFunctions = Set("not", "hi", "lo")
val predefinedFunctions = Set("not", "hi", "lo", "nonet")
}

View File

@ -1,6 +1,6 @@
package millfork.test
import millfork.test.emu.EmuUnoptimizedRun
import millfork.test.emu.{EmuBenchmarkRun, EmuUnoptimizedRun}
import org.scalatest.{FunSuite, Matchers}
/**
@ -28,7 +28,7 @@ class NonetSuite extends FunSuite with Matchers {
}
test("Nonet left shift") {
val m = EmuUnoptimizedRun(
EmuBenchmarkRun(
"""
| word output0 @$c000
| word output1 @$c002
@ -42,10 +42,34 @@ class NonetSuite extends FunSuite with Matchers {
| output2 = a <<<< 6
| output3 = a <<<< 7
| }
""".stripMargin)
""".stripMargin) { m =>
m.readWord(0xc000) should equal(0x06)
m.readWord(0xc002) should equal(0x0C)
m.readWord(0xc004) should equal(0xC0)
m.readWord(0xc006) should equal(0x180)
}
}
test("Nonet left shift 2") {
EmuBenchmarkRun(
"""
| word output0 @$c000
| word output1 @$c002
| word output2 @$c004
| word output3 @$c006
| void main () {
| byte a
| a = 3
| output0 = nonet(a << 1)
| output1 = nonet(a << 2)
| output2 = nonet(a << 6)
| output3 = nonet(a << 7)
| }
""".stripMargin) { m =>
m.readWord(0xc000) should equal(0x06)
m.readWord(0xc002) should equal(0x0C)
m.readWord(0xc004) should equal(0xC0)
m.readWord(0xc006) should equal(0x180)
}
}
}