mirror of
https://github.com/irmen/prog8.git
synced 2024-12-24 16:29:21 +00:00
asmgen: byte to word sign extensions
This commit is contained in:
parent
6e53eb9d5c
commit
b2d1757e5a
@ -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")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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")
|
||||
|
@ -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")
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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")
|
||||
}
|
||||
}
|
||||
|
@ -7,6 +7,12 @@ main {
|
||||
|
||||
sub start() {
|
||||
|
||||
word wv
|
||||
byte bv
|
||||
|
||||
wv = bv
|
||||
|
||||
|
||||
}
|
||||
|
||||
asmsub testX() {
|
||||
|
Loading…
Reference in New Issue
Block a user