mirror of
https://github.com/KarolS/millfork.git
synced 2025-04-17 01:37:44 +00:00
Added unsigned byte comparisons for Z80
This commit is contained in:
parent
4d00cb4db9
commit
62e94d96f7
src
main/scala/millfork/compiler
test/scala/millfork/test
@ -1,4 +1,4 @@
|
||||
package millfork.compiler.mos
|
||||
package millfork.compiler
|
||||
|
||||
/**
|
||||
* @author Karol Stasiak
|
38
src/main/scala/millfork/compiler/z80/Z80Comparisons.scala
Normal file
38
src/main/scala/millfork/compiler/z80/Z80Comparisons.scala
Normal file
@ -0,0 +1,38 @@
|
||||
package millfork.compiler.z80
|
||||
|
||||
import millfork.assembly.z80._
|
||||
import millfork.compiler._
|
||||
import millfork.node.{Expression, ZRegister}
|
||||
|
||||
/**
|
||||
* @author Karol Stasiak
|
||||
*/
|
||||
object Z80Comparisons {
|
||||
|
||||
import ComparisonType._
|
||||
|
||||
def compile8BitComparison(ctx: CompilationContext, compType: ComparisonType.Value, l: Expression, r: Expression, branches: BranchSpec): List[ZLine] = {
|
||||
compType match {
|
||||
case GreaterUnsigned | LessOrEqualUnsigned | GreaterSigned | LessOrEqualSigned =>
|
||||
return compile8BitComparison(ctx, ComparisonType.flip(compType), r, l, branches)
|
||||
case _ => ()
|
||||
}
|
||||
val calculateFlags =
|
||||
Z80ExpressionCompiler.compileToA(ctx, r) ++
|
||||
List(ZLine.ld8(ZRegister.E, ZRegister.A)) ++
|
||||
Z80ExpressionCompiler.stashDEIfChanged(Z80ExpressionCompiler.compileToA(ctx, l)) ++
|
||||
List(ZLine.register(ZOpcode.CP, ZRegister.E))
|
||||
val jump = (compType, branches) match {
|
||||
case (Equal, BranchIfTrue(label)) => ZLine.jump(label, IfFlagSet(ZFlag.Z))
|
||||
case (Equal, BranchIfFalse(label)) => ZLine.jump(label, IfFlagClear(ZFlag.Z))
|
||||
case (NotEqual, BranchIfTrue(label)) => ZLine.jump(label, IfFlagClear(ZFlag.Z))
|
||||
case (NotEqual, BranchIfFalse(label)) => ZLine.jump(label, IfFlagSet(ZFlag.Z))
|
||||
case (LessUnsigned, BranchIfTrue(label)) => ZLine.jump(label, IfFlagSet(ZFlag.C))
|
||||
case (LessUnsigned, BranchIfFalse(label)) => ZLine.jump(label, IfFlagClear(ZFlag.C))
|
||||
case (GreaterOrEqualUnsigned, BranchIfTrue(label)) => ZLine.jump(label, IfFlagClear(ZFlag.C))
|
||||
case (GreaterOrEqualUnsigned, BranchIfFalse(label)) => ZLine.jump(label, IfFlagSet(ZFlag.C))
|
||||
case _ => ???
|
||||
}
|
||||
calculateFlags :+ jump
|
||||
}
|
||||
}
|
@ -216,22 +216,52 @@ object Z80ExpressionCompiler extends AbstractExpressionCompiler[ZLine] {
|
||||
???
|
||||
case "<" =>
|
||||
val (size, signed) = assertComparison(ctx, params)
|
||||
???
|
||||
compileTransitiveRelation(ctx, "<", params, target, branches) { (l, r) =>
|
||||
size match {
|
||||
case 1 => Z80Comparisons.compile8BitComparison(ctx, if (signed) ComparisonType.LessSigned else ComparisonType.LessUnsigned, l, r, branches)
|
||||
case _ => ???
|
||||
}
|
||||
}
|
||||
case ">=" =>
|
||||
val (size, signed) = assertComparison(ctx, params)
|
||||
???
|
||||
compileTransitiveRelation(ctx, ">=", params, target, branches) { (l, r) =>
|
||||
size match {
|
||||
case 1 => Z80Comparisons.compile8BitComparison(ctx, if (signed) ComparisonType.GreaterOrEqualSigned else ComparisonType.GreaterOrEqualUnsigned, l, r, branches)
|
||||
case _ => ???
|
||||
}
|
||||
}
|
||||
case ">" =>
|
||||
val (size, signed) = assertComparison(ctx, params)
|
||||
???
|
||||
compileTransitiveRelation(ctx, ">", params, target, branches) { (l, r) =>
|
||||
size match {
|
||||
case 1 => Z80Comparisons.compile8BitComparison(ctx, if (signed) ComparisonType.GreaterSigned else ComparisonType.GreaterUnsigned, l, r, branches)
|
||||
case _ => ???
|
||||
}
|
||||
}
|
||||
case "<=" =>
|
||||
val (size, signed) = assertComparison(ctx, params)
|
||||
???
|
||||
compileTransitiveRelation(ctx, "<=", params, target, branches) { (l, r) =>
|
||||
size match {
|
||||
case 1 => Z80Comparisons.compile8BitComparison(ctx, if (signed) ComparisonType.LessOrEqualSigned else ComparisonType.LessOrEqualUnsigned, l, r, branches)
|
||||
case _ => ???
|
||||
}
|
||||
}
|
||||
case "==" =>
|
||||
val size = params.map(p => getExpressionType(ctx, p).size).max
|
||||
???
|
||||
compileTransitiveRelation(ctx, "==", params, target, branches) { (l, r) =>
|
||||
size match {
|
||||
case 1 => Z80Comparisons.compile8BitComparison(ctx, ComparisonType.Equal, l, r, branches)
|
||||
case _ => ???
|
||||
}
|
||||
}
|
||||
case "!=" =>
|
||||
val (l, r, size) = assertBinary(ctx, params)
|
||||
???
|
||||
compileTransitiveRelation(ctx, "!=", params, target, branches) { (l, r) =>
|
||||
size match {
|
||||
case 1 => Z80Comparisons.compile8BitComparison(ctx, ComparisonType.NotEqual, l, r, branches)
|
||||
case _ => ???
|
||||
}
|
||||
}
|
||||
case "+=" =>
|
||||
val (l, r, size) = assertAssignmentLike(ctx, params)
|
||||
size match {
|
||||
@ -495,4 +525,39 @@ object Z80ExpressionCompiler extends AbstractExpressionCompiler[ZLine] {
|
||||
case SeparateBytesExpression(hi, lo) => ???
|
||||
}
|
||||
}
|
||||
|
||||
private def compileTransitiveRelation(ctx: CompilationContext,
|
||||
operator: String,
|
||||
params: List[Expression],
|
||||
target: ZExpressionTarget.Value,
|
||||
branches: BranchSpec)(binary: (Expression, Expression) => List[ZLine]): List[ZLine] = {
|
||||
params match {
|
||||
case List(l, r) => binary(l, r)
|
||||
case List(_) | Nil =>
|
||||
ErrorReporting.fatal("")
|
||||
case _ =>
|
||||
params.tail.init.foreach { e =>
|
||||
if (ctx.env.eval(e).isEmpty) e match {
|
||||
case VariableExpression(_) =>
|
||||
case LiteralExpression(_, _) =>
|
||||
case IndexedExpression(_, VariableExpression(_)) =>
|
||||
case IndexedExpression(_, LiteralExpression(_, _)) =>
|
||||
case IndexedExpression(_, SumExpression(List(
|
||||
(_, LiteralExpression(_, _)),
|
||||
(false, VariableExpression(_))
|
||||
), false)) =>
|
||||
case IndexedExpression(_, SumExpression(List(
|
||||
(false, VariableExpression(_)),
|
||||
(_, LiteralExpression(_, _))
|
||||
), false)) =>
|
||||
case _ =>
|
||||
ErrorReporting.warn("A complex expression may be evaluated multiple times", ctx.options, e.position)
|
||||
}
|
||||
}
|
||||
val conjunction = params.init.zip(params.tail).map {
|
||||
case (l, r) => FunctionCallExpression(operator, List(l, r))
|
||||
}.reduceLeft((a, b) => FunctionCallExpression("&&", List(a, b)))
|
||||
compile(ctx, conjunction, target, branches)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
package millfork.test
|
||||
|
||||
import millfork.test.emu.{EmuBenchmarkRun, EmuSuperOptimizedRun, EmuUltraBenchmarkRun}
|
||||
import millfork.CpuFamily
|
||||
import millfork.test.emu.{EmuBenchmarkRun, EmuCrossPlatformBenchmarkRun, EmuSuperOptimizedRun, EmuUltraBenchmarkRun}
|
||||
import org.scalatest.{FunSuite, Matchers}
|
||||
|
||||
/**
|
||||
@ -9,7 +10,7 @@ import org.scalatest.{FunSuite, Matchers}
|
||||
class ComparisonSuite extends FunSuite with Matchers {
|
||||
|
||||
test("Equality and inequality") {
|
||||
EmuBenchmarkRun(
|
||||
EmuCrossPlatformBenchmarkRun(CpuFamily.M6502, CpuFamily.I80)(
|
||||
"""
|
||||
| byte output @$c000
|
||||
| void main () {
|
||||
@ -27,7 +28,7 @@ class ComparisonSuite extends FunSuite with Matchers {
|
||||
}
|
||||
|
||||
test("Less") {
|
||||
EmuBenchmarkRun(
|
||||
EmuCrossPlatformBenchmarkRun(CpuFamily.M6502, CpuFamily.I80)(
|
||||
"""
|
||||
| byte output @$c000
|
||||
| void main () {
|
||||
@ -40,7 +41,7 @@ class ComparisonSuite extends FunSuite with Matchers {
|
||||
}
|
||||
|
||||
test("Compare to zero") {
|
||||
EmuBenchmarkRun(
|
||||
EmuCrossPlatformBenchmarkRun(CpuFamily.M6502, CpuFamily.I80)(
|
||||
"""
|
||||
| byte output @$c000
|
||||
| void main () {
|
||||
|
Loading…
x
Reference in New Issue
Block a user