IR: don't confuse symbol names starting with 'r', with register names

Added start of buffer.p8 (experimental)
This commit is contained in:
Irmen de Jong 2024-07-04 00:04:45 +02:00
parent 3f6521cc9b
commit 0c053e4a2c
4 changed files with 190 additions and 45 deletions

View File

@ -0,0 +1,69 @@
; experimental buffer data structures
smallringbuffer {
; -- A ringbuffer (FIFO queue) that occupies a single page in memory, containing 255 bytes maximum.
; You can store and retrieve words too.
; It's optimized for speed and depends on the byte-wrap-around feature when doing incs and decs.
ubyte fill
ubyte head
ubyte tail
ubyte[256] buffer
sub init() {
; -- (re)initialize the ringbuffer, you must call this before using the other routines
head = fill = 0
tail = 255
}
sub put(ubyte value) -> bool {
; -- store a byte in the buffer, returns success
if fill==255
return false
buffer[head] = value
head++
fill++
}
sub putw(uword value) -> bool {
; -- store a word in the buffer, returns success
if fill>=254
return false
fill+=2
buffer[head] = lsb(value)
head++
buffer[head] = msb(value)
head++
}
sub get() -> ubyte {
; -- retrieves a byte from the buffer. Also sets Carry flag: set=success, clear=buffer was empty
if fill==0 {
sys.clear_carry()
return 0
}
fill--
tail++
sys.set_carry()
return buffer[tail]
}
sub getw() -> uword {
; -- retrieves a word from the buffer. Also sets Carry flag: set=success, clear=buffer was empty
if fill<2 {
sys.clear_carry()
return 0
}
fill-=2
tail++
cx16.r0L = buffer[tail]
tail++
cx16.r0H = buffer[tail]
sys.set_carry()
return cx16.r0
}
}
; TODO ringbuffer (FIFO queue) using more than 1 page of ram (maybe even banked ram on the x16)
; TODO stack (LIFO queue) using more than 1 page of ram (maybe even banked ram on the x16)

View File

@ -3,6 +3,8 @@ TODO
See open issues on github. See open issues on github.
IR: add SEC and CLC instructions in place of call to sys.set_carry() and sys.clear_carry(). (check more inline sub calls that should be a single instruction?)
optimize signed byte/word division by powers of 2 (and shift right?), it's now using divmod routine. (also % ?) optimize signed byte/word division by powers of 2 (and shift right?), it's now using divmod routine. (also % ?)
see inplacemodificationByteVariableWithLiteralval() and inplacemodificationSomeWordWithLiteralval() see inplacemodificationByteVariableWithLiteralval() and inplacemodificationSomeWordWithLiteralval()
and for IR: see divideByConst() in IRCodeGen and for IR: see divideByConst() in IRCodeGen

View File

@ -1,52 +1,102 @@
%import textio %import textio
%zeropage basicsafe %zeropage basicsafe
%option no_sysinit %option no_sysinit
main { main {
sub start() { sub start() {
signed() ringbuffer256.init()
unsigned()
cx16.r0L = ringbuffer256.get()
if_cs {
txt.print_ub(cx16.r0L)
txt.nl()
} else {
txt.print("buffer empty\n")
} }
sub signed() {
byte @shared bvalue = -100
word @shared wvalue = -20000
bvalue /= 2 ; TODO should be a simple bit shift?
wvalue /= 2 ; TODO should be a simple bit shift?
txt.print_b(bvalue)
txt.nl()
txt.print_w(wvalue)
txt.nl()
bvalue *= 2
wvalue *= 2
txt.print_b(bvalue)
txt.nl()
txt.print_w(wvalue)
txt.nl()
}
sub unsigned() {
ubyte @shared ubvalue = 100
uword @shared uwvalue = 20000
ubvalue /= 2
uwvalue /= 2
txt.print_ub(ubvalue)
txt.nl()
txt.print_uw(uwvalue)
txt.nl()
ubvalue *= 2
uwvalue *= 2
txt.print_ub(ubvalue)
txt.nl()
txt.print_uw(uwvalue)
txt.nl()
} }
} }
ringbuffer256 {
uword size
ubyte head
ubyte tail
ubyte[256] buffer
sub init() {
size = head = 0
tail = 255
}
sub add(ubyte value) -> bool {
if size==256
return false
buffer[head] = value
head++
size++
}
sub get() -> ubyte {
if size==0 {
sys.clear_carry()
return 0
}
size--
tail++
sys.set_carry()
return buffer[tail]
}
}
;
;main {
; sub start() {
; signed()
; unsigned()
; }
;
; sub signed() {
; byte @shared bvalue = -100
; word @shared wvalue = -20000
;
; bvalue /= 2 ; TODO should be a simple bit shift?
; wvalue /= 2 ; TODO should be a simple bit shift?
;
; txt.print_b(bvalue)
; txt.nl()
; txt.print_w(wvalue)
; txt.nl()
;
; bvalue *= 2
; wvalue *= 2
;
; txt.print_b(bvalue)
; txt.nl()
; txt.print_w(wvalue)
; txt.nl()
; }
;
; sub unsigned() {
; ubyte @shared ubvalue = 100
; uword @shared uwvalue = 20000
;
; ubvalue /= 2
; uwvalue /= 2
;
; txt.print_ub(ubvalue)
; txt.nl()
; txt.print_uw(uwvalue)
; txt.nl()
;
; ubvalue *= 2
; uwvalue *= 2
;
; txt.print_ub(ubvalue)
; txt.nl()
; txt.print_uw(uwvalue)
; txt.nl()
; }
;}

View File

@ -118,12 +118,12 @@ fun parseIRCodeLine(line: String): Either<IRInstruction, String> {
operands.forEach { oper -> operands.forEach { oper ->
if (oper[0] == '&') if (oper[0] == '&')
throw IRParseException("address-of should be done with normal LOAD <symbol>") throw IRParseException("address-of should be done with normal LOAD <symbol>")
else if (oper[0] in "rR") { else if (isRegisterName(oper)) {
if (reg1 == null) reg1 = oper.substring(1).toInt() if (reg1 == null) reg1 = oper.substring(1).toInt()
else if (reg2 == null) reg2 = oper.substring(1).toInt() else if (reg2 == null) reg2 = oper.substring(1).toInt()
else if (reg3 == null) reg3 = oper.substring(1).toInt() else if (reg3 == null) reg3 = oper.substring(1).toInt()
else throw IRParseException("too many register operands") else throw IRParseException("too many register operands")
} else if (oper[0] in "fF" && oper[1] in "rR") { } else if (isFloatRegisterName(oper)) {
if (fpReg1 == null) fpReg1 = oper.substring(2).toInt() if (fpReg1 == null) fpReg1 = oper.substring(2).toInt()
else if (fpReg2 == null) fpReg2 = oper.substring(2).toInt() else if (fpReg2 == null) fpReg2 = oper.substring(2).toInt()
else throw IRParseException("too many fp register operands") else throw IRParseException("too many fp register operands")
@ -212,6 +212,30 @@ fun parseIRCodeLine(line: String): Either<IRInstruction, String> {
return left(IRInstruction(opcode, type, reg1, reg2, reg3, fpReg1, fpReg2, immediateInt, immediateFp, address, labelSymbol = labelSymbol, symbolOffset = offset)) return left(IRInstruction(opcode, type, reg1, reg2, reg3, fpReg1, fpReg2, immediateInt, immediateFp, address, labelSymbol = labelSymbol, symbolOffset = offset))
} }
private fun isRegisterName(oper: String): Boolean {
if(oper[0] in "rR") {
try {
oper.substring(1).toInt()
return true
} catch(_: NumberFormatException) {
return false
}
}
return false
}
private fun isFloatRegisterName(oper: String): Boolean {
if(oper[0] in "fF" && oper[1] in "rR") {
try {
oper.substring(2).toInt()
return true
} catch(_: NumberFormatException) {
return false
}
}
return false
}
private class ParsedCall( private class ParsedCall(
val target: String?, val target: String?,
val address: Int?, val address: Int?,