Skip to content

Commit bbda1ea

Browse files
Allow PEEK(-32768) to work
1 parent 7b51f4c commit bbda1ea

2 files changed

Lines changed: 53 additions & 26 deletions

File tree

fp.s

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -376,19 +376,14 @@ truncate_fp_to_int:
376376
cmp #32 ; Exponent >= 32 means out of range!
377377
bcs raise_out_of_range
378378
@in_range:
379-
lda FP0s ; Was float value negative?
380-
bpl @positive
381-
jsr negate_significand
382-
@positive:
383-
lda FP0t+1 ; Load the high byte of the return value
384-
tax ; Move into X for return
385-
rol A ; Rotate high bit into carry: this is the sign of the return value
386-
lda #0
387-
adc FP0t+2 ; If I add the sign to the top 2 bytes, it must be zero
388-
bne raise_out_of_range
389-
adc FP0t+3
379+
lda FP0t+2 ; Upper two bytes of magnitude must be zero
380+
ora FP0t+3
390381
bne raise_out_of_range
391-
lda FP0t+0 ; Load low byte of return value into A
382+
lda FP0s ; Was float value negative?
383+
bpl @load
384+
jsr negate_significand ; Negate the significand; upper bytes don't matter anymore
385+
@load:
386+
ldax FP0t ; Load result into AX
392387
rts
393388

394389
raise_out_of_range:

tests/fp_test.c

Lines changed: 46 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -175,9 +175,6 @@ void test_truncate_fp_to_int(void) {
175175
const IntConversionTestCase* test_case;
176176
int i;
177177
int result;
178-
Float less_than_one = { 0x00000000, 127 };
179-
Float too_large = { 0x00000000, 144 };
180-
Float much_too_large = { 0x00000000, 197 };
181178

182179
PRINT_TEST_NAME();
183180

@@ -194,18 +191,53 @@ void test_truncate_fp_to_int(void) {
194191
// Some unusual cases.
195192

196193
// If floating point value is less than 1, then output is zero.
197-
load_fp0(&less_than_one);
198-
result = truncate_fp_to_int();
199-
ASSERT_EQ(err, 0);
200-
ASSERT_EQ(result, 0);
194+
{
195+
Float less_than_one = { 0x00000000, 127 };
196+
load_fp0(&less_than_one);
197+
result = truncate_fp_to_int();
198+
ASSERT_EQ(err, 0);
199+
ASSERT_EQ(result, 0);
200+
}
201201

202-
// If floating point value is >=2^16, the function should return error.
203-
load_fp0(&too_large);
204-
result = truncate_fp_to_int();
205-
ASSERT_NE(err, 0);
206-
load_fp0(&much_too_large);
207-
result = truncate_fp_to_int();
208-
ASSERT_NE(err, 0);
202+
// 32768 (positive) should succeed. On cc65 the 16-bit int wraps to -32768.
203+
{
204+
Float fp_32768 = { 0x00000000, 143 }; // +32768
205+
load_fp0(&fp_32768);
206+
result = truncate_fp_to_int();
207+
ASSERT_EQ(err, 0);
208+
ASSERT_EQ(result, (int)-32768L);
209+
}
210+
211+
// 65535 should succeed. On cc65 the 16-bit int wraps to -1.
212+
{
213+
Float fp_65535 = { 0x7FFF0000, 143 }; // 65535
214+
load_fp0(&fp_65535);
215+
result = truncate_fp_to_int();
216+
ASSERT_EQ(err, 0);
217+
ASSERT_EQ(result, -1);
218+
}
219+
220+
// If floating point value is >=2^16 (65536), the function should return error.
221+
{
222+
Float too_large = { 0x00000000, 144 }; // 65536
223+
Float much_too_large = { 0x00000000, 197 };
224+
load_fp0(&too_large);
225+
result = truncate_fp_to_int();
226+
ASSERT_NE(err, 0);
227+
load_fp0(&much_too_large);
228+
result = truncate_fp_to_int();
229+
ASSERT_NE(err, 0);
230+
}
231+
232+
// -32769 should succeed (magnitude 32769 fits in 16 bits).
233+
// 16-bit negation of 0x8001 = 0x7FFF = 32767.
234+
{
235+
Float fp_neg_32769 = { 0x80010000, 143 }; // -32769
236+
load_fp0(&fp_neg_32769);
237+
result = truncate_fp_to_int();
238+
ASSERT_EQ(err, 0);
239+
ASSERT_EQ(result, 32767);
240+
}
209241
}
210242

211243
typedef struct Int32ConversionTestCase {

0 commit comments

Comments
 (0)