Skip to content

Commit 380f557

Browse files
committed
vm: implement split incr/decr
1 parent 1bdae53 commit 380f557

File tree

6 files changed

+186
-53
lines changed

6 files changed

+186
-53
lines changed

codeGenIntermediate/src/prog8/codegen/intermediate/IRCodeGen.kt

Lines changed: 67 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1361,44 +1361,87 @@ class IRCodeGen(
13611361
private fun translate(postIncrDecr: PtPostIncrDecr): IRCodeChunks {
13621362
val result = mutableListOf<IRCodeChunkBase>()
13631363
val array = postIncrDecr.target.array
1364-
val operationMem: Opcode
1365-
val operationRegister: Opcode
1366-
when(postIncrDecr.operator) {
1367-
"++" -> {
1368-
operationMem = Opcode.INCM
1369-
operationRegister = Opcode.INC
1370-
}
1371-
"--" -> {
1372-
operationMem = Opcode.DECM
1373-
operationRegister = Opcode.DEC
1374-
}
1375-
else -> throw AssemblyError("weird operator")
1376-
}
1377-
13781364
if(array?.splitWords==true) {
13791365
val variable = array.variable.name
13801366
val fixedIndex = constIntValue(array.index)
13811367
val iterable = symbolTable.flat.getValue(array.variable.name) as StStaticVariable
1382-
val arrayLength = iterable.length!!
13831368
if(fixedIndex!=null) {
1384-
TODO("split incr decr")
1385-
// addInstr(result, IRInstruction(operationMem, irDt, immediate = arrayLength, labelSymbol="$variable+$fixedIndex"), null)
1369+
val skipLabel = createLabelName()
1370+
when(postIncrDecr.operator) {
1371+
"++" -> {
1372+
result += IRCodeChunk(null, null).also {
1373+
it += IRInstruction(Opcode.INCM, IRDataType.BYTE, labelSymbol = "${variable}_lsb+$fixedIndex")
1374+
it += IRInstruction(Opcode.BSTNE, labelSymbol = skipLabel)
1375+
it += IRInstruction(Opcode.INCM, IRDataType.BYTE, labelSymbol = "${variable}_msb+$fixedIndex")
1376+
}
1377+
result += IRCodeChunk(skipLabel, null)
1378+
}
1379+
"--" -> {
1380+
val valueReg=registers.nextFree()
1381+
result += IRCodeChunk(null, null).also {
1382+
it += IRInstruction(Opcode.LOADM, IRDataType.BYTE, reg1=valueReg, labelSymbol = "${variable}_lsb+$fixedIndex")
1383+
it += IRInstruction(Opcode.BSTNE, labelSymbol = skipLabel)
1384+
it += IRInstruction(Opcode.DECM, IRDataType.BYTE, labelSymbol = "${variable}_msb+$fixedIndex")
1385+
}
1386+
result += IRCodeChunk(skipLabel, null).also {
1387+
it += IRInstruction(Opcode.DECM, IRDataType.BYTE, labelSymbol = "${variable}_lsb+$fixedIndex")
1388+
}
1389+
}
1390+
else -> throw AssemblyError("weird operator")
1391+
}
13861392
} else {
1393+
val arrayLength = iterable.length!!
13871394
val indexTr = expressionEval.translateExpression(array.index)
13881395
addToResult(result, indexTr, indexTr.resultReg, -1)
1389-
val chunk = IRCodeChunk(null, null)
13901396
val incReg = registers.nextFree()
1391-
TODO("load split")
1392-
// chunk += IRInstruction(Opcode.LOADXSPLIT, irDt, reg1=incReg, reg2=indexTr.resultReg, immediate = arrayLength, labelSymbol=variable)
1393-
// chunk += IRInstruction(operationRegister, irDt, reg1=incReg)
1394-
TODO("store split")
1395-
// chunk += IRInstruction(Opcode.STOREXSPLIT, irDt, reg1=incReg, reg2=indexTr.resultReg, immediate = arrayLength, labelSymbol=variable)
1396-
result += chunk
1397+
val skipLabel = createLabelName()
1398+
when(postIncrDecr.operator) {
1399+
"++" -> {
1400+
result += IRCodeChunk(null, null).also {
1401+
it += IRInstruction(Opcode.LOADX, IRDataType.BYTE, reg1=incReg, reg2=indexTr.resultReg, immediate = arrayLength, labelSymbol = "${variable}_lsb")
1402+
it += IRInstruction(Opcode.INC, IRDataType.BYTE, reg1=incReg)
1403+
it += IRInstruction(Opcode.STOREX, IRDataType.BYTE, reg1=incReg, reg2=indexTr.resultReg, immediate = arrayLength, labelSymbol = "${variable}_lsb")
1404+
it += IRInstruction(Opcode.BSTNE, labelSymbol = skipLabel)
1405+
it += IRInstruction(Opcode.LOADX, IRDataType.BYTE, reg1=incReg, reg2=indexTr.resultReg, immediate = arrayLength, labelSymbol = "${variable}_msb")
1406+
it += IRInstruction(Opcode.INC, IRDataType.BYTE, reg1=incReg)
1407+
it += IRInstruction(Opcode.STOREX, IRDataType.BYTE, reg1=incReg, reg2=indexTr.resultReg, immediate = arrayLength, labelSymbol = "${variable}_msb")
1408+
}
1409+
result += IRCodeChunk(skipLabel, null)
1410+
}
1411+
"--" -> {
1412+
result += IRCodeChunk(null, null).also {
1413+
it += IRInstruction(Opcode.LOADX, IRDataType.BYTE, reg1=incReg, reg2=indexTr.resultReg, immediate = arrayLength, labelSymbol = "${variable}_lsb")
1414+
it += IRInstruction(Opcode.BSTNE, labelSymbol = skipLabel)
1415+
it += IRInstruction(Opcode.LOADX, IRDataType.BYTE, reg1=incReg, reg2=indexTr.resultReg, immediate = arrayLength, labelSymbol = "${variable}_msb")
1416+
it += IRInstruction(Opcode.DEC, IRDataType.BYTE, reg1=incReg)
1417+
it += IRInstruction(Opcode.STOREX, IRDataType.BYTE, reg1=incReg, reg2=indexTr.resultReg, immediate = arrayLength, labelSymbol = "${variable}_msb")
1418+
}
1419+
result += IRCodeChunk(skipLabel, null).also {
1420+
it += IRInstruction(Opcode.LOADX, IRDataType.BYTE, reg1=incReg, reg2=indexTr.resultReg, immediate = arrayLength, labelSymbol = "${variable}_lsb")
1421+
it += IRInstruction(Opcode.DEC, IRDataType.BYTE, reg1=incReg)
1422+
it += IRInstruction(Opcode.STOREX, IRDataType.BYTE, reg1=incReg, reg2=indexTr.resultReg, immediate = arrayLength, labelSymbol = "${variable}_lsb")
1423+
}
1424+
}
1425+
else -> throw AssemblyError("weird operator")
1426+
}
13971427
}
13981428
} else {
13991429
val ident = postIncrDecr.target.identifier
14001430
val memory = postIncrDecr.target.memory
14011431
val irDt = irType(postIncrDecr.target.type)
1432+
val operationMem: Opcode
1433+
val operationRegister: Opcode
1434+
when(postIncrDecr.operator) {
1435+
"++" -> {
1436+
operationMem = Opcode.INCM
1437+
operationRegister = Opcode.INC
1438+
}
1439+
"--" -> {
1440+
operationMem = Opcode.DECM
1441+
operationRegister = Opcode.DEC
1442+
}
1443+
else -> throw AssemblyError("weird operator")
1444+
}
14021445
if(ident!=null) {
14031446
addInstr(result, IRInstruction(operationMem, irDt, labelSymbol = ident.name), null)
14041447
} else if(memory!=null) {

docs/source/building.rst

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ Then you can choose a few ways to get a compiler:
1414
**Download a precompiled version from github:**
1515

1616
#. download a recent "fat-jar" (called something like "prog8compiler-all.jar") from `the releases on Github <https://github.com/irmen/prog8/releases>`_
17-
#. run the compiler with "java -jar prog8compiler-all.jar" to see how you can use it.
17+
#. run the compiler with "java -jar prog8compiler.jar" to see how you can use it (use the correct name and version of the jar file you've downloaded).
1818

1919
**Using the Gradle build system to build it yourself:**
2020

@@ -86,11 +86,12 @@ The compiler will link everything together into one output program at the end.
8686
If you start the compiler without arguments, it will print a short usage text.
8787
For normal use the compiler can be invoked with the command:
8888

89-
``$ java -jar prog8compiler-8.14-all.jar sourcefile.p8``
89+
``$ java -jar prog8compiler.jar -target cx16 sourcefile.p8``
9090

9191
(Use the appropriate name and version of the jar file downloaded from one of the Git releases.
9292
Other ways to invoke the compiler are also available: see the introduction page about how
93-
to build and run the compiler yourself)
93+
to build and run the compiler yourself. The -target option is required, in this case we
94+
tell it to compile a program for the Commander X16)
9495

9596

9697
By default, assembly code is generated and written to ``sourcefile.asm``.

docs/source/todo.rst

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
TODO
22
====
33

4-
- vm: fix the last replacement code for the now removed LOADSPLIT/STORESPLIT opcodes.
5-
64
...
75

86

examples/test.p8

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,12 @@ main {
1515
; }
1616
; txt.nl()
1717
ubyte idx=1
18-
names[idx] = 2000
19-
txt.print_uw(names[1])
18+
names[idx] = $20ff
19+
txt.print_uwhex(names[1], true)
2020
names[idx]++
21-
txt.print_uw(names[1])
21+
txt.print_uwhex(names[1], true)
2222
names[idx]--
23-
txt.print_uw(names[1])
23+
txt.print_uwhex(names[1], true)
2424

2525
names = [1111,2222,3333]
2626
for ww in names {

intermediate/src/prog8/intermediate/IRInstructions.kt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,9 @@ Program to execute is not stored in the system memory, it's just a separate list
1515
65536 bytes of memory. Thus memory pointers (addresses) are limited to 16 bits.
1616
Value stack, max 128 entries of 1 byte each.
1717
Status flags: Carry, Zero, Negative. NOTE: status flags are only affected by the CMP instruction or explicit CLC/SEC!!!
18-
logical or arithmetic operations DO NOT AFFECT THE STATUS FLAGS UNLESS EXPLICITLY NOTED!
18+
LOAD instructions DO affect the Z and N flags
19+
INC/DEC instructions DO affect the Z and N flags
20+
other instructions such as logical or arithmetic operations DO NOT AFFECT THE STATUS FLAGS UNLESS EXPLICITLY NOTED!
1921
2022
Instruction set is mostly a load/store architecture, there are few instructions operating on memory directly.
2123

virtualmachine/src/prog8/vm/VirtualMachine.kt

Lines changed: 108 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -375,8 +375,11 @@ class VirtualMachine(irProgram: IRProgram) {
375375
if(i.type==IRDataType.FLOAT)
376376
registers.setFloat(i.fpReg1!!, i.immediateFp!!)
377377
else {
378-
if(i.immediate!=null)
378+
if(i.immediate!=null) {
379379
setResultReg(i.reg1!!, i.immediate!!, i.type!!)
380+
statusZero = i.immediate==0
381+
statusNegative = i.immediate!! <0
382+
}
380383
else {
381384
if(i.labelSymbol==null)
382385
throw IllegalArgumentException("expected LOAD of address of labelsymbol")
@@ -388,26 +391,56 @@ class VirtualMachine(irProgram: IRProgram) {
388391

389392
private fun InsLOADM(i: IRInstruction) {
390393
when(i.type!!) {
391-
IRDataType.BYTE -> registers.setUB(i.reg1!!, memory.getUB(i.address!!))
392-
IRDataType.WORD -> registers.setUW(i.reg1!!, memory.getUW(i.address!!))
394+
IRDataType.BYTE -> {
395+
val value = memory.getUB(i.address!!)
396+
registers.setUB(i.reg1!!, value)
397+
statusZero = value==0.toUByte()
398+
statusNegative = value>=0x80u
399+
}
400+
IRDataType.WORD -> {
401+
val value = memory.getUW(i.address!!)
402+
registers.setUW(i.reg1!!, value)
403+
statusZero = value== 0.toUShort()
404+
statusNegative = value>=0x8000u
405+
}
393406
IRDataType.FLOAT -> registers.setFloat(i.fpReg1!!, memory.getFloat(i.address!!))
394407
}
395408
nextPc()
396409
}
397410

398411
private fun InsLOADI(i: IRInstruction) {
399412
when(i.type!!) {
400-
IRDataType.BYTE -> registers.setUB(i.reg1!!, memory.getUB(registers.getUW(i.reg2!!).toInt()))
401-
IRDataType.WORD -> registers.setUW(i.reg1!!, memory.getUW(registers.getUW(i.reg2!!).toInt()))
413+
IRDataType.BYTE -> {
414+
val value = memory.getUB(registers.getUW(i.reg2!!).toInt())
415+
registers.setUB(i.reg1!!, value)
416+
statusZero = value==0.toUByte()
417+
statusNegative = value>=0x80u
418+
}
419+
IRDataType.WORD -> {
420+
val value = memory.getUW(registers.getUW(i.reg2!!).toInt())
421+
registers.setUW(i.reg1!!, value)
422+
statusZero = value== 0.toUShort()
423+
statusNegative = value>=0x8000u
424+
}
402425
IRDataType.FLOAT -> registers.setFloat(i.fpReg1!!, memory.getFloat(registers.getUW(i.reg1!!).toInt()))
403426
}
404427
nextPc()
405428
}
406429

407430
private fun InsLOADX(i: IRInstruction) {
408431
when (i.type!!) {
409-
IRDataType.BYTE -> registers.setUB(i.reg1!!, memory.getUB(i.address!! + registers.getUW(i.reg2!!).toInt()))
410-
IRDataType.WORD -> registers.setUW(i.reg1!!, memory.getUW(i.address!! + registers.getUW(i.reg2!!).toInt()))
432+
IRDataType.BYTE -> {
433+
val value = memory.getUB(i.address!! + registers.getUW(i.reg2!!).toInt())
434+
registers.setUB(i.reg1!!, value)
435+
statusZero = value==0.toUByte()
436+
statusNegative = value>=0x80u
437+
}
438+
IRDataType.WORD -> {
439+
val value = memory.getUW(i.address!! + registers.getUW(i.reg2!!).toInt())
440+
registers.setUW(i.reg1!!, value)
441+
statusZero = value== 0.toUShort()
442+
statusNegative = value>=0x8000u
443+
}
411444
IRDataType.FLOAT -> registers.setFloat(i.fpReg1!!, memory.getFloat(i.address!! + registers.getUW(i.reg1!!).toInt()))
412445
}
413446
nextPc()
@@ -417,11 +450,17 @@ class VirtualMachine(irProgram: IRProgram) {
417450
when (i.type!!) {
418451
IRDataType.BYTE -> {
419452
val pointer = memory.getUW(i.address!!) + registers.getUB(i.reg2!!)
420-
registers.setUB(i.reg1!!, memory.getUB(pointer.toInt()))
453+
val value = memory.getUB(pointer.toInt())
454+
registers.setUB(i.reg1!!, value)
455+
statusZero = value==0.toUByte()
456+
statusNegative = value>=0x80u
421457
}
422458
IRDataType.WORD -> {
423459
val pointer = memory.getUW(i.address!!) + registers.getUB(i.reg2!!)
424-
registers.setUW(i.reg1!!, memory.getUW(pointer.toInt()))
460+
val value = memory.getUW(pointer.toInt())
461+
registers.setUW(i.reg1!!, value)
462+
statusZero = value== 0.toUShort()
463+
statusNegative = value>=0x8000u
425464
}
426465
IRDataType.FLOAT -> {
427466
val pointer = memory.getUW(i.address!!) + registers.getUB(i.reg1!!)
@@ -433,8 +472,18 @@ class VirtualMachine(irProgram: IRProgram) {
433472

434473
private fun InsLOADR(i: IRInstruction) {
435474
when(i.type!!) {
436-
IRDataType.BYTE -> registers.setUB(i.reg1!!, registers.getUB(i.reg2!!))
437-
IRDataType.WORD -> registers.setUW(i.reg1!!, registers.getUW(i.reg2!!))
475+
IRDataType.BYTE -> {
476+
val value = registers.getUB(i.reg2!!)
477+
registers.setUB(i.reg1!!, value)
478+
statusZero = value==0.toUByte()
479+
statusNegative = value>=0x80u
480+
}
481+
IRDataType.WORD -> {
482+
val value = registers.getUW(i.reg2!!)
483+
registers.setUW(i.reg1!!, value)
484+
statusZero = value== 0.toUShort()
485+
statusNegative = value>=0x8000u
486+
}
438487
IRDataType.FLOAT -> registers.setFloat(i.fpReg1!!, registers.getFloat(i.fpReg2!!))
439488
}
440489
nextPc()
@@ -842,8 +891,18 @@ class VirtualMachine(irProgram: IRProgram) {
842891

843892
private fun InsINC(i: IRInstruction) {
844893
when(i.type!!) {
845-
IRDataType.BYTE -> registers.setUB(i.reg1!!, (registers.getUB(i.reg1!!)+1u).toUByte())
846-
IRDataType.WORD -> registers.setUW(i.reg1!!, (registers.getUW(i.reg1!!)+1u).toUShort())
894+
IRDataType.BYTE -> {
895+
val value = (registers.getUB(i.reg1!!)+1u).toUByte()
896+
registers.setUB(i.reg1!!, value)
897+
statusZero = value==0.toUByte()
898+
statusNegative = value>=0x80u
899+
}
900+
IRDataType.WORD -> {
901+
val value = (registers.getUW(i.reg1!!)+1u).toUShort()
902+
registers.setUW(i.reg1!!, value)
903+
statusZero = value==0.toUShort()
904+
statusNegative = value>=0x8000u
905+
}
847906
IRDataType.FLOAT -> registers.setFloat(i.fpReg1!!, registers.getFloat(i.fpReg1!!)+1f)
848907
}
849908
nextPc()
@@ -852,26 +911,56 @@ class VirtualMachine(irProgram: IRProgram) {
852911
private fun InsINCM(i: IRInstruction) {
853912
val address = i.address!!
854913
when(i.type!!) {
855-
IRDataType.BYTE -> memory.setUB(address, (memory.getUB(address)+1u).toUByte())
856-
IRDataType.WORD -> memory.setUW(address, (memory.getUW(address)+1u).toUShort())
914+
IRDataType.BYTE -> {
915+
val value = (memory.getUB(address)+1u).toUByte()
916+
memory.setUB(address, value)
917+
statusZero = value==0.toUByte()
918+
statusNegative = value>=0x80u
919+
}
920+
IRDataType.WORD -> {
921+
val value = (memory.getUW(address)+1u).toUShort()
922+
memory.setUW(address, value)
923+
statusZero = value== 0.toUShort()
924+
statusNegative = value>=0x8000u
925+
}
857926
IRDataType.FLOAT -> memory.setFloat(address, memory.getFloat(address)+1f)
858927
}
859928
nextPc()
860929
}
861930

862931
private fun InsDEC(i: IRInstruction) {
863932
when(i.type!!) {
864-
IRDataType.BYTE -> registers.setUB(i.reg1!!, (registers.getUB(i.reg1!!)-1u).toUByte())
865-
IRDataType.WORD -> registers.setUW(i.reg1!!, (registers.getUW(i.reg1!!)-1u).toUShort())
933+
IRDataType.BYTE -> {
934+
val value = (registers.getUB(i.reg1!!)-1u).toUByte()
935+
registers.setUB(i.reg1!!, value)
936+
statusZero = value== 0.toUByte()
937+
statusNegative = value>=0x80u
938+
}
939+
IRDataType.WORD -> {
940+
val value = (registers.getUW(i.reg1!!)-1u).toUShort()
941+
registers.setUW(i.reg1!!, value)
942+
statusZero = value== 0.toUShort()
943+
statusNegative = value>=0x8000u
944+
}
866945
IRDataType.FLOAT -> registers.setFloat(i.fpReg1!!, registers.getFloat(i.fpReg1!!)-1f)
867946
}
868947
nextPc()
869948
}
870949

871950
private fun InsDECM(i: IRInstruction) {
872951
when(i.type!!) {
873-
IRDataType.BYTE -> memory.setUB(i.address!!, (memory.getUB(i.address!!)-1u).toUByte())
874-
IRDataType.WORD -> memory.setUW(i.address!!, (memory.getUW(i.address!!)-1u).toUShort())
952+
IRDataType.BYTE -> {
953+
val value = (memory.getUB(i.address!!)-1u).toUByte()
954+
memory.setUB(i.address!!, value)
955+
statusZero = value== 0.toUByte()
956+
statusNegative = value>=0x80u
957+
}
958+
IRDataType.WORD -> {
959+
val value = (memory.getUW(i.address!!)-1u).toUShort()
960+
memory.setUW(i.address!!, value)
961+
statusZero = value== 0.toUShort()
962+
statusNegative = value>=0x8000u
963+
}
875964
IRDataType.FLOAT -> memory.setFloat(i.address!!, memory.getFloat(i.address!!)-1f)
876965
}
877966
nextPc()

0 commit comments

Comments
 (0)