fork of PCE focusing on macplus, supporting DaynaPort SCSI network emulation
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}