The actual code changes.

This commit is contained in:
OBattler
2026-01-10 02:25:25 +01:00
parent 3ed1ac905b
commit b857e809bf
11 changed files with 156 additions and 128 deletions

View File

@@ -1578,12 +1578,22 @@ pc_send_cae(void)
extern void softresetx86(void);
extern void hardresetx86(void);
extern void biu_set_bus_cycle(int bus_cycle);
extern void biu_set_bus_state(int bus_state);
extern void biu_set_bus_next_state(int bus_next_state);
extern void biu_set_cycle_t1(void);
extern void biu_set_next_cycle(void);
extern int biu_get_bus_cycle(void);
extern int biu_get_bus_state(void);
extern int biu_get_bus_next_state(void);
extern void prefetch_queue_set_pos(int pos);
extern void prefetch_queue_set_ip(uint16_t ip);
extern void prefetch_queue_set_prefetching(int p);
extern void prefetch_queue_set_in(uint16_t in);
extern void prefetch_queue_set_suspended(int p);
extern int prefetch_queue_get_pos(void);
extern uint16_t prefetch_queue_get_ip(void);
extern int prefetch_queue_get_prefetching(void);
extern uint16_t prefetch_queue_get_in(void);
extern int prefetch_queue_get_suspended(void);
extern int prefetch_queue_get_size(void);
*/
static void

View File

@@ -237,7 +237,7 @@ exec386_2386(int32_t cycs)
cycles += cycs;
while (cycles > 0) {
cycle_period = (timer_target - (uint32_t) tsc) + 1;
cycle_period = (timer_target - (uint64_t) tsc) + 1;
x86_was_reset = 0;
cycdiff = 0;
@@ -411,7 +411,7 @@ block_ended:
fatal("Life expired\n");
}
if (TIMER_VAL_LESS_THAN_VAL(timer_target, (uint32_t) tsc))
if (TIMER_VAL_LESS_THAN_VAL(timer_target, (uint64_t) tsc))
timer_process();
#ifdef USE_GDBSTUB

View File

@@ -280,7 +280,7 @@ update_tsc(void)
tsc += cycdiff;
if (cycdiff > 0) {
if (TIMER_VAL_LESS_THAN_VAL(timer_target, (uint32_t) tsc))
if (TIMER_VAL_LESS_THAN_VAL(timer_target, (uint64_t) tsc))
timer_process();
}
}
@@ -865,7 +865,7 @@ exec386_dynarec(int32_t cycs)
}
if (cycdiff > 0) {
if (TIMER_VAL_LESS_THAN_VAL(timer_target, (uint32_t) tsc))
if (TIMER_VAL_LESS_THAN_VAL(timer_target, (uint64_t) tsc))
timer_process();
}
@@ -894,7 +894,7 @@ exec386(int32_t cycs)
cycles += cycs;
while (cycles > 0) {
cycle_period = (timer_target - (uint32_t) tsc) + 1;
cycle_period = (timer_target - (uint64_t) tsc) + 1;
x86_was_reset = 0;
cycdiff = 0;
@@ -1078,7 +1078,7 @@ block_ended:
fatal("Life expired\n");
}
if (TIMER_VAL_LESS_THAN_VAL(timer_target, (uint32_t) tsc))
if (TIMER_VAL_LESS_THAN_VAL(timer_target, (uint64_t) tsc))
timer_process();
#ifdef USE_GDBSTUB

View File

@@ -272,7 +272,7 @@ clock_end(void)
/* On 808x systems, clock speed is usually crystal frequency divided by an integer. */
tsc += (uint64_t) diff * ((uint64_t) xt_cpu_multi >> 32ULL); /* Shift xt_cpu_multi by 32 bits to the right and then multiply. */
if (TIMER_VAL_LESS_THAN_VAL(timer_target, (uint32_t) tsc))
if (TIMER_VAL_LESS_THAN_VAL(timer_target, (uint64_t) tsc))
timer_process();
}

View File

@@ -313,7 +313,7 @@ hdd_timing_write(hard_disk_t *hdd, uint32_t addr, uint32_t len)
}
}
hdd->cache.write_start_time = tsc + (uint32_t) (seek_time * cpuclock / 1000000.0);
hdd->cache.write_start_time = tsc + (uint64_t) (seek_time * cpuclock / 1000000.0);
return seek_time;
}
@@ -383,7 +383,7 @@ update_lru:
cache->ra_ongoing = 1;
cache->ra_segment = active_seg->id;
cache->ra_start_time = tsc + (uint32_t) (seek_time * cpuclock / 1000000.0);
cache->ra_start_time = tsc + (uint64_t) (seek_time * cpuclock / 1000000.0);
return seek_time;
}

View File

@@ -1,6 +1,14 @@
#ifndef _TIMER_H_
#define _TIMER_H_
#ifndef int128_t
#define int128_t __int128
#endif
#ifndef uint128_t
#define uint128_t unsigned __int128
#endif
extern uint64_t tsc;
/* Maximum period, currently 1 second. */
@@ -11,18 +19,6 @@ extern uint64_t tsc;
#define TIMER_SPLIT 2
#define TIMER_ENABLED 1
#pragma pack(push, 1)
typedef struct ts_struct_t {
uint32_t frac;
uint32_t integer;
} ts_struct_t;
#pragma pack(pop)
typedef union ts_t {
uint64_t ts64;
ts_struct_t ts32;
} ts_t;
/*Timers are based on the CPU Time Stamp Counter. Timer timestamps are in a
32:32 fixed point format, with the integer part compared against the TSC. The
fractional part is used when advancing the timestamp to ensure a more accurate
@@ -36,12 +32,8 @@ typedef union ts_t {
to repeat, the callback must call timer_advance_u64(). This is a change from
the old timer API.*/
typedef struct pc_timer_t {
#ifdef USE_PCEM_TIMER
uint32_t ts_integer;
uint64_t ts_integer;
uint32_t ts_frac;
#else
ts_t ts;
#endif
int flags; /* The flags are defined above. */
int in_callback;
double period; /* This is used for large period timers to count
@@ -60,7 +52,7 @@ extern "C" {
/*Timestamp of nearest enabled timer. CPU emulation must call timer_process()
when TSC matches or exceeds this.*/
extern uint32_t timer_target;
extern uint64_t timer_target;
/*Enable timer, without updating timestamp*/
extern void timer_enable(pc_timer_t *timer);
@@ -82,18 +74,33 @@ extern void timer_add(pc_timer_t *timer, void (*callback)(void *priv), void *pri
extern uint64_t TIMER_USEC;
/*True if timer a expires before timer b*/
#define TIMER_LESS_THAN(a, b) ((int64_t) ((a)->ts.ts64 - (b)->ts.ts64) <= 0)
#define TIMER_LESS_THAN(a, b) ((int64_t) ((a)->ts_integer - (b)->ts_integer) <= 0)
/*True if timer a expires before 32 bit integer timestamp b*/
#define TIMER_LESS_THAN_VAL(a, b) ((int32_t) ((a)->ts.ts32.integer - (b)) <= 0)
#define TIMER_LESS_THAN_VAL(a, b) ((int64_t) ((a)->ts_integer - (b)) <= 0)
/*True if 32 bit integer timestamp a expires before 32 bit integer timestamp b*/
#define TIMER_VAL_LESS_THAN_VAL(a, b) ((int32_t) ((a) - (b)) <= 0)
#define TIMER_VAL_LESS_THAN_VAL(a, b) ((int64_t) ((a) - (b)) <= 0)
#ifndef printf
#include <stdio.h>
#endif
/*Advance timer by delay, specified in 32:32 format. This should be used to
resume a recurring timer in a callback routine*/
static __inline void
timer_advance_u64(pc_timer_t *timer, uint64_t delay)
{
timer->ts.ts64 += delay;
uint64_t int_delay = delay >> 32;
uint32_t frac_delay = delay & 0xffffffff;
if (int_delay & 0x0000000080000000ULL) {
printf("timer_advance_u64(): Negative delay: %08X%08X!\n", (uint32_t) (int_delay), frac_delay);
int_delay |= 0xffffffff00000000ULL;
}
if ((frac_delay + timer->ts_frac) < frac_delay)
timer->ts_integer++;
timer->ts_frac += frac_delay;
timer->ts_integer += int_delay;
timer_enable(timer);
}
@@ -103,9 +110,16 @@ timer_advance_u64(pc_timer_t *timer, uint64_t delay)
static __inline void
timer_set_delay_u64(pc_timer_t *timer, uint64_t delay)
{
timer->ts.ts64 = 0ULL;
timer->ts.ts32.integer = tsc;
timer->ts.ts64 += delay;
uint64_t int_delay = delay >> 32;
uint32_t frac_delay = delay & 0xffffffff;
if (int_delay & 0x0000000080000000ULL) {
printf("timer_set_delay_u64(): Negative delay: %08X%08X!\n", (uint32_t) (int_delay), frac_delay);
int_delay |= 0xffffffff00000000ULL;
}
timer->ts_frac = frac_delay;
timer->ts_integer = int_delay + (uint64_t)tsc;
timer_enable(timer);
}
@@ -125,21 +139,19 @@ timer_is_on(pc_timer_t *timer)
}
/*Return integer timestamp of timer*/
static __inline uint32_t
static __inline uint64_t
timer_get_ts_int(pc_timer_t *timer)
{
return timer->ts.ts32.integer;
return timer->ts_integer;
}
/*Return remaining time before timer expires, in us. If the timer has already
expired then return 0*/
static __inline uint32_t
static __inline uint64_t
timer_get_remaining_us(pc_timer_t *timer)
{
int64_t remaining;
if (timer->flags & TIMER_ENABLED) {
remaining = (int64_t) (timer->ts.ts64 - (uint64_t) (tsc << 32));
int128_t remaining = (((uint128_t)timer->ts_integer << 32) | timer->ts_frac) - ((uint128_t)tsc << 32);
if (remaining < 0)
return 0;
@@ -151,13 +163,11 @@ timer_get_remaining_us(pc_timer_t *timer)
/*Return remaining time before timer expires, in 32:32 timestamp format. If the
timer has already expired then return 0*/
static __inline uint64_t
static __inline uint128_t
timer_get_remaining_u64(pc_timer_t *timer)
{
int64_t remaining;
if (timer->flags & TIMER_ENABLED) {
remaining = (int64_t) (timer->ts.ts64 - (uint64_t) (tsc << 32));
int128_t remaining = (((uint128_t)timer->ts_integer << 32) | timer->ts_frac) - ((uint128_t)tsc << 32);
if (remaining < 0)
return 0;

View File

@@ -668,7 +668,6 @@ read_mem_b(uint32_t addr)
{
mem_mapping_t *map;
uint8_t ret = 0xff;
int old_cycles = cycles;
mem_logical_addr = addr;
addr &= rammask;
@@ -677,8 +676,6 @@ read_mem_b(uint32_t addr)
if (map && map->read_b)
ret = map->read_b(addr, map->priv);
resub_cycles(old_cycles);
return ret;
}
@@ -687,7 +684,6 @@ read_mem_w(uint32_t addr)
{
mem_mapping_t *map;
uint16_t ret = 0xffff;
int old_cycles = cycles;
mem_logical_addr = addr;
addr &= rammask;
@@ -703,8 +699,6 @@ read_mem_w(uint32_t addr)
ret = map->read_b(addr, map->priv) | (map->read_b(addr + 1, map->priv) << 8);
}
resub_cycles(old_cycles);
return ret;
}
@@ -712,7 +706,6 @@ void
write_mem_b(uint32_t addr, uint8_t val)
{
mem_mapping_t *map;
int old_cycles = cycles;
mem_logical_addr = addr;
addr &= rammask;
@@ -720,15 +713,12 @@ write_mem_b(uint32_t addr, uint8_t val)
map = write_mapping[addr >> MEM_GRANULARITY_BITS];
if (map && map->write_b)
map->write_b(addr, val, map->priv);
resub_cycles(old_cycles);
}
void
write_mem_w(uint32_t addr, uint16_t val)
{
mem_mapping_t *map;
int old_cycles = cycles;
mem_logical_addr = addr;
addr &= rammask;
@@ -747,8 +737,6 @@ write_mem_w(uint32_t addr, uint16_t val)
}
}
}
resub_cycles(old_cycles);
}
uint8_t

View File

@@ -29,6 +29,7 @@
#include <86box/nmc93cxx.h>
#include <86box/plat_unused.h>
#define ENABLE_NMC93CXX_EEPROM_LOG 1
#ifdef ENABLE_NMC93CXX_EEPROM_LOG
int nmc93cxx_eeprom_do_log = ENABLE_NMC93CXX_EEPROM_LOG;

View File

@@ -8,7 +8,7 @@
#include <86box/nv/vid_nv_rivatimer.h>
uint64_t TIMER_USEC;
uint32_t timer_target;
uint64_t timer_target;
/*Enabled timers are stored in a linked list, with the first timer to expire at
the head.*/
@@ -23,68 +23,55 @@ void
timer_enable(pc_timer_t *timer)
{
pc_timer_t *timer_node = timer_head;
int ret = 0;
if (!timer_inited || (timer == NULL))
return;
if (timer->flags & TIMER_ENABLED)
timer_disable(timer);
if (timer->next || timer->prev)
fatal("timer_disable(): Attempting to enable a non-isolated "
"timer incorrectly marked as disabled\n");
fatal("timer_enable - timer->next\n");
timer->flags |= TIMER_ENABLED;
/*List currently empty - add to head*/
if (!timer_head) {
timer_head = timer;
timer_head = timer;
timer->next = timer->prev = NULL;
timer_target = timer_head->ts.ts32.integer;
ret = 1;
} else if (TIMER_LESS_THAN(timer, timer_head)) {
timer->next = timer_head;
timer->prev = NULL;
timer_head->prev = timer;
timer_head = timer;
timer_target = timer_head->ts.ts32.integer;
ret = 1;
} else if (!timer_head->next) {
timer_head->next = timer;
timer->prev = timer_head;
ret = 1;
timer_target = timer_head->ts_integer;
return;
}
if (ret == 0) {
pc_timer_t *prev = timer_head;
timer_node = timer_head->next;
timer_node = timer_head;
while (1) {
/*Timer expires before timer_node. Add to list in front of timer_node*/
if (TIMER_LESS_THAN(timer, timer_node)) {
timer->next = timer_node;
timer->prev = prev;
timer_node->prev = timer;
prev->next = timer;
ret = 1;
break;
while (1) {
/*
Timer expires before timer_node.
Add to list in front of timer_node
*/
if (TIMER_LESS_THAN(timer, timer_node)) {
timer->next = timer_node;
timer->prev = timer_node->prev;
timer_node->prev = timer;
if (timer->prev)
timer->prev->next = timer;
else {
timer_head = timer;
timer_target = timer_head->ts_integer;
}
/*timer_node is last in the list. Add timer to end of list*/
if (!timer_node->next) {
timer_node->next = timer;
timer->prev = timer_node;
ret = 1;
break;
}
prev = timer_node;
timer_node = timer_node->next;
return;
}
}
/* Do not mark it as enabled if it has failed every single condition. */
if (ret == 1)
timer->flags |= TIMER_ENABLED;
/*
timer_node is last in the list.
Add timer to end of list
*/
if (!timer_node->next) {
timer_node->next = timer;
timer->prev = timer_node;
return;
}
timer_node = timer_node->next;
}
}
void
@@ -93,9 +80,12 @@ timer_disable(pc_timer_t *timer)
if (!timer_inited || (timer == NULL) || !(timer->flags & TIMER_ENABLED))
return;
if (!timer->next && !timer->prev && timer != timer_head)
if (!timer->next && !timer->prev && timer != timer_head) {
uint32_t *p = NULL;
*p = 5; /* Crash deliberately. */
fatal("timer_disable(): Attempting to disable an isolated "
"non-head timer incorrectly marked as enabled\n");
}
timer->flags &= ~TIMER_ENABLED;
timer->in_callback = 0;
@@ -109,41 +99,60 @@ timer_disable(pc_timer_t *timer)
timer->prev = timer->next = NULL;
}
static void
timer_remove_head(void)
{
if (timer_head) {
pc_timer_t *timer = timer_head;
timer_head = timer->next;
timer_head->prev = NULL;
timer->next = timer->prev = NULL;
timer->flags &= ~TIMER_ENABLED;
}
}
void
timer_process(void)
{
pc_timer_t *timer;
int num = 0;
if (!timer_head)
return;
uint64_t old_target = timer_target;
while (1) {
timer = timer_head;
pc_timer_t *timer = timer_head;
if (!TIMER_LESS_THAN_VAL(timer, (uint32_t) tsc))
if (!TIMER_LESS_THAN_VAL(timer, (uint64_t) tsc)) {
if (num == 0)
pclog("No processing because all timers expire later\n");
break;
}
timer_head = timer->next;
if (timer_head)
timer_head->prev = NULL;
timer->next = timer->prev = NULL;
timer->flags &= ~TIMER_ENABLED;
timer_remove_head();
if (timer->flags & TIMER_SPLIT)
timer_advance_ex(timer, 0); /* We're splitting a > 1 s period into
multiple <= 1 s periods. */
multiple <= 1 s periods. */
else if (timer->callback != NULL) {
/* Make sure it's not NULL, so that we can
/*
Make sure it's not NULL, so that we can
have a NULL callback when no operation
is needed. */
is needed.
*/
timer->in_callback = 1;
timer->callback(timer->priv);
timer->in_callback = 0;
}
num++;
}
timer_target = timer_head->ts.ts32.integer;
timer_target = timer_head->ts_integer;
if (old_target > timer_target)
pclog("Timer wraparound!\n");
}
void
@@ -200,7 +209,8 @@ timer_stop(pc_timer_t *timer)
return;
timer->period = 0.0;
timer_disable(timer);
if (timer->flags & TIMER_ENABLED)
timer_disable(timer);
timer->flags &= ~TIMER_SPLIT;
timer->in_callback = 0;
}
@@ -277,11 +287,11 @@ timer_set_new_tsc(uint64_t new_tsc)
}
timer = timer_head;
timer_target = new_tsc + (int32_t)(timer_get_ts_int(timer_head) - (uint32_t)tsc);
timer_target = new_tsc + (int64_t)(timer_get_ts_int(timer_head) - (uint64_t)tsc);
while (timer) {
int32_t offset_from_current_tsc = (int32_t)(timer_get_ts_int(timer) - (uint32_t)tsc);
timer->ts.ts32.integer = new_tsc + offset_from_current_tsc;
int64_t offset_from_current_tsc = (int64_t)(timer_get_ts_int(timer) - (uint64_t)tsc);
timer->ts_integer = new_tsc + offset_from_current_tsc;
timer = timer->next;
}

View File

@@ -239,15 +239,23 @@ cga_recalctimings(cga_t *cga)
if (cga->cgamode & CGA_MODE_FLAG_HIGHRES) {
disptime = (double) (cga->crtc[CGA_CRTC_HTOTAL] + 1);
_dispontime = (double) cga->crtc[CGA_CRTC_HDISP];
if (_dispontime >= disptime)
_dispontime = disptime - 1;
} else {
disptime = (double) ((cga->crtc[CGA_CRTC_HTOTAL] + 1) << 1);
_dispontime = (double) (cga->crtc[CGA_CRTC_HDISP] << 1);
if (_dispontime >= disptime)
_dispontime = disptime - 2;
}
_dispofftime = disptime - _dispontime;
_dispontime = _dispontime * CGACONST;
_dispofftime = _dispofftime * CGACONST;
cga->dispontime = (uint64_t) (_dispontime);
if (cga->dispontime > 0x7fffffffffffffffULL)
pclog("CGA: Negative display on time (%i, %i, %i)\n", cga->cgamode & CGA_MODE_FLAG_HIGHRES, cga->crtc[CGA_CRTC_HTOTAL] + 1, cga->crtc[CGA_CRTC_HDISP]);
cga->dispofftime = (uint64_t) (_dispofftime);
if (cga->dispofftime > 0x7fffffffffffffffULL)
pclog("CGA: Negative display off time (%i, %i, %i)\n", cga->cgamode & CGA_MODE_FLAG_HIGHRES, cga->crtc[CGA_CRTC_HTOTAL] + 1, cga->crtc[CGA_CRTC_HDISP]);
}
static void

View File

@@ -329,12 +329,13 @@ genius_recalctimings(genius_t *genius)
double disptime;
double _dispontime;
double _dispofftime;
double crtcconst = (cpuclock / 53216000.0 * (double) (1ULL << 32)) * 9.0;
disptime = 0x31;
_dispontime = 0x28;
disptime = 0x62;
_dispontime = 0x50;
_dispofftime = disptime - _dispontime;
_dispontime *= MDACONST;
_dispofftime *= MDACONST;
_dispontime *= crtcconst;
_dispofftime *= crtcconst;
genius->dispontime = (uint64_t) (_dispontime);
genius->dispofftime = (uint64_t) (_dispofftime);
}