Commit | Line | Data |
---|---|---|
594266fc SC |
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 | */ | |
90fe361f | 20 | #include "sysdep.h" |
594266fc SC |
21 | #include <sys/times.h> |
22 | #include <sys/param.h> | |
23 | ||
24 | #define O_RECOMPILE 85 | |
25 | #define DEFINE_TABLE | |
26 | ||
27 | #define DISASSEMBLER_TABLE | |
28 | ||
29 | #define SBIT(x) ((x)&sbit) | |
90fe361f SC |
30 | #define R0 saved_state.asregs.regs[0] |
31 | #define Rn saved_state.asregs.regs[n] | |
32 | #define Rm saved_state.asregs.regs[m] | |
33 | #define UR0 (unsigned int)(saved_state.asregs.regs[0]) | |
34 | #define UR (unsigned int)R | |
35 | #define UR (unsigned int)R | |
36 | #define SR0 saved_state.asregs.regs[0] | |
37 | #define GBR saved_state.asregs.gbr | |
38 | #define VBR saved_state.asregs.vbr | |
39 | #define MACH saved_state.asregs.mach | |
40 | #define MACL saved_state.asregs.macl | |
41 | #define M saved_state.asregs.sr.bits.m | |
42 | #define Q saved_state.asregs.sr.bits.q | |
594266fc | 43 | |
594266fc SC |
44 | #define GET_SR() (saved_state.asregs.sr.bits.t = T, saved_state.asregs.sr.word) |
45 | #define SET_SR(x) {saved_state.asregs.sr.word = (x); T =saved_state.asregs.sr.bits.t;} | |
46 | ||
47 | #define PC pc | |
48 | #define C cycles | |
49 | ||
90fe361f SC |
50 | #ifdef TARGET_BIG_ENDIAN |
51 | #define LMEM(x) *((long *)(memory+((x)&maskl))) | |
52 | #define BMEM(x) *((char *)(memory+((x)&maskb))) | |
53 | #define UWMEM(x) *((unsigned short *)(memory+((x)&maskw))) | |
54 | #define SWMEM(x) *((short *)(memory+((x)&maskw))) | |
55 | #define WLAT(x,value) (LMEM(x) = value) | |
56 | #define RLAT(x) (LMEM(x)) | |
57 | #define WWAT(x,value) (UWMEM(x) = value) | |
58 | #define RSWAT(x) (SWMEM(x)) | |
59 | #define RUWAT(x) (UWMEM(x)) | |
60 | #define WBAT(x,value) (BMEM(x) = value) | |
61 | #define RBAT(x) (BMEM(x)) | |
62 | #else | |
63 | /* For little endian or unknown host machines */ | |
64 | #define WLAT(x,value)\ | |
65 | { int v = value; unsigned char *p = memory + ((x) & maskl);\ | |
66 | p[0] =v>>24;p[1] = v>>16;p[2]=v>>8;p[3]=v; } | |
67 | ||
68 | #define WWAT(x,value)\ | |
69 | { int v = value; unsigned char *p = memory + (x & maskw);p[0] =v>>8;p[1] = v ;} | |
70 | ||
71 | #define WBAT(x,value)\ | |
72 | { unsigned char *p = memory + (x & maskb);p[0] =value;} | |
73 | ||
74 | #define RLAT(x)\ | |
75 | ((memory[x&maskl]<<24)|(memory[(x&maskl)+1]<<16)|(memory[(x&maskl)+2]<<8)| (memory[(x&maskl)+3])) | |
76 | ||
77 | #define RWAT(x)\ | |
78 | ((memory[x&maskw]<<8)|(memory[(x&maskw)+1])) | |
79 | ||
80 | #define RBAT(x)\ | |
81 | ((memory[x&maskb])) | |
82 | ||
83 | #define RUWAT(x) (RWAT(x) & 0xffff) | |
84 | #define RSWAT(x) ((short)(RWAT(x))) | |
85 | #define RSBAT(x) (SEXT(RBAT(x))) | |
86 | ||
87 | #endif | |
88 | ||
89 | ||
90 | ||
91 | #define SEXT(x) (((x&0xff) ^ (~0x7f))+0x80) | |
92 | #define SEXTW(y) ((int)((short)y)) | |
93 | ||
94 | #define SL(TEMPPC) iword= RUWAT(TEMPPC); goto top; | |
95 | ||
96 | ||
97 | #define L(x) thislock = x; | |
98 | #define TL(x) if ((x) == prevlock) stalls++; | |
99 | #define TB(x,y) if ((x) == prevlock || (y)==prevlock) stalls++; | |
100 | int sim_memory_size = 19; | |
101 | static int sim_profile_size = 17; | |
102 | static int nsamples; | |
594266fc SC |
103 | typedef union |
104 | { | |
105 | ||
106 | struct | |
107 | { | |
108 | ||
109 | int regs[16]; | |
110 | int pc; | |
111 | int pr; | |
112 | ||
113 | int gbr; | |
114 | int vbr; | |
115 | int mach; | |
116 | int macl; | |
117 | ||
118 | ||
119 | union | |
120 | { | |
121 | struct | |
122 | { | |
90fe361f SC |
123 | unsigned int d0:22; |
124 | unsigned int m:1; | |
125 | unsigned int q:1; | |
126 | unsigned int i:4; | |
127 | unsigned int d1:2; | |
128 | unsigned int s:1; | |
129 | unsigned int t:1; | |
594266fc SC |
130 | } |
131 | bits; | |
132 | int word; | |
133 | } | |
134 | sr; | |
135 | int ticks; | |
90fe361f | 136 | int stalls; |
594266fc SC |
137 | int cycles; |
138 | int insts; | |
594266fc | 139 | |
90fe361f SC |
140 | |
141 | int prevlock; | |
142 | int thislock; | |
143 | int exception; | |
144 | int msize; | |
145 | #define PROFILE_FREQ 1 | |
146 | #define PROFILE_SHIFT 2 | |
147 | int profile; | |
148 | unsigned short *profile_hist; | |
149 | unsigned char *memory; | |
fdc506e6 | 150 | |
594266fc SC |
151 | } |
152 | asregs; | |
90fe361f | 153 | int asints[28]; |
594266fc SC |
154 | |
155 | } | |
156 | ||
157 | saved_state_type; | |
594266fc SC |
158 | saved_state_type saved_state; |
159 | ||
594266fc SC |
160 | static int |
161 | get_now () | |
162 | { | |
163 | struct tms b; | |
164 | times (&b); | |
165 | return b.tms_utime + b.tms_stime; | |
166 | } | |
167 | ||
168 | static int | |
169 | now_persec () | |
170 | { | |
90fe361f SC |
171 | #ifdef CLK_TCK |
172 | return CLK_TCK; | |
173 | #endif | |
174 | #ifdef HZ | |
594266fc | 175 | return HZ; |
90fe361f SC |
176 | #endif |
177 | return 50; | |
178 | } | |
179 | ||
180 | ||
181 | ||
182 | static FILE *profile_file; | |
183 | ||
fdc506e6 SC |
184 | static void |
185 | swap (b, n) | |
90fe361f SC |
186 | unsigned char *b; |
187 | int n; | |
fdc506e6 SC |
188 | { |
189 | b[0] = n >> 24; | |
190 | b[1] = n >> 16; | |
191 | b[2] = n >> 8; | |
192 | b[3] = n >> 0; | |
90fe361f | 193 | } |
fdc506e6 SC |
194 | static void |
195 | swap16 (b, n) | |
90fe361f SC |
196 | unsigned char *b; |
197 | int n; | |
fdc506e6 SC |
198 | { |
199 | b[0] = n >> 8; | |
200 | b[1] = n >> 0; | |
594266fc SC |
201 | } |
202 | ||
90fe361f | 203 | static void |
fdc506e6 | 204 | swapout (n) |
90fe361f SC |
205 | int n; |
206 | { | |
fdc506e6 | 207 | if (profile_file) |
90fe361f SC |
208 | { |
209 | char b[4]; | |
fdc506e6 SC |
210 | swap (b, n); |
211 | fwrite (b, 4, 1, profile_file); | |
90fe361f | 212 | } |
fdc506e6 | 213 | } |
90fe361f SC |
214 | |
215 | static void | |
fdc506e6 | 216 | swapout16 (n) |
90fe361f SC |
217 | int n; |
218 | { | |
219 | char b[4]; | |
fdc506e6 SC |
220 | swap16 (b, n); |
221 | fwrite (b, 2, 1, profile_file); | |
222 | } | |
90fe361f SC |
223 | |
224 | ||
225 | /* Turn a pointer in a register into a pointer into real memory. */ | |
226 | ||
227 | static char * | |
228 | ptr (x) | |
229 | int x; | |
230 | { | |
fdc506e6 | 231 | return (char *) (x + saved_state.asregs.memory); |
90fe361f SC |
232 | } |
233 | ||
234 | /* Simulate a monitor trap. */ | |
235 | ||
236 | static void | |
594266fc | 237 | trap (i, regs) |
90fe361f | 238 | int i; |
594266fc SC |
239 | int *regs; |
240 | { | |
241 | switch (i) | |
242 | { | |
243 | case 1: | |
244 | printf ("%c", regs[0]); | |
245 | break; | |
246 | case 2: | |
247 | saved_state.asregs.exception = SIGQUIT; | |
248 | break; | |
90fe361f SC |
249 | case 3: |
250 | { | |
251 | extern int errno; | |
252 | int perrno = errno; | |
253 | errno = 0; | |
254 | ||
255 | switch (regs[4]) | |
256 | { | |
257 | case 3: | |
258 | regs[4] = read (regs[5], ptr (regs[6]), regs[7]); | |
259 | break; | |
260 | case 4: | |
261 | regs[4] = write (regs[5], ptr (regs[6]), regs[7]); | |
262 | break; | |
263 | case 19: | |
264 | regs[4] = lseek (regs[5], regs[6], regs[7]); | |
265 | break; | |
266 | case 6: | |
267 | regs[4] = close (regs[5]); | |
268 | break; | |
269 | case 5: | |
270 | regs[4] = open (ptr (regs[5]), regs[6]); | |
271 | break; | |
272 | default: | |
273 | abort (); | |
274 | } | |
275 | regs[0] = errno; | |
276 | errno = perrno; | |
277 | } | |
278 | ||
279 | break; | |
280 | ||
594266fc SC |
281 | case 255: |
282 | saved_state.asregs.exception = SIGILL; | |
283 | break; | |
284 | } | |
285 | ||
286 | } | |
287 | void | |
288 | control_c (sig, code, scp, addr) | |
289 | int sig; | |
290 | int code; | |
291 | char *scp; | |
292 | char *addr; | |
293 | { | |
294 | saved_state.asregs.exception = SIGINT; | |
295 | } | |
296 | ||
297 | ||
fdc506e6 | 298 | static int |
90fe361f | 299 | div1 (R, iRn2, iRn1, T) |
594266fc | 300 | int *R; |
90fe361f SC |
301 | int iRn1; |
302 | int iRn2; | |
594266fc SC |
303 | int T; |
304 | { | |
305 | unsigned long tmp0; | |
306 | unsigned char old_q, tmp1; | |
90fe361f | 307 | |
594266fc | 308 | old_q = Q; |
90fe361f SC |
309 | Q = (unsigned char) ((0x80000000 & R[iRn1]) != 0); |
310 | R[iRn1] <<= 1; | |
311 | R[iRn1] |= (unsigned long) T; | |
312 | ||
313 | switch (old_q) | |
594266fc | 314 | { |
fdc506e6 | 315 | case 0: |
90fe361f | 316 | switch (M) |
fdc506e6 SC |
317 | { |
318 | case 0: | |
319 | tmp0 = R[iRn1]; | |
320 | R[iRn1] -= R[iRn2]; | |
321 | tmp1 = (R[iRn1] > tmp0); | |
322 | switch (Q) | |
323 | { | |
324 | case 0: | |
325 | Q = tmp1; | |
326 | break; | |
327 | case 1: | |
328 | Q = (unsigned char) (tmp1 == 0); | |
329 | break; | |
330 | } | |
331 | break; | |
332 | case 1: | |
333 | tmp0 = R[iRn1]; | |
334 | R[iRn1] += R[iRn2]; | |
335 | tmp1 = (R[iRn1] < tmp0); | |
336 | switch (Q) | |
337 | { | |
338 | case 0: | |
339 | Q = (unsigned char) (tmp1 == 0); | |
340 | break; | |
341 | case 1: | |
342 | Q = tmp1; | |
343 | break; | |
344 | } | |
345 | break; | |
346 | } | |
594266fc SC |
347 | break; |
348 | case 1: | |
349 | switch (M) | |
350 | { | |
fdc506e6 | 351 | case 0: |
90fe361f SC |
352 | tmp0 = R[iRn1]; |
353 | R[iRn1] += R[iRn2]; | |
354 | tmp1 = (R[iRn1] < tmp0); | |
355 | switch (Q) | |
356 | { | |
357 | case 0: | |
358 | Q = tmp1; | |
359 | break; | |
360 | case 1: | |
361 | Q = (unsigned char) (tmp1 == 0); | |
fdc506e6 | 362 | break; |
90fe361f | 363 | } |
594266fc | 364 | break; |
fdc506e6 | 365 | case 1: |
90fe361f SC |
366 | tmp0 = R[iRn1]; |
367 | R[iRn1] -= R[iRn2]; | |
368 | tmp1 = (R[iRn1] > tmp0); | |
369 | switch (Q) | |
370 | { | |
371 | case 0: | |
372 | Q = (unsigned char) (tmp1 == 0); | |
373 | break; | |
374 | case 1: | |
375 | Q = tmp1; | |
376 | break; | |
377 | } | |
594266fc SC |
378 | break; |
379 | } | |
380 | break; | |
90fe361f SC |
381 | } |
382 | T = (Q == M); | |
383 | return T; | |
384 | } | |
385 | ||
90fe361f | 386 | |
fdc506e6 SC |
387 | static void |
388 | dmul (sign, rm, rn) | |
389 | int sign; | |
390 | unsigned int rm; | |
391 | unsigned int rn; | |
392 | { | |
393 | unsigned long RnL, RnH; | |
394 | unsigned long RmL, RmH; | |
395 | unsigned long temp0, temp1, temp2, temp3; | |
396 | unsigned long Res2, Res1, Res0; | |
90fe361f | 397 | |
594266fc | 398 | |
fdc506e6 | 399 | if (!sign) |
90fe361f | 400 | { |
594266fc | 401 | |
fdc506e6 SC |
402 | RnL = rn & 0xffff; |
403 | RnH = (rn >> 16) & 0xffff; | |
404 | RmL = rm & 0xffff; | |
405 | RmH = (rm >> 16) & 0xffff; | |
406 | temp0 = RmL * RnL; | |
407 | temp1 = RmH * RnL; | |
408 | temp2 = RmL * RnH; | |
409 | temp3 = RmH * RnH; | |
410 | Res2 = 0; | |
411 | Res1 = temp1 + temp2; | |
412 | if (Res1 < temp1) | |
413 | Res2 += 0x00010000; | |
414 | temp1 = (Res1 << 16) & 0xffff0000; | |
415 | Res0 = temp0 + temp1; | |
416 | if (Res0 < temp0) | |
417 | Res2 += 1; | |
418 | Res2 += ((Res1 >> 16) & 0xffff) + temp3; | |
419 | MACH = Res2; | |
420 | MACL = Res0; | |
594266fc | 421 | |
90fe361f | 422 | } |
fdc506e6 SC |
423 | |
424 | else | |
90fe361f | 425 | { |
fdc506e6 | 426 | abort (); |
90fe361f | 427 | } |
fdc506e6 | 428 | |
594266fc SC |
429 | } |
430 | ||
fdc506e6 | 431 | |
90fe361f SC |
432 | /* Set the memory size to the power of two provided. */ |
433 | ||
434 | void | |
435 | sim_size (power) | |
436 | int power; | |
437 | ||
438 | { | |
439 | saved_state.asregs.msize = 1 << power; | |
440 | ||
fdc506e6 | 441 | sim_memory_size = power; |
90fe361f SC |
442 | |
443 | ||
444 | if (saved_state.asregs.memory) | |
445 | { | |
446 | free (saved_state.asregs.memory); | |
447 | } | |
448 | ||
449 | saved_state.asregs.memory = | |
450 | (unsigned char *) calloc (64, saved_state.asregs.msize / 64); | |
451 | ||
452 | if (!saved_state.asregs.memory) | |
453 | { | |
454 | fprintf (stderr, | |
455 | "Not enough VM for simuation of %d bytes of RAM\n", | |
456 | saved_state.asregs.msize); | |
457 | ||
458 | saved_state.asregs.msize = 1; | |
fdc506e6 | 459 | saved_state.asregs.memory = (unsigned char *) calloc (1, 1); |
90fe361f SC |
460 | } |
461 | } | |
462 | ||
463 | ||
464 | ||
fdc506e6 | 465 | static |
90fe361f SC |
466 | void |
467 | init_pointers () | |
468 | { | |
469 | if (saved_state.asregs.msize != 1 << sim_memory_size) | |
470 | { | |
471 | sim_size (sim_memory_size); | |
472 | } | |
473 | ||
474 | if (saved_state.asregs.profile && !profile_file) | |
475 | { | |
fdc506e6 | 476 | profile_file = fopen ("gmon.out", "wb"); |
90fe361f | 477 | /* Seek to where to put the call arc data */ |
fdc506e6 | 478 | nsamples = (1 << sim_profile_size); |
90fe361f | 479 | |
fdc506e6 SC |
480 | fseek (profile_file, nsamples * 2 + 12, 0); |
481 | ||
482 | if (!profile_file) | |
90fe361f | 483 | { |
fdc506e6 | 484 | fprintf (stderr, "Can't open gmon.out\n"); |
90fe361f | 485 | } |
fdc506e6 | 486 | else |
90fe361f SC |
487 | { |
488 | saved_state.asregs.profile_hist = | |
fdc506e6 | 489 | (unsigned short *) calloc (64, (nsamples * sizeof (short) / 64)); |
90fe361f SC |
490 | } |
491 | } | |
492 | } | |
493 | ||
494 | static void | |
fdc506e6 | 495 | dump_profile () |
90fe361f | 496 | { |
fdc506e6 | 497 | unsigned int minpc; |
90fe361f SC |
498 | unsigned int maxpc; |
499 | unsigned short *p; | |
500 | ||
501 | int thisshift; | |
fdc506e6 | 502 | |
90fe361f SC |
503 | unsigned short *first; |
504 | ||
505 | int i; | |
506 | p = saved_state.asregs.profile_hist; | |
fdc506e6 SC |
507 | minpc = 0; |
508 | maxpc = (1 << sim_profile_size); | |
509 | ||
510 | fseek (profile_file, 0L, 0); | |
511 | swapout (minpc << PROFILE_SHIFT); | |
512 | swapout (maxpc << PROFILE_SHIFT); | |
513 | swapout (nsamples * 2 + 12); | |
514 | for (i = 0; i < nsamples; i++) | |
515 | swapout16 (saved_state.asregs.profile_hist[i]); | |
516 | ||
90fe361f SC |
517 | } |
518 | ||
fdc506e6 SC |
519 | static int |
520 | gotcall (from, to) | |
90fe361f SC |
521 | int from; |
522 | int to; | |
523 | { | |
fdc506e6 SC |
524 | swapout (from); |
525 | swapout (to); | |
526 | swapout (1); | |
90fe361f SC |
527 | } |
528 | ||
529 | #define MMASKB ((saved_state.asregs.msize -1) & ~0) | |
530 | void | |
594266fc | 531 | sim_resume (step) |
90fe361f | 532 | int step; |
594266fc | 533 | { |
fdc506e6 | 534 | register unsigned int pc; |
90fe361f SC |
535 | register int cycles = 0; |
536 | register int stalls = 0; | |
537 | register int insts = 0; | |
538 | register int prevlock; | |
fdc506e6 SC |
539 | register int thislock; |
540 | register unsigned int doprofile; | |
90fe361f | 541 | |
594266fc SC |
542 | int tick_start = get_now (); |
543 | void (*prev) (); | |
544 | extern unsigned char sh_jump_table0[]; | |
545 | ||
546 | register unsigned char *jump_table = sh_jump_table0; | |
547 | ||
548 | register int *R = &(saved_state.asregs.regs[0]); | |
549 | register int T; | |
550 | register int PR; | |
551 | ||
90fe361f SC |
552 | register int maskb = ((saved_state.asregs.msize - 1) & ~0); |
553 | register int maskw = ((saved_state.asregs.msize - 1) & ~1); | |
554 | register int maskl = ((saved_state.asregs.msize - 1) & ~3); | |
594266fc | 555 | register unsigned char *memory = saved_state.asregs.memory; |
90fe361f SC |
556 | register unsigned int sbit = (1 << 31); |
557 | ||
594266fc SC |
558 | prev = signal (SIGINT, control_c); |
559 | ||
fdc506e6 SC |
560 | init_pointers (); |
561 | ||
594266fc SC |
562 | if (step) |
563 | { | |
564 | saved_state.asregs.exception = SIGTRAP; | |
565 | } | |
566 | else | |
567 | { | |
568 | saved_state.asregs.exception = 0; | |
569 | } | |
570 | ||
571 | pc = saved_state.asregs.pc; | |
572 | PR = saved_state.asregs.pr; | |
573 | T = saved_state.asregs.sr.bits.t; | |
90fe361f SC |
574 | prevlock = saved_state.asregs.prevlock; |
575 | thislock = saved_state.asregs.thislock; | |
576 | doprofile = saved_state.asregs.profile; | |
577 | ||
578 | /* If profiling not enabled, disable it by asking for | |
579 | profiles infrequently. */ | |
fdc506e6 | 580 | if (doprofile == 0) |
90fe361f | 581 | doprofile = ~0; |
fdc506e6 | 582 | |
594266fc SC |
583 | do |
584 | { | |
fdc506e6 SC |
585 | register unsigned int iword = RUWAT (pc); |
586 | register unsigned int ult; | |
594266fc SC |
587 | |
588 | insts++; | |
589 | top: | |
590 | ||
591 | #include "code.c" | |
592 | ||
90fe361f | 593 | |
594266fc | 594 | pc += 2; |
90fe361f SC |
595 | prevlock = thislock; |
596 | thislock = 30; | |
594266fc | 597 | cycles++; |
90fe361f SC |
598 | |
599 | if (cycles >= doprofile) | |
600 | { | |
601 | saved_state.asregs.cycles += doprofile; | |
602 | cycles -= doprofile; | |
fdc506e6 | 603 | if (saved_state.asregs.profile_hist) |
90fe361f SC |
604 | { |
605 | int n = pc >> PROFILE_SHIFT; | |
fdc506e6 | 606 | if (n < nsamples) |
90fe361f SC |
607 | { |
608 | int i = saved_state.asregs.profile_hist[n]; | |
609 | if (i < 65000) | |
fdc506e6 | 610 | saved_state.asregs.profile_hist[n] = i + 1; |
90fe361f | 611 | } |
fdc506e6 | 612 | |
90fe361f SC |
613 | } |
614 | } | |
594266fc SC |
615 | } |
616 | while (!saved_state.asregs.exception); | |
617 | ||
90fe361f | 618 | if (saved_state.asregs.exception == SIGILL) |
594266fc | 619 | { |
90fe361f | 620 | pc -= 2; |
594266fc | 621 | } |
90fe361f | 622 | |
594266fc SC |
623 | saved_state.asregs.ticks += get_now () - tick_start; |
624 | saved_state.asregs.cycles += cycles; | |
90fe361f | 625 | saved_state.asregs.stalls += stalls; |
594266fc SC |
626 | saved_state.asregs.insts += insts; |
627 | saved_state.asregs.pc = pc; | |
628 | saved_state.asregs.sr.bits.t = T; | |
629 | saved_state.asregs.pr = PR; | |
630 | ||
90fe361f SC |
631 | saved_state.asregs.prevlock = prevlock; |
632 | saved_state.asregs.thislock = thislock; | |
633 | ||
634 | ||
635 | if (profile_file) | |
636 | { | |
fdc506e6 | 637 | dump_profile (); |
90fe361f | 638 | } |
fdc506e6 | 639 | |
594266fc SC |
640 | signal (SIGINT, prev); |
641 | } | |
642 | ||
643 | ||
644 | ||
90fe361f | 645 | |
594266fc SC |
646 | void |
647 | sim_write (addr, buffer, size) | |
648 | long int addr; | |
649 | unsigned char *buffer; | |
650 | int size; | |
651 | { | |
652 | int i; | |
653 | init_pointers (); | |
654 | ||
655 | for (i = 0; i < size; i++) | |
656 | { | |
657 | saved_state.asregs.memory[MMASKB & (addr + i)] = buffer[i]; | |
658 | } | |
659 | } | |
660 | ||
661 | void | |
662 | sim_read (addr, buffer, size) | |
663 | long int addr; | |
664 | char *buffer; | |
665 | int size; | |
666 | { | |
667 | int i; | |
668 | ||
669 | init_pointers (); | |
670 | ||
671 | for (i = 0; i < size; i++) | |
672 | { | |
673 | buffer[i] = saved_state.asregs.memory[MMASKB & (addr + i)]; | |
674 | } | |
675 | } | |
676 | ||
677 | ||
90fe361f | 678 | void |
594266fc SC |
679 | sim_store_register (rn, value) |
680 | int rn; | |
681 | int value; | |
682 | { | |
683 | saved_state.asregs.regs[rn] = value; | |
684 | } | |
685 | ||
90fe361f | 686 | void |
594266fc SC |
687 | sim_fetch_register (rn, buf) |
688 | int rn; | |
689 | char *buf; | |
690 | { | |
594266fc SC |
691 | int value = ((int *) (&saved_state))[rn]; |
692 | ||
fdc506e6 | 693 | swap (buf, value); |
594266fc SC |
694 | } |
695 | ||
90fe361f | 696 | |
594266fc SC |
697 | int |
698 | sim_trace () | |
699 | { | |
594266fc | 700 | return 0; |
594266fc SC |
701 | } |
702 | ||
90fe361f | 703 | int |
594266fc SC |
704 | sim_stop_signal () |
705 | { | |
706 | return saved_state.asregs.exception; | |
707 | } | |
708 | ||
90fe361f | 709 | void |
594266fc | 710 | sim_set_pc (x) |
90fe361f | 711 | int x; |
594266fc SC |
712 | { |
713 | saved_state.asregs.pc = x; | |
714 | } | |
715 | ||
716 | ||
90fe361f | 717 | void |
594266fc SC |
718 | sim_info () |
719 | { | |
720 | double timetaken = (double) saved_state.asregs.ticks / (double) now_persec (); | |
90fe361f SC |
721 | double virttime = saved_state.asregs.cycles / 36.0e6; |
722 | ||
723 | printf ("\n\n# instructions executed %10d\n", saved_state.asregs.insts); | |
fdc506e6 | 724 | printf ("# cycles %10d\n", saved_state.asregs.cycles); |
90fe361f SC |
725 | printf ("# pipeline stalls %10d\n", saved_state.asregs.stalls); |
726 | printf ("# real time taken %10.4f\n", timetaken); | |
727 | printf ("# virtual time taked %10.4f\n", virttime); | |
728 | printf ("# profiling size %10d\n", sim_profile_size); | |
fdc506e6 SC |
729 | printf ("# profiling frequency %10d\n", saved_state.asregs.profile); |
730 | printf ("# profile maxpc %10x\n", (1 << sim_profile_size) << PROFILE_SHIFT); | |
731 | ||
732 | if (timetaken != 0) | |
90fe361f SC |
733 | { |
734 | printf ("# cycles/second %10d\n", (int) (saved_state.asregs.cycles / timetaken)); | |
735 | printf ("# simulation ratio %10.4f\n", virttime / timetaken); | |
736 | } | |
594266fc SC |
737 | } |
738 | ||
90fe361f SC |
739 | |
740 | void | |
fdc506e6 | 741 | sim_set_profile (n) |
594266fc | 742 | { |
90fe361f SC |
743 | saved_state.asregs.profile = n; |
744 | } | |
745 | ||
746 | void | |
fdc506e6 | 747 | sim_set_profile_size (n) |
90fe361f SC |
748 | { |
749 | sim_profile_size = n; | |
594266fc | 750 | } |