mirror of
https://github.com/KarolS/millfork.git
synced 2025-04-11 23:37:15 +00:00
Fixes for flag boolean types (fixes #123)
This commit is contained in:
parent
90e5360bfd
commit
3b0aa9a425
src
main/scala/millfork/compiler
test/scala/millfork/test
@ -688,7 +688,20 @@ object M6809ExpressionCompiler extends AbstractExpressionCompiler[MLine] {
|
||||
case FatBooleanType => compileToB(ctx, expr)
|
||||
case t: ConstantBooleanType =>
|
||||
List(MLine.immediate(MOpcode.LDB, if (t.value) 1 else 0))
|
||||
case BuiltInBooleanType | _: FlagBooleanType =>
|
||||
case t: FlagBooleanType =>
|
||||
val condition = compile(ctx, expr, MExpressionTarget.NOTHING, NoBranching)
|
||||
condition ++ (t.jumpIfFalse.m6809 match {
|
||||
case BCC => List(MLine.immediate(LDB, 0), MLine.inherentB(ROL))
|
||||
case BCS => List(MLine.immediate(LDB, 0), MLine.inherentB(ROL), MLine.immediate(EORB, 1))
|
||||
case o =>
|
||||
val label = ctx.env.nextLabel("bo")
|
||||
List(
|
||||
MLine.immediate(LDB, 0),
|
||||
MLine.shortBranch(o, label),
|
||||
MLine.inherentB(INC),
|
||||
MLine.label(label))
|
||||
})
|
||||
case BuiltInBooleanType =>
|
||||
val label = ctx.env.nextLabel("bo")
|
||||
val condition = compile(ctx, expr, MExpressionTarget.NOTHING, BranchIfFalse(label))
|
||||
val conditionWithoutJump = condition.init
|
||||
|
@ -476,7 +476,20 @@ object MosExpressionCompiler extends AbstractExpressionCompiler[AssemblyLine] {
|
||||
compileToA(ctx, expr)
|
||||
case t: ConstantBooleanType =>
|
||||
List(AssemblyLine.immediate(LDA, if (t.value) 1 else 0))
|
||||
case _: FlagBooleanType | BuiltInBooleanType =>
|
||||
case t: FlagBooleanType =>
|
||||
val condition = compile(ctx, expr, None, NoBranching)
|
||||
condition ++ (t.jumpIfFalse.mosOpcode match {
|
||||
case BCC => List(AssemblyLine.immediate(LDA, 0), AssemblyLine.implied(ROL))
|
||||
case BCS => List(AssemblyLine.immediate(LDA, 0), AssemblyLine.implied(ROL), AssemblyLine.immediate(EOR, 1))
|
||||
case o =>
|
||||
val label = env.nextLabel("bo")
|
||||
List(
|
||||
AssemblyLine.immediate(LDA, 0),
|
||||
AssemblyLine.relative(o, label),
|
||||
AssemblyLine.immediate(LDA, 1),
|
||||
AssemblyLine.label(label))
|
||||
})
|
||||
case BuiltInBooleanType =>
|
||||
val label = env.nextLabel("bo")
|
||||
val condition = compile(ctx, expr, None, BranchIfFalse(label))
|
||||
if (condition.isEmpty) {
|
||||
|
@ -27,7 +27,18 @@ object Z80ExpressionCompiler extends AbstractExpressionCompiler[ZLine] {
|
||||
case FatBooleanType => compileToA(ctx, expression)
|
||||
case t: ConstantBooleanType =>
|
||||
List(ZLine.ldImm8(ZRegister.A, if (t.value) 1 else 0))
|
||||
case BuiltInBooleanType | _: FlagBooleanType =>
|
||||
case t: FlagBooleanType =>
|
||||
val condition = Z80ExpressionCompiler.compile(ctx, expression, ZExpressionTarget.NOTHING, NoBranching)
|
||||
condition ++ (t.jumpIfFalse.z80Flags match {
|
||||
case o =>
|
||||
val label = ctx.env.nextLabel("bo")
|
||||
List(
|
||||
ZLine.ldImm8(ZRegister.A, 0),
|
||||
ZLine.jumpR(ctx, label, o),
|
||||
ZLine.register(INC, ZRegister.A),
|
||||
ZLine.label(label))
|
||||
})
|
||||
case BuiltInBooleanType =>
|
||||
// TODO optimize if using CARRY
|
||||
// TODO: helper functions to convert flags to booleans, to make code smaller
|
||||
val label = ctx.env.nextLabel("bo")
|
||||
|
190
src/test/scala/millfork/test/BooleanFlagTypesSuite.scala
Normal file
190
src/test/scala/millfork/test/BooleanFlagTypesSuite.scala
Normal file
@ -0,0 +1,190 @@
|
||||
package millfork.test
|
||||
|
||||
import millfork.Cpu
|
||||
import millfork.test.emu.{EmuCrossPlatformBenchmarkRun, EmuUnoptimizedCrossPlatformRun, EmuUnoptimizedRun, ShouldNotCompile}
|
||||
import org.scalatest.{AppendedClues, FunSuite, Matchers}
|
||||
|
||||
/**
|
||||
* @author Karol Stasiak
|
||||
*/
|
||||
class BooleanFlagTypesSuite extends FunSuite with Matchers with AppendedClues {
|
||||
|
||||
test("clear_carry") {
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Motorola6809)(
|
||||
"""
|
||||
| asm clear_carry testCarryResult(byte register(a) dummy)
|
||||
|{
|
||||
| // we always set carry, so this is always false:
|
||||
| #if ARCH_6502
|
||||
| STA param
|
||||
| SEC
|
||||
| RTS
|
||||
| #elseif ARCH_I80
|
||||
| #pragma zilog_syntax
|
||||
| LD (param),A
|
||||
| OR A
|
||||
| CCF
|
||||
| RET
|
||||
| #elseif ARCH_6809
|
||||
| STA param
|
||||
| COMA
|
||||
| RTS
|
||||
| #else
|
||||
| #error unknown arch
|
||||
| #endif
|
||||
|}
|
||||
|
|
||||
|byte output @$c000
|
||||
|byte param @$c001
|
||||
|
|
||||
|void main() {
|
||||
| bool clearCarry
|
||||
| clearCarry = testCarryResult(55)
|
||||
| if clearCarry {
|
||||
| output = 0
|
||||
| } else {
|
||||
| output = 1
|
||||
| }
|
||||
|}
|
||||
""".stripMargin) { m =>
|
||||
m.readByte(0xc000) should equal(1)
|
||||
m.readByte(0xc001) should equal(55)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
test("set_carry") {
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Motorola6809)(
|
||||
"""
|
||||
| asm set_carry testCarryResult(byte register(a) dummy)
|
||||
|{
|
||||
| // we always set carry, so this is always true:
|
||||
| #if ARCH_6502
|
||||
| STA param
|
||||
| SEC
|
||||
| RTS
|
||||
| #elseif ARCH_I80
|
||||
| #pragma zilog_syntax
|
||||
| LD (param),A
|
||||
| OR A
|
||||
| CCF
|
||||
| RET
|
||||
| #elseif ARCH_6809
|
||||
| STA param
|
||||
| COMA
|
||||
| RTS
|
||||
| #else
|
||||
| #error unknown arch
|
||||
| #endif
|
||||
|}
|
||||
|
|
||||
|byte output @$c000
|
||||
|byte param @$c001
|
||||
|
|
||||
|void main() {
|
||||
| bool setCarry
|
||||
| setCarry = testCarryResult(55)
|
||||
| if setCarry {
|
||||
| output = 1
|
||||
| } else {
|
||||
| output = 0
|
||||
| }
|
||||
|}
|
||||
""".stripMargin) { m =>
|
||||
m.readByte(0xc000) should equal(1)
|
||||
m.readByte(0xc001) should equal(55)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
test("set_zero") {
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Motorola6809)(
|
||||
"""
|
||||
| asm set_zero testCarryResult(byte register(a) dummy)
|
||||
|{
|
||||
| // we always set zero, so this is always true:
|
||||
| #if ARCH_6502
|
||||
| STA param
|
||||
| LDA #0
|
||||
| RTS
|
||||
| #elseif ARCH_I80
|
||||
| #pragma zilog_syntax
|
||||
| LD (param),A
|
||||
| XOR A
|
||||
| CCF
|
||||
| RET
|
||||
| #elseif ARCH_6809
|
||||
| STA param
|
||||
| LDA #0
|
||||
| RTS
|
||||
| #else
|
||||
| #error unknown arch
|
||||
| #endif
|
||||
|}
|
||||
|
|
||||
|byte output @$c000
|
||||
|byte param @$c001
|
||||
|
|
||||
|void main() {
|
||||
| bool setZero
|
||||
| setZero = testCarryResult(55)
|
||||
| if setZero {
|
||||
| output = 1
|
||||
| } else {
|
||||
| output = 0
|
||||
| }
|
||||
|}
|
||||
""".stripMargin) { m =>
|
||||
m.readByte(0xc000) should equal(1)
|
||||
m.readByte(0xc001) should equal(55)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
test("clear_zero") {
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Motorola6809)(
|
||||
"""
|
||||
| asm clear_zero testCarryResult(byte register(a) dummy)
|
||||
|{
|
||||
| // we always set zero, so this is always false:
|
||||
| #if ARCH_6502
|
||||
| STA param
|
||||
| LDA #0
|
||||
| RTS
|
||||
| #elseif ARCH_I80
|
||||
| #pragma zilog_syntax
|
||||
| LD (param),A
|
||||
| XOR A
|
||||
| CCF
|
||||
| RET
|
||||
| #elseif ARCH_6809
|
||||
| STA param
|
||||
| LDA #0
|
||||
| RTS
|
||||
| #else
|
||||
| #error unknown arch
|
||||
| #endif
|
||||
|}
|
||||
|
|
||||
|byte output @$c000
|
||||
|byte param @$c001
|
||||
|
|
||||
|void main() {
|
||||
| bool clearZero
|
||||
| clearZero = testCarryResult(55)
|
||||
| if clearZero {
|
||||
| output = 0
|
||||
| } else {
|
||||
| output = 1
|
||||
| }
|
||||
|}
|
||||
""".stripMargin) { m =>
|
||||
m.readByte(0xc000) should equal(1)
|
||||
m.readByte(0xc001) should equal(55)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user