From f9d70176875c35ecf4340d7cd73a88ddbcfd45fb Mon Sep 17 00:00:00 2001 From: Stephen Heumann Date: Tue, 16 Feb 2021 18:44:38 -0600 Subject: [PATCH] Add real to long long conversion routines. For conversion to signed long long, we can almost just use SANE's FX2C call to convert it to comp. But LLONG_MIN corresponds to the bit pattern of the comp NaN, so it has to be treated specially. (You might think SANE would return the comp NaN when converting out-of-range values, which would give the value we want, but somewhat strangely it does not.) For conversion to unsigned long long, we check if the value is greater than LLONG_MAX (which is also the max comp value). If so, we subtract LLONG_MAX+1 from the floating-point value before conversion and add it back in to the integer afterward. --- int64.asm | 129 ++++++++++++++++++++++++++++++++++++++++++++++++++- int64.macros | 24 ++++++++++ 2 files changed, 152 insertions(+), 1 deletion(-) diff --git a/int64.asm b/int64.asm index ce39d25..0be044c 100644 --- a/int64.asm +++ b/int64.asm @@ -614,7 +614,7 @@ exponent equ mantissa+8 biased exponent and sign bit ldy #0 default sign bit is 0 (positive) lda mantissa+6 if mantissa is negative then bpl lb0 - negate8 mantissa negate it + negate8 mantissa negate it ldy #$8000 sign bit is 1 (negative) lb0 tya set sign @@ -634,3 +634,130 @@ lp1 dec exponent normalize number ret pld rtl end + +**************************************************************** +* +* ~CnvRealLongLong - convert an extended SANE real into +* a long long integer +* +* Inputs: +* extended real on stack +* +* Outputs: +* signed long long int on stack +* +**************************************************************** +* +~CnvRealLongLong start + tsc + clc + adc #4 + pea 0 push src address for fcpxx + pha + pea llmin|-16 push dst address for fcpxx + pea llmin + pea 0 push operand address for ftintx + pha + ftintx round + fcpxx compare with LLONG_MIN + bne convert + + lda #$8000 if it is LONG_MIN, use that value + sta 12,s + asl a + sta 10,s + sta 8,s + sta 6,s + bra done + +convert tsc if it is not LONG_MIN, call fx2c: + clc + adc #4 + pea 0 push src address for fx2c + pha + pea 0 push dst address for fx2c + inc a + inc a + pha + fx2c convert + +done phb move return address + pla + plx + ply + phx + pha + plb + rtl + +llmin dc e'-9223372036854775808' + end + +**************************************************************** +* +* ~CnvRealULongLong - convert an extended SANE real into +* an unsigned long long integer +* +* Inputs: +* extended real on stack +* +* Outputs: +* unsigned long long int on stack +* +**************************************************************** +* +~CnvRealULongLong start + pea 0 initially assume val <= LLONG_MAX + + tsc + clc + adc #6 + pea 0 push src address for fcpxx + pha + pea llbig|-16 push dst address for fcpxx + pea llbig + pea 0 push operand address for ftintx + pha + ftintx round + fcpxx compare with LLONG_MAX+1 + bmi convert + + lda #1 if val > LLONG_MAX: + sta 1,S save flag to indicate this + tsc + clc + adc #6 + pea llbig|-16 push src address for fsubx + pea llbig + pea 0 push dst address for fsubx + pha + fsubx val -= LLONG_MAX+1 + +convert tsc + clc + adc #6 + pea 0 push src address for fx2c + pha + pea 0 push dst address for fx2c + inc a + inc a + pha + fx2c convert val as comp + + pla if orig val was > LLONG_MAX: + beq done + lda 12,s + eor #$8000 + sta 12,s result += LLONG_MAX+1 + +done phb move return address + pla + plx + ply + phx + pha + plb + rtl + +llbig dc e'9223372036854775808' + end diff --git a/int64.macros b/int64.macros index ea1d37e..f4da0ae 100644 --- a/int64.macros +++ b/int64.macros @@ -140,3 +140,27 @@ .d sta 2+&op mend + MACRO +&LAB FTINTX +&LAB PEA $0016 + LDX #$090A + JSL $E10000 + MEND + MACRO +&LAB FX2C +&LAB PEA $0510 + LDX #$090A + JSL $E10000 + MEND + MACRO +&LAB FCPXX +&LAB PEA $0A + LDX #$090A + JSL $E10000 + MEND + MACRO +&LAB FSUBX +&LAB PEA 2 + LDX #$090A + JSL $E10000 + MEND