Commit | Line | Data |
---|---|---|
c906108c SS |
1 | /* Simulator for the Hitachi SH architecture. |
2 | ||
3 | Written by Steve Chamberlain of Cygnus Support. | |
4 | sac@cygnus.com | |
5 | ||
6 | This file is part of SH sim | |
7 | ||
8 | ||
9 | THIS SOFTWARE IS NOT COPYRIGHTED | |
10 | ||
11 | Cygnus offers the following for use in the public domain. Cygnus | |
12 | makes no warranty with regard to the software or it's performance | |
13 | and the user accepts the software "AS IS" with all faults. | |
14 | ||
15 | CYGNUS DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED, WITH REGARD TO | |
16 | THIS SOFTWARE INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |
17 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. | |
18 | ||
19 | */ | |
20 | ||
21 | #include "config.h" | |
22 | ||
23 | #include <signal.h> | |
24 | #ifdef HAVE_UNISTD_H | |
25 | #include <unistd.h> | |
26 | #endif | |
27 | ||
28 | #include "sysdep.h" | |
29 | #include "bfd.h" | |
30 | #include "callback.h" | |
31 | #include "remote-sim.h" | |
32 | ||
33 | /* This file is local - if newlib changes, then so should this. */ | |
34 | #include "syscall.h" | |
35 | ||
36 | #include <math.h> | |
37 | ||
38 | #ifdef _WIN32 | |
39 | #include <float.h> /* Needed for _isnan() */ | |
40 | #define isnan _isnan | |
41 | #endif | |
42 | ||
43 | #ifndef SIGBUS | |
44 | #define SIGBUS SIGSEGV | |
45 | #endif | |
46 | ||
47 | #ifndef SIGQUIT | |
48 | #define SIGQUIT SIGTERM | |
49 | #endif | |
50 | ||
51 | #ifndef SIGTRAP | |
52 | #define SIGTRAP 5 | |
53 | #endif | |
54 | ||
55 | #define O_RECOMPILE 85 | |
56 | #define DEFINE_TABLE | |
57 | #define DISASSEMBLER_TABLE | |
58 | ||
7a292a7a SS |
59 | /* Define the rate at which the simulator should poll the host |
60 | for a quit. */ | |
61 | #define POLL_QUIT_INTERVAL 0x60000 | |
62 | ||
c906108c SS |
63 | typedef union |
64 | { | |
65 | ||
66 | struct | |
67 | { | |
7a292a7a SS |
68 | /* On targets like sparc-sun-solaris, fregs will be aligned on a 64 bit |
69 | boundary (because of the d member). To avoid padding between | |
70 | registers - which whould make the job of sim_fetch_register harder, | |
71 | we add padding at the start. */ | |
c906108c SS |
72 | int pad_dummy; |
73 | int regs[16]; | |
74 | int pc; | |
75 | int pr; | |
76 | ||
77 | int gbr; | |
78 | int vbr; | |
79 | int mach; | |
80 | int macl; | |
81 | ||
82 | int sr; | |
83 | ||
84 | int fpul; | |
85 | ||
86 | int fpscr; | |
87 | ||
88 | /* sh3e */ | |
89 | union fregs_u | |
90 | { | |
91 | float f[16]; | |
92 | double d[8]; | |
93 | int i[16]; | |
94 | } | |
7a292a7a | 95 | fregs[2]; |
c906108c SS |
96 | |
97 | int ssr; | |
98 | int spc; | |
99 | /* sh3 */ | |
100 | int bank[2][8]; | |
101 | ||
102 | int ticks; | |
103 | int stalls; | |
104 | int memstalls; | |
105 | int cycles; | |
106 | int insts; | |
107 | ||
108 | int prevlock; | |
109 | int thislock; | |
110 | int exception; | |
111 | ||
112 | int end_of_registers; | |
113 | ||
114 | int msize; | |
115 | #define PROFILE_FREQ 1 | |
116 | #define PROFILE_SHIFT 2 | |
117 | int profile; | |
118 | unsigned short *profile_hist; | |
119 | unsigned char *memory; | |
120 | } | |
121 | asregs; | |
122 | int asints[40]; | |
123 | } saved_state_type; | |
124 | ||
125 | saved_state_type saved_state; | |
126 | ||
127 | ||
128 | /* These variables are at file scope so that functions other than | |
129 | sim_resume can use the fetch/store macros */ | |
130 | ||
131 | static int target_little_endian; | |
132 | static int host_little_endian; | |
133 | ||
134 | #if 1 | |
135 | static int maskl = ~0; | |
136 | static int maskw = ~0; | |
137 | #endif | |
138 | ||
139 | static SIM_OPEN_KIND sim_kind; | |
140 | static char *myname; | |
141 | ||
142 | ||
143 | /* Short hand definitions of the registers */ | |
144 | ||
145 | #define SBIT(x) ((x)&sbit) | |
146 | #define R0 saved_state.asregs.regs[0] | |
147 | #define Rn saved_state.asregs.regs[n] | |
148 | #define Rm saved_state.asregs.regs[m] | |
149 | #define UR0 (unsigned int)(saved_state.asregs.regs[0]) | |
150 | #define UR (unsigned int)R | |
151 | #define UR (unsigned int)R | |
152 | #define SR0 saved_state.asregs.regs[0] | |
153 | #define GBR saved_state.asregs.gbr | |
154 | #define VBR saved_state.asregs.vbr | |
155 | #define SSR saved_state.asregs.ssr | |
156 | #define SPC saved_state.asregs.spc | |
157 | #define MACH saved_state.asregs.mach | |
158 | #define MACL saved_state.asregs.macl | |
159 | #define FPUL saved_state.asregs.fpul | |
160 | ||
161 | #define PC pc | |
162 | ||
163 | ||
164 | ||
165 | /* Alternate bank of registers r0-r6 */ | |
166 | ||
167 | /* Note: code controling SR handles flips between BANK0 and BANK1 */ | |
168 | #define Rn_BANK(n) (saved_state.asregs.bank[!SR_RB][(n)]) | |
169 | #define SET_Rn_BANK(n, EXP) do { saved_state.asregs.bank[!SR_RB][(n)] = (EXP); } while (0) | |
170 | ||
171 | ||
172 | /* Manipulate SR */ | |
173 | ||
174 | #define SR_MASK_M (1 << 9) | |
175 | #define SR_MASK_Q (1 << 8) | |
176 | #define SR_MASK_I (0xf << 4) | |
177 | #define SR_MASK_S (1 << 1) | |
178 | #define SR_MASK_T (1 << 0) | |
179 | ||
180 | #define SR_MASK_BL (1 << 28) | |
181 | #define SR_MASK_RB (1 << 29) | |
182 | #define SR_MASK_MD (1 << 30) | |
183 | ||
184 | #define M ((saved_state.asregs.sr & SR_MASK_M) != 0) | |
185 | #define Q ((saved_state.asregs.sr & SR_MASK_Q) != 0) | |
186 | #define S ((saved_state.asregs.sr & SR_MASK_S) != 0) | |
187 | #define T ((saved_state.asregs.sr & SR_MASK_T) != 0) | |
188 | ||
189 | #define SR_BL ((saved_state.asregs.sr & SR_MASK_BL) != 0) | |
190 | #define SR_RB ((saved_state.asregs.sr & SR_MASK_RB) != 0) | |
191 | #define SR_MD ((saved_state.asregs.sr & SR_MASK_MD) != 0) | |
192 | ||
193 | /* Note: don't use this for privileged bits */ | |
194 | #define SET_SR_BIT(EXP, BIT) \ | |
195 | do { \ | |
196 | if ((EXP) & 1) \ | |
197 | saved_state.asregs.sr |= (BIT); \ | |
198 | else \ | |
199 | saved_state.asregs.sr &= ~(BIT); \ | |
200 | } while (0) | |
201 | ||
202 | #define SET_SR_M(EXP) SET_SR_BIT ((EXP), SR_MASK_M) | |
203 | #define SET_SR_Q(EXP) SET_SR_BIT ((EXP), SR_MASK_Q) | |
204 | #define SET_SR_S(EXP) SET_SR_BIT ((EXP), SR_MASK_S) | |
205 | #define SET_SR_T(EXP) SET_SR_BIT ((EXP), SR_MASK_T) | |
206 | ||
207 | #define GET_SR() (saved_state.asregs.sr - 0) | |
208 | #define SET_SR(x) set_sr (x) | |
209 | static void | |
210 | set_sr (new_sr) | |
211 | int new_sr; | |
212 | { | |
213 | /* do we need to swap banks */ | |
214 | int old_gpr = (SR_MD ? !SR_RB : 0); | |
215 | int new_gpr = ((new_sr & SR_MASK_MD) | |
216 | ? (new_sr & SR_MASK_RB) == 0 | |
217 | : 0); | |
218 | if (old_gpr != new_gpr) | |
219 | { | |
220 | int i; | |
221 | for (i = 0; i < 8; i++) | |
222 | { | |
223 | saved_state.asregs.bank[old_gpr][i] = saved_state.asregs.regs[i]; | |
224 | saved_state.asregs.regs[i] = saved_state.asregs.bank[new_gpr][i]; | |
225 | } | |
226 | } | |
227 | } | |
228 | ||
229 | ||
230 | /* Manipulate FPSCR */ | |
231 | ||
7a292a7a SS |
232 | #define FPSCR_MASK_FR (1 << 21) |
233 | #define FPSCR_MASK_SZ (1 << 20) | |
234 | #define FPSCR_MASK_PR (1 << 19) | |
235 | ||
236 | #define FPSCR_FR ((GET_FPSCR() & FPSCR_MASK_FR) != 0) | |
237 | #define FPSCR_SZ ((GET_FPSCR() & FPSCR_MASK_SZ) != 0) | |
238 | #define FPSCR_PR ((GET_FPSCR() & FPSCR_MASK_PR) != 0) | |
239 | ||
240 | static void | |
241 | set_fpscr1 (x) | |
242 | int x; | |
243 | { | |
244 | int old = saved_state.asregs.fpscr; | |
245 | saved_state.asregs.fpscr = (x); | |
246 | /* swap the floating point register banks */ | |
247 | if ((saved_state.asregs.fpscr ^ old) & FPSCR_MASK_FR) | |
248 | { | |
249 | union fregs_u tmpf = saved_state.asregs.fregs[0]; | |
250 | saved_state.asregs.fregs[0] = saved_state.asregs.fregs[1]; | |
251 | saved_state.asregs.fregs[1] = tmpf; | |
252 | } | |
253 | } | |
254 | ||
c906108c | 255 | #define GET_FPSCR() (saved_state.asregs.fpscr) |
7a292a7a SS |
256 | #define SET_FPSCR(x) \ |
257 | do { \ | |
258 | set_fpscr1 (x); \ | |
259 | } while (0) | |
c906108c SS |
260 | |
261 | ||
262 | int | |
263 | fail () | |
264 | { | |
265 | abort (); | |
266 | } | |
267 | ||
7a292a7a SS |
268 | int |
269 | special_address (addr, bits_written, data) | |
270 | void *addr; | |
271 | int bits_written, data; | |
272 | { | |
273 | if ((unsigned) addr >> 24 == 0xf0 && bits_written == 32 && (data & 1) == 0) | |
274 | /* This invalidates (if not associative) or might invalidate | |
275 | (if associative) an instruction cache line. This is used for | |
276 | trampolines. Since we don't simulate the cache, this is a no-op | |
277 | as far as the simulator is concerned. */ | |
278 | return 1; | |
279 | /* We can't do anything useful with the other stuff, so fail. */ | |
280 | return 0; | |
281 | } | |
282 | ||
c906108c SS |
283 | /* This function exists solely for the purpose of setting a breakpoint to |
284 | catch simulated bus errors when running the simulator under GDB. */ | |
285 | ||
286 | void | |
287 | bp_holder () | |
288 | { | |
289 | } | |
290 | ||
291 | /* FIXME: sim_resume should be renamed to sim_engine_run. sim_resume | |
292 | being implemented by ../common/sim_resume.c and the below should | |
293 | make a call to sim_engine_halt */ | |
294 | ||
7a292a7a SS |
295 | #define BUSERROR(addr, mask, bits_written, data) \ |
296 | if (addr & ~mask) \ | |
297 | { \ | |
298 | if (special_address (addr, bits_written, data)) \ | |
299 | return; \ | |
300 | saved_state.asregs.exception = SIGBUS; \ | |
301 | bp_holder (); \ | |
302 | } | |
c906108c SS |
303 | |
304 | /* Define this to enable register lifetime checking. | |
305 | The compiler generates "add #0,rn" insns to mark registers as invalid, | |
306 | the simulator uses this info to call fail if it finds a ref to an invalid | |
307 | register before a def | |
308 | ||
309 | #define PARANOID | |
310 | */ | |
311 | ||
312 | #ifdef PARANOID | |
313 | int valid[16]; | |
314 | #define CREF(x) if(!valid[x]) fail(); | |
315 | #define CDEF(x) valid[x] = 1; | |
316 | #define UNDEF(x) valid[x] = 0; | |
317 | #else | |
318 | #define CREF(x) | |
319 | #define CDEF(x) | |
320 | #define UNDEF(x) | |
321 | #endif | |
322 | ||
323 | static void parse_and_set_memory_size PARAMS ((char *str)); | |
324 | ||
325 | static int IOMEM PARAMS ((int addr, int write, int value)); | |
326 | ||
327 | static host_callback *callback; | |
328 | ||
329 | ||
330 | ||
331 | /* Floating point registers */ | |
332 | ||
7a292a7a SS |
333 | #define DR(n) (get_dr (n)) |
334 | static double | |
335 | get_dr (n) | |
336 | int n; | |
337 | { | |
338 | n = (n & ~1); | |
339 | if (host_little_endian) | |
340 | { | |
341 | union | |
342 | { | |
343 | int i[2]; | |
344 | double d; | |
345 | } dr; | |
346 | dr.i[1] = saved_state.asregs.fregs[0].i[n + 0]; | |
347 | dr.i[0] = saved_state.asregs.fregs[0].i[n + 1]; | |
348 | return dr.d; | |
349 | } | |
350 | else | |
351 | return (saved_state.asregs.fregs[0].d[n >> 1]); | |
352 | } | |
353 | ||
354 | #define SET_DR(n, EXP) set_dr ((n), (EXP)) | |
355 | static void | |
356 | set_dr (n, exp) | |
357 | int n; | |
358 | double exp; | |
359 | { | |
360 | n = (n & ~1); | |
361 | if (host_little_endian) | |
362 | { | |
363 | union | |
364 | { | |
365 | int i[2]; | |
366 | double d; | |
367 | } dr; | |
368 | dr.d = exp; | |
369 | saved_state.asregs.fregs[0].i[n + 0] = dr.i[1]; | |
370 | saved_state.asregs.fregs[0].i[n + 1] = dr.i[0]; | |
371 | } | |
372 | else | |
373 | saved_state.asregs.fregs[0].d[n >> 1] = exp; | |
374 | } | |
375 | ||
376 | #define SET_FI(n,EXP) (saved_state.asregs.fregs[0].i[(n)] = (EXP)) | |
377 | #define FI(n) (saved_state.asregs.fregs[0].i[(n)]) | |
c906108c | 378 | |
7a292a7a SS |
379 | #define FR(n) (saved_state.asregs.fregs[0].f[(n)]) |
380 | #define SET_FR(n,EXP) (saved_state.asregs.fregs[0].f[(n)] = (EXP)) | |
c906108c | 381 | |
7a292a7a SS |
382 | #define XD_TO_XF(n) ((((n) & 1) << 5) | ((n) & 0x1e)) |
383 | #define XF(n) (saved_state.asregs.fregs[(n) >> 5].i[(n) & 0x1f]) | |
384 | #define SET_XF(n,EXP) (saved_state.asregs.fregs[(n) >> 5].i[(n) & 0x1f] = (EXP)) | |
385 | ||
386 | ||
387 | #define FP_OP(n, OP, m) \ | |
388 | { \ | |
389 | if (FPSCR_PR) \ | |
390 | { \ | |
391 | if (((n) & 1) || ((m) & 1)) \ | |
392 | saved_state.asregs.exception = SIGILL; \ | |
393 | else \ | |
394 | SET_DR(n, (DR(n) OP DR(m))); \ | |
395 | } \ | |
396 | else \ | |
397 | SET_FR(n, (FR(n) OP FR(m))); \ | |
398 | } while (0) | |
399 | ||
400 | #define FP_UNARY(n, OP) \ | |
401 | { \ | |
402 | if (FPSCR_PR) \ | |
403 | { \ | |
404 | if ((n) & 1) \ | |
405 | saved_state.asregs.exception = SIGILL; \ | |
406 | else \ | |
407 | SET_DR(n, (OP (DR(n)))); \ | |
408 | } \ | |
409 | else \ | |
410 | SET_FR(n, (OP (FR(n)))); \ | |
411 | } while (0) | |
412 | ||
413 | #define FP_CMP(n, OP, m) \ | |
414 | { \ | |
415 | if (FPSCR_PR) \ | |
416 | { \ | |
417 | if (((n) & 1) || ((m) & 1)) \ | |
418 | saved_state.asregs.exception = SIGILL; \ | |
419 | else \ | |
420 | SET_SR_T (DR(n) OP DR(m)); \ | |
421 | } \ | |
422 | else \ | |
423 | SET_SR_T (FR(n) OP FR(m)); \ | |
424 | } while (0) | |
c906108c SS |
425 | |
426 | ||
427 | ||
428 | static void INLINE | |
429 | wlat_little (memory, x, value, maskl) | |
430 | unsigned char *memory; | |
431 | { | |
432 | int v = value; | |
433 | unsigned char *p = memory + ((x) & maskl); | |
7a292a7a | 434 | BUSERROR(x, maskl, 32, v); |
c906108c SS |
435 | p[3] = v >> 24; |
436 | p[2] = v >> 16; | |
437 | p[1] = v >> 8; | |
438 | p[0] = v; | |
439 | } | |
440 | ||
441 | static void INLINE | |
442 | wwat_little (memory, x, value, maskw) | |
443 | unsigned char *memory; | |
444 | { | |
445 | int v = value; | |
446 | unsigned char *p = memory + ((x) & maskw); | |
7a292a7a | 447 | BUSERROR(x, maskw, 16, v); |
c906108c SS |
448 | |
449 | p[1] = v >> 8; | |
450 | p[0] = v; | |
451 | } | |
452 | ||
453 | static void INLINE | |
454 | wbat_any (memory, x, value, maskb) | |
455 | unsigned char *memory; | |
456 | { | |
457 | unsigned char *p = memory + (x & maskb); | |
458 | if (x > 0x5000000) | |
459 | IOMEM (x, 1, value); | |
7a292a7a | 460 | BUSERROR(x, maskb, 8, value); |
c906108c SS |
461 | |
462 | p[0] = value; | |
463 | } | |
464 | ||
465 | static void INLINE | |
466 | wlat_big (memory, x, value, maskl) | |
467 | unsigned char *memory; | |
468 | { | |
469 | int v = value; | |
470 | unsigned char *p = memory + ((x) & maskl); | |
7a292a7a | 471 | BUSERROR(x, maskl, 32, v); |
c906108c SS |
472 | |
473 | p[0] = v >> 24; | |
474 | p[1] = v >> 16; | |
475 | p[2] = v >> 8; | |
476 | p[3] = v; | |
477 | } | |
478 | ||
479 | static void INLINE | |
480 | wwat_big (memory, x, value, maskw) | |
481 | unsigned char *memory; | |
482 | { | |
483 | int v = value; | |
484 | unsigned char *p = memory + ((x) & maskw); | |
7a292a7a | 485 | BUSERROR(x, maskw, 16, v); |
c906108c SS |
486 | |
487 | p[0] = v >> 8; | |
488 | p[1] = v; | |
489 | } | |
490 | ||
491 | static void INLINE | |
492 | wbat_big (memory, x, value, maskb) | |
493 | unsigned char *memory; | |
494 | { | |
495 | unsigned char *p = memory + (x & maskb); | |
7a292a7a | 496 | BUSERROR(x, maskb, 8, value); |
c906108c SS |
497 | |
498 | if (x > 0x5000000) | |
499 | IOMEM (x, 1, value); | |
500 | p[0] = value; | |
501 | } | |
502 | ||
503 | /* Read functions */ | |
504 | ||
505 | static int INLINE | |
506 | rlat_little (memory, x, maskl) | |
507 | unsigned char *memory; | |
508 | { | |
509 | unsigned char *p = memory + ((x) & maskl); | |
7a292a7a | 510 | BUSERROR(x, maskl, -32, -1); |
c906108c SS |
511 | |
512 | return (p[3] << 24) | (p[2] << 16) | (p[1] << 8) | p[0]; | |
513 | } | |
514 | ||
515 | static int INLINE | |
516 | rwat_little (memory, x, maskw) | |
517 | unsigned char *memory; | |
518 | { | |
519 | unsigned char *p = memory + ((x) & maskw); | |
7a292a7a | 520 | BUSERROR(x, maskw, -16, -1); |
c906108c SS |
521 | |
522 | return (p[1] << 8) | p[0]; | |
523 | } | |
524 | ||
525 | static int INLINE | |
526 | rbat_any (memory, x, maskb) | |
527 | unsigned char *memory; | |
528 | { | |
529 | unsigned char *p = memory + ((x) & maskb); | |
7a292a7a | 530 | BUSERROR(x, maskb, -8, -1); |
c906108c SS |
531 | |
532 | return p[0]; | |
533 | } | |
534 | ||
535 | static int INLINE | |
536 | rlat_big (memory, x, maskl) | |
537 | unsigned char *memory; | |
538 | { | |
539 | unsigned char *p = memory + ((x) & maskl); | |
7a292a7a | 540 | BUSERROR(x, maskl, -32, -1); |
c906108c SS |
541 | |
542 | return (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]; | |
543 | } | |
544 | ||
545 | static int INLINE | |
546 | rwat_big (memory, x, maskw) | |
547 | unsigned char *memory; | |
548 | { | |
549 | unsigned char *p = memory + ((x) & maskw); | |
7a292a7a | 550 | BUSERROR(x, maskw, -16, -1); |
c906108c SS |
551 | |
552 | return (p[0] << 8) | p[1]; | |
553 | } | |
554 | ||
555 | #define RWAT(x) (little_endian ? rwat_little(memory, x, maskw): rwat_big(memory, x, maskw)) | |
556 | #define RLAT(x) (little_endian ? rlat_little(memory, x, maskl): rlat_big(memory, x, maskl)) | |
557 | #define RBAT(x) (rbat_any (memory, x, maskb)) | |
558 | #define WWAT(x,v) (little_endian ? wwat_little(memory, x, v, maskw): wwat_big(memory, x, v, maskw)) | |
559 | #define WLAT(x,v) (little_endian ? wlat_little(memory, x, v, maskl): wlat_big(memory, x, v, maskl)) | |
560 | #define WBAT(x,v) (wbat_any (memory, x, v, maskb)) | |
561 | ||
562 | #define RUWAT(x) (RWAT(x) & 0xffff) | |
563 | #define RSWAT(x) ((short)(RWAT(x))) | |
564 | #define RSBAT(x) (SEXT(RBAT(x))) | |
565 | ||
7a292a7a SS |
566 | #define RDAT(x, n) (do_rdat (memory, (x), (n), (little_endian))) |
567 | static int | |
568 | do_rdat (memory, x, n, little_endian) | |
569 | char *memory; | |
570 | int x; | |
571 | int n; | |
572 | int little_endian; | |
573 | { | |
574 | int f0; | |
575 | int f1; | |
576 | int i = (n & 1); | |
577 | int j = (n & ~1); | |
578 | if (little_endian) | |
579 | { | |
580 | f0 = rlat_little (memory, x + 0, maskl); | |
581 | f1 = rlat_little (memory, x + 4, maskl); | |
582 | } | |
583 | else | |
584 | { | |
585 | f0 = rlat_big (memory, x + 0, maskl); | |
586 | f1 = rlat_big (memory, x + 4, maskl); | |
587 | } | |
588 | saved_state.asregs.fregs[i].i[(j + 0)] = f0; | |
589 | saved_state.asregs.fregs[i].i[(j + 1)] = f1; | |
590 | return 0; | |
591 | } | |
c906108c | 592 | |
7a292a7a SS |
593 | #define WDAT(x, n) (do_wdat (memory, (x), (n), (little_endian))) |
594 | static int | |
595 | do_wdat (memory, x, n, little_endian) | |
596 | char *memory; | |
597 | int x; | |
598 | int n; | |
599 | int little_endian; | |
600 | { | |
601 | int f0; | |
602 | int f1; | |
603 | int i = (n & 1); | |
604 | int j = (n & ~1); | |
605 | f0 = saved_state.asregs.fregs[i].i[(j + 0)]; | |
606 | f1 = saved_state.asregs.fregs[i].i[(j + 1)]; | |
607 | if (little_endian) | |
608 | { | |
609 | wlat_little (memory, (x + 0), f0, maskl); | |
610 | wlat_little (memory, (x + 4), f1, maskl); | |
611 | } | |
612 | else | |
613 | { | |
614 | wlat_big (memory, (x + 0), f0, maskl); | |
615 | wlat_big (memory, (x + 4), f1, maskl); | |
616 | } | |
617 | return 0; | |
618 | } | |
c906108c SS |
619 | |
620 | ||
621 | #define MA(n) do { memstalls += (((pc & 3) != 0) ? (n) : ((n) - 1)); } while (0) | |
622 | ||
623 | #define SEXT(x) (((x & 0xff) ^ (~0x7f))+0x80) | |
624 | #define SEXT12(x) (((x & 0xfff) ^ 0x800) - 0x800) | |
625 | #define SEXTW(y) ((int)((short)y)) | |
626 | ||
627 | #define Delay_Slot(TEMPPC) iword = RUWAT(TEMPPC); goto top; | |
628 | ||
629 | int empty[16]; | |
630 | ||
631 | #define L(x) thislock = x; | |
632 | #define TL(x) if ((x) == prevlock) stalls++; | |
633 | #define TB(x,y) if ((x) == prevlock || (y)==prevlock) stalls++; | |
634 | ||
635 | #if defined(__GO32__) || defined(_WIN32) | |
636 | int sim_memory_size = 19; | |
637 | #else | |
638 | int sim_memory_size = 24; | |
639 | #endif | |
640 | ||
641 | static int sim_profile_size = 17; | |
642 | static int nsamples; | |
643 | ||
644 | #undef TB | |
645 | #define TB(x,y) | |
646 | ||
647 | #define SMR1 (0x05FFFEC8) /* Channel 1 serial mode register */ | |
648 | #define BRR1 (0x05FFFEC9) /* Channel 1 bit rate register */ | |
649 | #define SCR1 (0x05FFFECA) /* Channel 1 serial control register */ | |
650 | #define TDR1 (0x05FFFECB) /* Channel 1 transmit data register */ | |
651 | #define SSR1 (0x05FFFECC) /* Channel 1 serial status register */ | |
652 | #define RDR1 (0x05FFFECD) /* Channel 1 receive data register */ | |
653 | ||
654 | #define SCI_RDRF 0x40 /* Recieve data register full */ | |
655 | #define SCI_TDRE 0x80 /* Transmit data register empty */ | |
656 | ||
657 | static int | |
658 | IOMEM (addr, write, value) | |
659 | int addr; | |
660 | int write; | |
661 | int value; | |
662 | { | |
663 | if (write) | |
664 | { | |
665 | switch (addr) | |
666 | { | |
667 | case TDR1: | |
668 | if (value != '\r') | |
669 | { | |
670 | putchar (value); | |
671 | fflush (stdout); | |
672 | } | |
673 | break; | |
674 | } | |
675 | } | |
676 | else | |
677 | { | |
678 | switch (addr) | |
679 | { | |
680 | case RDR1: | |
681 | return getchar (); | |
682 | } | |
683 | } | |
684 | return 0; | |
685 | } | |
686 | ||
687 | static int | |
688 | get_now () | |
689 | { | |
690 | return time ((long *) 0); | |
691 | } | |
692 | ||
693 | static int | |
694 | now_persec () | |
695 | { | |
696 | return 1; | |
697 | } | |
698 | ||
699 | static FILE *profile_file; | |
700 | ||
701 | static void | |
702 | swap (memory, n) | |
703 | unsigned char *memory; | |
704 | int n; | |
705 | { | |
706 | int little_endian = target_little_endian; | |
707 | WLAT (0, n); | |
708 | } | |
709 | ||
710 | static void | |
711 | swap16 (memory, n) | |
712 | unsigned char *memory; | |
713 | int n; | |
714 | { | |
715 | int little_endian = target_little_endian; | |
716 | WWAT (0, n); | |
717 | } | |
718 | ||
719 | static void | |
720 | swapout (n) | |
721 | int n; | |
722 | { | |
723 | if (profile_file) | |
724 | { | |
725 | char b[4]; | |
726 | swap (b, n); | |
727 | fwrite (b, 4, 1, profile_file); | |
728 | } | |
729 | } | |
730 | ||
731 | static void | |
732 | swapout16 (n) | |
733 | int n; | |
734 | { | |
735 | char b[4]; | |
736 | swap16 (b, n); | |
737 | fwrite (b, 2, 1, profile_file); | |
738 | } | |
739 | ||
740 | /* Turn a pointer in a register into a pointer into real memory. */ | |
741 | ||
742 | static char * | |
743 | ptr (x) | |
744 | int x; | |
745 | { | |
746 | return (char *) (x + saved_state.asregs.memory); | |
747 | } | |
748 | ||
749 | /* Simulate a monitor trap, put the result into r0 and errno into r1 */ | |
750 | ||
751 | static void | |
752 | trap (i, regs, memory, maskl, maskw, little_endian) | |
753 | int i; | |
754 | int *regs; | |
755 | unsigned char *memory; | |
756 | { | |
757 | switch (i) | |
758 | { | |
759 | case 1: | |
760 | printf ("%c", regs[0]); | |
761 | break; | |
762 | case 2: | |
763 | saved_state.asregs.exception = SIGQUIT; | |
764 | break; | |
765 | case 3: /* FIXME: for backwards compat, should be removed */ | |
766 | case 34: | |
767 | { | |
768 | extern int errno; | |
769 | int perrno = errno; | |
770 | errno = 0; | |
771 | ||
772 | switch (regs[4]) | |
773 | { | |
774 | ||
775 | #if !defined(__GO32__) && !defined(_WIN32) | |
776 | case SYS_fork: | |
777 | regs[0] = fork (); | |
778 | break; | |
779 | case SYS_execve: | |
780 | regs[0] = execve (ptr (regs[5]), (char **)ptr (regs[6]), (char **)ptr (regs[7])); | |
781 | break; | |
782 | case SYS_execv: | |
783 | regs[0] = execve (ptr (regs[5]),(char **) ptr (regs[6]), 0); | |
784 | break; | |
785 | case SYS_pipe: | |
786 | { | |
787 | char *buf; | |
788 | int host_fd[2]; | |
789 | ||
790 | buf = ptr (regs[5]); | |
791 | ||
792 | regs[0] = pipe (host_fd); | |
793 | ||
794 | WLAT (buf, host_fd[0]); | |
795 | buf += 4; | |
796 | WLAT (buf, host_fd[1]); | |
797 | } | |
798 | break; | |
799 | ||
800 | case SYS_wait: | |
801 | regs[0] = wait (ptr (regs[5])); | |
802 | break; | |
803 | #endif | |
804 | ||
805 | case SYS_read: | |
806 | regs[0] = callback->read (callback, regs[5], ptr (regs[6]), regs[7]); | |
807 | break; | |
808 | case SYS_write: | |
809 | if (regs[5] == 1) | |
810 | regs[0] = (int)callback->write_stdout (callback, ptr(regs[6]), regs[7]); | |
811 | else | |
812 | regs[0] = (int)callback->write (callback, regs[5], ptr (regs[6]), regs[7]); | |
813 | break; | |
814 | case SYS_lseek: | |
815 | regs[0] = callback->lseek (callback,regs[5], regs[6], regs[7]); | |
816 | break; | |
817 | case SYS_close: | |
818 | regs[0] = callback->close (callback,regs[5]); | |
819 | break; | |
820 | case SYS_open: | |
821 | regs[0] = callback->open (callback,ptr (regs[5]), regs[6]); | |
822 | break; | |
823 | case SYS_exit: | |
824 | /* EXIT - caller can look in r5 to work out the reason */ | |
825 | saved_state.asregs.exception = SIGQUIT; | |
826 | regs[0] = regs[5]; | |
827 | break; | |
828 | ||
829 | case SYS_stat: /* added at hmsi */ | |
830 | /* stat system call */ | |
831 | { | |
832 | struct stat host_stat; | |
833 | char *buf; | |
834 | ||
835 | regs[0] = stat (ptr (regs[5]), &host_stat); | |
836 | ||
837 | buf = ptr (regs[6]); | |
838 | ||
839 | WWAT (buf, host_stat.st_dev); | |
840 | buf += 2; | |
841 | WWAT (buf, host_stat.st_ino); | |
842 | buf += 2; | |
843 | WLAT (buf, host_stat.st_mode); | |
844 | buf += 4; | |
845 | WWAT (buf, host_stat.st_nlink); | |
846 | buf += 2; | |
847 | WWAT (buf, host_stat.st_uid); | |
848 | buf += 2; | |
849 | WWAT (buf, host_stat.st_gid); | |
850 | buf += 2; | |
851 | WWAT (buf, host_stat.st_rdev); | |
852 | buf += 2; | |
853 | WLAT (buf, host_stat.st_size); | |
854 | buf += 4; | |
855 | WLAT (buf, host_stat.st_atime); | |
856 | buf += 4; | |
857 | WLAT (buf, 0); | |
858 | buf += 4; | |
859 | WLAT (buf, host_stat.st_mtime); | |
860 | buf += 4; | |
861 | WLAT (buf, 0); | |
862 | buf += 4; | |
863 | WLAT (buf, host_stat.st_ctime); | |
864 | buf += 4; | |
865 | WLAT (buf, 0); | |
866 | buf += 4; | |
867 | WLAT (buf, 0); | |
868 | buf += 4; | |
869 | WLAT (buf, 0); | |
870 | buf += 4; | |
871 | } | |
872 | break; | |
873 | ||
874 | #ifndef _WIN32 | |
875 | case SYS_chown: | |
876 | regs[0] = chown (ptr (regs[5]), regs[6], regs[7]); | |
877 | break; | |
878 | #endif /* _WIN32 */ | |
879 | case SYS_chmod: | |
880 | regs[0] = chmod (ptr (regs[5]), regs[6]); | |
881 | break; | |
882 | case SYS_utime: | |
883 | /* Cast the second argument to void *, to avoid type mismatch | |
884 | if a prototype is present. */ | |
885 | regs[0] = utime (ptr (regs[5]), (void *) ptr (regs[6])); | |
886 | break; | |
887 | default: | |
888 | abort (); | |
889 | } | |
890 | regs[1] = callback->get_errno (callback); | |
891 | errno = perrno; | |
892 | } | |
893 | break; | |
894 | ||
895 | case 0xc3: | |
896 | case 255: | |
897 | saved_state.asregs.exception = SIGTRAP; | |
898 | break; | |
899 | } | |
900 | ||
901 | } | |
902 | ||
903 | void | |
904 | control_c (sig, code, scp, addr) | |
905 | int sig; | |
906 | int code; | |
907 | char *scp; | |
908 | char *addr; | |
909 | { | |
910 | saved_state.asregs.exception = SIGINT; | |
911 | } | |
912 | ||
913 | static int | |
914 | div1 (R, iRn2, iRn1/*, T*/) | |
915 | int *R; | |
916 | int iRn1; | |
917 | int iRn2; | |
918 | /* int T;*/ | |
919 | { | |
920 | unsigned long tmp0; | |
921 | unsigned char old_q, tmp1; | |
922 | ||
923 | old_q = Q; | |
924 | SET_SR_Q ((unsigned char) ((0x80000000 & R[iRn1]) != 0)); | |
925 | R[iRn1] <<= 1; | |
926 | R[iRn1] |= (unsigned long) T; | |
927 | ||
928 | switch (old_q) | |
929 | { | |
930 | case 0: | |
931 | switch (M) | |
932 | { | |
933 | case 0: | |
934 | tmp0 = R[iRn1]; | |
935 | R[iRn1] -= R[iRn2]; | |
936 | tmp1 = (R[iRn1] > tmp0); | |
937 | switch (Q) | |
938 | { | |
939 | case 0: | |
940 | SET_SR_Q (tmp1); | |
941 | break; | |
942 | case 1: | |
943 | SET_SR_Q ((unsigned char) (tmp1 == 0)); | |
944 | break; | |
945 | } | |
946 | break; | |
947 | case 1: | |
948 | tmp0 = R[iRn1]; | |
949 | R[iRn1] += R[iRn2]; | |
950 | tmp1 = (R[iRn1] < tmp0); | |
951 | switch (Q) | |
952 | { | |
953 | case 0: | |
954 | SET_SR_Q ((unsigned char) (tmp1 == 0)); | |
955 | break; | |
956 | case 1: | |
957 | SET_SR_Q (tmp1); | |
958 | break; | |
959 | } | |
960 | break; | |
961 | } | |
962 | break; | |
963 | case 1: | |
964 | switch (M) | |
965 | { | |
966 | case 0: | |
967 | tmp0 = R[iRn1]; | |
968 | R[iRn1] += R[iRn2]; | |
969 | tmp1 = (R[iRn1] < tmp0); | |
970 | switch (Q) | |
971 | { | |
972 | case 0: | |
973 | SET_SR_Q (tmp1); | |
974 | break; | |
975 | case 1: | |
976 | SET_SR_Q ((unsigned char) (tmp1 == 0)); | |
977 | break; | |
978 | } | |
979 | break; | |
980 | case 1: | |
981 | tmp0 = R[iRn1]; | |
982 | R[iRn1] -= R[iRn2]; | |
983 | tmp1 = (R[iRn1] > tmp0); | |
984 | switch (Q) | |
985 | { | |
986 | case 0: | |
987 | SET_SR_Q ((unsigned char) (tmp1 == 0)); | |
988 | break; | |
989 | case 1: | |
990 | SET_SR_Q (tmp1); | |
991 | break; | |
992 | } | |
993 | break; | |
994 | } | |
995 | break; | |
996 | } | |
997 | /*T = (Q == M);*/ | |
998 | SET_SR_T (Q == M); | |
999 | /*return T;*/ | |
1000 | } | |
1001 | ||
1002 | static void | |
1003 | dmul (sign, rm, rn) | |
1004 | int sign; | |
1005 | unsigned int rm; | |
1006 | unsigned int rn; | |
1007 | { | |
1008 | unsigned long RnL, RnH; | |
1009 | unsigned long RmL, RmH; | |
1010 | unsigned long temp0, temp1, temp2, temp3; | |
1011 | unsigned long Res2, Res1, Res0; | |
1012 | ||
1013 | RnL = rn & 0xffff; | |
1014 | RnH = (rn >> 16) & 0xffff; | |
1015 | RmL = rm & 0xffff; | |
1016 | RmH = (rm >> 16) & 0xffff; | |
1017 | temp0 = RmL * RnL; | |
1018 | temp1 = RmH * RnL; | |
1019 | temp2 = RmL * RnH; | |
1020 | temp3 = RmH * RnH; | |
1021 | Res2 = 0; | |
1022 | Res1 = temp1 + temp2; | |
1023 | if (Res1 < temp1) | |
1024 | Res2 += 0x00010000; | |
1025 | temp1 = (Res1 << 16) & 0xffff0000; | |
1026 | Res0 = temp0 + temp1; | |
1027 | if (Res0 < temp0) | |
1028 | Res2 += 1; | |
1029 | Res2 += ((Res1 >> 16) & 0xffff) + temp3; | |
1030 | ||
1031 | if (sign) | |
1032 | { | |
1033 | if (rn & 0x80000000) | |
1034 | Res2 -= rm; | |
1035 | if (rm & 0x80000000) | |
1036 | Res2 -= rn; | |
1037 | } | |
1038 | ||
1039 | MACH = Res2; | |
1040 | MACL = Res0; | |
1041 | } | |
1042 | ||
1043 | static void | |
1044 | macw (regs, memory, n, m) | |
1045 | int *regs; | |
1046 | unsigned char *memory; | |
1047 | int m, n; | |
1048 | { | |
1049 | int little_endian = target_little_endian; | |
1050 | long tempm, tempn; | |
1051 | long prod, macl, sum; | |
1052 | ||
1053 | tempm=RSWAT(regs[m]); regs[m]+=2; | |
1054 | tempn=RSWAT(regs[n]); regs[n]+=2; | |
1055 | ||
1056 | macl = MACL; | |
1057 | prod = (long)(short) tempm * (long)(short) tempn; | |
1058 | sum = prod + macl; | |
1059 | if (S) | |
1060 | { | |
1061 | if ((~(prod ^ macl) & (sum ^ prod)) < 0) | |
1062 | { | |
1063 | /* MACH's lsb is a sticky overflow bit. */ | |
1064 | MACH |= 1; | |
1065 | /* Store the smallest negative number in MACL if prod is | |
1066 | negative, and the largest positive number otherwise. */ | |
1067 | sum = 0x7fffffff + (prod < 0); | |
1068 | } | |
1069 | } | |
1070 | else | |
1071 | { | |
1072 | long mach; | |
1073 | /* Add to MACH the sign extended product, and carry from low sum. */ | |
1074 | mach = MACH + (-(prod < 0)) + ((unsigned long) sum < prod); | |
1075 | /* Sign extend at 10:th bit in MACH. */ | |
1076 | MACH = (mach & 0x1ff) | -(mach & 0x200); | |
1077 | } | |
1078 | MACL = sum; | |
1079 | } | |
1080 | ||
1081 | /* Set the memory size to the power of two provided. */ | |
1082 | ||
1083 | void | |
1084 | sim_size (power) | |
1085 | int power; | |
1086 | ||
1087 | { | |
1088 | saved_state.asregs.msize = 1 << power; | |
1089 | ||
1090 | sim_memory_size = power; | |
1091 | ||
1092 | if (saved_state.asregs.memory) | |
1093 | { | |
1094 | free (saved_state.asregs.memory); | |
1095 | } | |
1096 | ||
1097 | saved_state.asregs.memory = | |
1098 | (unsigned char *) calloc (64, saved_state.asregs.msize / 64); | |
1099 | ||
1100 | if (!saved_state.asregs.memory) | |
1101 | { | |
1102 | fprintf (stderr, | |
1103 | "Not enough VM for simulation of %d bytes of RAM\n", | |
1104 | saved_state.asregs.msize); | |
1105 | ||
1106 | saved_state.asregs.msize = 1; | |
1107 | saved_state.asregs.memory = (unsigned char *) calloc (1, 1); | |
1108 | } | |
1109 | } | |
1110 | ||
1111 | static void | |
1112 | init_pointers () | |
1113 | { | |
1114 | host_little_endian = 0; | |
1115 | *(char*)&host_little_endian = 1; | |
1116 | host_little_endian &= 1; | |
1117 | ||
1118 | if (saved_state.asregs.msize != 1 << sim_memory_size) | |
1119 | { | |
1120 | sim_size (sim_memory_size); | |
1121 | } | |
1122 | ||
1123 | if (saved_state.asregs.profile && !profile_file) | |
1124 | { | |
1125 | profile_file = fopen ("gmon.out", "wb"); | |
1126 | /* Seek to where to put the call arc data */ | |
1127 | nsamples = (1 << sim_profile_size); | |
1128 | ||
1129 | fseek (profile_file, nsamples * 2 + 12, 0); | |
1130 | ||
1131 | if (!profile_file) | |
1132 | { | |
1133 | fprintf (stderr, "Can't open gmon.out\n"); | |
1134 | } | |
1135 | else | |
1136 | { | |
1137 | saved_state.asregs.profile_hist = | |
1138 | (unsigned short *) calloc (64, (nsamples * sizeof (short) / 64)); | |
1139 | } | |
1140 | } | |
1141 | } | |
1142 | ||
1143 | static void | |
1144 | dump_profile () | |
1145 | { | |
1146 | unsigned int minpc; | |
1147 | unsigned int maxpc; | |
1148 | unsigned short *p; | |
1149 | int i; | |
1150 | ||
1151 | p = saved_state.asregs.profile_hist; | |
1152 | minpc = 0; | |
1153 | maxpc = (1 << sim_profile_size); | |
1154 | ||
1155 | fseek (profile_file, 0L, 0); | |
1156 | swapout (minpc << PROFILE_SHIFT); | |
1157 | swapout (maxpc << PROFILE_SHIFT); | |
1158 | swapout (nsamples * 2 + 12); | |
1159 | for (i = 0; i < nsamples; i++) | |
1160 | swapout16 (saved_state.asregs.profile_hist[i]); | |
1161 | ||
1162 | } | |
1163 | ||
1164 | static void | |
1165 | gotcall (from, to) | |
1166 | int from; | |
1167 | int to; | |
1168 | { | |
1169 | swapout (from); | |
1170 | swapout (to); | |
1171 | swapout (1); | |
1172 | } | |
1173 | ||
1174 | #define MMASKB ((saved_state.asregs.msize -1) & ~0) | |
1175 | ||
1176 | int | |
1177 | sim_stop (sd) | |
1178 | SIM_DESC sd; | |
1179 | { | |
1180 | saved_state.asregs.exception = SIGINT; | |
1181 | return 1; | |
1182 | } | |
1183 | ||
1184 | void | |
1185 | sim_resume (sd, step, siggnal) | |
1186 | SIM_DESC sd; | |
1187 | int step, siggnal; | |
1188 | { | |
1189 | register unsigned int pc; | |
1190 | register int cycles = 0; | |
1191 | register int stalls = 0; | |
1192 | register int memstalls = 0; | |
1193 | register int insts = 0; | |
1194 | register int prevlock; | |
1195 | register int thislock; | |
1196 | register unsigned int doprofile; | |
1197 | register int pollcount = 0; | |
1198 | register int little_endian = target_little_endian; | |
1199 | ||
1200 | int tick_start = get_now (); | |
1201 | void (*prev) (); | |
1202 | void (*prev_fpe) (); | |
1203 | extern unsigned char sh_jump_table0[]; | |
1204 | ||
1205 | register unsigned char *jump_table = sh_jump_table0; | |
1206 | ||
1207 | register int *R = &(saved_state.asregs.regs[0]); | |
1208 | /*register int T;*/ | |
1209 | register int PR; | |
1210 | ||
1211 | register int maskb = ((saved_state.asregs.msize - 1) & ~0); | |
1212 | register int maskw = ((saved_state.asregs.msize - 1) & ~1); | |
1213 | register int maskl = ((saved_state.asregs.msize - 1) & ~3); | |
1214 | register unsigned char *memory; | |
1215 | register unsigned int sbit = ((unsigned int) 1 << 31); | |
1216 | ||
1217 | prev = signal (SIGINT, control_c); | |
1218 | prev_fpe = signal (SIGFPE, SIG_IGN); | |
1219 | ||
1220 | init_pointers (); | |
1221 | ||
1222 | memory = saved_state.asregs.memory; | |
1223 | ||
1224 | if (step) | |
1225 | { | |
1226 | saved_state.asregs.exception = SIGTRAP; | |
1227 | } | |
1228 | else | |
1229 | { | |
1230 | saved_state.asregs.exception = 0; | |
1231 | } | |
1232 | ||
1233 | pc = saved_state.asregs.pc; | |
1234 | PR = saved_state.asregs.pr; | |
1235 | /*T = GET_SR () & SR_MASK_T;*/ | |
1236 | prevlock = saved_state.asregs.prevlock; | |
1237 | thislock = saved_state.asregs.thislock; | |
1238 | doprofile = saved_state.asregs.profile; | |
1239 | ||
1240 | /* If profiling not enabled, disable it by asking for | |
1241 | profiles infrequently. */ | |
1242 | if (doprofile == 0) | |
1243 | doprofile = ~0; | |
1244 | ||
1245 | do | |
1246 | { | |
1247 | register unsigned int iword = RUWAT (pc); | |
1248 | register unsigned int ult; | |
1249 | register unsigned int nia = pc + 2; | |
1250 | #ifndef ACE_FAST | |
1251 | insts++; | |
1252 | #endif | |
1253 | top: | |
1254 | ||
1255 | #include "code.c" | |
1256 | ||
1257 | ||
1258 | pc = nia; | |
1259 | ||
1260 | if (--pollcount < 0) | |
1261 | { | |
7a292a7a | 1262 | pollcount = POLL_QUIT_INTERVAL; |
c906108c SS |
1263 | if ((*callback->poll_quit) != NULL |
1264 | && (*callback->poll_quit) (callback)) | |
1265 | { | |
1266 | sim_stop (sd); | |
1267 | } | |
1268 | } | |
1269 | ||
1270 | #ifndef ACE_FAST | |
1271 | prevlock = thislock; | |
1272 | thislock = 30; | |
1273 | cycles++; | |
1274 | ||
1275 | if (cycles >= doprofile) | |
1276 | { | |
1277 | ||
1278 | saved_state.asregs.cycles += doprofile; | |
1279 | cycles -= doprofile; | |
1280 | if (saved_state.asregs.profile_hist) | |
1281 | { | |
1282 | int n = pc >> PROFILE_SHIFT; | |
1283 | if (n < nsamples) | |
1284 | { | |
1285 | int i = saved_state.asregs.profile_hist[n]; | |
1286 | if (i < 65000) | |
1287 | saved_state.asregs.profile_hist[n] = i + 1; | |
1288 | } | |
1289 | ||
1290 | } | |
1291 | } | |
1292 | #endif | |
1293 | } | |
1294 | while (!saved_state.asregs.exception); | |
1295 | ||
1296 | if (saved_state.asregs.exception == SIGILL | |
1297 | || saved_state.asregs.exception == SIGBUS) | |
1298 | { | |
1299 | pc -= 2; | |
1300 | } | |
1301 | ||
1302 | saved_state.asregs.ticks += get_now () - tick_start; | |
1303 | saved_state.asregs.cycles += cycles; | |
1304 | saved_state.asregs.stalls += stalls; | |
1305 | saved_state.asregs.memstalls += memstalls; | |
1306 | saved_state.asregs.insts += insts; | |
1307 | saved_state.asregs.pc = pc; | |
1308 | /* restore the T and other cached SR bits */ | |
1309 | SET_SR (GET_SR()); | |
1310 | saved_state.asregs.pr = PR; | |
1311 | ||
1312 | saved_state.asregs.prevlock = prevlock; | |
1313 | saved_state.asregs.thislock = thislock; | |
1314 | ||
1315 | if (profile_file) | |
1316 | { | |
1317 | dump_profile (); | |
1318 | } | |
1319 | ||
1320 | signal (SIGFPE, prev_fpe); | |
1321 | signal (SIGINT, prev); | |
1322 | } | |
1323 | ||
1324 | int | |
1325 | sim_write (sd, addr, buffer, size) | |
1326 | SIM_DESC sd; | |
1327 | SIM_ADDR addr; | |
1328 | unsigned char *buffer; | |
1329 | int size; | |
1330 | { | |
1331 | int i; | |
1332 | ||
1333 | init_pointers (); | |
1334 | ||
1335 | for (i = 0; i < size; i++) | |
1336 | { | |
1337 | saved_state.asregs.memory[MMASKB & (addr + i)] = buffer[i]; | |
1338 | } | |
1339 | return size; | |
1340 | } | |
1341 | ||
1342 | int | |
1343 | sim_read (sd, addr, buffer, size) | |
1344 | SIM_DESC sd; | |
1345 | SIM_ADDR addr; | |
1346 | unsigned char *buffer; | |
1347 | int size; | |
1348 | { | |
1349 | int i; | |
1350 | ||
1351 | init_pointers (); | |
1352 | ||
1353 | for (i = 0; i < size; i++) | |
1354 | { | |
1355 | buffer[i] = saved_state.asregs.memory[MMASKB & (addr + i)]; | |
1356 | } | |
1357 | return size; | |
1358 | } | |
1359 | ||
1360 | /* We have to add one to RN as an index into asints because of the padding | |
1361 | added at the start of asregs. */ | |
1362 | int | |
1363 | sim_store_register (sd, rn, memory, length) | |
1364 | SIM_DESC sd; | |
1365 | int rn; | |
1366 | unsigned char *memory; | |
1367 | int length; | |
1368 | { | |
1369 | int little_endian; | |
1370 | init_pointers (); | |
1371 | little_endian = target_little_endian; | |
1372 | if (&saved_state.asints[rn+1] | |
1373 | == &saved_state.asregs.fpscr) | |
1374 | set_fpscr1 (RLAT(0)); | |
1375 | else | |
1376 | saved_state.asints[rn+1] = RLAT(0); | |
1377 | return -1; | |
1378 | } | |
1379 | ||
1380 | int | |
1381 | sim_fetch_register (sd, rn, memory, length) | |
1382 | SIM_DESC sd; | |
1383 | int rn; | |
1384 | unsigned char *memory; | |
1385 | int length; | |
1386 | { | |
1387 | int little_endian; | |
1388 | init_pointers (); | |
1389 | little_endian = target_little_endian; | |
1390 | WLAT (0, saved_state.asints[rn+1]); | |
1391 | return -1; | |
1392 | } | |
1393 | ||
1394 | int | |
1395 | sim_trace (sd) | |
1396 | SIM_DESC sd; | |
1397 | { | |
1398 | return 0; | |
1399 | } | |
1400 | ||
1401 | void | |
1402 | sim_stop_reason (sd, reason, sigrc) | |
1403 | SIM_DESC sd; | |
1404 | enum sim_stop *reason; | |
1405 | int *sigrc; | |
1406 | { | |
1407 | /* The SH simulator uses SIGQUIT to indicate that the program has | |
1408 | exited, so we must check for it here and translate it to exit. */ | |
1409 | if (saved_state.asregs.exception == SIGQUIT) | |
1410 | { | |
1411 | *reason = sim_exited; | |
1412 | *sigrc = saved_state.asregs.regs[5]; | |
1413 | } | |
1414 | else | |
1415 | { | |
1416 | *reason = sim_stopped; | |
1417 | *sigrc = saved_state.asregs.exception; | |
1418 | } | |
1419 | } | |
1420 | ||
1421 | void | |
1422 | sim_info (sd, verbose) | |
1423 | SIM_DESC sd; | |
1424 | int verbose; | |
1425 | { | |
1426 | double timetaken = (double) saved_state.asregs.ticks / (double) now_persec (); | |
1427 | double virttime = saved_state.asregs.cycles / 36.0e6; | |
1428 | ||
1429 | callback->printf_filtered (callback, "\n\n# instructions executed %10d\n", | |
1430 | saved_state.asregs.insts); | |
1431 | callback->printf_filtered (callback, "# cycles %10d\n", | |
1432 | saved_state.asregs.cycles); | |
1433 | callback->printf_filtered (callback, "# pipeline stalls %10d\n", | |
1434 | saved_state.asregs.stalls); | |
1435 | callback->printf_filtered (callback, "# misaligned load/store %10d\n", | |
1436 | saved_state.asregs.memstalls); | |
1437 | callback->printf_filtered (callback, "# real time taken %10.4f\n", | |
1438 | timetaken); | |
1439 | callback->printf_filtered (callback, "# virtual time taken %10.4f\n", | |
1440 | virttime); | |
1441 | callback->printf_filtered (callback, "# profiling size %10d\n", | |
1442 | sim_profile_size); | |
1443 | callback->printf_filtered (callback, "# profiling frequency %10d\n", | |
1444 | saved_state.asregs.profile); | |
1445 | callback->printf_filtered (callback, "# profile maxpc %10x\n", | |
1446 | (1 << sim_profile_size) << PROFILE_SHIFT); | |
1447 | ||
1448 | if (timetaken != 0) | |
1449 | { | |
1450 | callback->printf_filtered (callback, "# cycles/second %10d\n", | |
1451 | (int) (saved_state.asregs.cycles / timetaken)); | |
1452 | callback->printf_filtered (callback, "# simulation ratio %10.4f\n", | |
1453 | virttime / timetaken); | |
1454 | } | |
1455 | } | |
1456 | ||
1457 | void | |
1458 | sim_set_profile (n) | |
1459 | int n; | |
1460 | { | |
1461 | saved_state.asregs.profile = n; | |
1462 | } | |
1463 | ||
1464 | void | |
1465 | sim_set_profile_size (n) | |
1466 | int n; | |
1467 | { | |
1468 | sim_profile_size = n; | |
1469 | } | |
1470 | ||
1471 | SIM_DESC | |
1472 | sim_open (kind, cb, abfd, argv) | |
1473 | SIM_OPEN_KIND kind; | |
1474 | host_callback *cb; | |
1475 | struct _bfd *abfd; | |
1476 | char **argv; | |
1477 | { | |
1478 | char **p; | |
1479 | int endian_set = 0; | |
1480 | ||
1481 | sim_kind = kind; | |
1482 | myname = argv[0]; | |
1483 | callback = cb; | |
1484 | ||
1485 | for (p = argv + 1; *p != NULL; ++p) | |
1486 | { | |
1487 | if (strcmp (*p, "-E") == 0) | |
1488 | { | |
1489 | ++p; | |
1490 | if (*p == NULL) | |
1491 | { | |
1492 | /* FIXME: This doesn't use stderr, but then the rest of the | |
1493 | file doesn't either. */ | |
1494 | callback->printf_filtered (callback, "Missing argument to `-E'.\n"); | |
1495 | return 0; | |
1496 | } | |
1497 | target_little_endian = strcmp (*p, "big") != 0; | |
1498 | endian_set = 1; | |
1499 | } | |
1500 | else if (isdigit (**p)) | |
1501 | parse_and_set_memory_size (*p); | |
1502 | } | |
1503 | ||
1504 | if (abfd != NULL && ! endian_set) | |
1505 | target_little_endian = ! bfd_big_endian (abfd); | |
1506 | ||
1507 | /* fudge our descriptor for now */ | |
1508 | return (SIM_DESC) 1; | |
1509 | } | |
1510 | ||
1511 | static void | |
1512 | parse_and_set_memory_size (str) | |
1513 | char *str; | |
1514 | { | |
1515 | int n; | |
1516 | ||
1517 | n = strtol (str, NULL, 10); | |
1518 | if (n > 0 && n <= 24) | |
1519 | sim_memory_size = n; | |
1520 | else | |
1521 | callback->printf_filtered (callback, "Bad memory size %d; must be 1 to 24, inclusive\n", n); | |
1522 | } | |
1523 | ||
1524 | void | |
1525 | sim_close (sd, quitting) | |
1526 | SIM_DESC sd; | |
1527 | int quitting; | |
1528 | { | |
1529 | /* nothing to do */ | |
1530 | } | |
1531 | ||
1532 | SIM_RC | |
1533 | sim_load (sd, prog, abfd, from_tty) | |
1534 | SIM_DESC sd; | |
1535 | char *prog; | |
1536 | bfd *abfd; | |
1537 | int from_tty; | |
1538 | { | |
1539 | extern bfd *sim_load_file (); /* ??? Don't know where this should live. */ | |
1540 | bfd *prog_bfd; | |
1541 | ||
1542 | prog_bfd = sim_load_file (sd, myname, callback, prog, abfd, | |
1543 | sim_kind == SIM_OPEN_DEBUG, | |
1544 | 0, sim_write); | |
1545 | if (prog_bfd == NULL) | |
1546 | return SIM_RC_FAIL; | |
1547 | if (abfd == NULL) | |
1548 | bfd_close (prog_bfd); | |
1549 | return SIM_RC_OK; | |
1550 | } | |
1551 | ||
1552 | SIM_RC | |
1553 | sim_create_inferior (sd, prog_bfd, argv, env) | |
1554 | SIM_DESC sd; | |
1555 | struct _bfd *prog_bfd; | |
1556 | char **argv; | |
1557 | char **env; | |
1558 | { | |
1559 | /* clear the registers */ | |
1560 | memset (&saved_state, 0, | |
1561 | (char*)&saved_state.asregs.end_of_registers - (char*)&saved_state); | |
1562 | /* set the PC */ | |
1563 | if (prog_bfd != NULL) | |
1564 | saved_state.asregs.pc = bfd_get_start_address (prog_bfd); | |
1565 | return SIM_RC_OK; | |
1566 | } | |
1567 | ||
1568 | void | |
1569 | sim_do_command (sd, cmd) | |
1570 | SIM_DESC sd; | |
1571 | char *cmd; | |
1572 | { | |
1573 | char *sms_cmd = "set-memory-size"; | |
1574 | int cmdsize; | |
1575 | ||
1576 | if (cmd == NULL || *cmd == '\0') | |
1577 | { | |
1578 | cmd = "help"; | |
1579 | } | |
1580 | ||
1581 | cmdsize = strlen (sms_cmd); | |
1582 | if (strncmp (cmd, sms_cmd, cmdsize) == 0 && strchr (" \t", cmd[cmdsize]) != NULL) | |
1583 | { | |
1584 | parse_and_set_memory_size (cmd + cmdsize + 1); | |
1585 | } | |
1586 | else if (strcmp (cmd, "help") == 0) | |
1587 | { | |
1588 | (callback->printf_filtered) (callback, "List of SH simulator commands:\n\n"); | |
1589 | (callback->printf_filtered) (callback, "set-memory-size <n> -- Set the number of address bits to use\n"); | |
1590 | (callback->printf_filtered) (callback, "\n"); | |
1591 | } | |
1592 | else | |
1593 | { | |
1594 | (callback->printf_filtered) (callback, "Error: \"%s\" is not a valid SH simulator command.\n", cmd); | |
1595 | } | |
1596 | } | |
1597 | ||
1598 | void | |
1599 | sim_set_callbacks (p) | |
1600 | host_callback *p; | |
1601 | { | |
1602 | callback = p; | |
1603 | } |