mirror of
https://github.com/KarolS/millfork.git
synced 2025-04-13 05:39:54 +00:00
Fix sign extension when using pointers
This commit is contained in:
parent
510f85960c
commit
1bcb6d5010
@ -1002,7 +1002,7 @@ object M6809ExpressionCompiler extends AbstractExpressionCompiler[MLine] {
|
||||
else if (i == 1) List(
|
||||
MLine.tfr(M6809Register.A, M6809Register.B),
|
||||
MLine.inherent(SEX),
|
||||
MLine.tfr(M6809Register.B, M6809Register.A)
|
||||
MLine.tfr(M6809Register.A, M6809Register.B)
|
||||
)
|
||||
else List(MLine.tfr(M6809Register.A, M6809Register.B))
|
||||
} else {
|
||||
|
@ -1029,7 +1029,7 @@ object MosExpressionCompiler extends AbstractExpressionCompiler[AssemblyLine] {
|
||||
if (target.typ.size == 1) {
|
||||
AssemblyLine.variable(ctx, STA, target)
|
||||
}
|
||||
else if (target.typ.isSigned) {
|
||||
else if (pointy.elementType.isSigned) {
|
||||
AssemblyLine.variable(ctx, STA, target) ++ signExtendA(ctx) ++
|
||||
List.tabulate(target.typ.size - 1)(i => AssemblyLine.variable(ctx, STA, target, i + 1)).flatten
|
||||
} else {
|
||||
@ -1119,10 +1119,30 @@ object MosExpressionCompiler extends AbstractExpressionCompiler[AssemblyLine] {
|
||||
Nil
|
||||
}
|
||||
register match {
|
||||
case MosRegister.A | MosRegister.X | MosRegister.Y => result ++ suffix
|
||||
case MosRegister.AX | MosRegister.YX => result :+ AssemblyLine.immediate(LDX, 0) // TODO: signedness?
|
||||
case MosRegister.AY | MosRegister.XY => result :+ AssemblyLine.immediate(LDY, 0)
|
||||
case MosRegister.AW => result ++ List(AssemblyLine.implied(XBA), AssemblyLine.immediate(LDA, 0), AssemblyLine.implied(XBA))
|
||||
case MosRegister.A | MosRegister.X | MosRegister.Y =>
|
||||
result ++ suffix
|
||||
case MosRegister.AX | MosRegister.YX if !pointy.elementType.isSigned =>
|
||||
result :+ AssemblyLine.immediate(LDX, 0)
|
||||
case MosRegister.AY | MosRegister.XY if !pointy.elementType.isSigned =>
|
||||
result :+ AssemblyLine.immediate(LDY, 0)
|
||||
case MosRegister.XA | MosRegister.YA if !pointy.elementType.isSigned =>
|
||||
result :+ AssemblyLine.immediate(LDA, 0)
|
||||
case MosRegister.AX =>
|
||||
result ++ List(AssemblyLine.implied(PHA)) ++ signExtendA(ctx) ++ List(AssemblyLine.implied(TAX), AssemblyLine.implied(PLA))
|
||||
case MosRegister.AY =>
|
||||
result ++ List(AssemblyLine.implied(PHA)) ++ signExtendA(ctx) ++ List(AssemblyLine.implied(TAY), AssemblyLine.implied(PLA))
|
||||
case MosRegister.XY =>
|
||||
result ++ List(AssemblyLine.implied(TAX)) ++ signExtendA(ctx) ++ List(AssemblyLine.implied(TAY))
|
||||
case MosRegister.YX =>
|
||||
result ++ List(AssemblyLine.implied(TAY)) ++ signExtendA(ctx) ++ List(AssemblyLine.implied(TAX))
|
||||
case MosRegister.XA =>
|
||||
result ++ List(AssemblyLine.implied(TAX)) ++ signExtendA(ctx)
|
||||
case MosRegister.YA =>
|
||||
result ++ List(AssemblyLine.implied(TAY)) ++ signExtendA(ctx)
|
||||
case MosRegister.AW if !pointy.elementType.isSigned =>
|
||||
result ++ List(AssemblyLine.implied(XBA), AssemblyLine.immediate(LDA, 0), AssemblyLine.implied(XBA))
|
||||
case MosRegister.AW =>
|
||||
result ++ List(AssemblyLine.implied(PHA), AssemblyLine.implied(XBA), AssemblyLine.implied(PLA)) ++ signExtendA(ctx) ++ List(AssemblyLine.implied(XBA))
|
||||
}
|
||||
}
|
||||
case DerefExpression(inner, offset, targetType) =>
|
||||
@ -1168,7 +1188,8 @@ object MosExpressionCompiler extends AbstractExpressionCompiler[AssemblyLine] {
|
||||
case Some((variableType, variable)) =>
|
||||
prepare ++ (0 until variableType.size).flatMap { i =>
|
||||
val load =
|
||||
if (i >= targetType.size) List(AssemblyLine.immediate(LDA, 0))
|
||||
if (i == targetType.size) signExtendA(ctx)
|
||||
else if (i > targetType.size) Nil
|
||||
else if (am == AbsoluteY) List(AssemblyLine.absolute(LDA, addr + offset + i))
|
||||
else if (i == 0) List(AssemblyLine.immediate(LDY, offset), AssemblyLine(LDA, am, addr))
|
||||
else List(AssemblyLine.implied(INY), AssemblyLine(LDA, am, addr))
|
||||
@ -2249,7 +2270,7 @@ object MosExpressionCompiler extends AbstractExpressionCompiler[AssemblyLine] {
|
||||
AssemblyLine(STA, am, addr))
|
||||
case (_, AbsoluteY) =>
|
||||
prepare ++ (0 until targetType.size).flatMap { i =>
|
||||
val load = if (i >= sourceType.size) List(AssemblyLine.immediate(LDA, 0)) else AssemblyLine.variable(ctx, LDA, variable, i)
|
||||
val load = loadSingleByteAssumingAPreserved(ctx, sourceType, variable, i)
|
||||
load ++ List(
|
||||
AssemblyLine.absolute(STA, addr + offset + i))
|
||||
}
|
||||
@ -2257,14 +2278,14 @@ object MosExpressionCompiler extends AbstractExpressionCompiler[AssemblyLine] {
|
||||
fastTarget match {
|
||||
case Some((constAddr, fastAddrMode, initializeY)) =>
|
||||
initializeY(offset) ++ (0 until targetType.size).flatMap { i =>
|
||||
val load = if (i >= sourceType.size) List(AssemblyLine.immediate(LDA, 0)) else AssemblyLine.variable(ctx, LDA, variable, i)
|
||||
val load = loadSingleByteAssumingAPreserved(ctx, sourceType, variable, i)
|
||||
load ++ (if (i == 0) List(AssemblyLine(STA, fastAddrMode, constAddr)) else List(
|
||||
AssemblyLine.implied(INY),
|
||||
AssemblyLine(STA, fastAddrMode, constAddr)))
|
||||
}
|
||||
case _ =>
|
||||
prepare ++ (0 until targetType.size).flatMap { i =>
|
||||
val load = if (i >= sourceType.size) List(AssemblyLine.immediate(LDA, 0)) else AssemblyLine.variable(ctx, LDA, variable, i)
|
||||
val load = loadSingleByteAssumingAPreserved(ctx, sourceType, variable, i)
|
||||
load ++ List(
|
||||
if (i == 0) AssemblyLine.immediate(LDY, offset) else AssemblyLine.implied(INY),
|
||||
AssemblyLine(STA, am, addr))
|
||||
@ -2279,32 +2300,17 @@ object MosExpressionCompiler extends AbstractExpressionCompiler[AssemblyLine] {
|
||||
(am, amSource) match {
|
||||
case (AbsoluteY, AbsoluteY) =>
|
||||
prepare ++ prepareSource ++ (0 until targetType.size).flatMap { i =>
|
||||
if (i >= sourceType.size) List(
|
||||
AssemblyLine.immediate(LDA, 0),
|
||||
AssemblyLine.absolute(STA, addr + offset + i))
|
||||
else List(
|
||||
AssemblyLine.absolute(LDA, addrSource + sourceOffset + i),
|
||||
AssemblyLine.absolute(STA, addr + offset + i))
|
||||
loadSingleByteAssumingAPreserved(ctx, sourceType, addrSource + sourceOffset, i) :+ AssemblyLine.absolute(STA, addr + offset + i)
|
||||
}
|
||||
case (AbsoluteY, _) =>
|
||||
prepare ++ prepareSource ++ (0 until targetType.size).flatMap { i =>
|
||||
if (i >= sourceType.size) List(
|
||||
AssemblyLine.immediate(LDA, 0),
|
||||
AssemblyLine.absolute(STA, addr + offset + i))
|
||||
else List(
|
||||
if (i == 0) AssemblyLine.immediate(LDY, sourceOffset) else AssemblyLine.implied(INY),
|
||||
AssemblyLine(LDA, amSource, addrSource),
|
||||
AssemblyLine.absolute(STA, addr + offset + i))
|
||||
loadSingleByteIndexedCountingYAssumingAPreserved(ctx, sourceType, amSource, addrSource, sourceOffset, i) :+
|
||||
AssemblyLine.absolute(STA, addr + offset + i)
|
||||
}
|
||||
case (_, AbsoluteY) =>
|
||||
prepare ++ prepareSource ++ (0 until targetType.size).flatMap { i =>
|
||||
if (i >= sourceType.size) List(
|
||||
if (i == 0) AssemblyLine.immediate(LDY, sourceOffset) else AssemblyLine.implied(INY),
|
||||
AssemblyLine.immediate(LDA, 0),
|
||||
AssemblyLine(STA, am, addr))
|
||||
else List(
|
||||
if (i == 0) AssemblyLine.immediate(LDY, sourceOffset) else AssemblyLine.implied(INY),
|
||||
AssemblyLine.absolute(LDA, addrSource + sourceOffset + i),
|
||||
(if (i == 0) AssemblyLine.immediate(LDY, sourceOffset) else AssemblyLine.implied(INY)) ::
|
||||
(loadSingleByteAssumingAPreserved(ctx, sourceType, addrSource + sourceOffset, i) :+
|
||||
AssemblyLine(STA, am, addr))
|
||||
}
|
||||
case (IndexedY, IndexedY) =>
|
||||
@ -2320,13 +2326,8 @@ object MosExpressionCompiler extends AbstractExpressionCompiler[AssemblyLine] {
|
||||
AssemblyLine.zeropage(STA, reg, 2),
|
||||
AssemblyLine.zeropage(LDA, reg, 1),
|
||||
AssemblyLine.zeropage(STA, reg, 3)) ++ prepareSource ++ (0 until targetType.size).flatMap { i =>
|
||||
if (i >= sourceType.size) List(
|
||||
if (i == 0) AssemblyLine.immediate(LDY, sourceOffset) else AssemblyLine.implied(INY),
|
||||
AssemblyLine.immediate(LDA, 0),
|
||||
AssemblyLine.indexedY(STA, reg, 2))
|
||||
else List(
|
||||
if (i == 0) AssemblyLine.immediate(LDY, sourceOffset) else AssemblyLine.implied(INY),
|
||||
AssemblyLine.indexedY(LDA, reg),
|
||||
(if (i == 0) AssemblyLine.immediate(LDY, sourceOffset) else AssemblyLine.implied(INY)) ::
|
||||
(loadSingleByteIndexedAssumingAPreserved(ctx, sourceType, IndexedY, reg.toAddress, i) :+
|
||||
AssemblyLine.indexedY(STA, reg, 2))
|
||||
}
|
||||
case (false, true) =>
|
||||
@ -2335,13 +2336,8 @@ object MosExpressionCompiler extends AbstractExpressionCompiler[AssemblyLine] {
|
||||
AssemblyLine.zeropage(STA, reg, 2),
|
||||
AssemblyLine.zeropage(LDA, reg, 1),
|
||||
AssemblyLine.zeropage(STA, reg, 3)) ++ prepare ++ (0 until targetType.size).flatMap { i =>
|
||||
if (i >= sourceType.size) List(
|
||||
if (i == 0) AssemblyLine.immediate(LDY, sourceOffset) else AssemblyLine.implied(INY),
|
||||
AssemblyLine.immediate(LDA, 0),
|
||||
AssemblyLine.indexedY(STA, reg))
|
||||
else List(
|
||||
if (i == 0) AssemblyLine.immediate(LDY, sourceOffset) else AssemblyLine.implied(INY),
|
||||
AssemblyLine.indexedY(LDA, reg, 2),
|
||||
(if (i == 0) AssemblyLine.immediate(LDY, sourceOffset) else AssemblyLine.implied(INY)) ::
|
||||
(loadSingleByteIndexedAssumingAPreserved(ctx, sourceType, IndexedY, reg.toAddress + 2, i) :+
|
||||
AssemblyLine.indexedY(STA, reg))
|
||||
}
|
||||
case _ =>
|
||||
@ -2354,25 +2350,15 @@ object MosExpressionCompiler extends AbstractExpressionCompiler[AssemblyLine] {
|
||||
AssemblyLine.zeropage(STA, reg, 2),
|
||||
AssemblyLine.implied(PLA),
|
||||
AssemblyLine.zeropage(STA, reg, 3)) ++ (0 until targetType.size).flatMap { i =>
|
||||
if (i >= sourceType.size) List(
|
||||
if (i == 0) AssemblyLine.immediate(LDY, sourceOffset) else AssemblyLine.implied(INY),
|
||||
AssemblyLine.immediate(LDA, 0),
|
||||
AssemblyLine.indexedY(STA, reg, 2))
|
||||
else List(
|
||||
if (i == 0) AssemblyLine.immediate(LDY, sourceOffset) else AssemblyLine.implied(INY),
|
||||
AssemblyLine.indexedY(LDA, reg),
|
||||
(if (i == 0) AssemblyLine.immediate(LDY, sourceOffset) else AssemblyLine.implied(INY)) ::
|
||||
(loadSingleByteIndexedAssumingAPreserved(ctx, sourceType, IndexedY, reg.toAddress, i) :+
|
||||
AssemblyLine.indexedY(STA, reg, 2))
|
||||
}
|
||||
}
|
||||
case (MemoryAddressConstant(thT: MemoryVariable), MemoryAddressConstant(thS: MemoryVariable)) if thT.name != thS.name =>
|
||||
prepare ++ prepareSource ++ (0 until targetType.size).flatMap { i =>
|
||||
if (i >= sourceType.size) List(
|
||||
if (i == 0) AssemblyLine.immediate(LDY, sourceOffset) else AssemblyLine.implied(INY),
|
||||
AssemblyLine.immediate(LDA, 0),
|
||||
AssemblyLine.indexedY(STA, thT))
|
||||
else List(
|
||||
if (i == 0) AssemblyLine.immediate(LDY, sourceOffset) else AssemblyLine.implied(INY),
|
||||
AssemblyLine.indexedY(LDA, thS),
|
||||
(if (i == 0) AssemblyLine.immediate(LDY, sourceOffset) else AssemblyLine.implied(INY)) ::
|
||||
(loadSingleByteIndexedAssumingAPreserved(ctx, sourceType, IndexedY, thS.toAddress, i) :+
|
||||
AssemblyLine.indexedY(STA, thT))
|
||||
}
|
||||
case _ =>
|
||||
@ -2450,6 +2436,34 @@ object MosExpressionCompiler extends AbstractExpressionCompiler[AssemblyLine] {
|
||||
}
|
||||
}
|
||||
|
||||
private def loadSingleByteAssumingAPreserved(ctx: CompilationContext, sourceType: Type, variable: Variable, i: Int) = {
|
||||
if (i == sourceType.size) {
|
||||
if (sourceType.isSigned) signExtendA(ctx) else List(AssemblyLine.immediate(LDA, 0))
|
||||
} else if (i > sourceType.size) Nil
|
||||
else AssemblyLine.variable(ctx, LDA, variable, i)
|
||||
}
|
||||
|
||||
private def loadSingleByteAssumingAPreserved(ctx: CompilationContext, sourceType: Type, varAddr: Constant, i: Int) = {
|
||||
if (i == sourceType.size) {
|
||||
if (sourceType.isSigned) signExtendA(ctx) else List(AssemblyLine.immediate(LDA, 0))
|
||||
} else if (i > sourceType.size) Nil
|
||||
else List(AssemblyLine.absolute(LDA, varAddr + i))
|
||||
}
|
||||
|
||||
private def loadSingleByteIndexedAssumingAPreserved(ctx: CompilationContext, sourceType: Type, addrMode: AddrMode.Value, baseAddr: Constant, i: Int) = {
|
||||
if (i == sourceType.size) {
|
||||
if (sourceType.isSigned) signExtendA(ctx) else List(AssemblyLine.immediate(LDA, 0))
|
||||
} else if (i > sourceType.size) Nil
|
||||
else List(AssemblyLine(LDA, addrMode, baseAddr))
|
||||
}
|
||||
|
||||
private def loadSingleByteIndexedCountingYAssumingAPreserved(ctx: CompilationContext, sourceType: Type, addrMode: AddrMode.Value, baseAddr: Constant, sourceOffset:Int, i: Int) = {
|
||||
if (i == sourceType.size) {
|
||||
if (sourceType.isSigned) signExtendA(ctx) else List(AssemblyLine.immediate(LDA, 0))
|
||||
} else if (i > sourceType.size) Nil
|
||||
else List(if(i==0) AssemblyLine.immediate(LDY, sourceOffset) else AssemblyLine.implied(INY), AssemblyLine(LDA, addrMode, baseAddr))
|
||||
}
|
||||
|
||||
def arrayBoundsCheck(ctx: CompilationContext, pointy: Pointy, register: MosRegister.Value, index: Expression): List[AssemblyLine] = {
|
||||
if (!ctx.options.flags(CompilationFlag.CheckIndexOutOfBounds)) return Nil
|
||||
val arrayLength:Int = pointy match {
|
||||
|
@ -1505,31 +1505,28 @@ object Z80ExpressionCompiler extends AbstractExpressionCompiler[ZLine] {
|
||||
case ZExpressionTarget.HL =>
|
||||
if (signExtend) {
|
||||
List(ldAbs8(A, sourceAddr, elidability), ld8(L, A)) ++
|
||||
signExtendHighestByte(ctx, A, signExtend) ++
|
||||
List(ld8(H, A))
|
||||
signExtendHighestByte(ctx, A, H, signedSource = signExtend)
|
||||
} else {
|
||||
List(ldAbs8(A, sourceAddr, elidability), ld8(L, A), ldImm8(H, 0))
|
||||
}
|
||||
case ZExpressionTarget.BC =>
|
||||
if (signExtend) {
|
||||
List(ldAbs8(A, sourceAddr, elidability), ld8(C, A)) ++
|
||||
signExtendHighestByte(ctx, A, signExtend) ++
|
||||
List(ld8(B, A))
|
||||
signExtendHighestByte(ctx, A, B, signedSource = signExtend)
|
||||
} else {
|
||||
List(ldAbs8(A, sourceAddr, elidability), ld8(C, A), ldImm8(B, 0))
|
||||
}
|
||||
case ZExpressionTarget.DE =>
|
||||
if (signExtend) {
|
||||
List(ldAbs8(A, sourceAddr, elidability), ld8(E, A)) ++
|
||||
signExtendHighestByte(ctx, A, signExtend) ++
|
||||
List(ld8(D, A))
|
||||
signExtendHighestByte(ctx, A, D, signedSource = signExtend)
|
||||
} else {
|
||||
List(ldAbs8(A, sourceAddr, elidability), ld8(E, A), ldImm8(D, 0))
|
||||
}
|
||||
case ZExpressionTarget.EHL =>
|
||||
if (signExtend) {
|
||||
List(ldAbs8(A, sourceAddr, elidability), ld8(L, A)) ++
|
||||
signExtendHighestByte(ctx, A, signExtend) ++
|
||||
signExtendHighestByte(ctx, A, A, signedSource = signExtend) ++
|
||||
List(ld8(H, A), ld8(E, A))
|
||||
} else {
|
||||
List(ldAbs8(ZRegister.A, sourceAddr, elidability), ld8(L, A), ldImm8(H, 0), ldImm8(E, 0))
|
||||
@ -1537,7 +1534,7 @@ object Z80ExpressionCompiler extends AbstractExpressionCompiler[ZLine] {
|
||||
case ZExpressionTarget.DEHL =>
|
||||
if (signExtend) {
|
||||
List(ldAbs8(A, sourceAddr, elidability), ld8(L, A)) ++
|
||||
signExtendHighestByte(ctx, A, signExtend) ++
|
||||
signExtendHighestByte(ctx, A, A, signExtend) ++
|
||||
List(ld8(H, A), ld8(E, A), ld8(D, A))
|
||||
} else {
|
||||
List(ldAbs8(A, sourceAddr, elidability), ld8(L, A), ldImm8(H, 0), ldImm16(DE, 0))
|
||||
@ -1593,13 +1590,13 @@ object Z80ExpressionCompiler extends AbstractExpressionCompiler[ZLine] {
|
||||
prepareA ++ fillUpperBytes
|
||||
}
|
||||
|
||||
private def signExtendHighestByte(ctx: CompilationContext, hiRegister: ZRegister.Value, signedSource: Boolean = true): List[ZLine] = {
|
||||
private def signExtendHighestByte(ctx: CompilationContext, sourceHiRegister: ZRegister.Value, targetHiRegister: ZRegister.Value = ZRegister.A, signedSource: Boolean = true): List[ZLine] = {
|
||||
if (!signedSource) {
|
||||
return List(ZLine.ldImm8(ZRegister.A, 0))
|
||||
return List(ZLine.ldImm8(targetHiRegister, 0))
|
||||
}
|
||||
val prefix = if (hiRegister == ZRegister.A) Nil else List(ZLine.ld8(ZRegister.A, hiRegister))
|
||||
val prefix = if (sourceHiRegister == ZRegister.A) Nil else List(ZLine.ld8(ZRegister.A, sourceHiRegister))
|
||||
val label = ctx.nextLabel("sx")
|
||||
if (ctx.options.flag(CompilationFlag.EmitIntel8080Opcodes)) {
|
||||
val resultInA = if (ctx.options.flag(CompilationFlag.EmitIntel8080Opcodes)) {
|
||||
prefix ++ List(
|
||||
ZLine.imm8(OR, 0x7f),
|
||||
ZLine.jump(label, IfFlagSet(ZFlag.S)),
|
||||
@ -1616,6 +1613,7 @@ object Z80ExpressionCompiler extends AbstractExpressionCompiler[ZLine] {
|
||||
} else {
|
||||
throw new IllegalStateException()
|
||||
}
|
||||
if (targetHiRegister == ZRegister.A) resultInA else resultInA :+ ZLine.ld8(targetHiRegister, ZRegister.A)
|
||||
}
|
||||
|
||||
def signExtendViaIX(ctx: CompilationContext, targetOffset: Int, hiRegister: ZRegister.Value, bytes: Int, signedSource: Boolean): List[ZLine] = {
|
||||
@ -1874,10 +1872,11 @@ object Z80ExpressionCompiler extends AbstractExpressionCompiler[ZLine] {
|
||||
val lo = stashAFIfChanged(ctx, compileDerefPointer(ctx, e)) :+ ZLine.ld8(ZRegister.MEM_HL, ZRegister.A)
|
||||
if (targetType.size == 1) lo
|
||||
else if (targetType.size == 2) {
|
||||
lo ++ List(ZLine.register(INC_16, ZRegister.HL)) ++ signExtendHighestByte(ctx, ZRegister.MEM_HL)
|
||||
lo
|
||||
lo ++ List(ZLine.register(INC_16, ZRegister.HL)) ++
|
||||
signExtendHighestByte(ctx, ZRegister.A, signedSource = signedSource) ++
|
||||
List(ZLine.ld8(ZRegister.MEM_HL, ZRegister.A))
|
||||
} else {
|
||||
lo ++ signExtendHighestByte(ctx, ZRegister.A) ++ List.tabulate(targetType.size - 1)(_ => List(
|
||||
lo ++ signExtendHighestByte(ctx, ZRegister.A, signedSource = signedSource) ++ List.tabulate(targetType.size - 1)(_ => List(
|
||||
ZLine.register(INC_16, ZRegister.HL),
|
||||
ZLine.ld8(ZRegister.MEM_HL, ZRegister.A)
|
||||
)).flatten
|
||||
@ -2020,7 +2019,7 @@ object Z80ExpressionCompiler extends AbstractExpressionCompiler[ZLine] {
|
||||
ZLine.ld8(MEM_HL, B),
|
||||
ZLine.register(INC_16, HL),
|
||||
ZLine.ld8(MEM_HL, E)) ++ (
|
||||
if (targetType.size > 3) signExtendHighestByte(ctx, E, signedSource) ++ List.fill(targetType.size - 3)(List(ZLine.register(INC_16, HL), ZLine.ld8(MEM_HL, A))).flatten
|
||||
if (targetType.size > 3) signExtendHighestByte(ctx, E, A, signedSource) ++ List.fill(targetType.size - 3)(List(ZLine.register(INC_16, HL), ZLine.ld8(MEM_HL, A))).flatten
|
||||
else Nil)
|
||||
}
|
||||
|
||||
@ -2054,7 +2053,7 @@ object Z80ExpressionCompiler extends AbstractExpressionCompiler[ZLine] {
|
||||
ZLine.ld8(MEM_HL, E),
|
||||
ZLine.register(INC_16, HL),
|
||||
ZLine.ld8(MEM_HL, D)) ++ (
|
||||
if (targetType.size > 4) signExtendHighestByte(ctx, D, signedSource) ++ List.fill(targetType.size - 4)(List(ZLine.register(INC_16, HL), ZLine.ld8(MEM_HL, A))).flatten
|
||||
if (targetType.size > 4) signExtendHighestByte(ctx, D, A, signedSource) ++ List.fill(targetType.size - 4)(List(ZLine.register(INC_16, HL), ZLine.ld8(MEM_HL, A))).flatten
|
||||
else Nil)
|
||||
}
|
||||
|
||||
|
@ -936,4 +936,30 @@ class AssemblyOptimizationSuite extends FunSuite with Matchers {
|
||||
|}
|
||||
|""".stripMargin)
|
||||
}
|
||||
|
||||
test("Sign extension") {
|
||||
EmuBenchmarkRun(
|
||||
"""
|
||||
|array(word) output [5]@$c000
|
||||
|
|
||||
|noinline void set(byte i, sbyte s) {
|
||||
| word w
|
||||
| output[i] = s
|
||||
|}
|
||||
|
|
||||
|void main() {
|
||||
| set(0, 0)
|
||||
| set(1, -1)
|
||||
| set(2, 1)
|
||||
| set(3, 0)
|
||||
| set(4, 10)
|
||||
|}
|
||||
|""".stripMargin) { m =>
|
||||
m.readWord(0xc000) should equal(0)
|
||||
m.readWord(0xc002) should equal(0xffff)
|
||||
m.readWord(0xc004) should equal(1)
|
||||
m.readWord(0xc006) should equal(0)
|
||||
m.readWord(0xc008) should equal(10)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -207,4 +207,72 @@ class SignExtensionSuite extends FunSuite with Matchers {
|
||||
}
|
||||
}
|
||||
|
||||
test("Derefs and sign extension") {
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Motorola6809)(
|
||||
"""
|
||||
|pointer.word op
|
||||
|pointer.sbyte ip
|
||||
|array(sbyte) input[1]
|
||||
|array(word) output [4] @$c000
|
||||
|word output2 @$c010
|
||||
|
|
||||
|noinline byte id(byte x) = x
|
||||
|
|
||||
|noinline void init() {
|
||||
| input[0] = -2
|
||||
| ip = input[0].pointer
|
||||
| op = output[0].pointer
|
||||
|}
|
||||
|
|
||||
|void main() {
|
||||
| sbyte sb
|
||||
| sb = -2
|
||||
| init()
|
||||
| op[id(0)] = sb
|
||||
| output[id(1)] = sb
|
||||
| op[id(2)] = ip[id(0)]
|
||||
| output[id(3)] = ip[id(0)]
|
||||
| output2 = ip[id(0)]
|
||||
|}
|
||||
|""".stripMargin){ m =>
|
||||
m.readWord(0xc000) should equal(0xfffe)
|
||||
m.readWord(0xc002) should equal(0xfffe)
|
||||
m.readWord(0xc004) should equal(0xfffe)
|
||||
m.readWord(0xc006) should equal(0xfffe)
|
||||
m.readWord(0xc010) should equal(0xfffe)
|
||||
}
|
||||
}
|
||||
|
||||
test("Derefs and sign extension 2") {
|
||||
EmuUnoptimizedCrossPlatformRun(Cpu.Mos, Cpu.Z80, Cpu.Motorola6809)(
|
||||
"""
|
||||
|pointer.long op
|
||||
|pointer.sbyte ip
|
||||
|array(sbyte) input[1]
|
||||
|array(long) output [4] @$c000
|
||||
|long output2 @$c010
|
||||
|
|
||||
|noinline byte id(byte x) = x
|
||||
|
|
||||
|noinline void init() {
|
||||
| input[0] = -2
|
||||
| ip = input[0].pointer
|
||||
| op = output[0].pointer
|
||||
|}
|
||||
|
|
||||
|void main() {
|
||||
| sbyte sb
|
||||
| sb = -2
|
||||
| init()
|
||||
| op[id(0)] = sb
|
||||
| output[id(1)] = sb
|
||||
| output2 = ip[id(0)]
|
||||
|}
|
||||
|""".stripMargin){ m =>
|
||||
m.readLong(0xc000) should equal(-2)
|
||||
m.readLong(0xc004) should equal(-2)
|
||||
m.readLong(0xc010) should equal(-2)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user