mirror of
https://github.com/irmen/prog8.git
synced 2024-12-24 16:29:21 +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.
|
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
|
||||||
|
136
examples/test.p8
136
examples/test.p8
@ -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()
|
||||||
|
; }
|
||||||
|
;}
|
||||||
|
@ -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?,
|
||||||
|
Loading…
Reference in New Issue
Block a user