diff --git a/src/codegen/codegen_ops_x86-64.h b/src/codegen/codegen_ops_x86-64.h index a68dee7ae..906b07dc6 100644 --- a/src/codegen/codegen_ops_x86-64.h +++ b/src/codegen/codegen_ops_x86-64.h @@ -4363,7 +4363,7 @@ static inline int FP_LOAD_REG_INT_W(int reg) addbyte(0xc5); addbyte((uint8_t)cpu_state_offset(ST)); - CALL_FUNC((uintptr_t)x87_fround); + CALL_FUNC((uintptr_t)x87_fround16_64); addbyte(0x93); /*XCHG EBX, EAX*/ @@ -4393,7 +4393,7 @@ static inline int FP_LOAD_REG_INT(int reg) addbyte(0xc5); addbyte((uint8_t)cpu_state_offset(ST)); - CALL_FUNC((uintptr_t)x87_fround); + CALL_FUNC((uintptr_t)x87_fround32_64); addbyte(0x93); /*XCHG EBX, EAX*/ diff --git a/src/cpu/x87_ops.h b/src/cpu/x87_ops.h index 17861fa57..9e06a343e 100644 --- a/src/cpu/x87_ops.h +++ b/src/cpu/x87_ops.h @@ -152,10 +152,72 @@ static __inline double x87_pop() return t; } +static __inline int16_t x87_fround16(double b) +{ + int16_t a, c; + + switch ((cpu_state.npxc >> 10) & 3) + { + case 0: /*Nearest*/ + a = (int16_t)floor(b); + c = (int16_t)floor(b + 1.0); + if ((b - a) < (c - b)) + return a; + else if ((b - a) > (c - b)) + return c; + else + return (a & 1) ? c : a; + case 1: /*Down*/ + return (int16_t)floor(b); + case 2: /*Up*/ + return (int16_t)ceil(b); + case 3: /*Chop*/ + return (int16_t)b; + } + + return 0; +} + +static __inline int64_t x87_fround16_64(double b) +{ + return (int64_t) x87_fround16(b); +} + +static __inline int32_t x87_fround32(double b) +{ + int32_t a, c; + + switch ((cpu_state.npxc >> 10) & 3) + { + case 0: /*Nearest*/ + a = (int32_t)floor(b); + c = (int32_t)floor(b + 1.0); + if ((b - a) < (c - b)) + return a; + else if ((b - a) > (c - b)) + return c; + else + return (a & 1) ? c : a; + case 1: /*Down*/ + return (int32_t)floor(b); + case 2: /*Up*/ + return (int32_t)ceil(b); + case 3: /*Chop*/ + return (int32_t)b; + } + + return 0; +} + +static __inline int64_t x87_fround32_64(double b) +{ + return (int64_t) x87_fround32(b); +} + static __inline int64_t x87_fround(double b) { int64_t a, c; - + switch ((cpu_state.npxc >> 10) & 3) { case 0: /*Nearest*/ diff --git a/src/cpu/x87_ops_loadstore.h b/src/cpu/x87_ops_loadstore.h index f742196ea..5e754fc90 100644 --- a/src/cpu/x87_ops_loadstore.h +++ b/src/cpu/x87_ops_loadstore.h @@ -42,24 +42,20 @@ static int opFILDiw_a32(uint32_t fetchdat) static int opFISTiw_a16(uint32_t fetchdat) { - int64_t temp64; FP_ENTER(); fetch_ea_16(fetchdat); SEG_CHECK_WRITE(cpu_state.ea_seg); - temp64 = x87_fround(ST(0)); - seteaw((int16_t)temp64); + seteaw(x87_fround16(ST(0))); CLOCK_CYCLES((fpu_type >= FPU_487SX) ? (x87_timings.fist_16) : (x87_timings.fist_16 * cpu_multi)); return cpu_state.abrt; } #ifndef FPU_8087 static int opFISTiw_a32(uint32_t fetchdat) { - int64_t temp64; FP_ENTER(); fetch_ea_32(fetchdat); SEG_CHECK_WRITE(cpu_state.ea_seg); - temp64 = x87_fround(ST(0)); - seteaw((int16_t)temp64); + seteaw(x87_fround16(ST(0))); CLOCK_CYCLES((fpu_type >= FPU_487SX) ? (x87_timings.fist_16) : (x87_timings.fist_16 * cpu_multi)); return cpu_state.abrt; } @@ -67,12 +63,10 @@ static int opFISTiw_a32(uint32_t fetchdat) static int opFISTPiw_a16(uint32_t fetchdat) { - int64_t temp64; FP_ENTER(); fetch_ea_16(fetchdat); SEG_CHECK_WRITE(cpu_state.ea_seg); - temp64 = x87_fround(ST(0)); - seteaw((int16_t)temp64); if (cpu_state.abrt) return 1; + seteaw(x87_fround16(ST(0))); if (cpu_state.abrt) return 1; x87_pop(); CLOCK_CYCLES((fpu_type >= FPU_487SX) ? (x87_timings.fist_16) : (x87_timings.fist_16 * cpu_multi)); return 0; @@ -80,12 +74,10 @@ static int opFISTPiw_a16(uint32_t fetchdat) #ifndef FPU_8087 static int opFISTPiw_a32(uint32_t fetchdat) { - int64_t temp64; FP_ENTER(); fetch_ea_32(fetchdat); SEG_CHECK_WRITE(cpu_state.ea_seg); - temp64 = x87_fround(ST(0)); - seteaw((int16_t)temp64); if (cpu_state.abrt) return 1; + seteaw(x87_fround16(ST(0))); if (cpu_state.abrt) return 1; x87_pop(); CLOCK_CYCLES((fpu_type >= FPU_487SX) ? (x87_timings.fist_16) : (x87_timings.fist_16 * cpu_multi)); return 0; @@ -240,24 +232,20 @@ static int opFILDil_a32(uint32_t fetchdat) static int opFISTil_a16(uint32_t fetchdat) { - int64_t temp64; FP_ENTER(); fetch_ea_16(fetchdat); SEG_CHECK_WRITE(cpu_state.ea_seg); - temp64 = x87_fround(ST(0)); - seteal((int32_t)temp64); + seteal(x87_fround32(ST(0))); CLOCK_CYCLES((fpu_type >= FPU_487SX) ? (x87_timings.fist_32) : (x87_timings.fist_32 * cpu_multi)); return cpu_state.abrt; } #ifndef FPU_8087 static int opFISTil_a32(uint32_t fetchdat) { - int64_t temp64; FP_ENTER(); fetch_ea_32(fetchdat); SEG_CHECK_WRITE(cpu_state.ea_seg); - temp64 = x87_fround(ST(0)); - seteal((int32_t)temp64); + seteal(x87_fround32(ST(0))); CLOCK_CYCLES((fpu_type >= FPU_487SX) ? (x87_timings.fist_32) : (x87_timings.fist_32 * cpu_multi)); return cpu_state.abrt; } @@ -265,12 +253,10 @@ static int opFISTil_a32(uint32_t fetchdat) static int opFISTPil_a16(uint32_t fetchdat) { - int64_t temp64; FP_ENTER(); fetch_ea_16(fetchdat); SEG_CHECK_WRITE(cpu_state.ea_seg); - temp64 = x87_fround(ST(0)); - seteal((int32_t)temp64); if (cpu_state.abrt) return 1; + seteal(x87_fround32(ST(0))); if (cpu_state.abrt) return 1; x87_pop(); CLOCK_CYCLES((fpu_type >= FPU_487SX) ? (x87_timings.fist_32) : (x87_timings.fist_32 * cpu_multi)); return 0; @@ -278,12 +264,10 @@ static int opFISTPil_a16(uint32_t fetchdat) #ifndef FPU_8087 static int opFISTPil_a32(uint32_t fetchdat) { - int64_t temp64; FP_ENTER(); fetch_ea_32(fetchdat); SEG_CHECK_WRITE(cpu_state.ea_seg); - temp64 = x87_fround(ST(0)); - seteal((int32_t)temp64); if (cpu_state.abrt) return 1; + seteal(x87_fround32(ST(0))); if (cpu_state.abrt) return 1; x87_pop(); CLOCK_CYCLES((fpu_type >= FPU_487SX) ? (x87_timings.fist_32) : (x87_timings.fist_32 * cpu_multi)); return 0; diff --git a/src/floppy/fdc.c b/src/floppy/fdc.c index 4da50795e..3c81dd02e 100644 --- a/src/floppy/fdc.c +++ b/src/floppy/fdc.c @@ -1892,9 +1892,10 @@ fdc_is_verify(fdc_t *fdc) int -fdc_data(fdc_t *fdc, uint8_t data) +fdc_data(fdc_t *fdc, uint8_t data, int last) { - int result = 0; + int i, result = 0; + int n; if (fdc->deleted & 2) { /* We're in a VERIFY command, so return with 0. */ @@ -1924,27 +1925,39 @@ fdc_data(fdc_t *fdc, uint8_t data) } } } else { - result = dma_channel_write(fdc->dma_ch, data); - if (fdc->tc) return -1; - if (result & DMA_OVER) { - fdc->data_ready = 1; - fdc->stat = 0xd0; - fdc->tc = 1; - return -1; - } - if (!fdc->fifo || (fdc->tfifo < 1)) { + dma_channel_write(fdc->dma_ch, data); + fdc->data_ready = 1; fdc->stat = 0xd0; + + if (result & DMA_OVER) { + fdc->tc = 1; + return -1; + } } else { - fdc_fifo_buf_advance(fdc); - if (fdc->fifobufpos == 0) { + /* FIFO enabled */ + fdc_fifo_buf_write(fdc, data); + if (last || (fdc->fifobufpos == 0)) { /* We have wrapped around, means FIFO is over */ fdc->data_ready = 1; fdc->stat = 0xd0; + + n = (fdc->fifobufpos > 0) ? (fdc->fifobufpos - 1) : fdc->tfifo; + if (fdc->fifobufpos > 0) + fdc->fifobufpos = 0; + + for (i = 0; i <= n; i++) { + result = dma_channel_write(fdc->dma_ch, fdc->fifobuf[i]); + + if (result & DMA_OVER) { + fdc->tc = 1; + return -1; + } + } } } } @@ -2057,10 +2070,10 @@ fdc_writeprotect(fdc_t *fdc) int fdc_getdata(fdc_t *fdc, int last) { - int data; + int i, data = 0; if ((fdc->flags & FDC_FLAG_PCJR) || !fdc->dma) { - if ((fdc->flags & FDC_FLAG_PCJR) || !fdc->fifo) { + if ((fdc->flags & FDC_FLAG_PCJR) || !fdc->fifo || (fdc->tfifo < 1)) { data = fdc->dat; if (!last) @@ -2072,20 +2085,32 @@ int fdc_getdata(fdc_t *fdc, int last) fdc->stat = 0xb0; } } else { - data = dma_channel_read(fdc->dma_ch); + if (!fdc->fifo || (fdc->tfifo < 1)) { + data = dma_channel_read(fdc->dma_ch); + + if (data & DMA_OVER) + fdc->tc = 1; - if (!fdc->fifo) { if (!last) fdc->stat = 0x90; } else { - fdc_fifo_buf_advance(fdc); + if (fdc->fifobufpos == 0) { + for (i = 0; i <= fdc->tfifo; i++) { + data = dma_channel_read(fdc->dma_ch); + fdc->fifobuf[i] = data; + + if (data & DMA_OVER) { + fdc->tc = 1; + break; + } + } + } + + data = fdc_fifo_buf_read(fdc); if (!last && (fdc->fifobufpos == 0)) fdc->stat = 0x90; } - - if (data & DMA_OVER) - fdc->tc = 1; } return data & 0xff; diff --git a/src/floppy/fdd_86f.c b/src/floppy/fdd_86f.c index 5ff02adb3..ebd7d6f7c 100644 --- a/src/floppy/fdd_86f.c +++ b/src/floppy/fdd_86f.c @@ -1577,7 +1577,7 @@ d86f_read_sector_data(int drive, int side) } else { if (dev->data_find.bytes_obtained < d86f_get_data_len(drive)) { if (dev->state != STATE_16_VERIFY_DATA) { - read_status = fdc_data(d86f_fdc, data); + read_status = fdc_data(d86f_fdc, data, dev->data_find.bytes_obtained == ((d86f_get_data_len(drive)) - 1)); if (read_status == -1) dev->dma_over++; } @@ -2139,7 +2139,7 @@ d86f_turbo_read(int drive, int side) } else { if (dev->data_find.bytes_obtained < (128UL << dev->last_sector.id.n)) { if (dev->state != STATE_16_VERIFY_DATA) { - read_status = fdc_data(d86f_fdc, dat); + read_status = fdc_data(d86f_fdc, dat, dev->data_find.bytes_obtained == ((128UL << dev->last_sector.id.n) - 1)); if (read_status == -1) dev->dma_over++; } diff --git a/src/include/86box/fdc.h b/src/include/86box/fdc.h index 5e2d50d06..87404e174 100644 --- a/src/include/86box/fdc.h +++ b/src/include/86box/fdc.h @@ -157,7 +157,7 @@ extern void fdc_set_base(fdc_t *fdc, int base); extern void fdc_set_irq(fdc_t *fdc, int irq); extern void fdc_set_dma_ch(fdc_t *fdc, int dma_ch); extern int fdc_getdata(fdc_t *fdc, int last); -extern int fdc_data(fdc_t *fdc, uint8_t data); +extern int fdc_data(fdc_t *fdc, uint8_t data, int last); extern void fdc_sectorid(fdc_t *fdc, uint8_t track, uint8_t side, uint8_t sector, uint8_t size, uint8_t crc1,