File: faststring.cc

package info (click to toggle)
bochs 3.0%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 25,244 kB
  • sloc: cpp: 270,331; ansic: 25,334; sh: 8,371; makefile: 5,512; yacc: 1,485; asm: 395; perl: 359; lex: 318; csh: 3
file content (264 lines) | stat: -rw-r--r-- 8,017 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
/////////////////////////////////////////////////////////////////////////
// $Id$
/////////////////////////////////////////////////////////////////////////
//
//  Copyright (C) 2019  The Bochs Project
//
//  This library is free software; you can redistribute it and/or
//  modify it under the terms of the GNU Lesser General Public
//  License as published by the Free Software Foundation; either
//  version 2 of the License, or (at your option) any later version.
//
//  This library 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
//  Lesser General Public License for more details.
//
//  You should have received a copy of the GNU Lesser General Public
//  License along with this library; if not, write to the Free Software
//  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA
/////////////////////////////////////////////////////////////////////////

#define NEED_CPU_REG_SHORTCUTS 1
#include "bochs.h"
#include "cpu.h"
#define LOG_THIS BX_CPU_THIS_PTR

#include "pc_system.h"

//
// Repeat Speedups methods
//

#if BX_SUPPORT_REPEAT_SPEEDUPS
Bit32u BX_CPU_C::FastRepMOVSB(unsigned srcSeg, Bit32u srcOff, unsigned dstSeg, Bit32u dstOff, Bit32u byteCount, Bit32u granularity)
{
  BX_ASSERT(BX_CPU_THIS_PTR cpu_mode != BX_MODE_LONG_64);

  bx_address laddrSrc, laddrDst;

  bx_segment_reg_t *srcSegPtr = &BX_CPU_THIS_PTR sregs[srcSeg];
  if (srcSegPtr->cache.valid & SegAccessROK4G) {
    laddrSrc = srcOff;
  }
  else {
    if (!(srcSegPtr->cache.valid & SegAccessROK))
      return 0;
    if ((srcOff | 0xfff) > srcSegPtr->cache.u.segment.limit_scaled)
      return 0;

    laddrSrc = get_laddr32(srcSeg, srcOff);
  }

  bx_segment_reg_t *dstSegPtr = &BX_CPU_THIS_PTR sregs[dstSeg];
  if (dstSegPtr->cache.valid & SegAccessWOK4G) {
    laddrDst = dstOff;
  }
  else {
    if (!(dstSegPtr->cache.valid & SegAccessWOK))
      return 0;
    if ((dstOff | 0xfff) > dstSegPtr->cache.u.segment.limit_scaled)
      return 0;

    laddrDst = get_laddr32(dstSeg, dstOff);
  }

  return FastRepMOVSB(laddrSrc, laddrDst, byteCount, granularity);
}

Bit32u BX_CPU_C::FastRepMOVSB(bx_address laddrSrc, bx_address laddrDst, Bit64u byteCount, Bit32u granularity)
{
  Bit8u *hostAddrSrc = v2h_read_byte(laddrSrc, USER_PL);
  // Check that native host access was not vetoed for that page
  if (!hostAddrSrc) return 0;

  Bit8u *hostAddrDst = v2h_write_byte(laddrDst, USER_PL);
  // Check that native host access was not vetoed for that page
  if (!hostAddrDst) return 0;

  assert(! BX_CPU_THIS_PTR get_DF());

  // See how many bytes can fit in the rest of this page.
  Bit32u bytesFitSrc = 0x1000 - PAGE_OFFSET(laddrSrc);
  Bit32u bytesFitDst = 0x1000 - PAGE_OFFSET(laddrDst);

  // Restrict word count to the number that will fit in either
  // source or dest pages.
  if (byteCount > bytesFitSrc)
    byteCount = bytesFitSrc;
  if (byteCount > bytesFitDst)
    byteCount = bytesFitDst;
  if (byteCount > bx_pc_system.getNumCpuTicksLeftNextEvent())
    byteCount = bx_pc_system.getNumCpuTicksLeftNextEvent();

  byteCount &= ~(granularity-1);

  // If after all the restrictions, there is anything left to do...
  if (byteCount) {
    // Transfer data directly using host addresses
    for (unsigned j=0; j<byteCount; j++) {
      * (Bit8u *) hostAddrDst = * (Bit8u *) hostAddrSrc;
      hostAddrDst++;
      hostAddrSrc++;
    }
  }

  return byteCount;
}

Bit32u BX_CPU_C::FastRepSTOSB(unsigned dstSeg, Bit32u dstOff, Bit8u val, Bit32u count)
{
  bx_address laddrDst;

  BX_ASSERT(BX_CPU_THIS_PTR cpu_mode != BX_MODE_LONG_64);

  bx_segment_reg_t *dstSegPtr = &BX_CPU_THIS_PTR sregs[dstSeg];
  if (dstSegPtr->cache.valid & SegAccessWOK4G) {
    laddrDst = dstOff;
  }
  else {
    if (!(dstSegPtr->cache.valid & SegAccessWOK))
      return 0;
    if ((dstOff | 0xfff) > dstSegPtr->cache.u.segment.limit_scaled)
      return 0;

    laddrDst = get_laddr32(dstSeg, dstOff);
  }

  return FastRepSTOSB(laddrDst, val, count);
}

Bit32u BX_CPU_C::FastRepSTOSB(bx_address laddrDst, Bit8u val, Bit32u count)
{
  Bit8u *hostAddrDst = v2h_write_byte(laddrDst, USER_PL);
  // Check that native host access was not vetoed for that page
  if (!hostAddrDst) return 0;

  assert(! BX_CPU_THIS_PTR get_DF());

  // See how many bytes can fit in the rest of this page.
  Bit32u bytesFitDst = 0x1000 - PAGE_OFFSET(laddrDst);

  // Restrict word count to the number that will fit in either
  // source or dest pages.
  if (count > bytesFitDst)
    count = bytesFitDst;
  if (count > bx_pc_system.getNumCpuTicksLeftNextEvent())
    count = bx_pc_system.getNumCpuTicksLeftNextEvent();

  // If after all the restrictions, there is anything left to do...
  if (count) {
    // Transfer data directly using host addresses
    for (unsigned j=0; j<count; j++) {
      * (Bit8u *) hostAddrDst = val;
      hostAddrDst++;
    }
  }

  return count;
}

Bit32u BX_CPU_C::FastRepSTOSW(unsigned dstSeg, Bit32u dstOff, Bit16u val, Bit32u count)
{
  bx_address laddrDst;

  BX_ASSERT(BX_CPU_THIS_PTR cpu_mode != BX_MODE_LONG_64);

  bx_segment_reg_t *dstSegPtr = &BX_CPU_THIS_PTR sregs[dstSeg];
  if (dstSegPtr->cache.valid & SegAccessWOK4G) {
    laddrDst = dstOff;
  }
  else {
    if (!(dstSegPtr->cache.valid & SegAccessWOK))
      return 0;
    if ((dstOff | 0xfff) > dstSegPtr->cache.u.segment.limit_scaled)
      return 0;

    laddrDst = get_laddr32(dstSeg, dstOff);
  }

  return FastRepSTOSW(laddrDst, val, count);
}

Bit32u BX_CPU_C::FastRepSTOSW(bx_address laddrDst, Bit16u val, Bit32u count)
{
  Bit8u *hostAddrDst = v2h_write_byte(laddrDst, USER_PL);
  // Check that native host access was not vetoed for that page
  if (!hostAddrDst) return 0;

  assert(! BX_CPU_THIS_PTR get_DF());

  // See how many words can fit in the rest of this page.
  Bit32u wordsFitDst = (0x1000 - PAGE_OFFSET(laddrDst)) >> 1;

  // Restrict word count to the number that will fit in either
  // source or dest pages.
  if (count > wordsFitDst)
    count = wordsFitDst;
  if (count > bx_pc_system.getNumCpuTicksLeftNextEvent())
    count = bx_pc_system.getNumCpuTicksLeftNextEvent();

  // If after all the restrictions, there is anything left to do...
  if (count) {
    // Transfer data directly using host addresses
    for (unsigned j=0; j<count; j++) {
      WriteHostWordToLittleEndian((Bit16u*)hostAddrDst, val);
      hostAddrDst += 2;
    }
  }

  return count;
}

Bit32u BX_CPU_C::FastRepSTOSD(unsigned dstSeg, Bit32u dstOff, Bit32u val, Bit32u count)
{
  bx_address laddrDst;

  BX_ASSERT(BX_CPU_THIS_PTR cpu_mode != BX_MODE_LONG_64);

  bx_segment_reg_t *dstSegPtr = &BX_CPU_THIS_PTR sregs[dstSeg];
  if (dstSegPtr->cache.valid & SegAccessWOK4G) {
    laddrDst = dstOff;
  }
  else {
    if (!(dstSegPtr->cache.valid & SegAccessWOK))
      return 0;
    if ((dstOff | 0xfff) > dstSegPtr->cache.u.segment.limit_scaled)
      return 0;

    laddrDst = get_laddr32(dstSeg, dstOff);
  }

  return FastRepSTOSD(laddrDst, val, count);
}

Bit32u BX_CPU_C::FastRepSTOSD(bx_address laddrDst, Bit32u val, Bit32u count)
{
  Bit8u *hostAddrDst = v2h_write_byte(laddrDst, USER_PL);
  // Check that native host access was not vetoed for that page
  if (!hostAddrDst) return 0;

  assert(! BX_CPU_THIS_PTR get_DF());

  // See how many dwords can fit in the rest of this page.
  Bit32u dwordsFitDst = (0x1000 - PAGE_OFFSET(laddrDst)) >> 2;

  // Restrict dword count to the number that will fit in either
  // source or dest pages.
  if (count > dwordsFitDst)
    count = dwordsFitDst;
  if (count > bx_pc_system.getNumCpuTicksLeftNextEvent())
    count = bx_pc_system.getNumCpuTicksLeftNextEvent();

  // If after all the restrictions, there is anything left to do...
  if (count) {
    // Transfer data directly using host addresses
    for (unsigned j=0; j<count; j++) {
      WriteHostDWordToLittleEndian((Bit32u*)hostAddrDst, val);
      hostAddrDst += 4;
    }
  }

  return count;
}
#endif