Files
RustIJVM/files/custom/md5.jas

1603 lines
19 KiB
Plaintext

// vim: set fdm=marker:
// constants {{{
.constant
OBJREF 0xCAFEBABE
// 512 - 1 for modulo hack
SIZE_MODULO 511
SIZE_EQUIV 448
BIT_PAD_START 0x80
MASK_8 0xFF
MASK_31 0x7FFFFFFF
MASK_SIGN 0x80000000
BASE_H0 0x67452301
BASE_H1 0xEFCDAB89
BASE_H2 0x98BADCFE
BASE_H3 0x10325476
NOT_PATTERN 0xFFFFFFFF
XOR_PATTERN_1 0xAAAAAAAA
XOR_PATTERN_2 0x55555555
// Precalculated left-shift multipliers
SHL_24 0x01000000
SHL_16 0x00010000
SHL_8 0x00000100
// FUCK ME
SINES_0 0xd76aa478
SINES_1 0xe8c7b756
SINES_2 0x242070db
SINES_3 0xc1bdceee
SINES_4 0xf57c0faf
SINES_5 0x4787c62a
SINES_6 0xa8304613
SINES_7 0xfd469501
SINES_8 0x698098d8
SINES_9 0x8b44f7af
SINES_10 0xffff5bb1
SINES_11 0x895cd7be
SINES_12 0x6b901122
SINES_13 0xfd987193
SINES_14 0xa679438e
SINES_15 0x49b40821
SINES_16 0xf61e2562
SINES_17 0xc040b340
SINES_18 0x265e5a51
SINES_19 0xe9b6c7aa
SINES_20 0xd62f105d
SINES_21 0x02441453
SINES_22 0xd8a1e681
SINES_23 0xe7d3fbc8
SINES_24 0x21e1cde6
SINES_25 0xc33707d6
SINES_26 0xf4d50d87
SINES_27 0x455a14ed
SINES_28 0xa9e3e905
SINES_29 0xfcefa3f8
SINES_30 0x676f02d9
SINES_31 0x8d2a4c8a
SINES_32 0xfffa3942
SINES_33 0x8771f681
SINES_34 0x6d9d6122
SINES_35 0xfde5380c
SINES_36 0xa4beea44
SINES_37 0x4bdecfa9
SINES_38 0xf6bb4b60
SINES_39 0xbebfbc70
SINES_40 0x289b7ec6
SINES_41 0xeaa127fa
SINES_42 0xd4ef3085
SINES_43 0x04881d05
SINES_44 0xd9d4d039
SINES_45 0xe6db99e5
SINES_46 0x1fa27cf8
SINES_47 0xc4ac5665
SINES_48 0xf4292244
SINES_49 0x432aff97
SINES_50 0xab9423a7
SINES_51 0xfc93a039
SINES_52 0x655b59c3
SINES_53 0x8f0ccc92
SINES_54 0xffeff47d
SINES_55 0x85845dd1
SINES_56 0x6fa87e4f
SINES_57 0xfe2ce6e0
SINES_58 0xa3014314
SINES_59 0x4e0811a1
SINES_60 0xf7537e82
SINES_61 0xbd3af235
SINES_62 0x2ad7d2bb
SINES_63 0xeb86d391
.end-constant
// }}}
// main {{{
.main
.var
msg_chars
msg_len_byte
msg_len_word
msg_len_true
msg_buf
i
combined
.end-var
BIPUSH 0
ISTORE msg_chars
// INPUT LOOP
input_loop:
IN
DUP
IFEQ input_eof
IINC msg_chars 1
GOTO input_loop
input_eof:
POP // last zero
// calculate required buf length in bytes
LDC_W OBJREF
ILOAD msg_chars
INVOKEVIRTUAL calculate_size
ISTORE msg_len_byte
// We need to go shift characters together, but for that i want filled shit
// lets **add** a few characters :)
ILOAD msg_len_byte
ILOAD msg_chars
ISUB
// We always have at least one character to pad!
BIPUSH 1
ISUB
ISTORE i
LDC_W BIT_PAD_START // The 1 bit that's required
pad_loop:
ILOAD i
IFEQ pad_done
BIPUSH 0
IINC i -1
GOTO pad_loop
pad_done:
// Calculate heap size
LDC_W OBJREF
ILOAD msg_len_byte
BIPUSH 2
INVOKEVIRTUAL shr
ISTORE msg_len_word
// Allocate heap
ILOAD msg_len_word
BIPUSH 2 // remaining 64 bits
IADD
ISTORE msg_len_true
ILOAD msg_len_true
NEWARRAY
ISTORE msg_buf
// Index for storing
ILOAD msg_len_word
BIPUSH 1
ISUB
ISTORE i
fill_loop:
// pops off stack, stores in leftmost byte, clears rest
LDC_W OBJREF
SWAP
LDC_W SHL_24
SWAP // swap x, y for mul for speed!
INVOKEVIRTUAL mul
SWAP
// shift next byte 16, combine
LDC_W OBJREF
SWAP
LDC_W SHL_16
SWAP
INVOKEVIRTUAL mul
IOR
SWAP
// shift next byte 8, combine
LDC_W OBJREF
SWAP
LDC_W SHL_8
SWAP
INVOKEVIRTUAL mul
IOR
// final byte, no shift
IOR
// Value done!
// store it!
ILOAD i
ILOAD msg_buf
IASTORE
IINC i -1
ILOAD i
IFLT fill_done
GOTO fill_loop
fill_done:
// Finally we need the *bit size* at the end
// bit size
LDC_W OBJREF
ILOAD msg_chars
BIPUSH 8
INVOKEVIRTUAL mul
// load in last 2 bytes (lol 32bit only fuck you)
ILOAD msg_len_word
ILOAD msg_buf
IASTORE
LDC_W OBJREF
ILOAD msg_buf
ILOAD msg_len_true
INVOKEVIRTUAL md5sum
HALT
.end-main
// }}}
// calculate_size {{{
.method calculate_size(initial_size)
.var
size
.end-var
// Need to find length (with at least one padding) that satisfies bitlength
// x % 512 == 448
BIPUSH 1
LDC_W OBJREF
ILOAD initial_size
BIPUSH 8
INVOKEVIRTUAL mul
IADD
ISTORE size
loop:
ILOAD size
LDC_W SIZE_MODULO
IAND
LDC_W SIZE_EQUIV
IF_ICMPEQ found
// Add one, very fast!
IINC size 1
GOTO loop
found:
LDC_W OBJREF
ILOAD size
BIPUSH 3
INVOKEVIRTUAL shr
IRETURN
.end-method
// }}}
// md5sum {{{
.method md5sum(buf, len)
.var
offset
i
h0
h1
h2
h3
a
b
c
d
f
g
temp
round_shifts
round_sines
.end-var
// INITIALIZE STATE
BIPUSH 0
ISTORE offset
LDC_W BASE_H0
ISTORE h0
LDC_W BASE_H1
ISTORE h1
LDC_W BASE_H2
ISTORE h2
LDC_W BASE_H3
ISTORE h3
LDC_W OBJREF
INVOKEVIRTUAL get_round_shifts
ISTORE round_shifts
LDC_W OBJREF
INVOKEVIRTUAL get_sines
ISTORE round_sines
// todo offset loop
offset_loop:
// init hash values
ILOAD h0
ISTORE a
ILOAD h1
ISTORE b
ILOAD h2
ISTORE c
ILOAD h3
ISTORE d
// loop 64 rounds
BIPUSH 0
ISTORE i
main_loop:
ILOAD i
BIPUSH 64
IF_ICMPEQ main_loop_end
// determine round_type
ILOAD i
BIPUSH 16
ISUB
DUP
IFLT round_f
BIPUSH 16
ISUB
DUP
IFLT round_g
BIPUSH 16
ISUB
DUP
IFLT round_h
GOTO round_i
round_f:
// f = (b & c) | ((~b) & d)
// = b ~ d & b c & |
// g = i
LDC_W OBJREF
ILOAD b
INVOKEVIRTUAL not
ILOAD d
IAND
ILOAD b
ILOAD c
IAND
IOR
ISTORE f
ILOAD i
ISTORE g
GOTO rotate
round_g:
// f = ( d & b ) | ((~d) & c)
// = d ~ c & d b & |
// g = (5 * i + 1) % 16
LDC_W OBJREF
ILOAD d
INVOKEVIRTUAL not
ILOAD c
IAND
ILOAD d
ILOAD b
IAND
IOR
ISTORE f
LDC_W OBJREF
ILOAD i
BIPUSH 5
INVOKEVIRTUAL mul
BIPUSH 1
IADD
BIPUSH 15
IAND
ISTORE g
GOTO rotate
round_h:
// f = b ^ c ^ d
// = b c d ^ ^
// g = (3 * i + 5) % 16
LDC_W OBJREF
LDC_W OBJREF
ILOAD b
ILOAD c
INVOKEVIRTUAL xor
ILOAD d
INVOKEVIRTUAL xor
ISTORE f
LDC_W OBJREF
ILOAD i
BIPUSH 3
INVOKEVIRTUAL mul
BIPUSH 5
IADD
BIPUSH 15
IAND
ISTORE g
GOTO rotate
round_i:
// f = c ^ (b | (~d))
// = d ~ b | c ^
// g = (7 * i) % 16
LDC_W OBJREF
LDC_W OBJREF
ILOAD d
INVOKEVIRTUAL not
ILOAD b
IOR
ILOAD c
INVOKEVIRTUAL xor
ISTORE f
LDC_W OBJREF
ILOAD i
BIPUSH 7
INVOKEVIRTUAL mul
BIPUSH 15
IAND
ISTORE g
GOTO rotate
rotate:
POP // left over from the comparison tree
// temp = d
ILOAD d
ISTORE temp
// d = c
ILOAD c
ISTORE d
// c = b
ILOAD b
ISTORE c
// objref for soon call
LDC_W OBJREF
// this chunk is the first param to rotateleft
// namely a + f + k[i] + w[g]
ILOAD a
ILOAD f
// k[i]
ILOAD i
ILOAD round_sines
IALOAD
// w[g]
ILOAD g
ILOAD offset
IADD
ILOAD buf
IALOAD
IADD
IADD
IADD
// first param done
// r[i]
ILOAD i
ILOAD round_shifts
IALOAD
INVOKEVIRTUAL rotate_left
// b = b + rotate_left
ILOAD b
IADD
ISTORE b
// a = temp
ILOAD temp
ISTORE a
IINC i 1
ILOAD i
BIPUSH 64
IFEQ main_loop_end
GOTO main_loop
main_loop_end:
ILOAD h0
ILOAD a
IADD
ISTORE h0
ILOAD h1
ILOAD b
IADD
ISTORE h1
ILOAD h2
ILOAD c
IADD
ISTORE h2
ILOAD h3
ILOAD d
IADD
ISTORE h3
// Increment offset by 16 words
IINC offset 16
// Check if we are done
ILOAD offset
ILOAD len
IF_ICMPEQ offset_loop_end
GOTO offset_loop
offset_loop_end:
// #print "DONE\nhash="
LDC_W OBJREF
ILOAD h0
INVOKEVIRTUAL print_bytes
POP
LDC_W OBJREF
ILOAD h1
INVOKEVIRTUAL print_bytes
POP
LDC_W OBJREF
ILOAD h2
INVOKEVIRTUAL print_bytes
POP
LDC_W OBJREF
ILOAD h3
INVOKEVIRTUAL print_bytes
POP
#print "\n"
BIPUSH 0
IRETURN
.end-method
// }}}
// get_round_shifts {{{
.method get_round_shifts()
.var
shifts
idx
i
.end-var
BIPUSH 64
NEWARRAY
ISTORE shifts
BIPUSH 0
DUP
ISTORE idx
ISTORE i
loop1: // 7 12 17 22
BIPUSH 7
ILOAD idx
ILOAD shifts
IASTORE
IINC idx 1
BIPUSH 12
ILOAD idx
ILOAD shifts
IASTORE
IINC idx 1
BIPUSH 17
ILOAD idx
ILOAD shifts
IASTORE
IINC idx 1
BIPUSH 22
ILOAD idx
ILOAD shifts
IASTORE
IINC idx 1
IINC i 1
ILOAD i
BIPUSH 4
ISUB
IFLT loop1
BIPUSH 0
ISTORE i
loop2: // 5 9 14 20
BIPUSH 5
ILOAD idx
ILOAD shifts
IASTORE
IINC idx 1
BIPUSH 9
ILOAD idx
ILOAD shifts
IASTORE
IINC idx 1
BIPUSH 14
ILOAD idx
ILOAD shifts
IASTORE
IINC idx 1
BIPUSH 20
ILOAD idx
ILOAD shifts
IASTORE
IINC idx 1
IINC i 1
ILOAD i
BIPUSH 4
ISUB
IFLT loop2
BIPUSH 0
ISTORE i
loop3: // 4 11 16 23
BIPUSH 4
ILOAD idx
ILOAD shifts
IASTORE
IINC idx 1
BIPUSH 11
ILOAD idx
ILOAD shifts
IASTORE
IINC idx 1
BIPUSH 16
ILOAD idx
ILOAD shifts
IASTORE
IINC idx 1
BIPUSH 23
ILOAD idx
ILOAD shifts
IASTORE
IINC idx 1
IINC i 1
ILOAD i
BIPUSH 4
ISUB
IFLT loop3
BIPUSH 0
ISTORE i
loop4: // 6 10 15 21
BIPUSH 6
ILOAD idx
ILOAD shifts
IASTORE
IINC idx 1
BIPUSH 10
ILOAD idx
ILOAD shifts
IASTORE
IINC idx 1
BIPUSH 15
ILOAD idx
ILOAD shifts
IASTORE
IINC idx 1
BIPUSH 21
ILOAD idx
ILOAD shifts
IASTORE
IINC idx 1
IINC i 1
ILOAD i
BIPUSH 4
ISUB
IFLT loop4
// woo finally done
ILOAD shifts
IRETURN
.end-method
// }}}
// get_sines {{{
.method get_sines()
.var
sines
idx
.end-var
BIPUSH 64
NEWARRAY
ISTORE sines
BIPUSH 0
ISTORE idx
LDC_W SINES_0
ILOAD idx
ILOAD sines
IASTORE
IINC idx 1
LDC_W SINES_1
ILOAD idx
ILOAD sines
IASTORE
IINC idx 1
LDC_W SINES_2
ILOAD idx
ILOAD sines
IASTORE
IINC idx 1
LDC_W SINES_3
ILOAD idx
ILOAD sines
IASTORE
IINC idx 1
LDC_W SINES_4
ILOAD idx
ILOAD sines
IASTORE
IINC idx 1
LDC_W SINES_5
ILOAD idx
ILOAD sines
IASTORE
IINC idx 1
LDC_W SINES_6
ILOAD idx
ILOAD sines
IASTORE
IINC idx 1
LDC_W SINES_7
ILOAD idx
ILOAD sines
IASTORE
IINC idx 1
LDC_W SINES_8
ILOAD idx
ILOAD sines
IASTORE
IINC idx 1
LDC_W SINES_9
ILOAD idx
ILOAD sines
IASTORE
IINC idx 1
LDC_W SINES_10
ILOAD idx
ILOAD sines
IASTORE
IINC idx 1
LDC_W SINES_11
ILOAD idx
ILOAD sines
IASTORE
IINC idx 1
LDC_W SINES_12
ILOAD idx
ILOAD sines
IASTORE
IINC idx 1
LDC_W SINES_13
ILOAD idx
ILOAD sines
IASTORE
IINC idx 1
LDC_W SINES_14
ILOAD idx
ILOAD sines
IASTORE
IINC idx 1
LDC_W SINES_15
ILOAD idx
ILOAD sines
IASTORE
IINC idx 1
LDC_W SINES_16
ILOAD idx
ILOAD sines
IASTORE
IINC idx 1
LDC_W SINES_17
ILOAD idx
ILOAD sines
IASTORE
IINC idx 1
LDC_W SINES_18
ILOAD idx
ILOAD sines
IASTORE
IINC idx 1
LDC_W SINES_19
ILOAD idx
ILOAD sines
IASTORE
IINC idx 1
LDC_W SINES_20
ILOAD idx
ILOAD sines
IASTORE
IINC idx 1
LDC_W SINES_21
ILOAD idx
ILOAD sines
IASTORE
IINC idx 1
LDC_W SINES_22
ILOAD idx
ILOAD sines
IASTORE
IINC idx 1
LDC_W SINES_23
ILOAD idx
ILOAD sines
IASTORE
IINC idx 1
LDC_W SINES_24
ILOAD idx
ILOAD sines
IASTORE
IINC idx 1
LDC_W SINES_25
ILOAD idx
ILOAD sines
IASTORE
IINC idx 1
LDC_W SINES_26
ILOAD idx
ILOAD sines
IASTORE
IINC idx 1
LDC_W SINES_27
ILOAD idx
ILOAD sines
IASTORE
IINC idx 1
LDC_W SINES_28
ILOAD idx
ILOAD sines
IASTORE
IINC idx 1
LDC_W SINES_29
ILOAD idx
ILOAD sines
IASTORE
IINC idx 1
LDC_W SINES_30
ILOAD idx
ILOAD sines
IASTORE
IINC idx 1
LDC_W SINES_31
ILOAD idx
ILOAD sines
IASTORE
IINC idx 1
LDC_W SINES_32
ILOAD idx
ILOAD sines
IASTORE
IINC idx 1
LDC_W SINES_33
ILOAD idx
ILOAD sines
IASTORE
IINC idx 1
LDC_W SINES_34
ILOAD idx
ILOAD sines
IASTORE
IINC idx 1
LDC_W SINES_35
ILOAD idx
ILOAD sines
IASTORE
IINC idx 1
LDC_W SINES_36
ILOAD idx
ILOAD sines
IASTORE
IINC idx 1
LDC_W SINES_37
ILOAD idx
ILOAD sines
IASTORE
IINC idx 1
LDC_W SINES_38
ILOAD idx
ILOAD sines
IASTORE
IINC idx 1
LDC_W SINES_39
ILOAD idx
ILOAD sines
IASTORE
IINC idx 1
LDC_W SINES_40
ILOAD idx
ILOAD sines
IASTORE
IINC idx 1
LDC_W SINES_41
ILOAD idx
ILOAD sines
IASTORE
IINC idx 1
LDC_W SINES_42
ILOAD idx
ILOAD sines
IASTORE
IINC idx 1
LDC_W SINES_43
ILOAD idx
ILOAD sines
IASTORE
IINC idx 1
LDC_W SINES_44
ILOAD idx
ILOAD sines
IASTORE
IINC idx 1
LDC_W SINES_45
ILOAD idx
ILOAD sines
IASTORE
IINC idx 1
LDC_W SINES_46
ILOAD idx
ILOAD sines
IASTORE
IINC idx 1
LDC_W SINES_47
ILOAD idx
ILOAD sines
IASTORE
IINC idx 1
LDC_W SINES_48
ILOAD idx
ILOAD sines
IASTORE
IINC idx 1
LDC_W SINES_49
ILOAD idx
ILOAD sines
IASTORE
IINC idx 1
LDC_W SINES_50
ILOAD idx
ILOAD sines
IASTORE
IINC idx 1
LDC_W SINES_51
ILOAD idx
ILOAD sines
IASTORE
IINC idx 1
LDC_W SINES_52
ILOAD idx
ILOAD sines
IASTORE
IINC idx 1
LDC_W SINES_53
ILOAD idx
ILOAD sines
IASTORE
IINC idx 1
LDC_W SINES_54
ILOAD idx
ILOAD sines
IASTORE
IINC idx 1
LDC_W SINES_55
ILOAD idx
ILOAD sines
IASTORE
IINC idx 1
LDC_W SINES_56
ILOAD idx
ILOAD sines
IASTORE
IINC idx 1
LDC_W SINES_57
ILOAD idx
ILOAD sines
IASTORE
IINC idx 1
LDC_W SINES_58
ILOAD idx
ILOAD sines
IASTORE
IINC idx 1
LDC_W SINES_59
ILOAD idx
ILOAD sines
IASTORE
IINC idx 1
LDC_W SINES_60
ILOAD idx
ILOAD sines
IASTORE
IINC idx 1
LDC_W SINES_61
ILOAD idx
ILOAD sines
IASTORE
IINC idx 1
LDC_W SINES_62
ILOAD idx
ILOAD sines
IASTORE
IINC idx 1
LDC_W SINES_63
ILOAD idx
ILOAD sines
IASTORE
IINC idx 1
ILOAD sines
IRETURN
.end-method
// }}}
// print_buf {{{
.method print_buf(buf, len)
.var
i
.end-var
ILOAD len
IFLT done
BIPUSH 0
ISTORE i
loop:
ILOAD i
ILOAD len
IF_ICMPEQ done
LDC_W OBJREF
ILOAD i
ILOAD buf
IALOAD
INVOKEVIRTUAL print_bytes
POP
#print " "
IINC i 1
GOTO loop
done:
#print "\n"
BIPUSH 0
IRETURN
.end-method
// }}}
// print_bytes {{{
.method print_bytes(int)
// byte 1
ILOAD int
DUP
LDC_W MASK_8
IAND
LDC_W OBJREF
SWAP
INVOKEVIRTUAL print_byte
POP
// byte 2
LDC_W OBJREF
SWAP
BIPUSH 8
INVOKEVIRTUAL shr
DUP
LDC_W MASK_8
IAND
LDC_W OBJREF
SWAP
INVOKEVIRTUAL print_byte
POP
// byte 3
LDC_W OBJREF
SWAP
BIPUSH 8
INVOKEVIRTUAL shr
DUP
LDC_W MASK_8
IAND
LDC_W OBJREF
SWAP
INVOKEVIRTUAL print_byte
POP
// byte 4
LDC_W OBJREF
SWAP
BIPUSH 8
INVOKEVIRTUAL shr
LDC_W OBJREF
SWAP
INVOKEVIRTUAL print_byte
POP
BIPUSH 0
IRETURN
.end-method
// }}}
// print_byte {{{
.method print_byte(byte)
// upper
LDC_W OBJREF
ILOAD byte
BIPUSH 4
INVOKEVIRTUAL shr
BIPUSH 0xF
IAND
DUP
BIPUSH 10
ISUB
IFLT normal1
// hex offset to push it into A
BIPUSH 39
IADD
normal1:
BIPUSH 48
IADD
OUT
// lower
ILOAD byte
BIPUSH 0xF
IAND
DUP
BIPUSH 10
ISUB
IFLT normal2
// hex
BIPUSH 39
IADD
normal2:
BIPUSH 48
IADD
OUT
BIPUSH 0
IRETURN
.end-method
// }}}
// not {{{
.method not(x)
LDC_W OBJREF
ILOAD x
LDC_W NOT_PATTERN
INVOKEVIRTUAL xor
IRETURN
.end-method
// }}}
// xor {{{
.method xor(x, y)
ILOAD x
LDC_W XOR_PATTERN_1
IAND
ILOAD y
LDC_W XOR_PATTERN_1
IAND
IADD
LDC_W XOR_PATTERN_1
IAND
ILOAD x
LDC_W XOR_PATTERN_2
IAND
ILOAD y
LDC_W XOR_PATTERN_2
IAND
IADD
LDC_W XOR_PATTERN_2
IAND
IOR
IRETURN
.end-method
/// }}}
// mul {{{
.method mul(x, y)
// For the love of god, ensure *y* is the small number
.var
sum
.end-var
BIPUSH 0
ISTORE sum
loop_mul:
ILOAD y
IFEQ done
ILOAD sum
ILOAD x
IADD
ISTORE sum
IINC y -1
GOTO loop_mul
done:
ILOAD sum
IRETURN
.end-method
// }}}
// div {{{
.method div(a, b)
// Stolen from mandelbread, with love
.var
signed
res
k
bshift
.end-var
// store the signed state
BIPUSH 0
ISTORE signed
// get absolute of a and b
ha:
ILOAD a
IFLT negate_a
hb:
ILOAD b
IFLT negate_b
handled:
BIPUSH 0
ISTORE res
// edge case if a < b, we're done
ILOAD a
ILOAD b
ISUB
IFLT apply_sign
// edge case if b == 0, we error
ILOAD b
IFEQ division_by_zero
BIPUSH 1
ISTORE k
ILOAD b
ISTORE bshift
// build a stack of kn, kn * b, kn-1, kn-1 * b, ..., k0 (1), k0 * b (b)
build_stack:
ILOAD a
ILOAD bshift
ISUB
IFLT stack_unwind
// push bshift to stack and bshift += bshift
ILOAD bshift
DUP
DUP
IADD
ISTORE bshift
// push k to stack and k += k
ILOAD k
DUP
DUP
IADD
ISTORE k
GOTO build_stack
stack_unwind:
ISTORE k // stores k from (k * b) in size
// a - (k * b)
ILOAD a
SWAP
ISUB
// duplicate a - (k * b) on stack
DUP
// if (a - (k * b) < 0) cant_substract
IFLT cant_substract
substract:
// store a = a - k * b
ISTORE a
// calculate res
ILOAD res
ILOAD k
IADD
ISTORE res
ILOAD k
BIPUSH 1
IF_ICMPEQ apply_sign
GOTO stack_unwind
cant_substract:
// pop a - (k * b) from the stack
POP
ILOAD k
BIPUSH 1
IF_ICMPEQ apply_sign
GOTO stack_unwind
apply_sign:
ILOAD signed
IFEQ ret_res
BIPUSH 0
ILOAD res
ISUB
IRETURN
ret_res:
ILOAD res
IRETURN
negate_a:
BIPUSH 0
ILOAD a
ISUB
ISTORE a
IINC signed 1
GOTO hb
negate_b:
BIPUSH 0
ILOAD b
ISUB
ISTORE b
IINC signed 1
GOTO handled
division_by_zero:
BIPUSH 100
OUT
BIPUSH 105
OUT
BIPUSH 118
OUT
BIPUSH 32
OUT
BIPUSH 98
OUT
BIPUSH 121
OUT
BIPUSH 32
OUT
BIPUSH 48
OUT
BIPUSH 10
OUT
ERR
.end-method
// }}}
// shl {{{
.method shl(x, y)
// multiply by 2, y times :)
// dynamic version. If you know ahead of time, use the SHL_x constants and mul
loop:
ILOAD y
IFEQ done
LDC_W OBJREF
ILOAD x
BIPUSH 2
INVOKEVIRTUAL mul
ISTORE x
IINC y -1
GOTO loop
done:
ILOAD x
IRETURN
.end-method
// }}}
// shr {{{
.method shr(x, y)
// t'is horrible, but it works!
.var
unsigned
result
.end-var
// def shr(x, y)
// unsigned = x & 0x7F_FF_FF_FF
// result = unsigned / (2 << (y-1))
//
// if x & 0x80_00_00_00 != 0
// result |= (1 << (31 - y))
// end
//
// result
//end
LDC_W OBJREF
// all bits but the sign
ILOAD x
LDC_W MASK_31
IAND
LDC_W OBJREF
BIPUSH 1
ILOAD y
INVOKEVIRTUAL shl
INVOKEVIRTUAL div
// check if sign is set
ILOAD x
LDC_W MASK_SIGN
IAND
IFEQ no_sign
has_sign:
LDC_W OBJREF
BIPUSH 1
BIPUSH 31
ILOAD y
ISUB
INVOKEVIRTUAL shl
IOR
no_sign:
IRETURN
.end-method
// }}}
// rotate_left {{{
.method rotate_left(x, c)
.var
left
right
rightright
.end-var
// (((x) << (c)) | ((x) >> (32 - (c))))
// (x << c) | (x >> (32 - c))
// x c << x 32 c - >> |
LDC_W OBJREF
ILOAD x
ILOAD c
INVOKEVIRTUAL shl
ISTORE left
BIPUSH 32
ILOAD c
ISUB
ISTORE rightright
LDC_W OBJREF
ILOAD x
ILOAD rightright
INVOKEVIRTUAL shr
ISTORE right
ILOAD left
ILOAD right
IOR
IRETURN
.end-method
// }}}