%default {"srcdouble":"1","tgtlong":"1"}
/* On fp to int conversions, Java requires that
 * if the result > maxint, it should be clamped to maxint.  If it is less
 * than minint, it should be clamped to minint.  If it is a nan, the result
 * should be zero.  Further, the rounding mode is to truncate.  This model
 * differs from what is delivered normally via the x86 fpu, so we have
 * to play some games.
 */
    /* float/double to int/long vA, vB */
    movzbl    rINST_HI,%ecx           # ecx<- A+
    sarl      $$12,rINST_FULL         # rINST_FULL<- B
    .if $srcdouble
    fldl     (rFP,rINST_FULL,4)       # %st0<- vB
    .else
    flds     (rFP,rINST_FULL,4)       # %st0<- vB
    .endif
    ftst
    fnstcw   LOCAL0_OFFSET(%ebp)      # remember original rounding mode
    movzwl   LOCAL0_OFFSET(%ebp),%eax
    movb     $$0xc,%ah
    movw     %ax,LOCAL0_OFFSET+2(%ebp)
    fldcw    LOCAL0_OFFSET+2(%ebp)      # set "to zero" rounding mode
    FETCH_INST_WORD(1)
    andb     $$0xf,%cl                # ecx<- A
    .if $tgtlong
    fistpll  (rFP,%ecx,4)             # convert and store
    .else
    fistpl   (rFP,%ecx,4)             # convert and store
    .endif
    fldcw    LOCAL0_OFFSET(%ebp)      # restore previous rounding mode
    jmp      .L${opcode}_continue
%break


.L${opcode}_continue:
    .if $tgtlong
    movl     $$0x80000000,%eax
    xorl     4(rFP,%ecx,4),%eax
    orl      (rFP,%ecx,4),%eax
    .else
    cmpl     $$0x80000000,(rFP,%ecx,4)
    .endif
    je       .L${opcode}_special_case # fix up result

.L${opcode}_finish:
    ADVANCE_PC(1)
    GOTO_NEXT

.L${opcode}_special_case:
    fnstsw   %ax
    sahf
    jp       .L${opcode}_isNaN
    adcl     $$-1,(rFP,%ecx,4)
    .if $tgtlong
    adcl     $$-1,4(rFP,%ecx,4)
    .endif
   jmp       .L${opcode}_finish
.L${opcode}_isNaN:
    movl      $$0,(rFP,%ecx,4)
    .if $tgtlong
    movl      $$0,4(rFP,%ecx,4)
    .endif
    jmp       .L${opcode}_finish