/***************************************************************************** * pce * *****************************************************************************/ /***************************************************************************** * File name: src/cpu/e8086/pqueue.c * * Created: 2003-09-20 by Hampa Hug * * Copyright: (C) 2003-2017 Hampa Hug * *****************************************************************************/ /***************************************************************************** * This program is free software. You can redistribute it and / or modify it * * under the terms of the GNU General Public License version 2 as published * * by the Free Software Foundation. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY, without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General * * Public License for more details. * *****************************************************************************/ #include "e8086.h" #include "internal.h" /* * Before an instruction is executed the prefetch buffer (pq_buf) is * filled up to pq_fill bytes. After the instruction is executed * the instruction bytes are discarded and the remaining bytes up * to pq_size are copied to the front of the queue. Bytes between * pq_size and pq_fill are discarded (and possibly read again from * RAM). * * The prefetch buffer is filled with pq_fill instead of pq_size bytes * so that there is always at least one entire instruction in the * prefetch buffer. Yes, this is ugly. */ void e86_pq_init (e8086_t *c) { c->pq_cnt = 0; c->delay += 10; } /* * Fill the prefetch queue */ void e86_pq_fill (e8086_t *c) { unsigned i; unsigned short val; unsigned short seg, ofs; unsigned cnt; unsigned long addr; seg = e86_get_cs (c); ofs = e86_get_ip (c); cnt = c->pq_fill; if (ofs <= (0xffff - cnt)) { /* all within one segment */ addr = e86_get_linear (seg, ofs) & c->addr_mask; if ((addr + cnt) <= c->ram_cnt) { for (i = c->pq_cnt; i < cnt; i++) { c->pq[i] = c->ram[addr + i]; } } else { i = c->pq_cnt; while (i < cnt) { val = c->mem_get_uint16 (c->mem, (addr + i) & c->addr_mask); c->pq[i] = val & 0xff; c->pq[i + 1] = (val >> 8) & 0xff; i += 2; } } } else { i = c->pq_cnt; while (i < cnt) { val = e86_get_mem16 (c, seg, ofs + i); c->pq[i] = val & 0xff; c->pq[i + 1] = (val >> 8) & 0xff; i += 2; } } c->pq_cnt = c->pq_size; } /* * Remove cnt bytes from the prefetch queue and copy the rest to the front */ void e86_pq_adjust (e8086_t *c, unsigned cnt) { unsigned n; unsigned char *d, *s; if (cnt >= c->pq_cnt) { c->pq_cnt = 0; return; } n = c->pq_cnt - cnt; s = c->pq + cnt; d = c->pq; while (n > 0) { *(d++) = *(s++); n -= 1; } c->pq_cnt -= cnt; }