<html><head>
<title>Koyaanisqatsi Instructions Encoder</title>
<style>
body {
font-size:2em;
}
input {
font-size:1em;
width:90%;
}
</style>
<script>
function parse_vector(text) {
var i, j;
var prd = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
var ofs = 0, sign = 1, scan = 0, mode = 0;
var codes = [], code, parts, part;
var uses, used = 0, using, usings = [], base;
if(text.match(/[0-7_]+#/))
mode = +(text.replace(/0/g, "8").replace(/_/g, "9").match(/(\d+)/)[1]),
parts = text.replace(/[0-7_]+#/, "").match(/(D\d)|(\+\d*D\d)|([-+]\d+)/gi);
else
parts = text.match(/(D\d)|(\+\d*\*?D\d)|([-+]?\d+)/gi);
if(parts) {
if(parts[0].match(/^D\d$/i))
base = +(parts[0].substr(-1));
else
if(parts[0].match(/[-+]\d+/))
ofs = +(parts[0].substr(1)),
base = 9;
for(part of parts) {
if(part.match(/\+\d*D\d/i)) {
prd[+(part.substr(-1))] += isFinite(parseInt(part.substr(1))) ? parseInt(part.substr(1)) : 1;
} else
if(part.match(/[-+]\d+/)) {
if(part.match(/-\d+/))
sign = -1;
ofs = +(part.substr(1));
}
}
for(i = 0; i <= 9; ++ i) {
j = -1;
while((prd[i] >> (j + 1)) > 0)
++ j;
if(scan < j)
scan = j;
}
usings.push(base);
while(scan >= 0) {
uses = 0;
using = [];
i = usings.pop();
code = [];
if((prd[i] >> scan) > 0) {
prd[i] -= 1 << scan;
uses |= 1 << i;
code.push(i);
if(scan > 0 && ((prd[i] >> (scan - 1)) & 1) > 0)
using.push(String(i));
}
for(i = 0; i <= 9; ++ i) {
if((prd[i] >> scan) > 0) {
uses |= 1 << i;
code.push(String(i));
if(scan > 0 && ((prd[i] >> (scan - 1)) & 1) > 0)
using.push(i);
}
}
if((used & uses) == 0)
codes.push(String(base));
codes = codes.concat(code);
for(i = 0; i <= 9; ++ i) {
if((prd[i] >> scan) > 0)
prd[i] -= 1 << scan;
}
-- scan;
used = uses;
usings = [base].concat(using);
}
}
i = codes.length;
while(-- i >= 0)
codes[i] += String(ofs % 10),
ofs = (ofs / 10) | 0;
while(ofs > 0)
codes.unshift(base + String(ofs % 10)),
ofs = (ofs / 10) | 0;
if(sign < 0)
codes.unshift(base + "0");
if(typeof mode != "number")
mode = mode ? Number(mode[1]) : 0;
while(mode > 0)
codes.unshift((mode % 10) + "0", (mode % 10) + "0"),
mode = (mode / 10) | 0;
return codes.join(" ");
}
function encode(el) {
var alu = {
ADD:10, ADC:10, INC:10,
DEC:11, SBB:11, SUB:11,
AND:12, CLR:12, CON:12,
DIS:13, OR:13, SET:13,
EOR:14, NOT:14, XOR:14,
FOR:15, MOV:15
};
var rex = /(?<Label>[^:;"'`\s]*(?::))?(?:\s)*(?<Instruction>[A-Z]*)(?<Junk>[\d_]*)(?:\s*)(?<Operand1>[^\s,;"'`]*)(?:[,\s]*)?(?<Operand2>[^\s,;"'`]*)?(?:[,\s]*)?(?<Operand3>[^\s,;"'`]*)(?:[,\s]*)?(?:(?:("(?:\\.|.)*?")|('(?:\\.|.)*?')|(`(?:\\.|.)*?`)|[^;"'`]*)*)*(\.*)/i;
var part = rex.exec(el.value);
var command = (part.groups.Instruction + " " + part.groups.Operand1 + (part[4] ? "," + part[4] + (part[5] ? "," + part[5] : "") : "")).toUpperCase();
var arg = [];
var inf = [];
var __, _ = [];
var encode = "", codes = "";
var prefixes = "";
var junks = "";
var group = part.groups.Instruction
.replace(/^(ADC|ADD|AND|CON|DIS|EOR|FOR|MOV|OR|SBB|SUB|XOR)$/i, "ALU")
.replace(/^(CLR|DEC|INC|NOT|SET)$/i, "UNA");
var no_carry = (part[2].match(/^(ADD|SUB)$/i)) ? "CE " : "";
if(part[2].toUpperCase() in alu)
encode = alu[part[2].toUpperCase()];
for(var j = 4; j <= 6 && j < part.length; ++ j) {
if(part[j] && part[j] != "") {
if(part[j].match(/^(BC\d|D\d\+)$|[-+]\d+$|^[0-7_]*#/g))
_.push("@"),
arg.push(prefixes = parse_vector(part[j].toUpperCase().replace("BC", "D")));
else
_.push(part[j]),
arg.push(part[j]);
} else
arg.push("");
}
if(part.groups.Junk)
junks = part.groups.Junk.replace(/_/g, "9").replace(/0/g, "8").replace(/(\d)/g, "$10 $10 ");
inf.push(0);
__ = part[2].toUpperCase() + (_.length > 0 ? " " + _.join() : "");
__ = __.search.bind(__);
_ = group + (_.length > 0 ? " " + _.join() : "");
_ = _.search.bind(_);
switch(0) {
case __(/MOV (A0|FLG|FLAGS|PSW),@$/i): codes = "AA A0 :: 0F"; break;
case __(/MOV @,(A0|FLG|FLAGS|PSW)$/i): codes = ":: A0"; break;
case _(/UNA @$/i): codes = "AA A0 :: 0_"; break;
case _(/EXI$/i): codes = "AA A0 0E"; break;
case _(/SWP @,D[0-9]$/i): codes = "AY A0 :: yF"; break;
case _(/SWP D[0-9],@$/i): codes = "AX A0 :: xF"; break;
case __(/MOV @,([ABCD][0-9])$/i): codes = ":: Yy"; break;
case _(/ALU @,D[0-9]$/i): codes = "AY A0 ~:: y_"; break;
case _(/INF D[0-9]$/i): codes = "AX A0 #xF"; break;
case _(/EHI|EI|STI$/i): codes = "AD A0 #0C"; break;
case _(/UNA D[0-9]$/i): codes = "AD A0 #x_"; break;
case _(/SWP (A[1-9]|[BC][0-9]),@$/i): codes = "AX A0 :: xF"; break;
case _(/SWP @,(A[1-9]|[BC][0-9])$/i): codes = "AY A0 :: yF"; break;
case _(/ALU @,(A[1-9]|[BC][0-9])$/i): codes = "AY A0 ~:: y_"; break;
case __(/MOV (A0|FLG|FLAGS|PSW),(A[1-9]|[BC][0-9])$/i): codes = "AY A0 #yF"; break;
case _(/UNA (A[1-9]|[BC][0-9])$/i): codes = "AX A0 #x_"; break;
case _(/ALU D[0-9],@$/i): codes = "XA Xx ~:: 0_"; break;
case _(/OUF D[0-9]$/i): codes = "XA Xx #0F"; break;
case _(/UNA D[0-9],CF$/i): codes = "XA Xx #0_"; break;
case _(/ALU (A[1-9]|[BC][0-9]),@$/i): codes = "XA Xx ~:: 0_"; break;
case __(/MOV (A[1-9]|[BC][0-9]),(A0|FLG|FLAGS|PSW)$/i): codes = "XA Xx #0F"; break;
case _(/UNA (A[1-9]|[BC][0-9]),CF$/i): codes = "XA Xx #0_"; break;
case _(/LEA D[0-9],@$$/i): codes = "XX Xx :: xF"; break;
case _(/ORD @,(A[1-9]|[BCD][0-9]),(A[1-9]|[BCD][0-9])$$/i): codes = "YZ Yy :: zF"; break;
case _(/ALU D[0-9],@,D[0-9]$/i): codes = "XZ Xx :: z_"; break;
case _(/ALU D[0-9],D[0-9]$/i): codes = "XY Xx #y_"; break;
case _(/LEX (A[1-9]|[BCD][0-9]),@,(A[1-9]|[BC][0-9])$$/i): codes = "XZ Xx :: zF"; break;
case _(/ALU D[0-9],@,(A[1-9]|[BC][0-9])$/i): codes = "XZ Xx :: z_"; break;
case _(/OUT D[0-9],(A[1-9]|[BC][0-9])$/i): codes = "XY Xx #yF"; break;
case _(/ALU D[0-9],(A[1-9]|[BC][0-9])$/i): codes = "XY Xx ~#y_"; break;
case _(/ALU (A[1-9]|[BC][0-9]),@,D[0-9]$/i): codes = "XZ Xx ~:: z_"; break;
case _(/IN (A[1-9]|[BC][0-9]),D[0-9]$/i): codes = "XY Xx #yF"; break;
case _(/ALU (A[1-9]|[BC][0-9]),D[0-9]$/i): codes = "XY Xx ~#y_"; break;
case _(/ALU (A[1-9]|[BC][0-9]),@,(A[1-9]|[BC][0-9])$/i): codes = "XZ Xx ~:: z_"; break;
case _(/ALU (A[1-9]|[BC][0-9]),(A[1-9]|[BC][0-9])$/i): codes = "XY Xx ~#y_"; break;
case _(/ALU R[0-9]$/i): codes = "~#x_"; break;
case _(/ALU R,@,R[0-9]$/i): codes = "~:: z_"; break;
case _(/REG [ABCD][0-9],[ABCD][0-9],[ABCD][0-9]$/i): codes = "#Xx #Yy #Zz"; break;
case _(/REG [ABCD][0-9],[ABCD][0-9]$/i): codes = "#Xx #Yy"; break;
case _(/REG [ABCD][0-9]$/i): codes = "#Xx"; break;
case _(/ARG [ABCD][0-9],[ABCD][0-9]$/i): codes = "#XY Xx Yy"; break;
case _(/ARG [ABCD][0-9],[ABCD]$/i): codes = "#XY Xx"; break;
case _(/ARG [ABCD],[ABCD]$/i): codes = "#XY"; break;
case _(/BRK|HA?LT$/i): codes = "#00"; break;
case _(/(HA?LT|JU?MP) @$/i): codes = ":: 00"; break;
case __(/(CLR|ERA) [ABCD]F$/i): codes = "#XE"; break;
case __(/(CMP|FLP|INV|NOT) [ABCD]F$/i): codes = "#Xx"; break;
case __(/SET [ABCD]F$/i): codes = "#XE #Xx"; break;
case _(/(BRK|HA?LT|JU?MP|LOOP|RET) @,[ABCD]F$/i): codes = ":: Yy"; break;
case _(/DO @,[ABCD]F$/i): codes = ":: YE"; break;
case _(/(BRK|HA?LT|JU?MP|LOOP|RET) @,[ABCD]F,[ABCD]F$/i): codes = ":: YZ"; break;
case _(/(BRK|HA?LT|JU?MP|LOOP|RET) @,[ABCD]F,[ABCD]E$/i): codes = "ZF :: YZ ZF"; break;
case _(/(BRK|HA?LT|JU?MP|LOOP|RET) @,[ABCD]E,[ABCD]F$/i): codes = "YF :: YZ YF"; break;
case _(/(BRK|HA?LT|JU?MP|LOOP|RET) @,[ABCD]E,[ABCD]E$/i): codes = "YF ZF :: YZ ZF YF"; break;
}
if(codes != "") {
codes = codes
.replace(/::/g, (junks + prefixes).trim())
.replace(/#/g, junks)
.replace(/~/g, no_carry)
.replace(/_/g, encode.toString(16))
.replace(/X/g, arg[0].charAt(0))
.replace(/x/g, arg[0].charAt(1))
.replace(/Y/g, arg[1].charAt(0))
.replace(/y/g, arg[1].charAt(1))
.replace(/Z/g, arg[2].charAt(0))
.replace(/z/g, arg[2].charAt(1))
.toUpperCase()
.split(/\s/);
} else
codes = ["Error"];
document.querySelector(el.dataset.for).textContent = codes.join(" ");
}
</script>
</head>
<body>
<input type=text data-for='#Dump' placeholder='Type assembly at here' list=Samples onchange='encode(this)' spellcheck=false>
<pre id=Dump></pre>
<datalist id=Samples>
<option value='JUMP #D8+65536'>Jump [BC<sub>8</sub>+65536]</option>
<option value='SET CF'>Set Carry Flag</option>
<option value='INF D5'>Query Information about Port #5 and set Flags ZF/CF/OF/SF</option>
<option value='IN A4,D5'>Input data from Port #5 to Register A4</option>
<option value='ADC A7,C3'>Add C<sub>3</sub> to A<sub>7</sub> with Carry</option>
<option value='ADD86 A7,C3'>Add C<sub>3</sub> to A<sub>7</sub> in mode #86</option>
<option value='INC A7'>Increment Register A<sub>7</sub></option>
<option value='SBB A1,#D2'>Subtract from Register A<sub>1</sub> data from Memory cell pointed by D<sub>2</sub> with Borrow</option>
<option value='SUB #D2,A1'>Subtract from Memory cell pointed by D<sub>2</sub> the Register A<sub>1</sub></option>
<option value='DEC 7#D2'>Decrement Memory cell pointed by D<sub>2</sub> in mode #7</option>
<option value='LEA D1,#D2+3D3+4D4+56789'>Load Effective Address: Like x86-LEA</option>
<option value='LEX C1,#D2+3D3+4D4+56789,B0'>Lexical transform: Like x86-XLAT</option>
<option value='ORD #D1+234,D5,D6'>Put in Order Data from Memory and Register pairs BC<sub>6</sub> and set to BC<sub>5</sub> the average</option>
<option value='ORD #D1+234,C5,B6'>Put in Order Data from Memory and Register pairs BC<sub>6</sub> and set to C<sub>5</sub> the average</option>
</datalist>
</body>