--- tme/ic/sparc/sparc-fpu-auto.sh 2018/04/24 16:42:00 1.1 +++ tme/ic/sparc/sparc-fpu-auto.sh 2018/04/24 16:43:58 1.1.1.2 @@ -1,6 +1,6 @@ #! /bin/sh -# $Id: sparc-fpu-auto.sh,v 1.1 2018/04/24 16:42:00 root Exp $ +# $Id: sparc-fpu-auto.sh,v 1.1.1.2 2018/04/24 16:43:58 root Exp $ # ic/sparc-fpu-auto.sh - automatically generates C code for many SPARC FPU # emulation instructions: @@ -48,7 +48,7 @@ done PROG=`basename $0` cat <= 9) { + cc = TME_FIELD_MASK_EXTRACTU(TME_SPARC_INSN, (0x3 << 25)); + if (cc != 0) { + fcc = TME_FIELD_MASK_EXTRACTU(fcc, TME_SPARC_FSR_FCC); + ic->tme_sparc_fpu_xfsr + = ((ic->tme_sparc_fpu_xfsr + & ~ (tme_uint32_t) (0x3 << (2 * (cc - 1)))) + | (fcc << (2 * (cc - 1)))); + return; + } + } ic->tme_sparc_fpu_fsr = (ic->tme_sparc_fpu_fsr & ~TME_SPARC_FSR_FCC) | fcc; } @@ -163,12 +175,18 @@ for fpop in fpop1 fpop2; do echo "{" echo " tme_uint8_t rounding_mode;" echo " unsigned int opf;" + echo " unsigned int fpreg_rd_number_encoded;" echo " unsigned int fpreg_rd_number;" echo " const struct tme_float *fpreg_rs1;" echo " const struct tme_float *fpreg_rs2;" if test ${fpop} = fpop1; then echo " struct tme_float fpreg_rs1_buffer;" echo " struct tme_float fpreg_rs2_buffer;" + else + echo " unsigned int cc;" + echo " tme_uint32_t conds_mask;" + echo " unsigned int cc_i;" + echo " tme_uint32_t cond;" fi echo " struct tme_float fpreg_rd;" echo " unsigned int fpreg_rd_format;" @@ -186,15 +204,87 @@ for fpop in fpop1 fpop2; do echo "" echo " /* decode the rd and opf fields: */" - echo " fpreg_rd_number = TME_FIELD_MASK_EXTRACTU(TME_SPARC_INSN, TME_SPARC_FORMAT3_MASK_RD);" + echo " fpreg_rd_number_encoded = TME_FIELD_MASK_EXTRACTU(TME_SPARC_INSN, TME_SPARC_FORMAT3_MASK_RD);" echo " opf = TME_FIELD_MASK_EXTRACTU(TME_SPARC_INSN, (0x1ff << 5));" echo "" + echo " /* silence uninitialized variable warnings: */" + echo " fpreg_rd_number = 0;" + + echo "" + echo "#ifdef _TME_SPARC_RECODE_VERIFY" + echo " /* clear the rd buffer: */" + echo " memset(&fpreg_rd, 0, sizeof(fpreg_rd));" + echo "#endif /* _TME_SPARC_RECODE_VERIFY */" + + fmovcc= + if test ${fpop} = fpop2; then + fmovcc=cc + echo "" + echo " /* if this is an FMOVcc: */" + echo " if (((opf - 1) & 0x3f) < 3) {" + echo "" + echo " /* if opf bit eight is set, this uses integer condition codes: */" + echo " if (opf & TME_BIT(8)) {" + echo "" + echo " /* if opf bit six is set, this is unimplemented: */" + echo " if (__tme_predict_false(opf & TME_BIT(6))) {" + echo " _TME_SPARC_FPU_UNIMPL;" + echo " }" + echo "" + echo " /* get %icc or %xcc, depending on opf bit seven: */" + echo " cc = ic->tme_sparc64_ireg_ccr;" + echo " if (opf & TME_BIT(7)) {" + echo " cc /= (TME_SPARC64_CCR_XCC / TME_SPARC64_CCR_ICC);" + echo " }" + echo " cc = TME_FIELD_MASK_EXTRACTU(cc, TME_SPARC64_CCR_ICC);" + echo "" + echo " /* get the conditions mask: */" + echo " conds_mask = _tme_sparc_conds_icc[cc];" + echo " }" + echo "" + echo " /* otherwise, this uses floating-point condition codes: */" + echo " else {" + echo "" + echo " /* get the right %fcc: */" + echo " cc_i = TME_FIELD_MASK_EXTRACTU(opf, (0x3 << 6));" + echo " if (cc_i == 0) {" + echo " cc = TME_FIELD_MASK_EXTRACTU(ic->tme_sparc_fpu_fsr, TME_SPARC_FSR_FCC);" + echo " }" + echo " else {" + echo " cc = (ic->tme_sparc_fpu_xfsr >> (2 * (cc_i - 1))) & 0x3;" + echo " }" + echo "" + echo " /* get the conditions mask: */" + echo " conds_mask = _tme_sparc_conds_fcc[cc];" + echo " }" + echo "" + echo " /* add the not-conditions to the conditions mask: */" + echo " conds_mask += ((~conds_mask) << 8);" + echo "" + echo " /* get the cond field: */" + echo " cond = TME_BIT(TME_FIELD_MASK_EXTRACTU(TME_SPARC_INSN, (0xf << 14)));" + echo "" + echo " /* if the condition is not true: */" + echo " if (!(conds_mask & cond)) {" + echo "" + echo " /* return now: */" + echo " /* NB that this may expose us to guests, since we do not check" + echo " that the floating-point register numbers are valid: */" + echo " return;" + echo " }" + echo "" + echo " /* clear bits six, seven, and eight in opf: */" + echo " opf &= 0x3f;" + echo " }" + fi + + echo "" echo " /* dispatch on the opf field: */" echo " switch (opf) {" echo "#define _TME_SPARC_FPU_FORMAT_RS1(format) fpreg_rs1 = tme_sparc_fpu_fpreg_read(ic, TME_SPARC_FORMAT3_MASK_RS1, (format))" echo "#define _TME_SPARC_FPU_FORMAT_RS2(format) fpreg_rs2 = tme_sparc_fpu_fpreg_read(ic, TME_SPARC_FORMAT3_MASK_RS2, (format))" - echo "#define _TME_SPARC_FPU_FORMAT_RD(format) do { fpreg_rd_format = (format) | TME_IEEE754_FPREG_FORMAT_BUILTIN; tme_sparc_fpu_fpreg_aligned(ic, fpreg_rd_number, fpreg_rd_format); } while (/* CONSTCOND */ 0)" + echo "#define _TME_SPARC_FPU_FORMAT_RD(format) do { fpreg_rd_format = (format) | TME_IEEE754_FPREG_FORMAT_BUILTIN; fpreg_rd_number = tme_sparc_fpu_fpreg_decode(ic, fpreg_rd_number_encoded, fpreg_rd_format); } while (/* CONSTCOND */ 0)" echo "" # permute over the opf field: @@ -249,6 +339,52 @@ for fpop in fpop1 fpop2; do echo " _TME_SPARC_FPU_OP_MONADIC(tme_ieee754_ops_quad_from_int32," echo " fpreg_rs2->tme_float_value_ieee754_single, &fpreg_rd);" ;; + fpop1:010000100) + echo " case ${opf_decimal}: /* ${opf} FxTOs: */" + echo "#ifdef TME_HAVE_INT64_T" + echo " if (__tme_predict_true(TME_SPARC_VERSION(ic) >= 9)) {" + echo " _TME_SPARC_FPU_FORMAT_RS2(TME_IEEE754_FPREG_FORMAT_DOUBLE);" + echo " _TME_SPARC_FPU_FORMAT_RD(TME_IEEE754_FPREG_FORMAT_SINGLE);" + echo " _TME_SPARC_FPU_BEGIN;" + echo " _TME_SPARC_FPU_OP_MONADIC(tme_ieee754_ops_single_from_int64," + echo " fpreg_rs2->tme_float_value_ieee754_double.tme_value64_int, &fpreg_rd);" + echo " break;" + echo " }" + echo "#endif /* TME_HAVE_INT64_T */" + echo " _TME_SPARC_FPU_UNIMPL;" + echo " fpreg_rd_format = TME_IEEE754_FPREG_FORMAT_NULL;" + ;; + fpop1:010001000) + echo " case ${opf_decimal}: /* ${opf} FxTOd: */" + echo "#ifdef TME_HAVE_INT64_T" + echo " if (__tme_predict_true(TME_SPARC_VERSION(ic) >= 9)) {" + echo " _TME_SPARC_FPU_FORMAT_RS2(TME_IEEE754_FPREG_FORMAT_DOUBLE);" + echo " _TME_SPARC_FPU_FORMAT_RD(TME_IEEE754_FPREG_FORMAT_DOUBLE);" + echo " _TME_SPARC_FPU_BEGIN;" + echo " _TME_SPARC_FPU_OP_MONADIC(tme_ieee754_ops_double_from_int64," + echo " fpreg_rs2->tme_float_value_ieee754_double.tme_value64_int, &fpreg_rd);" + echo " break;" + echo " }" + echo "#endif /* TME_HAVE_INT64_T */" + echo " _TME_SPARC_FPU_UNIMPL;" + echo " fpreg_rd_format = TME_IEEE754_FPREG_FORMAT_NULL;" + ;; + fpop1:010001100) + echo " case ${opf_decimal}: /* ${opf} FxTOq: */" + echo "#ifdef TME_HAVE_INT64_T" + echo " if (__tme_predict_true(TME_SPARC_VERSION(ic) >= 9)) {" + echo " ${quad}" + echo " _TME_SPARC_FPU_FORMAT_RS2(TME_IEEE754_FPREG_FORMAT_DOUBLE);" + echo " _TME_SPARC_FPU_FORMAT_RD(TME_IEEE754_FPREG_FORMAT_QUAD);" + echo " _TME_SPARC_FPU_BEGIN;" + echo " _TME_SPARC_FPU_OP_MONADIC(tme_ieee754_ops_quad_from_int64," + echo " fpreg_rs2->tme_float_value_ieee754_double.tme_value64_int, &fpreg_rd);" + echo " break;" + echo " }" + echo "#endif /* TME_HAVE_INT64_T */" + echo " _TME_SPARC_FPU_UNIMPL;" + echo " fpreg_rd_format = TME_IEEE754_FPREG_FORMAT_NULL;" + ;; fpop1:011010001) echo " case ${opf_decimal}: /* ${opf} FsTOi: */" echo " _TME_SPARC_FPU_FORMAT_RS2(TME_IEEE754_FPREG_FORMAT_SINGLE | TME_IEEE754_FPREG_FORMAT_BUILTIN);" @@ -280,6 +416,58 @@ for fpop in fpop1 fpop2; do echo " _TME_SPARC_FPU_OP_MONADIC(tme_ieee754_ops_quad_to_int32," echo " fpreg_rs2, (tme_int32_t *) &fpreg_rd.tme_float_value_ieee754_single);" ;; + fpop1:010000001) + echo " case ${opf_decimal}: /* ${opf} FsTOx: */" + echo "#ifdef TME_HAVE_INT64_T" + echo " if (__tme_predict_true(TME_SPARC_VERSION(ic) >= 9)) {" + echo " _TME_SPARC_FPU_FORMAT_RS2(TME_IEEE754_FPREG_FORMAT_SINGLE | TME_IEEE754_FPREG_FORMAT_BUILTIN);" + echo " _TME_SPARC_FPU_FORMAT_RD(TME_IEEE754_FPREG_FORMAT_DOUBLE);" + echo " _TME_SPARC_FPU_BEGIN;" + echo " fpreg_rd.tme_float_format = TME_FLOAT_FORMAT_IEEE754_DOUBLE;" + echo " ic->tme_sparc_fpu_ieee754_ctl.tme_ieee754_ctl_rounding_mode = TME_FLOAT_ROUND_TO_ZERO;" + echo " _TME_SPARC_FPU_OP_MONADIC(tme_ieee754_ops_single_to_int64," + echo " fpreg_rs2, &fpreg_rd.tme_float_value_ieee754_double.tme_value64_int);" + echo " break;" + echo " }" + echo "#endif /* TME_HAVE_INT64_T */" + echo " _TME_SPARC_FPU_UNIMPL;" + echo " fpreg_rd_format = TME_IEEE754_FPREG_FORMAT_NULL;" + ;; + fpop1:010000010) + echo " case ${opf_decimal}: /* ${opf} FdTOx: */" + echo "#ifdef TME_HAVE_INT64_T" + echo " if (__tme_predict_true(TME_SPARC_VERSION(ic) >= 9)) {" + echo " _TME_SPARC_FPU_FORMAT_RS2(TME_IEEE754_FPREG_FORMAT_DOUBLE | TME_IEEE754_FPREG_FORMAT_BUILTIN);" + echo " _TME_SPARC_FPU_FORMAT_RD(TME_IEEE754_FPREG_FORMAT_DOUBLE);" + echo " _TME_SPARC_FPU_BEGIN;" + echo " fpreg_rd.tme_float_format = TME_FLOAT_FORMAT_IEEE754_DOUBLE;" + echo " ic->tme_sparc_fpu_ieee754_ctl.tme_ieee754_ctl_rounding_mode = TME_FLOAT_ROUND_TO_ZERO;" + echo " _TME_SPARC_FPU_OP_MONADIC(tme_ieee754_ops_double_to_int64," + echo " fpreg_rs2, &fpreg_rd.tme_float_value_ieee754_double.tme_value64_int);" + echo " break;" + echo " }" + echo "#endif /* TME_HAVE_INT64_T */" + echo " _TME_SPARC_FPU_UNIMPL;" + echo " fpreg_rd_format = TME_IEEE754_FPREG_FORMAT_NULL;" + ;; + fpop1:010000011) + echo " case ${opf_decimal}: /* ${opf} FqTOx: */" + echo "#ifdef TME_HAVE_INT64_T" + echo " if (__tme_predict_true(TME_SPARC_VERSION(ic) >= 9)) {" + echo " ${quad}" + echo " _TME_SPARC_FPU_FORMAT_RS2(TME_IEEE754_FPREG_FORMAT_QUAD | TME_IEEE754_FPREG_FORMAT_BUILTIN);" + echo " _TME_SPARC_FPU_FORMAT_RD(TME_IEEE754_FPREG_FORMAT_DOUBLE);" + echo " _TME_SPARC_FPU_BEGIN;" + echo " fpreg_rd.tme_float_format = TME_FLOAT_FORMAT_IEEE754_DOUBLE;" + echo " ic->tme_sparc_fpu_ieee754_ctl.tme_ieee754_ctl_rounding_mode = TME_FLOAT_ROUND_TO_ZERO;" + echo " _TME_SPARC_FPU_OP_MONADIC(tme_ieee754_ops_quad_to_int64," + echo " fpreg_rs2, &fpreg_rd.tme_float_value_ieee754_double.tme_value64_int);" + echo " break;" + echo " }" + echo "#endif /* TME_HAVE_INT64_T */" + echo " _TME_SPARC_FPU_UNIMPL;" + echo " fpreg_rd_format = TME_IEEE754_FPREG_FORMAT_NULL;" + ;; fpop1:011001001) echo " case ${opf_decimal}: /* ${opf} FsTOd: */" echo " _TME_SPARC_FPU_FORMAT_RS2(TME_IEEE754_FPREG_FORMAT_SINGLE | TME_IEEE754_FPREG_FORMAT_BUILTIN);" @@ -325,13 +513,20 @@ for fpop in fpop1 fpop2; do echo " _TME_SPARC_FPU_OP_MONADIC(tme_ieee754_ops_double_from_quad," echo " fpreg_rs2, &fpreg_rd);" ;; - fpop1:000000001) - echo " case ${opf_decimal}: /* ${opf} FMOVs: */" + fpop1:000000001 | fpop2:000000001) + echo " case ${opf_decimal}: /* ${opf} FMOVs${fmovcc}: */" echo " _TME_SPARC_FPU_FORMAT_RS2(TME_IEEE754_FPREG_FORMAT_SINGLE | TME_IEEE754_FPREG_FORMAT_BUILTIN);" echo " _TME_SPARC_FPU_FORMAT_RD(TME_IEEE754_FPREG_FORMAT_SINGLE);" echo " _TME_SPARC_FPU_BEGIN;" echo " fpreg_rd = *fpreg_rs2;" ;; + fpop1:000000010 | fpop2:000000010) + echo " case ${opf_decimal}: /* ${opf} FMOVd${fmovcc}: */" + echo " _TME_SPARC_FPU_FORMAT_RS2(TME_IEEE754_FPREG_FORMAT_DOUBLE | TME_IEEE754_FPREG_FORMAT_BUILTIN);" + echo " _TME_SPARC_FPU_FORMAT_RD(TME_IEEE754_FPREG_FORMAT_DOUBLE);" + echo " _TME_SPARC_FPU_BEGIN;" + echo " fpreg_rd = *fpreg_rs2;" + ;; fpop1:000000101) echo " case ${opf_decimal}: /* ${opf} FNEGs: */" echo " _TME_SPARC_FPU_FORMAT_RS2(TME_IEEE754_FPREG_FORMAT_SINGLE);" @@ -340,6 +535,14 @@ for fpop in fpop1 fpop2; do echo " fpreg_rd = *fpreg_rs2;" echo " fpreg_rd.tme_float_value_ieee754_single ^= 0x80000000;" ;; + fpop1:000000110) + echo " case ${opf_decimal}: /* ${opf} FNEGd: */" + echo " _TME_SPARC_FPU_FORMAT_RS2(TME_IEEE754_FPREG_FORMAT_DOUBLE);" + echo " _TME_SPARC_FPU_FORMAT_RD(TME_IEEE754_FPREG_FORMAT_DOUBLE);" + echo " _TME_SPARC_FPU_BEGIN;" + echo " fpreg_rd = *fpreg_rs2;" + echo " fpreg_rd.tme_float_value_ieee754_double.tme_value64_uint32_hi ^= 0x80000000;" + ;; fpop1:000001001) echo " case ${opf_decimal}: /* ${opf} FABSs: */" echo " _TME_SPARC_FPU_FORMAT_RS2(TME_IEEE754_FPREG_FORMAT_SINGLE);" @@ -348,6 +551,14 @@ for fpop in fpop1 fpop2; do echo " fpreg_rd = *fpreg_rs2;" echo " fpreg_rd.tme_float_value_ieee754_single &= ~0x80000000;" ;; + fpop1:000001010) + echo " case ${opf_decimal}: /* ${opf} FABSd: */" + echo " _TME_SPARC_FPU_FORMAT_RS2(TME_IEEE754_FPREG_FORMAT_DOUBLE);" + echo " _TME_SPARC_FPU_FORMAT_RD(TME_IEEE754_FPREG_FORMAT_DOUBLE);" + echo " _TME_SPARC_FPU_BEGIN;" + echo " fpreg_rd = *fpreg_rs2;" + echo " fpreg_rd.tme_float_value_ieee754_double.tme_value64_uint32_hi &= ~0x80000000;" + ;; fpop1:000101001) echo " case ${opf_decimal}: /* ${opf} FSQRTs: */" echo " _TME_SPARC_FPU_UNIMPL_IF(TME_SPARC_FPU_FLAG_NO_FSQRT);" @@ -457,7 +668,7 @@ for fpop in fpop1 fpop2; do echo " fpreg_rs1, &fpreg_rs1_buffer);" echo " _TME_SPARC_FPU_OP_MONADIC(tme_ieee754_ops_double_from_single," echo " fpreg_rs2, &fpreg_rs2_buffer);" - echo " _TME_SPARC_FPU_OP_DYADIC(tme_ieee754_ops_single_mul," + echo " _TME_SPARC_FPU_OP_DYADIC(tme_ieee754_ops_double_mul," echo " &fpreg_rs1_buffer, &fpreg_rs2_buffer, &fpreg_rd);" ;; fpop1:001101110) @@ -558,7 +769,10 @@ for fpop in fpop1 fpop2; do esac if $default; then :; else echo " break;"; echo ""; fi done - echo " default: _TME_SPARC_FPU_UNIMPL; fpreg_rd_format = TME_IEEE754_FPREG_FORMAT_NULL; break;" + echo " default:" + echo " _TME_SPARC_FPU_UNIMPL;" + echo " fpreg_rd_format = TME_IEEE754_FPREG_FORMAT_NULL;" + echo " break;" echo "" echo "#undef _TME_SPARC_FPU_FORMAT_RS1" echo "#undef _TME_SPARC_FPU_FORMAT_RS2" @@ -570,6 +784,7 @@ for fpop in fpop1 fpop2; do echo " if (fpreg_rd_format != TME_IEEE754_FPREG_FORMAT_NULL) {" echo " tme_sparc_fpu_fpreg_format(ic, fpreg_rd_number, fpreg_rd_format);" echo " ic->tme_sparc_fpu_fpregs[fpreg_rd_number] = fpreg_rd;" + echo " TME_SPARC_FPU_DIRTY(ic, fpreg_rd_number);" echo " }" echo ""