From e60c55a7468143eaf47946fa9518d74a71b27b3b Mon Sep 17 00:00:00 2001 From: Klaus Treichel Date: Tue, 21 Sep 2010 19:42:01 +0200 Subject: [PATCH] Add support for applying an opcode to one or two constant values. --- ChangeLog | 17 + config/jit-opcodes.ops | 930 +++++++++++++++++++++++++++------------- jit/Makefile.am | 1 + jit/jit-internal.h | 97 +++++ jit/jit-opcode-apply.c | 887 ++++++++++++++++++++++++++++++++++++++ tools/gen-ops-parser.y | 546 ++++++++++++++++++++++- tools/gen-ops-scanner.l | 35 ++ 7 files changed, 2193 insertions(+), 320 deletions(-) create mode 100644 jit/jit-opcode-apply.c diff --git a/ChangeLog b/ChangeLog index e051067..45765e2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,20 @@ +2010-09-21 Klaus Treichel + + * config/jit-opcodes.ops: Add definitions for the opcode's + intrinsics. + + * jit/Makefile.am: Add jit-opcode-apply.c to the sources. + + * jit/jit-internal.h (enum _jit_intrinsic_signature): Declare the + various intrinsic signatures. + (struct _jit_intrinsic_info): Declare structure to hold the intrinsic + information for an opcode. + + * jit/jit-opcode-apply.c: Add support for constant folding. + + * tools/gen-ops-parset.y, tools/gen-ops-scanner.l: Add support for + generating the opcode intrinsic table. + 2010-09-12 Klaus Treichel * config/jit-opcodes.ops: Remove the *eq_inv and *ne_inv float diff --git a/config/jit-opcodes.ops b/config/jit-opcodes.ops index 527b374..d54e628 100644 --- a/config/jit-opcodes.ops +++ b/config/jit-opcodes.ops @@ -68,362 +68,674 @@ extern "C" { %] +%option gen_intrinsic_table = yes +%option intrinsic_table_decl = "_jit_intrinsic_info_t const _jit_intrinsics[JIT_OP_NUM_OPCODES]" + opcodes(JIT_OP_, "jit_opcode_info_t const jit_opcodes[JIT_OP_NUM_OPCODES]") { op_def("nop") { } /* * Conversion opcodes */ - op_def("trunc_sbyte") { op_values(int, int) } - op_def("trunc_ubyte") { op_values(int, int) } - op_def("trunc_short") { op_values(int, int) } - op_def("trunc_ushort") { op_values(int, int) } - op_def("trunc_int") { op_values(int, int) } - op_def("trunc_uint") { op_values(int, int) } + op_def("trunc_sbyte") { op_values(int, int), + op_intrinsic(conv) } + op_def("trunc_ubyte") { op_values(int, int), + op_intrinsic(conv) } + op_def("trunc_short") { op_values(int, int), + op_intrinsic(conv) } + op_def("trunc_ushort") { op_values(int, int), + op_intrinsic(conv) } + op_def("trunc_int") { op_values(int, int), + op_intrinsic(conv) } + op_def("trunc_uint") { op_values(int, int), + op_intrinsic(conv) } op_def("check_sbyte") { op_values(int, int) } op_def("check_ubyte") { op_values(int, int) } op_def("check_short") { op_values(int, int) } op_def("check_ushort") { op_values(int, int) } op_def("check_int") { op_values(int, int) } op_def("check_uint") { op_values(int, int) } - op_def("low_word") { op_values(int, long) } - op_def("expand_int") { op_values(long, int) } - op_def("expand_uint") { op_values(long, int) } + op_def("low_word") { op_values(int, long), + op_intrinsic(conv) } + op_def("expand_int") { op_values(long, int), + op_intrinsic(conv) } + op_def("expand_uint") { op_values(long, int), + op_intrinsic(conv) } op_def("check_low_word") { op_values(int, long) } op_def("check_signed_low_word") { op_values(int, long) } op_def("check_long") { op_values(long, long) } op_def("check_ulong") { op_values(long, long) } - op_def("float32_to_int") { op_values(int, float32) } - op_def("float32_to_uint") { op_values(int, float32) } - op_def("float32_to_long") { op_values(long, float32) } - op_def("float32_to_ulong") { op_values(long, float32) } + op_def("float32_to_int") { op_values(int, float32), + op_intrinsic(conv) } + op_def("float32_to_uint") { op_values(int, float32), + op_intrinsic(conv) } + op_def("float32_to_long") { op_values(long, float32), + op_intrinsic(conv) } + op_def("float32_to_ulong") { op_values(long, float32), + op_intrinsic(conv) } op_def("check_float32_to_int") { op_values(int, float32) } op_def("check_float32_to_uint") { op_values(int, float32) } op_def("check_float32_to_long") { op_values(long, float32) } op_def("check_float32_to_ulong") { op_values(long, float32) } - op_def("int_to_float32") { op_values(float32, int) } - op_def("uint_to_float32") { op_values(float32, int) } - op_def("long_to_float32") { op_values(float32, long) } - op_def("ulong_to_float32") { op_values(float32, long) } - op_def("float32_to_float64") { op_values(float64, float32) } - op_def("float64_to_int") { op_values(int, float64) } - op_def("float64_to_uint") { op_values(int, float64) } - op_def("float64_to_long") { op_values(long, float64) } - op_def("float64_to_ulong") { op_values(long, float64) } + op_def("int_to_float32") { op_values(float32, int), + op_intrinsic(conv) } + op_def("uint_to_float32") { op_values(float32, int), + op_intrinsic(conv) } + op_def("long_to_float32") { op_values(float32, long), + op_intrinsic(conv) } + op_def("ulong_to_float32") { op_values(float32, long), + op_intrinsic(conv) } + op_def("float32_to_float64") { op_values(float64, float32), + op_intrinsic(conv) } + op_def("float64_to_int") { op_values(int, float64), + op_intrinsic(conv) } + op_def("float64_to_uint") { op_values(int, float64), + op_intrinsic(conv) } + op_def("float64_to_long") { op_values(long, float64), + op_intrinsic(conv) } + op_def("float64_to_ulong") { op_values(long, float64), + op_intrinsic(conv) } op_def("check_float64_to_int") { op_values(int, float64) } op_def("check_float64_to_uint") { op_values(int, float64) } op_def("check_float64_to_long") { op_values(long, float64) } op_def("check_float64_to_ulong") { op_values(long, float64) } - op_def("int_to_float64") { op_values(float64, int) } - op_def("uint_to_float64") { op_values(float64, int) } - op_def("long_to_float64") { op_values(float64, long) } - op_def("ulong_to_float64") { op_values(float64, long) } - op_def("float64_to_float32") { op_values(float32, float64) } - op_def("nfloat_to_int") { op_values(int, nfloat) } - op_def("nfloat_to_uint") { op_values(int, nfloat) } - op_def("nfloat_to_long") { op_values(long, nfloat) } - op_def("nfloat_to_ulong") { op_values(long, nfloat) } + op_def("int_to_float64") { op_values(float64, int), + op_intrinsic(conv) } + op_def("uint_to_float64") { op_values(float64, int), + op_intrinsic(conv) } + op_def("long_to_float64") { op_values(float64, long), + op_intrinsic(conv) } + op_def("ulong_to_float64") { op_values(float64, long), + op_intrinsic(conv) } + op_def("float64_to_float32") { op_values(float32, float64), + op_intrinsic(conv) } + op_def("nfloat_to_int") { op_values(int, nfloat), + op_intrinsic(conv) } + op_def("nfloat_to_uint") { op_values(int, nfloat), + op_intrinsic(conv) } + op_def("nfloat_to_long") { op_values(long, nfloat), + op_intrinsic(conv) } + op_def("nfloat_to_ulong") { op_values(long, nfloat), + op_intrinsic(conv) } op_def("check_nfloat_to_int") { op_values(int, nfloat) } op_def("check_nfloat_to_uint") { op_values(int, nfloat) } op_def("check_nfloat_to_long") { op_values(long, nfloat) } op_def("check_nfloat_to_ulong") { op_values(long, nfloat) } - op_def("int_to_nfloat") { op_values(nfloat, int) } - op_def("uint_to_nfloat") { op_values(nfloat, int) } - op_def("long_to_nfloat") { op_values(nfloat, long) } - op_def("ulong_to_nfloat") { op_values(nfloat, long) } - op_def("nfloat_to_float32") { op_values(float32, nfloat) } - op_def("nfloat_to_float64") { op_values(float64, nfloat) } - op_def("float32_to_nfloat") { op_values(nfloat, float32) } - op_def("float64_to_nfloat") { op_values(nfloat, float64) } + op_def("int_to_nfloat") { op_values(nfloat, int), + op_intrinsic(conv) } + op_def("uint_to_nfloat") { op_values(nfloat, int), + op_intrinsic(conv) } + op_def("long_to_nfloat") { op_values(nfloat, long), + op_intrinsic(conv) } + op_def("ulong_to_nfloat") { op_values(nfloat, long), + op_intrinsic(conv) } + op_def("nfloat_to_float32") { op_values(float32, nfloat), + op_intrinsic(conv) } + op_def("nfloat_to_float64") { op_values(float64, nfloat), + op_intrinsic(conv) } + op_def("float32_to_nfloat") { op_values(nfloat, float32), + op_intrinsic(conv) } + op_def("float64_to_nfloat") { op_values(nfloat, float64), + op_intrinsic(conv) } /* * Arithmetic opcodes. */ - op_def("iadd", +) { op_values(int, int, int) } - op_def("iadd_ovf") { op_values(int, int, int) } - op_def("iadd_ovf_un") { op_values(int, int, int) } - op_def("isub", -) { op_values(int, int, int) } - op_def("isub_ovf") { op_values(int, int, int) } - op_def("isub_ovf_un") { op_values(int, int, int) } - op_def("imul", *) { op_values(int, int, int) } - op_def("imul_ovf") { op_values(int, int, int) } - op_def("imul_ovf_un") { op_values(int, int, int) } - op_def("idiv", /) { op_values(int, int, int) } - op_def("idiv_un") { op_values(int, int, int) } - op_def("irem", %) { op_values(int, int, int) } - op_def("irem_un") { op_values(int, int, int) } - op_def("ineg", neg) { op_values(int, int) } - op_def("ladd", +) { op_values(long, long, long) } - op_def("ladd_ovf") { op_values(long, long, long) } - op_def("ladd_ovf_un") { op_values(long, long, long) } - op_def("lsub", -) { op_values(long, long, long) } - op_def("lsub_ovf") { op_values(long, long, long) } - op_def("lsub_ovf_un") { op_values(long, long, long) } - op_def("lmul", *) { op_values(long, long, long) } - op_def("lmul_ovf") { op_values(long, long, long) } - op_def("lmul_ovf_un") { op_values(long, long, long) } - op_def("ldiv", /) { op_values(long, long, long) } - op_def("ldiv_un") { op_values(long, long, long) } - op_def("lrem", %) { op_values(long, long, long) } - op_def("lrem_un") { op_values(long, long, long) } - op_def("lneg", neg) { op_values(long, long) } - op_def("fadd", +) { op_values(float32, float32, float32) } - op_def("fsub", -) { op_values( float32, float32, float32) } - op_def("fmul", *) { op_values(float32, float32, float32) } - op_def("fdiv", /) { op_values(float32, float32, float32) } - op_def("frem", %) { op_values(float32, float32, float32) } - op_def("frem_ieee") { op_values(float32, float32, float32) } - op_def("fneg", neg) { op_values(float32, float32) } - op_def("dadd", +) { op_values(float64, float64, float64) } - op_def("dsub", -) { op_values(float64, float64, float64) } - op_def("dmul", *) { op_values(float64, float64, float64) } - op_def("ddiv", /) { op_values(float64, float64, float64) } - op_def("drem", %) { op_values(float64, float64, float64) } - op_def("drem_ieee") { op_values(float64, float64, float64) } - op_def("dneg", neg) { op_values(float64, float64) } - op_def("nfadd", +) { op_values(nfloat, nfloat, nfloat) } - op_def("nfsub", -) { op_values(nfloat, nfloat, nfloat) } - op_def("nfmul", *) { op_values(nfloat, nfloat, nfloat) } - op_def("nfdiv", /) { op_values(nfloat, nfloat, nfloat) } - op_def("nfrem", %) { op_values(nfloat, nfloat, nfloat) } - op_def("nfrem_ieee") { op_values(nfloat, nfloat, nfloat) } - op_def("nfneg", neg) { op_values(nfloat, nfloat) } + op_def("iadd", +) { op_values(int, int, int), + op_intrinsic(jit_int_add, i_ii) } + op_def("iadd_ovf") { op_values(int, int, int), + op_intrinsic(jit_int_add_ovf, i_piii) } + op_def("iadd_ovf_un") { op_values(int, int, int), + op_intrinsic(jit_uint_add_ovf, i_pIII) } + op_def("isub", -) { op_values(int, int, int), + op_intrinsic(jit_int_sub, i_ii) } + op_def("isub_ovf") { op_values(int, int, int), + op_intrinsic(jit_int_sub_ovf, i_piii) } + op_def("isub_ovf_un") { op_values(int, int, int), + op_intrinsic(jit_uint_sub_ovf, i_pIII) } + op_def("imul", *) { op_values(int, int, int), + op_intrinsic(jit_int_mul, i_ii) } + op_def("imul_ovf") { op_values(int, int, int), + op_intrinsic(jit_int_mul_ovf, i_piii) } + op_def("imul_ovf_un") { op_values(int, int, int), + op_intrinsic(jit_uint_mul_ovf, i_pIII) } + op_def("idiv", /) { op_values(int, int, int), + op_intrinsic(jit_int_div, i_piii) } + op_def("idiv_un") { op_values(int, int, int), + op_intrinsic(jit_uint_div, i_pIII) } + op_def("irem", %) { op_values(int, int, int), + op_intrinsic(jit_int_rem, i_piii) } + op_def("irem_un") { op_values(int, int, int), + op_intrinsic(jit_uint_rem, i_pIII) } + op_def("ineg", neg) { op_values(int, int), + op_intrinsic(jit_int_neg, i_i) } + op_def("ladd", +) { op_values(long, long, long), + op_intrinsic(jit_long_add, l_ll) } + op_def("ladd_ovf") { op_values(long, long, long), + op_intrinsic(jit_long_add_ovf, i_plll) } + op_def("ladd_ovf_un") { op_values(long, long, long), + op_intrinsic(jit_ulong_add_ovf, i_pLLL) } + op_def("lsub", -) { op_values(long, long, long), + op_intrinsic(jit_long_sub, l_ll) } + op_def("lsub_ovf") { op_values(long, long, long), + op_intrinsic(jit_long_sub_ovf, i_plll) } + op_def("lsub_ovf_un") { op_values(long, long, long), + op_intrinsic(jit_ulong_sub_ovf, i_pLLL) } + op_def("lmul", *) { op_values(long, long, long), + op_intrinsic(jit_long_mul, l_ll) } + op_def("lmul_ovf") { op_values(long, long, long), + op_intrinsic(jit_long_mul_ovf, i_plll) } + op_def("lmul_ovf_un") { op_values(long, long, long), + op_intrinsic(jit_ulong_mul_ovf, i_pLLL) } + op_def("ldiv", /) { op_values(long, long, long), + op_intrinsic(jit_long_div, i_plll) } + op_def("ldiv_un") { op_values(long, long, long), + op_intrinsic(jit_ulong_div, i_pLLL) } + op_def("lrem", %) { op_values(long, long, long), + op_intrinsic(jit_long_rem, i_plll) } + op_def("lrem_un") { op_values(long, long, long), + op_intrinsic(jit_ulong_rem, i_pLLL) } + op_def("lneg", neg) { op_values(long, long), + op_intrinsic(jit_long_neg, l_l) } + op_def("fadd", +) { op_values(float32, float32, float32), + op_intrinsic(jit_float32_add, f_ff) } + op_def("fsub", -) { op_values( float32, float32, float32), + op_intrinsic(jit_float32_sub, f_ff) } + op_def("fmul", *) { op_values(float32, float32, float32), + op_intrinsic(jit_float32_mul, f_ff) } + op_def("fdiv", /) { op_values(float32, float32, float32), + op_intrinsic(jit_float32_div, f_ff) } + op_def("frem", %) { op_values(float32, float32, float32), + op_intrinsic(jit_float32_rem, f_ff) } + op_def("frem_ieee") { op_values(float32, float32, float32), + op_intrinsic(jit_float32_ieee_rem, f_ff) } + op_def("fneg", neg) { op_values(float32, float32), + op_intrinsic(jit_float32_neg, f_f) } + op_def("dadd", +) { op_values(float64, float64, float64), + op_intrinsic(jit_float64_add, d_dd) } + op_def("dsub", -) { op_values(float64, float64, float64), + op_intrinsic(jit_float64_sub, d_dd) } + op_def("dmul", *) { op_values(float64, float64, float64), + op_intrinsic(jit_float64_mul, d_dd) } + op_def("ddiv", /) { op_values(float64, float64, float64), + op_intrinsic(jit_float64_div, d_dd) } + op_def("drem", %) { op_values(float64, float64, float64), + op_intrinsic(jit_float64_rem, d_dd) } + op_def("drem_ieee") { op_values(float64, float64, float64), + op_intrinsic(jit_float64_ieee_rem, d_dd) } + op_def("dneg", neg) { op_values(float64, float64), + op_intrinsic(jit_float64_neg, d_d) } + op_def("nfadd", +) { op_values(nfloat, nfloat, nfloat), + op_intrinsic(jit_nfloat_add, D_DD) } + op_def("nfsub", -) { op_values(nfloat, nfloat, nfloat), + op_intrinsic(jit_nfloat_sub, D_DD) } + op_def("nfmul", *) { op_values(nfloat, nfloat, nfloat), + op_intrinsic(jit_nfloat_mul, D_DD) } + op_def("nfdiv", /) { op_values(nfloat, nfloat, nfloat), + op_intrinsic(jit_nfloat_div, D_DD) } + op_def("nfrem", %) { op_values(nfloat, nfloat, nfloat), + op_intrinsic(jit_nfloat_rem, D_DD) } + op_def("nfrem_ieee") { op_values(nfloat, nfloat, nfloat), + op_intrinsic(jit_nfloat_ieee_rem, D_DD) } + op_def("nfneg", neg) { op_values(nfloat, nfloat), + op_intrinsic(jit_nfloat_neg, D_D) } /* * Bitwise opcodes. */ - op_def("iand", &) { op_values(int, int, int) } - op_def("ior", |) { op_values(int, int, int) } - op_def("ixor", ^) { op_values(int, int, int) } - op_def("inot", ~) { op_values(int, int) } - op_def("ishl", <<) { op_values(int, int, int) } - op_def("ishr", >>) { op_values(int, int, int) } - op_def("ishr_un", shr_un) { op_values(int, int, int) } - op_def("land", &) { op_values(long, long, long) } - op_def("lor", |) { op_values(long, long, long) } - op_def("lxor", ^) { op_values(long, long, long) } - op_def("lnot", ~) { op_values(long, long) } - op_def("lshl", <<) { op_values(long, long, int) } - op_def("lshr", >>) { op_values(long, long, int) } - op_def("lshr_un", shr_un) { op_values(long, long, int) } + op_def("iand", &) { op_values(int, int, int), + op_intrinsic(jit_int_and, i_ii) } + op_def("ior", |) { op_values(int, int, int), + op_intrinsic(jit_int_or, i_ii) } + op_def("ixor", ^) { op_values(int, int, int), + op_intrinsic(jit_int_xor, i_ii) } + op_def("inot", ~) { op_values(int, int), + op_intrinsic(jit_int_not, i_i) } + op_def("ishl", <<) { op_values(int, int, int), + op_intrinsic(jit_int_shl, i_iI) } + op_def("ishr", >>) { op_values(int, int, int), + op_intrinsic(jit_int_shr, i_iI) } + op_def("ishr_un", shr_un) { op_values(int, int, int), + op_intrinsic(jit_uint_shr, i_iI) } + op_def("land", &) { op_values(long, long, long), + op_intrinsic(jit_long_and, l_ll) } + op_def("lor", |) { op_values(long, long, long), + op_intrinsic(jit_long_or, l_ll) } + op_def("lxor", ^) { op_values(long, long, long), + op_intrinsic(jit_long_xor, l_ll) } + op_def("lnot", ~) { op_values(long, long), + op_intrinsic(jit_long_not, l_l) } + op_def("lshl", <<) { op_values(long, long, int), + op_intrinsic(jit_long_shl, l_lI) } + op_def("lshr", >>) { op_values(long, long, int), + op_intrinsic(jit_long_shr, l_lI) } + op_def("lshr_un", shr_un) { op_values(long, long, int), + op_intrinsic(jit_ulong_shr, L_LI) } /* * Branch opcodes. */ op_def("br") { op_type(branch) } - op_def("br_ifalse") { op_type(branch), op_values(empty, int) } - op_def("br_itrue") { op_type(branch), op_values(empty, int) } - op_def("br_ieq", ==) { op_type(branch), op_values(empty, int, int) } - op_def("br_ine", !=) { op_type(branch), op_values(empty, int, int) } - op_def("br_ilt", <) { op_type(branch), op_values(empty, int, int) } - op_def("br_ilt_un") { op_type(branch), op_values(empty, int, int) } - op_def("br_ile", <=) { op_type(branch), op_values(empty, int, int) } - op_def("br_ile_un") { op_type(branch), op_values(empty, int, int) } - op_def("br_igt", >) { op_type(branch), op_values(empty, int, int) } - op_def("br_igt_un") { op_type(branch), op_values(empty, int, int) } - op_def("br_ige", >=) { op_type(branch), op_values(empty, int, int) } - op_def("br_ige_un") { op_type(branch), op_values(empty, int, int) } - op_def("br_lfalse") { op_type(branch), op_values(empty, long) } - op_def("br_ltrue") { op_type(branch), op_values(empty, long) } - op_def("br_leq", ==) { op_type(branch), op_values(empty, long, long) } - op_def("br_lne", !=) { op_type(branch), op_values(empty, long, long) } - op_def("br_llt", <) { op_type(branch), op_values(empty, long, long) } - op_def("br_llt_un") { op_type(branch), op_values(empty, long, long) } - op_def("br_lle", <=) { op_type(branch), op_values(empty, long, long) } - op_def("br_lle_un") { op_type(branch), op_values(empty, long, long) } - op_def("br_lgt", >) { op_type(branch), op_values(empty, long, long) } - op_def("br_lgt_un") { op_type(branch), op_values(empty, long, long) } - op_def("br_lge", >=) { op_type(branch), op_values(empty, long, long) } - op_def("br_lge_un") { op_type(branch), op_values(empty, long, long) } - op_def("br_feq", ==) { op_type(branch), op_values(empty, float32, float32) } - op_def("br_fne", !=) { op_type(branch), op_values(empty, float32, float32) } - op_def("br_flt", <) { op_type(branch), op_values(empty, float32, float32) } - op_def("br_fle", <=) { op_type(branch), op_values(empty, float32, float32) } - op_def("br_fgt", >) { op_type(branch), op_values(empty, float32, float32) } - op_def("br_fge", >=) { op_type(branch), op_values(empty, float32, float32) } - op_def("br_flt_inv") { op_type(branch), op_values(empty, float32, float32) } - op_def("br_fle_inv") { op_type(branch), op_values(empty, float32, float32) } - op_def("br_fgt_inv") { op_type(branch), op_values(empty, float32, float32) } - op_def("br_fge_inv") { op_type(branch), op_values(empty, float32, float32) } - op_def("br_deq", ==) { op_type(branch), op_values(empty, float64, float64) } - op_def("br_dne", !=) { op_type(branch), op_values(empty, float64, float64) } - op_def("br_dlt", <) { op_type(branch), op_values(empty, float64, float64) } - op_def("br_dle", <=) { op_type(branch), op_values(empty, float64, float64) } - op_def("br_dgt", >) { op_type(branch), op_values(empty, float64, float64) } - op_def("br_dge", >=) { op_type(branch), op_values(empty, float64, float64) } - op_def("br_dlt_inv") { op_type(branch), op_values(empty, float64, float64) } - op_def("br_dle_inv") { op_type(branch), op_values(empty, float64, float64) } - op_def("br_dgt_inv") { op_type(branch), op_values(empty, float64, float64) } - op_def("br_dge_inv") { op_type(branch), op_values(empty, float64, float64) } - op_def("br_nfeq", ==) { op_type(branch), op_values(empty, nfloat, nfloat) } - op_def("br_nfne", !=) { op_type(branch), op_values(empty, nfloat, nfloat) } - op_def("br_nflt", <) { op_type(branch), op_values(empty, nfloat, nfloat) } - op_def("br_nfle", <=) { op_type(branch), op_values(empty, nfloat, nfloat) } - op_def("br_nfgt", >) { op_type(branch), op_values(empty, nfloat, nfloat) } - op_def("br_nfge", >=) { op_type(branch), op_values(empty, nfloat, nfloat) } - op_def("br_nflt_inv") { op_type(branch), op_values(empty, nfloat, nfloat) } - op_def("br_nfle_inv") { op_type(branch), op_values(empty, nfloat, nfloat) } - op_def("br_nfgt_inv") { op_type(branch), op_values(empty, nfloat, nfloat) } - op_def("br_nfge_inv") { op_type(branch), op_values(empty, nfloat, nfloat) } + op_def("br_ifalse") { op_type(branch), op_values(empty, int), + op_intrinsic("_JIT_INTRINSIC_FLAG_BRANCH_UNARY | _JIT_INTRINSIC_FLAG_IFALSE") } + op_def("br_itrue") { op_type(branch), op_values(empty, int), + op_intrinsic("_JIT_INTRINSIC_FLAG_BRANCH_UNARY | _JIT_INTRINSIC_FLAG_ITRUE") } + op_def("br_ieq", ==) { op_type(branch), op_values(empty, int, int), + op_intrinsic("_JIT_INTRINSIC_FLAG_BRANCH | JIT_OP_IEQ") } + op_def("br_ine", !=) { op_type(branch), op_values(empty, int, int), + op_intrinsic("_JIT_INTRINSIC_FLAG_BRANCH | JIT_OP_INE") } + op_def("br_ilt", <) { op_type(branch), op_values(empty, int, int), + op_intrinsic("_JIT_INTRINSIC_FLAG_BRANCH | JIT_OP_ILT") } + op_def("br_ilt_un") { op_type(branch), op_values(empty, int, int), + op_intrinsic("_JIT_INTRINSIC_FLAG_BRANCH | JIT_OP_ILT_UN") } + op_def("br_ile", <=) { op_type(branch), op_values(empty, int, int), + op_intrinsic("_JIT_INTRINSIC_FLAG_BRANCH | JIT_OP_ILE") } + op_def("br_ile_un") { op_type(branch), op_values(empty, int, int), + op_intrinsic("_JIT_INTRINSIC_FLAG_BRANCH | JIT_OP_ILE_UN") } + op_def("br_igt", >) { op_type(branch), op_values(empty, int, int), + op_intrinsic("_JIT_INTRINSIC_FLAG_BRANCH | JIT_OP_IGT") } + op_def("br_igt_un") { op_type(branch), op_values(empty, int, int), + op_intrinsic("_JIT_INTRINSIC_FLAG_BRANCH | JIT_OP_IGT_UN") } + op_def("br_ige", >=) { op_type(branch), op_values(empty, int, int), + op_intrinsic("_JIT_INTRINSIC_FLAG_BRANCH | JIT_OP_IGE") } + op_def("br_ige_un") { op_type(branch), op_values(empty, int, int), + op_intrinsic("_JIT_INTRINSIC_FLAG_BRANCH | JIT_OP_IGE_UN") } + op_def("br_lfalse") { op_type(branch), op_values(empty, long), + op_intrinsic("_JIT_INTRINSIC_FLAG_BRANCH_UNARY | _JIT_INTRINSIC_FLAG_LFALSE") } + op_def("br_ltrue") { op_type(branch), op_values(empty, long), + op_intrinsic("_JIT_INTRINSIC_FLAG_BRANCH_UNARY | _JIT_INTRINSIC_FLAG_LTRUE") } + op_def("br_leq", ==) { op_type(branch), op_values(empty, long, long), + op_intrinsic("_JIT_INTRINSIC_FLAG_BRANCH | JIT_OP_LEQ") } + op_def("br_lne", !=) { op_type(branch), op_values(empty, long, long), + op_intrinsic("_JIT_INTRINSIC_FLAG_BRANCH | JIT_OP_LNE") } + op_def("br_llt", <) { op_type(branch), op_values(empty, long, long), + op_intrinsic("_JIT_INTRINSIC_FLAG_BRANCH | JIT_OP_LLT") } + op_def("br_llt_un") { op_type(branch), op_values(empty, long, long), + op_intrinsic("_JIT_INTRINSIC_FLAG_BRANCH | JIT_OP_LLT_UN") } + op_def("br_lle", <=) { op_type(branch), op_values(empty, long, long), + op_intrinsic("_JIT_INTRINSIC_FLAG_BRANCH | JIT_OP_LLE") } + op_def("br_lle_un") { op_type(branch), op_values(empty, long, long), + op_intrinsic("_JIT_INTRINSIC_FLAG_BRANCH | JIT_OP_LLE_UN") } + op_def("br_lgt", >) { op_type(branch), op_values(empty, long, long), + op_intrinsic("_JIT_INTRINSIC_FLAG_BRANCH | JIT_OP_LGT") } + op_def("br_lgt_un") { op_type(branch), op_values(empty, long, long), + op_intrinsic("_JIT_INTRINSIC_FLAG_BRANCH | JIT_OP_LGT_UN") } + op_def("br_lge", >=) { op_type(branch), op_values(empty, long, long), + op_intrinsic("_JIT_INTRINSIC_FLAG_BRANCH | JIT_OP_LGE") } + op_def("br_lge_un") { op_type(branch), op_values(empty, long, long), + op_intrinsic("_JIT_INTRINSIC_FLAG_BRANCH | JIT_OP_LGE_UN") } + op_def("br_feq", ==) { op_type(branch), op_values(empty, float32, float32), + op_intrinsic("_JIT_INTRINSIC_FLAG_BRANCH | JIT_OP_FEQ") } + op_def("br_fne", !=) { op_type(branch), op_values(empty, float32, float32), + op_intrinsic("_JIT_INTRINSIC_FLAG_BRANCH | JIT_OP_FNE") } + op_def("br_flt", <) { op_type(branch), op_values(empty, float32, float32), + op_intrinsic("_JIT_INTRINSIC_FLAG_BRANCH | JIT_OP_FLT") } + op_def("br_fle", <=) { op_type(branch), op_values(empty, float32, float32), + op_intrinsic("_JIT_INTRINSIC_FLAG_BRANCH | JIT_OP_FLE") } + op_def("br_fgt", >) { op_type(branch), op_values(empty, float32, float32), + op_intrinsic("_JIT_INTRINSIC_FLAG_BRANCH | JIT_OP_FGT") } + op_def("br_fge", >=) { op_type(branch), op_values(empty, float32, float32), + op_intrinsic("_JIT_INTRINSIC_FLAG_BRANCH | JIT_OP_FGE") } + op_def("br_flt_inv") { op_type(branch), op_values(empty, float32, float32), + op_intrinsic("_JIT_INTRINSIC_FLAG_BRANCH | JIT_OP_FLT_INV") } + op_def("br_fle_inv") { op_type(branch), op_values(empty, float32, float32), + op_intrinsic("_JIT_INTRINSIC_FLAG_BRANCH | JIT_OP_FLE_INV") } + op_def("br_fgt_inv") { op_type(branch), op_values(empty, float32, float32), + op_intrinsic("_JIT_INTRINSIC_FLAG_BRANCH | JIT_OP_FGT_INV") } + op_def("br_fge_inv") { op_type(branch), op_values(empty, float32, float32), + op_intrinsic("_JIT_INTRINSIC_FLAG_BRANCH | JIT_OP_FGE_INV") } + op_def("br_deq", ==) { op_type(branch), op_values(empty, float64, float64), + op_intrinsic("_JIT_INTRINSIC_FLAG_BRANCH | JIT_OP_DEQ") } + op_def("br_dne", !=) { op_type(branch), op_values(empty, float64, float64), + op_intrinsic("_JIT_INTRINSIC_FLAG_BRANCH | JIT_OP_DNE") } + op_def("br_dlt", <) { op_type(branch), op_values(empty, float64, float64), + op_intrinsic("_JIT_INTRINSIC_FLAG_BRANCH | JIT_OP_DLT") } + op_def("br_dle", <=) { op_type(branch), op_values(empty, float64, float64), + op_intrinsic("_JIT_INTRINSIC_FLAG_BRANCH | JIT_OP_DLE") } + op_def("br_dgt", >) { op_type(branch), op_values(empty, float64, float64), + op_intrinsic("_JIT_INTRINSIC_FLAG_BRANCH | JIT_OP_DGT") } + op_def("br_dge", >=) { op_type(branch), op_values(empty, float64, float64), + op_intrinsic("_JIT_INTRINSIC_FLAG_BRANCH | JIT_OP_DGE") } + op_def("br_dlt_inv") { op_type(branch), op_values(empty, float64, float64), + op_intrinsic("_JIT_INTRINSIC_FLAG_BRANCH | JIT_OP_DLT_INV") } + op_def("br_dle_inv") { op_type(branch), op_values(empty, float64, float64), + op_intrinsic("_JIT_INTRINSIC_FLAG_BRANCH | JIT_OP_DLE_INV") } + op_def("br_dgt_inv") { op_type(branch), op_values(empty, float64, float64), + op_intrinsic("_JIT_INTRINSIC_FLAG_BRANCH | JIT_OP_DGT_INV") } + op_def("br_dge_inv") { op_type(branch), op_values(empty, float64, float64), + op_intrinsic("_JIT_INTRINSIC_FLAG_BRANCH | JIT_OP_DGE_INV") } + op_def("br_nfeq", ==) { op_type(branch), op_values(empty, nfloat, nfloat), + op_intrinsic("_JIT_INTRINSIC_FLAG_BRANCH | JIT_OP_NFEQ") } + op_def("br_nfne", !=) { op_type(branch), op_values(empty, nfloat, nfloat), + op_intrinsic("_JIT_INTRINSIC_FLAG_BRANCH | JIT_OP_NFNE") } + op_def("br_nflt", <) { op_type(branch), op_values(empty, nfloat, nfloat), + op_intrinsic("_JIT_INTRINSIC_FLAG_BRANCH | JIT_OP_NFLT") } + op_def("br_nfle", <=) { op_type(branch), op_values(empty, nfloat, nfloat), + op_intrinsic("_JIT_INTRINSIC_FLAG_BRANCH | JIT_OP_NFLE") } + op_def("br_nfgt", >) { op_type(branch), op_values(empty, nfloat, nfloat), + op_intrinsic("_JIT_INTRINSIC_FLAG_BRANCH | JIT_OP_NFGT") } + op_def("br_nfge", >=) { op_type(branch), op_values(empty, nfloat, nfloat), + op_intrinsic("_JIT_INTRINSIC_FLAG_BRANCH | JIT_OP_NFGE") } + op_def("br_nflt_inv") { op_type(branch), op_values(empty, nfloat, nfloat), + op_intrinsic("_JIT_INTRINSIC_FLAG_BRANCH | JIT_OP_NFLT_INV") } + op_def("br_nfle_inv") { op_type(branch), op_values(empty, nfloat, nfloat), + op_intrinsic("_JIT_INTRINSIC_FLAG_BRANCH | JIT_OP_NFLE_INV") } + op_def("br_nfgt_inv") { op_type(branch), op_values(empty, nfloat, nfloat), + op_intrinsic("_JIT_INTRINSIC_FLAG_BRANCH | JIT_OP_NFGT_INV") } + op_def("br_nfge_inv") { op_type(branch), op_values(empty, nfloat, nfloat), + op_intrinsic("_JIT_INTRINSIC_FLAG_BRANCH | JIT_OP_NFGE_INV") } /* * Comparison opcodes. */ - op_def("icmp") { op_values(int, int, int) } - op_def("icmp_un") { op_values(int, int, int) } - op_def("lcmp") { op_values(int, long, long) } - op_def("lcmp_un") { op_values(int, long, long) } - op_def("fcmpl") { op_values(int, float32, float32) } - op_def("fcmpg") { op_values(int, float32, float32) } - op_def("dcmpl") { op_values(int, float64, float64) } - op_def("dcmpg") { op_values(int, float64, float64) } - op_def("nfcmpl") { op_values(int, nfloat, nfloat) } - op_def("nfcmpg") { op_values(int, nfloat, nfloat) } - op_def("ieq", ==) { op_values(int, int, int) } - op_def("ine", !=) { op_values(int, int, int) } - op_def("ilt", <) { op_values(int, int, int) } - op_def("ilt_un") { op_values(int, int, int) } - op_def("ile", <=) { op_values(int, int, int) } - op_def("ile_un") { op_values(int, int, int) } - op_def("igt", >) { op_values(int, int, int) } - op_def("igt_un") { op_values(int, int, int) } - op_def("ige", >=) { op_values(int, int, int) } - op_def("ige_un") { op_values(int, int, int) } - op_def("leq", ==) { op_values(int, long, long) } - op_def("lne", !=) { op_values(int, long, long) } - op_def("llt", <) { op_values(int, long, long) } - op_def("llt_un") { op_values(int, long, long) } - op_def("lle", <=) { op_values(int, long, long) } - op_def("lle_un") { op_values(int, long, long) } - op_def("lgt", >) { op_values(int, long, long) } - op_def("lgt_un") { op_values(int, long, long) } - op_def("lge", >=) { op_values(int, long, long) } - op_def("lge_un") { op_values(int, long, long) } - op_def("feq", ==) { op_values(int, float32, float32) } - op_def("fne", !=) { op_values(int, float32, float32) } - op_def("flt", <) { op_values(int, float32, float32) } - op_def("fle", <=) { op_values(int, float32, float32) } - op_def("fgt", >) { op_values(int, float32, float32) } - op_def("fge", >=) { op_values(int, float32, float32) } - op_def("flt_inv") { op_values(int, float32, float32) } - op_def("fle_inv") { op_values(int, float32, float32) } - op_def("fgt_inv") { op_values(int, float32, float32) } - op_def("fge_inv") { op_values(int, float32, float32) } - op_def("deq", ==) { op_values(int, float64, float64) } - op_def("dne", !=) { op_values(int, float64, float64) } - op_def("dlt", <) { op_values(int, float64, float64) } - op_def("dle", <=) { op_values(int, float64, float64) } - op_def("dgt", >) { op_values(int, float64, float64) } - op_def("dge", >=) { op_values(int, float64, float64) } - op_def("dlt_inv") { op_values(int, float64, float64) } - op_def("dle_inv") { op_values(int, float64, float64) } - op_def("dgt_inv") { op_values(int, float64, float64) } - op_def("dge_inv") { op_values(int, float64, float64) } - op_def("nfeq", ==) { op_values(int, nfloat, nfloat) } - op_def("nfne", !=) { op_values(int, nfloat, nfloat) } - op_def("nflt", <) { op_values(int, nfloat, nfloat) } - op_def("nfle", <=) { op_values(int, nfloat, nfloat) } - op_def("nfgt", >) { op_values(int, nfloat, nfloat) } - op_def("nfge", >=) { op_values(int, nfloat, nfloat) } - op_def("nflt_inv") { op_values(int, nfloat, nfloat) } - op_def("nfle_inv") { op_values(int, nfloat, nfloat) } - op_def("nfgt_inv") { op_values(int, nfloat, nfloat) } - op_def("nfge_inv") { op_values(int, nfloat, nfloat) } - op_def("is_fnan") { op_values(int, float32) } - op_def("is_finf") { op_values(int, float32) } - op_def("is_ffinite") { op_values(int, float32) } - op_def("is_dnan") { op_values(int, float64) } - op_def("is_dinf") { op_values(int, float64) } - op_def("is_dfinite") { op_values(int, float64) } - op_def("is_nfnan") { op_values(int, nfloat) } - op_def("is_nfinf") { op_values(int, nfloat) } - op_def("is_nffinite") { op_values(int, nfloat) } + op_def("icmp") { op_values(int, int, int), + op_intrinsic(jit_int_cmp, i_ii) } + op_def("icmp_un") { op_values(int, int, int), + op_intrinsic(jit_uint_cmp, i_II) } + op_def("lcmp") { op_values(int, long, long), + op_intrinsic(jit_long_cmp, i_ll) } + op_def("lcmp_un") { op_values(int, long, long), + op_intrinsic(jit_ulong_cmp, i_LL) } + op_def("fcmpl") { op_values(int, float32, float32), + op_intrinsic(jit_float32_cmpl, i_ff) } + op_def("fcmpg") { op_values(int, float32, float32), + op_intrinsic(jit_float32_cmpg, i_ff) } + op_def("dcmpl") { op_values(int, float64, float64), + op_intrinsic(jit_float64_cmpl, i_dd) } + op_def("dcmpg") { op_values(int, float64, float64), + op_intrinsic(jit_float64_cmpg, i_dd) } + op_def("nfcmpl") { op_values(int, nfloat, nfloat), + op_intrinsic(jit_nfloat_cmpl, i_DD) } + op_def("nfcmpg") { op_values(int, nfloat, nfloat), + op_intrinsic(jit_nfloat_cmpg, i_DD) } + op_def("ieq", ==) { op_values(int, int, int), + op_intrinsic(jit_int_eq, i_ii) } + op_def("ine", !=) { op_values(int, int, int), + op_intrinsic(jit_int_ne, i_ii) } + op_def("ilt", <) { op_values(int, int, int), + op_intrinsic(jit_int_lt, i_ii) } + op_def("ilt_un") { op_values(int, int, int), + op_intrinsic(jit_uint_lt, i_II) } + op_def("ile", <=) { op_values(int, int, int), + op_intrinsic(jit_int_le, i_ii) } + op_def("ile_un") { op_values(int, int, int), + op_intrinsic(jit_uint_le, i_II) } + op_def("igt", >) { op_values(int, int, int), + op_intrinsic(jit_int_gt, i_ii) } + op_def("igt_un") { op_values(int, int, int), + op_intrinsic(jit_uint_gt, i_II) } + op_def("ige", >=) { op_values(int, int, int), + op_intrinsic(jit_int_ge, i_ii) } + op_def("ige_un") { op_values(int, int, int), + op_intrinsic(jit_uint_ge, i_II) } + op_def("leq", ==) { op_values(int, long, long), + op_intrinsic(jit_long_eq, i_ll) } + op_def("lne", !=) { op_values(int, long, long), + op_intrinsic(jit_long_ne, i_ll) } + op_def("llt", <) { op_values(int, long, long), + op_intrinsic(jit_long_lt, i_ll) } + op_def("llt_un") { op_values(int, long, long), + op_intrinsic(jit_ulong_lt, i_LL) } + op_def("lle", <=) { op_values(int, long, long), + op_intrinsic(jit_long_le, i_ll) } + op_def("lle_un") { op_values(int, long, long), + op_intrinsic(jit_ulong_le, i_LL) } + op_def("lgt", >) { op_values(int, long, long), + op_intrinsic(jit_long_gt, i_ll) } + op_def("lgt_un") { op_values(int, long, long), + op_intrinsic(jit_ulong_gt, i_LL) } + op_def("lge", >=) { op_values(int, long, long), + op_intrinsic(jit_long_ge, i_ll) } + op_def("lge_un") { op_values(int, long, long), + op_intrinsic(jit_ulong_ge, i_LL) } + op_def("feq", ==) { op_values(int, float32, float32), + op_intrinsic(jit_float32_eq, i_ff) } + op_def("fne", !=) { op_values(int, float32, float32), + op_intrinsic(jit_float32_ne, i_ff) } + op_def("flt", <) { op_values(int, float32, float32), + op_intrinsic(jit_float32_lt, i_ff) } + op_def("fle", <=) { op_values(int, float32, float32), + op_intrinsic(jit_float32_le, i_ff) } + op_def("fgt", >) { op_values(int, float32, float32), + op_intrinsic(jit_float32_gt, i_ff) } + op_def("fge", >=) { op_values(int, float32, float32), + op_intrinsic(jit_float32_ge, i_ff) } + op_def("flt_inv") { op_values(int, float32, float32), + op_intrinsic("_JIT_INTRINSIC_FLAG_NOT | JIT_OP_FGE") } + op_def("fle_inv") { op_values(int, float32, float32), + op_intrinsic("_JIT_INTRINSIC_FLAG_NOT | JIT_OP_FGT") } + op_def("fgt_inv") { op_values(int, float32, float32), + op_intrinsic("_JIT_INTRINSIC_FLAG_NOT | JIT_OP_FLE") } + op_def("fge_inv") { op_values(int, float32, float32), + op_intrinsic("_JIT_INTRINSIC_FLAG_NOT | JIT_OP_FLT") } + op_def("deq", ==) { op_values(int, float64, float64), + op_intrinsic(jit_float64_eq, i_dd) } + op_def("dne", !=) { op_values(int, float64, float64), + op_intrinsic(jit_float64_ne, i_dd) } + op_def("dlt", <) { op_values(int, float64, float64), + op_intrinsic(jit_float64_lt, i_dd) } + op_def("dle", <=) { op_values(int, float64, float64), + op_intrinsic(jit_float64_le, i_dd) } + op_def("dgt", >) { op_values(int, float64, float64), + op_intrinsic(jit_float64_gt, i_dd) } + op_def("dge", >=) { op_values(int, float64, float64), + op_intrinsic(jit_float64_ge, i_dd) } + op_def("dlt_inv") { op_values(int, float64, float64), + op_intrinsic("_JIT_INTRINSIC_FLAG_NOT | JIT_OP_DGE") } + op_def("dle_inv") { op_values(int, float64, float64), + op_intrinsic("_JIT_INTRINSIC_FLAG_NOT | JIT_OP_DGT") } + op_def("dgt_inv") { op_values(int, float64, float64), + op_intrinsic("_JIT_INTRINSIC_FLAG_NOT | JIT_OP_DLE") } + op_def("dge_inv") { op_values(int, float64, float64), + op_intrinsic("_JIT_INTRINSIC_FLAG_NOT | JIT_OP_DLT") } + op_def("nfeq", ==) { op_values(int, nfloat, nfloat), + op_intrinsic(jit_nfloat_eq, i_DD) } + op_def("nfne", !=) { op_values(int, nfloat, nfloat), + op_intrinsic(jit_nfloat_ne, i_DD) } + op_def("nflt", <) { op_values(int, nfloat, nfloat), + op_intrinsic(jit_nfloat_lt, i_DD) } + op_def("nfle", <=) { op_values(int, nfloat, nfloat), + op_intrinsic(jit_nfloat_le, i_DD) } + op_def("nfgt", >) { op_values(int, nfloat, nfloat), + op_intrinsic(jit_nfloat_gt, i_DD) } + op_def("nfge", >=) { op_values(int, nfloat, nfloat), + op_intrinsic(jit_nfloat_ge, i_DD) } + op_def("nflt_inv") { op_values(int, nfloat, nfloat), + op_intrinsic("_JIT_INTRINSIC_FLAG_NOT | JIT_OP_NFGE") } + op_def("nfle_inv") { op_values(int, nfloat, nfloat), + op_intrinsic("_JIT_INTRINSIC_FLAG_NOT | JIT_OP_NFGT") } + op_def("nfgt_inv") { op_values(int, nfloat, nfloat), + op_intrinsic("_JIT_INTRINSIC_FLAG_NOT | JIT_OP_NFLE") } + op_def("nfge_inv") { op_values(int, nfloat, nfloat), + op_intrinsic("_JIT_INTRINSIC_FLAG_NOT | JIT_OP_NFLT") } + op_def("is_fnan") { op_values(int, float32), + op_intrinsic(jit_float32_is_nan, i_f) } + op_def("is_finf") { op_values(int, float32), + op_intrinsic(jit_float32_is_inf, i_f) } + op_def("is_ffinite") { op_values(int, float32), + op_intrinsic(jit_float32_is_finite, i_f) } + op_def("is_dnan") { op_values(int, float64), + op_intrinsic(jit_float64_is_nan, i_d) } + op_def("is_dinf") { op_values(int, float64), + op_intrinsic(jit_float64_is_inf, i_d) } + op_def("is_dfinite") { op_values(int, float64), + op_intrinsic(jit_float64_is_finite, i_d) } + op_def("is_nfnan") { op_values(int, nfloat), + op_intrinsic(jit_nfloat_is_nan, i_D) } + op_def("is_nfinf") { op_values(int, nfloat), + op_intrinsic(jit_nfloat_is_inf, i_D) } + op_def("is_nffinite") { op_values(int, nfloat), + op_intrinsic(jit_nfloat_is_finite, i_D) } /* * Mathematical functions. */ - op_def("facos") { op_values(float32, float32) } - op_def("fasin") { op_values(float32, float32) } - op_def("fatan") { op_values(float32, float32) } - op_def("fatan2") { op_values(float32, float32, float32) } - op_def("fceil") { op_values(float32, float32) } - op_def("fcos") { op_values(float32, float32) } - op_def("fcosh") { op_values(float32, float32) } - op_def("fexp") { op_values(float32, float32) } - op_def("ffloor") { op_values(float32, float32) } - op_def("flog") { op_values(float32, float32) } - op_def("flog10") { op_values(float32, float32) } - op_def("fpow") { op_values(float32, float32, float32) } - op_def("frint") { op_values(float32, float32) } - op_def("fround") { op_values(float32, float32) } - op_def("fsin") { op_values(float32, float32) } - op_def("fsinh") { op_values(float32, float32) } - op_def("fsqrt") { op_values(float32, float32) } - op_def("ftan") { op_values(float32, float32) } - op_def("ftanh") { op_values(float32, float32) } - op_def("ftrunc") { op_values(float32, float32) } - op_def("dacos") { op_values(float64, float64) } - op_def("dasin") { op_values(float64, float64) } - op_def("datan") { op_values(float64, float64) } - op_def("datan2") { op_values(float64, float64, float64)} - op_def("dceil") { op_values(float64, float64) } - op_def("dcos") { op_values(float64, float64) } - op_def("dcosh") { op_values(float64, float64) } - op_def("dexp") { op_values(float64, float64) } - op_def("dfloor") { op_values(float64, float64) } - op_def("dlog") { op_values(float64, float64) } - op_def("dlog10") { op_values(float64, float64) } - op_def("dpow") { op_values(float64, float64, float64) } - op_def("drint") { op_values(float64, float64) } - op_def("dround") { op_values(float64, float64) } - op_def("dsin") { op_values(float64, float64) } - op_def("dsinh") { op_values(float64, float64) } - op_def("dsqrt") { op_values(float64, float64) } - op_def("dtan") { op_values(float64, float64) } - op_def("dtanh") { op_values(float64, float64) } - op_def("dtrunc") { op_values(float64, float64) } - op_def("nfacos") { op_values(nfloat, nfloat) } - op_def("nfasin") { op_values(nfloat, nfloat) } - op_def("nfatan") { op_values(nfloat, nfloat) } - op_def("nfatan2") { op_values(nfloat, nfloat, nfloat) } - op_def("nfceil") { op_values(nfloat, nfloat) } - op_def("nfcos") { op_values(nfloat, nfloat) } - op_def("nfcosh") { op_values(nfloat, nfloat) } - op_def("nfexp") { op_values(nfloat, nfloat) } - op_def("nffloor") { op_values(nfloat, nfloat) } - op_def("nflog") { op_values(nfloat, nfloat) } - op_def("nflog10") { op_values(nfloat, nfloat) } - op_def("nfpow") { op_values(nfloat, nfloat, nfloat) } - op_def("nfrint") { op_values(nfloat, nfloat) } - op_def("nfround") { op_values(nfloat, nfloat) } - op_def("nfsin") { op_values(nfloat, nfloat) } - op_def("nfsinh") { op_values(nfloat, nfloat) } - op_def("nfsqrt") { op_values(nfloat, nfloat) } - op_def("nftan") { op_values(nfloat, nfloat) } - op_def("nftanh") { op_values(nfloat, nfloat) } - op_def("nftrunc") { op_values(nfloat, nfloat) } + op_def("facos") { op_values(float32, float32), + op_intrinsic(jit_float32_acos, f_f) } + op_def("fasin") { op_values(float32, float32), + op_intrinsic(jit_float32_asin, f_f) } + op_def("fatan") { op_values(float32, float32), + op_intrinsic(jit_float32_atan, f_f) } + op_def("fatan2") { op_values(float32, float32, float32), + op_intrinsic(jit_float32_atan2, f_ff) } + op_def("fceil") { op_values(float32, float32), + op_intrinsic(jit_float32_ceil, f_f) } + op_def("fcos") { op_values(float32, float32), + op_intrinsic(jit_float32_cos, f_f) } + op_def("fcosh") { op_values(float32, float32), + op_intrinsic(jit_float32_cosh, f_f) } + op_def("fexp") { op_values(float32, float32), + op_intrinsic(jit_float32_exp, f_f) } + op_def("ffloor") { op_values(float32, float32), + op_intrinsic(jit_float32_floor, f_f) } + op_def("flog") { op_values(float32, float32), + op_intrinsic(jit_float32_log, f_f) } + op_def("flog10") { op_values(float32, float32), + op_intrinsic(jit_float32_log10, f_f) } + op_def("fpow") { op_values(float32, float32, float32), + op_intrinsic(jit_float32_pow, f_ff) } + op_def("frint") { op_values(float32, float32), + op_intrinsic(jit_float32_rint, f_f) } + op_def("fround") { op_values(float32, float32), + op_intrinsic(jit_float32_round, f_f) } + op_def("fsin") { op_values(float32, float32), + op_intrinsic(jit_float32_sin, f_f) } + op_def("fsinh") { op_values(float32, float32), + op_intrinsic(jit_float32_sinh, f_f) } + op_def("fsqrt") { op_values(float32, float32), + op_intrinsic(jit_float32_sqrt, f_f) } + op_def("ftan") { op_values(float32, float32), + op_intrinsic(jit_float32_tan, f_f) } + op_def("ftanh") { op_values(float32, float32), + op_intrinsic(jit_float32_tanh, f_f) } + op_def("ftrunc") { op_values(float32, float32), + op_intrinsic(jit_float32_trunc, f_f) } + op_def("dacos") { op_values(float64, float64), + op_intrinsic(jit_float64_acos, d_d) } + op_def("dasin") { op_values(float64, float64), + op_intrinsic(jit_float64_asin, d_d) } + op_def("datan") { op_values(float64, float64), + op_intrinsic(jit_float64_atan, d_d) } + op_def("datan2") { op_values(float64, float64, float64), + op_intrinsic(jit_float64_atan2, d_dd) } + op_def("dceil") { op_values(float64, float64), + op_intrinsic(jit_float64_ceil, d_d) } + op_def("dcos") { op_values(float64, float64), + op_intrinsic(jit_float64_cos, d_d) } + op_def("dcosh") { op_values(float64, float64), + op_intrinsic(jit_float64_cosh, d_d) } + op_def("dexp") { op_values(float64, float64), + op_intrinsic(jit_float64_exp, d_d) } + op_def("dfloor") { op_values(float64, float64), + op_intrinsic(jit_float64_floor, d_d) } + op_def("dlog") { op_values(float64, float64), + op_intrinsic(jit_float64_log, d_d) } + op_def("dlog10") { op_values(float64, float64), + op_intrinsic(jit_float64_log10, d_d) } + op_def("dpow") { op_values(float64, float64, float64), + op_intrinsic(jit_float64_pow, d_dd) } + op_def("drint") { op_values(float64, float64), + op_intrinsic(jit_float64_rint, d_d) } + op_def("dround") { op_values(float64, float64), + op_intrinsic(jit_float64_round, d_d) } + op_def("dsin") { op_values(float64, float64), + op_intrinsic(jit_float64_sin, d_d) } + op_def("dsinh") { op_values(float64, float64), + op_intrinsic(jit_float64_sinh, d_d) } + op_def("dsqrt") { op_values(float64, float64), + op_intrinsic(jit_float64_sqrt, d_d) } + op_def("dtan") { op_values(float64, float64), + op_intrinsic(jit_float64_tan, d_d) } + op_def("dtanh") { op_values(float64, float64), + op_intrinsic(jit_float64_tanh, d_d) } + op_def("dtrunc") { op_values(float64, float64), + op_intrinsic(jit_float64_trunc, d_d) } + op_def("nfacos") { op_values(nfloat, nfloat), + op_intrinsic(jit_nfloat_acos, D_D) } + op_def("nfasin") { op_values(nfloat, nfloat), + op_intrinsic(jit_nfloat_asin, D_D) } + op_def("nfatan") { op_values(nfloat, nfloat), + op_intrinsic(jit_nfloat_atan, D_D) } + op_def("nfatan2") { op_values(nfloat, nfloat, nfloat), + op_intrinsic(jit_nfloat_atan2, D_DD) } + op_def("nfceil") { op_values(nfloat, nfloat), + op_intrinsic(jit_nfloat_ceil, D_D) } + op_def("nfcos") { op_values(nfloat, nfloat), + op_intrinsic(jit_nfloat_cos, D_D) } + op_def("nfcosh") { op_values(nfloat, nfloat), + op_intrinsic(jit_nfloat_cosh, D_D) } + op_def("nfexp") { op_values(nfloat, nfloat), + op_intrinsic(jit_nfloat_exp, D_D) } + op_def("nffloor") { op_values(nfloat, nfloat), + op_intrinsic(jit_nfloat_floor, D_D) } + op_def("nflog") { op_values(nfloat, nfloat), + op_intrinsic(jit_nfloat_log, D_D) } + op_def("nflog10") { op_values(nfloat, nfloat), + op_intrinsic(jit_nfloat_log10, D_D) } + op_def("nfpow") { op_values(nfloat, nfloat, nfloat), + op_intrinsic(jit_nfloat_pow, D_DD) } + op_def("nfrint") { op_values(nfloat, nfloat), + op_intrinsic(jit_nfloat_rint, D_D) } + op_def("nfround") { op_values(nfloat, nfloat), + op_intrinsic(jit_nfloat_round, D_D) } + op_def("nfsin") { op_values(nfloat, nfloat), + op_intrinsic(jit_nfloat_sin, D_D) } + op_def("nfsinh") { op_values(nfloat, nfloat), + op_intrinsic(jit_nfloat_sinh, D_D) } + op_def("nfsqrt") { op_values(nfloat, nfloat), + op_intrinsic(jit_nfloat_sqrt, D_D) } + op_def("nftan") { op_values(nfloat, nfloat), + op_intrinsic(jit_nfloat_tan, D_D) } + op_def("nftanh") { op_values(nfloat, nfloat), + op_intrinsic(jit_nfloat_tanh, D_D) } + op_def("nftrunc") { op_values(nfloat, nfloat), + op_intrinsic(jit_nfloat_trunc, D_D) } /* * Absolute, minimum, maximum, and sign. */ - op_def("iabs") { op_values(int, int) } - op_def("labs") { op_values(long, long) } - op_def("fabs") { op_values(float32, float32) } - op_def("dabs") { op_values(float64, float64) } - op_def("nfabs") { op_values(nfloat, nfloat) } - op_def("imin") { op_values(int, int, int) } - op_def("imin_un") { op_values(int, int, int) } - op_def("lmin") { op_values(long, long, long) } - op_def("lmin_un") { op_values(long, long, long) } - op_def("fmin") { op_values(float32, float32, float32) } - op_def("dmin") { op_values(float64, float64, float64) } - op_def("nfmin") { op_values(nfloat, nfloat, nfloat) } - op_def("imax") { op_values(int, int, int) } - op_def("imax_un") { op_values(int, int, int) } - op_def("lmax") { op_values(long, long, long) } - op_def("lmax_un") { op_values(long, long, long) } - op_def("fmax") { op_values(float32, float32, float32) } - op_def("dmax") { op_values(float64, float64, float64) } - op_def("nfmax") { op_values(nfloat, nfloat, nfloat) } - op_def("isign") { op_values(int, int) } - op_def("lsign") { op_values(int, long) } - op_def("fsign") { op_values(int, float32) } - op_def("dsign") { op_values(int, float64) } - op_def("nfsign") { op_values(int, nfloat) } + op_def("iabs") { op_values(int, int), + op_intrinsic(jit_int_abs, i_i) } + op_def("labs") { op_values(long, long), + op_intrinsic(jit_long_abs, l_l) } + op_def("fabs") { op_values(float32, float32), + op_intrinsic(jit_float32_abs, f_f) } + op_def("dabs") { op_values(float64, float64), + op_intrinsic(jit_float64_abs, d_d) } + op_def("nfabs") { op_values(nfloat, nfloat), + op_intrinsic(jit_nfloat_abs, D_D) } + op_def("imin") { op_values(int, int, int), + op_intrinsic(jit_int_min, i_ii) } + op_def("imin_un") { op_values(int, int, int), + op_intrinsic(jit_uint_min, I_II) } + op_def("lmin") { op_values(long, long, long), + op_intrinsic(jit_long_min, l_ll) } + op_def("lmin_un") { op_values(long, long, long), + op_intrinsic(jit_ulong_min, L_LL) } + op_def("fmin") { op_values(float32, float32, float32), + op_intrinsic(jit_float32_min, f_ff) } + op_def("dmin") { op_values(float64, float64, float64), + op_intrinsic(jit_float64_min, d_dd) } + op_def("nfmin") { op_values(nfloat, nfloat, nfloat), + op_intrinsic(jit_nfloat_min, D_DD) } + op_def("imax") { op_values(int, int, int), + op_intrinsic(jit_int_max, i_ii) } + op_def("imax_un") { op_values(int, int, int), + op_intrinsic(jit_uint_max, I_II) } + op_def("lmax") { op_values(long, long, long), + op_intrinsic(jit_long_max, l_ll) } + op_def("lmax_un") { op_values(long, long, long), + op_intrinsic(jit_ulong_max, L_LL) } + op_def("fmax") { op_values(float32, float32, float32), + op_intrinsic(jit_float32_max, f_ff) } + op_def("dmax") { op_values(float64, float64, float64), + op_intrinsic(jit_float64_max, d_dd) } + op_def("nfmax") { op_values(nfloat, nfloat, nfloat), + op_intrinsic(jit_nfloat_max, D_DD) } + op_def("isign") { op_values(int, int), + op_intrinsic(jit_int_sign, i_i) } + op_def("lsign") { op_values(int, long), + op_intrinsic(jit_long_sign, i_l) } + op_def("fsign") { op_values(int, float32), + op_intrinsic(jit_float32_sign, i_f) } + op_def("dsign") { op_values(int, float64), + op_intrinsic(jit_float64_sign, i_d) } + op_def("nfsign") { op_values(int, nfloat), + op_intrinsic(jit_nfloat_sign, i_D) } /* * Pointer check opcodes. */ diff --git a/jit/Makefile.am b/jit/Makefile.am index ef2af91..965afe9 100644 --- a/jit/Makefile.am +++ b/jit/Makefile.am @@ -47,6 +47,7 @@ libjit_la_SOURCES = \ jit-memory.c \ jit-memory.h \ jit-meta.c \ + jit-opcode-apply.c \ jit-objmodel.c \ jit-opcode.c \ jit-pool.c \ diff --git a/jit/jit-internal.h b/jit/jit-internal.h index 35961ab..83d0bb4 100644 --- a/jit/jit-internal.h +++ b/jit/jit-internal.h @@ -757,6 +757,103 @@ extern struct _jit_type const _jit_type_float64_def; extern struct _jit_type const _jit_type_nfloat_def; extern struct _jit_type const _jit_type_void_ptr_def; +/* + * Intrinsic signatures. + * + * Naming convention is return type folowed by an underscore and the + * argument types. + * + * jit_int -> i (lower case I) + * jit_uint -> I + * jit_long -> l (lower case L) + * jit_ulong -> L + * jit_float32 -> f + * jit_float64 -> d + * jit_nflloat -> D + * + * pointer -> p followed by the type + * + * Special signatures are conv and conv_ovf for type conversions without + * and with overflow checks. + */ +enum +{ + JIT_SIG_NONE = 0, + JIT_SIG_i_i = 1, + JIT_SIG_i_ii = 2, + JIT_SIG_i_piii = 3, + JIT_SIG_i_iI = 4, + JIT_SIG_i_II = 5, + JIT_SIG_I_I = 6, + JIT_SIG_I_II = 7, + JIT_SIG_i_pIII = 8, + JIT_SIG_l_l = 9, + JIT_SIG_l_ll = 10, + JIT_SIG_i_plll = 11, + JIT_SIG_i_l = 12, + JIT_SIG_i_ll = 13, + JIT_SIG_l_lI = 14, + JIT_SIG_L_L = 15, + JIT_SIG_L_LL = 16, + JIT_SIG_i_pLLL = 17, + JIT_SIG_i_LL = 18, + JIT_SIG_L_LI = 19, + JIT_SIG_f_f = 20, + JIT_SIG_f_ff = 21, + JIT_SIG_i_f = 22, + JIT_SIG_i_ff = 23, + JIT_SIG_d_d = 24, + JIT_SIG_d_dd = 25, + JIT_SIG_i_d = 26, + JIT_SIG_i_dd = 27, + JIT_SIG_D_D = 28, + JIT_SIG_D_DD = 29, + JIT_SIG_i_D = 30, + JIT_SIG_i_DD = 31, + JIT_SIG_conv = 32, + JIT_SIG_conv_ovf= 33 +} _jit_intrinsic_signature; + +/* + * Flags for the instinsic info. + */ +#define _JIT_INTRINSIC_FLAG_NONE 0x0000 +#define _JIT_INTRINSIC_FLAG_BRANCH 0x8000 +#define _JIT_INTRINSIC_FLAG_BRANCH_UNARY 0xC000 +#define _JIT_INTRINSIC_FLAG_NOT 0x4000 +#define _JIT_INTRINSIC_FLAG_MASK 0xC000 + +/* + * Addititional intrinsic flags for the unary branches. + */ +#define _JIT_INTRINSIC_FLAG_IFALSE 0x0000 +#define _JIT_INTRINSIC_FLAG_ITRUE 0x0001 +#define _JIT_INTRINSIC_FLAG_LFALSE 0x0002 +#define _JIT_INTRINSIC_FLAG_LTRUE 0x0003 + +/* + * Descriprion for the implementation of an opcode by an intrinsic. + */ +typedef struct _jit_intrinsic_info _jit_intrinsic_info_t; +struct _jit_intrinsic_info +{ + jit_short flags; + jit_short signature; + void *intrinsic; +}; + +extern _jit_intrinsic_info_t const _jit_intrinsics[JIT_OP_NUM_OPCODES]; + +/* + * Apply an opcode to one or two constant values. + * Returns the constant result value on success and NULL otherwise. + * NOTE: dest_type MUST be either the correct destination type for the + * opcode or a tagged type of the correct destination type. + */ +jit_value_t +_jit_opcode_apply(jit_function_t func, jit_uint opcode, jit_type_t dest_type, + jit_value_t value1, jit_value_t value2); + /* * Extra call flags for internal use. */ diff --git a/jit/jit-opcode-apply.c b/jit/jit-opcode-apply.c new file mode 100644 index 0000000..494436b --- /dev/null +++ b/jit/jit-opcode-apply.c @@ -0,0 +1,887 @@ +/* + * jit-opcode-apply.c - Constant folding. + * + * Copyright (C) 2008 Southern Storm Software, Pty Ltd. + * + * This file is part of the libjit library. + * + * The libjit library is free software: you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation, either version 2.1 of + * the License, or (at your option) any later version. + * + * The libjit library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the libjit library. If not, see + * . + */ + +#include "jit-internal.h" +#include "jit-rules.h" + +/* + * Signatures for the different intrinsics + */ +typedef jit_int (*jit_cf_i_i_func)(jit_int value); +typedef jit_int (*jit_cf_i_ii_func)(jit_int value1, jit_int value2); +typedef jit_int (*jit_cf_i_piii_func)(jit_int *result, jit_int value1, jit_int value2); +typedef jit_int (*jit_cf_i_iI_func)(jit_int value1, jit_uint value2); +typedef jit_int (*jit_cf_i_II_func)(jit_uint value1, jit_uint value2); +typedef jit_uint (*jit_cf_I_I_func)(jit_uint value); +typedef jit_uint (*jit_cf_I_II_func)(jit_uint value1, jit_uint value2); +typedef jit_int (*jit_cf_i_pIII_func)(jit_uint *result, jit_uint value1, jit_uint value2); +typedef jit_long (*jit_cf_l_l_func)(jit_long value); +typedef jit_long (*jit_cf_l_ll_func)(jit_long value1, jit_long value2); +typedef jit_int (*jit_cf_i_plll_func)(jit_long *result, jit_long value1, jit_long value2); +typedef jit_int (*jit_cf_i_l_func)(jit_long value); +typedef jit_int (*jit_cf_i_ll_func)(jit_long value1, jit_long value2); +typedef jit_long (*jit_cf_l_lI_func)(jit_long value1, jit_uint value2); +typedef jit_ulong (*jit_cf_L_L_func)(jit_ulong value); +typedef jit_ulong (*jit_cf_L_LL_func)(jit_ulong value1, jit_ulong value2); +typedef jit_int (*jit_cf_i_pLLL_func)(jit_ulong *result, jit_ulong value1, jit_ulong value2); +typedef jit_int (*jit_cf_i_LL_func)(jit_ulong value1, jit_ulong value2); +typedef jit_ulong (*jit_cf_L_LI_func)(jit_ulong value1, jit_uint value2); +typedef jit_float32 (*jit_cf_f_f_func)(jit_float32 value); +typedef jit_float32 (*jit_cf_f_ff_func)(jit_float32 value1, jit_float32 value2); +typedef jit_int (*jit_cf_i_f_func)(jit_float32 value); +typedef jit_int (*jit_cf_i_ff_func)(jit_float32 value1, jit_float32 value2); +typedef jit_float64 (*jit_cf_d_d_func)(jit_float64 value); +typedef jit_float64 (*jit_cf_d_dd_func)(jit_float64 value1, jit_float64 value2); +typedef jit_int (*jit_cf_i_d_func)(jit_float64 value); +typedef jit_int (*jit_cf_i_dd_func)(jit_float64 value1, jit_float64 value2); +typedef jit_nfloat (*jit_cf_D_D_func)(jit_nfloat value); +typedef jit_nfloat (*jit_cf_D_DD_func)(jit_nfloat value1, jit_nfloat value2); +typedef jit_int (*jit_cf_i_D_func)(jit_nfloat value); +typedef jit_int (*jit_cf_i_DD_func)(jit_nfloat value1, jit_nfloat value2); + +/* + * NOTE: The result type is already set in const_result. + */ +static int +apply_conv(jit_constant_t *const_result, jit_value_t value, int overflow_check) +{ + jit_type_t srctype; + jit_constant_t const_value; + + srctype = jit_type_promote_int(jit_type_normalize(value->type)); + if(!srctype) + { + return 0; + } + const_value.type = srctype; + switch(srctype->kind) + { + case JIT_TYPE_INT: + { + const_value.un.int_value = value->address; + } + break; + + case JIT_TYPE_UINT: + { + const_value.un.uint_value = value->address; + } + break; + + case JIT_TYPE_LONG: + { +#ifdef JIT_NATIVE_INT64 + const_value.un.long_value = value->address; +#else + const_value.un.long_value = *(jit_long *)(value->address); +#endif + } + break; + + case JIT_TYPE_ULONG: + { +#ifdef JIT_NATIVE_INT64 + const_value.un.ulong_value = value->address; +#else + const_value.un.ulong_value = *(jit_ulong *)(value->address); +#endif + } + break; + + case JIT_TYPE_FLOAT32: + { + const_value.un.float32_value = *(jit_float32 *)(value->address); + } + break; + + case JIT_TYPE_FLOAT64: + { + const_value.un.float64_value = *(jit_float64 *)(value->address); + } + break; + + case JIT_TYPE_NFLOAT: + { + const_value.un.nfloat_value = *(jit_nfloat *)(value->address); + } + break; + + default: + { + return 0; + } + } + return jit_constant_convert(const_result, &const_value, + const_result->type, overflow_check); +} + +/* + * NOTE: value1 is guaranteed to be valid and a constant n entry of each + * of the apply_* functions. + * This is checked on entry of the public _jit_opcode_apply function. + */ +static int +apply_i_i(jit_constant_t *const_result, jit_value_t value1, + jit_cf_i_i_func intrinsic) +{ + if(value1->is_nint_constant) + { + const_result->un.int_value = (*intrinsic)(value1->address); + return 1; + } + return 0; +} + +static int +apply_i_ii(jit_constant_t *const_result, + jit_value_t value1, jit_value_t value2, + jit_cf_i_ii_func intrinsic) +{ + if(value1->is_nint_constant && value2 && value2->is_nint_constant) + { + const_result->un.int_value = (*intrinsic)(value1->address, + value2->address); + return 1; + } + return 0; +} + +static int +apply_i_piii(jit_constant_t *const_result, + jit_value_t value1, jit_value_t value2, + jit_cf_i_piii_func intrinsic) +{ + if(value1->is_nint_constant && value2 && value2->is_nint_constant) + { + return (*intrinsic)(&(const_result->un.int_value), + value1->address, value2->address); + } + return 0; +} + +static int +apply_i_iI(jit_constant_t *const_result, + jit_value_t value1, jit_value_t value2, + jit_cf_i_iI_func intrinsic) +{ + if(value1->is_nint_constant && value2 && value2->is_nint_constant) + { + const_result->un.int_value = (*intrinsic)(value1->address, + value2->address); + return 1; + } + return 0; +} + +static int +apply_i_II(jit_constant_t *const_result, + jit_value_t value1, jit_value_t value2, + jit_cf_i_II_func intrinsic) +{ + if(value1->is_nint_constant && value2 && value2->is_nint_constant) + { + const_result->un.int_value = (*intrinsic)(value1->address, value2->address); + return 1; + } + return 0; +} + +static int +apply_I_I(jit_constant_t *const_result, jit_value_t value1, + jit_cf_I_I_func intrinsic) +{ + if(value1->is_nint_constant) + { + const_result->un.uint_value = (*intrinsic)(value1->address); + return 1; + } + return 0; +} + +static int +apply_I_II(jit_constant_t *const_result, + jit_value_t value1, jit_value_t value2, + jit_cf_I_II_func intrinsic) +{ + if(value1->is_nint_constant && value2 && value2->is_nint_constant) + { + const_result->un.uint_value = (*intrinsic)(value1->address, value2->address); + return 1; + } + return 0; +} + +static int +apply_i_pIII(jit_constant_t *const_result, + jit_value_t value1, jit_value_t value2, + jit_cf_i_pIII_func intrinsic) +{ + if(value1->is_nint_constant && value2 && value2->is_nint_constant) + { + return (*intrinsic)(&(const_result->un.uint_value), + value1->address, value2->address); + } + return 0; +} + +static int +apply_l_l(jit_constant_t *const_result, jit_value_t value1, + jit_cf_l_l_func intrinsic) +{ +#ifdef JIT_NATIVE_INT64 + const_result->un.long_value = (*intrinsic)(value1->address); +#else + const_result->un.long_value = (*intrinsic)(*(jit_long *)(value1->address)); +#endif + return 1; +} + +static int +apply_l_ll(jit_constant_t *const_result, + jit_value_t value1, jit_value_t value2, + jit_cf_l_ll_func intrinsic) +{ + if(value2 && value2->is_constant) + { +#ifdef JIT_NATIVE_INT64 + const_result->un.long_value = (*intrinsic)(value1->address, + value2->address); +#else + const_result->un.long_value = (*intrinsic)(*(jit_long *)(value1->address), + *(jit_long *)(value2->address)); +#endif + return 1; + } + return 0; +} + +static int +apply_i_plll(jit_constant_t *const_result, + jit_value_t value1, jit_value_t value2, + jit_cf_i_plll_func intrinsic) +{ + if(value2 && value2->is_constant) + { +#ifdef JIT_NATIVE_INT64 + return (*intrinsic)(&(const_result->un.long_value), + value1->address, value2->address); +#else + return (*intrinsic)(&(const_result->un.long_value), + *(jit_long *)(value1->address), + *(jit_long *)(value2->address))) +#endif + } + return 0; +} + +static int +apply_i_l(jit_constant_t *const_result, + jit_value_t value, jit_cf_i_l_func intrinsic) +{ +#ifdef JIT_NATIVE_INT64 + const_result->un.int_value = (*intrinsic)(value->address); +#else + const_result->un.int_value = (*intrinsic)(*(jit_long *)(value->address)); +#endif + return 1; +} + +static int +apply_i_ll(jit_constant_t *const_result, + jit_value_t value1, jit_value_t value2, + jit_cf_i_ll_func intrinsic) +{ + if(value2 && value2->is_constant) + { +#ifdef JIT_NATIVE_INT64 + const_result->un.int_value = (*intrinsic)(value1->address, + value2->address); +#else + const_result->un.int_value = (*intrinsic)(*(jit_long *)(value1->address), + *(jit_long *)(value2->address)); +#endif + return 1; + } + return 0; +} + +static int +apply_l_lI(jit_constant_t *const_result, + jit_value_t value1, jit_value_t value2, + jit_cf_l_lI_func intrinsic) +{ + if(value2 && value2->is_nint_constant) + { +#ifdef JIT_NATIVE_INT64 + const_result->un.long_value = (*intrinsic)(value1->address, + value2->address); +#else + const_result->un.long_value = (*intrinsic)(*(jit_long *)(value1->address), + value2->address); +#endif + return 1; + } + return 0; +} + +static int +apply_L_L(jit_constant_t *const_result, jit_value_t value, + jit_cf_L_L_func intrinsic) +{ +#ifdef JIT_NATIVE_INT64 + const_result->un.ulong_value = (*intrinsic)(value->address); +#else + const_result->un.ulong_value = (*intrinsic)(*(jit_ulong *)(value->address)); +#endif + return 1; +} + +static int +apply_L_LL(jit_constant_t *const_result, + jit_value_t value1, jit_value_t value2, + jit_cf_L_LL_func intrinsic) +{ + if(value2 && value2->is_constant) + { +#ifdef JIT_NATIVE_INT64 + const_result->un.ulong_value = (*intrinsic)(value1->address, + value2->address); +#else + const_result->un.ulong_value = (*intrinsic)(*(jit_ulong *)(value1->address), + *(jit_ulong *)(value2->address)); +#endif + return 1; + } + return 0; +} + +static int +apply_i_pLLL(jit_constant_t *const_result, + jit_value_t value1, jit_value_t value2, + jit_cf_i_pLLL_func intrinsic) +{ + if(value2 && value2->is_constant) + { +#ifdef JIT_NATIVE_INT64 + return (*intrinsic)(&(const_result->un.ulong_value), + value1->address, value2->address); +#else + return (*intrinsic)(&(const_result->un.ulong_value), + *(jit_ulong *)(value1->address), + *(jit_ulong *)(value2->address)); +#endif + } + return 0; +} + +static int +apply_i_LL(jit_constant_t *const_result, + jit_value_t value1, jit_value_t value2, + jit_cf_i_LL_func intrinsic) +{ + if(value2 && value2->is_constant) + { +#ifdef JIT_NATIVE_INT64 + const_result->un.int_value = (*intrinsic)(value1->address, + value2->address); +#else + const_result->un.int_value = (*intrinsic)(*(jit_ulong *)(value1->address), + *(jit_ulong *)(value2->address)); +#endif + return 1; + } + return 0; +} + +static int +apply_L_LI(jit_constant_t *const_result, + jit_value_t value1, jit_value_t value2, + jit_cf_L_LI_func intrinsic) +{ + if(value2 && value2->is_nint_constant) + { +#ifdef JIT_NATIVE_INT64 + const_result->un.ulong_value = (*intrinsic)(value1->address, + value2->address); +#else + const_result->un.ulong_value = (*intrinsic)(*(jit_ulong *)(value1->address), + value2->address); +#endif + return 1; + } + return 0; +} + +static int +apply_f_f(jit_constant_t *const_result, jit_value_t value, + jit_cf_f_f_func intrinsic) +{ + const_result->un.float32_value = (*intrinsic)(*(jit_float32 *)(value->address)); + return 1; +} + +static int +apply_f_ff(jit_constant_t *const_result, + jit_value_t value1, jit_value_t value2, + jit_cf_f_ff_func intrinsic) +{ + if(value2 && value2->is_constant) + { + const_result->un.float32_value = (*intrinsic)(*(jit_float32 *)(value1->address), + *(jit_float32 *)(value2->address)); + return 1; + } + return 0; +} + +static int +apply_i_f(jit_constant_t *const_result, jit_value_t value, + jit_cf_i_f_func intrinsic) +{ + const_result->un.int_value = (*intrinsic)(*(jit_float32 *)(value->address)); + return 1; +} + +static int +apply_i_ff(jit_constant_t *const_result, + jit_value_t value1, jit_value_t value2, + jit_cf_i_ff_func intrinsic) +{ + if(value2 && value2->is_constant) + { + const_result->un.int_value = (*intrinsic)(*(jit_float32 *)(value1->address), + *(jit_float32 *)(value2->address)); + return 1; + } + return 0; +} + +static int +apply_d_d(jit_constant_t *const_result, jit_value_t value, + jit_cf_d_d_func intrinsic) +{ + const_result->un.float64_value = (*intrinsic)(*(jit_float64 *)(value->address)); + return 1; +} + +static int +apply_d_dd(jit_constant_t *const_result, + jit_value_t value1, jit_value_t value2, + jit_cf_d_dd_func intrinsic) +{ + if(value2 && value2->is_constant) + { + const_result->un.float64_value = (*intrinsic)(*(jit_float64 *)(value1->address), + *(jit_float64 *)(value2->address)); + return 1; + } + return 0; +} + +static int +apply_i_d(jit_constant_t *const_result, jit_value_t value, + jit_cf_i_d_func intrinsic) +{ + const_result->un.int_value = (*intrinsic)(*(jit_float64 *)(value->address)); + return 1; +} + +static int +apply_i_dd(jit_constant_t *const_result, + jit_value_t value1, jit_value_t value2, + jit_cf_i_dd_func intrinsic) +{ + if(value2 && value2->is_constant) + { + const_result->un.int_value = (*intrinsic)(*(jit_float64 *)(value1->address), + *(jit_float64 *)(value2->address)); + return 1; + } + return 0; +} + +static int +apply_D_D(jit_constant_t *const_result, jit_value_t value, + jit_cf_D_D_func intrinsic) +{ + const_result->un.nfloat_value = (*intrinsic)(*(jit_nfloat *)(value->address)); + return 1; +} + +static int +apply_D_DD(jit_constant_t *const_result, + jit_value_t value1, jit_value_t value2, + jit_cf_D_DD_func intrinsic) +{ + if(value2 && value2->is_constant) + { + const_result->un.nfloat_value = (*intrinsic)(*(jit_nfloat *)(value1->address), + *(jit_nfloat *)(value2->address)); + return 1; + } + return 0; +} + +static int +apply_i_D(jit_constant_t *const_result, + jit_value_t value, jit_cf_i_D_func intrinsic) +{ + const_result->un.int_value = (*intrinsic)(*(jit_nfloat *)(value->address)); + return 1; +} + +static int +apply_i_DD(jit_constant_t *const_result, + jit_value_t value1, jit_value_t value2, + jit_cf_i_DD_func intrinsic) +{ + if(value2 && value2->is_constant) + { + const_result->un.int_value = (*intrinsic)(*(jit_nfloat *)(value1->address), + *(jit_nfloat *)(value2->address)); + return 1; + } + return 0; +} + +static jit_value_t +apply_opcode(jit_function_t func, const _jit_intrinsic_info_t *opcode_info, + jit_type_t dest_type, jit_value_t value1, jit_value_t value2) +{ + jit_constant_t const_result; + int result = 0; + + const_result.type = dest_type; + switch(opcode_info->signature) + { + case JIT_SIG_i_i: + { + result = apply_i_i + (&const_result, value1, + (jit_cf_i_i_func)opcode_info->intrinsic); + } + break; + + case JIT_SIG_i_ii: + { + result = apply_i_ii + (&const_result, value1, value2, + (jit_cf_i_ii_func)opcode_info->intrinsic); + } + break; + + case JIT_SIG_i_piii: + { + result = apply_i_piii + (&const_result, value1, value2, + (jit_cf_i_piii_func)opcode_info->intrinsic); + } + break; + + case JIT_SIG_i_iI: + { + result = apply_i_iI + (&const_result, value1, value2, + (jit_cf_i_iI_func)opcode_info->intrinsic); + } + break; + + case JIT_SIG_i_II: + { + result = apply_i_II + (&const_result, value1, value2, + (jit_cf_i_II_func)opcode_info->intrinsic); + } + break; + + case JIT_SIG_I_I: + { + result = apply_I_I + (&const_result, value1, + (jit_cf_I_I_func)opcode_info->intrinsic); + } + break; + + case JIT_SIG_I_II: + { + result = apply_I_II + (&const_result, value1, value2, + (jit_cf_I_II_func)opcode_info->intrinsic); + } + break; + + case JIT_SIG_i_pIII: + { + result = apply_i_pIII + (&const_result, value1, value2, + (jit_cf_i_pIII_func)opcode_info->intrinsic); + } + break; + + case JIT_SIG_l_l: + { + result = apply_l_l + (&const_result, value1, + (jit_cf_l_l_func)opcode_info->intrinsic); + } + break; + + case JIT_SIG_l_ll: + { + result = apply_l_ll + (&const_result, value1, value2, + (jit_cf_l_ll_func)opcode_info->intrinsic); + } + break; + + case JIT_SIG_i_plll: + { + result = apply_i_plll + (&const_result, value1, value2, + (jit_cf_i_plll_func)opcode_info->intrinsic); + } + break; + + case JIT_SIG_i_l: + { + result = apply_i_l + (&const_result, value1, + (jit_cf_i_l_func)opcode_info->intrinsic); + } + break; + + case JIT_SIG_i_ll: + { + result = apply_i_ll + (&const_result, value1, value2, + (jit_cf_i_ll_func)opcode_info->intrinsic); + } + break; + + case JIT_SIG_l_lI: + { + result = apply_l_lI + (&const_result, value1, value2, + (jit_cf_l_lI_func)opcode_info->intrinsic); + } + break; + + case JIT_SIG_L_L: + { + result = apply_L_L + (&const_result, value1, + (jit_cf_L_L_func)opcode_info->intrinsic); + } + break; + + case JIT_SIG_L_LL: + { + result = apply_L_LL + (&const_result, value1, value2, + (jit_cf_L_LL_func)opcode_info->intrinsic); + } + break; + + case JIT_SIG_i_pLLL: + { + result = apply_i_pLLL + (&const_result, value1, value2, + (jit_cf_i_pLLL_func)opcode_info->intrinsic); + } + break; + + case JIT_SIG_i_LL: + { + result = apply_i_LL + (&const_result, value1, value2, + (jit_cf_i_LL_func)opcode_info->intrinsic); + } + break; + + case JIT_SIG_L_LI: + { + result = apply_L_LI + (&const_result, value1, value2, + (jit_cf_L_LI_func)opcode_info->intrinsic); + } + break; + + case JIT_SIG_f_f: + { + result = apply_f_f + (&const_result, value1, + (jit_cf_f_f_func)opcode_info->intrinsic); + } + break; + + case JIT_SIG_f_ff: + { + result = apply_f_ff + (&const_result, value1, value2, + (jit_cf_f_ff_func)opcode_info->intrinsic); + } + break; + + case JIT_SIG_i_f: + { + result = apply_i_f + (&const_result, value1, + (jit_cf_i_f_func)opcode_info->intrinsic); + } + break; + + case JIT_SIG_i_ff: + { + result = apply_i_ff + (&const_result, value1, value2, + (jit_cf_i_ff_func)opcode_info->intrinsic); + } + break; + + case JIT_SIG_d_d: + { + result = apply_d_d + (&const_result, value1, + (jit_cf_d_d_func)opcode_info->intrinsic); + } + break; + + case JIT_SIG_d_dd: + { + result = apply_d_dd + (&const_result, value1, value2, + (jit_cf_d_dd_func)opcode_info->intrinsic); + } + break; + + case JIT_SIG_i_d: + { + result = apply_i_d + (&const_result, value1, + (jit_cf_i_d_func)opcode_info->intrinsic); + } + break; + + case JIT_SIG_i_dd: + { + result = apply_i_dd + (&const_result, value1, value2, + (jit_cf_i_dd_func)opcode_info->intrinsic); + } + break; + + case JIT_SIG_D_D: + { + result = apply_D_D + (&const_result, value1, + (jit_cf_D_D_func)opcode_info->intrinsic); + } + break; + + case JIT_SIG_D_DD: + { + result = apply_D_DD + (&const_result, value1, value2, + (jit_cf_D_DD_func)opcode_info->intrinsic); + } + break; + + case JIT_SIG_i_D: + { + result = apply_i_D + (&const_result, value1, + (jit_cf_i_D_func)opcode_info->intrinsic); + } + break; + + case JIT_SIG_i_DD: + { + result = apply_i_DD + (&const_result, value1, value2, + (jit_cf_i_DD_func)opcode_info->intrinsic); + } + break; + + case JIT_SIG_conv: + { + result = apply_conv(&const_result, value1, 0); + } + break; + + case JIT_SIG_conv_ovf: + { + result = apply_conv(&const_result, value1, 1); + } + break; + } + if(result) + { + return jit_value_create_constant(func, &const_result); + } + return 0; +} + +jit_value_t +_jit_opcode_apply(jit_function_t func, jit_uint opcode, jit_type_t dest_type, + jit_value_t value1, jit_value_t value2) +{ + const _jit_intrinsic_info_t *opcode_info; + + if(!func || opcode >= JIT_OP_NUM_OPCODES) + { + return 0; + } + if((value1 == 0) || !(value1->is_constant)) + { + return 0; + } + opcode_info = &(_jit_intrinsics[opcode]); + if((opcode_info->flags & _JIT_INTRINSIC_FLAG_MASK) == + _JIT_INTRINSIC_FLAG_NOT) + { + jit_value_t value; + + opcode = opcode_info->flags & ~_JIT_INTRINSIC_FLAG_MASK; + if(opcode >= JIT_OP_NUM_OPCODES) + { + return 0; + } + opcode_info = &(_jit_intrinsics[opcode]); + value = apply_opcode(func, opcode_info, dest_type, value1, value2); + if(value) + { + /* + * We have to apply a logical not to the constant + * jit_int result value. + */ + value->address = !(value->address); + return value; + } + } + else if((opcode_info->flags & _JIT_INTRINSIC_FLAG_MASK) == + _JIT_INTRINSIC_FLAG_NONE) + { + return apply_opcode(func, opcode_info, dest_type, value1, value2); + } + return 0; +} + diff --git a/tools/gen-ops-parser.y b/tools/gen-ops-parser.y index 35dc051..a6ac448 100644 --- a/tools/gen-ops-parser.y +++ b/tools/gen-ops-parser.y @@ -50,6 +50,7 @@ extern char yytext[]; #define TASK_GEN_NONE 0 #define TASK_GEN_HEADER 1 #define TASK_GEN_TABLE 2 +#define TASK_GEN_CF_TABLE 3 /* * Value Flags @@ -99,15 +100,60 @@ extern char yytext[]; #define OP_COPY 0x14 #define OP_ADDRESS_OF 0x15 +/* + * Intrinisc signatures + */ +#define SIG_NONE 0 +#define SIG_i_i 1 +#define SIG_i_ii 2 +#define SIG_i_piii 3 +#define SIG_i_iI 4 +#define SIG_i_II 5 +#define SIG_I_I 6 +#define SIG_I_II 7 +#define SIG_i_pIII 8 +#define SIG_l_l 9 +#define SIG_l_ll 10 +#define SIG_i_plll 11 +#define SIG_i_l 12 +#define SIG_i_ll 13 +#define SIG_l_lI 14 +#define SIG_L_L 15 +#define SIG_L_LL 16 +#define SIG_i_pLLL 17 +#define SIG_i_LL 18 +#define SIG_L_LI 19 +#define SIG_f_f 20 +#define SIG_f_ff 21 +#define SIG_i_f 22 +#define SIG_i_ff 23 +#define SIG_d_d 24 +#define SIG_d_dd 25 +#define SIG_i_d 26 +#define SIG_i_dd 27 +#define SIG_D_D 28 +#define SIG_D_DD 29 +#define SIG_i_D 30 +#define SIG_i_DD 31 +#define SIG_conv 32 +#define SIG_conv_ovf 33 + /* * Current file and line number. */ extern char *genops_filename; extern long genops_linenum; +struct intrinsic_info +{ + const char *flags; + int signature; + const char *intrinsic; +}; + struct genops_opcode { - struct genops_opcode *next; + struct genops_opcode *next; const char *name; int type; int oper; @@ -115,6 +161,7 @@ struct genops_opcode int input1_flags; int input2_flags; const char *expression; + struct intrinsic_info intrinsic_info; }; /* @@ -140,6 +187,12 @@ static int genops_task = TASK_GEN_NONE; static FILE *genops_file = 0; static int genops_file_needs_close = 0; +/* + * options + */ +static int genops_gen_intrinsic_table = 0; +static const char *genops_intrinsic_decl = 0; + /* * Blocks coppied to the resulting file. */ @@ -201,7 +254,10 @@ genops_create_opcode_header(const char *define_start, const char *declaration, * Create an opcode entry */ static struct genops_opcode * -genops_add_opcode(const char *name, int type, int oper, int dest_flags, int input1_flags, int input2_flags, const char *expression) +genops_add_opcode(const char *name, int type, int oper, int dest_flags, + int input1_flags, int input2_flags, const char *expression, + const char *intrinsic_flags, int signature, + const char *intrinsic) { struct genops_opcode *opcode; @@ -229,6 +285,9 @@ genops_add_opcode(const char *name, int type, int oper, int dest_flags, int inpu opcode->input1_flags= input1_flags; opcode->input2_flags= input2_flags; opcode->expression = expression; + opcode->intrinsic_info.flags = intrinsic_flags; + opcode->intrinsic_info.signature = signature; + opcode->intrinsic_info.intrinsic = intrinsic; return opcode; } @@ -509,6 +568,220 @@ genops_output_value_flags(const char *prefix, int flags, int needs_or) return needs_or; } +/* + * + */ +static void +genops_output_signature(int signature) +{ + switch(signature) + { + case SIG_NONE: + { + printf("JIT_SIG_NONE"); + } + break; + + case SIG_i_i: + { + printf("JIT_SIG_i_i"); + } + break; + + case SIG_i_ii: + { + printf("JIT_SIG_i_ii"); + } + break; + + case SIG_i_piii: + { + printf("JIT_SIG_i_piii"); + } + break; + + case SIG_i_iI: + { + printf("JIT_SIG_i_iI"); + } + break; + + case SIG_i_II: + { + printf("JIT_SIG_i_II"); + } + break; + + case SIG_I_I: + { + printf("JIT_SIG_I_I"); + } + break; + + case SIG_I_II: + { + printf("JIT_SIG_I_II"); + } + break; + + case SIG_i_pIII: + { + printf("JIT_SIG_i_pIII"); + } + break; + + case SIG_l_l: + { + printf("JIT_SIG_l_l"); + } + break; + + case SIG_l_ll: + { + printf("JIT_SIG_l_ll"); + } + break; + + case SIG_i_plll: + { + printf("JIT_SIG_i_plll"); + } + break; + + case SIG_i_l: + { + printf("JIT_SIG_i_l"); + } + break; + + case SIG_i_ll: + { + printf("JIT_SIG_i_ll"); + } + break; + + case SIG_l_lI: + { + printf("JIT_SIG_l_lI"); + } + break; + + case SIG_L_L: + { + printf("JIT_SIG_L_L"); + } + break; + + case SIG_L_LL: + { + printf("JIT_SIG_L_LL"); + } + break; + + case SIG_i_pLLL: + { + printf("JIT_SIG_i_pLLL"); + } + break; + + case SIG_i_LL: + { + printf("JIT_SIG_i_LL"); + } + break; + + case SIG_L_LI: + { + printf("JIT_SIG_L_LI"); + } + break; + + case SIG_f_f: + { + printf("JIT_SIG_f_f"); + } + break; + + case SIG_f_ff: + { + printf("JIT_SIG_f_ff"); + } + break; + + case SIG_i_f: + { + printf("JIT_SIG_i_f"); + } + break; + + case SIG_i_ff: + { + printf("JIT_SIG_i_ff"); + } + break; + + case SIG_d_d: + { + printf("JIT_SIG_d_d"); + } + break; + + case SIG_d_dd: + { + printf("JIT_SIG_d_dd"); + } + break; + + case SIG_i_d: + { + printf("JIT_SIG_i_d"); + } + break; + + case SIG_i_dd: + { + printf("JIT_SIG_i_dd"); + } + break; + + case SIG_D_D: + { + printf("JIT_SIG_D_D"); + } + break; + + case SIG_D_DD: + { + printf("JIT_SIG_D_DD"); + } + break; + + case SIG_i_D: + { + printf("JIT_SIG_i_D"); + } + break; + + case SIG_i_DD: + { + printf("JIT_SIG_i_DD"); + } + break; + + case SIG_conv: + { + printf("JIT_SIG_conv"); + } + break; + + case SIG_conv_ovf: + { + printf("JIT_SIG_conv_ovf"); + } + break; + } +} + /* * Create an upper-case copy of a string. */ @@ -530,6 +803,37 @@ genops_string_upper(const char *string) return 0; } +static int +genops_set_option(const char *option, const char *value) +{ + if(!strcmp(option, "gen_intrinsic_table")) + { + if(!strcmp(value, "yes")) + { + genops_gen_intrinsic_table = 1; + } + else if(!strcmp(value, "no")) + { + genops_gen_intrinsic_table = 0; + } + else + { + yyerror("Invalid boolean value for the option. Allowed values: yes | no"); + return 0; + } + } + else if(!strcmp(option, "intrinsic_table_decl")) + { + genops_intrinsic_decl = value; + } + else + { + yyerror("Invalid option"); + return 0; + } + return 1; +} + %} /* @@ -567,8 +871,17 @@ genops_string_upper(const char *string) int input1_flags; int input2_flags; const char *expression; + const char *intrinsic_flags; + int signature; + const char *intrinsic; } opcode_properties; struct + { + const char *intrinsic_flags; + int signature; + const char *intrinsic; + } intrinsic_info; + struct { const char *name; int type; @@ -577,6 +890,9 @@ genops_string_upper(const char *string) int input1_flags; int input2_flags; const char *expression; + const char *intrinsic_flags; + int signature; + const char *intrinsic; } opcode; } @@ -592,8 +908,8 @@ genops_string_upper(const char *string) %token K_INT "int" %token K_LONG "long" %token K_PTR "ptr" -%token K_FLOAT32 "float32" -%token K_FLOAT64 "float64" +%token K_FLOAT32 "float32" +%token K_FLOAT64 "float64" %token K_NFLOAT "nfloat" %token K_NEG "neg" %token K_EQ "==" @@ -612,10 +928,45 @@ genops_string_upper(const char *string) %token K_CALL_EXTERNAL "call_external" %token K_JUMP_TABLE "jump_table" %token K_OP_DEF "op_def" -%token K_OP_TYPE "op_type" +%token K_OP_INTRINSIC "op_intrinsic" +%token K_OP_TYPE "op_type" %token K_OP_VALUES "op_values" -%token K_OPCODES "opcodes" +%token K_OPCODES "opcodes" %token K_REG "reg" +%token K_POPTION "%option" +%token K_i_i "i_i" +%token K_i_ii "i_ii" +%token K_i_piii "i_piii" +%token K_i_iI "i_iI" +%token K_i_II "i_II" +%token K_I_I "I_I" +%token K_I_II "I_II" +%token K_i_pIII "i_pIII" +%token K_l_l "l_l" +%token K_l_ll "l_ll" +%token K_i_plll "i_plll" +%token K_i_l "i_l" +%token K_i_ll "i_ll" +%token K_l_lI "l_lI" +%token K_L_L "L_L" +%token K_L_LL "L_LL" +%token K_i_pLLL "i_pLLL" +%token K_i_LL "i_LL" +%token K_L_LI "L_LI" +%token K_f_f "f_f" +%token K_f_ff "f_ff" +%token K_i_f "i_f" +%token K_i_ff "i_ff" +%token K_d_d "d_d" +%token K_d_dd "d_dd" +%token K_i_d "i_d" +%token K_i_dd "i_dd" +%token K_D_D "D_D" +%token K_D_DD "D_DD" +%token K_i_D "i_D" +%token K_i_DD "i_DD" +%token K_CONV "conv" +%token K_CONV_OVF "conv_ovf" /* * Define the yylval types of the various non-terminals. @@ -626,11 +977,13 @@ genops_string_upper(const char *string) %type OpcodeListHeader %type ValueFlag Op %type OpcodeType OpcodeTypeFlag +%type Signature %type OpcodeExpression %type Opcode %type OpcodeHeader %type OpcodeProperties %type OpcodeValues +%type OpcodeIntrinsicInfo %expect 0 @@ -640,11 +993,11 @@ genops_string_upper(const char *string) %% Start - : Blocks OpcodeDeclarations Blocks { + : Blocks OptOptions OpcodeDeclarations Blocks { start_code_block = ($1).code; start_header_block = ($1).header; - end_code_block = ($3).code;; - end_header_block = ($3).header; + end_code_block = ($4).code;; + end_header_block = ($4).header; } ; @@ -690,14 +1043,20 @@ Opcodes ($1).oper, ($1).dest_flags, ($1).input1_flags, ($1).input2_flags, - ($1).expression); + ($1).expression, + ($1).intrinsic_flags, + ($1).signature, + ($1).intrinsic); } | Opcodes Opcode { genops_add_opcode(($2).name, ($2).type, ($2).oper, ($2).dest_flags, ($2).input1_flags, ($2).input2_flags, - ($2).expression); + ($2).expression, + ($2).intrinsic_flags, + ($2).signature, + ($2).intrinsic); } ; @@ -710,6 +1069,9 @@ Opcode ($$).input1_flags = VALUE_FLAG_EMPTY; ($$).input2_flags = VALUE_FLAG_EMPTY; ($$).expression = 0; + ($$).intrinsic_flags = 0; + ($$).signature = SIG_NONE; + ($$).intrinsic = 0;; } | OpcodeHeader '{' OpcodeProperties '}' { ($$).name = ($1).name; @@ -719,6 +1081,9 @@ Opcode ($$).input1_flags = ($3).input1_flags; ($$).input2_flags = ($3).input2_flags; ($$).expression = ($3).expression; + ($$).intrinsic_flags = ($3).intrinsic_flags; + ($$).signature = ($3).signature; + ($$).intrinsic = ($3).intrinsic;; } ; @@ -740,6 +1105,9 @@ OpcodeProperties ($$).input1_flags = VALUE_FLAG_EMPTY; ($$).input2_flags = VALUE_FLAG_EMPTY; ($$).expression = 0; + ($$).intrinsic_flags = 0; + ($$).signature = SIG_NONE; + ($$).intrinsic = 0;; } | OpcodeValues { ($$).type = 0; @@ -747,6 +1115,9 @@ OpcodeProperties ($$).input1_flags = ($1).input1_flags; ($$).input2_flags = ($1).input2_flags; ($$).expression = 0; + ($$).intrinsic_flags = 0; + ($$).signature = SIG_NONE; + ($$).intrinsic = 0;; } | OpcodeExpression { ($$).type = 0; @@ -754,6 +1125,19 @@ OpcodeProperties ($$).input1_flags = VALUE_FLAG_EMPTY; ($$).input2_flags = VALUE_FLAG_EMPTY; ($$).expression = $1; + ($$).intrinsic_flags = 0; + ($$).signature = SIG_NONE; + ($$).intrinsic = 0;; + } + | OpcodeIntrinsicInfo { + ($$).type = 0; + ($$).dest_flags = VALUE_FLAG_EMPTY; + ($$).input1_flags = VALUE_FLAG_EMPTY; + ($$).input2_flags = VALUE_FLAG_EMPTY; + ($$).expression = 0; + ($$).intrinsic_flags = ($1).intrinsic_flags; + ($$).signature = ($1).signature; + ($$).intrinsic = ($1).intrinsic;; } | OpcodeProperties ',' OpcodeType { ($$).type = $3; @@ -761,6 +1145,9 @@ OpcodeProperties ($$).input1_flags = ($1).input1_flags; ($$).input2_flags = ($1).input2_flags; ($$).expression = ($1).expression; + ($$).intrinsic_flags = ($1).intrinsic_flags; + ($$).signature = ($1).signature; + ($$).intrinsic = ($1).intrinsic;; } | OpcodeProperties ',' OpcodeValues { ($$).type = ($1).type; @@ -768,6 +1155,9 @@ OpcodeProperties ($$).input1_flags = ($3).input1_flags; ($$).input2_flags = ($3).input2_flags; ($$).expression = ($1).expression; + ($$).intrinsic_flags = ($1).intrinsic_flags; + ($$).signature = ($1).signature; + ($$).intrinsic = ($1).intrinsic;; } | OpcodeProperties ',' OpcodeExpression { ($$).type = ($1).type; @@ -775,6 +1165,19 @@ OpcodeProperties ($$).input1_flags = ($1).input1_flags; ($$).input2_flags = ($1).input2_flags; ($$).expression = $3; + ($$).intrinsic_flags = ($1).intrinsic_flags; + ($$).signature = ($1).signature; + ($$).intrinsic = ($1).intrinsic;; + } + | OpcodeProperties ',' OpcodeIntrinsicInfo { + ($$).type = ($1).type; + ($$).dest_flags = ($1).dest_flags; + ($$).input1_flags = ($1).input1_flags; + ($$).input2_flags = ($1).input2_flags; + ($$).expression = ($1).expression; + ($$).intrinsic_flags = ($3).intrinsic_flags; + ($$).signature = ($3).signature; + ($$).intrinsic = ($3).intrinsic;; } ; @@ -849,6 +1252,60 @@ ValueFlag | K_ANY { $$ = VALUE_FLAG_ANY; } ; +OpcodeIntrinsicInfo + : K_OP_INTRINSIC '(' Literal ')' { + ($$).intrinsic_flags = $3; + ($$).signature = SIG_NONE; + ($$).intrinsic = 0;; + } + | K_OP_INTRINSIC '(' Signature ')' { + ($$).intrinsic_flags = 0; + ($$).signature = $3; + ($$).intrinsic = 0; + } + | K_OP_INTRINSIC '(' IDENTIFIER ',' Signature ')' { + ($$).intrinsic_flags = 0; + ($$).signature = $5; + ($$).intrinsic = $3; + } + ; + +Signature + : K_i_i { $$ = SIG_i_i; } + | K_i_ii { $$ = SIG_i_ii; } + | K_i_piii { $$ = SIG_i_piii; } + | K_i_iI { $$ = SIG_i_iI; } + | K_i_II { $$ = SIG_i_II; } + | K_I_I { $$ = SIG_I_I; } + | K_I_II { $$ = SIG_I_II; } + | K_i_pIII { $$ = SIG_i_pIII; } + | K_l_l { $$ = SIG_l_l; } + | K_l_ll { $$ = SIG_l_ll; } + | K_i_plll { $$ = SIG_i_plll; } + | K_i_l { $$ = SIG_i_l; } + | K_i_ll { $$ = SIG_i_ll; } + | K_l_lI { $$ = SIG_l_lI; } + | K_L_L { $$ = SIG_L_L; } + | K_L_LL { $$ = SIG_L_LL; } + | K_i_pLLL { $$ = SIG_i_pLLL; } + | K_i_LL { $$ = SIG_i_LL; } + | K_L_LI { $$ = SIG_L_LI; } + | K_f_f { $$ = SIG_f_f; } + | K_f_ff { $$ = SIG_f_ff; } + | K_i_f { $$ = SIG_i_f; } + | K_i_ff { $$ = SIG_i_ff; } + | K_d_d { $$ = SIG_d_d; } + | K_d_dd { $$ = SIG_d_dd; } + | K_i_d { $$ = SIG_i_d; } + | K_i_dd { $$ = SIG_i_dd; } + | K_D_D { $$ = SIG_D_D; } + | K_D_DD { $$ = SIG_D_DD; } + | K_i_D { $$ = SIG_i_D; } + | K_i_DD { $$ = SIG_i_DD; } + | K_CONV { $$ = SIG_conv; } + | K_CONV_OVF { $$ = SIG_conv_ovf; } + ; + Literal : LITERAL { $$ = $1; } | Literal LITERAL { @@ -865,6 +1322,25 @@ Literal } ; +OptOptions + : /* None */ { } + | Options + ; + +Options + : Option + | Options Option + ; + +Option + : K_POPTION IDENTIFIER '=' IDENTIFIER { + genops_set_option($2, $4); + } + | K_POPTION IDENTIFIER '=' Literal { + genops_set_option($2, $4); + } + ; + %% /* @@ -1052,6 +1528,49 @@ genops_output_ops(void) printf("};\n"); } +static void +genops_output_intrinsic_table(const char *define_start) +{ + struct genops_opcode *current; + + printf("%s = {\n", genops_intrinsic_decl); + current = opcode_header->first_opcode; + while(current) + { + printf("\t{"); + if(current->intrinsic_info.flags) + { + printf("%s", current->intrinsic_info.flags); + } + else + { + printf("%i", 0); + } + printf(", "); + genops_output_signature(current->intrinsic_info.signature); + printf(", "); + if(current->intrinsic_info.intrinsic) + { + printf("%s", current->intrinsic_info.intrinsic); + } + else + { + printf("0"); + } + printf("}"); + current = current->next; + if(current) + { + printf(",\n"); + } + else + { + printf("\n"); + } + } + printf("};\n"); +} + static void genops_output_opcode_table(const char *filename) { @@ -1062,6 +1581,11 @@ genops_output_opcode_table(const char *filename) printf("%s", start_code_block); } genops_output_ops(); + if(genops_gen_intrinsic_table) + { + printf("\n"); + genops_output_intrinsic_table(opcode_header->define_start); + } if(end_code_block) { printf("%s", end_code_block); diff --git a/tools/gen-ops-scanner.l b/tools/gen-ops-scanner.l index 25af607..27b428e 100644 --- a/tools/gen-ops-scanner.l +++ b/tools/gen-ops-scanner.l @@ -112,10 +112,45 @@ WHITE [ \t\v\r\f] "call_external" { RETURNTOK(K_CALL_EXTERNAL); } "jump_table" { RETURNTOK(K_JUMP_TABLE); } "op_def" { RETURNTOK(K_OP_DEF); } +"op_intrinsic" { RETURNTOK(K_OP_INTRINSIC); } "op_type" { RETURNTOK(K_OP_TYPE); } "op_values" { RETURNTOK(K_OP_VALUES); } "opcodes" { RETURNTOK(K_OPCODES); } "reg" { RETURNTOK(K_REG); } +"%option" { RETURNTOK(K_POPTION); } +"i_i" { RETURNTOK(K_i_i); } +"i_ii" { RETURNTOK(K_i_ii); } +"i_piii" { RETURNTOK(K_i_piii); } +"i_iI" { RETURNTOK(K_i_iI); } +"i_II" { RETURNTOK(K_i_II); } +"I_I" { RETURNTOK(K_I_I); } +"I_II" { RETURNTOK(K_I_II); } +"i_pIII" { RETURNTOK(K_i_pIII); } +"l_l" { RETURNTOK(K_l_l); } +"l_ll" { RETURNTOK(K_l_ll); } +"i_plll" { RETURNTOK(K_i_plll); } +"i_l" { RETURNTOK(K_i_l); } +"i_ll" { RETURNTOK(K_i_ll); } +"l_lI" { RETURNTOK(K_l_lI); } +"L_L" { RETURNTOK(K_L_L); } +"L_LL" { RETURNTOK(K_L_LL); } +"i_pLLL" { RETURNTOK(K_i_pLLL); } +"i_LL" { RETURNTOK(K_i_LL); } +"L_LI" { RETURNTOK(K_L_LI); } +"f_f" { RETURNTOK(K_f_f); } +"f_ff" { RETURNTOK(K_f_ff); } +"i_f" { RETURNTOK(K_i_f); } +"i_ff" { RETURNTOK(K_i_ff); } +"d_d" { RETURNTOK(K_d_d); } +"d_dd" { RETURNTOK(K_d_dd); } +"i_d" { RETURNTOK(K_i_d); } +"i_dd" { RETURNTOK(K_i_dd); } +"D_D" { RETURNTOK(K_D_D); } +"D_DD" { RETURNTOK(K_D_DD); } +"i_D" { RETURNTOK(K_i_D); } +"i_DD" { RETURNTOK(K_i_DD); } +"conv" { RETURNTOK(K_CONV); } +"conv_ovf" { RETURNTOK(K_CONV_OVF); } "!"?{IDALPHA}({DIGIT}|{IDALPHA})* { yylval.name = genops_strdup(yytext); -- 2.47.3