From 85b5fde272be6ab543aa866baebabddc24566bdb Mon Sep 17 00:00:00 2001 From: cheapie Date: Sat, 23 May 2026 20:14:34 -0500 Subject: Add initial content --- .gitignore | 3 + c/bfhello/Makefile | 20 + c/bfhello/bfhello.b | 1 + c/bfhello/bfhello.c | 91 + c/bfhello/bfhello.elf | Bin 0 -> 6508 bytes c/bfhello/bfhello.hex | 27 + c/bfhello/bfhello.o | Bin 0 -> 1856 bytes c/bfhello/rvcontroller.ld | 45 + c/bigfib/Makefile | 20 + c/bigfib/bigfib.c | 23 + c/bigfib/bigfib.elf | Bin 0 -> 6552 bytes c/bigfib/bigfib.hex | 19 + c/bigfib/bigfib.o | Bin 0 -> 2184 bytes c/bigfib/rvcontroller.ld | 45 + c/drawercalc/Makefile | 20 + c/drawercalc/drawercalc.c | 129 ++ c/drawercalc/drawercalc.elf | Bin 0 -> 7028 bytes c/drawercalc/drawercalc.hex | 56 + c/drawercalc/drawercalc.o | Bin 0 -> 5512 bytes c/drawercalc/rvcontroller.ld | 45 + c/elevator/Makefile | 20 + c/elevator/elevator.c | 230 +++ c/elevator/elevator.elf | Bin 0 -> 8748 bytes c/elevator/elevator.hex | 135 ++ c/elevator/elevator.o | Bin 0 -> 12580 bytes c/elevator/rvcontroller.ld | 45 + c/elevator/states.h | 14 + c/gol/Makefile | 20 + c/gol/gol.c | 89 + c/gol/gol.elf | Bin 0 -> 13812 bytes c/gol/gol.hex | 463 +++++ c/gol/gol.o | Bin 0 -> 13396 bytes c/gol/rvcontroller.ld | 45 + c/menu/Makefile | 44 + c/menu/calculator.c | 95 + c/menu/calculator.h | 6 + c/menu/calculator.o | Bin 0 -> 6432 bytes c/menu/digilines.c | 66 + c/menu/digilines.h | 6 + c/menu/digilines.o | Bin 0 -> 3800 bytes c/menu/games.c | 121 ++ c/menu/games.h | 6 + c/menu/games.o | Bin 0 -> 7412 bytes c/menu/menu.c | 74 + c/menu/menu.elf | Bin 0 -> 13056 bytes c/menu/menu.hex | 377 ++++ c/menu/menu.o | Bin 0 -> 4704 bytes c/menu/rvcontroller.ld | 45 + c/menu/screensaver.c | 137 ++ c/menu/screensaver.h | 6 + c/menu/screensaver.o | Bin 0 -> 7492 bytes c/rrxing/Makefile | 20 + c/rrxing/rrxing.c | 86 + c/rrxing/rrxing.elf | Bin 0 -> 7292 bytes c/rrxing/rrxing.hex | 70 + c/rrxing/rrxing.o | Bin 0 -> 7340 bytes c/rrxing/rvcontroller.ld | 45 + c/rvcontroller-libraries/Makefile | 10 + c/rvcontroller-libraries/rvcontroller-ecalls.S | 108 + c/rvcontroller-libraries/rvcontroller-ecalls.h | 108 + c/rvcontroller-libraries/rvcontroller-ecalls.o | Bin 0 -> 1292 bytes c/rvcontroller-libraries/rvcontroller-init.S | 26 + c/rvcontroller-libraries/rvcontroller-init.o | Bin 0 -> 916 bytes c/squares/Makefile | 20 + c/squares/rvcontroller.ld | 45 + c/squares/squares.b | 8 + c/squares/squares.c | 169 ++ c/squares/squares.elf | Bin 0 -> 6752 bytes c/squares/squares.hex | 42 + c/squares/squares.o | Bin 0 -> 2336 bytes cross-links | 3 + cross-toolchain/activate.sh | 6 + fib.S | 29 + guessnum-random.S | 126 ++ guessnum.S | 119 ++ hello.S | 6 + loader.lua | 83 + misa.S | 112 + rrxing.S | 198 ++ rvcontroller.ld | 45 + rvcontroller.lua | 2604 ++++++++++++++++++++++++ 81 files changed, 6676 insertions(+) create mode 100644 .gitignore create mode 100644 c/bfhello/Makefile create mode 100644 c/bfhello/bfhello.b create mode 100644 c/bfhello/bfhello.c create mode 100755 c/bfhello/bfhello.elf create mode 100644 c/bfhello/bfhello.hex create mode 100644 c/bfhello/bfhello.o create mode 100644 c/bfhello/rvcontroller.ld create mode 100644 c/bigfib/Makefile create mode 100644 c/bigfib/bigfib.c create mode 100755 c/bigfib/bigfib.elf create mode 100644 c/bigfib/bigfib.hex create mode 100644 c/bigfib/bigfib.o create mode 100644 c/bigfib/rvcontroller.ld create mode 100644 c/drawercalc/Makefile create mode 100644 c/drawercalc/drawercalc.c create mode 100755 c/drawercalc/drawercalc.elf create mode 100644 c/drawercalc/drawercalc.hex create mode 100644 c/drawercalc/drawercalc.o create mode 100644 c/drawercalc/rvcontroller.ld create mode 100644 c/elevator/Makefile create mode 100644 c/elevator/elevator.c create mode 100755 c/elevator/elevator.elf create mode 100644 c/elevator/elevator.hex create mode 100644 c/elevator/elevator.o create mode 100644 c/elevator/rvcontroller.ld create mode 100644 c/elevator/states.h create mode 100644 c/gol/Makefile create mode 100644 c/gol/gol.c create mode 100755 c/gol/gol.elf create mode 100644 c/gol/gol.hex create mode 100644 c/gol/gol.o create mode 100644 c/gol/rvcontroller.ld create mode 100644 c/menu/Makefile create mode 100644 c/menu/calculator.c create mode 100644 c/menu/calculator.h create mode 100644 c/menu/calculator.o create mode 100644 c/menu/digilines.c create mode 100644 c/menu/digilines.h create mode 100644 c/menu/digilines.o create mode 100644 c/menu/games.c create mode 100644 c/menu/games.h create mode 100644 c/menu/games.o create mode 100644 c/menu/menu.c create mode 100755 c/menu/menu.elf create mode 100644 c/menu/menu.hex create mode 100644 c/menu/menu.o create mode 100644 c/menu/rvcontroller.ld create mode 100644 c/menu/screensaver.c create mode 100644 c/menu/screensaver.h create mode 100644 c/menu/screensaver.o create mode 100644 c/rrxing/Makefile create mode 100644 c/rrxing/rrxing.c create mode 100755 c/rrxing/rrxing.elf create mode 100644 c/rrxing/rrxing.hex create mode 100644 c/rrxing/rrxing.o create mode 100644 c/rrxing/rvcontroller.ld create mode 100644 c/rvcontroller-libraries/Makefile create mode 100644 c/rvcontroller-libraries/rvcontroller-ecalls.S create mode 100644 c/rvcontroller-libraries/rvcontroller-ecalls.h create mode 100644 c/rvcontroller-libraries/rvcontroller-ecalls.o create mode 100644 c/rvcontroller-libraries/rvcontroller-init.S create mode 100644 c/rvcontroller-libraries/rvcontroller-init.o create mode 100644 c/squares/Makefile create mode 100644 c/squares/rvcontroller.ld create mode 100644 c/squares/squares.b create mode 100644 c/squares/squares.c create mode 100755 c/squares/squares.elf create mode 100644 c/squares/squares.hex create mode 100644 c/squares/squares.o create mode 100644 cross-links create mode 100755 cross-toolchain/activate.sh create mode 100644 fib.S create mode 100644 guessnum-random.S create mode 100644 guessnum.S create mode 100644 hello.S create mode 100644 loader.lua create mode 100644 misa.S create mode 100644 rrxing.S create mode 100644 rvcontroller.ld create mode 100644 rvcontroller.lua diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..bedf027 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +cross-toolchain/build/* +cross-toolchain/source/* +cross-toolchain/install/* diff --git a/c/bfhello/Makefile b/c/bfhello/Makefile new file mode 100644 index 0000000..fa163ed --- /dev/null +++ b/c/bfhello/Makefile @@ -0,0 +1,20 @@ +all: bfhello.hex + +bfhello.o: bfhello.c + clang -target riscv32-none-elf -I../rvcontroller-libraries -march=rv32imacb_zicntr_zicond_zicsr_zifencei_zihintpause_zilsd_zclsd_zabha_zacas_zbkb_zbkx_zcb_zcmp_zcmt -ffreestanding -O3 -c -o bfhello.o bfhello.c + +bfhello.elf: ../rvcontroller-libraries/rvcontroller-init.o ../rvcontroller-libraries/rvcontroller-ecalls.o bfhello.o + riscv32-none-elf-ld -T rvcontroller.ld --no-warn-rwx-segments -o bfhello.elf ../rvcontroller-libraries/rvcontroller-init.o bfhello.o ../rvcontroller-libraries/rvcontroller-ecalls.o + +dump: bfhello.elf + riscv32-none-elf-objdump -d bfhello.elf + +bfhello.hex: bfhello.elf + riscv32-none-elf-objcopy -O ihex bfhello.elf bfhello.hex + +load: bfhello.hex + bash -c "wl-copy < bfhello.hex" + +clean: + rm -f bfhello.bin bfhello.elf bfhello.o init.o + diff --git a/c/bfhello/bfhello.b b/c/bfhello/bfhello.b new file mode 100644 index 0000000..8e5e5a6 --- /dev/null +++ b/c/bfhello/bfhello.b @@ -0,0 +1 @@ +++++++++[>+++++++++<-]>.+++++++++++++++++++++++++++++.+++++++..+++.>++++[>++++++++<-]>.>+++++[<+++++++++++>-]<.>++++[<++++++>-]<.+++.------.--------.>+++[>+++++++++++<-]>.>++++++++++. diff --git a/c/bfhello/bfhello.c b/c/bfhello/bfhello.c new file mode 100644 index 0000000..95d2209 --- /dev/null +++ b/c/bfhello/bfhello.c @@ -0,0 +1,91 @@ +/* This is a translation of bfhello.b, generated by bftoc.py (by Paul Kaefer) + * It was generated on Sunday, May 17, 2026 at 12:17AM + */ + +#include "rvcontroller-ecalls.h" + +void main(void) +{ + int size = 1000; + int tape[size]; + int i = 0; + + /* Clearing the tape (array) */ + for (i=0; i RAM + .data : + { + *(.sbss) + *(.data) + *(.bss) + *(.rela*) + *(COMMON) + } > RAM + + .heap : + { + . = ALIGN(4); + PROVIDE ( end = . ); + _sheap = .; + . = . + __heap_size; + . = ALIGN(4); + _eheap = .; + } >RAM + + .stack : + { + . = ALIGN(4); + _estack = .; + . = . + __stack_size; + . = ALIGN(4); + _sstack = .; + } >RAM + } diff --git a/c/bigfib/Makefile b/c/bigfib/Makefile new file mode 100644 index 0000000..6eb4ffc --- /dev/null +++ b/c/bigfib/Makefile @@ -0,0 +1,20 @@ +all: bigfib.hex + +bigfib.o: bigfib.c + clang -target riscv32-none-elf -I../rvcontroller-libraries -march=rv32imacb_zicntr_zicond_zicsr_zifencei_zihintpause_zilsd_zclsd_zabha_zacas_zbkb_zbkx_zcb_zcmp_zcmt -ffreestanding -O3 -c -o bigfib.o bigfib.c + +bigfib.elf: ../rvcontroller-libraries/rvcontroller-init.o ../rvcontroller-libraries/rvcontroller-ecalls.o bigfib.o + riscv32-none-elf-ld -T rvcontroller.ld --no-warn-rwx-segments -o bigfib.elf ../rvcontroller-libraries/rvcontroller-init.o bigfib.o ../rvcontroller-libraries/rvcontroller-ecalls.o + +dump: bigfib.elf + riscv32-none-elf-objdump -d bigfib.elf + +bigfib.hex: bigfib.elf + riscv32-none-elf-objcopy -O ihex bigfib.elf bigfib.hex + +load: bigfib.hex + bash -c "wl-copy < bigfib.hex" + +clean: + rm -f bigfib.bin bigfib.elf bigfib.o init.o + diff --git a/c/bigfib/bigfib.c b/c/bigfib/bigfib.c new file mode 100644 index 0000000..063c27e --- /dev/null +++ b/c/bigfib/bigfib.c @@ -0,0 +1,23 @@ +/* Fibonacci Sequence for RVController + * A product of Advanced Mesecons Devices, a Cheapie Systems company + * This is free and unencumbered software released into the public domain. + * See http://unlicense.org/ for more information */ + +#include +#include "rvcontroller-ecalls.h" + +uint64_t prev = 0; +uint64_t oldprev = 0; +uint64_t curr = 1; + +void main(void) { + while ((curr & 0x800000000000000) == 0 ) { + printstr("\nH "); + printint(curr/(1LL << 32)); + printstr("\nL "); + printint(curr%(1LL << 32)); + oldprev = prev; + prev = curr; + curr = prev + oldprev; + } +} diff --git a/c/bigfib/bigfib.elf b/c/bigfib/bigfib.elf new file mode 100755 index 0000000..2fcdf75 Binary files /dev/null and b/c/bigfib/bigfib.elf differ diff --git a/c/bigfib/bigfib.hex b/c/bigfib/bigfib.hex new file mode 100644 index 0000000..b13c263 --- /dev/null +++ b/c/bigfib/bigfib.hex @@ -0,0 +1,19 @@ +:10000000370101002920A94873000000828096B8BA +:1000100022E44AE003457010218939E1B70900085C +:100020001309400F130A800F930480104A85812022 +:10003000032540100D2852851D280325001025207A +:1000400003350010906088E090E4B6952A96333529 +:10005000A600B386A50033F536012330C01079D54C +:100060002264026996BE8548730000008280914830 +:10007000730000008280AD48730000008280930806 +:10008000100873000000828093085008730000007D +:10009000828093087008730000008280732510C06E +:1000A0008280732500C0828093086008730000007E +:1000B00082800589F322008093920248B3E2A20075 +:1000C00073900280828095487300000082809308BC +:1000D0000008730000008280A14873000000828045 +:1000E0009308300873000000828093084008730072 +:0C00F000000082800A4820000A4C20001A +:1001000001000000000000000000000000000000EE +:080110000000000000000000E7 +:00000001FF diff --git a/c/bigfib/bigfib.o b/c/bigfib/bigfib.o new file mode 100644 index 0000000..32d9e29 Binary files /dev/null and b/c/bigfib/bigfib.o differ diff --git a/c/bigfib/rvcontroller.ld b/c/bigfib/rvcontroller.ld new file mode 100644 index 0000000..985892b --- /dev/null +++ b/c/bigfib/rvcontroller.ld @@ -0,0 +1,45 @@ +/* Thanks https://github.com/darklife/darkriscv */ + __heap_size = 0x200; /* required amount of heap */ + __stack_size = 0x800; /* required amount of stack */ + ENTRY(_start); + MEMORY + { + RAM (rwx) : ORIGIN = 0x00000000, LENGTH = 0x10000 + } + SECTIONS + { + .text : + { + *(.text.startup) + *(.text) + *(.text) + *(.rodata*) + } > RAM + .data : + { + *(.sbss) + *(.data) + *(.bss) + *(.rela*) + *(COMMON) + } > RAM + + .heap : + { + . = ALIGN(4); + PROVIDE ( end = . ); + _sheap = .; + . = . + __heap_size; + . = ALIGN(4); + _eheap = .; + } >RAM + + .stack : + { + . = ALIGN(4); + _estack = .; + . = . + __stack_size; + . = ALIGN(4); + _sstack = .; + } >RAM + } diff --git a/c/drawercalc/Makefile b/c/drawercalc/Makefile new file mode 100644 index 0000000..52f47d1 --- /dev/null +++ b/c/drawercalc/Makefile @@ -0,0 +1,20 @@ +all: drawercalc.hex + +drawercalc.o: drawercalc.c + clang -target riscv32-none-elf -I../rvcontroller-libraries -march=rv32imacb_zicntr_zicond_zicsr_zifencei_zihintpause_zilsd_zclsd_zabha_zacas_zbkb_zbkx_zcb_zcmp_zcmt -ffreestanding -O3 -c -o drawercalc.o drawercalc.c + +drawercalc.elf: ../rvcontroller-libraries/rvcontroller-init.o ../rvcontroller-libraries/rvcontroller-ecalls.o drawercalc.o + riscv32-none-elf-ld -T rvcontroller.ld --no-warn-rwx-segments -o drawercalc.elf ../rvcontroller-libraries/rvcontroller-init.o drawercalc.o ../rvcontroller-libraries/rvcontroller-ecalls.o + +dump: drawercalc.elf + riscv32-none-elf-objdump -d drawercalc.elf + +drawercalc.hex: drawercalc.elf + riscv32-none-elf-objcopy -O ihex drawercalc.elf drawercalc.hex + +load: drawercalc.hex + bash -c "wl-copy < drawercalc.hex" + +clean: + rm -f drawercalc.bin drawercalc.elf drawercalc.o init.o + diff --git a/c/drawercalc/drawercalc.c b/c/drawercalc/drawercalc.c new file mode 100644 index 0000000..1d2de03 --- /dev/null +++ b/c/drawercalc/drawercalc.c @@ -0,0 +1,129 @@ +/* Drawer Capacity Calculator for RVController + * A product of Advanced Mesecons Devices, a Cheapie Systems company + * This is free and unencumbered software released into the public domain. + * See http://unlicense.org/ for more information */ + +#include +#include +#include "rvcontroller-ecalls.h" + +#define BASE_SLOTS 32 +#define STACK_MAX 99 +#define STEEL_UPGRADE_MULT 1 +#define GOLD_UPGRADE_MULT 2 +#define OBSIDIAN_UPGRADE_MULT 3 +#define DIAMOND_UPGRADE_MULT 7 +#define MITHRIL_UPGRADE_MULT 12 + +bool checkUpgradeCount(int32_t count,int32_t maxcount) { + return (count >= 0 && count <= maxcount); +} + +void main(void) { + while (true) { + int32_t capacity = BASE_SLOTS * STACK_MAX; + uint8_t upgrades_used = 0; + printstr("\n\n\nSettings:\n"); + printstr("Base Stack Count: "); + printint(BASE_SLOTS); + printstr("\nMax Stack Size: "); + printint(STACK_MAX); + printchar('\n'); + + int32_t upgcount = 0; + while (true) { + printstr("\nSteel Upgrades?\n[0-5] > "); + upgcount = readint(); + printint(upgcount); + printchar('\n'); + if (checkUpgradeCount(upgcount,5)) { + break; + } else { + printstr("Invalid entry"); + } + } + upgrades_used += upgcount; + capacity += BASE_SLOTS * STACK_MAX * STEEL_UPGRADE_MULT * upgcount; + + if (upgrades_used < 5) { + while (true) { + printstr("\nGold Upgrades?\n[0-"); + printint(5-upgrades_used); + printstr("] > "); + upgcount = readint(); + printint(upgcount); + printchar('\n'); + if (checkUpgradeCount(upgcount,5-upgrades_used)) { + break; + } else { + printstr("Invalid entry"); + } + } + upgrades_used += upgcount; + capacity += BASE_SLOTS * STACK_MAX * GOLD_UPGRADE_MULT * upgcount; + } + + if (upgrades_used < 5) { + while (true) { + printstr("\nObsidian Upgrades?\n[0-"); + printint(5-upgrades_used); + printstr("] > "); + upgcount = readint(); + printint(upgcount); + printchar('\n'); + if (checkUpgradeCount(upgcount,5-upgrades_used)) { + break; + } else { + printstr("Invalid entry"); + } + } + upgrades_used += upgcount; + capacity += BASE_SLOTS * STACK_MAX * OBSIDIAN_UPGRADE_MULT * upgcount; + } + + if (upgrades_used < 5) { + while (true) { + printstr("\nDiamond Upgrades?\n[0-"); + printint(5-upgrades_used); + printstr("] > "); + upgcount = readint(); + printint(upgcount); + printchar('\n'); + if (checkUpgradeCount(upgcount,5-upgrades_used)) { + break; + } else { + printstr("Invalid entry"); + } + } + upgrades_used += upgcount; + capacity += BASE_SLOTS * STACK_MAX * DIAMOND_UPGRADE_MULT * upgcount; + } + + if (upgrades_used < 5) { + while (true) { + printstr("\nMithril Upgrades?\n[0-"); + printint(5-upgrades_used); + printstr("] > "); + upgcount = readint(); + printint(upgcount); + printchar('\n'); + if (checkUpgradeCount(upgcount,5-upgrades_used)) { + break; + } else { + printstr("Invalid entry"); + } + } + upgrades_used += upgcount; + capacity += BASE_SLOTS * STACK_MAX * MITHRIL_UPGRADE_MULT * upgcount; + } + + printstr("\n1 slot: "); + printint(capacity); + printstr("\n2 slots: "); + printint(capacity/2); + printstr("\n4 slots: "); + printint(capacity/4); + printstr("\nPress 0 to run again\n"); + upgcount = readint(); + } +} diff --git a/c/drawercalc/drawercalc.elf b/c/drawercalc/drawercalc.elf new file mode 100755 index 0000000..be34b55 Binary files /dev/null and b/c/drawercalc/drawercalc.elf differ diff --git a/c/drawercalc/drawercalc.hex b/c/drawercalc/drawercalc.hex new file mode 100644 index 0000000..b66fc63 --- /dev/null +++ b/c/drawercalc/drawercalc.hex @@ -0,0 +1,56 @@ +:10000000370101002928A948730000008280135697 +:10001000F50133A5A500518D1345150082804EB81A +:100020000111A2E4CAE052FC5AF862F46AF00565D4 +:100030001309C0279304A0281304D029930BF02A96 +:10004000194B9549930C702D130D402C130C902CCB +:100050008965930DB02E1566A566130505C62ACED3 +:100060001385058C2ACC138505522ACA1305066A06 +:100070002AC8138506482AC63DA83245419D2A9ABA +:100080005A899304A0281304D029194B130510335F +:100090009D225285A92A1305B033B12A13551A009F +:1000A000B92213056034812A13552A0089221305C9 +:1000B00010359122692A4A853D2A26852D2A130565 +:1000C000000235222285052A130530060D22294516 +:1000D0003D225E850D22A52AAA8A112A29450522DC +:1000E00063ED6A016285012A5E8531228D22AA8A2A +:1000F000FD2829452922E3E759FF7245338AAA02E0 +:100100002A9AE3853AF96685FD20338B59415A8551 +:10011000F9286A85CD20252AAA84D1282945C52019 +:1001200063779B006285C1286685F120CDB7A69ACA +:100130006245459D2A9A1145E36555F54A8B6E85C2 +:100140005D28B384594126855D206A856D20012292 +:100150002A847128294565201309303063F184020F +:10016000628551286E854128268551206A85612047 +:10017000F9282A84AD2829455920E3E384FEA29A70 +:100180005245419D2A9A1145E36C55EF4A85A520B9 +:10019000B38459412685A1286A85B1284D282A842F +:1001A000B9202945A92863F784006285A9204A85DA +:1001B0009920CDB7A29A4245419D2A9A1145E36103 +:1001C00055ED1309A0314A853D20B3845941268558 +:1001D00039286A850D20A5282A841128294505205B +:1001E000E3FD84E8628501284A853120CDB7854842 +:1001F0007300000082809148730000008280AD4847 +:100200007300000082809308100873000000828051 +:1002100093085008730000008280930870087300F0 +:1002200000008280732510C08280732500C0828008 +:10023000930860087300000082800589F322008023 +:1002400093920248B3E2A2007390028082809548A4 +:100250007300000082809308000873000000828011 +:10026000A1487300000082809308300873000000EA +:100270008280930840087300000082800A0A0A53B3 +:10028000657474696E67733A0A004261736520533E +:100290007461636B20436F756E743A20000A4D6180 +:1002A0007820537461636B2053697A653A20000AA1 +:1002B000537465656C2055706772616465733F0A9D +:1002C0005B302D355D203E2000496E76616C69649F +:1002D00020656E747279000A476F6C6420557067F0 +:1002E00072616465733F0A5B302D000A4F62736967 +:1002F0006469616E2055706772616465733F0A5B63 +:10030000302D000A4469616D6F6E6420557067720C +:10031000616465733F0A5B302D000A4D6974687231 +:10032000696C2055706772616465733F0A5B302D9C +:10033000000A3120736C6F743A20000A3220736C0B +:100340006F74733A20000A3420736C6F74733A2010 +:10035000000A5072657373203020746F2072756EBE +:0803600020616761696E0A006B +:00000001FF diff --git a/c/drawercalc/drawercalc.o b/c/drawercalc/drawercalc.o new file mode 100644 index 0000000..fac534a Binary files /dev/null and b/c/drawercalc/drawercalc.o differ diff --git a/c/drawercalc/rvcontroller.ld b/c/drawercalc/rvcontroller.ld new file mode 100644 index 0000000..985892b --- /dev/null +++ b/c/drawercalc/rvcontroller.ld @@ -0,0 +1,45 @@ +/* Thanks https://github.com/darklife/darkriscv */ + __heap_size = 0x200; /* required amount of heap */ + __stack_size = 0x800; /* required amount of stack */ + ENTRY(_start); + MEMORY + { + RAM (rwx) : ORIGIN = 0x00000000, LENGTH = 0x10000 + } + SECTIONS + { + .text : + { + *(.text.startup) + *(.text) + *(.text) + *(.rodata*) + } > RAM + .data : + { + *(.sbss) + *(.data) + *(.bss) + *(.rela*) + *(COMMON) + } > RAM + + .heap : + { + . = ALIGN(4); + PROVIDE ( end = . ); + _sheap = .; + . = . + __heap_size; + . = ALIGN(4); + _eheap = .; + } >RAM + + .stack : + { + . = ALIGN(4); + _estack = .; + . = . + __stack_size; + . = ALIGN(4); + _sstack = .; + } >RAM + } diff --git a/c/elevator/Makefile b/c/elevator/Makefile new file mode 100644 index 0000000..875cd3b --- /dev/null +++ b/c/elevator/Makefile @@ -0,0 +1,20 @@ +all: elevator.hex + +elevator.o: elevator.c + clang -target riscv32-none-elf -I../rvcontroller-libraries -march=rv32imacb_zicntr_zicond_zicsr_zifencei_zihintpause_zilsd_zclsd_zabha_zacas_zbkb_zbkx_zcb_zcmp_zcmt -ffreestanding -O3 -c -o elevator.o elevator.c + +elevator.elf: ../rvcontroller-libraries/rvcontroller-init.o ../rvcontroller-libraries/rvcontroller-ecalls.o elevator.o + riscv32-none-elf-ld -T rvcontroller.ld --no-warn-rwx-segments -o elevator.elf ../rvcontroller-libraries/rvcontroller-init.o elevator.o ../rvcontroller-libraries/rvcontroller-ecalls.o + +dump: elevator.elf + riscv32-none-elf-objdump -d elevator.elf + +elevator.hex: elevator.elf + riscv32-none-elf-objcopy -O ihex elevator.elf elevator.hex + +load: elevator.hex + bash -c "wl-copy < elevator.hex" + +clean: + rm -f elevator.bin elevator.elf elevator.o init.o + diff --git a/c/elevator/elevator.c b/c/elevator/elevator.c new file mode 100644 index 0000000..845a57e --- /dev/null +++ b/c/elevator/elevator.c @@ -0,0 +1,230 @@ +/* Conway's Game of Life for RVController + * A product of Advanced Mesecons Devices, a Cheapie Systems company + * This is free and unencumbered software released into the public domain. + * See http://unlicense.org/ for more information */ + +#include +#include +#include "rvcontroller-ecalls.h" +#include "states.h" + +int state = STATE_INIT; +bool sensor1state = false; +bool sensor2state = false; +bool sensor3state = false; +bool call1state = false; +bool call2state = false; +bool call3state = false; +int direction = DIRECTION_UP; +int timer; + +char channelbuf[16]; +char msgbuf[64]; + +bool streq(char *a, char *b) { + for (int i=0;a[i] != 0 || b[i] != 0;i++) { + if (a[i] != b[i]) { + return false; + } + } + return true; +} + +void sleep(uint32_t delay) { + //This will start having problems after about 130 years + //of uptime, but that's probably acceptable + uint32_t endtime = rdtime() + delay; + while (rdtime() < endtime) {} + return; +} + +void sendSensorGetMessages(void) { + digiline_send("sensor1","GET"); + digiline_send("sensor2","GET"); + digiline_send("sensor3","GET"); +} + +void processDigilinesMessages(void) { + while (digiline_bufferlevel() > 0) { + digiline_receive(channelbuf,16,msgbuf,64); + if (streq(channelbuf,"sensor1")) { + sensor1state = (streq(msgbuf,"mesecons_movestones:movestone_vertical")); + } else if (streq(channelbuf,"sensor2")) { + sensor2state = (streq(msgbuf,"mesecons_movestones:movestone_vertical")); + } else if (streq(channelbuf,"sensor3")) { + sensor3state = (streq(msgbuf,"mesecons_movestones:movestone_vertical")); + } else if (streq(channelbuf,"button1") && (state != STATE_TIMING_1) && (state != STATE_IDLE_1)) { + call1state = true; + digiline_send("button1","light_on"); + } else if (streq(channelbuf,"button2") && (state != STATE_TIMING_2) && (state != STATE_IDLE_2)) { + call2state = true; + digiline_send("button2","light_on"); + } else if (streq(channelbuf,"button3") && (state != STATE_TIMING_3) && (state != STATE_IDLE_3)) { + call3state = true; + digiline_send("button3","light_on"); + } + } +} + +void main(void) { + while (true) { + sendSensorGetMessages(); + processDigilinesMessages(); + switch (state) { + case STATE_INIT: + printstr("\nElevator Controller\nfor RVController\nInitializing"); + digiline_send("door1","extend"); + digiline_send("door2","extend"); + digiline_send("door3","extend"); + digiline_send("sel","extend"); + digiline_send("down","extend"); + digiline_send("up","retract_sticky"); + digiline_send("button1","light_off"); + digiline_send("button2","light_off"); + digiline_send("button3","light_off"); + printstr("\nBottom Floor Demand"); + state = STATE_BOTTOM_FLOOR_DEMAND; + break; + case STATE_BOTTOM_FLOOR_DEMAND: + if (sensor1state) { + printstr("\nBFD Complete"); + digiline_send("down","retract_sticky"); + digiline_send("door1","retract_sticky"); + state = STATE_TIMING_1; + timer = 5; + } + break; + case STATE_TIMING_1: + timer--; + if (timer <= 0) { + printstr("\nIdle at 1"); + state = STATE_IDLE_1; + } + break; + case STATE_TIMING_2: + timer--; + if (timer <= 0) { + printstr("\nIdle at 2"); + state = STATE_IDLE_2; + } + break; + case STATE_TIMING_3: + timer--; + if (timer <= 0) { + printstr("\nIdle at 3"); + state = STATE_IDLE_3; + } + break; + case STATE_IDLE_1: + if (call2state) { + direction = DIRECTION_UP; + printstr("\nMoving to 2"); + state = STATE_MOVING_2; + digiline_send("door1","extend"); + digiline_send("sel","retract_sticky"); + digiline_send("up","extend"); + } else if (call3state) { + direction = DIRECTION_UP; + printstr("\nMoving to 3"); + state = STATE_MOVING_3; + digiline_send("door1","extend"); + digiline_send("sel","extend"); + digiline_send("up","extend"); + } + break; + case STATE_IDLE_2: + if (direction == DIRECTION_UP) { + if (call3state) { + direction = DIRECTION_UP; + printstr("\nMoving to 3"); + state = STATE_MOVING_3; + digiline_send("door2","extend"); + digiline_send("sel","extend"); + digiline_send("up","extend"); + } else if (call1state) { + direction = DIRECTION_DOWN; + printstr("\nMoving to 1"); + state = STATE_MOVING_1; + digiline_send("door2","extend"); + digiline_send("sel","extend"); + digiline_send("down","extend"); + } + } else { + if (call1state) { + direction = DIRECTION_DOWN; + printstr("\nMoving to 1"); + state = STATE_MOVING_1; + digiline_send("door2","extend"); + digiline_send("sel","extend"); + digiline_send("down","extend"); + } else if (call3state) { + direction = DIRECTION_UP; + printstr("\nMoving to 3"); + state = STATE_MOVING_3; + digiline_send("door2","extend"); + digiline_send("sel","extend"); + digiline_send("up","extend"); + } + } + break; + case STATE_IDLE_3: + if (call2state) { + direction = DIRECTION_DOWN; + printstr("\nMoving to 2"); + state = STATE_MOVING_2; + digiline_send("door3","extend"); + digiline_send("sel","retract_sticky"); + digiline_send("down","extend"); + } else if (call1state) { + direction = DIRECTION_DOWN; + printstr("\nMoving to 1"); + state = STATE_MOVING_1; + digiline_send("door3","extend"); + digiline_send("sel","extend"); + digiline_send("down","extend"); + } + break; + case STATE_MOVING_1: + if (sensor1state) { + printstr("\nArrived at 1"); + digiline_send("button1","light_off"); + direction = DIRECTION_UP; + digiline_send("down","retract_sticky"); + digiline_send("door1","retract_sticky"); + timer = 5; + state = STATE_TIMING_1; + call1state = false; + } + break; + case STATE_MOVING_2: + if (sensor2state) { + printstr("\nArrived at 2"); + digiline_send("button2","light_off"); + digiline_send("up","retract_sticky"); + digiline_send("down","retract_sticky"); + digiline_send("door2","retract_sticky"); + timer = 5; + state = STATE_TIMING_2; + call2state = false; + } + break; + case STATE_MOVING_3: + if (sensor3state) { + printstr("\nArrived at 3"); + digiline_send("button3","light_off"); + direction = DIRECTION_DOWN; + digiline_send("up","retract_sticky"); + digiline_send("door3","retract_sticky"); + timer = 5; + state = STATE_TIMING_3; + call3state = false; + } + break; + } + if ((state == STATE_IDLE_1) || (state == STATE_IDLE_2) || (state == STATE_IDLE_3)) { + lightweight_mode(1); + sleep(1); + lightweight_mode(0); + } + } +} diff --git a/c/elevator/elevator.elf b/c/elevator/elevator.elf new file mode 100755 index 0000000..9b5cafc Binary files /dev/null and b/c/elevator/elevator.elf differ diff --git a/c/elevator/elevator.hex b/c/elevator/elevator.hex new file mode 100644 index 0000000..2da4185 --- /dev/null +++ b/c/elevator/elevator.hex @@ -0,0 +1,135 @@ +:10000000370101008124A948730000008280148117 +:10001000988133E6E60009C685050505E389E6FE15 +:1000200013351600828052B82A84C92B2A94F923EA +:10003000E36F85FE52BE46B822E422E00145130577 +:100040000068014413048068A285512B0145130503 +:10005000C068A2856923014513054069A285226411 +:10006000026446BAADAB4EB822F44AF052EC5AE8FC +:1000700062E46AE0952B6300051C014B130BC07E04 +:10008000814B930B0068014C130CC069814C014DEE +:10009000130DC068814D930D4069814A930A306CFD +:1000A0000949014A130A406D81499309C06D9304BF +:1000B0004B0113044B0201A813B516002306A07EC2 +:1000C0002523630A0516C14593060004268522866A +:1000D0000D23FEAC1D4614813367D6003DC39881C5 +:1000E0007D1685050505E388E6FE1D45A6856A861D +:1000F00094813367D5002DC718827D1505068505C7 +:10010000E388E6FE13054B019D456E86148133E7B7 +:10011000D50035CB1882FD1505060505E388E6FEFA +:1001200013054B019D455686148133E7D50041C325 +:100130001882FD1505060505E388E6FE03258B00FC +:10014000B5A813056002A28562869881B366E500B2 +:10015000A5D61C827D1505068505E308F7FEA9BF17 +:1001600013056002A28562869881B366E50099C690 +:100170001C827D1505068505E308F7FE13B51600FC +:10018000A306A07E35BF13054B029305600262866D +:100190001881B3E6E50099C61C82FD150506050524 +:1001A000E308F7FE13B516002307A07E11BF032551 +:1001B0008B006305250195456311B50693054B0139 +:1001C0001D46D2869881B367E60081CB9C827D165E +:1001D00085068505E308F7FE39A099456305B50056 +:1001E0008D456311B50493054B011D46CE8698815C +:1001F000B367E60081CB9C827D1685068505E30802 +:10020000F7FE7DBD9145E30DB5EA9D45E30AB5EAEC +:100210000545A302AB004E8511A80545A307A07EA6 +:10022000568529A005452302AB00528581459305DB +:10023000B06C752671B522740279626A426B226CC9 +:10024000026D4EBE4EB822F44AF052EC5AE862E417 +:100250006AE0014913090068814493048068814978 +:100260009309C068814C930C4069014C130CC07E0B +:10027000A94A894D0544014D130D4065014B130BEF +:10028000D071014A130AC07366AD912EE6AD812E7E +:100290006685A685A926C13B03258C0063E5AA30A7 +:1002A0003345A5210841028501451305406E052609 +:1002B000014513057071DA851D260145130540724D +:1002C000DA85312E01451305A072DA85092E014524 +:1002D00013050073DA852126014513054073DA857D +:1002E000FD2C014513059073D285D52C01451305CE +:1002F000306C01441304B074A285D5240145130564 +:10030000406DA285E92C01451305C06DA285054409 +:10031000F9240145130550755D2C23248C0061A43C +:1003200003250C019305F5FF2328BC00634DA4268B +:1003300001451305E078612C1D452324AC00A5A4DC +:1003400001450345D07E6300052601451305E07C89 +:10035000BD2C01451305406D81459305B0744124C2 +:10036000014513059073D2859D2C014513054073FB +:10037000D285B524014513054072D2858D24230210 +:100380000C000D4535A203250C019305F5FF23282C +:10039000BC00634AA4200145130580770D2C154548 +:1003A0002324AC0009A403250C019305F5FF2328A1 +:1003B000BC00634AA41E014513053078092C194579 +:1003C0002324AC00CDA203454C000589630A051225 +:1003D00023268C00014513059079D52A2545232431 +:1003E000AC0001451305A072DA85D52A0145130535 +:1003F0000073D2855DA201450345C07E0589630473 +:10040000051A01451305A076D9220145130540734D +:10041000D285F122014513057071D285C922D9A870 +:1004200003454C000589630E050E23260C0001458B +:1004300013059079692A25452324AC00014513054D +:100440007071DA85692A014513050073D28519AAEE +:100450000325CC006306050E01450345F07E631CB1 +:10046000051003455C006300051423260C00E1A879 +:1004700001450345E07E0589630705120145130523 +:10048000C07DB12201451305C06D81459305B0744F +:10049000B92223268C00014513059073D285812251 +:1004A00001451305A072D2851D2AA3020C00114537 +:1004B0002324AC0091A001450345C07E0589630457 +:1004C000050E01451305007C192201451305306C0A +:1004D00081459305B074212223260C0001451305A4 +:1004E0004073D285ED28014513057071D285C5286A +:1004F000A3010C002324BC0115452328AC0065A0F2 +:1005000001450345F07E45C123268C0001451305B6 +:10051000307B752821452324AC0001451305A072CA +:10052000BDA003455C0041C123260C000145130515 +:10053000607A712823245C0101451305707129A894 +:1005400003455C000DC501451305607A492023244D +:100550005C01014513054072DA8551200145130500 +:100560000073DA85AD280145130590731DA8014578 +:100570000345F07E0DC923268C0001451305307B11 +:10058000B92021452324AC00014513054072DA85CA +:10059000B920014513050073DA8591200145130543 +:1005A0004073DA852D2803258C006D15E3EEADCC64 +:1005B00005458520A120930B15008920E36F75FF69 +:1005C00001458128D1B1854873000000828091489F +:1005D000730000008280AD487300000082809308A1 +:1005E0001008730000008280930850087300000018 +:1005F000828093087008730000008280732510C009 +:100600008280732500C08280930860087300000018 +:1006100082800589F322008093920248B3E2A2000F +:100620007390028082809548730000008280930856 +:100630000008730000008280A148730000008280DF +:10064000930830087300000082809308400873000C +:1006500000008280A8020000F6030000860300006C +:10066000A603000020030000200400005004000046 +:10067000C6030000B6040000400300007004000040 +:1006800073656E736F7231004745540073656E7306 +:100690006F72320073656E736F7233006D657365D0 +:1006A000636F6E735F6D6F766573746F6E65733AAB +:1006B0006D6F766573746F6E655F7665727469636E +:1006C000616C00627574746F6E31006C6967687478 +:1006D0005F6F6E00627574746F6E32006275747451 +:1006E0006F6E33000A456C657661746F7220436FDC +:1006F0006E74726F6C6C65720A666F72205256432C +:100700006F6E74726F6C6C65720A496E69746961A0 +:100710006C697A696E6700646F6F72310065787416 +:10072000656E6400646F6F723200646F6F723300C5 +:1007300073656C00646F776E00757000726574721B +:100740006163745F737469636B79006C6967687463 +:100750005F6F6666000A426F74746F6D20466C6F3F +:100760006F722044656D616E64000A424644204306 +:100770006F6D706C657465000A49646C6520617406 +:100780002031000A49646C652061742032000A49F6 +:10079000646C652061742033000A4D6F76696E6762 +:1007A00020746F2032000A4D6F76696E6720746F77 +:1007B0002033000A4D6F76696E6720746F20310018 +:1007C0000A417272697665642061742031000A41C1 +:1007D0007272697665642061742032000A41727217 +:0A07E000697665642061742033001F +:1007EC0000000000000000000000000000000000FD +:1007FC0000000000000000000000000000000000ED +:10080C0000000000000000000000000000000000DC +:10081C0000000000000000000000000000000000CC +:10082C0000000000000000000000000000000000BC +:10083C0000000000000000000000000000000000AC +:04084C0000000000A8 +:00000001FF diff --git a/c/elevator/elevator.o b/c/elevator/elevator.o new file mode 100644 index 0000000..834800b Binary files /dev/null and b/c/elevator/elevator.o differ diff --git a/c/elevator/rvcontroller.ld b/c/elevator/rvcontroller.ld new file mode 100644 index 0000000..985892b --- /dev/null +++ b/c/elevator/rvcontroller.ld @@ -0,0 +1,45 @@ +/* Thanks https://github.com/darklife/darkriscv */ + __heap_size = 0x200; /* required amount of heap */ + __stack_size = 0x800; /* required amount of stack */ + ENTRY(_start); + MEMORY + { + RAM (rwx) : ORIGIN = 0x00000000, LENGTH = 0x10000 + } + SECTIONS + { + .text : + { + *(.text.startup) + *(.text) + *(.text) + *(.rodata*) + } > RAM + .data : + { + *(.sbss) + *(.data) + *(.bss) + *(.rela*) + *(COMMON) + } > RAM + + .heap : + { + . = ALIGN(4); + PROVIDE ( end = . ); + _sheap = .; + . = . + __heap_size; + . = ALIGN(4); + _eheap = .; + } >RAM + + .stack : + { + . = ALIGN(4); + _estack = .; + . = . + __stack_size; + . = ALIGN(4); + _sstack = .; + } >RAM + } diff --git a/c/elevator/states.h b/c/elevator/states.h new file mode 100644 index 0000000..27fb4d2 --- /dev/null +++ b/c/elevator/states.h @@ -0,0 +1,14 @@ +#define STATE_INIT 0 +#define STATE_BOTTOM_FLOOR_DEMAND 1 +#define STATE_TIMING_1 2 +#define STATE_TIMING_2 3 +#define STATE_TIMING_3 4 +#define STATE_IDLE_1 5 +#define STATE_IDLE_2 6 +#define STATE_IDLE_3 7 +#define STATE_MOVING_1 8 +#define STATE_MOVING_2 9 +#define STATE_MOVING_3 10 + +#define DIRECTION_UP 0 +#define DIRECTION_DOWN 1 diff --git a/c/gol/Makefile b/c/gol/Makefile new file mode 100644 index 0000000..54e4d4a --- /dev/null +++ b/c/gol/Makefile @@ -0,0 +1,20 @@ +all: gol.hex + +gol.o: gol.c + clang -target riscv32-none-elf -I../rvcontroller-libraries -march=rv32imacb_zicntr_zicond_zicsr_zifencei_zihintpause_zilsd_zclsd_zabha_zacas_zbkb_zbkx_zcb_zcmp_zcmt -ffreestanding -O3 -c -o gol.o gol.c + +gol.elf: ../rvcontroller-libraries/rvcontroller-init.o ../rvcontroller-libraries/rvcontroller-ecalls.o gol.o + riscv32-none-elf-ld -T rvcontroller.ld --no-warn-rwx-segments -o gol.elf ../rvcontroller-libraries/rvcontroller-init.o gol.o ../rvcontroller-libraries/rvcontroller-ecalls.o + +dump: gol.elf + riscv32-none-elf-objdump -d gol.elf + +gol.hex: gol.elf + riscv32-none-elf-objcopy -O ihex gol.elf gol.hex + +load: gol.hex + bash -c "wl-copy < gol.hex" + +clean: + rm -f gol.bin gol.elf gol.o init.o + diff --git a/c/gol/gol.c b/c/gol/gol.c new file mode 100644 index 0000000..1ccb4c4 --- /dev/null +++ b/c/gol/gol.c @@ -0,0 +1,89 @@ +/* Conway's Game of Life for RVController + * A product of Advanced Mesecons Devices, a Cheapie Systems company + * This is free and unencumbered software released into the public domain. + * See http://unlicense.org/ for more information */ + +#include +#include +#include "rvcontroller-ecalls.h" + +bool field[176] = {false}; // 22*8, extra pixel on each edge will just always be false, makes generation logic easier +bool field2[176] = {false}; +char screenbuf[121] = {'x'}; //20*6 + terminator + +void randomFill(void) { + for (int y=1;y<=6;y++) { + for (int x=1;x<=20;x++) { + int cell = (y*22)+x; + field[cell] = (randomint(0,1) == 1); + } + } +} + +void draw(void) { + char channelbuf[3] = {0}; + for (int y=1;y<=6;y++) { + channelbuf[1] = 0x30+y; + for (int x=1;x<=20;x++) { + channelbuf[0] = 0x40+x; + int cell = (y*22)+x; + int outpos = ((y-1)*20)+x-1; + if (field[cell]) { + screenbuf[outpos] = '*'; + digiline_send(channelbuf,"ffaa55"); + } else { + screenbuf[outpos] = ' '; + digiline_send(channelbuf,"552200"); + } + } + } + screenbuf[120] = 0; + printstr(screenbuf); +} + +int countLivingCells(int cell) { + int count = 0; + if (field[cell-23]) { count += 1; } //Up-left + if (field[cell-22]) { count += 1; } //Up + if (field[cell-21]) { count += 1; } //Up-right + if (field[cell-1]) { count += 1; } //Left + if (field[cell+1]) { count += 1; } //Right + if (field[cell+21]) { count += 1; } //Down-left + if (field[cell+22]) { count += 1; } //Down + if (field[cell+23]) { count += 1; } //Down-right + return count; +} + +void calculateNewGeneration(void) { + for (int y=1;y<=6;y++) { + for (int x=1;x<=20;x++) { + int cell = (y*22)+x; + int living = countLivingCells(cell); + if (field[cell]) { + //Currently alive, stay if 2 or 3 + field2[cell] = (living == 2 || living == 3); + } else { + //Not currently alive, spawn if 3 + field2[cell] = (living == 3); + } + } + } +} + +void copyNewGeneration(void) { + for (int y=1;y<=6;y++) { + for (int x=1;x<=20;x++) { + int cell = (y*22)+x; + field[cell] = field2[cell]; + } + } +} + +void main(void) { + randomFill(); + while (true) { + draw(); + calculateNewGeneration(); + copyNewGeneration(); + } +} diff --git a/c/gol/gol.elf b/c/gol/gol.elf new file mode 100755 index 0000000..157bcc0 Binary files /dev/null and b/c/gol/gol.elf differ diff --git a/c/gol/gol.hex b/c/gol/gol.hex new file mode 100644 index 0000000..0623260 --- /dev/null +++ b/c/gol/gol.hex @@ -0,0 +1,463 @@ +:1000000037010100EF107019A948730000008280C9 +:1000100046B822E40965130535B71304A502930415 +:10002000E50A85450145EF10102A7D1513351500A9 +:10003000A306A4FE85450145EF10F0287D15133574 +:1000400015002307A4FE85450145EF10D0277D1537 +:1000500013351500A307A4FE85450145EF10B02612 +:100060007D15133515002308A4FE85450145EF10C5 +:1000700090257D1513351500A308A4FE854501457F +:10008000EF1070247D15133515002309A4FE854556 +:100090000145EF1050237D1513351500A309A4FE6B +:1000A00085450145EF1030227D1513351500230AD3 +:1000B000A4FE85450145EF1010217D15133515006F +:1000C000A30AA4FE85450145EF10F01F7D151335E9 +:1000D0001500230BA4FE85450145EF10D01E7D15AC +:1000E00013351500A30BA4FE85450145EF10B01D87 +:1000F0007D1513351500230CA4FE85450145EF1031 +:10010000901C7D1513351500A30CA4FE85450145F3 +:10011000EF10701B7D1513351500230DA4FE8545CA +:100120000145EF10501A7D1513351500A30DA4FEDF +:1001300085450145EF1030197D1513351500230E47 +:10014000A4FE85450145EF1010187D1513351500E7 +:10015000A30EA4FE85450145EF10F0167D1513355D +:100160001500230FA4FE85450145EF10D0157D1520 +:1001700013351500A30FA4FE85450145EF10B014FB +:100180007D151335150008885904E31C94E8226492 +:1001900046BE4EB8411122FC4AF852F45AF062ECC5 +:1001A0006AE813051003130610048969938939B7A7 +:1001B0005959096A130A3AAF89649384C4AE83C556 +:1001C0007901A306C100930A10042307A100A30725 +:1001D00001003375B90E3376BA0EB3D5B40E1305DC +:1001E000A502D18D09641304A4AF08881305D100BA +:1001F000EF10700803C5890193052004A306B10020 +:10020000130B2004B375A90E3376AA0E33D5A40EB2 +:100210009386A502B365C50054881305D100EF107D +:10022000900503C5990193053004A306B100930B13 +:100230003004B375A90E3376AA0E33D5A40E938677 +:10024000A502B365C50034881305D100EF10B002D4 +:1002500003C5A90193054004A306B100130C400493 +:10026000B375A90E3376AA0E33D5A40E9386A502D4 +:10027000B365C50074881305D100EF10C07F03C5B6 +:10028000B90193055004A306B100B375A90E3376E6 +:10029000AA0E33D5A40E9386A502B365C50023022A +:1002A000D4001305D100EF10007D03C5C9019305EB +:1002B0006004A306B100B375A90E3376AA0E33D538 +:1002C000A40E9386A502B365C500A302D40013054E +:1002D000D100EF10407A03C5D90193057004A3063D +:1002E000B100B375A90E3376AA0E33D5A40E93864A +:1002F000A502B365C5002303D4001305D100EF1098 +:10030000807703C5E90193058004A306B100B375A6 +:10031000A90E3376AA0E33D5A40E9386A502B36533 +:10032000C500A303D4001305D100EF10C07403C5AA +:10033000F90193059004A306B100B375A90E3376B5 +:10034000AA0E33D5A40E9386A502B365C500230477 +:10035000D4001305D100EF10007203C50902930504 +:10036000A004A306B100B375A90E3376AA0E33D547 +:10037000A40E9386A502B365C500A304D40013059B +:10038000D100EF10406F03C519029305B004A30616 +:10039000B100B375A90E3376AA0E33D5A40E938699 +:1003A000A502B365C5002305D4001305D100EF10E5 +:1003B000806C03C529029305C004A306B100B37580 +:1003C000A90E3376AA0E33D5A40E9386A502B36583 +:1003D000C500A305D4001305D100EF10C06903C503 +:1003E00039029305D004A306B100B375A90E337684 +:1003F000AA0E33D5A40E9386A502B365C5002306C5 +:10040000D4001305D100EF10006703C5490293051E +:10041000E004A306B100B375A90E3376AA0E33D556 +:10042000A40E9386A502B365C500A306D4001305E8 +:10043000D100EF10406403C559029305F004A306F0 +:10044000B100B375A90E3376AA0E33D5A40E9386E8 +:10045000A502B365C5002307D4001305D100EF1032 +:10046000806103C5690293050005A306B100B37559 +:10047000A90E3376AA0E33D5A40E9386A502B365D2 +:10048000C500A307D4001305D100EF10C05E03C55B +:10049000790293051005A306B100B375A90E337652 +:1004A000AA0E33D5A40E9386A502B365C500230812 +:1004B000D4001305D100EF10005C03C58902930539 +:1004C0002005A306B100B375A90E3376AA0E33D565 +:1004D000A40E9386A502B365C500A308D400130536 +:1004E000D100EF10405903C5990293053005A306CA +:1004F000B100B375A90E3376AA0E33D5A40E938638 +:10050000A502B365C5002309D4001305D100EF107F +:10051000805603C5A90293054005A306B100930CBC +:100520004005B375A90E3376AA0E33D5A40E938673 +:10053000A502B365C500A309D4001305D100EF10CF +:10054000805303C5D90293052003A3065101130D5F +:1005500010042307B100B375A90E3376AA0E33D564 +:10056000A40E9386A502B365C500230AD400130523 +:10057000D100EF10405003C5E902A3066101930DBD +:100580002004B375A90E3376AA0E33D5A40E938634 +:10059000A502B365C500A30AD4001305D100EF106E +:1005A000804D03C5F902A3067101930A3004B375A7 +:1005B000A90E3376AA0E33D5A40E9386A502B36591 +:1005C000C500230BD4001305D100EF10C04A03C5AA +:1005D0000903A3068101130B4004B375A90E3376FA +:1005E000AA0E33D5A40E9386A502B365C500A30B4E +:1005F000D4001305D100EF10004803C5190393057B +:100600005004A306B100930B5004B375A90E3376C2 +:10061000AA0E33D5A40E9386A502B365C500230C9C +:10062000D4001305D100EF10004503C5290393053D +:100630006004A306B100130C6004B375A90E3376F1 +:10064000AA0E33D5A40E9386A502B365C500A30CEC +:10065000D4001305D100EF10004203C53903930500 +:100660007004A306B100B375A90E3376AA0E33D574 +:10067000A40E9386A502B365C500230DD40013050F +:10068000D100EF10403F03C5490393058004A30642 +:10069000B100B375A90E3376AA0E33D5A40E938696 +:1006A000A502B365C500A30DD4001305D100EF105A +:1006B000803C03C5590393059004A306B100B375AC +:1006C000A90E3376AA0E33D5A40E9386A502B36580 +:1006D000C500230ED4001305D100EF10C03903C5A7 +:1006E00069039305A004A306B100B375A90E337680 +:1006F000AA0E33D5A40E9386A502B365C500A30E3A +:10070000D4001305D100EF10003703C5790393051A +:10071000B004A306B100B375A90E3376AA0E33D583 +:10072000A40E9386A502B365C500230FD40013055C +:10073000D100EF10403403C589039305C004A3061C +:10074000B100B375A90E3376AA0E33D5A40E9386E5 +:10075000A502B365C500A30FD4001305D100EF10A7 +:10076000803103C599039305D004A306B100B37586 +:10077000A90E3376AA0E33D5A40E9386A502B365CF +:10078000C5002300D4021305D100EF10C02E03C50D +:10079000A9039305E004A306B100B375A90E33764F +:1007A000AA0E33D5A40E9386A502B365C500A30097 +:1007B000D4021305D100EF10002C03C5B903930533 +:1007C000F004A306B100B375A90E3376AA0E33D593 +:1007D000A40E9386A502B365C5002301D4021305B8 +:1007E000D100EF10402903C5C90393050005A306F6 +:1007F000B100B375A90E3376AA0E33D5A40E938635 +:10080000A502B365C500A301D4021305D100EF1002 +:10081000802603C5D90393051005A306B100B3755F +:10082000A90E3376AA0E33D5A40E9386A502B3651E +:10083000C5002302D4021305D100EF10C02303C565 +:10084000E90393052005A306B100B375A90E33761D +:10085000AA0E33D5A40E9386A502B365C500A302E4 +:10086000D4021305D100EF10002103C5F90393054D +:100870003005A306B100B375A90E3376AA0E33D5A1 +:10088000A40E9386A502B365C5002303D402130505 +:10089000D100EF10401E03C50904A3069101930C7B +:1008A0004005B375A90E3376AA0E33D5A40E9386F0 +:1008B000A502B365C500A303D4021305D100EF1050 +:1008C000801B03C5390493053003A306A101130D52 +:1008D00010042307B100B375A90E3376AA0E33D5E1 +:1008E000A40E9386A502B365C5002304D4021305A4 +:1008F000D100EF10401803C54904A306B101930DC0 +:100900002004B375A90E3376AA0E33D5A40E9386B0 +:10091000A502B365C500A304D4021305D100EF10EE +:10092000801503C55904A3065101930A3004B37519 +:10093000A90E3376AA0E33D5A40E9386A502B3650D +:10094000C5002305D4021305D100EF10C01203C562 +:100950006904A3066101130B4004B375A90E337635 +:10096000AA0E33D5A40E9386A502B365C500A305D0 +:10097000D4021305D100EF10001003C57904A306BB +:100980007101930B5004B375A90E3376AA0E33D5BB +:10099000A40E9386A502B365C5002306D4021305F1 +:1009A000D100EF10400D03C58904A3068101130C8B +:1009B0006004B375A90E3376AA0E33D5A40E9386C0 +:1009C000A502B365C500A306D4021305D100EF103C +:1009D000800A03C5990493057004A306B100B3759A +:1009E000A90E3376AA0E33D5A40E9386A502B3655D +:1009F000C5002307D4021305D100EF10C00703C5BB +:100A0000A90493058004A306B100B375A90E33763B +:100A1000AA0E33D5A40E9386A502B365C500A3071D +:100A2000D4021305D100EF10000503C5B9049305E6 +:100A30009004A306B100B375A90E3376AA0E33D580 +:100A4000A40E9386A502B365C5002308D40213053E +:100A5000D100EF10400203C5C9049305A004A3060A +:100A6000B100B375A90E3376AA0E33D5A40E9386C2 +:100A7000A502B365C500A308D4021305D100EF0099 +:100A8000907F03C5D9049305B004A306B100B375E4 +:100A9000A90E3376AA0E33D5A40E9386A502B365AC +:100AA000C5002309D4021305D100EF00D07C03C593 +:100AB000E9049305C004A306B100B375A90E33760B +:100AC000AA0E33D5A40E9386A502B365C500A3096B +:100AD000D4021305D100EF00107A03C5F904930581 +:100AE000D004A306B100B375A90E3376AA0E33D590 +:100AF000A40E9386A502B365C500230AD40213058C +:100B0000D100EF00507703C509059305E004A30663 +:100B1000B100B375A90E3376AA0E33D5A40E938611 +:100B2000A502B365C500A30AD4021305D100EF00E6 +:100B3000907403C519059305F004A306B100B375BD +:100B4000A90E3376AA0E33D5A40E9386A502B365FB +:100B5000C500230BD4021305D100EF00D07103C5EB +:100B6000290593050005A306B100B375A90E3376D8 +:100B7000AA0E33D5A40E9386A502B365C500A30BB8 +:100B8000D4021305D100EF00106F03C5390593059A +:100B90001005A306B100B375A90E3376AA0E33D59E +:100BA000A40E9386A502B365C500230CD4021305D9 +:100BB000D100EF00506C03C5490593052005A3063D +:100BC000B100B375A90E3376AA0E33D5A40E938661 +:100BD000A502B365C500A30CD4021305D100EF0034 +:100BE000906903C5590593053005A306B100B37597 +:100BF000A90E3376AA0E33D5A40E9386A502B3654B +:100C0000C500230DD4021305D100EF00D06603C543 +:100C10006905A3069101930C4005B375A90E3376BF +:100C2000AA0E33D5A40E9386A502B365C500A30D05 +:100C3000D4021305D100EF00106403C59905930594 +:100C40004003A306A101130D10042307B100B375DF +:100C5000A90E3376AA0E33D5A40E9386A502B365EA +:100C6000C500230ED4021305D100EF00D06003C5E8 +:100C7000A905A306B101930D2004B375A90E33761F +:100C8000AA0E33D5A40E9386A502B365C500A30EA4 +:100C9000D4021305D100EF00105E03C5B905A30609 +:100CA0005101930A3004B375A90E3376AA0E33D5D9 +:100CB000A40E9386A502B365C500230FD4021305C5 +:100CC000D100EF00505B03C5C905A3066101130BFA +:100CD0004004B375A90E3376AA0E33D5A40E9386BD +:100CE000A502B365C500A30FD4021305D100EF0020 +:100CF000905803C5D905A3067101930B5004B37531 +:100D0000A90E3376AA0E33D5A40E9386A502B36539 +:100D1000C5002300D4041305D100EF00D05503C54E +:100D2000E905A3068101130C6004B375A90E33769F +:100D3000AA0E33D5A40E9386A502B365C500A30001 +:100D4000D4041305D100EF00105303C5F905930532 +:100D50007004A306B100B375A90E3376AA0E33D57D +:100D6000A40E9386A502B365C5002301D404130520 +:100D7000D100EF00505003C5090693058004A30677 +:100D8000B100B375A90E3376AA0E33D5A40E93869F +:100D9000A502B365C500A301D4041305D100EF007B +:100DA000904D03C5190693059004A306B100B375D1 +:100DB000A90E3376AA0E33D5A40E9386A502B36589 +:100DC000C5002302D4041305D100EF00D04A03C5A7 +:100DD00029069305A004A306B100B375A90E3376C6 +:100DE000AA0E33D5A40E9386A502B365C500A3024F +:100DF000D4041305D100EF00104803C5390693054C +:100E0000B004A306B100B375A90E3376AA0E33D58C +:100E1000A40E9386A502B365C5002303D40413056D +:100E2000D100EF00504503C549069305C004A30651 +:100E3000B100B375A90E3376AA0E33D5A40E9386EE +:100E4000A502B365C500A303D4041305D100EF00C8 +:100E5000904203C559069305D004A306B100B375AB +:100E6000A90E3376AA0E33D5A40E9386A502B365D8 +:100E7000C5002304D4041305D100EF00D03F03C5FF +:100E800069069305E004A306B100B375A90E337695 +:100E9000AA0E33D5A40E9386A502B365C500A3049C +:100EA000D4041305D100EF00103D03C57906930566 +:100EB000F004A306B100B375A90E3376AA0E33D59C +:100EC000A40E9386A502B365C5002305D4041305BB +:100ED000D100EF00503A03C5890693050005A3062B +:100EE000B100B375A90E3376AA0E33D5A40E93863E +:100EF000A502B365C500A305D4041305D100EF0016 +:100F0000903703C5990693051005A306B100B37584 +:100F1000A90E3376AA0E33D5A40E9386A502B36527 +:100F2000C5002306D4041305D100EF00D03403C557 +:100F3000A90693052005A306B100B375A90E337663 +:100F4000AA0E33D5A40E9386A502B365C500A306E9 +:100F5000D4041305D100EF00103203C5B906930580 +:100F60003005A306B100B375A90E3376AA0E33D5AA +:100F7000A40E9386A502B365C5002307D404130508 +:100F8000D100EF00502F03C5C906A3069101B37528 +:100F9000A90E3376AA0E33D5A40E9386A502B365A7 +:100FA000C500A307D4041305D100EF00D02C03C55E +:100FB000F90693055003A306A101930C100423071F +:100FC000B100B375A90E3376AA0E33D5A40E93865D +:100FD000A502B365C5002308D4041305D100EF00B2 +:100FE000902903C50907A306B101130D2004B375A9 +:100FF000A90E3376AA0E33D5A40E9386A502B36547 +:10100000C500A308D4041305D100EF00D02603C502 +:101010001907A3065101930D3004B375A90E337659 +:10102000AA0E33D5A40E9386A502B365C500230985 +:10103000D4041305D100EF00102403C52907A3062B +:101040006101930A4004B375A90E3376AA0E33D515 +:10105000A40E9386A502B365C500A309D4041305A5 +:10106000D100EF00502103C53907A3067101130B0E +:101070005004B375A90E3376AA0E33D5A40E938609 +:10108000A502B365C500230AD4041305D100EF00FF +:10109000901E03C54907A3068101930B6004B37535 +:1010A000A90E3376AA0E33D5A40E9386A502B36596 +:1010B000C500A30AD4041305D100EF00D01B03C55B +:1010C000590793057004A306B100130C7004B3759F +:1010D000A90E3376AA0E33D5A40E9386A502B36566 +:1010E000C500230BD4041305D100EF00D01803C5AD +:1010F000690793058004A306B100B375A90E337682 +:10110000AA0E33D5A40E9386A502B365C500A30B22 +:10111000D4041305D100EF00101603C57907930519 +:101120009004A306B100B375A90E3376AA0E33D589 +:10113000A40E9386A502B365C500230CD404130541 +:10114000D100EF00501303C589079305A004A3063F +:10115000B100B375A90E3376AA0E33D5A40E9386CB +:10116000A502B365C500A30CD4041305D100EF009C +:10117000901003C599079305B004A306B100B37599 +:10118000A90E3376AA0E33D5A40E9386A502B365B5 +:10119000C500230DD4041305D100EF00D00D03C505 +:1011A000A9079305C004A306B100B375A90E337651 +:1011B000AA0E33D5A40E9386A502B365C500A30D70 +:1011C000D4041305D100EF00100B03C5B907930534 +:1011D000D004A306B100B375A90E3376AA0E33D599 +:1011E000A40E9386A502B365C500230ED40413058F +:1011F000D100EF00500803C5C9079305E004A3061A +:10120000B100B375A90E3376AA0E33D5A40E93861A +:10121000A502B365C500A30ED4041305D100EF00E9 +:10122000900503C5D9079305F004A306B100B37573 +:10123000A90E3376AA0E33D5A40E9386A502B36504 +:10124000C500230FD4041305D100EF00D00203C55D +:10125000E90793050005A306B100B375A90E33761F +:10126000AA0E33D5A40E9386A502B365C500A30FBD +:10127000D4041305D100EF00100003C5F90793054E +:101280001005A306B100B375A90E3376AA0E33D5A7 +:10129000A40E9386A502B365C5002300D4061305EA +:1012A000D100D12F03C5090893052005A306B1007D +:1012B000B375A90E3376AA0E33D5A40E9386A50274 +:1012C000B365C500A300D4061305D1006D2703C57F +:1012D000190893053005A306B100B375A90E33763E +:1012E000AA0E33D5A40E9386A502B365C5002301CB +:1012F000D4061305D100412703C5290893054005ED +:10130000A306B100B375A90E3376AA0E33D5A40E89 +:101310009386A502B365C500A301D4061305D100C9 +:10132000992F03C5590893056003A306910123076C +:10133000B100B375A90E3376AA0E33D5A40E9386E9 +:10134000A502B365C5002302D4061305D1002527E5 +:1013500003C56908A306A101B375A90E3376AA0EC9 +:1013600033D5A40E9386A502B365C500A302D406A7 +:101370001305D100092703C57908A306B101B37588 +:10138000A90E3376AA0E33D5A40E9386A502B365B3 +:10139000C5002303D4061305D100F12D03C5890828 +:1013A000A3065101B375A90E3376AA0E33D5A40E48 +:1013B0009386A502B365C500A303D4061305D10027 +:1013C0005D2D03C59908A3066101B375A90E337697 +:1013D000AA0E33D5A40E9386A502B365C5002304D7 +:1013E000D4061305D100412D03C5A908A306710138 +:1013F000B375A90E3376AA0E33D5A40E9386A50233 +:10140000B365C500A304D4061305D100AD2503C5FB +:10141000B908A3068101B375A90E3376AA0E33D598 +:10142000A40E9386A502B365C5002305D406130553 +:10143000D100912503C5C90893058004A306B10016 +:10144000B375A90E3376AA0E33D5A40E9386A502E2 +:10145000B365C500A305D4061305D100292D03C526 +:10146000D90893059004A306B100B375A90E33768D +:10147000AA0E33D5A40E9386A502B365C500230634 +:10148000D4061305D100C52B03C5E9089305A004B4 +:10149000A306B100B375A90E3376AA0E33D5A40EF8 +:1014A0009386A502B365C500A306D4061305D10033 +:1014B000D92303C5F9089305B004A306B100B37599 +:1014C000A90E3376AA0E33D5A40E9386A502B36572 +:1014D000C5002307D4061305D100712B03C50909E4 +:1014E0009305C004A306B100B375A90E3376AA0E06 +:1014F00033D5A40E9386A502B365C500A307D40611 +:101500001305D1008D2B03C519099305D004A3063B +:10151000B100B375A90E3376AA0E33D5A40E938607 +:10152000A502B365C5002308D4061305D100A12385 +:1015300003C529099305E004A306B100B375A90EFC +:101540003376AA0E33D5A40E9386A502B365C500E3 +:10155000A308D4061305D100392B03C53909930517 +:10156000F004A306B100B375A90E3376AA0E33D5E5 +:10157000A40E9386A502B365C5002309D4061305FE +:10158000D100D52903C5490993050005A306B1007B +:10159000B375A90E3376AA0E33D5A40E9386A50291 +:1015A000B365C500A309D4061305D100E92103C51D +:1015B000590993051005A306B100B375A90E33763A +:1015C000AA0E33D5A40E9386A502B365C500230ADF +:1015D000D4061305D100452103C5690993052005EB +:1015E000A306B100B375A90E3376AA0E33D5A40EA7 +:1015F0009386A502B365C500A30AD4061305D100DE +:101600009D2903C5790993053005A306B100B3757B +:10161000A90E3376AA0E33D5A40E9386A502B36520 +:10162000C500230BD4061305D100B12103C58909D8 +:1016300093054005A306B100B375A90E3376AA0E33 +:1016400033D5A40E9386A502B365C500A30BD406BB +:101650001305D1000D21230C040622852921627473 +:101660004279227A027B626C426D41014EBE8965ED +:10167000938535B72E95834595FE0346A5FE834693 +:10168000B5FE0347F5FFB295508183475501BA96E1 +:1016900003476501034575013E96B6953A96B295A6 +:1016A0002E9582808965938535B713884501908191 +:1016B000D481B88183C7650183C8850103C5C5028C +:1016C00036963E9783C6750183C7D50246953A96EE +:1016D00003C7E5023E953295138615003A951377B8 +:1016E000E500751579171335150013371700337595 +:1016F000D50EB356D70E558DA383A50CB285E3182E +:1017000006FB0965130535B7130845010346650156 +:1017100083467501034785018347C5028348E50277 +:1017200083452504B382C6003E978346D50283478E +:101730003504C695034645041697BE95BA95B295ED +:1017400013F6E500F515791693B515001336160056 +:10175000B3F5D50E3356D60ED18DA30EB50C0505B7 +:10176000E31605FB0965130535B713084501034664 +:10177000C5028346D5020347E50283472504834813 +:10178000450483458505B382C6003E9783463504EC +:1017900083479505C6950346A5051697BE95BA9548 +:1017A000B29513F6E500F515791693B515001336C5 +:1017B0001600B3F5D50E3356D60ED18DA309B50E4E +:1017C0000505E31605FB0968130838B7930598105B +:1017D0009308D81183C695F303C7A5F383C7B5F360 +:1017E00003C5F5F483C215F503C655F63303D700D8 +:1017F0003E9503C705F583C765F6169683C675F64D +:101800001A953E96329536951376E500751579163C +:1018100013351500133616003375E50E3356E60EF4 +:10182000518D88898505E39715FB9305F811930879 +:10183000381303C595F383C6A5F303C7B5F383C770 +:10184000F5F483C215F503C655F63383A6003E971B +:1018500083C605F583C765F6169603C575F61A9710 +:101860003E963A9632951376E5007515791613353E +:101870001500133616003375D50E3356D60E518D1E +:1018800088898505E39715FB9305A8091308E80ADD +:1018900003C645FD83C655FD03C765FD83C7A5FE89 +:1018A00083C8C5FE888136963E9783C6B5FEDC8127 +:1018B00046953A96B8813E953295138615003A952D +:1018C0001377E500751579171335150013371700D1 +:1018D0003375D50EB356D70E558DA38DA508B28599 +:1018E000E31806FB82808965938535B71385A50DBE +:1018F0009385E5150346D5FE8346E5FE0347F5FED1 +:10190000834705FFA30EC5F2230FD5F2A30FE5F21F +:101910002300F5F4034615FF834625FF034735FFF3 +:10192000834745FFA300C5F42301D5F4A301E5F4E3 +:101930002302F5F4034655FF834665FF034775FF11 +:10194000834785FFA302C5F42303D5F4A303E5F47D +:101950002304F5F4034695FF8346A5FF0347B5FF2F +:101960008347C5FFA304C5F42305D5F4A305E5F417 +:101970002306F5F40346D5FF8346E5FF0347F5FF4D +:101980001C81A306C5F42307D5F4A307E5F42308B7 +:10199000F5F45905E310B5F6828046B822E4EFE08D +:1019A0002FE70965130535B71304A50D9304E51555 +:1019B000EFE02FFEC53922858345D5FE0346E5FEBF +:1019C0008346F5FE034705FFA30EB5F2230FC5F2CC +:1019D000A30FD5F22300E5F4834515FF034625FF49 +:1019E000834635FF034745FFA300B5F42301C5F443 +:1019F000A301D5F42302E5F4834555FF034665FFB3 +:101A0000834675FF034785FFA302B5F42303C5F49E +:101A1000A303D5F42304E5F4834595FF0346A5FF0E +:101A20008346B5FF0347C5FFA304B5F42305C5F4FA +:101A3000A305D5F42306E5F48345D5FF0346E5FF6A +:101A40008346F5FF1881A306B5F42307C5F4A30761 +:101A5000D5F42308E5F45905E31095F691BF8548C0 +:101A60007300000082809148730000008280AD48BE +:101A700073000000828093081008730000008280C9 +:101A80009308500873000000828093087008730068 +:101A900000008280732510C08280732500C0828080 +:101AA000930860087300000082800589F32200809B +:101AB00093920248B3E2A20073900280828095481C +:101AC0007300000082809308000873000000828089 +:101AD000A148730000008280930830087300000062 +:101AE000828093084008730000008280666661610E +:0A1AF0003535003535323230300054 +:101AFA007800000000000000000000000000000064 +:101B0A0000000000000000000000000000000000CB +:101B1A0000000000000000000000000000000000BB +:101B2A0000000000000000000000000000000000AB +:101B3A00000000000000000000000000000000009B +:101B4A00000000000000000000000000000000008B +:101B5A00000000000000000000000000000000007B +:101B6A00000000000000000000000000000000006B +:101B7A00000000000000000000000000000000005B +:101B8A00000000000000000000000000000000004B +:101B9A00000000000000000000000000000000003B +:101BAA00000000000000000000000000000000002B +:101BBA00000000000000000000000000000000001B +:101BCA00000000000000000000000000000000000B +:101BDA0000000000000000000000000000000000FB +:101BEA0000000000000000000000000000000000EB +:101BFA0000000000000000000000000000000000DB +:101C0A0000000000000000000000000000000000CA +:101C1A0000000000000000000000000000000000BA +:101C2A0000000000000000000000000000000000AA +:101C3A00000000000000000000000000000000009A +:101C4A00000000000000000000000000000000008A +:101C5A00000000000000000000000000000000007A +:101C6A00000000000000000000000000000000006A +:101C7A00000000000000000000000000000000005A +:101C8A00000000000000000000000000000000004A +:101C9A00000000000000000000000000000000003A +:101CAA00000000000000000000000000000000002A +:101CBA00000000000000000000000000000000001A +:091CCA0000000000000000000011 +:00000001FF diff --git a/c/gol/gol.o b/c/gol/gol.o new file mode 100644 index 0000000..6c841a1 Binary files /dev/null and b/c/gol/gol.o differ diff --git a/c/gol/rvcontroller.ld b/c/gol/rvcontroller.ld new file mode 100644 index 0000000..985892b --- /dev/null +++ b/c/gol/rvcontroller.ld @@ -0,0 +1,45 @@ +/* Thanks https://github.com/darklife/darkriscv */ + __heap_size = 0x200; /* required amount of heap */ + __stack_size = 0x800; /* required amount of stack */ + ENTRY(_start); + MEMORY + { + RAM (rwx) : ORIGIN = 0x00000000, LENGTH = 0x10000 + } + SECTIONS + { + .text : + { + *(.text.startup) + *(.text) + *(.text) + *(.rodata*) + } > RAM + .data : + { + *(.sbss) + *(.data) + *(.bss) + *(.rela*) + *(COMMON) + } > RAM + + .heap : + { + . = ALIGN(4); + PROVIDE ( end = . ); + _sheap = .; + . = . + __heap_size; + . = ALIGN(4); + _eheap = .; + } >RAM + + .stack : + { + . = ALIGN(4); + _estack = .; + . = . + __stack_size; + . = ALIGN(4); + _sstack = .; + } >RAM + } diff --git a/c/menu/Makefile b/c/menu/Makefile new file mode 100644 index 0000000..bd92e6a --- /dev/null +++ b/c/menu/Makefile @@ -0,0 +1,44 @@ +CC ?= clang +CFLAGS_MARCH ?= -march=rv32imacb_zicntr_zicond_zicsr_zifencei_zihintpause_zilsd_zclsd_zabha_zacas_zbkb_zbkx_zcb_zcmp_zcmt +CFLAGS_OPT ?= -O3 +CFLAGS ?= ${CFLAGS_MARCH} ${CFLAGS_OPT} + +ifeq (${CC}, clang) + CC := ${CC} -target riscv32-none-elf +endif + +.PHONY: all dump load clean + +all: menu.hex + +menu.o: menu.c calculator.h digilines.h games.h screensaver.h + ${CC} -I../rvcontroller-libraries ${CFLAGS} -ffreestanding -c -o menu.o menu.c + +calculator.o: calculator.c + ${CC} -I../rvcontroller-libraries ${CFLAGS} -ffreestanding -c -o calculator.o calculator.c + +digilines.o: digilines.c + ${CC} -I../rvcontroller-libraries ${CFLAGS} -ffreestanding -c -o digilines.o digilines.c + +games.o: games.c + ${CC} -I../rvcontroller-libraries ${CFLAGS} -ffreestanding -c -o games.o games.c + +screensaver.o: screensaver.c + ${CC} -I../rvcontroller-libraries ${CFLAGS} -ffreestanding -c -o screensaver.o screensaver.c + +menu.elf: ../rvcontroller-libraries/rvcontroller-init.o ../rvcontroller-libraries/rvcontroller-ecalls.o menu.o calculator.o digilines.o games.o screensaver.o +# riscv32-none-elf-ld -T rvcontroller.ld --no-warn-rwx-segments -o menu.elf ../rvcontroller-libraries/rvcontroller-init.o ../rvcontroller-libraries/rvcontroller-ecalls.o menu.o calculator.o digilines.o games.o + ${CC} -T rvcontroller.ld -nostdlib -nostartfiles -Xlinker --no-warn-rwx-segments -o menu.elf ../rvcontroller-libraries/rvcontroller-init.o ../rvcontroller-libraries/rvcontroller-ecalls.o menu.o calculator.o digilines.o games.o screensaver.o + +dump: menu.elf + riscv32-none-elf-objdump -d menu.elf + +menu.hex: menu.elf + riscv32-none-elf-objcopy -O ihex menu.elf menu.hex + +load: menu.hex + bash -c "wl-copy < menu.hex" + +clean: + rm -f menu.bin menu.elf menu.o init.o calculator.o digilines.o games.o screensaver.o + diff --git a/c/menu/calculator.c b/c/menu/calculator.c new file mode 100644 index 0000000..ff26f07 --- /dev/null +++ b/c/menu/calculator.c @@ -0,0 +1,95 @@ +/* Menu Thing for RVController - Calculator + * A product of Advanced Mesecons Devices, a Cheapie Systems company + * This is free and unencumbered software released into the public domain. + * See http://unlicense.org/ for more information */ + +#include +#include +#include "rvcontroller-ecalls.h" + +void runCalculator(void) { + char input[2] = {0}; + int32_t num1 = 0; + int32_t num2 = 0; + int32_t result = 0; + + printstr("\n\n\n\n\n\n"); + printstr("Enter number 1:\n> "); + num1 = readint(); + printint(num1); + printstr("\nEnter number 2:\n> "); + num2 = readint(); + printint(num2); + + bool opok = false; + while (!opok) { + printstr("\nSelect operation:\n[+-*/%&|^<<>>] > "); + readstr(input,2); + printstr(input); + + switch (input[0]) { + case '<': + case '>': + // Duplicate the character for these two to give the illusion that I bothered to store both + // Then fall through + printstr(input); + case '+': + case '-': + case '*': + case '/': + case '%': + case '&': + case '|': + case '^': + printchar('\n'); + opok = true; + break; + default: + printstr("\nInvalid operation\n"); + } + } + + switch (input[0]) { + case '+': + printint(num1+num2); + break; + case '-': + printint(num1-num2); + break; + case '*': + printint(num1*num2); + break; + case '/': + printint(num1/num2); + break; + case '%': + printint(num1%num2); + break; + case '&': + printint(num1&num2); + break; + case '|': + printint(num1|num2); + break; + case '^': + printint(num1^num2); + break; + case '<': + if (num2 < 0 || num2 > 31) { + printstr("Nice try."); + } else { + printint(num1<' : + if (num2 < 0 || num2 > 31) { + printstr("Nice try."); + } else { + printint(num1>>num2); + } + break; + } + + printstr("\nPress any key"); + readstr(input,1); +} diff --git a/c/menu/calculator.h b/c/menu/calculator.h new file mode 100644 index 0000000..4a70356 --- /dev/null +++ b/c/menu/calculator.h @@ -0,0 +1,6 @@ +/* Menu Thing for RVController - Calculator + * A product of Advanced Mesecons Devices, a Cheapie Systems company + * This is free and unencumbered software released into the public domain. + * See http://unlicense.org/ for more information */ + +void runCalculator(void); diff --git a/c/menu/calculator.o b/c/menu/calculator.o new file mode 100644 index 0000000..7247432 Binary files /dev/null and b/c/menu/calculator.o differ diff --git a/c/menu/digilines.c b/c/menu/digilines.c new file mode 100644 index 0000000..620d61f --- /dev/null +++ b/c/menu/digilines.c @@ -0,0 +1,66 @@ +/* Menu Thing for RVController - Digilines + * A product of Advanced Mesecons Devices, a Cheapie Systems company + * This is free and unencumbered software released into the public domain. + * See http://unlicense.org/ for more information */ + +#include +#include +#include "rvcontroller-ecalls.h" + +char dispbuf[] = "\nLast channel:\n(none) \nLast message:\n(none) \ns: Send\nq: Quit"; + +void dispWrite(char *text,int pos) { + int outpos; + for (int i=0;;i++) { + if (text[i] == 0) { break; } + outpos = pos + i; + dispbuf[outpos] = text[i]; + } +} + +void sendUI(void) { + char channeloutbuf[19]; + char msgoutbuf[19]; + printstr("\n\n\n\n\nEnter channel:\n> "); + readstr(channeloutbuf,19); + printstr(channeloutbuf); + printstr("\nEnter message:\n> "); + readstr(msgoutbuf,19); + printstr(msgoutbuf); + digiline_send(channeloutbuf,msgoutbuf); + printstr("\nSent!\nPress any key"); + readstr(channeloutbuf,1); +} + +void runDigilines(void) { + char channelinbuf[21]; + char msginbuf[21]; + char kbinput; + bool quit = false; + + console_clearbuffer(); + digiline_clearbuffer(); + dispWrite("(none) ",15); + dispWrite("(none) ",50); + + while (!quit) { + if (digiline_bufferlevel() > 0) { + digiline_receive(channelinbuf,21,msginbuf,21); + dispWrite(" ",15); + dispWrite(" ",50); + dispWrite(channelinbuf,15); + dispWrite(msginbuf,50); + } + printstr(dispbuf); + + kbinput = console_readchar(); + switch (kbinput) { + case 's': + sendUI(); + break; + case 'q': + quit = true; + break; + } + } +} diff --git a/c/menu/digilines.h b/c/menu/digilines.h new file mode 100644 index 0000000..480623a --- /dev/null +++ b/c/menu/digilines.h @@ -0,0 +1,6 @@ +/* Menu Thing for RVController - Digilines + * A product of Advanced Mesecons Devices, a Cheapie Systems company + * This is free and unencumbered software released into the public domain. + * See http://unlicense.org/ for more information */ + +void runDigilines(void); diff --git a/c/menu/digilines.o b/c/menu/digilines.o new file mode 100644 index 0000000..95a2ac8 Binary files /dev/null and b/c/menu/digilines.o differ diff --git a/c/menu/games.c b/c/menu/games.c new file mode 100644 index 0000000..574c6f0 --- /dev/null +++ b/c/menu/games.c @@ -0,0 +1,121 @@ +/* Menu Thing for RVController - Games + * A product of Advanced Mesecons Devices, a Cheapie Systems company + * This is free and unencumbered software released into the public domain. + * See http://unlicense.org/ for more information */ + +#include +#include +#include "rvcontroller-ecalls.h" + +void runCasino(void) { + int32_t input; + int32_t money = 10; + bool quit = false; + char strscratch[1]; + + printstr("\nCASINO\n"); + + while (!quit) { + printstr("You have:\n$"); + printint(money); + printstr("\nBet how much?\n(0 to quit)\n> "); + input = readint(); + printint(input); + printchar('\n'); + + if (input == 0) { + quit = true; + } else if (input < 0 || input > money) { + printstr("Nice try.\n"); + } else { + if (randomint(0,9) >= 6) { // Of course it's not a fair chance. This is a casino, gotta make money here! + printstr("You win!\n"); + money = money + input; + if (money >= 1000000000) { + printstr("You're a \nbillionaire!\nBest quit while\nyou're ahead...\n\nPress any key"); + readstr(strscratch,1); + quit = true; + } + } else { + printstr("You lose.\n"); + money = money - input; + if (money <= 0) { + printstr("You've gambled away\nyour life savings.\nTime to go home...\n\nPress any key"); + readstr(strscratch,1); + quit = true; + } + } + } + } +} + +void runGuessNum(void) { + int32_t answer = randomint(1,99); + int32_t entry; + int32_t guesses = 0; + uint32_t time = rdtime(); + bool quit = false; + char strscratch[1]; + + printstr("GUESS THE NUMBER\nThe computer will\npick a number from\n1 to 99 and you need\nto guess it.\n\nPress any key"); + readstr(strscratch,1); + printstr("\n\n\n\n"); + + while (!quit) { + printstr("Enter your guess:\n(0 to quit)\n> "); + entry = readint(); + if (entry == 0) { + quit = true; + } + printint(entry); + guesses = guesses + 1; + + if (entry == answer) { + printstr("\nCorrect!\n\nYou got it in:\n"); + printint(guesses); + printstr(" guess"); + if (guesses != 1) { printstr("es"); } + printchar('\n'); + time = rdtime() - time; + printint(time); + printstr(" second"); + if (time != 1) { printchar('s'); } + printstr("\nPress any key"); + readstr(strscratch,1); + quit = true; + } else if (entry > answer) { + printstr("\nToo high!\n\n"); + } else { + printstr("\nToo low!\n\n"); + } + } +} + +void runGames(void) { + char inputbuf[2]; + bool quit = false; + while (!quit) { + printstr("\nGAMES\n"); + printstr("1: Casino\n"); + printstr("2: Guess the Number\n"); + printstr("\n\n0: Back"); + readstr(inputbuf,2); + + switch (inputbuf[0]) { + case '0': + quit = true; + break; + case '1': + runCasino(); + quit = true; + break; + case '2': + runGuessNum(); + quit = true; + break; + default: + printstr("\nInvalid option\n\nPress any key\n\n\n"); + readstr(inputbuf,2); + } + } +} diff --git a/c/menu/games.h b/c/menu/games.h new file mode 100644 index 0000000..d2b67be --- /dev/null +++ b/c/menu/games.h @@ -0,0 +1,6 @@ +/* Menu Thing for RVController - Games + * A product of Advanced Mesecons Devices, a Cheapie Systems company + * This is free and unencumbered software released into the public domain. + * See http://unlicense.org/ for more information */ + +void runGames(void); diff --git a/c/menu/games.o b/c/menu/games.o new file mode 100644 index 0000000..749068a Binary files /dev/null and b/c/menu/games.o differ diff --git a/c/menu/menu.c b/c/menu/menu.c new file mode 100644 index 0000000..4d3aa14 --- /dev/null +++ b/c/menu/menu.c @@ -0,0 +1,74 @@ +/* Menu Thing for RVController - Main Menu + * A product of Advanced Mesecons Devices, a Cheapie Systems company + * This is free and unencumbered software released into the public domain. + * See http://unlicense.org/ for more information */ + +#include +#include +#include "rvcontroller-ecalls.h" +#include "calculator.h" +#include "digilines.h" +#include "games.h" +#include "screensaver.h" + +uint_fast8_t menupage = 0; + +void main(void) { + char inputbuf[32] = {0}; // Overkill for now but it's not like I'm short on RAM + while (true) { + switch (menupage) { + case 0: + printstr("\nMAIN MENU Page 1\n"); + printstr("< > to change page\n"); + printstr("1: Calculator\n"); + printstr("2: Calendar\n"); + printstr("3: Digilines\n"); + printstr("4: Games"); + break; + case 1: + printstr("\nMAIN MENU Page 2\n"); + printstr("< > to change page\n"); + printstr("5: Screensaver\n"); + printstr("6: Text Editor\n"); + printstr("More coming soon\n"); + printstr("(maybe)"); + break; + default: + printstr("\nInvalid menu page\n\n\n\n\n\n"); + } + + readstr(inputbuf,32); + + switch (inputbuf[0]) { + case '<': + if (menupage > 0) { + menupage--; + } else { + menupage = 1; + } + break; + case '>': + menupage = (menupage + 1) % 2; + break; + case '1': + runCalculator(); + break; + case '3': + runDigilines(); + break; + case '4': + runGames(); + break; + case '5': + runScreensaver(); + break; + default: + printstr("\nUnknown or\n"); + printstr("unimplemented\n"); + printstr("command\n"); + printstr("\n"); + printstr("Press any key\n"); + readstr(inputbuf,32); + } + } +} diff --git a/c/menu/menu.elf b/c/menu/menu.elf new file mode 100755 index 0000000..92b42fe Binary files /dev/null and b/c/menu/menu.elf differ diff --git a/c/menu/menu.hex b/c/menu/menu.hex new file mode 100644 index 0000000..2b96462 --- /dev/null +++ b/c/menu/menu.hex @@ -0,0 +1,377 @@ +:10000000370101006128A9487300000082808548FB +:100010007300000082809148730000008280AD4828 +:100020007300000082809308100873000000828033 +:1000300093085008730000008280930870087300D2 +:1000400000008280732510C08280732500C08280EA +:10005000930860087300000082800589F322008005 +:1000600093920248B3E2A200739002808280954886 +:1000700073000000828093080008730000008280F3 +:10008000A1487300000082809308300873000000CC +:100090008280930840087300000082804EB80111EE +:1000A000A2E4CAE052FC5AF862F46AF002C802CA3A +:1000B00002CC02CE02C002C202C402C6056D856D2A +:1000C000938D5DFF0569130979FE85699389A9FD03 +:1000D000056A130ABAFC856A938A4AFA354B856B1E +:1000E000938BCBF611A0712583456D77568552848D +:1000F000CE8C4A8CEE8495C585649384B404054502 +:10010000639CA50205651305E5FF0564130414014E +:10011000856C938C1C02056C130C1C038564938402 +:100120003404D53D0565130575FBF5352285E535A8 +:100130006685D5356285C5352685F13D0A859305E9 +:1001400000023D3F034501001305F5FC6360AB026F +:1001500033457521084102859D2079B703456D77A8 +:10016000854533F5A540230BAD76BDBF0565130569 +:1001700045065535056513051507713D05651305DC +:100180000508513D056513053536713505651305BF +:10019000950851350A8593050002DD35B1B74D222A +:1001A000A1B7EF00105089B703456D7709C57D15DC +:1001B000230BAD7615BF0545230BAD7635B74AB891 +:1001C00022EC4AE852E42313010005651305E535E6 +:1001D00099350565130585093D3D513D2A89053D44 +:1001E00005651305B50A053D5935AA890D35056420 +:1001F0001304F40B93047005056A130A4A0E856A0A +:10020000938A4A3A19A05285393522852935130532 +:1002100061008945B53513056100F53B0345610073 +:100220001305B5FDE3E1A4FE3345552108410285E0 +:100230002945F533034561001305B5FD93057005A8 +:1002400063E2A5088565938545503345B52008418F +:10025000028533653903B5A0130561006D3B29455F +:100260007D3B034561001305B5FD93057005E3FB78 +:10027000A5FC89A833852903A9A03345390391A09A +:1002800033F529013DA81305000263F9A9003315D0 +:10029000390105A81305000263E3A90205651305EA +:1002A000850F953B05A03385290121A833053941E8 +:1002B00009A833E5290131A033C5290119A0335517 +:1002C0003941B13305651305051CB13313056100D0 +:1002D00085457D3362644269226A4ABE108119CA2B +:1002E00085669386066AB695050590891081050591 +:1002F000850565FE82804EB8056513052510213BF6 +:100300001305D101CD45AD3B1305D1012933056559 +:100310001305951109331305A100CD459533130538 +:10032000A100D5391305D1019305A100ED3905656B +:100330001305C512CD311305D101854591334EBE4C +:100340004EB85D71A2FCCAF8D2F4DAF0E2ECEAE849 +:10035000253BFD3905641304046A930680021306E5 +:10036000E0061307F0061305500693059002930468 +:100370000002930A6101130B1100930B300705690A +:1003800013092910856993899911056A130ACA12FC +:10039000A307D4002308C400A308E4002309C40071 +:1003A0002309D402A309C402230AE402A30AC40253 +:1003B000130C1007A309A400230AB400A30A940095 +:1003C000230B9400A30B9400230C9400A30C940023 +:1003D000230D9400A30D9400230E9400A30E94000B +:1003E000230F9400A30F940023009402A30094020F +:1003F00023019402230BA402A30BB402230C940246 +:10040000A30C9402230D9402A30D9402230E9402D4 +:10041000A30E9402230F9402A30F940223009404CA +:10042000A300940423019404A301940423029404DC +:10043000A3029404930C2403130DF40035A84A85F9 +:10044000D93E1305D103CD4525391305D103E13636 +:100450004E85D1361305A102CD451D311305A102EC +:100460005D3E1305D1039305A102753E52856536A5 +:100470001305D10385452931653E79C9130551011D +:10048000D5450A86D546553EA30794002308940017 +:10049000A308940023099400A3099400230A94005C +:1004A000A30A9400230B9400A30B9400230C940044 +:1004B000A30C9400230D9400A30D9400230E94002C +:1004C000A30E9400230F9400A30F94002300940222 +:1004D000A30094022301940223099402A309940225 +:1004E000230A9402A30A9402230B9402A30B9402FE +:1004F000230C9402A30C9402230D9402A30D9402E6 +:10050000230E9402A30E9402230F9402A30F9402CD +:1005100023009404A300940403455101230194048F +:10052000A301940423029404A302940401C9EA855C +:100530005686888908820506850565FD0345010004 +:1005400001C9E6855A86888908820506850565FD04 +:100550002285D1343D3EE30475EFE31F85F16674D7 +:100560004679267A067B666C466D61614EBE4EB852 +:10057000411122FC4AF852F45AF062EC6AE805652F +:1005800013051514493C05651305A514693429455F +:10059000A944B53C056513056515B53CC93C2A84DD +:1005A000BD342945AD3C51C4056913094917856916 +:1005B0009389A914856B938B6B15194C856A938A63 +:1005C000FA17856C938C9C1837D59A3B056B130BE7 +:1005D000FB1C130DF59F056A130AAA1D39A84A854D +:1005E0001D3C4E850D3C26851D345E852D344134E1 +:1005F0002A84313C294525340DCCE34204FEE3C076 +:1006000084FEA5450145853C634885015685213416 +:10061000A294E3589DFC39A05A85F53A818CE342B7 +:1006200090FC11A0668A5285FD321305F1008545C4 +:10063000813C62744279227A027B626C426D410194 +:100640004EBEBAB822EC4AE852E40545930530069E +:10065000854415342A8BFD322A8905651305352218 +:100660005D3A130571008545213C05651305053686 +:100670005D3205651305A528793AD53A2A84413AB1 +:100680006318640505651305B52A713205454132C5 +:1006900005651305652C4132294551326532330415 +:1006A00025412285AD3205651305D52CAD32630594 +:1006B000940013053007A53205651305051CA13A02 +:1006C0001305710085456D3A62644269226ABABEBB +:1006D000635B8B0005651305552D353A11E862649F +:1006E0004269226ABABE05651305252E2D3265D8EA +:1006F00005651305A52805329D3AAA84093A0944DF +:10070000638C640385699389592D056A130AAA28A5 +:10071000856A938A2A2E63569B004E85ED3889E4BC +:100720007DBF5685CD38C5DC5285F5308932AA8427 +:10073000F9380504E39164FF05651305B52AE1382E +:100740002285F13005651305652CF130056513052B +:10075000B5FFD1302945E130F530330425412285FC +:100760007D3005651305D52C7D300545E313A4F4D4 +:10077000A1B74EB822F44AF052EC5AE805691309C1 +:10078000E92E85699389692F056A130A1A30056B6A +:10079000130B6B311304000393042003930B10031A +:1007A000856A938A0A324A85BD304E85AD305285BE +:1007B0009D305A858D301305E1008945D1300345C0 +:1007C000E100630E8500630195026309750156859A +:1007D00099301305E10089456530F1B7493B227432 +:1007E0000279626A426B4EBEA93D22740279626A46 +:1007F000426B4EBE81453306B5001082850565FE0D +:100800001385F5FF8280FD573307F5005883850770 +:1008100065FF63C405023387F500514893284701FB +:100820003307B8403377170FB3D7170FB368F70004 +:100830002E882A87634A1001A9A801483307B540CA +:10084000B388F50063571005B347C62033C6C720E9 +:1008500085C2429605651305756F32950505B30788 +:100860001501930500020C890505E31EF5FE15A090 +:10087000429685669386766F4698B305B5403305F4 +:10088000D6000505C2951083050710890505E31CF0 +:10089000B7FE82804AB822EC4AE852E45AE0954515 +:1008A0000145EFF04FFD2A84EFF00FFEEFF06FFEF1 +:1008B00005691309796FCD4419C105457DA04D5ACD +:1008C000856993892934930B1900D54A214B29A8AE +:1008D00095450145EFF02FFA2A84D1444A85EFF07F +:1008E0008FF3EFF00FFB2DE1E3549AFE1385F4FF35 +:1008F000635B900063C16403B3849A402A86CE850B +:10090000634E90001DA80146B38599408505B1044A +:10091000634690001DA0B544CE852A86B346842048 +:10092000DE94B3C68620B2963386DB00A696988105 +:10093000188A05068505E31CD6FEAA844A85EFF0D1 +:100940008FEDEFF00FF54DD163CA04001D4563ED47 +:10095000A4005145058D634AA00035A01385D4003D +:1009600081446344A00005A03545B3458420CA9462 +:10097000B3C58520A69585052E951306000290899E +:100980008505E39EA5FE62644269226A026B4ABE47 +:100990004EB822F44AF052EC5AE862E46AE0EFF012 +:1009A000AFEEEFF00FEF314985699389796F01C59B +:1009B0008144014501AA814A8144854C138A19006A +:1009C00013040002056B130B0B35D14B214C054D65 +:1009D0002DA813A514007D1D3375AD0E93A51A0027 +:1009E000FD1CB3F5BC0E13A674007D160505336D12 +:1009F000A60013A55A007D158505B36CB5004E857C +:100A0000EFF06FE1EFF0EFE851E963CA040063EE45 +:100A1000840133859B40A685634BA0003DA08145A2 +:100A20001385C4006345A0000DA03145A68533C6DB +:100A30005A21B306AA0033455621AA953305BA00B8 +:100A4000B69500890505E31EB5FEEA94E69A63CBE8 +:100A5000040063E18403B3859B4026865A85634E78 +:100A6000B00085BF014633059B409385C4006346B3 +:100A7000B00085B7B1455A852686B3C65A213307DB +:100A8000BA00B3C556212E96B305CA003A96148112 +:100A9000948985050505E39CC5FE25BF33C55A210C +:100AA0003345552163CB0400A14563EDB400D14526 +:100AB000338995406348200105A01389C40081440F +:100AC000635C200126954E9505052A999305000241 +:100AD0000C890505E31E25FF22740279626A426BC8 +:100AE000226C026D4EBE4EB83971A2F4CAF0D2EC3F +:100AF000DAE8E2E4EAE079556D58FD52F1566157C3 +:100B0000A547B1480944C94505469D442ADE194315 +:100B10003AD636D816DA42DC954B3ED4114532CC63 +:100B20002ECE22D046D28D4526CA930D00022EC26B +:100B30002AC45EC61AC82311B101EFF0EFD4EFF05A +:100B40004FD5056A130A7A6F630A051EA300BA011E +:100B50002301BA01A301BA012302BA01A302BA0117 +:100B60002303BA01A303BA012304BA01A304BA01FF +:100B70002305BA01A305BA012306BA01A306BA01E7 +:100B80002307BA01A307BA012308BA01A308BA01CF +:100B90002309BA01A309BA01230ABA01230BBA0136 +:100BA000A30BBA01230CBA01A30CBA01230DBA019D +:100BB000A30DBA01230EBA01A30EBA01230FBA0185 +:100BC000A30FBA012300BA03A300BA032301BA0397 +:100BD000A301BA032302BA03A302BA032303BA038D +:100BE000A303BA032304BA03A304BA03A305BA03F5 +:100BF0002306BA03A306BA032307BA03A307BA035B +:100C00002308BA03A308BA032309BA03A309BA0342 +:100C1000230ABA03A30ABA03230BBA03A30BBA032A +:100C2000230CBA03A30CBA03230DBA03A30DBA0312 +:100C3000230EBA03A30EBA03230FBA032300BA0587 +:100C4000A300BA052301BA05A301BA052302BA0518 +:100C5000A302BA052303BA05A303BA052304BA0500 +:100C6000A304BA052305BA05A305BA052306BA05E8 +:100C7000A306BA052307BA05A307BA052308BA05D0 +:100C8000A308BA052309BA05A309BA05A30ABA0538 +:100C9000230BBA05A30BBA05230CBA05A30CBA059E +:100CA000230DBA05A30DBA05230EBA05A30EBA0586 +:100CB000230FBA05A30FBA052300BA07A300BA078A +:100CC0002301BA07A301BA072302BA07A302BA078E +:100CD0002303BA07A303BA072304BA072305BA07F5 +:100CE000A305BA072306BA07A306BA072307BA075C +:100CF000A307BA072308BA07A308BA072309BA0744 +:100D0000A309BA07230ABA07A30ABA07230BBA072B +:100D1000A30BBA07230CBA07A30CBA07230DBA0713 +:100D2000A30DBA07230EBA07A30EBA0726740679D5 +:100D3000666A466B266C066D21614EBE014D6410DD +:100D4000130B810113042100130C6A0121A0050D6E +:100D5000630F7D05B3499D2003A90900930C190079 +:100D600023A09901130510029305A007EFF0AFB07F +:100D70002301A10063E99B0733456D210841FD551F +:100D80003306B4005082850565FE3306B50063481E +:100D9000050213264601D146898EB3F6C60E33D618 +:100DA000C50E558E930521006340C0022DA85285C3 +:100DB000EFF06FA6EFF0EFAD014D49DD41BBB3059C +:100DC000A44001456351C002B3462921B3C6262180 +:100DD000AA963305DC00E2963696948114890505BF +:100DE0008505E31CC5FE4800B34AAD2003A50A00F3 +:100DF000B385AC4063E7BB06B3456D218C417D569E +:100E0000B306C400D4820506E5FE93D6F501338708 +:100E1000C500D1478D8F93244701B3F7970E335602 +:100E2000960E5D8E3376D60EB356D70E558E641061 +:100E3000E35FC0F0B3E5050AB3462921B3C6262116 +:100E40003347A5203347A720B6953305EC402E95B0 +:100E5000998DE2952E962300B5010505E31DC5FE8B +:100E6000FDB51945E3C5A5EE85450145EFF0AFA0F9 +:100E70008545E31EB5EC05458D45EFF0CF9F330565 +:100E8000A04023A0A900CD450145EFF0CF9EB3457A +:100E90006D2188C10945A145EFF0EF9D23A0AA006F +:100EA0007DB54EB8411122FC4AF852F45AF062EC7A +:100EB0006AE805691309D935856993895936056A40 +:100EC000130A2A37856A938AEA37056B130B0B39A5 +:100ED000056C130C3C3605641304B43993041003F9 +:100EE000930C0003856B938B0B32130D2003930D32 +:100EF000300309A85E85EFF00F9213057100854558 +:100F0000EFF00F984A85EFF00F914E85EFF0AF901C +:100F10005285EFF04F905685EFF0EF8F5A85EFF046 +:100F20008F8F6285EFF02F8F2285EFF0CF8E130524 +:100F300071008945EFF0CF940345710063C7A400A9 +:100F4000630E9501E31895FA09A86306A501E3135A +:100F5000B5FB513E21A02D3C11A02D3A627442797F +:100F6000227A027B626C426D41014EBE5801000044 +:100F70006C0100009E010000E6000000A2010000DC +:100F80006C0100006C0100006C0100006C010000AD +:100F90006C0100006C010000A80100006C01000061 +:100FA0005C0100000A4D41494E204D454E552050F0 +:100FB00061676520310A003C203E20746F20636821 +:100FC000616E676520706167650A00313A20436190 +:100FD0006C63756C61746F720A00323A2043616C05 +:100FE000656E6461720A00333A20446967696C690E +:100FF0006E65730A00343A2047616D6573000A4DCF +:1010000041494E204D454E55205061676520320ABA +:1010100000353A2053637265656E73617665720AB6 +:1010200000363A205465787420456469746F720AFA +:10103000004D6F726520636F6D696E6720736F6F0F +:101040006E0A00286D6179626529000A496E766131 +:101050006C6964206D656E7520706167650A0A0AA7 +:101060000A0A0A000A556E6B6E6F776E206F720A5D +:1010700000756E696D706C656D656E7465640A00EF +:10108000636F6D6D616E640A0050726573732061E9 +:101090006E79206B65790A00456E746572206E75F5 +:1010A0006D62657220313A0A3E20000A456E746511 +:1010B00072206E756D62657220323A0A3E20000A17 +:1010C00053656C656374206F7065726174696F6ECF +:1010D0003A0A5B2B2D2A2F25267C5E3C3C3E3E5D4A +:1010E000203E20000A496E76616C6964206F70654D +:1010F000726174696F6E0A004E696365207472795B +:101100002E000A0A0A0A0A456E7465722063686135 +:101110006E6E656C3A0A3E20000A456E7465722058 +:101120006D6573736167653A0A3E20000A53656E08 +:1011300074210A507265737320616E79206B657932 +:10114000000A434153494E4F0A00596F75206861A8 +:1011500076653A0A24000A42657420686F77206D2C +:101160007563683F0A283020746F2071756974298F +:101170000A3E20004E696365207472792E0A005978 +:101180006F752077696E210A00596F752772652087 +:1011900061200A62696C6C696F6E61697265210A0F +:1011A000426573742071756974207768696C650A8B +:1011B000796F752772652061686561642E2E2E0A2D +:1011C0000A507265737320616E79206B65790059DE +:1011D0006F75206C6F73652E0A00596F75277665E1 +:1011E0002067616D626C656420617761790A796F4F +:1011F0007572206C69666520736176696E67732EFF +:101200000A54696D6520746F20676F20686F6D6583 +:101210002E2E2E0A0A507265737320616E79206B30 +:10122000657900475545535320544845204E554D48 +:101230004245520A54686520636F6D70757465721B +:101240002077696C6C0A7069636B2061206E756D24 +:101250006265722066726F6D0A3120746F203939B1 +:1012600020616E6420796F75206E6565640A746F05 +:101270002067756573732069742E0A0A507265734E +:101280007320616E79206B657900456E74657220FC +:10129000796F75722067756573733A0A2830207408 +:1012A0006F2071756974290A3E20000A436F7272BB +:1012B000656374210A0A596F7520676F7420697419 +:1012C00020696E3A0A0020677565737300207365A4 +:1012D000636F6E64000A546F6F2068696768210A43 +:1012E0000A000A546F6F206C6F77210A0A000A47C0 +:1012F000414D45530A00313A20436173696E6F0ACC +:1013000000323A20477565737320746865204E7506 +:101310006D6265720A000A0A303A204261636B000E +:101320000A496E76616C6964206F7074696F6E0A29 +:101330000A507265737320616E79206B65790A0AB1 +:101340000A005256436F6E74726F6C6C65722000A7 +:101350005256436F6E74726F6C6C6572000A0A0AA3 +:101360000A0A0A0A0053435245454E534156455214 +:101370000A00313A204D6172717565650A00323A92 +:1013800020426F756E63696E6720546578740A0039 +:10139000333A204D61747269780A00303A204578FA +:1013A00069740000300200003002000006020000F4 +:1013B00006020000060200003002000030020000B9 +:1013C00006020000300200000602000030020000A9 +:1013D00006020000060200000602000006020000ED +:1013E00006020000060200000602000006020000DD +:1013F00006020000060200000602000006020000CD +:101400005802000006020000580200000602000018 +:1014100006020000060200000602000006020000AC +:10142000060200000602000006020000060200009C +:10143000060200000602000006020000060200008C +:10144000060200000602000006020000060200007C +:10145000060200000602000006020000060200006C +:10146000060200000602000006020000060200005C +:10147000060200000602000006020000060200004C +:101480000602000006020000300200000602000012 +:10149000060200000602000006020000060200002C +:1014A000060200000602000006020000060200001C +:1014B000060200000602000006020000060200000C +:1014C00006020000060200000602000006020000FC +:1014D00006020000060200000602000006020000EC +:1014E00006020000060200000602000006020000DC +:1014F00006020000060200000602000006020000CC +:10150000300200005202000080020000C40200000D +:10151000C4020000C402000074020000A602000021 +:10152000C4020000AC020000C40200007A02000005 +:10153000C4020000C4020000C4020000C402000093 +:10154000C4020000C4020000C4020000C402000083 +:10155000C4020000C4020000C4020000C402000073 +:1015600086020000C402000094020000C4020000D1 +:10157000C4020000C4020000C4020000C402000053 +:10158000C4020000C4020000C4020000C402000043 +:10159000C4020000C4020000C4020000C402000033 +:1015A000C4020000C4020000C4020000C402000023 +:1015B000C4020000C4020000C4020000C402000013 +:1015C000C4020000C4020000C4020000C402000003 +:1015D000C4020000C4020000C4020000C4020000F3 +:1015E000C4020000C4020000B8020000C4020000EF +:1015F000C4020000C4020000C4020000C4020000D3 +:10160000C4020000C4020000C4020000C4020000C2 +:10161000C4020000C4020000C4020000C4020000B2 +:10162000C4020000C4020000C4020000C4020000A2 +:10163000C4020000C4020000C4020000C402000092 +:10164000C4020000C4020000C4020000C402000082 +:10165000C4020000C4020000C4020000C402000072 +:10166000B2020000F8FFFFFFFCFFFFFFFFFFFFFFDC +:10167000FBFFFFFFFEFFFFFF010000001200000064 +:10168000020000000C000000090000000300000040 +:101690000400000005000000060000000700000034 +:1016A0000A4C617374206368616E6E656C3A0A2837 +:1016B0006E6F6E65292020202020202020202020F1 +:1016C0002020200A4C617374206D65737361676517 +:1016D0003A0A286E6F6E65292020202020202020C5 +:1016E0002020202020200A733A2053656E640A715E +:1016F0003A2051756974000A2020202020202020E3 +:101700002020202020202020202020200A202020EF +:1017100020202020202020202020202020202020C9 +:10172000200A2020202020202020202020202020CF +:101730002020202020200A202020202020202020BF +:1017400020202020202020202020200A20202020AF +:101750002020202020202020202020202020202089 +:101760000A2020202020202020202020202020208F +:0717700020202020200000D2 +:00000001FF diff --git a/c/menu/menu.o b/c/menu/menu.o new file mode 100644 index 0000000..43e4e58 Binary files /dev/null and b/c/menu/menu.o differ diff --git a/c/menu/rvcontroller.ld b/c/menu/rvcontroller.ld new file mode 100644 index 0000000..985892b --- /dev/null +++ b/c/menu/rvcontroller.ld @@ -0,0 +1,45 @@ +/* Thanks https://github.com/darklife/darkriscv */ + __heap_size = 0x200; /* required amount of heap */ + __stack_size = 0x800; /* required amount of stack */ + ENTRY(_start); + MEMORY + { + RAM (rwx) : ORIGIN = 0x00000000, LENGTH = 0x10000 + } + SECTIONS + { + .text : + { + *(.text.startup) + *(.text) + *(.text) + *(.rodata*) + } > RAM + .data : + { + *(.sbss) + *(.data) + *(.bss) + *(.rela*) + *(COMMON) + } > RAM + + .heap : + { + . = ALIGN(4); + PROVIDE ( end = . ); + _sheap = .; + . = . + __heap_size; + . = ALIGN(4); + _eheap = .; + } >RAM + + .stack : + { + . = ALIGN(4); + _estack = .; + . = . + __stack_size; + . = ALIGN(4); + _sstack = .; + } >RAM + } diff --git a/c/menu/screensaver.c b/c/menu/screensaver.c new file mode 100644 index 0000000..70e1647 --- /dev/null +++ b/c/menu/screensaver.c @@ -0,0 +1,137 @@ +/* Menu Thing for RVController - Screensaver + * A product of Advanced Mesecons Devices, a Cheapie Systems company + * This is free and unencumbered software released into the public domain. + * See http://unlicense.org/ for more information */ + +#include +#include +#include "rvcontroller-ecalls.h" + +char screensaverbuf[] = "\n \n \n \n \n \n "; + +int strlen(char *string) { + int i; + for (i = 0;string[i] != 0;i++) {} + return i; +} + +void screensaverWriteText(char *text, int column, int row, bool erase) { + int textlen = strlen(text); + if (column < 0) { + // Cut the left side off of the text and change the start position to the left side of the screen + text = text + (0 - column); + textlen = textlen + column; + column = 0; + } else if (column + textlen > 19) { + // Cut the right side off of the text + textlen = 20 - column; + } + for (int i=0;i < textlen;i++) { + if (erase) { + screensaverbuf[(row*21)+column+i+1] = 0x20; + } else { + screensaverbuf[(row*21)+column+i+1] = text[i]; + } + } +} + +void doMarquee(void) { + char text[] = "RVController "; + int col = 19; + int row = randomint(0,5); + console_clearbuffer(); + while (console_readchar() == 0) { + col--; + if (col < (0 - strlen(text))) { + col = 20; + row = randomint(0,5); + } + screensaverWriteText(text,col,row,false); + printstr(screensaverbuf); + } + screensaverWriteText(text,col,row,true); +} + +void doBouncingText(void) { + char text[] = "RVController"; + int col = 0; + int row = 0; + int xdir = 1; + int ydir = 1; + console_clearbuffer(); + while (console_readchar() == 0) { + screensaverWriteText(text,col,row,true); + col = col + xdir; + row = row + ydir; + if (col <= 0) { xdir = 1; } + if (col >= (19 - strlen(text))) { xdir = -1; } + if (row <= 0) { ydir = 1; } + if (row >= 5) { ydir = -1; } + screensaverWriteText(text,col,row,false); + printstr(screensaverbuf); + } + screensaverWriteText(text,col,row,true); +} + +void doMatrix(void) { + int row[] = {-8,-4,-1,-5,-2}; // "Random" positions off the top of the screen to give "random" start delays + int col[] = {1,18,2,12,9}; + int len[] = {3,4,5,6,7}; + char textscratch[] = " "; + console_clearbuffer(); + while (console_readchar() == 0) { + for (int i=0;i<=4;i++) { + row[i]++; + textscratch[0] = randomint(0x21,0x7a); + if (row[i] <= 5 && row[i] >= 0) { + screensaverWriteText(textscratch,col[i],row[i],false); + } + if ((row[i] - len[i]) <= 5 && (row[i] - len[i]) >= 0) { + screensaverWriteText(textscratch,col[i],(row[i] - len[i]),true); + } else if ((row[i] - len[i]) > 5 && randomint(0,1) == 1) { + row[i] = 0 - randomint(1,3); + col[i] = randomint(0,19); + len[i] = randomint(2,8); + } + } + printstr(screensaverbuf); + } + for (int i=0;i <= 5;i++) { + screensaverWriteText(" ",0,i,true); + } +} + +void runScreensaver(void) { + char inputbuf[9]; + bool quit = false; + while (!quit) { + printstr("\n\n\n\n\n\n\n"); + printstr("SCREENSAVER\n"); + printstr("1: Marquee\n"); + printstr("2: Bouncing Text\n"); + printstr("3: Matrix\n"); + printstr("\n"); + printstr("0: Exit"); + readstr(inputbuf,2); + switch (inputbuf[0]) { + case '0': + quit = true; + break; + case '1': + doMarquee(); + quit = true; + break; + case '2': + doBouncingText(); + quit = true; + break; + case '3': + doMatrix(); + quit = true; + break; + default: + printstr("\nInvalid option\n\nPress any key\n\n\n"); + readstr(inputbuf,1); + } + } +} diff --git a/c/menu/screensaver.h b/c/menu/screensaver.h new file mode 100644 index 0000000..f56811a --- /dev/null +++ b/c/menu/screensaver.h @@ -0,0 +1,6 @@ +/* Menu Thing for RVController - Screensaver + * A product of Advanced Mesecons Devices, a Cheapie Systems company + * This is free and unencumbered software released into the public domain. + * See http://unlicense.org/ for more information */ + +void runScreensaver(void); diff --git a/c/menu/screensaver.o b/c/menu/screensaver.o new file mode 100644 index 0000000..1f725d3 Binary files /dev/null and b/c/menu/screensaver.o differ diff --git a/c/rrxing/Makefile b/c/rrxing/Makefile new file mode 100644 index 0000000..1087a53 --- /dev/null +++ b/c/rrxing/Makefile @@ -0,0 +1,20 @@ +all: rrxing.hex + +rrxing.o: rrxing.c + clang -target riscv32-none-elf -I../rvcontroller-libraries -march=rv32imacb_zicntr_zicond_zicsr_zifencei_zihintpause_zilsd_zclsd_zabha_zacas_zbkb_zbkx_zcb_zcmp_zcmt -ffreestanding -O3 -c -o rrxing.o rrxing.c + +rrxing.elf: ../rvcontroller-libraries/rvcontroller-init.o ../rvcontroller-libraries/rvcontroller-ecalls.o rrxing.o + riscv32-none-elf-ld -T rvcontroller.ld --no-warn-rwx-segments -o rrxing.elf ../rvcontroller-libraries/rvcontroller-init.o rrxing.o ../rvcontroller-libraries/rvcontroller-ecalls.o + +dump: rrxing.elf + riscv32-none-elf-objdump -d rrxing.elf + +rrxing.hex: rrxing.elf + riscv32-none-elf-objcopy -O ihex rrxing.elf rrxing.hex + +load: rrxing.hex + bash -c "wl-copy < rrxing.hex" + +clean: + rm -f rrxing.bin rrxing.elf rrxing.o init.o + diff --git a/c/rrxing/rrxing.c b/c/rrxing/rrxing.c new file mode 100644 index 0000000..e867e8a --- /dev/null +++ b/c/rrxing/rrxing.c @@ -0,0 +1,86 @@ +#include +#include +#include "rvcontroller-ecalls.h" + +bool streq(char *a, char *b) { + for (int i=0;a[i] != 0 || b[i] != 0;i++) { + if (a[i] != b[i]) { + return false; + } + } + return true; +} + +void sleep(uint32_t delay) { + //This will start having problems after about 130 years + //of uptime, but that's probably acceptable + uint32_t endtime = rdtime() + delay; + while (rdtime() < endtime) {} + return; +} + +bool checkdetector(void) { + char channelbuf[16]; + char msgbuf[16]; + while (digiline_bufferlevel() > 0) { + lightweight_mode(0); + digiline_receive(channelbuf,16,msgbuf,16); + if (streq(channelbuf,"detect")) { + return true; + } + } + lightweight_mode(1); + return false; +} + +void main() { + printstr("Railroad Crossing\nfor RVController\nInitializing HW\n"); + digiline_send("light","OFF"); + digiline_send("bell","off"); + digiline_send("gate","up"); + digiline_clearbuffer(); + while (true) { + printstr("Idle\n"); + lightweight_mode(1); + printstr("Lightweight: On\n"); + while (!checkdetector()) {} + printstr("Train detected\nLightweight: Off\n"); + lightweight_mode(0); + digiline_send("light","YELLOW"); + printstr("Light: Yellow\n"); + sleep(2); + digiline_send("bell","on"); + printstr("Bell: On\n"); + sleep(2); + digiline_send("light","RED"); + printstr("Light: Red\n"); + sleep(3); + digiline_send("gate","down"); + printstr("Gate: Down\n"); + sleep(4); + digiline_send("bell","off"); + printstr("Bell: Off\n"); + + digiline_clearbuffer(); + for (uint8_t time = 15;time > 0;time--) { + printstr("Timeout in "); + printint(time); + printstr("s\n"); + sleep(1); + bool train = checkdetector(); + lightweight_mode(0); //checkdetector() turns this on + if (train) { + digiline_clearbuffer(); + time = 25; + printstr("Time reset by train\n"); + } + } + printstr("Timed out\n"); + + digiline_send("gate","up"); + printstr("Gate: Up\n"); + sleep(2); + digiline_send("light","OFF"); + printstr("Light: Off\n"); + } +} diff --git a/c/rrxing/rrxing.elf b/c/rrxing/rrxing.elf new file mode 100755 index 0000000..fd70937 Binary files /dev/null and b/c/rrxing/rrxing.elf differ diff --git a/c/rrxing/rrxing.hex b/c/rrxing/rrxing.hex new file mode 100644 index 0000000..a6ac7d8 --- /dev/null +++ b/c/rrxing/rrxing.hex @@ -0,0 +1,70 @@ +:10000000370101006520A948730000008280148137 +:10001000988133E6E60009C685050505E389E6FE15 +:1000200013351600828052B82A84452C2A947524F0 +:10003000E36F85FE52BE4EB822F44AF0692435C102 +:100040001309400693045006130440079309300631 +:1000500019A0952C39C50145612C0808C1450A86AF +:10006000C146BD2403450101E31525FF03451101E8 +:10007000E31195FE03452101E31D85FC0345310194 +:10008000E31995FC03454101E31535FD0345510195 +:10009000E31185FC034561014DFD0545227402799C +:1000A0004EBE0545B124227402794EBC4EB80111F2 +:1000B000A2E4CAE052FC5AF862F46AF01305203355 +:1000C000F522130460369305C0362285C52A9309AC +:1000D0000037930550374E85D52213059037930589 +:1000E000E037E92A0924930B4006130C5006930DC0 +:1000F000400713093006930C8040130D4041930ACA +:100100007041130510385D220545DD221305703856 +:10011000712A552A21C50145E12A0808C1450A86E8 +:10012000C1467D2203450101E31575FF0345110119 +:10013000E31185FF03452101E31DB5FD03453101B1 +:10014000E31985FD03454101E31525FD03455101F3 +:10015000E311B5FD034561014DFD21A00545492A87 +:100160004DBF1305803999220145592222859305F7 +:10017000903BA9221305003C152A852293042500F3 +:10018000A92AE36F95FE4E859305F03C052A1305D9 +:10019000203D292A9922930425008122E36F95FEB0 +:1001A00022859305C03D192A1305003E0122352200 +:1001B000930435001D22E36F95FE130590379305D8 +:1001C000C03EED281305103FD520012A93044500B9 +:1001D0002922E36F95FE4E8A4E8593055037F92804 +:1001E0001305D03FE1200122BD4909A80545092298 +:1001F0000145FD28FD1913F5F90F3DC913FBF90F52 +:1002000066856D205A8579286A854D20F9209304EA +:100210001500E120E36F95FE7D2069D90145C928CD +:100220000808C1450A86C146652003450101E3155A +:1002300075FF03451101E31185FF03452101E31D0E +:10024000B5FD03453101E31985FD03454101E31582 +:1002500025FD03455101E311B5FD034561014DFD48 +:100260004128512056859920E14913F5F90F59F598 +:100270001305C0422528130590379305E0373D2824 +:10028000130570432520912893042500B920E36FBE +:1002900095FE22859305C03615201305104439209C +:1002A000D28985B58548730000008280914873002B +:1002B00000008280AD48730000008280930810081F +:1002C0007300000082809308500873000000828051 +:1002D00093087008730000008280732510C082802C +:1002E000732500C08280930860087300000082803C +:1002F0000589F322008093920248B3E2A200739032 +:100300000280828095487300000082809308000874 +:10031000730000008280A14873000000828093086F +:1003200030087300000082809308400873000000CA +:1003300082805261696C726F61642043726F737363 +:10034000696E670A666F72205256436F6E74726FE1 +:100350006C6C65720A496E697469616C697A696E60 +:10036000672048570A006C69676874004F4646006A +:1003700062656C6C006F666600676174650075701D +:100380000049646C650A004C696768747765696741 +:1003900068743A204F6E0A00547261696E20646579 +:1003A0007465637465640A4C696768747765696726 +:1003B00068743A204F66660A0059454C4C4F570006 +:1003C0004C696768743A2059656C6C6F770A006FE6 +:1003D0006E0042656C6C3A204F6E0A005245440034 +:1003E0004C696768743A205265640A00646F776EDE +:1003F00000476174653A20446F776E0A0042656C6D +:100400006C3A204F66660A0054696D656F757420FA +:10041000696E2000730A0054696D6520726573650A +:100420007420627920747261696E0A0054696D6586 +:1004300064206F75740A00476174653A2055700A2C +:0D044000004C696768743A204F66660A0038 +:00000001FF diff --git a/c/rrxing/rrxing.o b/c/rrxing/rrxing.o new file mode 100644 index 0000000..3d0bd00 Binary files /dev/null and b/c/rrxing/rrxing.o differ diff --git a/c/rrxing/rvcontroller.ld b/c/rrxing/rvcontroller.ld new file mode 100644 index 0000000..985892b --- /dev/null +++ b/c/rrxing/rvcontroller.ld @@ -0,0 +1,45 @@ +/* Thanks https://github.com/darklife/darkriscv */ + __heap_size = 0x200; /* required amount of heap */ + __stack_size = 0x800; /* required amount of stack */ + ENTRY(_start); + MEMORY + { + RAM (rwx) : ORIGIN = 0x00000000, LENGTH = 0x10000 + } + SECTIONS + { + .text : + { + *(.text.startup) + *(.text) + *(.text) + *(.rodata*) + } > RAM + .data : + { + *(.sbss) + *(.data) + *(.bss) + *(.rela*) + *(COMMON) + } > RAM + + .heap : + { + . = ALIGN(4); + PROVIDE ( end = . ); + _sheap = .; + . = . + __heap_size; + . = ALIGN(4); + _eheap = .; + } >RAM + + .stack : + { + . = ALIGN(4); + _estack = .; + . = . + __stack_size; + . = ALIGN(4); + _sstack = .; + } >RAM + } diff --git a/c/rvcontroller-libraries/Makefile b/c/rvcontroller-libraries/Makefile new file mode 100644 index 0000000..eca2a8c --- /dev/null +++ b/c/rvcontroller-libraries/Makefile @@ -0,0 +1,10 @@ +all: rvcontroller-init.o rvcontroller-ecalls.o + +rvcontroller-init.o: rvcontroller-init.S + riscv32-none-elf-as -march=rv32imcb_zicsr_zbkx -o rvcontroller-init.o rvcontroller-init.S + +rvcontroller-ecalls.o: rvcontroller-ecalls.S + riscv32-none-elf-as -march=rv32imcb_zicsr_zbkx -o rvcontroller-ecalls.o rvcontroller-ecalls.S + +clean: + rm -f rvcontroller-init.o rvcontroller-ecalls.o diff --git a/c/rvcontroller-libraries/rvcontroller-ecalls.S b/c/rvcontroller-libraries/rvcontroller-ecalls.S new file mode 100644 index 0000000..454bcb6 --- /dev/null +++ b/c/rvcontroller-libraries/rvcontroller-ecalls.S @@ -0,0 +1,108 @@ +#RVController ecall C Library - Assembly Portion +#A product of Advanced Mesecons Devices, a Cheapie Systems company +#This is free and unencumbered software released into the public domain. +#See http://unlicense.org/ for more information + +printint: +# Number to print is already in a0 +li a7,1 # Write number +ecall +ret + +printstr: +# String address is already in a0 +li a7,4 +ecall +ret + +printchar: +# Character is already in a0 +li a7,11 +ecall +ret + +digiline_send: +# Channel pointer is already in a0, message pointer is already in a1 +li a7,129 +ecall +ret + +digiline_bufferlevel: +li a7,133 +ecall +# Result is already in a0 +ret + +digiline_receive: +# Arguments are already in a0-a3 +li a7,135 +ecall +ret + +rdtime: +rdtime a0 +ret + +rdcycle: +rdcycle a0 +ret + +digiline_clearbuffer: +li a7,134 +ecall +ret + +lightweight_mode: +andi a0,a0,1 +csrrs t0,0x800,x0 +bclri t0,t0,0 +or t0,t0,a0 +csrrw x0,0x800,t0 +ret + +readint: +li a7,5 +ecall +# Result is already in a0 +ret + +randomint: +li a7,128 +# Arguments are already in a0 and a1 +ecall +# Result is already in a0 +ret + +readstr: +li a7,8 +# Arguments are already in a0 and a1 +ecall +# Result is already in a0 +ret + +console_clearbuffer: +li a7,131 +ecall +ret + +console_readchar: +li a7,132 +ecall +# Result is already in a0 +ret + +.globl printint +.globl printstr +.globl printchar +.globl digiline_send +.globl digiline_bufferlevel +.globl digiline_receive +.globl rdtime +.globl rdcycle +.globl digiline_clearbuffer +.globl lightweight_mode +.globl readint +.globl randomint +.globl readstr +.globl console_clearbuffer +.globl console_readchar diff --git a/c/rvcontroller-libraries/rvcontroller-ecalls.h b/c/rvcontroller-libraries/rvcontroller-ecalls.h new file mode 100644 index 0000000..7107d21 --- /dev/null +++ b/c/rvcontroller-libraries/rvcontroller-ecalls.h @@ -0,0 +1,108 @@ +/* RVController ecall C Library - C Header Portion + * A product of Advanced Mesecons Devices, a Cheapie Systems company + * This is free and unencumbered software released into the public domain. + * See http://unlicense.org/ for more information */ + +#ifndef _STDINT_H +#include +#endif + +/* printint(number) + * + * Prints a 32-bit signed integer to standard output. + * number: The number to print */ +void printint(int32_t number); + +/* printstr(*str) + * + * Prints a null-terminated ASCII string to standard output. + * *str: Pointer to the start of the string data */ +void printstr(char *str); + +/* printchar(c) + * + * Prints a single ASCII character to standard output. + * c: The character to print */ +void printchar(char c); + +/* digiline_send(*channel,*msg) + * + * Sends an arbitrary digilines message on an arbitrary channel. + * *channel: Pointer to the start of the null-terminated channel string + * *msg: Pointer to the start of the null-terminated message string */ +void digiline_send(char *channel, char *msg); + +/* digiline_bufferlevel() + * + * Reads the current number of digilines messages that have been received + * but not yet read. + * Returns: Number of messages */ +uint8_t digiline_bufferlevel(void); + +/* digiline_receive(*channelbuf,channelbuflen,*msgbuf,msgbuflen) + * + * Reads the first (oldest) digilines message from the receive queue and removes + * the message from the queue. + * Null termination will be added to all received strings. + * *channelbuf: Pointer to the location of a buffer into which the channel will be placed + * channelbuflen: The size of the buffer pointed to by channelbuf + * *msgbuf: Pointer to the location of a buffer into which the message will be placed + * msgbuflen: The size of the buffer pointed to by channelbuf */ +void digiline_receive(char *channelbuf, int channelbuflen, char *msgbuf, int msgbuflen); + +/* rdcycle() + * + * Reads the number of clock cycles that have passed since the processor was started. + * Returns: Number of clock cycles */ +uint32_t rdcycle(void); + +/* rdtime() + * + * Reads the number of seconds that have elapsed since the processor was started. + * Returns: Number of seconds */ +uint32_t rdtime(void); + +/* digiline_clearbuffer() + * + * Discards all received digilines messages currently waiting in the queue. */ +void digiline_clearbuffer(void); + +/* lightweight_mode(enabled) + * + * Turns lightweight mode (see RVController documentation) or or off. + * enabled: 1 to enable, 0 to disable, other values are reserved */ +void lightweight_mode(char enabled); + +/* readint() + * + * Reads a 32-bit signed integer from the console. + * This will block until the user enters a valid number. + * returns: The number typed by the user */ +int32_t readint(void); + +/* readstr() + * + * Reads a null-terminated string from the console. + * This will block until the user enters something. + * buffer: Pointer to a buffer that the string will be stored in + * bufsize: The size of the buffer */ +void readstr(char *buffer, uint32_t bufsize); + +/* randomint(lowlimit,highlimit) + * + * Generates a random integer between lowlimit and highlimit. + * lowlimit: The lowest number that can be generated (inclusive) + * highlimit: The highest number that can be generated (inclusive) + * returns: Random number */ +int32_t randomint(int32_t lowlimit,int32_t highlimit); + +/* console_clearbuffer() + * + * Discards all characters currently waiting in the console input buffer. */ +void console_clearbuffer(void); + +/* console_readchar() + * + * Reads one character from the console input buffer. + * returns: Character, or 0 if no characters are available to read */ +char console_readchar(void); diff --git a/c/rvcontroller-libraries/rvcontroller-ecalls.o b/c/rvcontroller-libraries/rvcontroller-ecalls.o new file mode 100644 index 0000000..e23d3fe Binary files /dev/null and b/c/rvcontroller-libraries/rvcontroller-ecalls.o differ diff --git a/c/rvcontroller-libraries/rvcontroller-init.S b/c/rvcontroller-libraries/rvcontroller-init.S new file mode 100644 index 0000000..83cab9d --- /dev/null +++ b/c/rvcontroller-libraries/rvcontroller-init.S @@ -0,0 +1,26 @@ +#Assembly stub for C programs targeting RVController +#A product of Advanced Mesecons Devices, a Cheapie Systems company +#This is free and unencumbered software released into the public domain. +#See http://unlicense.org/ for more information + +#This file should always be linked first. +#RVController has a default reset vector of 0, +#therefore _start should end up as the first thing in the file. + +.section .text.startup +_start: + +# Set up stack pointer +li sp,0x10000 + +# Call main function +call main + +# Exit program +li a7,10 +ecall + +# Shouldn't ever get here, will crash if it does +ret + +.globl _start diff --git a/c/rvcontroller-libraries/rvcontroller-init.o b/c/rvcontroller-libraries/rvcontroller-init.o new file mode 100644 index 0000000..3f57faf Binary files /dev/null and b/c/rvcontroller-libraries/rvcontroller-init.o differ diff --git a/c/squares/Makefile b/c/squares/Makefile new file mode 100644 index 0000000..f957bfa --- /dev/null +++ b/c/squares/Makefile @@ -0,0 +1,20 @@ +all: squares.hex + +squares.o: squares.c + clang -target riscv32-none-elf -I../rvcontroller-libraries -march=rv32imacb_zicntr_zicond_zicsr_zifencei_zihintpause_zilsd_zclsd_zabha_zacas_zbkb_zbkx_zcb_zcmp_zcmt -ffreestanding -O3 -c -o squares.o squares.c + +squares.elf: ../rvcontroller-libraries/rvcontroller-init.o ../rvcontroller-libraries/rvcontroller-ecalls.o squares.o + riscv32-none-elf-ld -T rvcontroller.ld --no-warn-rwx-segments -o squares.elf ../rvcontroller-libraries/rvcontroller-init.o squares.o ../rvcontroller-libraries/rvcontroller-ecalls.o + +dump: squares.elf + riscv32-none-elf-objdump -d squares.elf + +squares.hex: squares.elf + riscv32-none-elf-objcopy -O ihex squares.elf squares.hex + +load: squares.hex + bash -c "wl-copy < squares.hex" + +clean: + rm -f squares.bin squares.elf squares.o init.o + diff --git a/c/squares/rvcontroller.ld b/c/squares/rvcontroller.ld new file mode 100644 index 0000000..985892b --- /dev/null +++ b/c/squares/rvcontroller.ld @@ -0,0 +1,45 @@ +/* Thanks https://github.com/darklife/darkriscv */ + __heap_size = 0x200; /* required amount of heap */ + __stack_size = 0x800; /* required amount of stack */ + ENTRY(_start); + MEMORY + { + RAM (rwx) : ORIGIN = 0x00000000, LENGTH = 0x10000 + } + SECTIONS + { + .text : + { + *(.text.startup) + *(.text) + *(.text) + *(.rodata*) + } > RAM + .data : + { + *(.sbss) + *(.data) + *(.bss) + *(.rela*) + *(COMMON) + } > RAM + + .heap : + { + . = ALIGN(4); + PROVIDE ( end = . ); + _sheap = .; + . = . + __heap_size; + . = ALIGN(4); + _eheap = .; + } >RAM + + .stack : + { + . = ALIGN(4); + _estack = .; + . = . + __stack_size; + . = ALIGN(4); + _sstack = .; + } >RAM + } diff --git a/c/squares/squares.b b/c/squares/squares.b new file mode 100644 index 0000000..b235485 --- /dev/null +++ b/c/squares/squares.b @@ -0,0 +1,8 @@ +++++[>+++++<-]>[<+++++>-]+<+[ + >[>+>+<<-]++>>[<<+>>-]>>>[-]++>[-]+ + >>>+[[-]++++++>>>]<<<[[<++++++++<++>>-]+<.<[>----<-]<] + <<[>>>>>[>>>[-]+++++++++<[>-<-]+++++++++>[-[<->-]+[<<<]]<[>+<-]>]<<-]<<- +] +[Outputs square numbers from 0 to 10000. +Daniel B Cristofani (cristofdathevanetdotcom) +http://www.hevanet.com/cristofd/brainfuck/] diff --git a/c/squares/squares.c b/c/squares/squares.c new file mode 100644 index 0000000..435ddff --- /dev/null +++ b/c/squares/squares.c @@ -0,0 +1,169 @@ +/* This is a translation of squares.b, generated by bftoc.py (by Paul Kaefer) + * It was generated on Friday, May 15, 2026 at 07:20PM + */ + +#include "rvcontroller-ecalls.h" + +void main(void) +{ + int size = 1000; + int tape[size]; + int i = 0; + + /* Clearing the tape (array) */ + for (i=0; i " +toolowmsg: .asciz "Too low! Try again\n" +toohighmsg: .asciz "Too high! Try again\n" +correctmsg: .asciz "Correct!\nYou got it in:\n" +guessesmsg: .asciz " guess" +guessespluralize: .asciz "es" +seconds: .asciz " seconds" +playagainmsg: .asciz "Play again? [Y/n]" diff --git a/guessnum.S b/guessnum.S new file mode 100644 index 0000000..8d5b2fb --- /dev/null +++ b/guessnum.S @@ -0,0 +1,119 @@ +restart: +rdtime t3 # Get the time the program was started at + +li a7,11 # Print character +li a0,0xa # \n +ecall +li t0,0 # Number of guesses + +# Get a random number for the player to guess +li a7,128 # Get random integer +li a0,1 # Lower bound = 1 +li a1,99 # Upper bound = 99 +ecall +mv t1,a0 # Put the result in t1 where it's expected + +loop: +# Increment number of guesses +addi t0,t0,1 + +# Prompt player to enter their guess +li a7,4 # Write string +la a0,prompt # 'Enter your guess' prompt address +ecall + +# Read the player's guess +li a7,5 # Read integer +ecall +mv t2,a0 # Store it in t2 + +# Print it back out +li a7,1 # Write integer +ecall +li a7,11 # Write character +li a0,0xa # \n +ecall + +# Too low? +blt t2,t1,toolow + +# Too high? +blt t1,t2,toohigh + +# Otherwise it must be right +j correct + +toolow: +# Show too low message +li a7,4 # Write string +la a0,toolowmsg +ecall +j loop # Go back for the next guess + +toohigh: +# Show too high message +li a7,4 # Write string +la a0,toohighmsg +ecall +j loop # Go back for the next guess + +correct: +# Show congratulations message +li a7,4 # Write string +la a0,correctmsg +ecall + +# Show number of guesses +mv a0,t0 # Get the number of guesses +li a7,1 # Write integer +ecall + +# Add proper suffix depending on whether it should be plural or not +li a7,4 # Write string +la a0,guessesmsg # "guess" +ecall +li t2,1 +beq t0,t2,playagain # Leave it singular if it was 1 +la a0,guessespluralize # "es" +ecall + +playagain: +li a7,11 # Write character +li a0,0xa # \n +ecall +# Show the number of seconds the player took +rdtime t4 # Get the current time +sub a0,t4,t3 # Subtract the start time +li a7,1 # Write integer +ecall +li a7,4 # Write string +la a0,seconds +ecall + +li a7,11 # Print character +li a0,0xa # \n +ecall + +# Ask the user if they want to play again +li a7,4 # Write string +la a0,playagainmsg +ecall +li a7,12 # Read character +ecall +li a7,11 # Write character +ecall +li t0,0x6e # n +bne a0,t0,restart + +li a7,10 # Exit program +ecall + + +prompt: .asciz "Enter your guess:\n> " +toolowmsg: .asciz "Too low! Try again\n" +toohighmsg: .asciz "Too high! Try again\n" +correctmsg: .asciz "Correct!\nYou got it in:\n" +guessesmsg: .asciz " guess" +guessespluralize: .asciz "es" +seconds: .asciz " seconds" +playagainmsg: .asciz "Play again? [Y/n]" diff --git a/hello.S b/hello.S new file mode 100644 index 0000000..3eecf13 --- /dev/null +++ b/hello.S @@ -0,0 +1,6 @@ +la a0,message +li a7,4 +ecall +li a7,10 +ecall +message: .asciz "Hello, world!\n" diff --git a/loader.lua b/loader.lua new file mode 100644 index 0000000..0622dc9 --- /dev/null +++ b/loader.lua @@ -0,0 +1,83 @@ +--RVController Loader +--A product of Advanced Mesecons Devices, a Cheapie Systems company +--This is free and unencumbered software released into the public domain. +--See http://unlicense.org/ for more information + +local function formspec_escape(text) + local ret = "" + local badchars = { + ["\\"] = true, + ["["] = true, + ["]"] = true, + [";"] = true, + [","] = true + } + for i=1,string.len(text),1 do + local char = string.sub(text,i,i) + if badchars[char] then ret = ret.."\\" end + ret = ret..char + end + return ret +end + +local function sendfs() + digiline_send("touchscreen","formspec_version[10]size[15,15]textarea[0,0;15,14;program;;"..formspec_escape(mem.data).."]button_exit[6.5,14;2,1;go;Load]checkbox[0.5,14.5;autorun;Run after load;"..tostring(mem.autorun).."]") +end + +if event.type == "program" then + mem.autorun = true + mem.data = "(paste Intel HEX data here)" + sendfs() +elseif event.channel == "touchscreen" and event.msg.autorun then + mem.autorun = event.msg.autorun == "true" + mem.data = event.msg.program + sendfs() +elseif event.channel == "touchscreen" and event.msg.go then + mem.data = event.msg.program + mem.addresshigh = 0 + mem.addressmid = 0 + digiline_send("reset","") + interrupt(1,"tick") +elseif event.iid == "tick" then + local nlpos = string.find(mem.data,"\n",1,true) + local thisline + if nlpos then + thisline = string.sub(mem.data,1,nlpos-1) + mem.data = string.sub(mem.data,nlpos+1,-1) + else + thisline = mem.data + mem.data = "" + end + local startpos = string.find(thisline,":",1,true) + local eof = false + if startpos then + thisline = string.sub(thisline,startpos+1,-1) + local rectype = string.sub(thisline,7,8) + if rectype == "00" then + --data + local bytecount = tonumber(string.sub(thisline,1,2),16) + local addresslow = tonumber(string.sub(thisline,3,6),16) + local linedata = string.sub(thisline,9,-3) + local address = (mem.addresshigh*2^16)+(mem.addressmid*2^4)+addresslow + digiline_send("load",{address=address,data=linedata,size=bytecount}) + elseif rectype == "01" then + --end of file + eof = true + digiline_send("load",{done=true,autorun=mem.autorun}) + elseif rectype == "02" then + --extended segment address + mem.addressmid = tonumber(string.sub(thisline,9,12),16) + elseif rectype == "04" then + --extended linear address + mem.addresshigh = tonumber(string.sub(thisline,9,12),16) + end + end + if string.len(mem.data) > 0 and not eof then + interrupt(0.05,"tick") + else + mem.data = "(paste Intel HEX data here)" + sendfs() + end +elseif event.iid == "run" then + digiline_send("monitorkb","run") +end diff --git a/misa.S b/misa.S new file mode 100644 index 0000000..4bd93ef --- /dev/null +++ b/misa.S @@ -0,0 +1,112 @@ +csrr t0,0x301 # Read misa + +li a7,11 # Print character +li a0,'R' +ecall +li a0,'V' +ecall +li a0,'3' +ecall +li a0,'2' +ecall + +bexti t1,t0,8 +li a7,11 +li a0,'I' +czero.eqz a7,a7,t1 # Clear ecall function if bit isn't set +ecall + +bexti t1,t0,4 +li a7,11 +li a0,'E' +czero.eqz a7,a7,t1 +ecall + +bexti t1,t0,12 +li a7,11 +li a0,'M' +czero.eqz a7,a7,t1 +ecall + +bexti t1,t0,0 +li a7,11 +li a0,'A' +czero.eqz a7,a7,t1 +ecall + +bexti t1,t0,5 +li a7,11 +li a0,'F' +czero.eqz a7,a7,t1 +ecall + +bexti t1,t0,3 +li a7,11 +li a0,'D' +czero.eqz a7,a7,t1 +ecall + +bexti t1,t0,16 +li a7,11 +li a0,'Q' +czero.eqz a7,a7,t1 +ecall + +bexti t1,t0,11 +li a7,11 +li a0,'L' +czero.eqz a7,a7,t1 +ecall + +bexti t1,t0,2 +li a7,11 +li a0,'C' +czero.eqz a7,a7,t1 +ecall + +bexti t1,t0,1 +li a7,11 +li a0,'B' +czero.eqz a7,a7,t1 +ecall + +bexti t1,t0,9 +li a7,11 +li a0,'J' +czero.eqz a7,a7,t1 +ecall + +bexti t1,t0,19 +li a7,11 +li a0,'T' +czero.eqz a7,a7,t1 +ecall + +bexti t1,t0,15 +li a7,11 +li a0,'P' +czero.eqz a7,a7,t1 +ecall + +bexti t1,t0,21 +li a7,11 +li a0,'V' +czero.eqz a7,a7,t1 +ecall + +bexti t1,t0,7 +li a7,11 +li a0,'H' +czero.eqz a7,a7,t1 +ecall + +bexti t1,t0,18 +li a7,11 +li a0,'S' +czero.eqz a7,a7,t1 +ecall + +bexti t1,t0,2 + +li a7,10 +ecall diff --git a/rrxing.S b/rrxing.S new file mode 100644 index 0000000..61fb41c --- /dev/null +++ b/rrxing.S @@ -0,0 +1,198 @@ +li a7,134 # Clear digilines buffer +ecall + +restart: +# Hardware initialization + +# Make sure light is off +li a7,129 # Send digilines message +la a0,lightchannel +la a1,lightoffmsg +ecall + +# Make sure bell is off +li a7,129 # Send digilines message +la a0,bellchannel +la a1,belloffmsg +ecall + +# Make sure gate is up +li a7,129 # Send digilines message +la a0,gatechannel +la a1,gateupmsg +ecall + +receiveloop: +li a7,133 # Get digilines buffer level +ecall +beq a0,x0,receiveloop # If no messages yet, restart the loop + +li a7,135 # Read digilines message +la a0,channelbuf +li a1,16 # Channel buffer size +la a2,msgbuf +li a3,16 # Message buffer size +ecall + +# Check if it's the right channel +la a0,channelbuf +la a1,detectchannel +call strcmp +beq a0,x0,receiveloop # Not the right channel, ignore it + +# Turn the light yellow +li a7,129 # Send digilines message +la a0,lightchannel +la a1,lightyellowmsg +ecall + +# Wait 1 second +li a0,1 +call sleep + +# Turn the bell on +li a7,129 # Send digilines message +la a0,bellchannel +la a1,bellonmsg +ecall + +# Wait 2 seconds +li a0,2 +call sleep + +# Turn the light red +li a7,129 # Send digilines message +la a0,lightchannel +la a1,lightredmsg +ecall + +# Wait 3 seconds +li a0,3 +call sleep + +# Lower the gate +li a7,129 # Send digilines message +la a0,gatechannel +la a1,gatedownmsg +ecall + +# Wait 5 seconds +li a0,5 +call sleep + +# Turn the bell off +li a7,129 # Send digilines message +la a0,bellchannel +la a1,belloffmsg +ecall + +waitlonger: + +# Wait 10 seconds +li a0,10 +call sleep + +# Check if any more trains have been detected +receiveloop2: +li a7,133 # Get digilines buffer level +ecall +beq a0,x0,raise # If no messages yet, go ahead with timing out + +# If there is a message, check if it's a train + +li a7,135 # Read digilines message +la a0,channelbuf +li a1,16 # Channel buffer size +la a2,msgbuf +li a3,16 # Message buffer size +ecall + +# Check if it's the right channel +la a0,channelbuf +la a1,detectchannel +call strcmp +beq a0,x0,receiveloop2 # Not the right channel, ignore this message and go on to the next + +# If it is the right channel, then get rid of the rest of the messages (if any) +li a7,134 # Clear digilines buffer +ecall + +j waitlonger # And go wait another 10 seconds + +raise: + +# Raise the gate +li a7,129 # Send digilines message +la a0,gatechannel +la a1,gateupmsg +ecall + +# Wait 2 seconds +li a0,2 +call sleep + +# Turn the light off +li a7,129 # Send digilines message +la a0,lightchannel +la a1,lightoffmsg +ecall + +# And go wait for the next train +j restart + +sleep: + # Expects a number of seconds in a0 + # Uses t0 + rdtime t0 + add a0,t0,a0 + sleep_loop: + rdtime t0 + bltu t0,a0,sleep_loop +ret + +strcmp: + # Expects string pointers in a0 and a1 + # Compares until a NUL is reached on the first string + # Uses t0, t1, and t2 + # Returns a0=1 if strings match, a0=0 otherwise + li t0,0 # t0 is the loop counter + strcmp_loop: + # Calculate addresses + add t1,a0,t0 # t1 is the pointer for the first string + add t2,a1,t0 # t2 is the pointer for the second string + + # Read the bytes from each string + lb t1,0(t1) + lb t2,0(t2) + + # Increment the loop counter + addi t0,t0,1 + + # And compare + bne t1,t2,strcmp_mismatch + + # Check if a terminator was reached yet, keep going otherwise + li t2,0 + bne t1,t2,strcmp_loop + + # If we got here they match + li a0,1 + ret + + strcmp_mismatch: + li a0,0 + ret + +channelbuf: .ascii " " +msgbuf: .ascii " " +lightchannel: .asciz "light" +bellchannel: .asciz "bell" +gatechannel: .asciz "gate" +lightoffmsg: .asciz "OFF" +lightyellowmsg: .asciz "YELLOW" +lightredmsg: .asciz "RED" +bellonmsg: .asciz "on" +belloffmsg: .asciz "off" +gateupmsg: .asciz "up" +gatedownmsg: .asciz "down" +detectchannel: .asciz "detect" diff --git a/rvcontroller.ld b/rvcontroller.ld new file mode 100644 index 0000000..3203776 --- /dev/null +++ b/rvcontroller.ld @@ -0,0 +1,45 @@ +/* Thanks https://github.com/darklife/darkriscv */ + __heap_size = 0x200; /* required amount of heap */ + __stack_size = 0x800; /* required amount of stack */ + + MEMORY + { + RAM (rwx) : ORIGIN = 0x00000000, LENGTH = 0x10000 + } + SECTIONS + { + .text : + { + *(.boot) + *(.text) + *(.text) + *(.rodata*) + } > RAM + .data : + { + *(.sbss) + *(.data) + *(.bss) + *(.rela*) + *(COMMON) + } > RAM + + .heap : + { + . = ALIGN(4); + PROVIDE ( end = . ); + _sheap = .; + . = . + __heap_size; + . = ALIGN(4); + _eheap = .; + } >RAM + + .stack : + { + . = ALIGN(4); + _estack = .; + . = . + __stack_size; + . = ALIGN(4); + _sstack = .; + } >RAM + } diff --git a/rvcontroller.lua b/rvcontroller.lua new file mode 100644 index 0000000..3fda5db --- /dev/null +++ b/rvcontroller.lua @@ -0,0 +1,2604 @@ +--RVController +--A product of Advanced Mesecons Devices, a Cheapie Systems company +--This is free and unencumbered software released into the public domain. +--See http://unlicense.org/ for more information + +--[[ + +Emulated system specifications: + +Single RISC-V core, RV32IMACB_Zicntr_Zicond_Zicsr_Zifencei_Zihintpause_Zilsd_Zabha_Zacas_Zcb_Zclsd_Zcmp_Zcmt_Zbkb_Zbkx instruction set, little-endian +65536 bytes of RAM (configurable in settings below) starting at base address 0 + +Intended to be compliant with the following specifications: +* RV32I Base Integer Instruction Set, Version 2.1 +* "Zifencei" Extension for Instruction-Fetch Fence, Version 2.0 + - Note: Implemented as a 'nop' instruction as memory is always consistent (see note on RVWMO below) +* "Zicsr" Extension for Control and Status Register (CSR) Instructions, Version 2.0 +* "Zicond" Extension for Integer Conditional Operations, Version 1.0.0 +* "Zicntr" Extension for Counters, Version 2.0 +* "M" Extension for Integer Multiplication and Division, Version 2.0 + - Note: This implies the following: + - * Zmmul Extension, Version 1.0 +* "A" Extension for Atomic Instructions, Version 2.1 + - Note: This implies the following: + - * "Zalrsc" Extension for Load-Reserved/Store-Conditional Instructions + - * "Zaamo" Extension for Atomic Memory Operations +* RVWMO Memory Consistency Model, Version 2.0 + - Note: The actual implemented memory model is significantly more strict (memory is always consistent, there is no cache) +* "Ztso" Extension for Total Store Ordering, Version 1.0 +* "C" Extension for Compressed Instructions, Version 2.0 + - Note: This implies the following: + - * "Zca" Extension for Code Size Reduction, Version 1.0.0 +* Zcb: Extension for Code Size Reduction, Version 1.0.0 +* Zcmp: Extension for Code Size Reduction, Version 1.0.0 +* Zcmt: Extension for Code Size Reduction, Version 1.0.0 +* "B" Extension for Bit Manipulation, Version 1.0.0 + - Note: This implies the following: + - * Zba: Extension for Address generation, Version 1.0.0 + - * Zbb: Extension for Basic bit-manipulation, Version 1.0.0 + - * Zbs: Extension for Single-bit instructions, Version 1.0.0 +* "Zihintpause" Extension for Pause Hint, Version 2.0 +* Zilsd, Zclsd: Extensions for Load/Store pair for RV32, Version 1.0 +* "Zabha" Extension for Byte and Halfword Atomic Memory Operations, Version 1.0 +* "Zacas" Extension for Atomic Compare-and-Swap (CAS) Instructions, Version 1.0.0 +* Zbkb: Extension for Bit-manipulation for Cryptography, Version 1.0.0 +* Zbkx: Extension for Crossbar permutations, Version 1.0.0 + +See https://docs.riscv.org/reference/isa/unpriv/unpriv-index.html for full specifications. + +Monitor commands: + +peek
+Reads and displays the byte (8 bits) value from RAM at the specified address + +poke
+Writes the specified byte (8 bits) value to RAM at the specified address + +peekw
+Reads and displays the word (32 bits) value from RAM starting at the specified address + +pokew
+Writes the specified word (32 bits) value to RAM starting at the specified address + +getreg +Displays the current value of the specified register number (0-31) + +setreg +Sets the specified register (0-31) to the specified value + +getpc +Displays the current value of the program counter + +setpc +Sets the program counter to the specified value + +reset +Stops the CPU, resets all registers to zero, and clears all RAM + +step +Allows the CPU to run for one instruction, then halts + +run +Allows the CPU to run indefinitely + +stop +Halts the CPU + +setbreak
+Sets a breakpoint on the specified address. +Note that the breakpoint triggers just *before* the instruction fetch, +as in the instruction with the breakpoint on it will not have executed yet. +There can only be one breakpoint at a time. If one is already set, the new one will replace it. + +clearbreak +Clears any set breakpoint. Note that an ebreak instruction will still cause a break. + +help [command] +Shows information on a monitor command, or a list of commands if none is specified + + +ecall operations: + +a7 = 1 +Prints the integer value from register a0 + +a7 = 4 +Prints the null-terminated string from the address specified by register a0 + +a7 = 5 +Reads an integer from the console and stores it into register a0 +This will block until the user enters a valid number + +a7 = 8 +Reads a string from the console and stores it (with a null terminator) into the address pointed to by register a0 +Will not read more than the length specified in register a1, anything more is discarded +This will block until the user types something + +a7 = 10 +Exits the program (halts the CPU) + +a7 = 11 +Prints the character stored in the register a0 + +a7 = 12 +Reads one character from the console (any more characters on the line are discarded) and stores it into register a0 + +a7 = 128 +Gets a random integer (between the values in registers a0 and a1) and stores it into register a0 + +a7 = 129 +Sends a digilines string message: +* channel is specified by the null-terminated string at the address specified by register a0 +* message is specified by the null-terminated string at the address specified by register a1 + +a7 = 130 +Gets the number of characters available to read from the console input buffer +Result is stored in register a0 + +a7 = 131 +Clears the console input buffer + +a7 = 132 +Reads one character from the console input buffer and stores it into register a0 +This will not block - if no data is available to read, a NUL character (0) is returned +The input buffer can store up to 256 characters - if full, incoming characters are dropped + +a7 = 133 +Gets the number of messages in the digilines receive buffer +Result is stored in register a0 + +a7 = 134 +Clears the digilines receive buffer + +a7 = 135 +Reads one message from the digilines receive buffer, returns channel and message as null-terminated strings +This will not block - if no data is available to read, zero-length strings will be returned +Arguments: +a0 - Address that the channel string will be written to +a1 - Size of the buffer that the channel string will be written into +a2 - Address that the message will be written to +a3 - Size of the buffer that the message will be written into + +Custom CSRs: + +0x800[0] = Lightweight mode, controls processor clock speed and behavior when mapblock is unloaded: +0: 10 Hz (adjustable in settings below), processor does not stop when mapblock is unloaded +1: 1 Hz, processor stops when mapblock is unloaded +Note that when set to 0, a digilines message being received will cause the processor to run for one cycle. +This is intended to be used to check if the digilines message needs action to be taken in response, +and the program can then turn lightweight mode off if so. + +]] + +--Settings +local RAM_SIZE = 0x10000 --RAM size in bytes, must be a multiple of 256 +local CLOCK_SPEED = 20 --Clock speed in Hz when not in lightweight mode +local INSTRUCTIONS_PER_CLOCK = 50 --Maximum number of instructions that will be run on each clock cycle +local STDOUT_TO_TERMINAL = false --Whether to show standard output on the Luacontroller terminal in addition to the screen + + +local function implodebits(bits,count,signed) + local negative = false + if signed then + negative = bits[count-1] + end + local out = 0 + for i=0,count-1 do + if bits[i] then out = out + (2^i) end + end + if negative then out = out - (2^count) end + return out +end + +local function explodebits(num,count) + num = num%(2^count) + if num < 0 then + num = num + (2^count) + end + local out = {} + for i=0,count-1 do + out[i] = num%(2^(i+1)) >= 2^i + end + return out +end + +local function signextend(bits,fromcount,tocount) + for i=fromcount,tocount-1 do + bits[i] = bits[fromcount-1] + end +end + +local function mul64(a,b,asigned,bsigned) + --If in signed mode and the number is too big to be positive, make it negative + if asigned and a >= 2^31 then a = a - 2^32 end + if bsigned and b >= 2^31 then b = b - 2^32 end + + --Break 32-bit arguments into 16-bit pieces + local alow = a%2^16 + local ahigh = math.floor(a/2^16) + local blow = b%2^16 + local bhigh = math.floor(b/2^16) + + --Multiply 16x16-bit numbers to get 32-bit partial products + local pp1 = alow*blow + local pp2 = alow*bhigh + local pp3 = ahigh*blow + local pp4 = ahigh*bhigh + + --Split the two partial products that will straddle the 32-bit boundary + local pp2low = pp2%2^16 + local pp2high = math.floor(pp2/2^16) + local pp3low = pp3%2^16 + local pp3high = math.floor(pp3/2^16) + + --And give them the proper 16-bit shift + pp2low = pp2low*2^16 + pp3low = pp3low*2^16 + + --Sum the lower partial products into a 34-bit value + local lowresult = pp1+pp2low+pp3low + + --Split the upper 2 bits off into a carry value + local carry = math.floor(lowresult/2^32) + lowresult = lowresult%2^32 + + --Sum the upper partial products and carry + local highresult = carry+pp2high+pp3high+pp4 + + return lowresult,highresult +end + +local function getreg(reg) + return reg == 0 and 0 or mem.registers[reg] +end + +local function setreg(reg,val) + if val < 0 then val = val + (2^32) end + if reg ~= 0 then mem.registers[reg] = math.floor(val%(2^32)) end +end + +local function readram(address,bytes) + if address > RAM_SIZE-1 then + digiline_send("monitordisp",string.format("Out-of-bounds\nmemory read\nAddress: %08X\nPC: %08X\nSystem halted",address,mem.registers.pc)) + mem.running = false + return 0 + end + local out = 0 + for i=0,bytes-1 do + local offsetaddr = address+i + local segment = math.floor(offsetaddr/256) + local offset = offsetaddr%256 + out = out + (string.byte(string.sub(mem.ram[segment],offset+1,offset+1)) or 0) * 2^(8*i) + end + return out +end + +local function writeram(address,data,bytes) + if address > RAM_SIZE-1 then + digiline_send("monitordisp",string.format("Out-of-bounds\nmemory write\nAddress: %08X\nPC: %08X\nSystem halted",address,mem.registers.pc)) + mem.running = false + return + end + if mem.reservationset then + if mem.reservationset + 4 >= address and mem.reservationset <= address+bytes-1 then + mem.reservationset = nil + end + end + for i=0,bytes-1 do + local thisbyte = data % (2^((i+1)*8)) / 2^(i*8) + thisbyte = math.floor(thisbyte) % 2^32 + local offsetaddr = address+i + local segment = math.floor(offsetaddr/256) + local offset = offsetaddr%256 + mem.ram[segment] = string.sub(mem.ram[segment],0,offset)..string.char(thisbyte)..string.sub(mem.ram[segment],offset+2,-1) + end +end + +local stdoutdirty = false + +local function scrollstdout(lines) + lines = lines or 1 + for i=1,lines do + table.remove(mem.stdout,1) + mem.stdout[6] = "" + end +end + +local function stdout(text) + if string.len(text) == 0 then return end + if STDOUT_TO_TERMINAL then print(text) end + stdoutdirty = true + for i=1,string.len(text) do + local thischar = string.sub(text,i,i) + if string.len(mem.stdout[6]) == 20 or thischar == "\n" then + scrollstdout(1) + if thischar ~= "\n" then mem.stdout[6] = mem.stdout[6]..thischar end + elseif thischar ~= string.char(0) then + mem.stdout[6] = mem.stdout[6]..thischar + end + end +end + +local function readcsr(address) + if not mem.csr[address] then + digiline_send("monitordisp",string.format("W: Attempted read\nfrom unknown\nCSR 0x%03X\nPC: %08X",address,mem.registers.pc)) + return 0 + end + return mem.csr[address] +end + +local function writecsr(address,data) + if address == 0x17 then + --jvt + data = math.floor(data/2^6)*2^6 --WARL, and mode is required to be 0 + elseif address == 0xc00 or address == 0xc01 or address == 0xc02 or address == 0xc80 or address == 0xc81 or address == 0xc82 then + --One of the read-only CSRs from Zicntr, just ignore the write + return + elseif address == 0xf11 or address == 0xf12 or address == 0xf13 or address == 0xf14 or address == 0xf15 or address == 0x300 or address == 0x301 or address == 0x310 then + --Read-only machine information register, ignore write + return + end + if not mem.csr[address] then + digiline_send("monitordisp",string.format("W: Attempted write\nto unknown\nCSR 0x%03X\nPC: %08X",address,mem.registers.pc)) + return + end + mem.csr[address] = data +end + +local cmpushpopreglists = { + [4] = {registers = {1},stack = 16}, + [5] = {registers = {1,8},stack = 16}, + [6] = {registers = {1,8,9},stack = 16}, + [7] = {registers = {1,8,9,18},stack = 16}, + [8] = {registers = {1,8,9,18,19},stack = 32}, + [9] = {registers = {1,8,9,18,19,20},stack = 32}, + [10] = {registers = {1,8,9,18,19,20,21},stack = 32}, + [11] = {registers = {1,8,9,18,19,20,21,22},stack = 32}, + [12] = {registers = {1,8,9,18,19,20,21,22,23},stack = 48}, + [13] = {registers = {1,8,9,18,19,20,21,22,23,24},stack = 48}, + [14] = {registers = {1,8,9,18,19,20,21,22,23,24,25},stack = 48}, + [15] = {registers = {1,8,9,18,19,20,21,22,23,24,25,26,27},stack = 64}, + } + +local operations = { + add = function(rd,rs1,rs2) + setreg(rd,getreg(rs1)+getreg(rs2)) + end, + sub = function(rd,rs1,rs2) + setreg(rd,getreg(rs1)-getreg(rs2)) + end, + xor = function(rd,rs1,rs2) + local rs1bits = explodebits(getreg(rs1),32) + local rs2bits = explodebits(getreg(rs2),32) + local rdbits = {} + for i=0,31 do rdbits[i] = rs1bits[i] ~= rs2bits[i] end + setreg(rd,implodebits(rdbits,32,false)) + end, + orr = function(rd,rs1,rs2) --instruction is "or" but that's a reserved word + local rs1bits = explodebits(getreg(rs1),32) + local rs2bits = explodebits(getreg(rs2),32) + local rdbits = {} + for i=0,31 do rdbits[i] = rs1bits[i] or rs2bits[i] end + setreg(rd,implodebits(rdbits,32,false)) + end, + andr = function(rd,rs1,rs2) --instruction is "and" but that's a reserved word + local rs1bits = explodebits(getreg(rs1),32) + local rs2bits = explodebits(getreg(rs2),32) + local rdbits = {} + for i=0,31 do rdbits[i] = rs1bits[i] and rs2bits[i] end + setreg(rd,implodebits(rdbits,32,false)) + end, + xnor = function(rd,rs1,rs2) + local rs1bits = explodebits(getreg(rs1),32) + local rs2bits = explodebits(getreg(rs2),32) + local rdbits = {} + for i=0,31 do rdbits[i] = rs1bits[i] == rs2bits[i] end + setreg(rd,implodebits(rdbits,32,false)) + end, + orn = function(rd,rs1,rs2) + local rs1bits = explodebits(getreg(rs1),32) + local rs2bits = explodebits(getreg(rs2),32) + local rdbits = {} + for i=0,31 do rdbits[i] = rs1bits[i] or not rs2bits[i] end + setreg(rd,implodebits(rdbits,32,false)) + end, + andn = function(rd,rs1,rs2) + local rs1bits = explodebits(getreg(rs1),32) + local rs2bits = explodebits(getreg(rs2),32) + local rdbits = {} + for i=0,31 do rdbits[i] = rs1bits[i] and not rs2bits[i] end + setreg(rd,implodebits(rdbits,32,false)) + end, + sll = function(rd,rs1,rs2) + setreg(rd,getreg(rs1)*(2^(getreg(rs2)%2^5))) + end, + srl = function(rd,rs1,rs2) + setreg(rd,getreg(rs1)/(2^(getreg(rs2)%2^5))) + end, + sra = function(rd,rs1,rs2) + local num = getreg(rs1) + local amount = getreg(rs2)%2^5 + local sign = num>=(2^31) + if amount == 0 then return end + for _=1,amount do + num = num/2 + if sign then num = num+(2^31) end + end + setreg(rd,num) + end, + slt = function(rd,rs1,rs2) + local num1 = getreg(rs1) + local num2 = getreg(rs2) + if num1 >= 2^31 then num1 = num1-(2^32) end + if num2 >= 2^31 then num2 = num2-(2^32) end + setreg(rd,num1 < num2 and 1 or 0) + end, + sltu = function(rd,rs1,rs2) + local num1 = getreg(rs1) + local num2 = getreg(rs2) + setreg(rd,num1 < num2 and 1 or 0) + end, + addi = function(rd,rs1,imm) + local immbits = explodebits(imm,12) + signextend(immbits,12,32) + imm = implodebits(immbits,32,false) + setreg(rd,getreg(rs1)+imm) + end, + xori = function(rd,rs1,imm) + local rs1bits = explodebits(getreg(rs1),32) + local immbits = explodebits(imm,12) + signextend(immbits,12,32) + local rdbits = {} + for i=0,31 do + rdbits[i] = rs1bits[i] ~= immbits[i] + end + setreg(rd,implodebits(rdbits,32,false)) + end, + ori = function(rd,rs1,imm) + local rs1bits = explodebits(getreg(rs1),32) + local immbits = explodebits(imm,12) + signextend(immbits,12,32) + local rdbits = {} + for i=0,31 do + rdbits[i] = rs1bits[i] or immbits[i] + end + setreg(rd,implodebits(rdbits,32,false)) + end, + andi = function(rd,rs1,imm) + local rs1bits = explodebits(getreg(rs1),32) + local immbits = explodebits(imm,12) + signextend(immbits,12,32) + local rdbits = {} + for i=0,31 do + rdbits[i] = rs1bits[i] and immbits[i] + end + setreg(rd,implodebits(rdbits,32,false)) + end, + slli = function(rd,rs1,imm) + setreg(rd,getreg(rs1)*(2^imm)) + end, + srli = function(rd,rs1,imm) + setreg(rd,getreg(rs1)/(2^imm)) + end, + srai = function(rd,rs1,imm) + local num = getreg(rs1) + local sign = num>=(2^31) + if imm == 0 then return end + for _=1,imm do + num = num/2 + if sign then num = num+(2^31) end + end + setreg(rd,num) + end, + slti = function(rd,rs1,imm) + local num1 = getreg(rs1) + local immbits = explodebits(imm,12) + signextend(immbits,12,32) + local num2 = implodebits(immbits,32,false) + if num1 >= 2^31 then num1 = num1-(2^32) end + if num2 >= 2^31 then num2 = num2-(2^32) end + setreg(rd,num1 < num2 and 1 or 0) + end, + sltiu = function(rd,rs1,imm) + local num1 = getreg(rs1) + local immbits = explodebits(imm,12) + signextend(immbits,12,32) + local num2 = implodebits(immbits,32,false) + setreg(rd,num1 < num2 and 1 or 0) + end, + beq = function(rs1,rs2,imm) + local num1 = getreg(rs1) + local num2 = getreg(rs2) + if num1 == num2 then + local immbits = explodebits(imm,13) + signextend(immbits,13,32) + imm = implodebits(immbits,13,true) + mem.registers.pc = (mem.registers.pc + imm) % 2^32 + return true + end + end, + bne = function(rs1,rs2,imm) + local num1 = getreg(rs1) + local num2 = getreg(rs2) + if num1 ~= num2 then + local immbits = explodebits(imm,13) + signextend(immbits,13,32) + imm = implodebits(immbits,13,true) + mem.registers.pc = (mem.registers.pc + imm) % 2^32 + return true + end + end, + blt = function(rs1,rs2,imm) + local num1 = getreg(rs1) + local num2 = getreg(rs2) + if num1 >= 2^31 then num1 = num1-(2^32) end + if num2 >= 2^31 then num2 = num2-(2^32) end + if num1 < num2 then + local immbits = explodebits(imm,13) + signextend(immbits,13,32) + imm = implodebits(immbits,13,true) + mem.registers.pc = (mem.registers.pc + imm) % 2^32 + return true + end + end, + bge = function(rs1,rs2,imm) + local num1 = getreg(rs1) + local num2 = getreg(rs2) + if num1 >= 2^31 then num1 = num1-(2^32) end + if num2 >= 2^31 then num2 = num2-(2^32) end + if num1 >= num2 then + local immbits = explodebits(imm,13) + signextend(immbits,13,32) + imm = implodebits(immbits,13,true) + mem.registers.pc = (mem.registers.pc + imm) % 2^32 + return true + end + end, + bltu = function(rs1,rs2,imm) + local num1 = getreg(rs1) + local num2 = getreg(rs2) + if num1 < num2 then + local immbits = explodebits(imm,13) + signextend(immbits,13,32) + imm = implodebits(immbits,13,true) + mem.registers.pc = (mem.registers.pc + imm) % 2^32 + return true + end + end, + bgeu = function(rs1,rs2,imm) + local num1 = getreg(rs1) + local num2 = getreg(rs2) + if num1 >= num2 then + local immbits = explodebits(imm,13) + signextend(immbits,13,32) + imm = implodebits(immbits,13,true) + mem.registers.pc = (mem.registers.pc + imm) % 2^32 + return true + end + end, + jal = function(rd,imm,compressed) + setreg(rd,mem.registers.pc+(compressed and 2 or 4)) + local immbits = explodebits(imm,21) + signextend(immbits,21,32) + imm = implodebits(immbits,32,true) + local oldpc = mem.registers.pc + mem.registers.pc = (mem.registers.pc + imm) % 2^32 + return true + end, + jalr = function(rd,rs1,imm,compressed) + local oldpc = mem.registers.pc + local immbits = explodebits(imm,12) + signextend(immbits,12,32) + imm = implodebits(immbits,32,true) + mem.registers.pc = (getreg(rs1) + imm) % 2^32 + if mem.registers.pc%2 == 1 then mem.registers.pc = mem.registers.pc - 1 end + setreg(rd,oldpc+(compressed and 2 or 4)) + return true + end, + lui = function(rd,imm) + setreg(rd,imm) + end, + auipc = function(rd,imm) + setreg(rd,mem.registers.pc+imm) + end, + lb = function(rd,rs1,imm) + if imm >= 2^11 then imm = imm - 2^12 end + local data = readram(getreg(rs1)+imm,1) + data = explodebits(data,8) + signextend(data,8,32) + data = implodebits(data,32,false) + setreg(rd,data) + end, + lh = function(rd,rs1,imm) + if imm >= 2^11 then imm = imm - 2^12 end + local data = readram(getreg(rs1)+imm,2) + data = explodebits(data,16) + signextend(data,16,32) + data = implodebits(data,32,false) + setreg(rd,data) + end, + lw = function(rd,rs1,imm) + if imm >= 2^11 then imm = imm - 2^12 end + local data = readram(getreg(rs1)+imm,4) + setreg(rd,data) + end, + ld = function(rd,rs1,imm) + if rd == 0 or rd == 31 then return end + if imm >= 2^11 then imm = imm - 2^12 end + local address = getreg(rs1)+imm + setreg(rd,readram(address,4)) + setreg(rd+1,readram(address+4,4)) + end, + lhu = function(rd,rs1,imm) + if imm >= 2^11 then imm = imm - 2^12 end + local data = readram(getreg(rs1)+imm,2) + setreg(rd,data) + end, + lbu = function(rd,rs1,imm) + if imm >= 2^11 then imm = imm - 2^12 end + local data = readram(getreg(rs1)+imm,1) + setreg(rd,data) + end, + sb = function(rs1,rs2,imm) + if imm >= 2^11 then imm = imm - 2^12 end + writeram(getreg(rs1)+imm,getreg(rs2)%0x100,1) + end, + sh = function(rs1,rs2,imm) + if imm >= 2^11 then imm = imm - 2^12 end + writeram(getreg(rs1)+imm,getreg(rs2)%0x10000,2) + end, + sw = function(rs1,rs2,imm) + if imm >= 2^11 then imm = imm - 2^12 end + writeram(getreg(rs1)+imm,getreg(rs2),4) + end, + sd = function(rs1,rs2,imm) + if rs2 == 31 then return end + if imm >= 2^11 then imm = imm - 2^12 end + local address = getreg(rs1)+imm + writeram(address,getreg(rs2),4) + writeram(address+4,getreg(rs2+1),4) + end, + ecall = function() + local func = getreg(17) + local param1 = getreg(10) + local param2 = getreg(11) + if func == 1 then + --a7=1 - Print Integer + if param1 > 2^31 then param1 = param1-2^32 end + stdout(string.format("%d",param1)) + elseif func == 4 then + --a7=4 - Print String + local str = "" + for i=0,255 do + local byte = readram(param1+i,1) + if byte == 0 then break end + str = str..string.char(byte) + end + stdout(str) + elseif func == 5 then + --a7=5 - Read Integer + digiline_send("monitordisp","Waiting for input") + mem.running = false + mem.inputwaiting = true + mem.inputwaittype = "integer" + return false,true + elseif func == 8 then + --a7=8 - Read String + digiline_send("monitordisp","Waiting for input") + mem.running = false + mem.inputwaiting = true + mem.inputwaittype = "string" + mem.inputaddr = getreg(10) + mem.inputmax = getreg(11) + return false,true + elseif func == 10 then + --a7=10 - Exit Program + mem.running = false + digiline_send("monitordisp","Program\nexited normally") + digiline_send("monitordisp","System halted") + digiline_send("monitordisp",string.format("PC:%08X",mem.registers.pc)) + elseif func == 11 then + --a7=11 - Print Character + stdout(string.char(getreg(10))) + elseif func == 12 then + --a7=12 - Read Character + digiline_send("monitordisp","Waiting for input") + mem.running = false + mem.inputwaiting = true + mem.inputwaittype = "char" + return false,true + elseif func == 128 then + --a7=128 - Get Random Integer + local lowlimit = getreg(10) + local highlimit = getreg(11) + if lowlimit >= 2^31 then lowlimit = lowlimit - 2^32 end + if highlimit >= 2^31 then highlimit = highlimit - 2^32 end + local result = math.random(lowlimit,highlimit) + if result < 0 then result = result + 2^32 end + setreg(10,result) + elseif func == 129 then + --a7=129 - Send digilines string message + local channel = "" + for i=0,255 do + local byte = readram(param1+i,1) + if byte == 0 then break end + channel = channel..string.char(byte) + end + local message = "" + for i=0,255 do + local byte = readram(param2+i,1) + if byte == 0 then break end + message = message..string.char(byte) + end + digiline_send(channel,message) + elseif func == 130 then + --a7=130 - Get Input Buffer Level + setreg(10,string.len(mem.inputbuf)) + elseif func == 131 then + --a7=131 - Clear Input Buffer + mem.inputbuf = "" + elseif func == 132 then + --a7=132 -- Read Character From Input Buffer + if mem.inputbuf == "" then + setreg(10,0) + else + setreg(10,string.byte(string.sub(mem.inputbuf,1,1))) + mem.inputbuf = string.sub(mem.inputbuf,2,-1) + end + elseif func == 133 then + --a7=133 - Get Digilines Buffer Level + setreg(10,#mem.digilinesqueue) + elseif func == 134 then + --a7=134 - Clear Digilines Buffer + mem.digilinesqueue = {} + elseif func == 135 then + --a7=135 - Read Digilines Message + local dlevent = mem.digilinesqueue[1] + if not dlevent then dlevent = {channel = "",msg = ""} end + dlevent.channel = string.sub(dlevent.channel,1,getreg(11)-1).."\0" + dlevent.msg = string.sub(dlevent.msg,1,getreg(13)-1).."\0" + local channelstart = getreg(10) + for i=1,string.len(dlevent.channel) do + local address = channelstart+i-1 + writeram(address,string.byte(string.sub(dlevent.channel,i,i)),1) + end + local msgstart = getreg(12) + for i=1,string.len(dlevent.msg) do + local address = msgstart+i-1 + writeram(address,string.byte(string.sub(dlevent.msg,i,i)),1) + end + table.remove(mem.digilinesqueue,1) + end + end, + ebreak = function() + mem.running = false + digiline_send("monitordisp","Hit breakpoint") + digiline_send("montiordisp","System halted") + digiline_send("monitordisp",string.format("PC:%08X",mem.registers.pc)) + end, + csrrw = function(rd,rs1,imm) + setreg(rd,readcsr(imm)) + writecsr(imm,getreg(rs1)) + end, + csrrs = function(rd,rs1,imm) + setreg(rd,readcsr(imm)) + if rs1 == 0 then return end + local csrbits = explodebits(readcsr(imm),32) + local rs1bits = explodebits(getreg(rs1),32) + for i=0,31 do + csrbits[i] = csrbits[i] or rs1bits[i] + end + writecsr(imm,implodebits(csrbits,32)) + end, + csrrc = function(rd,rs1,imm) + setreg(rd,readcsr(imm)) + if rs1 == 0 then return end + local csrbits = explodebits(readcsr(imm),32) + local rs1bits = explodebits(getreg(rs1),32) + for i=0,31 do + csrbits[i] = csrbits[i] and not rs1bits[i] + end + writecsr(imm,implodebits(csrbits,32)) + end, + csrrwi = function(rd,rs1,imm) + setreg(rd,readcsr(imm)) + writecsr(imm,rs1) + end, + csrrsi = function(rd,rs1,imm) + setreg(rd,readcsr(imm)) + if rs1 == 0 then return end + local csrbits = explodebits(readcsr(imm),32) + local rs1bits = explodebits(rs1,32) + for i=0,31 do + csrbits[i] = csrbits[i] or rs1bits[i] + end + writecsr(imm,implodebits(csrbits,32)) + end, + csrrci = function(rd,rs1,imm) + setreg(rd,readcsr(imm)) + if rs1 == 0 then return end + local csrbits = explodebits(readcsr(imm),32) + local rs1bits = explodebits(rs1,32) + for i=0,31 do + csrbits[i] = csrbits[i] and not rs1bits[i] + end + writecsr(imm,implodebits(csrbits,32)) + end, + mul = function(rd,rs1,rs2) + local plow = mul64(getreg(rs1),getreg(rs2),false,false) + setreg(rd,plow) + end, + mulh = function(rd,rs1,rs2) + local _,phigh = mul64(getreg(rs1),getreg(rs2),true,true) + setreg(rd,phigh) + end, + mulsu = function(rd,rs1,rs2) + local _,phigh = mul64(getreg(rs1),getreg(rs2),true,false) + setreg(rd,phigh) + end, + mulu = function(rd,rs1,rs2) + local _,phigh = mul64(getreg(rs1),getreg(rs2),false,false) + setreg(rd,phigh) + end, + div = function(rd,rs1,rs2) + local a = getreg(rs1) + local b = getreg(rs2) + if b == 0 then + --Division by zero + setreg(rd,2^32-1) + return + end + if a >= 2^31 then a = a - 2^32 end + if b >= 2^31 then b = b - 2^32 end + if a == -2^31 and b == -1 then + --Divide overflow + setreg(rd,a) + end + local result = math.floor(a/b) + if result < 0 then result = result + 2^32 end + setreg(rd,result) + end, + rem = function(rd,rs1,rs2) + local a = getreg(rs1) + local b = getreg(rs2) + if b == 0 then + --Division by zero + setreg(rd,a) + return + end + if a >= 2^31 then a = a - 2^32 end + if b >= 2^31 then b = b - 2^32 end + if a == -2^31 and b == -1 then + --Divide overflow + setreg(rd,0) + end + local result = a%b + setreg(rd,result) + end, + divu = function(rd,rs1,rs2) + local a = getreg(rs1) + local b = getreg(rs2) + if b == 0 then + --Division by zero + setreg(rd,2^32-1) + return + end + local result = math.floor(a/b) + setreg(rd,result) + end, + remu = function(rd,rs1,rs2) + local a = getreg(rs1) + local b = getreg(rs2) + if b == 0 then + --Division by zero + setreg(rd,a) + return + end + local result = a%b + setreg(rd,result) + end, + sh1add = function(rd,rs1,rs2) + setreg(rd,getreg(rs1)*2+getreg(rs2)) + end, + sh2add = function(rd,rs1,rs2) + setreg(rd,getreg(rs1)*4+getreg(rs2)) + end, + sh3add = function(rd,rs1,rs2) + setreg(rd,getreg(rs1)*8+getreg(rs2)) + end, + clz = function(rd,rs1) + local bits = explodebits(getreg(rs1),32) + for i=31,0,-1 do + if bits[i] then + setreg(rd,31-i) + return + end + end + setreg(rd,32) + end, + ctz = function(rd,rs1) + local bits = explodebits(getreg(rs1),32) + for i=0,31 do + if bits[i] then + setreg(rd,i) + return + end + end + setreg(rd,32) + end, + cpop = function(rd,rs1) + local bits = explodebits(getreg(rs1),32) + local out = 0 + for i=0,31 do + if bits[i] then + out = out + 1 + end + end + setreg(rd,out) + end, + maxu = function(rd,rs1,rs2) + setreg(rd,math.max(getreg(rs1),getreg(rs2))) + end, + minu = function(rd,rs1,rs2) + setreg(rd,math.min(getreg(rs1),getreg(rs2))) + end, + max = function(rd,rs1,rs2) + local a = getreg(rs1) + local b = getreg(rs2) + if a >= 2^31 then a = a - 2^32 end + if b >= 2^31 then b = b - 2^32 end + local out = math.max(a,b) + if out < 0 then out = out + 2^32 end + setreg(rd,out) + end, + min = function(rd,rs1,rs2) + local a = getreg(rs1) + local b = getreg(rs2) + if a >= 2^31 then a = a - 2^32 end + if b >= 2^31 then b = b - 2^32 end + local out = math.min(a,b) + if out < 0 then out = out + 2^32 end + setreg(rd,out) + end, + sextb = function(rd,rs1) + local bits = explodebits(getreg(rs1),8) + signextend(bits,8,32) + setreg(rd,implodebits(bits,32)) + end, + sexth = function(rd,rs1) + local bits = explodebits(getreg(rs1),16) + signextend(bits,16,32) + setreg(rd,implodebits(bits,32)) + end, + zexth = function(rd,rs1) + setreg(rd,getreg(rs1)%2^16) + end, + rol = function(rd,rs1,rs2) + local num = getreg(rs1) + local amount = getreg(rs2)%32 + if amount == 0 then return end + for i=1,amount do + local endbit = num >= 2^31 + num = (num*2)%2^32 + if endbit then num = num + 1 end + end + setreg(rd,num) + end, + ror = function(rd,rs1,rs2) + local num = getreg(rs1) + local amount = getreg(rs2)%32 + if amount == 0 then + setreg(rd,num) + return + end + for _=1,amount do + local endbit = num%2 == 1 + num = math.floor(num/2) + if endbit then num = num + 2^31 end + end + setreg(rd,num) + end, + rori = function(rd,rs1,imm) + local num = getreg(rs1) + local amount = imm%32 + if amount == 0 then + setreg(rd,num) + return + end + for _=1,amount do + local endbit = num%2 == 1 + num = math.floor(num/2) + if endbit then num = num + 2^31 end + end + setreg(rd,num) + end, + orcb = function(rd,rs1) + local input = getreg(rs1) + local b1 = input%2^8 > 0 + local b2 = math.floor(input/2^8)%2^8 > 0 + local b3 = math.floor(input/2^16)%2^8 > 0 + local b4 = math.floor(input/2^24)%2^8 > 0 + local out = 0 + if b1 then out = out + 0xff end + if b2 then out = out + 0xff00 end + if b3 then out = out + 0xff0000 end + if b4 then out = out + 0xff000000 end + setreg(rd,out) + end, + rev8 = function(rd,rs1) + local input = getreg(rs1) + local b1 = input%2^8 + local b2 = math.floor(input/2^8)%2^8 + local b3 = math.floor(input/2^16)%2^8 + local b4 = math.floor(input/2^24)%2^8 + local out = b4 + out = out + (b3*2^8) + out = out + (b2*2^16) + out = out + (b1*2^24) + setreg(rd,out) + end, + bclr = function(rd,rs1,rs2) + local bits = explodebits(getreg(rs1),32) + bits[getreg(rs2)%32] = false + setreg(rd,implodebits(bits,32)) + end, + bset = function(rd,rs1,rs2) + local bits = explodebits(getreg(rs1),32) + bits[getreg(rs2)%32] = true + setreg(rd,implodebits(bits,32)) + end, + binv = function(rd,rs1,rs2) + local bits = explodebits(getreg(rs1),32) + bits[getreg(rs2)%32] = not bits[getreg(rs2)%32] + setreg(rd,implodebits(bits,32)) + end, + bclri = function(rd,rs1,imm) + local bits = explodebits(getreg(rs1),32) + bits[imm%32] = false + setreg(rd,implodebits(bits,32)) + end, + bseti = function(rd,rs1,imm) + local bits = explodebits(getreg(rs1),32) + bits[imm%32] = true + setreg(rd,implodebits(bits,32)) + end, + binvi = function(rd,rs1,imm) + local bits = explodebits(getreg(rs1),32) + bits[imm%32] = not bits[imm%32] + setreg(rd,implodebits(bits,32)) + end, + bext = function(rd,rs1,rs2) + local bit = explodebits(getreg(rs1),32)[getreg(rs2)%32] + setreg(rd,bit and 1 or 0) + end, + bexti = function(rd,rs1,imm) + local bit = explodebits(getreg(rs1),32)[imm%32] + setreg(rd,bit and 1 or 0) + end, + xperm8 = function(rd,rs1,rs2) + local a = getreg(rs1) + local outputs = { + [0] = a%2^8, + math.floor(a/2^8)%2^8, + math.floor(a/2^16)%2^8, + math.floor(a/2^24)%2^8, + } + local b = getreg(rs2) + local selections = { + [0] = b%2^8, + math.floor(b/2^8)%2^8, + math.floor(b/2^16)%2^8, + math.floor(b/2^24)%2^8, + } + local out = 0 + for i=0,3 do + local num = outputs[selections[i]] or 0 + out = out+(num*2^(i*8)) + end + setreg(rd,out) + end, + xperm4 = function(rd,rs1,rs2) + local a = getreg(rs1) + local outputs = { + [0] = a%2^4, + math.floor(a/2^4)%2^4, + math.floor(a/2^8)%2^4, + math.floor(a/2^12)%2^4, + math.floor(a/2^16)%2^4, + math.floor(a/2^20)%2^4, + math.floor(a/2^24)%2^4, + math.floor(a/2^28)%2^4, + } + local b = getreg(rs2) + local selections = { + [0] = b%2^4, + math.floor(b/2^4)%2^4, + math.floor(b/2^8)%2^4, + math.floor(b/2^12)%2^4, + math.floor(b/2^16)%2^4, + math.floor(b/2^20)%2^4, + math.floor(b/2^24)%2^4, + math.floor(b/2^28)%2^4, + } + local out = 0 + for i=0,7 do + local num = outputs[selections[i]] or 0 + out = out+(num*2^(i*4)) + end + setreg(rd,out) + end, + lr = function(rd,rs1,rs2) + local address = getreg(rs1) + setreg(rd,readram(address,4)) + mem.reservationset = address + end, + sc = function(rd,rs1,rs2) + local address = getreg(rs1) + if mem.reservationset == address then + writeram(address,getreg(rs2),4) + setreg(rd,0) + else + setreg(rd,1) + end + mem.reservationset = nil + end, + amoswapw = function(rd,rs1,rs2) + local address = getreg(rs1) + local newdata = getreg(rs2) + setreg(rd,readram(address,4)) + writeram(address,newdata,4) + end, + amoaddw = function(rd,rs1,rs2) + local address = getreg(rs1) + local data = readram(address,4) + local newdata = getreg(rs2) + setreg(rd,data) + writeram(address,(data+newdata)%2^32,4) + end, + amoandw = function(rd,rs1,rs2) + local address = getreg(rs1) + local data = readram(address,4) + local newdata = getreg(rs2) + setreg(rd,data) + local bits = explodebits(data,32) + local newbits = explodebits(newdata,32) + for i=0,31 do bits[i] = bits[i] and newbits[i] end + writeram(address,implodebits(bits,32),4) + end, + amoorw = function(rd,rs1,rs2) + local address = getreg(rs1) + local data = readram(address,4) + local newdata = getreg(rs2) + setreg(rd,data) + local bits = explodebits(data,32) + local newbits = explodebits(newdata,32) + for i=0,31 do bits[i] = bits[i] or newbits[i] end + writeram(address,implodebits(bits,32),4) + end, + amoxorw = function(rd,rs1,rs2) + local address = getreg(rs1) + local data = readram(address,4) + local newdata = getreg(rs2) + setreg(rd,data) + local bits = explodebits(data,32) + local newbits = explodebits(newdata,32) + for i=0,31 do bits[i] = bits[i] ~= newbits[i] end + writeram(address,implodebits(bits,32),4) + end, + amomaxw = function(rd,rs1,rs2) + local address = getreg(rs1) + local data = readram(address,4) + local newdata = getreg(rs2) + setreg(rd,data) + if data > 2^31 then data = data - 2^32 end + if newdata > 2^31 then newdata = newdata - 2^32 end + newdata = math.max(data,newdata) + if newdata < 0 then newdata = newdata + 2^32 end + writeram(address,newdata,4) + end, + amomaxuw = function(rd,rs1,rs2) + local address = getreg(rs1) + local data = readram(address,4) + local newdata = getreg(rs2) + setreg(rd,data) + newdata = math.max(data,newdata) + writeram(address,newdata,4) + end, + amominw = function(rd,rs1,rs2) + local address = getreg(rs1) + local data = readram(address,4) + local newdata = getreg(rs2) + setreg(rd,data) + if data > 2^31 then data = data - 2^32 end + if newdata > 2^31 then newdata = newdata - 2^32 end + newdata = math.min(data,newdata) + if newdata < 0 then newdata = newdata + 2^32 end + writeram(address,newdata,4) + end, + amominuw = function(rd,rs1,rs2) + local address = getreg(rs1) + local data = readram(address,4) + local newdata = getreg(rs2) + setreg(rd,data) + newdata = math.min(data,newdata) + writeram(address,newdata,4) + end, + amocasw = function(rd,rs1,rs2) + local address = getreg(rs1) + local data = readram(address,4) + local compare = getreg(rd) + if data == compare then + writeram(address,getreg(rs2),4) + end + setreg(rd,data) + end, + amocasd = function(rd,rs1,rs2) + if rd == 31 then return end + if rs2 == 31 then return end + local address = getreg(rs1) + local datalow = readram(address,4) + local datahigh = readram(address+4,4) + local comparelow = getreg(rd) + local comparehigh = rd == 0 and 0 or getreg(rd+1) + if datalow == comparelow and datahigh == comparehigh then + writeram(address,getreg(rs2),4) + writeram(address+4,rs2 == 0 and 0 or getreg(rs2+1),4) + end + if rd ~= 0 then + setreg(rd,datalow) + setreg(rd+1,datahigh) + end + end, + amoswaph = function(rd,rs1,rs2) + local address = getreg(rs1) + local newdata = getreg(rs2)%2^16 + local olddata = explodebits(readram(address,2),16) + signextend(olddata,16,32) + setreg(rd,implodebits(olddata,32)) + writeram(address,newdata,2) + end, + amoaddh = function(rd,rs1,rs2) + local address = getreg(rs1) + local data = readram(address,2) + local newdata = getreg(rs2)%2^16 + local oldbits = explodebits(data,16) + signextend(oldbits,16,32) + setreg(rd,implodebits(oldbits,32)) + writeram(address,(data+newdata)%2^16,2) + end, + amoandh = function(rd,rs1,rs2) + local address = getreg(rs1) + local data = readram(address,2) + local newdata = getreg(rs2)%2^16 + local bits = explodebits(data,16) + signextend(bits,16,32) + setreg(rd,implodebits(bits,32)) + local newbits = explodebits(newdata,16) + for i=0,15 do bits[i] = bits[i] and newbits[i] end + writeram(address,implodebits(bits,16),2) + end, + amoorh = function(rd,rs1,rs2) + local address = getreg(rs1) + local data = readram(address,2) + local newdata = getreg(rs2)%2^16 + local bits = explodebits(data,16) + signextend(bits,16,32) + setreg(rd,implodebits(bits,32)) + local newbits = explodebits(newdata,16) + for i=0,15 do bits[i] = bits[i] or newbits[i] end + writeram(address,implodebits(bits,16),2) + end, + amoxorh = function(rd,rs1,rs2) + local address = getreg(rs1) + local data = readram(address,2) + local newdata = getreg(rs2)%2^16 + local bits = explodebits(data,16) + signextend(bits,16,32) + setreg(rd,implodebits(bits,32)) + local newbits = explodebits(newdata,16) + for i=0,15 do bits[i] = bits[i] ~= newbits[i] end + writeram(address,implodebits(bits,16),2) + end, + amomaxh = function(rd,rs1,rs2) + local address = getreg(rs1) + local data = readram(address,2) + local newdata = getreg(rs2)%2^16 + local bits = explodebits(data,16) + signextend(bits,16,32) + setreg(rd,implodebits(bits,32)) + if data > 2^15 then data = data - 2^16 end + if newdata > 2^15 then newdata = newdata - 2^16 end + newdata = math.max(data,newdata) + if newdata < 0 then newdata = newdata + 2^16 end + writeram(address,newdata,2) + end, + amomaxuh = function(rd,rs1,rs2) + local address = getreg(rs1) + local data = readram(address,2) + local newdata = getreg(rs2)%2^16 + local bits = explodebits(data,16) + signextend(bits,16,32) + setreg(rd,implodebits(bits,32)) + newdata = math.max(data,newdata) + writeram(address,newdata,2) + end, + amominh = function(rd,rs1,rs2) + local address = getreg(rs1) + local data = readram(address,2) + local newdata = getreg(rs2)%2^16 + local bits = explodebits(data,16) + signextend(bits,16,32) + setreg(rd,implodebits(bits,32)) + if data > 2^15 then data = data - 2^16 end + if newdata > 2^15 then newdata = newdata - 2^16 end + newdata = math.min(data,newdata) + if newdata < 0 then newdata = newdata + 2^16 end + writeram(address,newdata,2) + end, + amominuh = function(rd,rs1,rs2) + local address = getreg(rs1) + local data = readram(address,2) + local newdata = getreg(rs2)%2^16 + local bits = explodebits(data,16) + signextend(bits,16,32) + setreg(rd,implodebits(bits,32)) + newdata = math.min(data,newdata) + writeram(address,newdata,2) + end, + amocash = function(rd,rs1,rs2) + local address = getreg(rs1) + local data = readram(address,2) + local compare = getreg(rd)%2^16 + if data == compare then + writeram(address,getreg(rs2)%2^16,2) + end + local bits = explodebits(data,16) + signextend(bits,16,32) + setreg(rd,implodebits(bits,32)) + end, + amoswapb = function(rd,rs1,rs2) + local address = getreg(rs1) + local newdata = getreg(rs2)%2^8 + local olddata = explodebits(readram(address,1),8) + signextend(olddata,8,32) + setreg(rd,implodebits(olddata,32)) + writeram(address,newdata,1) + end, + amoaddb = function(rd,rs1,rs2) + local address = getreg(rs1) + local data = readram(address,1) + local newdata = getreg(rs2)%2^8 + local oldbits = explodebits(data,8) + signextend(oldbits,8,32) + setreg(rd,implodebits(oldbits,32)) + writeram(address,(data+newdata)%2^8,1) + end, + amoandb = function(rd,rs1,rs2) + local address = getreg(rs1) + local data = readram(address,1) + local newdata = getreg(rs2)%2^8 + local bits = explodebits(data,8) + signextend(bits,8,32) + setreg(rd,implodebits(bits,32)) + local newbits = explodebits(newdata,8) + for i=0,7 do bits[i] = bits[i] and newbits[i] end + writeram(address,implodebits(bits,8),1) + end, + amoorb = function(rd,rs1,rs2) + local address = getreg(rs1) + local data = readram(address,1) + local newdata = getreg(rs2)%2^8 + local bits = explodebits(data,8) + signextend(bits,8,32) + setreg(rd,implodebits(bits,32)) + local newbits = explodebits(newdata,8) + for i=0,7 do bits[i] = bits[i] or newbits[i] end + writeram(address,implodebits(bits,8),1) + end, + amoxorb = function(rd,rs1,rs2) + local address = getreg(rs1) + local data = readram(address,1) + local newdata = getreg(rs2)%2^8 + local bits = explodebits(data,8) + signextend(bits,8,32) + setreg(rd,implodebits(bits,32)) + local newbits = explodebits(newdata,8) + for i=0,7 do bits[i] = bits[i] ~= newbits[i] end + writeram(address,implodebits(bits,8),1) + end, + amomaxb = function(rd,rs1,rs2) + local address = getreg(rs1) + local data = readram(address,1) + local newdata = getreg(rs2)%2^8 + local bits = explodebits(data,8) + signextend(bits,8,32) + setreg(rd,implodebits(bits,32)) + if data > 2^7 then data = data - 2^8 end + if newdata > 2^7 then newdata = newdata - 2^8 end + newdata = math.max(data,newdata) + if newdata < 0 then newdata = newdata + 2^8 end + writeram(address,newdata,1) + end, + amomaxub = function(rd,rs1,rs2) + local address = getreg(rs1) + local data = readram(address,1) + local newdata = getreg(rs2)%2^8 + local bits = explodebits(data,8) + signextend(bits,8,32) + setreg(rd,implodebits(bits,32)) + newdata = math.max(data,newdata) + writeram(address,newdata,1) + end, + amominb = function(rd,rs1,rs2) + local address = getreg(rs1) + local data = readram(address,1) + local newdata = getreg(rs2)%2^8 + local bits = explodebits(data,8) + signextend(bits,8,32) + setreg(rd,implodebits(bits,32)) + if data > 2^7 then data = data - 2^8 end + if newdata > 2^7 then newdata = newdata - 2^8 end + newdata = math.min(data,newdata) + if newdata < 0 then newdata = newdata + 2^8 end + writeram(address,newdata,1) + end, + amominub = function(rd,rs1,rs2) + local address = getreg(rs1) + local data = readram(address,1) + local newdata = getreg(rs2)%2^8 + local bits = explodebits(data,8) + signextend(bits,8,32) + setreg(rd,implodebits(bits,8)) + newdata = math.min(data,newdata) + writeram(address,newdata,1) + end, + amocasb = function(rd,rs1,rs2) + local address = getreg(rs1) + local data = readram(address,1) + local compare = getreg(rd)%2^8 + if data == compare then + writeram(address,getreg(rs2)%2^8,1) + end + local bits = explodebits(data,8) + signextend(bits,8,32) + setreg(rd,implodebits(bits,32)) + end, + pack = function(rd,rs1,rs2) + local lowhalf = getreg(rs1)%2^16 + local highhalf = (getreg(rs2)%2^16)*2^16 + setreg(rd,lowhalf+highhalf) + end, + packh = function(rd,rs1,rs2) + local lowhalf = getreg(rs1)%2^8 + local highhalf = (getreg(rs2)%2^8)*2^8 + setreg(rd,lowhalf+highhalf) + end, + brev8 = function(rd,rs1,imm) + local bits = explodebits(getreg(rs1),32) + local newbits = {} + for byte=0,3 do + for bit=0,7 do + local source = byte*8+bit + local destination = byte*8+(7-bit) + newbits[destination] = bits[source] + end + end + setreg(rd,implodebits(newbits,32)) + end, + zip = function(rd,rs1,imm) + local bits = explodebits(getreg(rs1),32) + local newbits = {} + for i=0,15 do + newbits[i*2] = bits[i] + newbits[i*2+1] = bits[i+16] + end + setreg(rd,implodebits(newbits,32)) + end, + unzip = function(rd,rs1,imm) + local bits = explodebits(getreg(rs1),32) + local newbits = {} + for i=0,15 do + newbits[i] = bits[i*2] + newbits[i+16] = bits[i*2+1] + end + setreg(rd,implodebits(newbits,32)) + end, + czeroeqz = function(rd,rs1,rs2) + if getreg(rs2) == 0 then + setreg(rd,0) + else + setreg(rd,getreg(rs1)) + end + end, + czeronez = function(rd,rs1,rs2) + if getreg(rs2) ~= 0 then + setreg(rd,0) + else + setreg(rd,getreg(rs1)) + end + end, +} + +local function runinst(instruction) + local bits = explodebits(instruction,32) + local opcode = implodebits(bits,7) + if opcode == 0x33 then + --R-type + --This is spectaularly inefficient and will probably need to be optimized later. + --Really, the whole program is. + --Focus is on making it work first... + local f3bits = {[0] = bits[12],bits[13],bits[14]} + local f3 = implodebits(f3bits,3) + local f7bits = {[0] = bits[25],bits[26],bits[27],bits[28],bits[29],bits[30],bits[31]} + local f7 = implodebits(f7bits,7) + local rdbits = {[0] = bits[7],bits[8],bits[9],bits[10],bits[11]} + local rd = implodebits(rdbits,5) + local rs1bits = {[0] = bits[15],bits[16],bits[17],bits[18],bits[19]} + local rs1 = implodebits(rs1bits,5) + local rs2bits = {[0] = bits[20],bits[21],bits[22],bits[23],bits[24]} + local rs2 = implodebits(rs2bits,5) + if f3 == 0x0 and f7 == 0x0 then + operations.add(rd,rs1,rs2) + elseif f3 == 0x0 and f7 == 0x20 then + operations.sub(rd,rs1,rs2) + elseif f3 == 0x4 and f7 == 0x0 then + operations.xor(rd,rs1,rs2) + elseif f3 == 0x6 and f7 == 0x0 then + operations.orr(rd,rs1,rs2) + elseif f3 == 0x7 and f7 == 0x0 then + operations.andr(rd,rs1,rs2) + elseif f3 == 0x1 and f7 == 0x0 then + operations.sll(rd,rs1,rs2) + elseif f3 == 0x5 and f7 == 0x0 then + operations.srl(rd,rs1,rs2) + elseif f3 == 0x5 and f7 == 0x20 then + operations.sra(rd,rs1,rs2) + elseif f3 == 0x2 and f7 == 0x0 then + operations.slt(rd,rs1,rs2) + elseif f3 == 0x3 and f7 == 0x0 then + operations.sltu(rd,rs1,rs2) + elseif f3 == 0x0 and f7 == 0x1 then + operations.mul(rd,rs1,rs2) + elseif f3 == 0x1 and f7 == 0x1 then + operations.mulh(rd,rs1,rs2) + elseif f3 == 0x2 and f7 == 0x1 then + operations.mulsu(rd,rs1,rs2) + elseif f3 == 0x3 and f7 == 0x1 then + operations.mulu(rd,rs1,rs2) + elseif f3 == 0x4 and f7 == 0x1 then + operations.div(rd,rs1,rs2) + elseif f3 == 0x5 and f7 == 0x1 then + operations.divu(rd,rs1,rs2) + elseif f3 == 0x6 and f7 == 0x1 then + operations.rem(rd,rs1,rs2) + elseif f3 == 0x7 and f7 == 0x1 then + operations.remu(rd,rs1,rs2) + elseif f3 == 0x2 and f7 == 0x10 then + operations.sh1add(rd,rs1,rs2) + elseif f3 == 0x4 and f7 == 0x10 then + operations.sh2add(rd,rs1,rs2) + elseif f3 == 0x6 and f7 == 0x10 then + operations.sh3add(rd,rs1,rs2) + elseif f3 == 0x7 and f7 == 0x20 then + operations.andn(rd,rs1,rs2) + elseif f3 == 0x6 and f7 == 0x20 then + operations.orn(rd,rs1,rs2) + elseif f3 == 0x4 and f7 == 0x20 then + operations.xnor(rd,rs1,rs2) + elseif f3 == 0x6 and f7 == 0x5 then + operations.max(rd,rs1,rs2) + elseif f3 == 0x7 and f7 == 0x5 then + operations.maxu(rd,rs1,rs2) + elseif f3 == 0x4 and f7 == 0x5 then + operations.min(rd,rs1,rs2) + elseif f3 == 0x5 and f7 == 0x5 then + operations.minu(rd,rs1,rs2) + elseif f3 == 0x4 and f7 == 0x4 and rs2 == 0x0 then + operations.zexth(rd,rs1) + elseif f3 == 0x1 and f7 == 0x30 then + operations.rol(rd,rs1,rs2) + elseif f3 == 0x5 and f7 == 0x30 then + operations.ror(rd,rs1,rs2) + elseif f3 == 0x1 and f7 == 0x24 then + operations.bclr(rd,rs1,rs2) + elseif f3 == 0x5 and f7 == 0x24 then + operations.bext(rd,rs1,rs2) + elseif f3 == 0x1 and f7 == 0x34 then + operations.binv(rd,rs1,rs2) + elseif f3 == 0x1 and f7 == 0x14 then + operations.bset(rd,rs1,rs2) + elseif f3 == 0x2 and f7 == 0x14 then + operations.xperm4(rd,rs1,rs2) + elseif f3 == 0x4 and f7 == 0x14 then + operations.xperm8(rd,rs1,rs2) + elseif f3 == 0x4 and f7 == 0x4 then + operations.pack(rd,rs1,rs2) + elseif f3 == 0x7 and f7 == 0x4 then + operations.packh(rd,rs1,rs2) + elseif f3 == 0x5 and f7 == 0x7 then + operations.czeroeqz(rd,rs1,rs2) + elseif f3 == 0x7 and f7 == 0x7 then + operations.czeronez(rd,rs1,rs2) + end + elseif opcode == 0x13 or opcode == 0x3 or opcode == 0x67 or opcode == 0x73 then + --I-type + local f3bits = {[0] = bits[12],bits[13],bits[14]} + local f3 = implodebits(f3bits,3) + local rdbits = {[0] = bits[7],bits[8],bits[9],bits[10],bits[11]} + local rd = implodebits(rdbits,5) + local rs1bits = {[0] = bits[15],bits[16],bits[17],bits[18],bits[19]} + local rs1 = implodebits(rs1bits,5) + local immbits = {[0] = bits[20],bits[21],bits[22],bits[23],bits[24],bits[25],bits[26],bits[27],bits[28],bits[29],bits[30],bits[31]} + local imm = implodebits(immbits,12) + if opcode == 0x13 then + if f3 == 0x0 then + operations.addi(rd,rs1,imm) + elseif f3 == 0x4 then + operations.xori(rd,rs1,imm) + elseif f3 == 0x6 then + operations.ori(rd,rs1,imm) + elseif f3 == 0x7 then + operations.andi(rd,rs1,imm) + elseif f3 == 0x1 and math.floor(imm/0x20) == 0x0 then + operations.slli(rd,rs1,imm%0x20) + elseif f3 == 0x5 and math.floor(imm/0x20) == 0x0 then + operations.srli(rd,rs1,imm%0x20) + elseif f3 == 0x5 and math.floor(imm/0x20) == 0x20 then + operations.srai(rd,rs1,imm%0x20) + elseif f3 == 0x2 then + operations.slti(rd,rs1,imm) + elseif f3 == 0x3 then + operations.sltiu(rd,rs1,imm) + elseif f3 == 0x1 and imm == 0x600 then + operations.clz(rd,rs1) + elseif f3 == 0x1 and imm == 0x601 then + operations.ctz(rd,rs1) + elseif f3 == 0x1 and imm == 0x602 then + operations.cpop(rd,rs1) + elseif f3 == 0x1 and imm == 0x604 then + operations.sextb(rd,rs1) + elseif f3 == 0x1 and imm == 0x605 then + operations.sexth(rd,rs1) + elseif f3 == 0x5 and math.floor(imm/2^5) == 0x30 then + operations.rori(rd,rs1,imm) + elseif f3 == 0x5 and imm == 0x287 then + operations.orcb(rd,rs1) + elseif f3 == 0x5 and imm == 0x698 then + operations.rev8(rd,rs1) + elseif f3 == 0x1 and math.floor(imm/2^5) == 0x24 then + operations.bclri(rd,rs1,imm) + elseif f3 == 0x5 and math.floor(imm/2^5) == 0x24 then + operations.bexti(rd,rs1,imm) + elseif f3 == 0x1 and math.floor(imm/2^5) == 0x34 then + operations.binvi(rd,rs1,imm) + elseif f3 == 0x1 and math.floor(imm/2^5) == 0x24 then + operations.bseti(rd,rs1,imm) + elseif f3 == 0x5 and imm == 0x687 then + operations.brev8(rd,rs1,imm) + elseif f3 == 0x1 and imm == 0x8f then + operations.zip(rd,rs1,imm) + elseif f3 == 0x5 and imm == 0x8f then + operations.unzip(rd,rs1,imm) + end + elseif opcode == 0x3 then + if f3 == 0x0 then + operations.lb(rd,rs1,imm) + elseif f3 == 0x1 then + operations.lh(rd,rs1,imm) + elseif f3 == 0x2 then + operations.lw(rd,rs1,imm) + elseif f3 == 0x3 then + operations.ld(rd,rs1,imm) + elseif f3 == 0x4 then + operations.lbu(rd,rs1,imm) + elseif f3 == 0x5 then + operations.lhu(rd,rs1,imm) + end + elseif opcode == 0x67 then + if f3 == 0x0 then + return operations.jalr(rd,rs1,imm) + end + elseif opcode == 0x73 then + if f3 == 0x0 then + if imm == 0x0 then + operations.ecall() + elseif imm == 0x1 then + operations.ebreak() + end + elseif f3 == 0x1 then + operations.csrrw(rd,rs1,imm) + elseif f3 == 0x2 then + operations.csrrs(rd,rs1,imm) + elseif f3 == 0x3 then + operations.csrrc(rd,rs1,imm) + elseif f3 == 0x5 then + operations.csrrwi(rd,rs1,imm) + elseif f3 == 0x6 then + operations.csrrsi(rd,rs1,imm) + elseif f3 == 0x7 then + operations.csrrci(rd,rs1,imm) + end + end + elseif opcode == 0x23 then + --S-type + local f3bits = {[0] = bits[12],bits[13],bits[14]} + local f3 = implodebits(f3bits,3) + local rs1bits = {[0] = bits[15],bits[16],bits[17],bits[18],bits[19]} + local rs1 = implodebits(rs1bits,5) + local rs2bits = {[0] = bits[20],bits[21],bits[22],bits[23],bits[24]} + local rs2 = implodebits(rs2bits,5) + local immbits = {[0] = bits[7],bits[8],bits[9],bits[10],bits[11],bits[25],bits[26],bits[27],bits[28],bits[29],bits[30],bits[31]} + local imm = implodebits(immbits,12) + if f3 == 0x0 then + operations.sb(rs1,rs2,imm) + elseif f3 == 0x1 then + operations.sh(rs1,rs2,imm) + elseif f3 == 0x2 then + operations.sw(rs1,rs2,imm) + elseif f3 == 0x3 then + operations.sd(rs1,rs2,imm) + end + elseif opcode == 0x63 then + --B-type + local f3bits = {[0] = bits[12],bits[13],bits[14]} + local f3 = implodebits(f3bits,3) + local rs1bits = {[0] = bits[15],bits[16],bits[17],bits[18],bits[19]} + local rs1 = implodebits(rs1bits,5) + local rs2bits = {[0] = bits[20],bits[21],bits[22],bits[23],bits[24]} + local rs2 = implodebits(rs2bits,5) + local immbits = {[0] = false,bits[8],bits[9],bits[10],bits[11],bits[25],bits[26],bits[27],bits[28],bits[29],bits[30],bits[7],bits[31]} + local imm = implodebits(immbits,13) + if f3 == 0x0 then + return operations.beq(rs1,rs2,imm) + elseif f3 == 0x1 then + return operations.bne(rs1,rs2,imm) + elseif f3 == 0x4 then + return operations.blt(rs1,rs2,imm) + elseif f3 == 0x5 then + return operations.bge(rs1,rs2,imm) + elseif f3 == 0x6 then + return operations.bltu(rs1,rs2,imm) + elseif f3 == 0x7 then + return operations.bgeu(rs1,rs2,imm) + end + elseif opcode == 0x37 or opcode == 0x17 then + --U-type + local rdbits = {[0] = bits[7],bits[8],bits[9],bits[10],bits[11]} + local rd = implodebits(rdbits,5) + --Immediate bits in this type actually all line up between the instruction and their actual value(!) + --This means it's way easier to just mask out rd/opcode + local imm = instruction - (instruction % 0x1000) + if opcode == 0x37 then + operations.lui(rd,imm) + elseif opcode == 0x17 then + operations.auipc(rd,imm) + end + elseif opcode == 0x6f then + --J-type + local rdbits = {[0] = bits[7],bits[8],bits[9],bits[10],bits[11]} + local rd = implodebits(rdbits,5) + --Something had to give after how easy the U-type immediates were + local immbits = {[0] = false,bits[21],bits[22],bits[23],bits[24],bits[25],bits[26],bits[27],bits[28],bits[29],bits[30],bits[20],bits[12],bits[13],bits[14],bits[15],bits[16],bits[17],bits[18],bits[19],bits[31]} + local imm = implodebits(immbits,21) + return operations.jal(rd,imm) + elseif opcode == 0x2f then + --Atomic memory operation + local f5 = math.floor(instruction/2^27) + local f3 = implodebits({[0] = bits[12],bits[13],bits[14]},3) + local rd = implodebits({[0] = bits[7],bits[8],bits[9],bits[10],bits[11]},5) + local rs1 = implodebits({[0] = bits[15],bits[16],bits[17],bits[18],bits[19]},5) + local rs2 = implodebits({[0] = bits[20],bits[21],bits[22],bits[23],bits[24]},5) + --Due to the way the memory model is implemented, aq and rl bits can be ignored + if f3 == 2 then + if f5 == 2 then + --lr.w + operations.lr(rd,rs1,rs2) + elseif f5 == 3 then + --sc.w + operations.sc(rd,rs1,rs2) + elseif f5 == 1 then + --amoswap.w + operations.amoswapw(rd,rs1,rs2) + elseif f5 == 0 then + --amoadd.w + operations.amoaddw(rd,rs1,rs2) + elseif f5 == 4 then + --amoxor.w + operations.amoxorw(rd,rs1,rs2) + elseif f5 == 12 then + --amoand.w + operations.amoandw(rd,rs1,rs2) + elseif f5 == 8 then + --amoor.w + operations.amoorw(rd,rs1,rs2) + elseif f5 == 16 then + --amomin.w + operations.amominw(rd,rs1,rs2) + elseif f5 == 20 then + --amomax.w + operations.amomaxw(rd,rs1,rs2) + elseif f5 == 24 then + --amominu.w + operations.amominuw(rd,rs1,rs2) + elseif f5 == 28 then + --amomaxu.w + operations.amomaxuw(rd,rs1,rs2) + elseif f5 == 5 then + --amocas.w + operations.amocasw(rd,rs1,rs2) + end + elseif f3 == 3 then + if f5 == 5 then + --amocas.d + operations.amocasd(rd,rs1,rs2) + end + elseif f3 == 0 then + if f5 == 1 then + --amoswap.b + operations.amoswapb(rd,rs1,rs2) + elseif f5 == 0 then + --amoadd.b + operations.amoaddb(rd,rs1,rs2) + elseif f5 == 4 then + --amoxor.b + operations.amoxorb(rd,rs1,rs2) + elseif f5 == 12 then + --amoamd.b + operations.amoandb(rd,rs1,rs2) + elseif f5 == 8 then + --amoor.b + operations.amoorb(rd,rs1,rs2) + elseif f5 == 16 then + --amomin.b + operations.amominb(rd,rs1,rs2) + elseif f5 == 20 then + --amomax.b + operations.amomaxb(rd,rs1,rs2) + elseif f5 == 24 then + --amominu.b + operations.amominub(rd,rs1,rs2) + elseif f5 == 28 then + --amomaxu.b + operations.amomaxub(rd,rs1,rs2) + elseif f5 == 5 then + --amocas.b + operations.amocasb(rd,rs1,rs2) + end + elseif f3 == 1 then + if f5 == 1 then + --amoswap.h + operations.amoswaph(rd,rs1,rs2) + elseif f5 == 0 then + --amoadd.h + operations.amoaddh(rd,rs1,rs2) + elseif f5 == 4 then + --amoxor.h + operations.amoxorh(rd,rs1,rs2) + elseif f5 == 12 then + --amoamd.h + operations.amoandh(rd,rs1,rs2) + elseif f5 == 8 then + --amoor.h + operations.amoorh(rd,rs1,rs2) + elseif f5 == 16 then + --amomin.h + operations.amominh(rd,rs1,rs2) + elseif f5 == 20 then + --amomax.h + operations.amomaxh(rd,rs1,rs2) + elseif f5 == 24 then + --amominu.h + operations.amominuh(rd,rs1,rs2) + elseif f5 == 28 then + --amomaxu.h + operations.amomaxuh(rd,rs1,rs2) + elseif f5 == 5 then + --amocas.h + operations.amocash(rd,rs1,rs2) + end + end + elseif opcode == 0x0f then + --Memory is always consistent on this implementation, + --so all fences can just turn into NOPs + if instruction == 0x0100000f then + --pause + return false,true + end + else + mem.running = false + digiline_send("monitordisp",string.format("Invalid opcode %02X,\nhalted",opcode)) + end +end + +local function runcinst(instruction) + local bits = explodebits(instruction,16) + local opcode = instruction%2^2 + local f8 = math.floor(instruction/2^8) + local f6 = math.floor(f8/2^2) + local f4 = math.floor(f6/2^2) + local f3 = math.floor(f4/2) + if opcode == 2 and f3 == 2 then + --c.lwsp (CI) + local imm = implodebits({[0] = false,false,bits[4],bits[5],bits[6],bits[12],bits[2],bits[3]},8) + local rd = implodebits({[0] = bits[7],bits[8],bits[9],bits[10],bits[11]},5) + operations.lw(rd,2,imm) + elseif opcode == 2 and f3 == 3 then + --c.ldsp + local imm = implodebits({[0] = false,false,false,bits[5],bits[6],bits[12],bits[2],bits[3],bits[4]},9) + local rd = implodebits({[0] = bits[7],bits[8],bits[9],bits[10],bits[11]},5) + operations.ld(rd,2,imm) + elseif opcode == 2 and f3 == 6 then + --c.swsp (CSS) + local imm = implodebits({[0] = false,false,bits[9],bits[10],bits[11],bits[12],bits[7],bits[8]},8) + local rs2 = implodebits({[0] = bits[2],bits[3],bits[4],bits[5],bits[6]},5) + operations.sw(2,rs2,imm) + elseif opcode == 2 and f3 == 7 then + --c.sdsp + local imm = implodebits({[0] = false,false,false,bits[10],bits[11],bits[12],bits[7],bits[8],bits[9]},9) + local rs2 = implodebits({[0] = bits[2],bits[3],bits[4],bits[5],bits[6]},5) + operations.sd(2,rs2,imm) + elseif opcode == 0 and f3 == 2 then + --c.lw (CL) + local imm = implodebits({[0] = false,false,bits[6],bits[10],bits[11],bits[12],bits[5]},7) + local rd = implodebits({[0] = bits[2],bits[3],bits[4]},3)+8 + local rs1 = implodebits({[0] = bits[7],bits[8],bits[9]},3)+8 + operations.lw(rd,rs1,imm) + elseif opcode == 0 and f3 == 3 then + --c.ld + local imm = implodebits({[0] = false,false,false,bits[6],bits[10],bits[11],bits[12],bits[5]},8) + local rd = implodebits({[0] = bits[2],bits[3],bits[4]},3)+8 + local rs1 = implodebits({[0] = bits[7],bits[8],bits[9]},3)+8 + operations.ld(rd,rs1,imm) + elseif opcode == 0 and f3 == 6 then + --c.sw (CS) + local imm = implodebits({[0] = false,false,bits[6],bits[10],bits[11],bits[12],bits[5]},7) + local rs2 = implodebits({[0] = bits[2],bits[3],bits[4]},3)+8 + local rs1 = implodebits({[0] = bits[7],bits[8],bits[9]},3)+8 + operations.sw(rs1,rs2,imm) + elseif opcode == 0 and f3 == 7 then + --c.sd + local imm = implodebits({[0] = false,false,false,bits[6],bits[10],bits[11],bits[12],bits[5]},8) + local rs2 = implodebits({[0] = bits[2],bits[3],bits[4]},3)+8 + local rs1 = implodebits({[0] = bits[7],bits[8],bits[9]},3)+8 + operations.sd(rs1,rs2,imm) + elseif opcode == 1 and f3 == 5 then + --c.j (CJ) + local immbits = {[0] = false,bits[3],bits[4],bits[5],bits[11],bits[2],bits[7],bits[6],bits[9],bits[10],bits[8],bits[12]} + signextend(immbits,12,21) + local offset = implodebits(immbits,21) + return operations.jal(0,offset,true) + elseif opcode == 1 and f3 == 1 then + --c.jal (CJ) + local immbits = {[0] = false,bits[3],bits[4],bits[5],bits[11],bits[2],bits[7],bits[6],bits[9],bits[10],bits[8],bits[12]} + signextend(immbits,12,21) + local offset = implodebits(immbits,21) + return operations.jal(1,offset,true) + elseif opcode == 2 and f4 == 8 and math.floor(instruction/2^2)%2^5 == 0 then + --c.jr (CR) + local rs1 = implodebits({[0] = bits[7],bits[8],bits[9],bits[10],bits[11]},5) + return operations.jalr(0,rs1,0,true) + elseif opcode == 2 and f4 == 9 then + local rd = implodebits({[0] = bits[7],bits[8],bits[9],bits[10],bits[11]},5) + local rs1 = implodebits({[0] = bits[7],bits[8],bits[9],bits[10],bits[11]},5) + local rs2 = implodebits({[0] = bits[2],bits[3],bits[4],bits[5],bits[6]},5) + if rd == 0 and rs2 == 0 then + --c.ebreak (CR) + operations.ebreak() + elseif rs2 == 0 then + --c.jalr (CR) + return operations.jalr(1,rs1,0,true) + else + --c.add (CR) + operations.add(rd,rd,rs2) + end + elseif opcode == 1 and f3 == 6 then + --c.beqz (CB) + local rs1 = implodebits({[0] = bits[7],bits[8],bits[9]},3)+8 + local imm = implodebits({[0] = false,bits[3],bits[4],bits[10],bits[11],bits[2],bits[5],bits[6],bits[12]},9,true) + return operations.beq(rs1,0,imm) + elseif opcode == 1 and f3 == 7 then + --c.bnez (CB) + local rs1 = implodebits({[0] = bits[7],bits[8],bits[9]},3)+8 + local imm = implodebits({[0] = false,bits[3],bits[4],bits[10],bits[11],bits[2],bits[5],bits[6],bits[12]},9,true) + if imm >= 2^8 then imm = imm - 2^9 end + return operations.bne(rs1,0,imm) + elseif opcode == 1 and f3 == 2 then + local imm = implodebits({[0] = bits[2],bits[3],bits[4],bits[5],bits[6],bits[12]},6,true) + local rd = implodebits({[0] = bits[7],bits[8],bits[9],bits[10],bits[11]},5) + if imm >= 2^5 then imm = imm - 2^6 end + --c.li (CI) + operations.addi(rd,0,imm) + elseif opcode == 1 and f3 == 3 then + local immbits = {[0] = bits[2],bits[3],bits[4],bits[5],bits[6],bits[12]} + local rd = implodebits({[0] = bits[7],bits[8],bits[9],bits[10],bits[11]},5) + if rd == 2 then + --c.addi16sp (CI) + --For whatever reason this has a completely different immediate format than c.lui + imm = implodebits({[0] = false,false,false,false,bits[6],bits[2],bits[5],bits[3],bits[4],bits[12]},10,true) + operations.addi(2,2,imm) + else + --c.lui (CI) + signextend(immbits,6,20) + local imm = implodebits(immbits,20) + imm = imm*2^12 + operations.lui(rd,imm) + end + elseif opcode == 1 and f3 == 0 then + --c.addi (CI) + local imm = implodebits({[0] = bits[2],bits[3],bits[4],bits[5],bits[6],bits[12]},6,true) + local rd = implodebits({[0] = bits[7],bits[8],bits[9],bits[10],bits[11]},5) + operations.addi(rd,rd,imm) + elseif opcode == 0 and f3 == 0 and instruction ~= 0 then + --c.addi4spn (CIW) + local imm = implodebits({[0] = false,false,bits[6],bits[5],bits[11],bits[12],bits[7],bits[8],bits[9],bits[10]},10) + local rd = (math.floor(instruction/2^2)%2^3)+8 + operations.addi(rd,2,imm) + elseif opcode == 2 and f3 == 0 then + --c.slli (CI) + local imm = implodebits({[0] = bits[2],bits[3],bits[4],bits[5],bits[6],bits[12]},6) + local rd = implodebits({[0] = bits[7],bits[8],bits[9],bits[10],bits[11]},5) + operations.slli(rd,rd,imm) + elseif opcode == 1 and f6 == 0x20 then + --c.srli (CB) + local rd = implodebits({[0] = bits[7],bits[8],bits[9]},3)+8 + local imm = implodebits({[0] = bits[2],bits[3],bits[4],bits[5],bits[6],bits[12]},6) + operations.srli(rd,rd,imm) + elseif opcode == 1 and f6 == 0x21 then + --c.srai (CB) + local rd = implodebits({[0] = bits[7],bits[8],bits[9]},3)+8 + local imm = implodebits({[0] = bits[2],bits[3],bits[4],bits[5],bits[6],bits[12]},6) + operations.srai(rd,rd,imm) + elseif opcode == 1 and (f6 == 0x22 or f6 == 0x26) then + --c.andi (CB) + local rd = implodebits({[0] = bits[7],bits[8],bits[9]},3)+8 + local immbits = {[0] = bits[2],bits[3],bits[4],bits[5],bits[6],bits[12]} + signextend(immbits,6,12) + local imm = implodebits(immbits,12) + operations.andi(rd,rd,imm) + elseif opcode == 2 and f4 == 8 then + --c.mv (CR) + local rd = implodebits({[0] = bits[7],bits[8],bits[9],bits[10],bits[11]},5) + local rs2 = implodebits({[0] = bits[2],bits[3],bits[4],bits[5],bits[6]},5) + operations.add(rd,0,rs2) + elseif opcode == 1 and f6 == 0x23 and bits[5] and bits[6] then + --c.and (CS) + local rs2 = implodebits({[0] = bits[2],bits[3],bits[4]},3)+8 + local rd = implodebits({[0] = bits[7],bits[8],bits[9]},3)+8 + operations.andr(rd,rd,rs2) + elseif opcode == 1 and f6 == 0x23 and bits[6] and not bits[5] then + --c.or (CS) + local rs2 = implodebits({[0] = bits[2],bits[3],bits[4]},3)+8 + local rd = implodebits({[0] = bits[7],bits[8],bits[9]},3)+8 + operations.orr(rd,rd,rs2) + elseif opcode == 1 and f6 == 0x23 and bits[5] and not bits[6] then + --c.xor (CS) + local rs2 = implodebits({[0] = bits[2],bits[3],bits[4]},3)+8 + local rd = implodebits({[0] = bits[7],bits[8],bits[9]},3)+8 + operations.xor(rd,rd,rs2) + elseif opcode == 1 and f6 == 0x23 and not (bits[5] or bits[6]) then + --c.sub (CS) + local rs2 = implodebits({[0] = bits[2],bits[3],bits[4]},3)+8 + local rd = implodebits({[0] = bits[7],bits[8],bits[9]},3)+8 + operations.sub(rd,rd,rs2) + elseif opcode == 0 and f6 == 0x20 then + --c.lbu + local rd = implodebits({[0] = bits[2],bits[3],bits[4]},3)+8 + local rs1 = implodebits({[0] = bits[7],bits[8],bits[9]},3)+8 + local imm = implodebits({[0] = bits[6],bits[5]},2) + operations.lbu(rd,rs1,imm) + elseif opcode == 0 and f6 == 0x21 and not bits[6] then + --c.lhu + local rd = implodebits({[0] = bits[2],bits[3],bits[4]},3)+8 + local rs1 = implodebits({[0] = bits[7],bits[8],bits[9]},3)+8 + local imm = implodebits({[0] = bits[5],bits[6]},2) + operations.lhu(rd,rs1,imm) + elseif opcode == 0 and f6 == 0x21 and bits[6] then + --c.lh + local rd = implodebits({[0] = bits[2],bits[3],bits[4]},3)+8 + local rs1 = implodebits({[0] = bits[7],bits[8],bits[9]},3)+8 + local imm = implodebits({[0] = false,bits[5]},2) + operations.lh(rd,rs1,imm) + elseif opcode == 0 and f6 == 0x22 then + --c.sb + local rs2 = implodebits({[0] = bits[2],bits[3],bits[4]},3)+8 + local rs1 = implodebits({[0] = bits[7],bits[8],bits[9]},3)+8 + local imm = implodebits({[0] = bits[6],bits[5]},2) + operations.sb(rs1,rs2,imm) + elseif opcode == 0 and f6 == 0x23 and not bits[6] then + --c.sh + local rs2 = implodebits({[0] = bits[2],bits[3],bits[4]},3)+8 + local rs1 = implodebits({[0] = bits[7],bits[8],bits[9]},3)+8 + local imm = implodebits({[0] = false,bits[5]},2) + operations.sh(rs1,rs2,imm) + elseif opcode == 1 and f6 == 0x27 and bits[5] and bits[6] and not (bits[2] or bits[3] or bits[4]) then + --c.zext.b + local rd = implodebits({[0] = bits[7],bits[8],bits[9]},3)+8 + operations.andi(rd,rd,0xff) + elseif opcode == 1 and f6 == 0x27 and bits[5] and bits[6] and bits[2] and not (bits[3] or bits[4]) then + --c.sext.b + local rd = implodebits({[0] = bits[7],bits[8],bits[9]},3)+8 + operations.sextb(rd,rd) + elseif opcode == 1 and f6 == 0x27 and bits[5] and bits[6] and bits[3] and not (bits[2] or bits[4]) then + --c.zext.h + local rd = implodebits({[0] = bits[7],bits[8],bits[9]},3)+8 + operations.zexth(rd,rd) + elseif opcode == 1 and f6 == 0x27 and bits[5] and bits[6] and bits[2] and bits[3] and not bits[4] then + --c.sext.h + local rd = implodebits({[0] = bits[7],bits[8],bits[9]},3)+8 + operations.sexth(rd,rd) + elseif opcode == 1 and f6 == 0x27 and bits[5] and bits[6] and bits[2] and bits[4] and not bits[3] then + --c.not + local rd = implodebits({[0] = bits[7],bits[8],bits[9]},3)+8 + operations.xori(rd,rd,0xffffffff) + elseif opcode == 1 and f6 == 0x27 and bits[6] and not bits[5] then + --c.mul + local rd = implodebits({[0] = bits[7],bits[8],bits[9]},3)+8 + local rs2 = implodebits({[0] = bits[2],bits[3],bits[4]},3)+8 + operations.mul(rd,rd,rs2) + elseif opcode == 2 and f8 == 0xb8 then + --cm.push + --This one decodes into possibly a whole bunch of instructions + local rlist = cmpushpopreglists[implodebits({[0] = bits[4],bits[5],bits[6],bits[7]},4)] + if not rlist then return end + stack = implodebits({[0] = bits[2],bits[3]},2) * 16 + rlist.stack + for i,reg in ipairs(rlist.registers) do + operations.sw(2,reg,-4*i) + end + operations.addi(2,2,-1 * stack) + elseif opcode == 2 and f8 == 0xba then + --cm.pop + --This one decodes into possibly a whole bunch of instructions + local rlist = cmpushpopreglists[implodebits({[0] = bits[4],bits[5],bits[6],bits[7]},4)] + if not rlist then return end + stack = implodebits({[0] = bits[2],bits[3]},2) * 16 + rlist.stack + operations.addi(2,2,stack) + for i,reg in ipairs(rlist.registers) do + operations.lw(reg,2,-4*i) + end + elseif opcode == 2 and f8 == 0xbc then + --cm.popretz + --This one decodes into a whole bunch of instructions + local rlist = cmpushpopreglists[implodebits({[0] = bits[4],bits[5],bits[6],bits[7]},4)] + if not rlist then return end + local stack = implodebits({[0] = bits[2],bits[3]},2) * 16 + rlist.stack + operations.addi(2,2,stack) + for i,reg in ipairs(rlist.registers) do + operations.lw(reg,2,-4*i) + end + operations.addi(10,0,0) + return operations.jalr(0,1,0) + --more like CISC-V amirite? + elseif opcode == 2 and f8 == 0xbe then + --cm.popret + --This one decodes into a whole bunch of instructions + local rlist = cmpushpopreglists[implodebits({[0] = bits[4],bits[5],bits[6],bits[7]},4)] + if not rlist then return end + local stack = implodebits({[0] = bits[2],bits[3]},2) * 16 + rlist.stack + operations.addi(2,2,stack) + for i,reg in ipairs(rlist.registers) do + operations.lw(reg,2,-4*i) + end + return operations.jalr(0,1,0) + elseif opcode == 2 and f6 == 0x2b and bits[5] and not bits[6] then + --cm.mvsa01 + --This one decodes into multiple instructions + local sreg = {[0] = 8,9,18,19,20,21,22,23} + local r1 = sreg[implodebits({[0] = bits[7],bits[8],bits[9]},3)] + local r2 = sreg[implodebits({[0] = bits[2],bits[3],bits[4]},3)] + operations.addi(r1,10,0) + operations.addi(r2,11,0) + elseif opcode == 2 and f6 == 0x2b and bits[5] and bits[6] then + --cm.mva01s + --This one decodes into multiple instructions + local sreg = {[0] = 8,9,18,19,20,21,22,23} + local r1 = sreg[implodebits({[0] = bits[7],bits[8],bits[9]},3)] + local r2 = sreg[implodebits({[0] = bits[2],bits[3],bits[4]},3)] + operations.addi(10,r1,0) + operations.addi(11,r2,0) + elseif opcode == 2 and f6 == 0x28 then + local index = implodebits({[0] = bits[2],bits[3],bits[4],bits[5],bits[6],bits[7],bits[8],bits[9]},8) + if index < 32 then + --cm.jt + local address = readcsr(0x17) --jvt + address = address + 4*index + local target = readram(address,4) + mem.registers.pc = target + return true + else + --cm.jalt + local address = readcsr(0x17) --jvt + address = address + 4*index + local target = readram(address,4) + setreg(1,mem.registers.pc+2) + mem.registers.pc = target + return true + end + else + mem.running = false + digiline_send("monitordisp","Invalid compressed\ninstruction, halted") + end +end + +local function run(limit) + --0xc00 = CYCLE + --0xc80 = CYCLEH + mem.csr[0xc00] = mem.csr[0xc00] + 1 + if mem.csr[0xc00] >= 2^32 then + mem.csr[0xc80] = mem.csr[0xc80] + math.floor(mem.csr[0xc00]/2^32) + mem.csr[0xc00] = mem.csr[0xc00]%2^32 + end + + --0xc01 = TIME + --0xc81 = TIMEH + local timediff = os.time()-mem.starttime + mem.csr[0xc01] = timediff%2^32 + mem.csr[0xc81] = math.floor(timediff/2^32) + + local first = true + repeat + if mem.registers.pc == mem.breakpoint and not first then + digiline_send("monitordisp","Hit breakpoint") + mem.running = false + break + end + first = false + local instruction = readram(mem.registers.pc,4) + if instruction%4 == 3 then + local jumped,stop = runinst(instruction) + if not jumped then mem.registers.pc = (mem.registers.pc + 4) % 2^32 end + if stop then break end + else + local jumped,stop = runcinst(instruction%2^16) + if not jumped then mem.registers.pc = (mem.registers.pc + 2) % 2^32 end + if stop then break end + end + + --0xc02 = INSTRET + --0xc82 = INSTRETH + mem.csr[0xc02] = mem.csr[0xc02] + 1 + if mem.csr[0xc02] >= 2^32 then + mem.csr[0xc82] = mem.csr[0xc82] + math.floor(mem.csr[0xc02]/2^32) + mem.csr[0xc02] = mem.csr[0xc02]%2^32 + end + limit = limit - 1 + until (not mem.running) or limit <= 0 +end + +local regaliases = { + zero = 0, + ra = 1, + sp = 2, + gp = 3, + tp = 4, + t0 = 5, + t1 = 6, + t2 = 7, + fp = 8, + s0 = 8, + s1 = 9, + a0 = 10, + a1 = 11, + a2 = 12, + a3 = 13, + a4 = 14, + a5 = 15, + a6 = 16, + a7 = 17, + s2 = 18, + s3 = 19, + s4 = 20, + s5 = 21, + s6 = 22, + s7 = 23, + s8 = 24, + s9 = 25, + s10 = 26, + s11 = 27, + t3 = 28, + t4 = 29, + t5 = 30, + t6 = 31, +} + +if event.type == "program" or event.iid == "reset" then + mem.ram = {} + for i=0,(RAM_SIZE/256)-1 do + mem.ram[i] = string.rep(string.char(0),256) + end + mem.registers = {} + for i=0,31 do mem.registers[i] = 0 end + mem.registers.pc = 0 + mem.running = false + mem.inputwaiting = false + mem.stdout = {} + mem.starttime = os.time() + mem.csr = { + [0x017] = 0, --jvt + [0xf11] = 0, --mvendorid + [0xf12] = 0x6f435652, --marchid ("RVCo") + [0xf13] = 0, --mimpid + [0xf14] = 0, --mhartid + [0x300] = 0, --mstatus + [0x301] = 0x40001107, --misa (RV32IMACB) + [0x310] = 0, --mstatush + [0x800] = 0, --Lightweight Mode + [0xc00] = 0, --CYCLE + [0xc01] = 0, --TIME + [0xc02] = 0, --INSTRET + [0xc80] = 0, --CYCLEH + [0xc81] = 0, --TIMEH + [0xc82] = 0, --INSTRETH + } + for i=1,6 do mem.stdout[i] = "" end + local mdisp = event.type == "program" and "\nReset: Cold" or "\nReset: Warm" + digiline_send("monitordisp",mdisp.."\n\nRVController Monitor\n\nType 'help' for help\nReady\n") + digiline_send("stdout","\n\n\n\n\n\n\n") + mem.inputbuf = "" + mem.digilinesqueue = {} + mem.breakpoint = -1 + mem.hexloading = false + mem.reservationset = nil +elseif event.channel == "reset" then + mem.running = false + digiline_send("monitordisp","\n\n\n\n\n\n\n") + digiline_send("stdout","\n\n\n\n\n\n\n") + interrupt(0.5,"reset") +elseif event.channel == "monitorkb" then + digiline_send("monitordisp","> "..event.msg) + local function validateandclamp(value,min,max,base) + base = base or 16 + value = tonumber(value or "",base) + if (not value) or value < min or value > max or value ~= math.floor(value) then + return + end + return value + end + local argv = {} + while true do + local spacepos = string.find(event.msg," ",nil,true) or string.len(event.msg)+1 + table.insert(argv,string.sub(event.msg,1,spacepos-1)) + event.msg = string.sub(event.msg,spacepos+1,-1) + if event.msg == "" then break end + end + local argc = #argv + if argv[1] == "peek" then + local address = validateandclamp(argv[2],0,RAM_SIZE-1) + if not address then + digiline_send("monitordisp","Bad address") + return + end + local data = readram(address,1) + digiline_send("monitordisp",string.format("%08X:%02X",address,data)) + elseif argv[1] == "peekw" then + local address = validateandclamp(argv[2],0,RAM_SIZE-1) + if not address then + digiline_send("monitordisp","Bad address") + return + end + local data = readram(address,4) + digiline_send("monitordisp",string.format("%08X:%08X",address,data)) + elseif argv[1] == "poke" then + local address = validateandclamp(argv[2],0,RAM_SIZE-1) + if not address then + digiline_send("monitordisp","Bad address") + return + end + local data = validateandclamp(argv[3],0,0xff) + if not data then + digiline_send("monitordisp","Bad data") + return + end + writeram(address,data,1) + digiline_send("monitordisp",string.format("%08X:%02X",address,data)) + elseif argv[1] == "pokew" then + local address = validateandclamp(argv[2],0,RAM_SIZE-1) + if not address then + digiline_send("monitordisp","Bad address") + return + end + local data = validateandclamp(argv[3],0,0xffffffff) + if not data then + digiline_send("monitordisp","Bad data") + return + end + writeram(address,data,4) + digiline_send("monitordisp",string.format("%08X:%08X",address,data)) + elseif argv[1] == "setreg" then + argv[2] = regaliases[argv[2]] or argv[2] + local reg = validateandclamp(argv[2],0,0x1f,10) + if not reg then + digiline_send("monitordisp","Bad register") + return + end + local data = validateandclamp(argv[3],0,0xffffffff) + if not data then + digiline_send("monitordisp","Bad data") + return + end + setreg(reg,data) + digiline_send("monitordisp",string.format("x%02d:%08X",reg,data)) + elseif argv[1] == "getreg" then + argv[2] = regaliases[argv[2]] or argv[2] + local reg = validateandclamp(argv[2],0,0x1f,10) + if not reg then + digiline_send("monitordisp","Bad register") + return + end + local data = getreg(reg) + digiline_send("monitordisp",string.format("x%02d:%08X",reg,data)) + elseif argv[1] == "getpc" then + digiline_send("monitordisp",string.format("PC:%08X",mem.registers.pc)) + elseif argv[1] == "setpc" then + local address = validateandclamp(argv[2],0,0xffffffff) + if not address then + digiline_send("monitordisp","Bad address") + return + end + mem.registers.pc = address + digiline_send("monitordisp",string.format("PC:%08X",address)) + elseif argv[1] == "reset" then + mem.running = false + digiline_send("monitordisp","\n\n\n\n\n\n\n") + digiline_send("stdout","\n\n\n\n\n\n\n") + interrupt(0.5,"reset") + elseif argv[1] == "step" then + run(1) + digiline_send("monitordisp",string.format("PC:%08X",mem.registers.pc)) + elseif argv[1] == "run" then + mem.starttime = os.time() + mem.running = true + digiline_send("monitordisp","CPU started\n\n") + run(50) + interrupt(0.1,"tick") + elseif argv[1] == "stop" then + mem.running = false + mem.inputwaiting = false + digiline_send("monitordisp","Stopped by user") + elseif argv[1] == "h" then + --Easter egg + digiline_send("monitordisp","h") + elseif argv[1] == "setbreak" then + local address = validateandclamp(argv[2],0,RAM_SIZE-1) + if not address then + digiline_send("monitordisp","Bad address") + return + end + mem.breakpoint = address + elseif argv[1] == "clearbreak" then + mem.breakpoint = -1 + elseif argv[1] == "help" then + if argc == 1 or argv[2] == "1" then + digiline_send("monitordisp","Use: help ") + digiline_send("monitordisp","Commands:\npoke pokew peek\npeekw setreg getreg\ngetpc setpc step run\n'help 2' for page 2") + elseif argv[2] == "poke" then + digiline_send("monitordisp","poke \nWrites the specified\nbyte (8 bits) to\nmemory at the\nspecified address") + elseif argv[2] == "pokew" then + digiline_send("monitordisp","pokew \nWrites the specified\nword (32 bits) to\nmemory at the\nspecified address") + elseif argv[2] == "peek" then + digiline_send("monitordisp","peek
\nReads the byte (8\nbits) value from\nmemory at the\nspecified address") + elseif argv[2] == "peekw" then + digiline_send("monitordisp","peekw
\nReads the word (32\nbits) value from\nmemory at the\nspecified address") + elseif argv[2] == "setreg" then + digiline_send("monitordisp","setreg \nWrites the specified\nword (32 bits) data\nto the specified\nregister") + elseif argv[2] == "getreg" then + digiline_send("monitordisp","getreg \nReads the word (32\nbits) data from the\nspecified register") + elseif argv[2] == "getpc" then + digiline_send("monitordisp","getpc\nReads the current\nvalue of the program\ncounter") + elseif argv[2] == "setpc" then + digiline_send("monitordisp","setpc \nWrites the specified\nvalue into the\nprogram counter") + elseif argv[2] == "step" then + digiline_send("monitordisp","step\nAllows the CPU to\nrun one instruction,\nthen halts") + elseif argv[2] == "run" then + digiline_send("monitordisp","run\nAllows the CPU to\nrun indefinitely") + elseif argv[2] == "stop" then + digiline_send("monitordisp","stop\nHalts the CPU") + elseif argv[2] == "reset" then + digiline_send("monitordisp","reset\nStops the CPU and\nclears RAM and all\nregisters") + elseif argv[2] == "help" then + digiline_send("monitordisp","help [command]\nShows information\nabout the specified\ncommand, or a list\nof commands if none\nis supplied") + elseif argv[2] == "2" then + digiline_send("monitordisp","Page 2\nreset stop help\nsetbreak clearbreak") + elseif argv[2] == "h" then + digiline_send("monitordisp","h\nhhhhhhhhhh") + elseif argv[2] == "setbreak" then + digiline_send("monitordisp","setbreak
\nSets a breakpoint\nat the specified\naddress") + elseif argv[2] == "clearbreak" then + digiline_send("monitordisp","clearbreak\nClears any set\nbreakpoint") + else + digiline_send("monitordisp","No such command or\nno help available") + end + else + digiline_send("monitordisp","Unknown command") + end +elseif event.channel == "stdin" then + if mem.inputwaiting then + --Blocking read in progress + if mem.inputwaittype == "string" then + event.msg = string.sub(event.msg,1,mem.inputmax-1)..string.char(0) + for i=1,string.len(event.msg) do + writeram(mem.inputaddr+i-1,string.byte(string.sub(event.msg,i,i)),1) + end + mem.inputwaiting = false + mem.running = true + digiline_send("monitordisp","CPU started") + run(INSTRUCTIONS_PER_CLOCK) + interrupt(1/CLOCK_SPEED,"tick") + elseif mem.inputwaittype == "integer" and tonumber(event.msg) then + event.msg = math.floor(event.msg) + if event.msg >= 2^32 then event.msg = 2^32-1 end + if event.msg < -1*(2^31) then event.msg = -1*(2^31) end + if event.msg < 0 then event.msg = event.msg + 2^32 end + setreg(10,event.msg) + mem.inputwaiting = false + mem.running = true + digiline_send("monitordisp","CPU started") + run(INSTRUCTIONS_PER_CLOCK) + interrupt(1/CLOCK_SPEED,"tick") + elseif mem.inputwaittype == "char" then + event.msg = string.sub(event.msg,1,1) + if event.msg == "" then event.msg = string.char(0) end + setreg(10,string.byte(event.msg)) + mem.inputwaiting = false + mem.running = true + digiline_send("monitordisp","CPU started") + run(INSTRUCTIONS_PER_CLOCK) + interrupt(1/CLOCK_SPEED,"tick") + end + else + --No blocking read in progress, buffer the data for nonblocking reads later + mem.inputbuf = string.sub(mem.inputbuf..event.msg,1,256) + end +elseif event.channel == "load" then + if event.msg.done then + mem.hexloading = false + digiline_send("monitordisp","Load complete\n") + if event.msg.autorun then + mem.running = true + digiline_send("monitordisp","CPU started\n") + run(INSTRUCTIONS_PER_CLOCK) + interrupt(1/CLOCK_SPEED,"tick") + end + else + if not mem.hexloading then + if mem.running then digiline_send("monitordisp","System halted\n") end + mem.running = false + mem.hexloading = true + digiline_send("monitordisp","Loading Intel\nHEX data") + digiline_send("stdout","\n\n\n\n\n\n\n") + mem.registers.pc = 0 + end + local address = event.msg.address + local data = event.msg.data + local size = event.msg.size + digiline_send("monitordisp",string.format("%08X\n",address)) + for i=0,size-1 do + local thisdata = tonumber(string.sub(data,i*2+1,i*2+2),16) + local thisaddress = address + i + writeram(thisaddress,thisdata,1) + end + end +elseif event.type == "digiline" then + --Unrecognized digilines signals get forwarded on to the program + event.channel = string.sub(event.channel,1,256) + event.msg = string.sub(tostring(event.msg),1,256) + if #mem.digilinesqueue < 16 then + table.insert(mem.digilinesqueue,{channel = event.channel, msg = event.msg}) + end + if mem.csr[0x800]%2 == 1 then + interrupt(0,"tick") + end +elseif event.iid == "tick" and mem.running then + run(INSTRUCTIONS_PER_CLOCK) + if mem.csr[0x800]%2 == 1 then + interrupt(1,"tick",true) + else + interrupt(1/CLOCK_SPEED,"tick") + end +end + +if stdoutdirty then + local text = table.concat(mem.stdout,"\n") + digiline_send("stdout",text.."\n") + stdoutdirty = false +end -- cgit v1.2.3