mirror of
https://github.com/irmen/prog8.git
synced 2025-08-19 10:27:43 +00:00
fixed assigning byte to word not clearing msb sometimes
This commit is contained in:
@@ -45,12 +45,12 @@ internal class AssignmentAsmGen(private val program: PtProgram,
|
|||||||
val variable = assign.source.asmVarname
|
val variable = assign.source.asmVarname
|
||||||
when (assign.target.datatype) {
|
when (assign.target.datatype) {
|
||||||
DataType.UBYTE, DataType.BYTE -> assignVariableByte(assign.target, variable)
|
DataType.UBYTE, DataType.BYTE -> assignVariableByte(assign.target, variable)
|
||||||
DataType.WORD -> assignVariableWord(assign.target, variable)
|
DataType.WORD -> assignVariableWord(assign.target, variable, assign.source.datatype)
|
||||||
DataType.UWORD -> {
|
DataType.UWORD -> {
|
||||||
if(assign.source.datatype in PassByReferenceDatatypes)
|
if(assign.source.datatype in PassByReferenceDatatypes)
|
||||||
assignAddressOf(assign.target, variable)
|
assignAddressOf(assign.target, variable)
|
||||||
else
|
else
|
||||||
assignVariableWord(assign.target, variable)
|
assignVariableWord(assign.target, variable, assign.source.datatype)
|
||||||
}
|
}
|
||||||
DataType.FLOAT -> assignVariableFloat(assign.target, variable)
|
DataType.FLOAT -> assignVariableFloat(assign.target, variable)
|
||||||
DataType.STR -> assignVariableString(assign.target, variable)
|
DataType.STR -> assignVariableString(assign.target, variable)
|
||||||
@@ -288,6 +288,7 @@ internal class AssignmentAsmGen(private val program: PtProgram,
|
|||||||
}
|
}
|
||||||
is PtPrefix -> {
|
is PtPrefix -> {
|
||||||
if(assign.target.array==null) {
|
if(assign.target.array==null) {
|
||||||
|
if(assign.source.datatype==assign.target.datatype) {
|
||||||
// First assign the value to the target then apply the operator in place on the target.
|
// First assign the value to the target then apply the operator in place on the target.
|
||||||
// This saves a temporary variable
|
// This saves a temporary variable
|
||||||
translateNormalAssignment(
|
translateNormalAssignment(
|
||||||
@@ -303,6 +304,30 @@ internal class AssignmentAsmGen(private val program: PtProgram,
|
|||||||
"not" -> throw AssemblyError("not should have been replaced in the Ast by ==0")
|
"not" -> throw AssemblyError("not should have been replaced in the Ast by ==0")
|
||||||
else -> throw AssemblyError("invalid prefix operator")
|
else -> throw AssemblyError("invalid prefix operator")
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
// use a temporary variable
|
||||||
|
val tempvar = if(value.type in ByteDatatypes) "P8ZP_SCRATCH_B1" else "P8ZP_SCRATCH_W1"
|
||||||
|
assignExpressionToVariable(value.value, tempvar, value.type)
|
||||||
|
when (value.operator) {
|
||||||
|
"+" -> {}
|
||||||
|
"-", "~" -> {
|
||||||
|
val assignTempvar = AsmAssignment(
|
||||||
|
AsmAssignSource(SourceStorageKind.VARIABLE, program, asmgen, value.type, variableAsmName = tempvar),
|
||||||
|
AsmAssignTarget(TargetStorageKind.VARIABLE, asmgen, value.type, scope, assign.position, variableAsmName = tempvar),
|
||||||
|
program.memsizer, assign.position)
|
||||||
|
if(value.operator=="-")
|
||||||
|
inplaceNegate(assignTempvar, true, scope)
|
||||||
|
else
|
||||||
|
inplaceInvert(assignTempvar, scope)
|
||||||
|
}
|
||||||
|
"not" -> throw AssemblyError("not should have been replaced in the Ast by ==0")
|
||||||
|
else -> throw AssemblyError("invalid prefix operator")
|
||||||
|
}
|
||||||
|
if(value.type in ByteDatatypes)
|
||||||
|
assignVariableByte(assign.target, tempvar)
|
||||||
|
else
|
||||||
|
assignVariableWord(assign.target, tempvar, value.type)
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
assignPrefixedExpressionToArrayElt(assign, scope)
|
assignPrefixedExpressionToArrayElt(assign, scope)
|
||||||
}
|
}
|
||||||
@@ -338,7 +363,7 @@ internal class AssignmentAsmGen(private val program: PtProgram,
|
|||||||
asmgen.translateNormalAssignment(assignToTempvar, scope)
|
asmgen.translateNormalAssignment(assignToTempvar, scope)
|
||||||
when(assign.target.datatype) {
|
when(assign.target.datatype) {
|
||||||
in ByteDatatypes -> assignVariableByte(assign.target, tempvar)
|
in ByteDatatypes -> assignVariableByte(assign.target, tempvar)
|
||||||
in WordDatatypes -> assignVariableWord(assign.target, tempvar)
|
in WordDatatypes -> assignVariableWord(assign.target, tempvar, assign.source.datatype)
|
||||||
DataType.FLOAT -> assignVariableFloat(assign.target, tempvar)
|
DataType.FLOAT -> assignVariableFloat(assign.target, tempvar)
|
||||||
else -> throw AssemblyError("weird dt")
|
else -> throw AssemblyError("weird dt")
|
||||||
}
|
}
|
||||||
@@ -827,7 +852,7 @@ internal class AssignmentAsmGen(private val program: PtProgram,
|
|||||||
DataType.UWORD -> {
|
DataType.UWORD -> {
|
||||||
asmgen.assignWordOperandsToAYAndVar(expr.right, expr.left, "P8ZP_SCRATCH_W1")
|
asmgen.assignWordOperandsToAYAndVar(expr.right, expr.left, "P8ZP_SCRATCH_W1")
|
||||||
asmgen.out(" jsr math.divmod_uw_asm")
|
asmgen.out(" jsr math.divmod_uw_asm")
|
||||||
assignVariableWord(assign.target, "P8ZP_SCRATCH_W2")
|
assignVariableWord(assign.target, "P8ZP_SCRATCH_W2", DataType.UWORD)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
else -> return false
|
else -> return false
|
||||||
@@ -2049,9 +2074,18 @@ internal class AssignmentAsmGen(private val program: PtProgram,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun assignVariableWord(target: AsmAssignTarget, sourceName: String) {
|
private fun assignVariableWord(target: AsmAssignTarget, sourceName: String, sourceDt: DataType) {
|
||||||
|
require(sourceDt in WordDatatypes || sourceDt==DataType.UBYTE)
|
||||||
when(target.kind) {
|
when(target.kind) {
|
||||||
TargetStorageKind.VARIABLE -> {
|
TargetStorageKind.VARIABLE -> {
|
||||||
|
if(sourceDt==DataType.UBYTE) {
|
||||||
|
asmgen.out(" lda $sourceName | sta ${target.asmVarname}")
|
||||||
|
if(asmgen.isTargetCpu(CpuType.CPU65c02))
|
||||||
|
asmgen.out(" stz ${target.asmVarname}")
|
||||||
|
else
|
||||||
|
asmgen.out(" lda #0 | sta ${target.asmVarname}")
|
||||||
|
}
|
||||||
|
else
|
||||||
asmgen.out("""
|
asmgen.out("""
|
||||||
lda $sourceName
|
lda $sourceName
|
||||||
ldy $sourceName+1
|
ldy $sourceName+1
|
||||||
@@ -2062,6 +2096,7 @@ internal class AssignmentAsmGen(private val program: PtProgram,
|
|||||||
throw AssemblyError("assign word to memory ${target.memory} should have gotten a typecast")
|
throw AssemblyError("assign word to memory ${target.memory} should have gotten a typecast")
|
||||||
}
|
}
|
||||||
TargetStorageKind.ARRAY -> {
|
TargetStorageKind.ARRAY -> {
|
||||||
|
if(sourceDt==DataType.UBYTE) TODO("assign byte to word array")
|
||||||
target.array!!
|
target.array!!
|
||||||
if(target.constArrayIndexValue!=null) {
|
if(target.constArrayIndexValue!=null) {
|
||||||
val scaledIdx = target.constArrayIndexValue!! * program.memsizer.memorySize(target.datatype).toUInt()
|
val scaledIdx = target.constArrayIndexValue!! * program.memsizer.memorySize(target.datatype).toUInt()
|
||||||
@@ -2137,6 +2172,21 @@ internal class AssignmentAsmGen(private val program: PtProgram,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
TargetStorageKind.REGISTER -> {
|
TargetStorageKind.REGISTER -> {
|
||||||
|
if(sourceDt==DataType.UBYTE) {
|
||||||
|
when(target.register!!) {
|
||||||
|
RegisterOrPair.AX -> asmgen.out(" ldx #0 | lda $sourceName")
|
||||||
|
RegisterOrPair.AY -> asmgen.out(" ldy #0 | lda $sourceName")
|
||||||
|
RegisterOrPair.XY -> asmgen.out(" ldy #0 | ldx $sourceName")
|
||||||
|
in Cx16VirtualRegisters -> {
|
||||||
|
asmgen.out(" lda $sourceName | sta cx16.${target.register.toString().lowercase()}")
|
||||||
|
if(asmgen.isTargetCpu(CpuType.CPU65c02))
|
||||||
|
asmgen.out(" stz cx16.${target.register.toString().lowercase()}+1")
|
||||||
|
else
|
||||||
|
asmgen.out(" lda #0 | sta cx16.${target.register.toString().lowercase()}+1")
|
||||||
|
}
|
||||||
|
else -> throw AssemblyError("can't load word in a single 8-bit register")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
when(target.register!!) {
|
when(target.register!!) {
|
||||||
RegisterOrPair.AX -> asmgen.out(" ldx $sourceName+1 | lda $sourceName")
|
RegisterOrPair.AX -> asmgen.out(" ldx $sourceName+1 | lda $sourceName")
|
||||||
RegisterOrPair.AY -> asmgen.out(" ldy $sourceName+1 | lda $sourceName")
|
RegisterOrPair.AY -> asmgen.out(" ldy $sourceName+1 | lda $sourceName")
|
||||||
@@ -2153,7 +2203,16 @@ internal class AssignmentAsmGen(private val program: PtProgram,
|
|||||||
else -> throw AssemblyError("can't load word in a single 8-bit register")
|
else -> throw AssemblyError("can't load word in a single 8-bit register")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
TargetStorageKind.STACK -> {
|
TargetStorageKind.STACK -> {
|
||||||
|
if(sourceDt==DataType.UBYTE) {
|
||||||
|
asmgen.out(" lda $sourceName | sta P8ESTACK_LO,x")
|
||||||
|
if(asmgen.isTargetCpu(CpuType.CPU65c02))
|
||||||
|
asmgen.out(" stz P8ESTACK_HI,x")
|
||||||
|
else
|
||||||
|
asmgen.out(" lda #0 | sta P8ESTACK_HI,x")
|
||||||
|
}
|
||||||
|
else
|
||||||
asmgen.out("""
|
asmgen.out("""
|
||||||
lda $sourceName
|
lda $sourceName
|
||||||
sta P8ESTACK_LO,x
|
sta P8ESTACK_LO,x
|
||||||
|
@@ -5,11 +5,11 @@ package prog8.buildversion
|
|||||||
*/
|
*/
|
||||||
const val MAVEN_GROUP = "prog8"
|
const val MAVEN_GROUP = "prog8"
|
||||||
const val MAVEN_NAME = "compiler"
|
const val MAVEN_NAME = "compiler"
|
||||||
const val VERSION = "9.1-SNAPSHOT"
|
const val VERSION = "9.2-SNAPSHOT"
|
||||||
const val GIT_REVISION = 3930
|
const val GIT_REVISION = 3964
|
||||||
const val GIT_SHA = "b4e94ae4dd1c29a966bb5ea0454ab31f1e9863cb"
|
const val GIT_SHA = "aaa30e4a583fa7c8da61998cf7cbb2a60b52afb0"
|
||||||
const val GIT_DATE = "2023-07-05T21:15:04Z"
|
const val GIT_DATE = "2023-07-16T21:16:18Z"
|
||||||
const val GIT_BRANCH = "master"
|
const val GIT_BRANCH = "master"
|
||||||
const val BUILD_DATE = "2023-07-05T21:15:07Z"
|
const val BUILD_DATE = "2023-07-16T21:16:23Z"
|
||||||
const val BUILD_UNIX_TIME = 1688591707834L
|
const val BUILD_UNIX_TIME = 1689542183583L
|
||||||
const val DIRTY = 1
|
const val DIRTY = 1
|
||||||
|
@@ -285,4 +285,37 @@ derp {
|
|||||||
compileText(VMTarget(), true, src, writeAssembly = true) shouldNotBe null
|
compileText(VMTarget(), true, src, writeAssembly = true) shouldNotBe null
|
||||||
compileText(Cx16Target(), true, src, writeAssembly = true) shouldNotBe null
|
compileText(Cx16Target(), true, src, writeAssembly = true) shouldNotBe null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test("prefix expressions with typecasting") {
|
||||||
|
val src="""
|
||||||
|
main
|
||||||
|
{
|
||||||
|
sub start()
|
||||||
|
{
|
||||||
|
uword uw = 54321
|
||||||
|
ubyte ub = 123
|
||||||
|
word sw = -12345
|
||||||
|
byte sb = -123
|
||||||
|
|
||||||
|
func_uw(~ub as uword)
|
||||||
|
func_ub(~uw as ubyte)
|
||||||
|
func_uw(~sb as uword)
|
||||||
|
func_ub(~sw as ubyte)
|
||||||
|
func_w(-sb as word)
|
||||||
|
func_b(-sw as byte)
|
||||||
|
}
|
||||||
|
|
||||||
|
sub func_uw(uword arg) {
|
||||||
|
}
|
||||||
|
sub func_w(word arg) {
|
||||||
|
}
|
||||||
|
sub func_ub(ubyte arg) {
|
||||||
|
}
|
||||||
|
sub func_b(byte arg) {
|
||||||
|
}
|
||||||
|
}"""
|
||||||
|
|
||||||
|
compileText(VMTarget(), false, src, writeAssembly = true) shouldNotBe null
|
||||||
|
compileText(Cx16Target(), false, src, writeAssembly = true) shouldNotBe null
|
||||||
|
}
|
||||||
})
|
})
|
@@ -5,37 +5,22 @@ main
|
|||||||
{
|
{
|
||||||
sub start()
|
sub start()
|
||||||
{
|
{
|
||||||
uword zc = 54321
|
uword uw = 54321
|
||||||
ubyte zb = 123
|
ubyte ub = 123
|
||||||
ubyte shift = 2
|
word sw = -12345
|
||||||
|
byte sb = -123
|
||||||
|
|
||||||
; txt.print_uw(zc<<shift)
|
txt.print_uw(~ub as uword) ;132
|
||||||
; txt.nl()
|
txt.nl()
|
||||||
; txt.print_uw(zc>>shift)
|
txt.print_ub(~uw as ubyte) ;206
|
||||||
; txt.nl()
|
txt.nl()
|
||||||
; txt.print_ub(zb<<shift)
|
txt.print_uw(~sb as uword) ;122
|
||||||
; txt.nl()
|
txt.nl()
|
||||||
; txt.print_ub(zb>>shift)
|
txt.print_ub(~sw as ubyte) ;56
|
||||||
; txt.nl()
|
txt.nl()
|
||||||
;
|
txt.print_w(-sb as word) ;123
|
||||||
; word szc = -12345
|
txt.nl()
|
||||||
; byte szb = -123
|
txt.print_b(-sw as byte) ;57
|
||||||
; txt.print_w(szc<<shift)
|
|
||||||
; txt.nl()
|
|
||||||
; txt.print_w(szc>>shift)
|
|
||||||
; txt.nl()
|
|
||||||
; txt.print_b(szb<<shift)
|
|
||||||
; txt.nl()
|
|
||||||
; txt.print_b(szb>>shift)
|
|
||||||
; txt.nl()
|
|
||||||
;
|
|
||||||
txt.print_uw(~zc as ubyte)
|
|
||||||
txt.spc()
|
|
||||||
txt.print_uw(~zb as uword)
|
|
||||||
txt.nl()
|
txt.nl()
|
||||||
|
|
||||||
|
|
||||||
; cx16.r1L = (zc<<shift) as ubyte
|
|
||||||
; txt.print_ub(cx16.r1L)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user