// Ruri/IJVMA implementation of CipherSaber-1.
// By Tom Rothamel <tom-11083@onegeek.org> 
// This software has NO WARRANTY, and is released under the terms of the
// GNU GPL.

.constant
objref 0x14a11
tff 0xFF
tfs 0x100
.end-constant

.main
.var
s1
s2
klen
c
bm
tff
tfs
i
j
k
temp
.end-var
	/// {

	/// (tff = const tff);
	LDC_W tff
	ISTORE tff

	/// (tfs = const tfs);
	LDC_W tfs
	ISTORE tfs

	/// (s1 = alloca(tfs));
	ILOAD tfs
	ALLOCA
	ISTORE s1

	/// (s2 = alloca(tfs));
	ILOAD tfs
	ALLOCA
	ISTORE s2

	/// (klen = 0);
	BIPUSH 0x0
	ISTORE klen

	/// out "Enter key:\n";
	BIPUSH 0x45
	OUT
	BIPUSH 0x6E
	OUT
	BIPUSH 0x74
	OUT
	BIPUSH 0x65
	OUT
	BIPUSH 0x72
	OUT
	BIPUSH 0x20
	OUT
	BIPUSH 0x6B
	OUT
	BIPUSH 0x65
	OUT
	BIPUSH 0x79
	OUT
	BIPUSH 0x3A
	OUT
	BIPUSH 0xA
	OUT

	/// while (true)
	// Condition always true, omitting condition.
cond0continue:
	/// {

	/// (c = getchar(1));
	LDC_W OBJREF
	BIPUSH 0x1
	INVOKEVIRTUAL getchar
	ISTORE c

	/// if (c == 10)
	BIPUSH 0xA
	ILOAD c
	IF_ICMPEQ cond1true
	GOTO cond1false
cond1true:

	/// break
	GOTO cond0break
cond1false:

	/// (s2[klen] = c);
	ILOAD c
	ILOAD klen
	ILOAD s2
	BASE
	IPUT

	/// (klen = (klen + 1));
	ILOAD klen
	BIPUSH 0x1
	IADD
	ISTORE klen
	/// }
	GOTO cond0continue
cond0break:

	/// out "Enter ISV (first ten bytes of cyphertext, in hex):\n";
	BIPUSH 0x45
	OUT
	BIPUSH 0x6E
	OUT
	BIPUSH 0x74
	OUT
	BIPUSH 0x65
	OUT
	BIPUSH 0x72
	OUT
	BIPUSH 0x20
	OUT
	BIPUSH 0x49
	OUT
	BIPUSH 0x53
	OUT
	BIPUSH 0x56
	OUT
	BIPUSH 0x20
	OUT
	BIPUSH 0x28
	OUT
	BIPUSH 0x66
	OUT
	BIPUSH 0x69
	OUT
	BIPUSH 0x72
	OUT
	BIPUSH 0x73
	OUT
	BIPUSH 0x74
	OUT
	BIPUSH 0x20
	OUT
	BIPUSH 0x74
	OUT
	BIPUSH 0x65
	OUT
	BIPUSH 0x6E
	OUT
	BIPUSH 0x20
	OUT
	BIPUSH 0x62
	OUT
	BIPUSH 0x79
	OUT
	BIPUSH 0x74
	OUT
	BIPUSH 0x65
	OUT
	BIPUSH 0x73
	OUT
	BIPUSH 0x20
	OUT
	BIPUSH 0x6F
	OUT
	BIPUSH 0x66
	OUT
	BIPUSH 0x20
	OUT
	BIPUSH 0x63
	OUT
	BIPUSH 0x79
	OUT
	BIPUSH 0x70
	OUT
	BIPUSH 0x68
	OUT
	BIPUSH 0x65
	OUT
	BIPUSH 0x72
	OUT
	BIPUSH 0x74
	OUT
	BIPUSH 0x65
	OUT
	BIPUSH 0x78
	OUT
	BIPUSH 0x74
	OUT
	BIPUSH 0x2C
	OUT
	BIPUSH 0x20
	OUT
	BIPUSH 0x69
	OUT
	BIPUSH 0x6E
	OUT
	BIPUSH 0x20
	OUT
	BIPUSH 0x68
	OUT
	BIPUSH 0x65
	OUT
	BIPUSH 0x78
	OUT
	BIPUSH 0x29
	OUT
	BIPUSH 0x3A
	OUT
	BIPUSH 0xA
	OUT

	/// for ((i = 0); i < 10; (i = (i + 1))
	// for: initalization expression
	BIPUSH 0x0
	ISTORE i
cond2loop:
	// for: loop condition
	ILOAD i
	BIPUSH 0xA
	ISUB
	IFLT cond2true
	GOTO cond2false
	// for: loop body
cond2true:
	/// {

	/// (s2[klen] = readbyte(1));
	LDC_W OBJREF
	BIPUSH 0x1
	INVOKEVIRTUAL readbyte
	ILOAD klen
	ILOAD s2
	BASE
	IPUT

	/// (klen = (klen + 1));
	ILOAD klen
	BIPUSH 0x1
	IADD
	ISTORE klen
	/// }

cond2continue:
	// for: repetition expression
	ILOAD i
	BIPUSH 0x1
	IADD
	ISTORE i
	GOTO cond2loop
cond2break:
cond2false:

	/// out "\nDone. Setting up keys.\n";
	BIPUSH 0xA
	OUT
	BIPUSH 0x44
	OUT
	BIPUSH 0x6F
	OUT
	BIPUSH 0x6E
	OUT
	BIPUSH 0x65
	OUT
	BIPUSH 0x2E
	OUT
	BIPUSH 0x20
	OUT
	BIPUSH 0x53
	OUT
	BIPUSH 0x65
	OUT
	BIPUSH 0x74
	OUT
	BIPUSH 0x74
	OUT
	BIPUSH 0x69
	OUT
	BIPUSH 0x6E
	OUT
	BIPUSH 0x67
	OUT
	BIPUSH 0x20
	OUT
	BIPUSH 0x75
	OUT
	BIPUSH 0x70
	OUT
	BIPUSH 0x20
	OUT
	BIPUSH 0x6B
	OUT
	BIPUSH 0x65
	OUT
	BIPUSH 0x79
	OUT
	BIPUSH 0x73
	OUT
	BIPUSH 0x2E
	OUT
	BIPUSH 0xA
	OUT

	/// for ((i = klen); i < tfs; (i = (i + 1))
	// for: initalization expression
	ILOAD klen
	ISTORE i
cond3loop:
	// for: loop condition
	ILOAD i
	ILOAD tfs
	ISUB
	IFLT cond3true
	GOTO cond3false
	// for: loop body
cond3true:
	/// {

	/// (s2[i] = s2[(i - klen)]);
	ILOAD i
	ILOAD klen
	ISUB
	ILOAD s2
	BASE
	IGET
	ILOAD i
	ILOAD s2
	BASE
	IPUT
	// }

cond3continue:
	// for: repetition expression
	ILOAD i
	BIPUSH 0x1
	IADD
	ISTORE i
	GOTO cond3loop
cond3break:
cond3false:

	/// for ((i = 0); i < tfs; (i = (i + 1))
	// for: initalization expression
	BIPUSH 0x0
	ISTORE i
cond4loop:
	// for: loop condition
	ILOAD i
	ILOAD tfs
	ISUB
	IFLT cond4true
	GOTO cond4false
	// for: loop body
cond4true:
	/// {

	/// (s1[i] = i);
	ILOAD i
	ILOAD i
	ILOAD s1
	BASE
	IPUT
	// }

cond4continue:
	// for: repetition expression
	ILOAD i
	BIPUSH 0x1
	IADD
	ISTORE i
	GOTO cond4loop
cond4break:
cond4false:

	/// (j = 0);
	BIPUSH 0x0
	ISTORE j

	/// for ((i = 0); i < tfs; (i = (i + 1))
	// for: initalization expression
	BIPUSH 0x0
	ISTORE i
cond5loop:
	// for: loop condition
	ILOAD i
	ILOAD tfs
	ISUB
	IFLT cond5true
	GOTO cond5false
	// for: loop body
cond5true:
	/// {

	/// (j = ((j + s1[i] + s2[i]) & tff));
	ILOAD j
	ILOAD i
	ILOAD s1
	BASE
	IGET
	ILOAD i
	ILOAD s2
	BASE
	IGET
	IADD
	IADD
	ILOAD tff
	IAND
	ISTORE j

	/// (temp = s1[i]);
	ILOAD i
	ILOAD s1
	BASE
	IGET
	ISTORE temp

	/// (s1[i] = s1[j]);
	ILOAD j
	ILOAD s1
	BASE
	IGET
	ILOAD i
	ILOAD s1
	BASE
	IPUT

	/// (s1[j] = temp);
	ILOAD temp
	ILOAD j
	ILOAD s1
	BASE
	IPUT

	/// (s2[i] = 0);
	BIPUSH 0x0
	ILOAD i
	ILOAD s2
	BASE
	IPUT
	/// }

cond5continue:
	// for: repetition expression
	ILOAD i
	BIPUSH 0x1
	IADD
	ISTORE i
	GOTO cond5loop
cond5break:
cond5false:

	/// out "Setup done. Enter cyphertext in hex (will not echo):\n";
	BIPUSH 0x53
	OUT
	BIPUSH 0x65
	OUT
	BIPUSH 0x74
	OUT
	BIPUSH 0x75
	OUT
	BIPUSH 0x70
	OUT
	BIPUSH 0x20
	OUT
	BIPUSH 0x64
	OUT
	BIPUSH 0x6F
	OUT
	BIPUSH 0x6E
	OUT
	BIPUSH 0x65
	OUT
	BIPUSH 0x2E
	OUT
	BIPUSH 0x20
	OUT
	BIPUSH 0x45
	OUT
	BIPUSH 0x6E
	OUT
	BIPUSH 0x74
	OUT
	BIPUSH 0x65
	OUT
	BIPUSH 0x72
	OUT
	BIPUSH 0x20
	OUT
	BIPUSH 0x63
	OUT
	BIPUSH 0x79
	OUT
	BIPUSH 0x70
	OUT
	BIPUSH 0x68
	OUT
	BIPUSH 0x65
	OUT
	BIPUSH 0x72
	OUT
	BIPUSH 0x74
	OUT
	BIPUSH 0x65
	OUT
	BIPUSH 0x78
	OUT
	BIPUSH 0x74
	OUT
	BIPUSH 0x20
	OUT
	BIPUSH 0x69
	OUT
	BIPUSH 0x6E
	OUT
	BIPUSH 0x20
	OUT
	BIPUSH 0x68
	OUT
	BIPUSH 0x65
	OUT
	BIPUSH 0x78
	OUT
	BIPUSH 0x20
	OUT
	BIPUSH 0x28
	OUT
	BIPUSH 0x77
	OUT
	BIPUSH 0x69
	OUT
	BIPUSH 0x6C
	OUT
	BIPUSH 0x6C
	OUT
	BIPUSH 0x20
	OUT
	BIPUSH 0x6E
	OUT
	BIPUSH 0x6F
	OUT
	BIPUSH 0x74
	OUT
	BIPUSH 0x20
	OUT
	BIPUSH 0x65
	OUT
	BIPUSH 0x63
	OUT
	BIPUSH 0x68
	OUT
	BIPUSH 0x6F
	OUT
	BIPUSH 0x29
	OUT
	BIPUSH 0x3A
	OUT
	BIPUSH 0xA
	OUT

	/// (i = 0);
	BIPUSH 0x0
	ISTORE i

	/// (j = 0);
	BIPUSH 0x0
	ISTORE j

	/// while (true)
	// Condition always true, omitting condition.
cond6continue:
	/// {

	/// (c = readbyte(0));
	LDC_W OBJREF
	BIPUSH 0x0
	INVOKEVIRTUAL readbyte
	ISTORE c

	/// (i = ((i + 1) & tff));
	ILOAD i
	BIPUSH 0x1
	IADD
	ILOAD tff
	IAND
	ISTORE i

	/// (j = ((j + s1[i]) & tff));
	ILOAD j
	ILOAD i
	ILOAD s1
	BASE
	IGET
	IADD
	ILOAD tff
	IAND
	ISTORE j

	/// (temp = s1[i]);
	ILOAD i
	ILOAD s1
	BASE
	IGET
	ISTORE temp

	/// (s1[i] = s1[j]);
	ILOAD j
	ILOAD s1
	BASE
	IGET
	ILOAD i
	ILOAD s1
	BASE
	IPUT

	/// (s1[j] = temp);
	ILOAD temp
	ILOAD j
	ILOAD s1
	BASE
	IPUT

	/// (k = ((s1[i] + s1[j]) & tff));
	ILOAD i
	ILOAD s1
	BASE
	IGET
	ILOAD j
	ILOAD s1
	BASE
	IGET
	IADD
	ILOAD tff
	IAND
	ISTORE k

	/// (k = s1[k]);
	ILOAD k
	ILOAD s1
	BASE
	IGET
	ISTORE k

	/// out (xor(c, k) & 255);
	LDC_W OBJREF
	ILOAD c
	ILOAD k
	INVOKEVIRTUAL xor
	BIPUSH 0xFF
	IAND
	OUT
	/// }
	GOTO cond6continue
cond6break:

	HALT
	/// }
.end-main

.method xor(a, b)
.var
.end-var
	/// {

	/// return ((~a & b) | (a & ~b));
	BIPUSH -1
	ILOAD a
	ISUB
	ILOAD b
	IAND
	ILOAD a
	BIPUSH -1
	ILOAD b
	ISUB
	IAND
	IOR
	IRETURN
	// }
.end-method

.method getchar(echo)
.var
c
.end-var
	/// {

	/// while (!((c = in)))
cond7continue:
	IN
	DUP
	ISTORE c
	IFEQ cond7true
	GOTO cond7false
cond7true:
	/// {
	/// }
	GOTO cond7continue
cond7break:
cond7false:

	/// if (echo)
	ILOAD echo
	IFEQ cond8false
	GOTO cond8true
cond8true:

	/// out c;
	ILOAD c
	OUT
cond8false:

	/// return c;
	ILOAD c
	IRETURN
	/// }
.end-method

.method readbyte(echo)
.var
val
read
c
.end-var
	/// {

	/// (val = 0);
	BIPUSH 0x0
	ISTORE val

	/// (read = 0);
	BIPUSH 0x0
	ISTORE read

	/// while (true)
	// Condition always true, omitting condition.
cond9continue:
	/// {

	/// (c = getchar(echo));
	LDC_W OBJREF
	ILOAD echo
	INVOKEVIRTUAL getchar
	ISTORE c

	/// if (!(c < 48) && !(c > 57))
	ILOAD c
	BIPUSH 0x30
	ISUB
	IFLT cond10false
	GOTO cond11true
cond11true:
	BIPUSH 0x39
	ILOAD c
	ISUB
	IFLT cond10false
	GOTO cond10true
cond10true:
	/// {

	/// (read = (read + 1));
	ILOAD read
	BIPUSH 0x1
	IADD
	ISTORE read

	/// (val = (((val << 4) + c) - 48));
	ILOAD val
	DUP
	IADD
	DUP
	IADD
	DUP
	IADD
	DUP
	IADD
	ILOAD c
	IADD
	BIPUSH 0x30
	ISUB
	ISTORE val
	/// }

	GOTO cond10done
	/// else
cond10false:

	/// if (!(c < 97) && !(c > 102))
	ILOAD c
	BIPUSH 0x61
	ISUB
	IFLT cond12false
	GOTO cond13true
cond13true:
	BIPUSH 0x66
	ILOAD c
	ISUB
	IFLT cond12false
	GOTO cond12true
cond12true:
	/// {

	/// (read = (read + 1));
	ILOAD read
	BIPUSH 0x1
	IADD
	ISTORE read

	/// (val = ((((val << 4) + c) - 97) + 10));
	ILOAD val
	DUP
	IADD
	DUP
	IADD
	DUP
	IADD
	DUP
	IADD
	ILOAD c
	IADD
	BIPUSH 0x61
	ISUB
	BIPUSH 0xA
	IADD
	ISTORE val
	/// }

	GOTO cond12done
	/// else
cond12false:

	/// if (!(c < 65) && !(c > 70))
	ILOAD c
	BIPUSH 0x41
	ISUB
	IFLT cond14false
	GOTO cond15true
cond15true:
	BIPUSH 0x46
	ILOAD c
	ISUB
	IFLT cond14false
	GOTO cond14true
cond14true:
	/// {

	/// (read = (read + 1));
	ILOAD read
	BIPUSH 0x1
	IADD
	ISTORE read

	/// (val = ((((val << 4) + c) - 65) + 10));
	ILOAD val
	DUP
	IADD
	DUP
	IADD
	DUP
	IADD
	DUP
	IADD
	ILOAD c
	IADD
	BIPUSH 0x41
	ISUB
	BIPUSH 0xA
	IADD
	ISTORE val
	/// }
cond14false:
cond12done:
cond10done:

	/// if (read == 2)
	BIPUSH 0x2
	ILOAD read
	IF_ICMPEQ cond16true
	GOTO cond16false
cond16true:

	/// return val;
	ILOAD val
	IRETURN
cond16false:
	/// }
	GOTO cond9continue
cond9break:
	/// }
.end-method
