1 /* Simulator for the Hitachi SH architecture.
3 Written by Steve Chamberlain of Cygnus Support.
6 This file is part of SH sim
9 THIS SOFTWARE IS NOT COPYRIGHTED
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.
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.
21 #include <sys/times.h>
22 #include <sys/param.h>
24 #define O_RECOMPILE 85
27 #define DISASSEMBLER_TABLE
29 #define SBIT(x) ((x)&sbit)
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
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;}
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))
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; }
68 #define WWAT(x,value)\
69 { int v = value; unsigned char *p = memory + (x & maskw);p[0] =v>>8;p[1] = v ;}
71 #define WBAT(x,value)\
72 { unsigned char *p = memory + (x & maskb);p[0] =value;}
75 ((memory[x&maskl]<<24)|(memory[(x&maskl)+1]<<16)|(memory[(x&maskl)+2]<<8)| (memory[(x&maskl)+3]))
78 ((memory[x&maskw]<<8)|(memory[(x&maskw)+1]))
83 #define RUWAT(x) (RWAT(x) & 0xffff)
84 #define RSWAT(x) ((short)(RWAT(x)))
85 #define RSBAT(x) (SEXT(RBAT(x)))
91 #define SEXT(x) (((x&0xff) ^ (~0x7f))+0x80)
92 #define SEXTW(y) ((int)((short)y))
94 #define SL(TEMPPC) iword= RUWAT(TEMPPC); goto top;
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;
145 #define PROFILE_FREQ 1
146 #define PROFILE_SHIFT 2
148 unsigned short *profile_hist
;
149 unsigned char *memory
;
158 saved_state_type saved_state
;
165 return b
.tms_utime
+ b
.tms_stime
;
182 static FILE *profile_file
;
184 static void swap(b
,n
)
193 static void swap16(b
,n
)
209 fwrite(b
, 4, 1, profile_file
);
219 fwrite(b
, 2, 1, profile_file
);
223 /* Turn a pointer in a register into a pointer into real memory. */
229 return (char *)(x
+ saved_state
.asregs
.memory
);
232 /* Simulate a monitor trap. */
242 printf ("%c", regs
[0]);
245 saved_state
.asregs
.exception
= SIGQUIT
;
256 regs
[4] = read (regs
[5], ptr (regs
[6]), regs
[7]);
259 regs
[4] = write (regs
[5], ptr (regs
[6]), regs
[7]);
262 regs
[4] = lseek (regs
[5], regs
[6], regs
[7]);
265 regs
[4] = close (regs
[5]);
268 regs
[4] = open (ptr (regs
[5]), regs
[6]);
280 saved_state
.asregs
.exception
= SIGILL
;
286 control_c (sig
, code
, scp
, addr
)
292 saved_state
.asregs
.exception
= SIGINT
;
297 div1 (R
, iRn2
, iRn1
, T
)
304 unsigned char old_q
, tmp1
;
307 Q
= (unsigned char) ((0x80000000 & R
[iRn1
]) != 0);
309 R
[iRn1
] |= (unsigned long) T
;
319 tmp1
= (R
[iRn1
] > tmp0
);
326 Q
= (unsigned char) (tmp1
== 0);
333 tmp1
= (R
[iRn1
] < tmp0
);
337 Q
= (unsigned char) (tmp1
== 0);
352 tmp1
= (R
[iRn1
] < tmp0
);
359 Q
= (unsigned char) (tmp1
== 0);
366 tmp1
= (R
[iRn1
] > tmp0
);
370 Q
= (unsigned char) (tmp1
== 0);
387 Q
= (R
[n
]&0x80000000) != 0;
397 tmp1
= (R
[n
] > tmp0
) != Q
;
403 tmp1
= (R
[n
] < tmp0
) == Q
;
410 static void dmul(sign
, rml
, rnl
)
418 unsigned int t0
,t1
,t2
,t3
;
419 unsigned int res0
,res1
,res2
;
420 /* Sign extend input if signed multiply */
423 rmh
= (rml
& 0x80000000) ? ~0 : 0;
424 rnh
= (rnl
& 0x80000000) ? ~0 : 0;
441 t1
= ((res1
<< 16) & 0xffff0000);
444 if (res0
< t0
) res2
++;
446 res2
= res2
+ ((res1
>> 16) & 0xffff) + t3
;
454 /* Set the memory size to the power of two provided. */
461 saved_state
.asregs
.msize
= 1 << power
;
463 sim_memory_size
= power
;
466 if (saved_state
.asregs
.memory
)
468 free (saved_state
.asregs
.memory
);
471 saved_state
.asregs
.memory
=
472 (unsigned char *) calloc (64, saved_state
.asregs
.msize
/ 64);
474 if (!saved_state
.asregs
.memory
)
477 "Not enough VM for simuation of %d bytes of RAM\n",
478 saved_state
.asregs
.msize
);
480 saved_state
.asregs
.msize
= 1;
481 saved_state
.asregs
.memory
= (unsigned char *)calloc(1,1);
491 if (saved_state
.asregs
.msize
!= 1 << sim_memory_size
)
493 sim_size (sim_memory_size
);
496 if (saved_state
.asregs
.profile
&& !profile_file
)
498 profile_file
= fopen("gmon.out","wb");
499 /* Seek to where to put the call arc data */
500 nsamples
= (1<<sim_profile_size
);
502 fseek (profile_file
, nsamples
* 2 +12, 0);
506 fprintf(stderr
,"Can't open gmon.out\n");
510 saved_state
.asregs
.profile_hist
=
511 (unsigned short *) calloc(64, (nsamples
* sizeof(short) / 64));
525 unsigned short *first
;
528 p
= saved_state
.asregs
.profile_hist
;
530 maxpc
= (1<<sim_profile_size
) ;
532 fseek(profile_file
, 0L, 0);
533 swapout(minpc
<<PROFILE_SHIFT
);
534 swapout(maxpc
<<PROFILE_SHIFT
);
535 swapout(nsamples
* 2 + 12);
536 for (i
= 0; i
< nsamples
; i
++)
537 swapout16(saved_state
.asregs
.profile_hist
[i
]);
541 static int gotcall(from
, to
)
550 #define MMASKB ((saved_state.asregs.msize -1) & ~0)
555 register unsigned int pc
;
556 register int cycles
= 0;
557 register int stalls
= 0;
558 register int insts
= 0;
559 register int prevlock
;
560 register int thislock
;
561 register unsigned int doprofile
;
563 int tick_start
= get_now ();
565 extern unsigned char sh_jump_table0
[];
567 register unsigned char *jump_table
= sh_jump_table0
;
569 register int *R
= &(saved_state
.asregs
.regs
[0]);
573 register int maskb
= ((saved_state
.asregs
.msize
- 1) & ~0);
574 register int maskw
= ((saved_state
.asregs
.msize
- 1) & ~1);
575 register int maskl
= ((saved_state
.asregs
.msize
- 1) & ~3);
576 register unsigned char *memory
= saved_state
.asregs
.memory
;
577 register unsigned int sbit
= (1 << 31);
579 prev
= signal (SIGINT
, control_c
);
585 saved_state
.asregs
.exception
= SIGTRAP
;
589 saved_state
.asregs
.exception
= 0;
592 pc
= saved_state
.asregs
.pc
;
593 PR
= saved_state
.asregs
.pr
;
594 T
= saved_state
.asregs
.sr
.bits
.t
;
595 prevlock
= saved_state
.asregs
.prevlock
;
596 thislock
= saved_state
.asregs
.thislock
;
597 doprofile
= saved_state
.asregs
.profile
;
599 /* If profiling not enabled, disable it by asking for
600 profiles infrequently. */
606 register unsigned int iword
= RUWAT (pc
);
607 register unsigned int ult
;
620 if (cycles
>= doprofile
)
622 saved_state
.asregs
.cycles
+= doprofile
;
624 if (saved_state
.asregs
.profile_hist
)
626 int n
= pc
>> PROFILE_SHIFT
;
629 int i
= saved_state
.asregs
.profile_hist
[n
];
631 saved_state
.asregs
.profile_hist
[n
] = i
+1;
637 while (!saved_state
.asregs
.exception
);
639 if (saved_state
.asregs
.exception
== SIGILL
)
644 saved_state
.asregs
.ticks
+= get_now () - tick_start
;
645 saved_state
.asregs
.cycles
+= cycles
;
646 saved_state
.asregs
.stalls
+= stalls
;
647 saved_state
.asregs
.insts
+= insts
;
648 saved_state
.asregs
.pc
= pc
;
649 saved_state
.asregs
.sr
.bits
.t
= T
;
650 saved_state
.asregs
.pr
= PR
;
652 saved_state
.asregs
.prevlock
= prevlock
;
653 saved_state
.asregs
.thislock
= thislock
;
661 signal (SIGINT
, prev
);
668 sim_write (addr
, buffer
, size
)
670 unsigned char *buffer
;
676 for (i
= 0; i
< size
; i
++)
678 saved_state
.asregs
.memory
[MMASKB
& (addr
+ i
)] = buffer
[i
];
683 sim_read (addr
, buffer
, size
)
692 for (i
= 0; i
< size
; i
++)
694 buffer
[i
] = saved_state
.asregs
.memory
[MMASKB
& (addr
+ i
)];
700 sim_store_register (rn
, value
)
704 saved_state
.asregs
.regs
[rn
] = value
;
708 sim_fetch_register (rn
, buf
)
712 int value
= ((int *) (&saved_state
))[rn
];
727 return saved_state
.asregs
.exception
;
734 saved_state
.asregs
.pc
= x
;
741 double timetaken
= (double) saved_state
.asregs
.ticks
/ (double) now_persec ();
742 double virttime
= saved_state
.asregs
.cycles
/ 36.0e6
;
744 printf ("\n\n# instructions executed %10d\n", saved_state
.asregs
.insts
);
745 printf ("# cycles %10d\n", saved_state
.asregs
.cycles
);
746 printf ("# pipeline stalls %10d\n", saved_state
.asregs
.stalls
);
747 printf ("# real time taken %10.4f\n", timetaken
);
748 printf ("# virtual time taked %10.4f\n", virttime
);
749 printf ("# profiling size %10d\n", sim_profile_size
);
750 printf( "# profiling frequency %10d\n", saved_state
.asregs
.profile
);
751 printf( "# profile maxpc %10x\n", (1<<sim_profile_size
) << PROFILE_SHIFT
);
755 printf ("# cycles/second %10d\n", (int) (saved_state
.asregs
.cycles
/ timetaken
));
756 printf ("# simulation ratio %10.4f\n", virttime
/ timetaken
);
764 saved_state
.asregs
.profile
= n
;
768 sim_set_profile_size(n
)
770 sim_profile_size
= n
;