OpenCores
URL https://opencores.org/ocsvn/ao486/ao486/trunk

Subversion Repositories ao486

[/] [ao486/] [trunk/] [bochs486/] [cpu/] [stack.cc] - Blame information for rev 2

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 alfik
/////////////////////////////////////////////////////////////////////////
2
// $Id: stack.cc 11580 2013-01-19 20:45:03Z sshwarts $
3
/////////////////////////////////////////////////////////////////////////
4
//
5
//   Copyright (c) 2012-2013 Stanislav Shwartsman
6
//          Written by Stanislav Shwartsman [sshwarts at sourceforge net]
7
//
8
//  This library is free software; you can redistribute it and/or
9
//  modify it under the terms of the GNU Lesser General Public
10
//  License as published by the Free Software Foundation; either
11
//  version 2 of the License, or (at your option) any later version.
12
//
13
//  This library is distributed in the hope that it will be useful,
14
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
15
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16
//  Lesser General Public License for more details.
17
//
18
//  You should have received a copy of the GNU Lesser General Public
19
//  License along with this library; if not, write to the Free Software
20
//  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA
21
//
22
/////////////////////////////////////////////////////////////////////////
23
 
24
#define NEED_CPU_REG_SHORTCUTS 1
25
#include "bochs.h"
26
#include "cpu.h"
27
#define LOG_THIS BX_CPU_THIS_PTR
28
 
29
void BX_CPP_AttrRegparmN(2) BX_CPU_C::stackPrefetch(bx_address offset, unsigned len)
30
{
31
  bx_address laddr;
32
  unsigned pageOffset;
33
 
34
  BX_CPU_THIS_PTR espHostPtr = 0; // initialize with NULL pointer
35
  BX_CPU_THIS_PTR espPageWindowSize = 0;
36
 
37
  len--;
38
 
39
#if BX_SUPPORT_X86_64
40
  if (long64_mode()) {
41
    laddr = offset;
42
    pageOffset = PAGE_OFFSET(offset);
43
 
44
    // canonical violations will miss the TLB below
45
 
46
    if (pageOffset + len >= 4096) // don't care for page split accesses
47
      return;
48
 
49
    BX_CPU_THIS_PTR espPageWindowSize = 4096;
50
  }
51
  else
52
#endif
53
  {
54
    laddr = get_laddr32(BX_SEG_REG_SS, offset);
55
    pageOffset = PAGE_OFFSET(laddr);
56
    if (pageOffset + len >= 4096) // don't care for page split accesses
57
      return;
58
 
59
    Bit32u limit = BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.limit_scaled;
60
    Bit32u pageStart = (Bit32u) offset - pageOffset;
61
 
62
    if (! BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.valid) {
63
      BX_ERROR(("stackPrefetch: SS not valid"));
64
      exception(BX_SS_EXCEPTION, 0);
65
    }
66
 
67
    BX_ASSERT(BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.p);
68
    BX_ASSERT(IS_DATA_SEGMENT_WRITEABLE(BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.type));
69
 
70
    // check that the begining of the page is within stack segment limits
71
    // problem can happen with EXPAND DOWN segments
72
    if (IS_DATA_SEGMENT_EXPAND_DOWN(BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.type)) {
73
      Bit32u upper_limit;
74
      if (BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.d_b)
75
        upper_limit = 0xffffffff;
76
      else
77
        upper_limit = 0x0000ffff;
78
      if (offset <= limit || offset > upper_limit || (upper_limit - offset) < len) {
79
        BX_ERROR(("stackPrefetch(%d): access [0x%08x] > SS.limit [0x%08x] ED", len+1, (Bit32u) offset, limit));
80
        exception(BX_SS_EXCEPTION, 0);
81
      }
82
 
83
      // check that the begining of the page is within stack segment limits
84
      // handle correctly the wrap corner case for EXPAND DOWN 
85
      Bit32u pageEnd = pageStart + 0xfff;
86
      if (pageStart > limit && pageStart < pageEnd) {
87
        BX_CPU_THIS_PTR espPageWindowSize = 4096;
88
        if ((upper_limit - offset) < (4096 - pageOffset))
89
          BX_CPU_THIS_PTR espPageWindowSize = (Bit32u)(upper_limit - offset + 1);
90
      }
91
    }
92
    else {
93
      if (offset > (limit - len) || len > limit) {
94
        BX_ERROR(("stackPrefetch(%d): access [0x%08x] > SS.limit [0x%08x]", len+1, (Bit32u) offset, limit));
95
        exception(BX_SS_EXCEPTION, 0);
96
      }
97
 
98
      if (pageStart <= limit) {
99
        BX_CPU_THIS_PTR espPageWindowSize = 4096;
100
        if ((limit - offset) < (4096 - pageOffset))
101
          BX_CPU_THIS_PTR espPageWindowSize = (Bit32u)(limit - offset + 1);
102
      }
103
    }
104
  }
105
 
106
  unsigned tlbIndex = BX_TLB_INDEX_OF(laddr, 0);
107
  Bit64u lpf = LPFOf(laddr);
108
  bx_TLB_entry *tlbEntry = &BX_CPU_THIS_PTR TLB.entry[tlbIndex];
109
  if (tlbEntry->lpf == lpf) {
110
    // See if the TLB entry privilege level allows us write access from this CPL
111
    // Assuming that we always can read if write access is OK
112
    if (tlbEntry->accessBits & (0x04 << USER_PL)) {
113
      BX_CPU_THIS_PTR espPageBias = (bx_address) pageOffset - offset;
114
      BX_CPU_THIS_PTR pAddrStackPage = tlbEntry->ppf;
115
      BX_CPU_THIS_PTR espHostPtr = (Bit8u*) tlbEntry->hostPageAddr;
116
    }
117
  }
118
 
119
  if (! BX_CPU_THIS_PTR espHostPtr || BX_CPU_THIS_PTR espPageWindowSize < 7)
120
    BX_CPU_THIS_PTR espPageWindowSize = 0;
121
  else
122
    BX_CPU_THIS_PTR espPageWindowSize -= 7;
123
}
124
 
125
void BX_CPP_AttrRegparmN(2) BX_CPU_C::stack_write_byte(bx_address offset, Bit8u data)
126
{
127
  bx_address espBiased = offset + BX_CPU_THIS_PTR espPageBias;
128
 
129
  if (espBiased >= BX_CPU_THIS_PTR espPageWindowSize) {
130
    stackPrefetch(offset, 1);
131
    espBiased = offset + BX_CPU_THIS_PTR espPageBias;
132
  }
133
 
134
  if (BX_CPU_THIS_PTR espHostPtr) {
135
    Bit8u *hostPageAddr = (Bit8u*)(BX_CPU_THIS_PTR espHostPtr + espBiased);
136
    bx_phy_address pAddr = BX_CPU_THIS_PTR pAddrStackPage + espBiased;
137
    BX_NOTIFY_LIN_MEMORY_ACCESS(get_laddr(BX_SEG_REG_SS, offset), pAddr, 1, CPL, BX_WRITE, (Bit8u*) &data);
138
    pageWriteStampTable.decWriteStamp(pAddr, 1);
139
    *hostPageAddr = data;
140
  }
141
  else {
142
    write_virtual_byte(BX_SEG_REG_SS, offset, data);
143
  }
144
}
145
 
146
void BX_CPP_AttrRegparmN(2) BX_CPU_C::stack_write_word(bx_address offset, Bit16u data)
147
{
148
  bx_address espBiased = offset + BX_CPU_THIS_PTR espPageBias;
149
 
150
  if (espBiased >= BX_CPU_THIS_PTR espPageWindowSize) {
151
    stackPrefetch(offset, 2);
152
    espBiased = offset + BX_CPU_THIS_PTR espPageBias;
153
  }
154
 
155
  if (BX_CPU_THIS_PTR espHostPtr) {
156
    Bit16u *hostPageAddr = (Bit16u*)(BX_CPU_THIS_PTR espHostPtr + espBiased);
157
    bx_phy_address pAddr = BX_CPU_THIS_PTR pAddrStackPage + espBiased;
158
#if BX_CPU_LEVEL >= 4 && BX_SUPPORT_ALIGNMENT_CHECK
159
    if (BX_CPU_THIS_PTR alignment_check() && (pAddr & 1) != 0) {
160
      BX_ERROR(("stack_write_word(): #AC misaligned access"));
161
      exception(BX_AC_EXCEPTION, 0);
162
    }
163
#endif
164
    BX_NOTIFY_LIN_MEMORY_ACCESS(get_laddr(BX_SEG_REG_SS, offset), pAddr, 2, CPL, BX_WRITE, (Bit8u*) &data);
165
    pageWriteStampTable.decWriteStamp(pAddr, 2);
166
    WriteHostWordToLittleEndian(hostPageAddr, data);
167
  }
168
  else {
169
    write_virtual_word(BX_SEG_REG_SS, offset, data);
170
  }
171
}
172
 
173
void BX_CPP_AttrRegparmN(2) BX_CPU_C::stack_write_dword(bx_address offset, Bit32u data)
174
{
175
  bx_address espBiased = offset + BX_CPU_THIS_PTR espPageBias;
176
 
177
  if (espBiased >= BX_CPU_THIS_PTR espPageWindowSize) {
178
    stackPrefetch(offset, 4);
179
    espBiased = offset + BX_CPU_THIS_PTR espPageBias;
180
  }
181
 
182
  if (BX_CPU_THIS_PTR espHostPtr) {
183
    Bit32u *hostPageAddr = (Bit32u*)(BX_CPU_THIS_PTR espHostPtr + espBiased);
184
    bx_phy_address pAddr = BX_CPU_THIS_PTR pAddrStackPage + espBiased;
185
#if BX_CPU_LEVEL >= 4 && BX_SUPPORT_ALIGNMENT_CHECK
186
    if (BX_CPU_THIS_PTR alignment_check() && (pAddr & 3) != 0) {
187
      BX_ERROR(("stack_write_dword(): #AC misaligned access"));
188
      exception(BX_AC_EXCEPTION, 0);
189
    }
190
#endif
191
    BX_NOTIFY_LIN_MEMORY_ACCESS(get_laddr(BX_SEG_REG_SS, offset), pAddr, 4, CPL, BX_WRITE, (Bit8u*) &data);
192
    pageWriteStampTable.decWriteStamp(pAddr, 4);
193
    WriteHostDWordToLittleEndian(hostPageAddr, data);
194
  }
195
  else {
196
    write_virtual_dword(BX_SEG_REG_SS, offset, data);
197
  }
198
}
199
 
200
void BX_CPP_AttrRegparmN(2) BX_CPU_C::stack_write_qword(bx_address offset, Bit64u data)
201
{
202
  bx_address espBiased = offset + BX_CPU_THIS_PTR espPageBias;
203
 
204
  if (espBiased >= BX_CPU_THIS_PTR espPageWindowSize) {
205
    stackPrefetch(offset, 8);
206
    espBiased = offset + BX_CPU_THIS_PTR espPageBias;
207
  }
208
 
209
  if (BX_CPU_THIS_PTR espHostPtr) {
210
    Bit64u *hostPageAddr = (Bit64u*)(BX_CPU_THIS_PTR espHostPtr + espBiased);
211
    bx_phy_address pAddr = BX_CPU_THIS_PTR pAddrStackPage + espBiased;
212
#if BX_CPU_LEVEL >= 4 && BX_SUPPORT_ALIGNMENT_CHECK
213
    if (BX_CPU_THIS_PTR alignment_check() && (pAddr & 7) != 0) {
214
      BX_ERROR(("stack_write_qword(): #AC misaligned access"));
215
      exception(BX_AC_EXCEPTION, 0);
216
    }
217
#endif
218
    BX_NOTIFY_LIN_MEMORY_ACCESS(get_laddr(BX_SEG_REG_SS, offset), pAddr, 8, CPL, BX_WRITE, (Bit8u*) &data);
219
    pageWriteStampTable.decWriteStamp(pAddr, 8);
220
    WriteHostQWordToLittleEndian(hostPageAddr, data);
221
  }
222
  else {
223
    write_virtual_qword(BX_SEG_REG_SS, offset, data);
224
  }
225
}
226
 
227
Bit8u BX_CPP_AttrRegparmN(1) BX_CPU_C::stack_read_byte(bx_address offset)
228
{
229
  bx_address espBiased = offset + BX_CPU_THIS_PTR espPageBias;
230
 
231
  if (espBiased >= BX_CPU_THIS_PTR espPageWindowSize) {
232
    stackPrefetch(offset, 1);
233
    espBiased = offset + BX_CPU_THIS_PTR espPageBias;
234
  }
235
 
236
  if (BX_CPU_THIS_PTR espHostPtr) {
237
    Bit8u *hostPageAddr = (Bit8u*)(BX_CPU_THIS_PTR espHostPtr + espBiased), data;
238
    data = *hostPageAddr;
239
    BX_NOTIFY_LIN_MEMORY_ACCESS(get_laddr(BX_SEG_REG_SS, offset),
240
        (BX_CPU_THIS_PTR pAddrStackPage + espBiased), 1, CPL, BX_READ, (Bit8u*) &data);
241
    return data;
242
  }
243
  else {
244
    return read_virtual_byte(BX_SEG_REG_SS, offset);
245
  }
246
}
247
 
248
Bit16u BX_CPP_AttrRegparmN(1) BX_CPU_C::stack_read_word(bx_address offset)
249
{
250
  bx_address espBiased = offset + BX_CPU_THIS_PTR espPageBias;
251
 
252
  if (espBiased >= BX_CPU_THIS_PTR espPageWindowSize) {
253
    stackPrefetch(offset, 2);
254
    espBiased = offset + BX_CPU_THIS_PTR espPageBias;
255
  }
256
 
257
  if (BX_CPU_THIS_PTR espHostPtr) {
258
    Bit16u *hostPageAddr = (Bit16u*)(BX_CPU_THIS_PTR espHostPtr + espBiased), data;
259
#if BX_CPU_LEVEL >= 4 && BX_SUPPORT_ALIGNMENT_CHECK
260
    if (BX_CPU_THIS_PTR alignment_check()) {
261
      bx_phy_address pAddr = BX_CPU_THIS_PTR pAddrStackPage + espBiased;
262
      if (pAddr & 1) {
263
        BX_ERROR(("stack_read_word(): #AC misaligned access"));
264
        exception(BX_AC_EXCEPTION, 0);
265
      }
266
    }
267
#endif
268
    ReadHostWordFromLittleEndian(hostPageAddr, data);
269
    BX_NOTIFY_LIN_MEMORY_ACCESS(get_laddr(BX_SEG_REG_SS, offset),
270
        (BX_CPU_THIS_PTR pAddrStackPage + espBiased), 2, CPL, BX_READ, (Bit8u*) &data);
271
    return data;
272
  }
273
  else {
274
    return read_virtual_word(BX_SEG_REG_SS, offset);
275
  }
276
}
277
 
278
Bit32u BX_CPP_AttrRegparmN(1) BX_CPU_C::stack_read_dword(bx_address offset)
279
{
280
  bx_address espBiased = offset + BX_CPU_THIS_PTR espPageBias;
281
 
282
  if (espBiased >= BX_CPU_THIS_PTR espPageWindowSize) {
283
    stackPrefetch(offset, 4);
284
    espBiased = offset + BX_CPU_THIS_PTR espPageBias;
285
  }
286
 
287
  if (BX_CPU_THIS_PTR espHostPtr) {
288
    Bit32u *hostPageAddr = (Bit32u*)(BX_CPU_THIS_PTR espHostPtr + espBiased), data;
289
#if BX_CPU_LEVEL >= 4 && BX_SUPPORT_ALIGNMENT_CHECK
290
    if (BX_CPU_THIS_PTR alignment_check()) {
291
      bx_phy_address pAddr = BX_CPU_THIS_PTR pAddrStackPage + espBiased;
292
      if (pAddr & 3) {
293
        BX_ERROR(("stack_read_dword(): #AC misaligned access"));
294
        exception(BX_AC_EXCEPTION, 0);
295
      }
296
    }
297
#endif
298
    ReadHostDWordFromLittleEndian(hostPageAddr, data);
299
    BX_NOTIFY_LIN_MEMORY_ACCESS(get_laddr(BX_SEG_REG_SS, offset),
300
        (BX_CPU_THIS_PTR pAddrStackPage + espBiased), 4, CPL, BX_READ, (Bit8u*) &data);
301
    return data;
302
  }
303
  else {
304
    return read_virtual_dword(BX_SEG_REG_SS, offset);
305
  }
306
}
307
 
308
Bit64u BX_CPP_AttrRegparmN(1) BX_CPU_C::stack_read_qword(bx_address offset)
309
{
310
  bx_address espBiased = offset + BX_CPU_THIS_PTR espPageBias;
311
 
312
  if (espBiased >= BX_CPU_THIS_PTR espPageWindowSize) {
313
    stackPrefetch(offset, 8);
314
    espBiased = offset + BX_CPU_THIS_PTR espPageBias;
315
  }
316
 
317
  if (BX_CPU_THIS_PTR espHostPtr) {
318
    Bit64u *hostPageAddr = (Bit64u*)(BX_CPU_THIS_PTR espHostPtr + espBiased), data;
319
#if BX_CPU_LEVEL >= 4 && BX_SUPPORT_ALIGNMENT_CHECK
320
    if (BX_CPU_THIS_PTR alignment_check()) {
321
      bx_phy_address pAddr = BX_CPU_THIS_PTR pAddrStackPage + espBiased;
322
      if (pAddr & 7) {
323
        BX_ERROR(("stack_read_qword(): #AC misaligned access"));
324
        exception(BX_AC_EXCEPTION, 0);
325
      }
326
    }
327
#endif
328
    ReadHostQWordFromLittleEndian(hostPageAddr, data);
329
    BX_NOTIFY_LIN_MEMORY_ACCESS(get_laddr(BX_SEG_REG_SS, offset),
330
        (BX_CPU_THIS_PTR pAddrStackPage + espBiased), 8, CPL, BX_READ, (Bit8u*) &data);
331
    return data;
332
  }
333
  else {
334
    return read_virtual_qword(BX_SEG_REG_SS, offset);
335
  }
336
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.