~ari-tczew/ubuntu/lucid/skyeye/sru-lp-464175

« back to all changes in this revision

Viewing changes to arch/mips/common/emul.c

  • Committer: Bazaar Package Importer
  • Author(s): Yu Guanghui
  • Date: 2007-02-09 20:24:29 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20070209202429-jknfb98t9ggaoz02
Tags: 1.2.1-2
Disable DBCT again.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#include "emul.h"
 
2
#include <stdlib.h>
 
3
 
 
4
extern MIPS_State* mstate;
 
5
/* Address decoder macros.
 
6
 * Bits 29, 30 and 31 of the virtual address select the user or kernel address spaces.
 
7
 */
 
8
int
 
9
vaddr_region(VA va)
 
10
{
 
11
        return bits(va, 31, 29); 
 
12
}
 
13
 
 
14
int 
 
15
vaddr_compat_region(UInt32 va)
 
16
 
17
        return bits(va, 31, 30); 
 
18
}
 
19
 
 
20
int 
 
21
get_random(MIPS_State* mstate) //Fix me: Shi yang 2006-08-10
 
22
{
 
23
        int wired = mstate->cp0[Wired];
 
24
        int free = tlb_size - wired;
 
25
        return (tlb_size - 1 - wired + (mstate->now - mstate->random_seed)) % free + wired;
 
26
}
 
27
 
 
28
void 
 
29
enter_kernel_mode(MIPS_State* mstate)
 
30
{       
 
31
        copy_bits(mstate->cp0[SR], (bits(mstate->cp0[SR], 3, 0) << 2), 5, 2); //Shi yang 2006-08-10
 
32
        clear_bits(mstate->cp0[SR], 1, 0); //Enter kernel mode
 
33
        mstate->mode = kmode;
 
34
}
 
35
 
 
36
void 
 
37
leave_kernel_mode(MIPS_State* mstate)
 
38
{
 
39
        copy_bits(mstate->cp0[SR], (bits(mstate->cp0[SR], 5, 2)), 3, 0);
 
40
        copy_bits(mstate->cp0[SR], (bits(mstate->cp0[SR], 3, 2) << 4), 5, 4); 
 
41
        if (bit(mstate->cp0[SR], 1) == 0)
 
42
                mstate->mode |= kmode; //From kernel mode to kernel mode
 
43
        else
 
44
                mstate->mode = umode; //From kernel mode to user mode
 
45
}
 
46
 
 
47
/* An ASID is represented by a 16 bit integer that is either a positive
 
48
 * (non-zero) ASID, complemented  if the G bit is also set. asid_match()
 
49
 * checks two ASIDs for equivalence. Yet another demonstration of the
 
50
 * versatility of exclusive-or. ;)
 
51
 */
 
52
int 
 
53
asid_match(Int16 asid1, Int16 asid2)
 
54
 
55
        return (asid1 ^ asid2) <= 0; 
 
56
}
 
57
 
 
58
 
 
59
/* Operations on the TLB lookup map. The map is a hash table indexed by a
 
60
 * hash value computed from the ASID and the bits of virtual page number
 
61
 * unaffected by any page mask. The result of the map lookup is a TLB
 
62
 * entry. The hash function doesn't provide an ideal distribution, but as
 
63
 * a minimum, it maintains a separate hash chain per ASID, and provides
 
64
 * good distribution at least for sparse address spaces.  The hash table
 
65
 * always has an extra entry pointing to an invalid page.
 
66
 */
 
67
 
 
68
int 
 
69
tlb_hash(VA va)
 
70
 
71
        return (bits(va, 31, 12) % tlb_map_size); 
 
72
}
 
73
 
 
74
int 
 
75
va_match(VA va1, VA va2)
 
76
 
77
        return !(va1 ^ va2); //Shi yang 2006-08-11 
 
78
}
 
79
 
 
80
// I-cache buffer operations.
 
81
 
 
82
int 
 
83
ibuf_match(PA pa, PA tag) //Shi yang 2006-08-10
 
84
 
85
        return ((pa >> log2_icache_line) ^ tag) == 0; 
 
86
}
 
87
 
 
88
// Some state information constants.
 
89
 
 
90
int 
 
91
allow_xinstr(MIPS_State* mstate) 
 
92
 
93
        return mstate->mode & (kmode|xmode); 
 
94
}
 
95
 
 
96
int 
 
97
branch_delay_slot(MIPS_State* mstate) //Shi yang 2006-08-10 
 
98
 
99
        return mstate->pipeline == branch_delay; 
 
100
}
 
101
 
 
102
void 
 
103
process_address_error(MIPS_State* mstate, int type, VA va)
 
104
{
 
105
        int exc = (type == data_store) ? EXC_AdES : EXC_AdEL;
 
106
        mstate->cp0[BadVAddr] = va;
 
107
        process_exception(mstate, exc, common_vector);
 
108
}
 
109
 
 
110
void 
 
111
process_tlb_refill(MIPS_State* mstate, int type, VA va)
 
112
{
 
113
        int exc = (type == data_store) ? EXC_TLBS : EXC_TLBL;
 
114
        int vec = tlb_refill_vector;
 
115
        mstate->cp0[BadVAddr] = va;
 
116
        mstate->cp0[Context] = copy_bits(mstate->cp0[Context],
 
117
                                         bits(mstate->cp0[BadVAddr], 31, 13), 20, 2); //Shi yang 2006-08-10
 
118
        mstate->cp0[EntryHi] = (va & (bitsmask(11, 0)))
 
119
                                | (bits(mstate->asid, 5, 0) << 6);
 
120
        process_exception(mstate, exc, vec);
 
121
}
 
122
 
 
123
void 
 
124
process_tlb_invalid(MIPS_State* mstate, int type, VA va)
 
125
{
 
126
        int exc = (type == data_store) ? EXC_TLBS : EXC_TLBL;
 
127
        mstate->cp0[BadVAddr] = va;
 
128
        mstate->cp0[Context] = copy_bits(mstate->cp0[Context],
 
129
                                         bits(mstate->cp0[BadVAddr], 31, 13), 20, 2); //Shi yang 2006-08-10
 
130
        mstate->cp0[EntryHi] = (va & (bitsmask(11, 0)))
 
131
                                | (bits(mstate->asid, 5, 0) << 6);
 
132
        process_exception(mstate, exc, common_vector);
 
133
}
 
134
 
 
135
void 
 
136
process_tlb_modified(MIPS_State* mstate, VA va)
 
137
{
 
138
        mstate->cp0[BadVAddr] = va;
 
139
        mstate->cp0[Context] = copy_bits(mstate->cp0[Context],
 
140
                                         bits(mstate->cp0[BadVAddr], 31, 13), 20, 2);
 
141
        mstate->cp0[EntryHi] = (va & (bitsmask(11, 0)))
 
142
                                | (bits(mstate->asid, 7, 0) << 6);
 
143
        process_exception(mstate, EXC_Mod, common_vector);
 
144
}
 
145
 
 
146
void 
 
147
process_bus_error(MIPS_State* mstate, int type)
 
148
{
 
149
        int exc = (type == instr_fetch) ? EXC_IBE : EXC_DBE;
 
150
        process_exception(mstate, exc, common_vector);
 
151
}
 
152
 
 
153
void 
 
154
process_integer_overflow(MIPS_State* mstate)
 
155
 
156
        process_exception(mstate,EXC_Ov, common_vector); 
 
157
}
 
158
 
 
159
void 
 
160
process_trap(MIPS_State* mstate)
 
161
{
 
162
        printf("Begin process_trap.\n");
 
163
        process_exception(mstate, EXC_Tr, common_vector); 
 
164
}
 
165
 
 
166
void 
 
167
process_syscall(MIPS_State* mstate)
 
168
 
169
        process_exception(mstate, EXC_Sys, common_vector); 
 
170
}
 
171
 
 
172
void 
 
173
process_breakpoint(MIPS_State* mstate)
 
174
 
175
        process_exception(mstate, EXC_Bp, common_vector); 
 
176
}
 
177
 
 
178
void 
 
179
process_reserved_instruction(MIPS_State* mstate)
 
180
 
181
        process_exception(mstate, EXC_RI, common_vector); 
 
182
}
 
183
 
 
184
void 
 
185
process_coprocessor_unusable(MIPS_State* mstate, int c)
 
186
 
187
        process_exception(mstate, EXC_CpU | (c << (Cause_CE_First)), common_vector); 
 
188
}
 
189
 
 
190
void 
 
191
process_fp_exception(MIPS_State* mstate)
 
192
 
193
        process_exception(mstate,EXC_FPE, common_vector); 
 
194
}
 
195
 
 
196
void 
 
197
process_interrupt(MIPS_State* mstate)
 
198
 
199
        process_exception(mstate,EXC_Int, common_vector); 
 
200
}
 
201
 
 
202
/* Endianess parameters. The data received from the memory bus is always
 
203
 * in the host byte order, and uses host byte addressing.
 
204
 */
 
205
int 
 
206
big_endian_mem(MIPS_State* mstate)
 
207
 
208
        return bit(mstate->cp0[Config], Config_BE); 
 
209
}
 
210
 
 
211
int 
 
212
reverse_endian(MIPS_State* mstate) 
 
213
 
214
        return mstate->mode & rmode; 
 
215
}
 
216
 
 
217
int 
 
218
big_endian_cpu(MIPS_State* mstate) 
 
219
 
220
        return mstate->mode & bmode; 
 
221
}
 
222
 
 
223
UInt32 
 
224
swizzle_word(UInt32 x, UInt32 addr) //Fix me: Shi yang
 
225
{
 
226
        return x; //Shi yang 2006-08-18
 
227
        
 
228
}
 
229
 
 
230
UInt8  
 
231
swizzle_byte(UInt32 x, UInt32 addr)
 
232
{
 
233
        int offset;
 
234
        offset = (((UInt32) mstate->bigendSig * 3) ^ (addr & 3)) << 3; //Shi yang 2006-08-18
 
235
        return (x >> offset) & 0xffL;
 
236
}
 
237
 
 
238
UInt16 
 
239
swizzle_doublebyte(UInt32 x, UInt32 addr)
 
240
{
 
241
        int offset;
 
242
        offset = (((UInt32)mstate->bigendSig * 2) ^ (addr & 2)) << 3; //Shi yang 2006-08-18
 
243
        return (x >> offset) & 0xffffL;
 
244
        
 
245
}
 
246
 
 
247
inline Int32 
 
248
sign_extend_Int32(Int32 x, int n)
 
249
{
 
250
        if (((Int32)-1 >> 1) < 0) {
 
251
                // Host platform does arithmetic right shifts.
 
252
                Int32 y = x;
 
253
                return y << (8 * sizeof(Int32) - n) >> (8 * sizeof(Int32) - n);
 
254
        } else if (n < 8 * sizeof(Int32)) {
 
255
                // We have to manually patch the high-order bits.
 
256
                if (bit(x, n - 1))
 
257
                        return set_bits(x, 8 * sizeof(Int32) - 1, n);
 
258
                else
 
259
                        return clear_bits(x, 8 * sizeof(Int32) - 1, n);
 
260
        }
 
261
}
 
262
 
 
263
inline UInt32 
 
264
sign_extend_UInt32(UInt32 x, int n)
 
265
{
 
266
        if (((UInt32)-1 >> 1) < 0) {
 
267
                // Host platform does arithmetic right shifts.
 
268
                UInt32 y = x;
 
269
                return y << (8 * sizeof(UInt32) - n) >> (8 * sizeof(UInt32) - n);
 
270
        } else if (n < 8 * sizeof(UInt32)) {
 
271
                // We have to manually patch the high-order bits.
 
272
                if (bit(x, n - 1))
 
273
                        return set_bits(x, 8 * sizeof(UInt32) - 1, n);
 
274
                else
 
275
                        return clear_bits(x, 8 * sizeof(UInt32) - 1, n);
 
276
 
 
277
        }
 
278
}
 
279
 
 
280
inline Int64 
 
281
sign_extend_Int64(Int64 x, int n)
 
282
{
 
283
        if (((Int64)-1 >> 1) < 0) {
 
284
                // Host platform does arithmetic right shifts.
 
285
                Int64 y = x;
 
286
                return y << (8 * sizeof(Int64) - n) >> (8 * sizeof(Int64) - n);
 
287
        } else if (n < 8 * sizeof(Int64)) {
 
288
                // We have to manually patch the high-order bits.
 
289
                if (bit(x, n - 1))
 
290
                        return set_bits(x, 8 * sizeof(Int64) - 1, n);
 
291
                else
 
292
                        return clear_bits(x, 8 * sizeof(Int64) - 1, n);
 
293
        }
 
294
}
 
295
 
 
296
inline UInt64 
 
297
sign_extend_UInt64(UInt64 x, int n)
 
298
{
 
299
        if (((UInt64)-1 >> 1) < 0) {
 
300
                // Host platform does arithmetic right shifts.
 
301
                UInt64 y = x;
 
302
                return y << (8 * sizeof(UInt64) - n) >> (8 * sizeof(UInt64) - n);
 
303
        } else if (n < 8 * sizeof(UInt64)) {
 
304
                // We have to manually patch the high-order bits.
 
305
                if (bit(x, n - 1))
 
306
                        return set_bits(x, 8 * sizeof(UInt64) - 1, n);
 
307
                else
 
308
                        return clear_bits(x, 8 * sizeof(UInt64) - 1, n);
 
309
        }
 
310
}
 
311
 
 
312
// Specialisations for 32 and 64 bit types.
 
313
 
 
314
inline void 
 
315
divide_Int32(Int32 a, Int32 b)
 
316
{
 
317
        if (32 <= sizeof(int)) {
 
318
                div_t r = div((int)(a), (int)(b));
 
319
                DivResult(r.quot, r.rem);
 
320
        } else {
 
321
                ldiv_t r = ldiv((long)(a),(long)(b));
 
322
                DivResult(r.quot, r.rem);
 
323
        }
 
324
}
 
325
 
 
326
inline void 
 
327
divide_UInt32(UInt32 a, UInt32 b)
 
328
{
 
329
        if (32 < sizeof(long)) {
 
330
                ldiv_t r = ldiv((long)(a), (long)(b));
 
331
                DivResult(r.quot, r.rem);
 
332
        } else {
 
333
                DivResult(a / b, a % b);
 
334
        }
 
335
}
 
336
 
 
337
inline void 
 
338
divide_Int64(Int64 a, Int64 b)
 
339
{
 
340
        if (64 <= sizeof(long)) {
 
341
                ldiv_t r = ldiv((long)(a), (long)(b));
 
342
                DivResult(r.quot, r.rem);
 
343
        } else if ((Int64)(-2) % (Int64)(3) < 0) 
 
344
                // Hardware division rounds towards zero.
 
345
                DivResult(a / b, a % b)
 
346
        else {
 
347
                // Hardware division rounds towards negative infinity, so fix it.
 
348
                if ((a ^ b) >= 0)
 
349
                        DivResult(a / b, a % b)
 
350
                else if (a < 0)
 
351
                        DivResult(-(-a / b), -(-a % b))
 
352
                else 
 
353
                        DivResult(-(a / -b), -(a % -b))
 
354
        }
 
355
}