280 lines
6.1 KiB
Kotlin
280 lines
6.1 KiB
Kotlin
// -------------------------------------------------------------
|
|
// ilo.kt, (c) charles childers
|
|
//
|
|
// build:
|
|
//
|
|
// kotlinc ilo.kt -include-runtime -d ilo.jar
|
|
//
|
|
// run:
|
|
//
|
|
// kotlin ilo.jar
|
|
// -------------------------------------------------------------
|
|
|
|
import java.io.File
|
|
|
|
var blocks = IntArray(1024*1024*4)
|
|
var input = ""
|
|
var ip = 0
|
|
var m = IntArray(65536)
|
|
var d = Stack()
|
|
var a = Stack()
|
|
|
|
fun ino() {}
|
|
fun ili() { ip++; d.push(m[ip]) }
|
|
fun idu() { d.push(d.tos()) }
|
|
fun idr() { d.pop() }
|
|
fun isw() { var x = d.pop(); var y = d.pop(); d.push(x); d.push(y) }
|
|
fun ipu() { a.push(d.pop()) }
|
|
fun ipo() { d.push(a.pop()) }
|
|
fun iju() { ip = d.pop() - 1 }
|
|
fun ica() { a.push(ip); iju() }
|
|
fun icc() { val t = d.pop(); if (d.pop() != 0) { a.push(ip); ip = t - 1 } }
|
|
fun icj() { val t = d.pop(); if (d.pop() != 0) { ip = t - 1 } }
|
|
fun ire() { ip = a.pop() }
|
|
fun ieq() { val x = d.pop(); val y = d.pop(); if (y == x) { d.push(-1) } else { d.push(0) } }
|
|
fun ine() { val x = d.pop(); val y = d.pop(); if (y != x) { d.push(-1) } else { d.push(0) } }
|
|
fun ilt() { val x = d.pop(); val y = d.pop(); if (y < x) { d.push(-1) } else { d.push(0) } }
|
|
fun igt() { val x = d.pop(); val y = d.pop(); if (y > x) { d.push(-1) } else { d.push(0) } }
|
|
fun ife() { val t = d.pop(); d.push(m[t]) }
|
|
fun ist() { val t = d.pop(); m[t] = d.pop() }
|
|
fun iad() { val x = d.pop(); val y = d.pop(); d.push(y + x) }
|
|
fun isu() { val x = d.pop(); val y = d.pop(); d.push(y - x) }
|
|
fun imu() { val x = d.pop(); val y = d.pop(); d.push(y * x) }
|
|
fun idi() { val x = d.pop(); val y = d.pop(); d.push(y % x); d.push(y / x) }
|
|
fun ian() { val x = d.pop(); val y = d.pop(); d.push(y and x) }
|
|
fun ior() { val x = d.pop(); val y = d.pop(); d.push(y or x) }
|
|
fun ixo() { val x = d.pop(); val y = d.pop(); d.push(y xor x) }
|
|
fun isl() { val x = d.pop(); val y = d.pop(); d.push(y shl x) }
|
|
fun isr() { val x = d.pop(); val y = d.pop(); d.push(y shr x) }
|
|
fun icp() {
|
|
var l = d.pop()
|
|
var t = d.pop()
|
|
var s = d.pop()
|
|
d.push(-1)
|
|
while (l > 0) {
|
|
if (m[t] != m[s]) { d.pop(); d.push(0) }
|
|
t++; s++; l--
|
|
}
|
|
}
|
|
fun icy() {
|
|
var l = d.pop()
|
|
var t = d.pop()
|
|
var s = d.pop()
|
|
while (l > 0) {
|
|
m[t] = m[s]
|
|
t++; s++; l--
|
|
}
|
|
}
|
|
fun iio() {
|
|
when (d.pop()) {
|
|
0 -> io_co()
|
|
1 -> io_ci()
|
|
2 -> io_rb()
|
|
3 -> io_wb()
|
|
4 -> io_si()
|
|
5 -> io_pc()
|
|
6 -> io_of()
|
|
7 -> io_sd()
|
|
}
|
|
}
|
|
|
|
fun io_co() { print(d.pop().toChar()) }
|
|
fun io_ci() {
|
|
if (input.length > 0) {
|
|
val c = input.first()
|
|
val v = c.code
|
|
d.push(v)
|
|
input = input.drop(1)
|
|
} else {
|
|
d.push(32)
|
|
}
|
|
}
|
|
fun io_rb() { read_block() }
|
|
fun io_wb() { write_block() }
|
|
fun io_si() { }
|
|
fun io_pc() { boot(); ip = -1 }
|
|
fun io_of() { ip = 65536 }
|
|
fun io_sd() { d.push(d.depth()); d.push(a.depth()) }
|
|
|
|
// -------------------------------------------------------------
|
|
// -------------------------------------------------------------
|
|
|
|
fun load_blocks() {
|
|
val bs = File("./ilo.blocks")
|
|
val bytes:ByteArray = bs.readBytes()
|
|
var i = 0
|
|
var o = 0
|
|
while (i < (1024*1024)) {
|
|
val x = (bytes[o++].toInt() and 0xff shl 24) or
|
|
(bytes[o++].toInt() and 0xff shl 16) or
|
|
(bytes[o++].toInt() and 0xff shl 8) or
|
|
(bytes[o++].toInt() and 0xff)
|
|
blocks[i] = fix(x.toLong())
|
|
i++
|
|
}
|
|
}
|
|
|
|
fun read_block() {
|
|
load_blocks()
|
|
val buffer = d.pop()
|
|
val block = d.pop()
|
|
var i = 0
|
|
while (i < 1024) {
|
|
m[buffer + i] = blocks[(block * 1024) + i]
|
|
i++
|
|
}
|
|
}
|
|
|
|
fun write_block() {
|
|
val buffer = d.pop()
|
|
val block = d.pop()
|
|
|
|
// update `blocks` cache
|
|
var i = 0
|
|
while (i < 1024) {
|
|
blocks[(block * 1024) + i] = m[buffer + i]
|
|
i++
|
|
}
|
|
|
|
// write `blocks` cache back to disk
|
|
val bs = File("./ilo.blocks")
|
|
var dump: ByteArray = ByteArray(1024*1024*4)
|
|
|
|
i = 0
|
|
var o = 0
|
|
while (i < (1024*1024)) {
|
|
val cell = fix(blocks[i].toLong())
|
|
dump[o++] = ((cell shr 24) and 0xFF).toByte()
|
|
dump[o++] = ((cell shr 16) and 0xFF).toByte()
|
|
dump[o++] = ((cell shr 8) and 0xFF).toByte()
|
|
dump[o++] = (cell and 0xFF).toByte()
|
|
i++
|
|
}
|
|
bs.writeBytes(dump)
|
|
}
|
|
|
|
fun process_instruction(op: Int) {
|
|
when (op) {
|
|
0 -> ino()
|
|
1 -> ili()
|
|
2 -> idu()
|
|
3 -> idr()
|
|
4 -> isw()
|
|
5 -> ipu()
|
|
6 -> ipo()
|
|
7 -> iju()
|
|
8 -> ica()
|
|
9 -> icc()
|
|
10 -> icj()
|
|
11 -> ire()
|
|
12 -> ieq()
|
|
13 -> ine()
|
|
14 -> ilt()
|
|
15 -> igt()
|
|
16 -> ife()
|
|
17 -> ist()
|
|
18 -> iad()
|
|
19 -> isu()
|
|
20 -> imu()
|
|
21 -> idi()
|
|
22 -> ian()
|
|
23 -> ior()
|
|
24 -> ixo()
|
|
25 -> isl()
|
|
26 -> isr()
|
|
27 -> icp()
|
|
28 -> icy()
|
|
29 -> iio()
|
|
else -> {
|
|
println("Invalid instruction!")
|
|
print("IP:")
|
|
print(ip)
|
|
print(" OC:")
|
|
println(op)
|
|
}
|
|
}
|
|
}
|
|
|
|
fun process() {
|
|
while (input.length > 0 && ip < 65536) {
|
|
val cur = ip
|
|
process_instruction(m[cur] and 0xFF)
|
|
process_instruction((m[cur] shr 8) and 0xFF)
|
|
process_instruction((m[cur] shr 16) and 0xFF)
|
|
process_instruction((m[cur] shr 24) and 0xFF)
|
|
ip++
|
|
}
|
|
}
|
|
|
|
fun boot() {
|
|
load_image()
|
|
load_blocks()
|
|
ip = 0
|
|
d.empty()
|
|
a.empty()
|
|
input = " "
|
|
process()
|
|
}
|
|
|
|
fun load_image() {
|
|
val bs = File("./ilo.rom")
|
|
val bytes:ByteArray = bs.readBytes()
|
|
var i = 0
|
|
var o = 0
|
|
while (i < 65536) {
|
|
val x = (bytes[o++].toInt() and 0xff shl 24) or
|
|
(bytes[o++].toInt() and 0xff shl 16) or
|
|
(bytes[o++].toInt() and 0xff shl 8) or
|
|
(bytes[o++].toInt() and 0xff)
|
|
m[i] = fix(x.toLong())
|
|
i++
|
|
}
|
|
}
|
|
|
|
// The JVM is a big endian system. ilo stores data & rom in
|
|
// little endian. This routine converts the data between these
|
|
// when necessary.
|
|
|
|
fun fix(v: Long): Int {
|
|
return (((v and 0x000000FF) shl 24) or
|
|
((v and 0x0000FF00) shl 8) or
|
|
((v and 0x00FF0000) shr 8) or
|
|
((v and 0xFF000000) shr 24)).toInt()
|
|
}
|
|
|
|
fun main(args: Array<String>) {
|
|
boot()
|
|
while (ip < 65536) {
|
|
input = readln()
|
|
input = " " + input + " \n"
|
|
process()
|
|
}
|
|
}
|
|
|
|
|
|
class Stack {
|
|
var sp = 0
|
|
var data = IntArray(256)
|
|
|
|
fun push(v: Int) {
|
|
sp++
|
|
data[sp] = v
|
|
}
|
|
|
|
fun pop(): Int {
|
|
sp--
|
|
return data[sp + 1]
|
|
}
|
|
|
|
fun tos(): Int {
|
|
return data[sp]
|
|
}
|
|
|
|
fun empty() {
|
|
sp = 0
|
|
}
|
|
|
|
fun depth(): Int {
|
|
return sp
|
|
}
|
|
}
|