mirror of
https://github.com/irmen/prog8.git
synced 2024-12-24 01:29:28 +00:00
IR: don't confuse symbol names starting with 'r', with register names
Added start of buffer.p8 (experimental)
This commit is contained in:
parent
3f6521cc9b
commit
0c053e4a2c
69
compiler/res/prog8lib/buffers.p8
Normal file
69
compiler/res/prog8lib/buffers.p8
Normal 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)
|
@ -3,6 +3,8 @@ TODO
|
||||
|
||||
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 % ?)
|
||||
see inplacemodificationByteVariableWithLiteralval() and inplacemodificationSomeWordWithLiteralval()
|
||||
and for IR: see divideByConst() in IRCodeGen
|
||||
|
136
examples/test.p8
136
examples/test.p8
@ -1,52 +1,102 @@
|
||||
|
||||
%import textio
|
||||
%zeropage basicsafe
|
||||
%option no_sysinit
|
||||
|
||||
main {
|
||||
sub start() {
|
||||
signed()
|
||||
unsigned()
|
||||
ringbuffer256.init()
|
||||
|
||||
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()
|
||||
; }
|
||||
;}
|
||||
|
@ -118,12 +118,12 @@ fun parseIRCodeLine(line: String): Either<IRInstruction, String> {
|
||||
operands.forEach { oper ->
|
||||
if (oper[0] == '&')
|
||||
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()
|
||||
else if (reg2 == null) reg2 = oper.substring(1).toInt()
|
||||
else if (reg3 == null) reg3 = oper.substring(1).toInt()
|
||||
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()
|
||||
else if (fpReg2 == null) fpReg2 = oper.substring(2).toInt()
|
||||
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))
|
||||
}
|
||||
|
||||
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(
|
||||
val target: String?,
|
||||
val address: Int?,
|
||||
|
Loading…
Reference in New Issue
Block a user