Koyaanisqatsi CPU Command Encoder

http://anycpu.org/forum/viewtopic.php?f=23&t=823

by Ruslan Alikberov

HTML

<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>

CSS

body {
	font-size: 2em;
}
input {
	font-size: 1em;
	width: 90%;
}

JavaScript

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...