+ // x87
+ case OP_FLD:
+ if (po->flags & OPF_FSHIFT)
+ fprintf(fout, " f_st1 = f_st0;\n");
+ if (po->operand[0].type == OPT_REG
+ && po->operand[0].reg == xST0)
+ {
+ strcat(g_comment, " fld st");
+ break;
+ }
+ fprintf(fout, " f_st0 = %s;",
+ out_src_opr_float(buf1, sizeof(buf1), po, &po->operand[0]));
+ strcat(g_comment, " fld");
+ break;
+
+ case OP_FILD:
+ if (po->flags & OPF_FSHIFT)
+ fprintf(fout, " f_st1 = f_st0;\n");
+ fprintf(fout, " f_st0 = (double)%s;",
+ out_src_opr(buf1, sizeof(buf1), po, &po->operand[0],
+ lmod_cast(po, po->operand[0].lmod, 1), 0));
+ strcat(g_comment, " fild");
+ break;
+
+ case OP_FLDc:
+ if (po->flags & OPF_FSHIFT)
+ fprintf(fout, " f_st1 = f_st0;\n");
+ fprintf(fout, " f_st0 = ");
+ switch (po->operand[0].val) {
+ case X87_CONST_1: fprintf(fout, "1.0;"); break;
+ case X87_CONST_Z: fprintf(fout, "0.0;"); break;
+ default: ferr(po, "TODO\n"); break;
+ }
+ break;
+
+ case OP_FST:
+ if ((po->flags & OPF_FPOP) && po->operand[0].type == OPT_REG
+ && po->operand[0].reg == xST0)
+ {
+ no_output = 1;
+ break;
+ }
+ fprintf(fout, " %s = f_st0;",
+ out_dst_opr_float(buf1, sizeof(buf1), po, &po->operand[0]));
+ if (po->flags & OPF_FSHIFT)
+ fprintf(fout, "\n f_st0 = f_st1;");
+ strcat(g_comment, " fst");
+ break;
+
+ case OP_FADD:
+ case OP_FDIV:
+ case OP_FMUL:
+ case OP_FSUB:
+ switch (po->op) {
+ case OP_FADD: j = '+'; break;
+ case OP_FDIV: j = '/'; break;
+ case OP_FMUL: j = '*'; break;
+ case OP_FSUB: j = '-'; break;
+ default: j = 'x'; break;
+ }
+ if (po->flags & OPF_FSHIFT) {
+ fprintf(fout, " f_st0 = f_st1 %c f_st0;", j);
+ }
+ else {
+ fprintf(fout, " %s %c= %s;",
+ out_dst_opr_float(buf1, sizeof(buf1), po, &po->operand[0]),
+ j,
+ out_src_opr_float(buf2, sizeof(buf2), po, &po->operand[1]));
+ }
+ break;
+
+ case OP_FDIVR:
+ case OP_FSUBR:
+ if (po->flags & OPF_FSHIFT)
+ snprintf(buf1, sizeof(buf1), "f_st0");
+ else
+ out_dst_opr_float(buf1, sizeof(buf1), po, &po->operand[0]);
+ fprintf(fout, " %s = %s %c %s;", buf1,
+ out_src_opr_float(buf2, sizeof(buf2), po, &po->operand[1]),
+ po->op == OP_FDIVR ? '/' : '-',
+ out_src_opr_float(buf3, sizeof(buf3), po, &po->operand[0]));
+ break;
+
+ case OP_FIADD:
+ case OP_FIDIV:
+ case OP_FIMUL:
+ case OP_FISUB:
+ switch (po->op) {
+ case OP_FIADD: j = '+'; break;
+ case OP_FIDIV: j = '/'; break;
+ case OP_FIMUL: j = '*'; break;
+ case OP_FISUB: j = '-'; break;
+ default: j = 'x'; break;
+ }
+ fprintf(fout, " f_st0 %c= (double)%s;", j,
+ out_src_opr(buf1, sizeof(buf1), po, &po->operand[0],
+ lmod_cast(po, po->operand[0].lmod, 1), 0));
+ break;
+
+ case OP_FIDIVR:
+ case OP_FISUBR:
+ fprintf(fout, " f_st0 = %s %c f_st0;",
+ out_src_opr_float(buf2, sizeof(buf2), po, &po->operand[1]),
+ po->op == OP_FIDIVR ? '/' : '-');
+ break;
+
+ case OPP_FTOL:
+ ferr_assert(po, po->flags & OPF_32BIT);
+ fprintf(fout, " eax = (s32)f_st0;");
+ if (po->flags & OPF_FSHIFT)
+ fprintf(fout, "\n f_st0 = f_st1;");
+ strcat(g_comment, " ftol");
+ break;
+