blob: a8bad639d60491df4a8c4390dc63156802d22bc4 [file] [log] [blame]
%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