fork of PCE focusing on macplus, supporting DaynaPort SCSI network emulation
at master 120 lines 3.3 kB view raw
1/***************************************************************************** 2 * pce * 3 *****************************************************************************/ 4 5/***************************************************************************** 6 * File name: src/cpu/e8086/pqueue.c * 7 * Created: 2003-09-20 by Hampa Hug <hampa@hampa.ch> * 8 * Copyright: (C) 2003-2017 Hampa Hug <hampa@hampa.ch> * 9 *****************************************************************************/ 10 11/***************************************************************************** 12 * This program is free software. You can redistribute it and / or modify it * 13 * under the terms of the GNU General Public License version 2 as published * 14 * by the Free Software Foundation. * 15 * * 16 * This program is distributed in the hope that it will be useful, but * 17 * WITHOUT ANY WARRANTY, without even the implied warranty of * 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General * 19 * Public License for more details. * 20 *****************************************************************************/ 21 22 23#include "e8086.h" 24#include "internal.h" 25 26 27/* 28 * Before an instruction is executed the prefetch buffer (pq_buf) is 29 * filled up to pq_fill bytes. After the instruction is executed 30 * the instruction bytes are discarded and the remaining bytes up 31 * to pq_size are copied to the front of the queue. Bytes between 32 * pq_size and pq_fill are discarded (and possibly read again from 33 * RAM). 34 * 35 * The prefetch buffer is filled with pq_fill instead of pq_size bytes 36 * so that there is always at least one entire instruction in the 37 * prefetch buffer. Yes, this is ugly. 38 */ 39 40 41void e86_pq_init (e8086_t *c) 42{ 43 c->pq_cnt = 0; 44 c->delay += 10; 45} 46 47/* 48 * Fill the prefetch queue 49 */ 50void e86_pq_fill (e8086_t *c) 51{ 52 unsigned i; 53 unsigned short val; 54 unsigned short seg, ofs; 55 unsigned cnt; 56 unsigned long addr; 57 58 seg = e86_get_cs (c); 59 ofs = e86_get_ip (c); 60 61 cnt = c->pq_fill; 62 63 if (ofs <= (0xffff - cnt)) { 64 /* all within one segment */ 65 66 addr = e86_get_linear (seg, ofs) & c->addr_mask; 67 68 if ((addr + cnt) <= c->ram_cnt) { 69 for (i = c->pq_cnt; i < cnt; i++) { 70 c->pq[i] = c->ram[addr + i]; 71 } 72 } 73 else { 74 i = c->pq_cnt; 75 while (i < cnt) { 76 val = c->mem_get_uint16 (c->mem, (addr + i) & c->addr_mask); 77 c->pq[i] = val & 0xff; 78 c->pq[i + 1] = (val >> 8) & 0xff; 79 i += 2; 80 } 81 } 82 } 83 else { 84 i = c->pq_cnt; 85 while (i < cnt) { 86 val = e86_get_mem16 (c, seg, ofs + i); 87 c->pq[i] = val & 0xff; 88 c->pq[i + 1] = (val >> 8) & 0xff; 89 90 i += 2; 91 } 92 } 93 94 c->pq_cnt = c->pq_size; 95} 96 97/* 98 * Remove cnt bytes from the prefetch queue and copy the rest to the front 99 */ 100void e86_pq_adjust (e8086_t *c, unsigned cnt) 101{ 102 unsigned n; 103 unsigned char *d, *s; 104 105 if (cnt >= c->pq_cnt) { 106 c->pq_cnt = 0; 107 return; 108 } 109 110 n = c->pq_cnt - cnt; 111 s = c->pq + cnt; 112 d = c->pq; 113 114 while (n > 0) { 115 *(d++) = *(s++); 116 n -= 1; 117 } 118 119 c->pq_cnt -= cnt; 120}