mirror of
https://github.com/KarolS/millfork.git
synced 2025-02-11 18:30:52 +00:00
8080: implement signed byte comparisons for CPU's without the overflow flag
This commit is contained in:
parent
0410cbea34
commit
138dcfa19f
@ -35,6 +35,14 @@ object ComparisonType extends Enumeration {
|
||||
case NotEqual => Equal
|
||||
}
|
||||
|
||||
def toUnsigned(x: ComparisonType.Value): ComparisonType.Value = x match {
|
||||
case LessSigned => LessUnsigned
|
||||
case GreaterSigned => GreaterUnsigned
|
||||
case LessOrEqualSigned => LessOrEqualUnsigned
|
||||
case GreaterOrEqualSigned => GreaterOrEqualUnsigned
|
||||
case x => x
|
||||
}
|
||||
|
||||
def isSigned(x: ComparisonType.Value): Boolean = x match {
|
||||
case LessSigned => true
|
||||
case GreaterSigned => true
|
||||
|
@ -4,7 +4,7 @@ import millfork.CompilationFlag
|
||||
import millfork.assembly.z80._
|
||||
import millfork.compiler.{ComparisonType, _}
|
||||
import millfork.env.NumericConstant
|
||||
import millfork.node.{Expression, ZRegister}
|
||||
import millfork.node.{Expression, FunctionCallExpression, LiteralExpression, ZRegister}
|
||||
|
||||
/**
|
||||
* @author Karol Stasiak
|
||||
@ -15,6 +15,12 @@ object Z80Comparisons {
|
||||
|
||||
def compile8BitComparison(ctx: CompilationContext, compType: ComparisonType.Value, l: Expression, r: Expression, branches: BranchSpec): List[ZLine] = {
|
||||
handleConstantComparison(ctx, compType, l, r, branches).foreach(return _)
|
||||
if (ComparisonType.isSigned(compType) && !ctx.options.flag(CompilationFlag.EmitZ80Opcodes)) {
|
||||
return compile8BitComparison(ctx, ComparisonType.toUnsigned(compType),
|
||||
FunctionCallExpression("^", List(l, LiteralExpression(0x80, 1).pos(l.position))).pos(l.position),
|
||||
FunctionCallExpression("^", List(r, LiteralExpression(0x80, 1).pos(r.position))).pos(r.position),
|
||||
branches)
|
||||
}
|
||||
compType match {
|
||||
case GreaterUnsigned | LessOrEqualUnsigned | GreaterSigned | LessOrEqualSigned =>
|
||||
return compile8BitComparison(ctx, ComparisonType.flip(compType), r, l, branches)
|
||||
@ -30,7 +36,7 @@ object Z80Comparisons {
|
||||
ZLine.jump(fixup, IfFlagClear(ZFlag.P)),
|
||||
ZLine.imm8(ZOpcode.XOR, 0x80),
|
||||
ZLine.label(fixup))
|
||||
} else if (ComparisonType.isSigned(compType) && !ctx.options.flag(CompilationFlag.EmitIntel8080Opcodes)) {
|
||||
} else if (ComparisonType.isSigned(compType) && !ctx.options.flag(CompilationFlag.EmitZ80Opcodes)) {
|
||||
List(ZLine.register(ZOpcode.SUB, ZRegister.E))
|
||||
} else List(ZLine.register(ZOpcode.CP, ZRegister.E))
|
||||
if (branches == NoBranching) return prepareAE ++ calculateFlags
|
||||
|
5
src/main/scala/millfork/env/Constant.scala
vendored
5
src/main/scala/millfork/env/Constant.scala
vendored
@ -365,6 +365,7 @@ case class CompoundConstant(operator: MathOperator.Value, lhs: Constant, rhs: Co
|
||||
}
|
||||
case (NumericConstant(lv, ls), NumericConstant(rv, rs)) =>
|
||||
var size = ls max rs
|
||||
val bitmask = (1L << (8*size)) - 1
|
||||
val value = operator match {
|
||||
case MathOperator.Plus => lv + rv
|
||||
case MathOperator.Minus => lv - rv
|
||||
@ -374,9 +375,9 @@ case class CompoundConstant(operator: MathOperator.Value, lhs: Constant, rhs: Co
|
||||
case MathOperator.Shl9 => (lv << rv) & 0x1ff
|
||||
case MathOperator.Plus9 => (lv + rv) & 0x1ff
|
||||
case MathOperator.Shr9 => (lv & 0x1ff) >> rv
|
||||
case MathOperator.Exor => lv ^ rv
|
||||
case MathOperator.Exor => (lv ^ rv) & bitmask
|
||||
case MathOperator.Or => lv | rv
|
||||
case MathOperator.And => lv & rv
|
||||
case MathOperator.And => lv & rv & bitmask
|
||||
case MathOperator.DecimalPlus if ls == 1 && rs == 1 =>
|
||||
asDecimal(lv & 0xff, rv & 0xff, _ + _) & 0xff
|
||||
case MathOperator.DecimalMinus if ls == 1 && rs == 1 && lv.&(0xff) >= rv.&(0xff) =>
|
||||
|
@ -233,9 +233,6 @@ class ComparisonSuite extends FunSuite with Matchers {
|
||||
}
|
||||
|
||||
test("Signed comparison with overflow") {
|
||||
// These examples require a CPU with an overflow flag.
|
||||
// Good: 6502, Z80
|
||||
// Bad: 8080, LR35902
|
||||
val src =
|
||||
"""
|
||||
| byte output @$c000
|
||||
@ -266,7 +263,7 @@ class ComparisonSuite extends FunSuite with Matchers {
|
||||
| if c > -1 { output += 1 }
|
||||
| }
|
||||
""".stripMargin
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80)(src)(_.readByte(0xc000) should equal(src.count(_ == '+')))
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp)(src)(_.readByte(0xc000) should equal(src.count(_ == '+')))
|
||||
}
|
||||
|
||||
test("Signed comparison < and <=") {
|
||||
@ -460,4 +457,40 @@ class ComparisonSuite extends FunSuite with Matchers {
|
||||
m.readByte(0xc000) should equal(11)
|
||||
}
|
||||
}
|
||||
|
||||
test("Signed compare to 0") {
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80)(
|
||||
"""
|
||||
| byte output @$c000
|
||||
| void main() {
|
||||
| stuff(0)
|
||||
| }
|
||||
| noinline void stuff (sbyte x) {
|
||||
| if x >= 0 {
|
||||
| output = 11
|
||||
| }
|
||||
| }
|
||||
""".stripMargin
|
||||
) { m =>
|
||||
m.readByte(0xc000) should equal(11)
|
||||
}
|
||||
}
|
||||
|
||||
test("Signed compare to 1") {
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80)(
|
||||
"""
|
||||
| byte output @$c000
|
||||
| void main() {
|
||||
| stuff(2)
|
||||
| }
|
||||
| noinline void stuff (sbyte x) {
|
||||
| if x > 1 {
|
||||
| output = 11
|
||||
| }
|
||||
| }
|
||||
""".stripMargin
|
||||
) { m =>
|
||||
m.readByte(0xc000) should equal(11)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user