asmgen: byte to word sign extensions

This commit is contained in:
Irmen de Jong 2020-10-10 15:39:48 +02:00
parent 6e53eb9d5c
commit b2d1757e5a
5 changed files with 104 additions and 18 deletions

View File

@ -1220,7 +1220,7 @@ $counterVar .byte 0""")
assemblyLines.add(assembly)
}
internal fun signExtendStackByte(valueDt: DataType) {
internal fun signExtendStackLsb(valueDt: DataType) {
// sign extend signed byte on stack to signed word
when(valueDt) {
DataType.UBYTE -> {
@ -1237,4 +1237,22 @@ $counterVar .byte 0""")
else -> throw AssemblyError("need byte type")
}
}
internal fun signExtendVariableLsb(asmvar: String, valueDt: DataType) {
// sign extend signed byte in a word variable
when(valueDt) {
DataType.UBYTE -> {
out(" lda #0 | sta $asmvar+1")
}
DataType.BYTE -> {
out("""
lda $asmvar+1
ora #$7f
bmi +
lda #0
+ sta $asmvar+1""")
}
else -> throw AssemblyError("need byte type")
}
}
}

View File

@ -1013,7 +1013,7 @@ internal class ExpressionsAsmGen(private val program: Program, private val asmge
DataType.BYTE -> {
when(typecast.type) {
DataType.UBYTE, DataType.BYTE -> {}
DataType.UWORD, DataType.WORD -> asmgen.signExtendStackByte(DataType.BYTE)
DataType.UWORD, DataType.WORD -> asmgen.signExtendStackLsb(DataType.BYTE)
DataType.FLOAT -> asmgen.out(" jsr floats.stack_b2float")
in PassByReferenceDatatypes -> throw AssemblyError("cannot cast to a pass-by-reference datatype")
else -> throw AssemblyError("weird type")

View File

@ -166,9 +166,13 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
val valueDt = value.inferType(program).typeOrElse(DataType.STRUCT)
when(value) {
is IdentifierReference -> {
if (valueDt == DataType.UBYTE || valueDt == DataType.BYTE) {
if(targetDt in WordDatatypes) {
assignVariableByteIntoWord(target, value, valueDt)
if(targetDt in WordDatatypes) {
if(valueDt==DataType.UBYTE) {
assignVariableUByteIntoWord(target, value)
return
}
if(valueDt==DataType.BYTE) {
assignVariableByteIntoWord(target, value)
return
}
}
@ -606,10 +610,68 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
}
}
private fun assignVariableByteIntoWord(wordtarget: AsmAssignTarget, bytevar: IdentifierReference, valueDt: DataType) {
if(valueDt == DataType.BYTE)
TODO("sign extend byte to word")
private fun assignVariableByteIntoWord(wordtarget: AsmAssignTarget, bytevar: IdentifierReference) {
val sourceName = asmgen.asmVariableName(bytevar)
when (wordtarget.kind) {
TargetStorageKind.VARIABLE -> {
asmgen.out("""
lda $sourceName
sta ${wordtarget.asmVarname}
ora #$7f
bmi +
lda #0
+ sta ${wordtarget.asmVarname}+1
""")
}
TargetStorageKind.ARRAY -> {
// TODO optimize slow stack evaluation for this case, see assignVariableUByteIntoWord
println("warning: slow stack evaluation used for sign-extend byte typecast at ${bytevar.position}")
asmgen.translateExpression(wordtarget.origAssign.source.expression!!)
assignStackValue(wordtarget)
}
TargetStorageKind.REGISTER -> {
when(wordtarget.register!!) {
RegisterOrPair.AX -> asmgen.out("""
lda $sourceName
pha
ora #$7f
bmi +
ldx #0
+ tax
pla""")
RegisterOrPair.AY -> asmgen.out("""
lda $sourceName
pha
ora #$7f
bmi +
ldy #0
+ tay
pla""")
RegisterOrPair.XY -> asmgen.out("""
lda $sourceName
tax
ora #$7f
bmi +
ldy #0
+ tay""")
else -> throw AssemblyError("only reg pairs are words")
}
}
TargetStorageKind.STACK -> {
asmgen.out("""
lda $sourceName
sta P8ESTACK_LO,x
ora #$7f
bmi +
lda #0
+ sta P8ESTACK_HI,x
dex""")
}
else -> throw AssemblyError("target type isn't word")
}
}
private fun assignVariableUByteIntoWord(wordtarget: AsmAssignTarget, bytevar: IdentifierReference) {
val sourceName = asmgen.asmVariableName(bytevar)
when(wordtarget.kind) {
TargetStorageKind.VARIABLE -> {
@ -649,13 +711,13 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
}
TargetStorageKind.STACK -> {
asmgen.out("""
lda #$sourceName
lda $sourceName
sta P8ESTACK_LO,x
lda #0
sta P8ESTACK_HI,x
dex""")
}
else -> throw AssemblyError("other types aren't word")
else -> throw AssemblyError("target type isn't word")
}
}

View File

@ -605,7 +605,7 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
sec
sbc P8ZP_SCRATCH_B1
sta $name""")
// TODO: more operators
// TODO: tuned code for more operators
}
else -> {
inplaceModification_byte_value_to_variable(name, dt, operator, memread);
@ -636,7 +636,7 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
bcc +
dec $name+1
+""")
// TODO: more operators
// TODO: tuned code for more operators
}
else -> {
inplaceModification_word_value_to_variable(name, dt, operator, memread);
@ -1150,17 +1150,17 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
}
"*" -> {
// stack contains (u) byte value, sign extend that and proceed with regular 16 bit operation
asmgen.signExtendStackByte(valueDt)
asmgen.signExtendStackLsb(valueDt)
multiplyWord()
}
"/" -> {
// stack contains (u) byte value, sign extend that and proceed with regular 16 bit operation
asmgen.signExtendStackByte(valueDt)
asmgen.signExtendStackLsb(valueDt)
divideWord()
}
"%" -> {
// stack contains (u) byte value, sign extend that and proceed with regular 16 bit operation
asmgen.signExtendStackByte(valueDt)
asmgen.signExtendStackLsb(valueDt)
remainderWord()
}
"<<" -> {
@ -1201,9 +1201,9 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
+""")
}
}
"&" -> TODO("bitand (u)word (u)byte")
"^" -> TODO("bitxor (u)word (u)byte")
"|" -> TODO("bitor (u)word (u)byte")
"&" -> TODO("bitand (u)word (u)byte on stack")
"^" -> TODO("bitxor (u)word (u)byte on stack")
"|" -> TODO("bitor (u)word (u)byte on stack")
else -> throw AssemblyError("invalid operator for in-place modification $operator")
}
}

View File

@ -7,6 +7,12 @@ main {
sub start() {
word wv
byte bv
wv = bv
}
asmsub testX() {