// ------------------------------------------------------------- // 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) { 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 } }