mirror of
https://github.com/KarolS/millfork.git
synced 2024-10-25 05:24:11 +00:00
Added unsigned byte comparisons for Z80
This commit is contained in:
parent
4d00cb4db9
commit
62e94d96f7
@ -1,4 +1,4 @@
|
|||||||
package millfork.compiler.mos
|
package millfork.compiler
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Karol Stasiak
|
* @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 "<" =>
|
case "<" =>
|
||||||
val (size, signed) = assertComparison(ctx, params)
|
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 ">=" =>
|
case ">=" =>
|
||||||
val (size, signed) = assertComparison(ctx, params)
|
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 ">" =>
|
case ">" =>
|
||||||
val (size, signed) = assertComparison(ctx, params)
|
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 "<=" =>
|
case "<=" =>
|
||||||
val (size, signed) = assertComparison(ctx, params)
|
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 "==" =>
|
case "==" =>
|
||||||
val size = params.map(p => getExpressionType(ctx, p).size).max
|
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 "!=" =>
|
case "!=" =>
|
||||||
val (l, r, size) = assertBinary(ctx, params)
|
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 "+=" =>
|
case "+=" =>
|
||||||
val (l, r, size) = assertAssignmentLike(ctx, params)
|
val (l, r, size) = assertAssignmentLike(ctx, params)
|
||||||
size match {
|
size match {
|
||||||
@ -495,4 +525,39 @@ object Z80ExpressionCompiler extends AbstractExpressionCompiler[ZLine] {
|
|||||||
case SeparateBytesExpression(hi, lo) => ???
|
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
|
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}
|
import org.scalatest.{FunSuite, Matchers}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -9,7 +10,7 @@ import org.scalatest.{FunSuite, Matchers}
|
|||||||
class ComparisonSuite extends FunSuite with Matchers {
|
class ComparisonSuite extends FunSuite with Matchers {
|
||||||
|
|
||||||
test("Equality and inequality") {
|
test("Equality and inequality") {
|
||||||
EmuBenchmarkRun(
|
EmuCrossPlatformBenchmarkRun(CpuFamily.M6502, CpuFamily.I80)(
|
||||||
"""
|
"""
|
||||||
| byte output @$c000
|
| byte output @$c000
|
||||||
| void main () {
|
| void main () {
|
||||||
@ -27,7 +28,7 @@ class ComparisonSuite extends FunSuite with Matchers {
|
|||||||
}
|
}
|
||||||
|
|
||||||
test("Less") {
|
test("Less") {
|
||||||
EmuBenchmarkRun(
|
EmuCrossPlatformBenchmarkRun(CpuFamily.M6502, CpuFamily.I80)(
|
||||||
"""
|
"""
|
||||||
| byte output @$c000
|
| byte output @$c000
|
||||||
| void main () {
|
| void main () {
|
||||||
@ -40,7 +41,7 @@ class ComparisonSuite extends FunSuite with Matchers {
|
|||||||
}
|
}
|
||||||
|
|
||||||
test("Compare to zero") {
|
test("Compare to zero") {
|
||||||
EmuBenchmarkRun(
|
EmuCrossPlatformBenchmarkRun(CpuFamily.M6502, CpuFamily.I80)(
|
||||||
"""
|
"""
|
||||||
| byte output @$c000
|
| byte output @$c000
|
||||||
| void main () {
|
| void main () {
|
||||||
|
Loading…
Reference in New Issue
Block a user