%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 rINSTbl, %ecx # ecx <- A+ sarl $$4, rINST # rINST <- B .if $srcdouble fldl VREG_ADDRESS(rINST) # %st0 <- vB .else flds VREG_ADDRESS(rINST) # %st0 <- vB .endif ftst fnstcw LOCAL0(%esp) # remember original rounding mode movzwl LOCAL0(%esp), %eax movb $$0xc, %ah movw %ax, LOCAL0+2(%esp) fldcw LOCAL0+2(%esp) # set "to zero" rounding mode andb $$0xf, %cl # ecx <- A .if $tgtlong fistpll VREG_ADDRESS(%ecx) # convert and store .else fistpl VREG_ADDRESS(%ecx) # convert and store .endif fldcw LOCAL0(%esp) # restore previous rounding mode .if $tgtlong movl $$0x80000000, %eax xorl VREG_HIGH_ADDRESS(%ecx), %eax orl VREG_ADDRESS(%ecx), %eax .else cmpl $$0x80000000, VREG_ADDRESS(%ecx) .endif je .L${opcode}_special_case # fix up result .L${opcode}_finish: xor %eax, %eax mov %eax, VREG_REF_ADDRESS(%ecx) .if $tgtlong mov %eax, VREG_REF_HIGH_ADDRESS(%ecx) .endif ADVANCE_PC_FETCH_AND_GOTO_NEXT 1 .L${opcode}_special_case: fnstsw %ax sahf jp .L${opcode}_isNaN adcl $$-1, VREG_ADDRESS(%ecx) .if $tgtlong adcl $$-1, VREG_HIGH_ADDRESS(%ecx) .endif jmp .L${opcode}_finish .L${opcode}_isNaN: movl $$0, VREG_ADDRESS(%ecx) .if $tgtlong movl $$0, VREG_HIGH_ADDRESS(%ecx) .endif jmp .L${opcode}_finish