diff --git a/Cargo.toml b/Cargo.toml index ad0dc8b..3eec088 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,8 +15,9 @@ bonus = ["bonus:network", "bonus:heap"] "bonus:network" = [] "bonus:heap" = [] -extra = ["extra:sleep"] +extra = ["extra:sleep", "extra:arithmetic"] "extra:sleep" = [] +"extra:arithmetic" = [] debug = ["debug:instr", "debug:frame", "debug:gc"] "debug:instr" = [] diff --git a/files/custom/md5.ijvm b/files/custom/md5.ijvm new file mode 100644 index 0000000..9240ef8 Binary files /dev/null and b/files/custom/md5.ijvm differ diff --git a/files/custom/md5.jas b/files/custom/md5.jas new file mode 100644 index 0000000..01cd4de --- /dev/null +++ b/files/custom/md5.jas @@ -0,0 +1,1602 @@ +// 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 +// }}} diff --git a/ijvm.config b/ijvm.config index f8abc45..c370182 100644 --- a/ijvm.config +++ b/ijvm.config @@ -1,27 +1,38 @@ +0x00 NOP + 0x10 BIPUSH byte +0x13 LDC_W constant +0x15 ILOAD var + +0x36 ISTORE var + +0x57 POP 0x59 DUP -0xA7 GOTO label +0x5F SWAP + 0x60 IADD +0x64 ISUB + +0x70 SHL +0x71 SHR +0x72 IMUL +0x73 IDIV + 0x7E IAND + +0x84 IINC var byte + 0x99 IFEQ label 0x9B IFLT label 0x9F IF_ICMPEQ label -0x84 IINC var byte -0x15 ILOAD var -0xB6 INVOKEVIRTUAL method -0xB0 IOR + +0xA7 GOTO label 0xAC IRETURN -0x36 ISTORE var -0x64 ISUB -0x13 LDC_W constant -0x00 NOP -0x57 POP -0x5F SWAP + +0xB0 IOR +0xB6 INVOKEVIRTUAL method + 0xC4 WIDE -0xFF HALT -0xFE ERR -0xFD OUT -0xFC IN 0xD1 NEWARRAY 0xD2 IALOAD @@ -34,4 +45,7 @@ 0xE4 NETOUT 0xE5 NETCLOSE -0xF0 SLP byte +0xFC IN +0xFD OUT +0xFE ERR +0xFF HALT diff --git a/src/heap.rs b/src/heap.rs index 77cba42..351b1e8 100644 --- a/src/heap.rs +++ b/src/heap.rs @@ -48,10 +48,8 @@ impl Heaps { } pub fn gc(&mut self) { - println!("GC PRE : {} weaks", self.len()); for i in 0..self.len() { - println!("\theap: {} = {:?}", i, self.get(i)); + self.get(i); } - println!("GC POST: {} weaks", self.len()); } } diff --git a/src/netstack.rs b/src/netstack.rs index be2e581..8429ae4 100644 --- a/src/netstack.rs +++ b/src/netstack.rs @@ -32,10 +32,10 @@ impl NetStack { } pub fn connect(&mut self, host: u32, port: u16) -> Result<()> { - let h1 = (host & (0xFF << 24)) >> 24 as u8; - let h2 = (host & (0xFF << 16)) >> 16 as u8; - let h3 = (host & (0xFF << 8)) >> 8 as u8; - let h4 = (host & 0xFF) >> 0 as u8; + let h1 = ((host >> 24) & 0xFF) as u8; + let h2 = ((host >> 16) & 0xFF) as u8; + let h3 = ((host >> 8) & 0xFF) as u8; + let h4 = ((host >> 0) & 0xFF) as u8; let addr: String = format!("{}.{}.{}.{}:{}", h1, h2, h3, h4, port); if let Ok(stream) = TcpStream::connect(addr) { diff --git a/src/ops.rs b/src/ops.rs index 0f36606..c1b2392 100644 --- a/src/ops.rs +++ b/src/ops.rs @@ -31,33 +31,49 @@ lazy_static! { let mut m = vec![Operation::Invalid; 0xFF + 1]; m[0x00] = Operation::Op("NOP", nop, vec![]); + m[0x10] = Operation::Op("BIPUSH", bipush, vec![Args::Byte]); m[0x13] = Operation::Op("LDC_W", ldc_w, vec![Args::Constant]); m[0x15] = Operation::Op("ILOAD", iload, vec![Args::Var]); + m[0x36] = Operation::Op("ISTORE", istore, vec![Args::Var]); + m[0x57] = Operation::Op("POP", pop, vec![]); m[0x59] = Operation::Op("DUP", dup, vec![]); m[0x5F] = Operation::Op("SWAP", swap, vec![]); + m[0x60] = Operation::Op("IADD", iadd, vec![]); m[0x64] = Operation::Op("ISUB", isub, vec![]); + + #[cfg(feature = "extra:arithmetic")] + { + m[0x70] = Operation::Op("SHL", shl, vec![]); + m[0x71] = Operation::Op("SHR", shr, vec![]); + m[0x72] = Operation::Op("IMUL", imul, vec![]); + m[0x73] = Operation::Op("IDIV", idiv, vec![]); + } m[0x7E] = Operation::Op("IAND", iand, vec![]); - m[0xB0] = Operation::Op("IOR", ior, vec![]); + m[0x84] = Operation::Op("IINC", iinc, vec![Args::Var, Args::Byte]); + m[0x99] = Operation::Op("IFEQ", ifeq, vec![Args::Label]); m[0x9b] = Operation::Op("IFLT", iflt, vec![Args::Label]); m[0x9F] = Operation::Op("IF_ICMPEQ", if_icmpeq, vec![Args::Label]); + m[0xA7] = Operation::Op("GOTO", goto, vec![Args::Label]); m[0xAC] = Operation::Op("IRETURN", ireturn, vec![]); - m[0xB6] = Operation::Op("INVOKEVIRTUAL", invokevirtual, vec![Args::Constant]); - m[0xC4] = Operation::Op("WIDE", wide, vec![]); - m[0xFC] = Operation::Op("IN", _in, vec![]); - m[0xFD] = Operation::Op("OUT", out, vec![]); - m[0xFE] = Operation::Op("ERR", err, vec![]); - m[0xFF] = Operation::Op("HALT", halt, vec![]); - #[cfg(feature = "extra:sleep")] + m[0xB0] = Operation::Op("IOR", ior, vec![]); + m[0xB6] = Operation::Op("INVOKEVIRTUAL", invokevirtual, vec![Args::Constant]); + + m[0xC4] = Operation::Op("WIDE", wide, vec![]); + + #[cfg(feature = "bonus:heap")] { - m[0xF0] = Operation::Op("SLP", slp, vec![Args::Byte]); + m[0xD1] = Operation::Op("NEWARRAY", newarray, vec![]); + m[0xD2] = Operation::Op("IALOAD", iaload, vec![]); + m[0xD3] = Operation::Op("IASTORE", iastore, vec![]); + m[0xD4] = Operation::Op("GC", gc, vec![]); } #[cfg(feature = "bonus:network")] @@ -69,13 +85,14 @@ lazy_static! { m[0xE5] = Operation::Op("NETCLOSE", netclose, vec![]); } - #[cfg(feature = "bonus:heap")] + #[cfg(feature = "extra:sleep")] { - m[0xD1] = Operation::Op("NEWARRAY", newarray, vec![]); - m[0xD2] = Operation::Op("IALOAD", iaload, vec![]); - m[0xD3] = Operation::Op("IASTORE", iastore, vec![]); - m[0xD4] = Operation::Op("GC", gc, vec![]); + m[0xF0] = Operation::Op("SLP", slp, vec![Args::Byte]); } + m[0xFC] = Operation::Op("IN", _in, vec![]); + m[0xFD] = Operation::Op("OUT", out, vec![]); + m[0xFE] = Operation::Op("ERR", err, vec![]); + m[0xFF] = Operation::Op("HALT", halt, vec![]); m }; @@ -293,18 +310,34 @@ fn slp(machine: &mut Machine) -> Result<()> { #[cfg(feature = "bonus:network")] fn netbind(machine: &mut Machine) -> Result<()> { let port: i32 = machine.cur_stack().pop()?.try_into()?; - machine.net.bind(port as u16) + + let result = match machine.net.bind(port as u16) { + Ok(_) => 1, + Err(_) => 0, + }; + machine.cur_stack().push(Value::Int(result)); + Ok(()) } #[cfg(feature = "bonus:network")] fn netconnect(machine: &mut Machine) -> Result<()> { let port: i32 = machine.cur_stack().pop()?.try_into()?; let host: i32 = machine.cur_stack().pop()?.try_into()?; - machine.net.connect(host as u32, port as u16) + let result = match machine.net.connect(host as u32, port as u16) { + Ok(_) => 1, + Err(_) => 0, + }; + machine.cur_stack().push(Value::Int(result)); + Ok(()) } #[cfg(feature = "bonus:network")] fn netin(machine: &mut Machine) -> Result<()> { + let netref: i32 = machine.cur_stack().pop()?.try_into()?; + if netref != 1 { + return Err("Invalid netref to netin"); + } + let byte = i32::from(machine.net.read_byte()?); machine.cur_stack().push(Value::Int(byte)); Ok(()) @@ -312,12 +345,21 @@ fn netin(machine: &mut Machine) -> Result<()> { #[cfg(feature = "bonus:network")] fn netout(machine: &mut Machine) -> Result<()> { + let netref: i32 = machine.cur_stack().pop()?.try_into()?; + if netref != 1 { + return Err("Invalid netref to netout"); + } + let val: i32 = machine.cur_stack().pop()?.try_into()?; machine.net.write_byte(val as u8) } #[cfg(feature = "bonus:network")] fn netclose(machine: &mut Machine) -> Result<()> { + let netref: i32 = machine.cur_stack().pop()?.try_into()?; + if netref != 1 { + return Err("Invalid netref to netclose"); + } machine.net.close() } @@ -367,3 +409,40 @@ fn gc(machine: &mut Machine) -> Result<()> { machine.heap.gc(); Ok(()) } + +#[cfg(feature = "extra:arithmetic")] +fn shl(machine: &mut Machine) -> Result<()> { + let shift: i32 = machine.cur_stack().pop()?.try_into()?; + let value: i32 = machine.cur_stack().pop()?.try_into()?; + + machine.cur_stack().push(Value::Int(value << shift)); + Ok(()) +} + +#[cfg(feature = "extra:arithmetic")] +fn shr(machine: &mut Machine) -> Result<()> { + let shift: i32 = machine.cur_stack().pop()?.try_into()?; + let value: i32 = machine.cur_stack().pop()?.try_into()?; + + let result: u32 = (value as u32) >> (shift as u32); + machine.cur_stack().push(Value::Int(result as i32)); + Ok(()) +} + +#[cfg(feature = "extra:arithmetic")] +fn imul(machine: &mut Machine) -> Result<()> { + let a: i32 = machine.cur_stack().pop()?.try_into()?; + let b: i32 = machine.cur_stack().pop()?.try_into()?; + + machine.cur_stack().push(Value::Int(a * b)); + Ok(()) +} + +#[cfg(feature = "extra:arithmetic")] +fn idiv(machine: &mut Machine) -> Result<()> { + let divisor: i32 = machine.cur_stack().pop()?.try_into()?; + let value: i32 = machine.cur_stack().pop()?.try_into()?; + + machine.cur_stack().push(Value::Int(value / divisor)); + Ok(()) +}