allow passing byte/word for register/registerpair arguments, fix stackvm string parameter handling

This commit is contained in:
Irmen de Jong 2018-12-15 00:07:25 +01:00
parent 8597ea2ec7
commit b9958412c7
8 changed files with 56 additions and 249 deletions

View File

@ -39,7 +39,7 @@
ask_guess:
c64.STROUT("\nYou have ")
c64scr.print_byte_decimal(attempts_left)
c64scr.print_ubyte_decimal(attempts_left)
c64.STROUT(" guess")
if(attempts_left>1)
c64.STROUT("es")
@ -66,7 +66,7 @@ ask_guess:
; game over.
c64.STROUT("\nToo bad! It was: ")
c64scr.print_byte_decimal(secretnumber)
c64scr.print_ubyte_decimal(secretnumber)
c64.CHROUT('\n')
goodbye:

View File

@ -26,7 +26,7 @@
; c64.CHROUT('\n')
c64scr.print_string("\nYou have ")
c64scr.print_byte_decimal(attempts_left)
c64scr.print_ubyte_decimal(attempts_left)
c64scr.print_string(" guess")
if attempts_left>1
c64scr.print_string("es")
@ -66,7 +66,7 @@
c64scr.print_string("\n\nYou guessed it, impressive!\n")
else {
c64scr.print_string("\nToo bad! My number was: ")
c64scr.print_byte_decimal(secretnumber)
c64scr.print_ubyte_decimal(secretnumber)
c64scr.print_string(".\n")
}
c64scr.print_string("Thanks for playing, ")

View File

@ -3,7 +3,7 @@
~ main {
sub start() {
str name = "????????????????????????????????????????"
str guessstr = "??????????"
str input = "??????????"
ubyte secretnumber = rnd() % 100
vm_write_str("Let's play a number guessing game!\n")
@ -20,15 +20,15 @@
if attempts_left>1
vm_write_str("es")
vm_write_str(" left. What is your next guess? ")
vm_input_str(guess)
ubyte guessednumber = str2ubyte(guess)
if guessednumber==secretnumber {
vm_input_str(input)
ubyte guess = str2ubyte(input)
if guess==secretnumber {
vm_write_str("\nYou guessed it, impressive!\n")
vm_write_str("Thanks for playing.\n")
return
} else {
vm_write_str("That is too ")
if guessednumber<secretnumber
if guess<secretnumber
vm_write_str("low!\n")
else
vm_write_str("high!\n")

View File

@ -7,219 +7,24 @@
ubyte ub1
ubyte ub2
byte b1
byte b1 = -99
byte b2
uword uw1
uword uw2
word w1
word w1 = -9999
word w2
float f1
float f2
float f3
; byte and ubyte output via print are all OK!
c64scr.print_byte_decimal(0)
c64.CHROUT(' ')
c64scr.print_byte_decimal(123)
c64.CHROUT(' ')
c64scr.print_byte_decimal(b2ub(-99)) ; @todo allow signed values for register
c64scr.print_byte_decimal(-99)
c64.CHROUT('\n')
c64scr.print_ubyte_decimal(0)
c64.CHROUT(' ')
c64scr.print_ubyte_decimal0(0)
c64.CHROUT(' ')
c64scr.print_ubyte_decimal(55)
c64.CHROUT(' ')
c64scr.print_ubyte_decimal0(55)
c64.CHROUT(' ')
c64scr.print_ubyte_decimal(254)
c64.CHROUT(' ')
c64scr.print_ubyte_decimal0(254)
c64scr.print_byte_decimal(b1)
c64.CHROUT('\n')
c64scr.print_ubyte_hex(0, 0)
c64.CHROUT(' ')
c64scr.print_ubyte_hex(1, 0)
c64.CHROUT(' ')
c64scr.print_ubyte_hex(0, $99)
c64.CHROUT(' ')
c64scr.print_ubyte_hex(1, $99)
c64.CHROUT(' ')
c64scr.print_ubyte_hex(0, $ea)
c64.CHROUT(' ')
c64scr.print_ubyte_hex(1, $ea)
c64scr.print_word_decimal(-9999)
c64.CHROUT('\n')
; print_uword_decimal are all OK!
c64scr.print_uword_decimal(0)
c64.CHROUT(' ')
c64scr.print_uword_decimal0(0)
c64.CHROUT(' ')
c64scr.print_uword_decimal(987)
c64.CHROUT(' ')
c64scr.print_uword_decimal0(987)
c64.CHROUT(' ')
c64scr.print_uword_decimal(55666)
c64.CHROUT(' ')
c64scr.print_uword_decimal0(55666)
c64scr.print_word_decimal(w1)
c64.CHROUT('\n')
c64scr.print_uword_hex(0, 0)
c64.CHROUT(' ')
c64scr.print_uword_hex(1, 0)
c64.CHROUT(' ')
c64scr.print_uword_hex(0, $99)
c64.CHROUT(' ')
c64scr.print_uword_hex(1, $99)
c64.CHROUT(' ')
c64scr.print_uword_hex(0, $1200)
c64.CHROUT(' ')
c64scr.print_uword_hex(1, $1200)
c64.CHROUT(' ')
c64scr.print_uword_hex(0, $fe98)
c64.CHROUT(' ')
c64scr.print_uword_hex(1, $fe98)
c64.CHROUT('\n')
; print_word_decimal works OK!
c64scr.print_word_decimal(0)
c64.CHROUT(' ')
c64scr.print_word_decimal(12345)
c64.CHROUT(' ')
c64scr.print_word_decimal(32555)
c64.CHROUT(' ')
c64scr.print_word_decimal(uwrd(-1)) ; @todo allow signed values for registerpair
c64.CHROUT(' ')
c64scr.print_word_decimal(uwrd(-9999)) ; @todo allow signed values for registerpair
c64.CHROUT(' ')
c64scr.print_word_decimal(uwrd(-$5fff)) ; @todo allow signed values for registerpair
c64.CHROUT(' ')
c64scr.print_word_decimal(uwrd(-$6000)) ; @todo allow signed values for registerpair
c64.CHROUT(' ')
c64scr.print_word_decimal(uwrd(-$6001)) ; @todo allow signed values for registerpair
c64.CHROUT('\n')
b1 = -6
b2 = 30
c64scr.print_byte_decimal(b2ub(b1))
c64.CHROUT('+')
c64scr.print_byte_decimal(b2ub(b2))
c64.CHROUT('=')
b1 += b2
c64scr.print_byte_decimal(b2ub(b1))
c64.CHROUT('\n')
b1 = 60
b2 = -3
c64scr.print_byte_decimal(b2ub(b1))
c64.CHROUT('+')
c64scr.print_byte_decimal(b2ub(b2))
c64.CHROUT('=')
b1 += b2
c64scr.print_byte_decimal(b2ub(b1))
c64.CHROUT('\n')
ub1 = 90
ub2 = 50
c64scr.print_ubyte_decimal(ub1)
c64.CHROUT('+')
c64scr.print_ubyte_decimal(ub2)
c64.CHROUT('=')
ub1 += ub2
c64scr.print_ubyte_decimal(ub1)
c64.CHROUT('\n')
ub1 = 50
ub2 = 90
c64scr.print_ubyte_decimal(ub1)
c64.CHROUT('+')
c64scr.print_ubyte_decimal(ub2)
c64.CHROUT('=')
ub1 += ub2
c64scr.print_ubyte_decimal(ub1)
c64.CHROUT('\n')
b1 = -6
b2 = 30
c64scr.print_byte_decimal(b2ub(b1))
c64.CHROUT('-')
c64scr.print_byte_decimal(b2ub(b2))
c64.CHROUT('=')
b1 -= b2
c64scr.print_byte_decimal(b2ub(b1))
c64.CHROUT('\n')
b1 = 60
b2 = -3
c64scr.print_byte_decimal(b2ub(b1))
c64.CHROUT('-')
c64scr.print_byte_decimal(b2ub(b2))
c64.CHROUT('=')
b1 -= b2
c64scr.print_byte_decimal(b2ub(b1))
c64.CHROUT('\n')
ub1 = 90
ub2 = 50
c64scr.print_ubyte_decimal(ub1)
c64.CHROUT('-')
c64scr.print_ubyte_decimal(ub2)
c64.CHROUT('=')
ub1 -= ub2
c64scr.print_ubyte_decimal(ub1)
c64.CHROUT('\n')
ub1 = 50
ub2 = 90
c64scr.print_ubyte_decimal(ub1)
c64.CHROUT('-')
c64scr.print_ubyte_decimal(ub2)
c64.CHROUT('=')
ub1 -= ub2
c64scr.print_ubyte_decimal(ub1)
c64.CHROUT('\n')
w1 = -600
w2 = 30000
c64scr.print_uword_hex(1, uwrd(w1))
c64.CHROUT('+')
c64scr.print_uword_hex(1, uwrd(w2))
c64.CHROUT('=')
w1 += w2
c64scr.print_uword_hex(1, uwrd(w1))
c64.CHROUT('\n')
w1 = 600
w2 = -30000
c64scr.print_uword_hex(1, uwrd(w1))
c64.CHROUT('+')
c64scr.print_uword_hex(1, uwrd(w2))
c64.CHROUT('=')
w1 += w2
c64scr.print_uword_hex(1, uwrd(w1))
c64.CHROUT('\n')
uw1 = 600
uw2 = 40000
c64scr.print_uword_decimal(uw1)
c64.CHROUT('+')
c64scr.print_uword_decimal(uw2)
c64.CHROUT('=')
uw1 += uw2
c64scr.print_uword_decimal(uw1)
c64.CHROUT('\n')
uw1 = 40000
uw2 = 600
c64scr.print_uword_decimal(uw1)
c64.CHROUT('+')
c64scr.print_uword_decimal(uw2)
c64.CHROUT('=')
uw1 += uw2
c64scr.print_uword_decimal(uw1)
c64.CHROUT('\n')
}
}

View File

@ -234,26 +234,32 @@ class AstChecker(private val namespace: INameScope,
if(subroutine.asmReturnvaluesRegisters.size != subroutine.returntypes.size)
err("number of return registers is not the same as number of return values")
for(param in subroutine.parameters.zip(subroutine.asmParameterRegisters)) {
if(param.second.registerOrPair in setOf(RegisterOrPair.A, RegisterOrPair.X, RegisterOrPair.Y))
if(param.first.type!=DataType.UBYTE)
err("parameter '${param.first.name}' should be ubyte")
else if(param.second.registerOrPair in setOf(RegisterOrPair.AX, RegisterOrPair.AY, RegisterOrPair.XY))
if(param.first.type!=DataType.UWORD)
err("parameter '${param.first.name}' should be uword")
else if(param.second.statusflag!=null)
if(param.first.type!=DataType.UBYTE)
if(param.second.registerOrPair in setOf(RegisterOrPair.A, RegisterOrPair.X, RegisterOrPair.Y)) {
if (param.first.type != DataType.UBYTE && param.first.type != DataType.BYTE)
err("parameter '${param.first.name}' should be (u)byte")
}
else if(param.second.registerOrPair in setOf(RegisterOrPair.AX, RegisterOrPair.AY, RegisterOrPair.XY)) {
if (param.first.type != DataType.UWORD && param.first.type != DataType.WORD && param.first.type !in StringDatatypes && param.first.type !in ArrayDatatypes)
err("parameter '${param.first.name}' should be (u)word/address")
}
else if(param.second.statusflag!=null) {
if (param.first.type != DataType.UBYTE)
err("parameter '${param.first.name}' should be ubyte")
}
}
for(ret in subroutine.returntypes.withIndex().zip(subroutine.asmReturnvaluesRegisters)) {
if(ret.second.registerOrPair in setOf(RegisterOrPair.A, RegisterOrPair.X, RegisterOrPair.Y))
if(ret.first.value!=DataType.UBYTE)
err("return value #${ret.first.index+1} should be ubyte")
else if(ret.second.registerOrPair in setOf(RegisterOrPair.AX, RegisterOrPair.AY, RegisterOrPair.XY))
if(ret.first.value!=DataType.UWORD)
err("return value #${ret.first.index+1} should be uword")
else if(ret.second.statusflag!=null)
if(ret.first.value!=DataType.UBYTE)
err("return value #${ret.first.index+1} should be ubyte")
if(ret.second.registerOrPair in setOf(RegisterOrPair.A, RegisterOrPair.X, RegisterOrPair.Y)) {
if (ret.first.value != DataType.UBYTE && ret.first.value != DataType.BYTE)
err("return value #${ret.first.index + 1} should be (u)byte")
}
else if(ret.second.registerOrPair in setOf(RegisterOrPair.AX, RegisterOrPair.AY, RegisterOrPair.XY)) {
if (ret.first.value != DataType.UWORD && ret.first.value != DataType.WORD && ret.first.value !in StringDatatypes && ret.first.value !in ArrayDatatypes)
err("return value #${ret.first.index + 1} should be (u)word/address")
}
else if(ret.second.statusflag!=null) {
if (ret.first.value != DataType.UBYTE)
err("return value #${ret.first.index + 1} should be ubyte")
}
}
val regCounts = mutableMapOf<Register, Int>().withDefault { 0 }

View File

@ -847,7 +847,7 @@ private class StatementTranslator(private val prog: IntermediateProgram,
translate(assignA)
translate(assignY)
}
DataType.UWORD -> {
DataType.UWORD, DataType.WORD -> {
translate(arg.first)
prog.instr(Opcode.POP_REGAY_WORD)
}
@ -1212,7 +1212,8 @@ private class StatementTranslator(private val prog: IntermediateProgram,
// convert value to target datatype if possible
when(targetDt) {
DataType.UBYTE, DataType.BYTE ->
throw CompilerException("incompatible data types valueDt=$valueDt targetDt=$targetDt at $stmt")
if(valueDt!=DataType.BYTE && valueDt!=DataType.UBYTE)
throw CompilerException("incompatible data types valueDt=$valueDt targetDt=$targetDt at $stmt")
DataType.WORD -> {
when (valueDt) {
DataType.UBYTE -> prog.instr(Opcode.UB2UWORD)

View File

@ -1417,20 +1417,15 @@ class StackVm(private var traceOutputFile: String?) {
print(Petscii.decodePetscii(listOf(evalstack.pop().integerValue().toShort()), true))
}
Syscall.VM_WRITE_STR -> {
val value = evalstack.pop()
when(value.type){
DataType.UBYTE, DataType.BYTE, DataType.UWORD, DataType.WORD, DataType.FLOAT -> print(value.numericValue())
DataType.STR, DataType.STR_P, DataType.STR_S, DataType.STR_PS -> print(heap.get(value.heapId).str)
DataType.ARRAY_UB, DataType.ARRAY_B, DataType.ARRAY_UW, DataType.ARRAY_W -> print(heap.get(value.heapId).array!!.toList())
DataType.ARRAY_F -> print(heap.get(value.heapId).doubleArray!!.toList())
}
val heapId = evalstack.pop().integerValue()
print(heap.get(heapId).str?.substringBefore('\u0000'))
}
Syscall.VM_INPUT_STR -> {
val variable = evalstack.pop()
val value = heap.get(variable.heapId)
val heapId = evalstack.pop().integerValue()
val value = heap.get(heapId)
val maxlen = value.str!!.length
val input = readLine() ?: ""
heap.update(variable.heapId, input.padEnd(maxlen, '\u0000').substring(0, maxlen))
heap.update(heapId, input.padEnd(maxlen, '\u0000').substring(0, maxlen))
}
Syscall.VM_GFX_PIXEL -> {
// plot pixel at (x, y, color) from stack
@ -1575,28 +1570,28 @@ class StackVm(private var traceOutputFile: String?) {
evalstack.push(Value(DataType.BYTE, y.toShort()))
}
Syscall.FUNC_STR2UBYTE -> {
val strvar = evalstack.pop()
val str = heap.get(strvar.heapId)
val heapId = evalstack.pop().integerValue()
val str = heap.get(heapId)
val y = str.str!!.trim().trimEnd('\u0000')
val number = (y.toInt() and 255).toShort()
evalstack.push(Value(DataType.UBYTE, number))
}
Syscall.FUNC_STR2WORD -> {
val strvar = evalstack.pop()
val str = heap.get(strvar.heapId)
val heapId = evalstack.pop().integerValue()
val str = heap.get(heapId)
val y = str.str!!.trim().trimEnd('\u0000')
evalstack.push(Value(DataType.WORD, y.toInt()))
}
Syscall.FUNC_STR2UWORD -> {
val strvar = evalstack.pop()
val str = heap.get(strvar.heapId)
val heapId = evalstack.pop().integerValue()
val str = heap.get(heapId)
val y = str.str!!.trim().trimEnd('\u0000')
val number = y.toInt() and 65535
evalstack.push(Value(DataType.UWORD, number))
}
Syscall.FUNC_STR2FLOAT -> {
val strvar = evalstack.pop()
val str = heap.get(strvar.heapId)
val heapId = evalstack.pop().integerValue()
val str = heap.get(heapId)
val y = str.str!!.trim().trimEnd('\u0000')
evalstack.push(Value(DataType.FLOAT, y.toDouble()))
}

View File

@ -649,7 +649,7 @@ _print_tens txa
}}
}
asmsub print_byte_decimal (value: ubyte @ A) -> clobbers(A,X,Y) -> () {
asmsub print_byte_decimal (value: byte @ A) -> clobbers(A,X,Y) -> () {
; ---- print the byte in A in decimal form, without left padding 0s
%asm {{
pha
@ -745,7 +745,7 @@ _pr_decimal
}}
}
asmsub print_word_decimal (value: uword @ AY) -> clobbers(A,X,Y) -> () {
asmsub print_word_decimal (value: word @ AY) -> clobbers(A,X,Y) -> () {
; ---- print the (signed) word in A/Y in decimal form, without left padding 0s
%asm {{
cpy #0