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.
31 #include "remote-sim.h"
33 /* This file is local - if newlib changes, then so should this. */
39 #include <float.h> /* Needed for _isnan() */
44 #define SIGBUS SIGSEGV
48 #define SIGQUIT SIGTERM
55 #define O_RECOMPILE 85
57 #define DISASSEMBLER_TABLE
59 #define SBIT(x) ((x)&sbit)
60 #define R0 saved_state.asregs.regs[0]
61 #define Rn saved_state.asregs.regs[n]
62 #define Rm saved_state.asregs.regs[m]
63 #define UR0 (unsigned int)(saved_state.asregs.regs[0])
64 #define UR (unsigned int)R
65 #define UR (unsigned int)R
66 #define SR0 saved_state.asregs.regs[0]
67 #define GBR saved_state.asregs.gbr
68 #define VBR saved_state.asregs.vbr
69 #define SSR saved_state.asregs.ssr
70 #define SPC saved_state.asregs.spc
71 #define MACH saved_state.asregs.mach
72 #define MACL saved_state.asregs.macl
73 #define M saved_state.asregs.sr.bits.m
74 #define Q saved_state.asregs.sr.bits.q
75 #define S saved_state.asregs.sr.bits.s
76 #define FPSCR saved_state.asregs.fpscr
77 #define FPUL saved_state.asregs.fpul
79 #define GET_SR() (saved_state.asregs.sr.bits.t = T, saved_state.asregs.sr.word)
80 #define SET_SR(x) {saved_state.asregs.sr.word = (x); T =saved_state.asregs.sr.bits.t;}
85 static SIM_OPEN_KIND sim_kind
;
87 static int little_endian_p
;
95 /* This function exists solely for the purpose of setting a breakpoint to
96 catch simulated bus errors when running the simulator under GDB. */
103 #define BUSERROR(addr, mask) \
104 if (addr & ~mask) { saved_state.asregs.exception = SIGBUS; bp_holder (); }
106 /* Define this to enable register lifetime checking.
107 The compiler generates "add #0,rn" insns to mark registers as invalid,
108 the simulator uses this info to call fail if it finds a ref to an invalid
109 register before a def
116 #define CREF(x) if(!valid[x]) fail();
117 #define CDEF(x) valid[x] = 1;
118 #define UNDEF(x) valid[x] = 0;
125 static void parse_and_set_memory_size
PARAMS ((char *str
));
127 static int IOMEM
PARAMS ((int addr
, int write
, int value
));
129 static host_callback
*callback
;
131 /* These variables are at file scope so that functions other than
132 sim_resume can use the fetch/store macros */
134 static int little_endian
;
137 static int maskl
= ~0;
138 static int maskw
= ~0;
190 #define PROFILE_FREQ 1
191 #define PROFILE_SHIFT 2
193 unsigned short *profile_hist
;
194 unsigned char *memory
;
200 saved_state_type saved_state
;
203 wlat_little (memory
, x
, value
, maskl
)
204 unsigned char *memory
;
207 unsigned char *p
= memory
+ ((x
) & maskl
);
216 wwat_little (memory
, x
, value
, maskw
)
217 unsigned char *memory
;
220 unsigned char *p
= memory
+ ((x
) & maskw
);
228 wbat_any (memory
, x
, value
, maskb
)
229 unsigned char *memory
;
231 unsigned char *p
= memory
+ (x
& maskb
);
240 wlat_big (memory
, x
, value
, maskl
)
241 unsigned char *memory
;
244 unsigned char *p
= memory
+ ((x
) & maskl
);
254 wwat_big (memory
, x
, value
, maskw
)
255 unsigned char *memory
;
258 unsigned char *p
= memory
+ ((x
) & maskw
);
266 wbat_big (memory
, x
, value
, maskb
)
267 unsigned char *memory
;
269 unsigned char *p
= memory
+ (x
& maskb
);
280 rlat_little (memory
, x
, maskl
)
281 unsigned char *memory
;
283 unsigned char *p
= memory
+ ((x
) & maskl
);
286 return (p
[3] << 24) | (p
[2] << 16) | (p
[1] << 8) | p
[0];
290 rwat_little (memory
, x
, maskw
)
291 unsigned char *memory
;
293 unsigned char *p
= memory
+ ((x
) & maskw
);
296 return (p
[1] << 8) | p
[0];
300 rbat_any (memory
, x
, maskb
)
301 unsigned char *memory
;
303 unsigned char *p
= memory
+ ((x
) & maskb
);
310 rlat_big (memory
, x
, maskl
)
311 unsigned char *memory
;
313 unsigned char *p
= memory
+ ((x
) & maskl
);
316 return (p
[0] << 24) | (p
[1] << 16) | (p
[2] << 8) | p
[3];
320 rwat_big (memory
, x
, maskw
)
321 unsigned char *memory
;
323 unsigned char *p
= memory
+ ((x
) & maskw
);
326 return (p
[0] << 8) | p
[1];
329 #define RWAT(x) (little_endian ? rwat_little(memory, x, maskw): rwat_big(memory, x, maskw))
330 #define RLAT(x) (little_endian ? rlat_little(memory, x, maskl): rlat_big(memory, x, maskl))
331 #define RBAT(x) (rbat_any (memory, x, maskb))
332 #define WWAT(x,v) (little_endian ? wwat_little(memory, x, v, maskw): wwat_big(memory, x, v, maskw))
333 #define WLAT(x,v) (little_endian ? wlat_little(memory, x, v, maskl): wlat_big(memory, x, v, maskl))
334 #define WBAT(x,v) (wbat_any (memory, x, v, maskb))
336 #define RUWAT(x) (RWAT(x) & 0xffff)
337 #define RSWAT(x) ((short)(RWAT(x)))
338 #define RSBAT(x) (SEXT(RBAT(x)))
340 #define MA() ((pc & 3) != 0 ? ++memstalls : 0)
342 #define SEXT(x) (((x&0xff) ^ (~0x7f))+0x80)
343 #define SEXTW(y) ((int)((short)y))
345 #define SL(TEMPPC) iword= RUWAT(TEMPPC); goto top;
349 #define L(x) thislock = x;
350 #define TL(x) if ((x) == prevlock) stalls++;
351 #define TB(x,y) if ((x) == prevlock || (y)==prevlock) stalls++;
353 #if defined(__GO32__) || defined(_WIN32)
354 int sim_memory_size
= 19;
356 int sim_memory_size
= 24;
359 static int sim_profile_size
= 17;
365 #define SMR1 (0x05FFFEC8) /* Channel 1 serial mode register */
366 #define BRR1 (0x05FFFEC9) /* Channel 1 bit rate register */
367 #define SCR1 (0x05FFFECA) /* Channel 1 serial control register */
368 #define TDR1 (0x05FFFECB) /* Channel 1 transmit data register */
369 #define SSR1 (0x05FFFECC) /* Channel 1 serial status register */
370 #define RDR1 (0x05FFFECD) /* Channel 1 receive data register */
372 #define SCI_RDRF 0x40 /* Recieve data register full */
373 #define SCI_TDRE 0x80 /* Transmit data register empty */
376 IOMEM (addr
, write
, value
)
408 return time ((long *) 0);
417 static FILE *profile_file
;
421 unsigned char *memory
;
429 unsigned char *memory
;
443 fwrite (b
, 4, 1, profile_file
);
453 fwrite (b
, 2, 1, profile_file
);
456 /* Turn a pointer in a register into a pointer into real memory. */
462 return (char *) (x
+ saved_state
.asregs
.memory
);
465 /* Simulate a monitor trap, put the result into r0 and errno into r1 */
468 trap (i
, regs
, memory
, maskl
, maskw
, little_endian
)
471 unsigned char *memory
;
476 printf ("%c", regs
[0]);
479 saved_state
.asregs
.exception
= SIGQUIT
;
481 case 3: /* FIXME: for backwards compat, should be removed */
491 #if !defined(__GO32__) && !defined(_WIN32)
496 regs
[0] = execve (ptr (regs
[5]), (char **)ptr (regs
[6]), (char **)ptr (regs
[7]));
499 regs
[0] = execve (ptr (regs
[5]),(char **) ptr (regs
[6]), 0);
508 regs
[0] = pipe (host_fd
);
510 WLAT (buf
, host_fd
[0]);
512 WLAT (buf
, host_fd
[1]);
517 regs
[0] = wait (ptr (regs
[5]));
522 regs
[0] = callback
->read (callback
, regs
[5], ptr (regs
[6]), regs
[7]);
526 regs
[0] = (int)callback
->write_stdout (callback
, ptr(regs
[6]), regs
[7]);
528 regs
[0] = (int)callback
->write (callback
, regs
[5], ptr (regs
[6]), regs
[7]);
531 regs
[0] = callback
->lseek (callback
,regs
[5], regs
[6], regs
[7]);
534 regs
[0] = callback
->close (callback
,regs
[5]);
537 regs
[0] = callback
->open (callback
,ptr (regs
[5]), regs
[6]);
540 /* EXIT - caller can look in r5 to work out the reason */
541 saved_state
.asregs
.exception
= SIGQUIT
;
545 case SYS_stat
: /* added at hmsi */
546 /* stat system call */
548 struct stat host_stat
;
551 regs
[0] = stat (ptr (regs
[5]), &host_stat
);
555 WWAT (buf
, host_stat
.st_dev
);
557 WWAT (buf
, host_stat
.st_ino
);
559 WLAT (buf
, host_stat
.st_mode
);
561 WWAT (buf
, host_stat
.st_nlink
);
563 WWAT (buf
, host_stat
.st_uid
);
565 WWAT (buf
, host_stat
.st_gid
);
567 WWAT (buf
, host_stat
.st_rdev
);
569 WLAT (buf
, host_stat
.st_size
);
571 WLAT (buf
, host_stat
.st_atime
);
575 WLAT (buf
, host_stat
.st_mtime
);
579 WLAT (buf
, host_stat
.st_ctime
);
592 regs
[0] = chown (ptr (regs
[5]), regs
[6], regs
[7]);
596 regs
[0] = chmod (ptr (regs
[5]), regs
[6]);
599 /* Cast the second argument to void *, to avoid type mismatch
600 if a prototype is present. */
601 regs
[0] = utime (ptr (regs
[5]), (void *) ptr (regs
[6]));
606 regs
[1] = callback
->get_errno (callback
);
613 saved_state
.asregs
.exception
= SIGTRAP
;
620 control_c (sig
, code
, scp
, addr
)
626 saved_state
.asregs
.exception
= SIGINT
;
630 div1 (R
, iRn2
, iRn1
, T
)
637 unsigned char old_q
, tmp1
;
640 Q
= (unsigned char) ((0x80000000 & R
[iRn1
]) != 0);
642 R
[iRn1
] |= (unsigned long) T
;
652 tmp1
= (R
[iRn1
] > tmp0
);
659 Q
= (unsigned char) (tmp1
== 0);
666 tmp1
= (R
[iRn1
] < tmp0
);
670 Q
= (unsigned char) (tmp1
== 0);
685 tmp1
= (R
[iRn1
] < tmp0
);
692 Q
= (unsigned char) (tmp1
== 0);
699 tmp1
= (R
[iRn1
] > tmp0
);
703 Q
= (unsigned char) (tmp1
== 0);
723 unsigned long RnL
, RnH
;
724 unsigned long RmL
, RmH
;
725 unsigned long temp0
, temp1
, temp2
, temp3
;
726 unsigned long Res2
, Res1
, Res0
;
729 RnH
= (rn
>> 16) & 0xffff;
731 RmH
= (rm
>> 16) & 0xffff;
737 Res1
= temp1
+ temp2
;
740 temp1
= (Res1
<< 16) & 0xffff0000;
741 Res0
= temp0
+ temp1
;
744 Res2
+= ((Res1
>> 16) & 0xffff) + temp3
;
759 macw (regs
, memory
, n
, m
)
761 unsigned char *memory
;
765 long prod
, macl
, sum
;
767 tempm
=RSWAT(regs
[m
]); regs
[m
]+=2;
768 tempn
=RSWAT(regs
[n
]); regs
[n
]+=2;
771 prod
= (long)(short) tempm
* (long)(short) tempn
;
775 if ((~(prod
^ macl
) & (sum
^ prod
)) < 0)
777 /* MACH's lsb is a sticky overflow bit. */
779 /* Store the smallest negative number in MACL if prod is
780 negative, and the largest positive number otherwise. */
781 sum
= 0x7fffffff + (prod
< 0);
787 /* Add to MACH the sign extended product, and carry from low sum. */
788 mach
= MACH
+ (-(prod
< 0)) + ((unsigned long) sum
< prod
);
789 /* Sign extend at 10:th bit in MACH. */
790 MACH
= (mach
& 0x1ff) | -(mach
& 0x200);
795 /* Set the memory size to the power of two provided. */
802 saved_state
.asregs
.msize
= 1 << power
;
804 sim_memory_size
= power
;
806 if (saved_state
.asregs
.memory
)
808 free (saved_state
.asregs
.memory
);
811 saved_state
.asregs
.memory
=
812 (unsigned char *) calloc (64, saved_state
.asregs
.msize
/ 64);
814 if (!saved_state
.asregs
.memory
)
817 "Not enough VM for simulation of %d bytes of RAM\n",
818 saved_state
.asregs
.msize
);
820 saved_state
.asregs
.msize
= 1;
821 saved_state
.asregs
.memory
= (unsigned char *) calloc (1, 1);
826 set_static_little_endian (x
)
835 int little_endian
= little_endian_p
;
837 set_static_little_endian (little_endian
);
839 if (saved_state
.asregs
.msize
!= 1 << sim_memory_size
)
841 sim_size (sim_memory_size
);
844 if (saved_state
.asregs
.profile
&& !profile_file
)
846 profile_file
= fopen ("gmon.out", "wb");
847 /* Seek to where to put the call arc data */
848 nsamples
= (1 << sim_profile_size
);
850 fseek (profile_file
, nsamples
* 2 + 12, 0);
854 fprintf (stderr
, "Can't open gmon.out\n");
858 saved_state
.asregs
.profile_hist
=
859 (unsigned short *) calloc (64, (nsamples
* sizeof (short) / 64));
872 p
= saved_state
.asregs
.profile_hist
;
874 maxpc
= (1 << sim_profile_size
);
876 fseek (profile_file
, 0L, 0);
877 swapout (minpc
<< PROFILE_SHIFT
);
878 swapout (maxpc
<< PROFILE_SHIFT
);
879 swapout (nsamples
* 2 + 12);
880 for (i
= 0; i
< nsamples
; i
++)
881 swapout16 (saved_state
.asregs
.profile_hist
[i
]);
895 #define MMASKB ((saved_state.asregs.msize -1) & ~0)
901 saved_state
.asregs
.exception
= SIGINT
;
906 sim_resume (sd
, step
, siggnal
)
910 register unsigned int pc
;
911 register int cycles
= 0;
912 register int stalls
= 0;
913 register int memstalls
= 0;
914 register int insts
= 0;
915 register int prevlock
;
916 register int thislock
;
917 register unsigned int doprofile
;
918 register int pollcount
= 0;
919 register int little_endian
= little_endian_p
;
921 int tick_start
= get_now ();
923 extern unsigned char sh_jump_table0
[];
925 register unsigned char *jump_table
= sh_jump_table0
;
927 register int *R
= &(saved_state
.asregs
.regs
[0]);
928 register float *F
= &(saved_state
.asregs
.fregs
[0]);
932 register int maskb
= ((saved_state
.asregs
.msize
- 1) & ~0);
933 register int maskw
= ((saved_state
.asregs
.msize
- 1) & ~1);
934 register int maskl
= ((saved_state
.asregs
.msize
- 1) & ~3);
935 register unsigned char *memory
;
936 register unsigned int sbit
= ((unsigned int) 1 << 31);
938 prev
= signal (SIGINT
, control_c
);
942 memory
= saved_state
.asregs
.memory
;
946 saved_state
.asregs
.exception
= SIGTRAP
;
950 saved_state
.asregs
.exception
= 0;
953 pc
= saved_state
.asregs
.pc
;
954 PR
= saved_state
.asregs
.pr
;
955 T
= saved_state
.asregs
.sr
.bits
.t
;
956 prevlock
= saved_state
.asregs
.prevlock
;
957 thislock
= saved_state
.asregs
.thislock
;
958 doprofile
= saved_state
.asregs
.profile
;
960 /* If profiling not enabled, disable it by asking for
961 profiles infrequently. */
967 register unsigned int iword
= RUWAT (pc
);
968 register unsigned int ult
;
980 if (pollcount
> 1000)
983 if ((*callback
->poll_quit
) != NULL
984 && (*callback
->poll_quit
) (callback
))
995 if (cycles
>= doprofile
)
998 saved_state
.asregs
.cycles
+= doprofile
;
1000 if (saved_state
.asregs
.profile_hist
)
1002 int n
= pc
>> PROFILE_SHIFT
;
1005 int i
= saved_state
.asregs
.profile_hist
[n
];
1007 saved_state
.asregs
.profile_hist
[n
] = i
+ 1;
1014 while (!saved_state
.asregs
.exception
);
1016 if (saved_state
.asregs
.exception
== SIGILL
1017 || saved_state
.asregs
.exception
== SIGBUS
)
1022 saved_state
.asregs
.ticks
+= get_now () - tick_start
;
1023 saved_state
.asregs
.cycles
+= cycles
;
1024 saved_state
.asregs
.stalls
+= stalls
;
1025 saved_state
.asregs
.memstalls
+= memstalls
;
1026 saved_state
.asregs
.insts
+= insts
;
1027 saved_state
.asregs
.pc
= pc
;
1028 saved_state
.asregs
.sr
.bits
.t
= T
;
1029 saved_state
.asregs
.pr
= PR
;
1031 saved_state
.asregs
.prevlock
= prevlock
;
1032 saved_state
.asregs
.thislock
= thislock
;
1039 signal (SIGINT
, prev
);
1043 sim_write (sd
, addr
, buffer
, size
)
1046 unsigned char *buffer
;
1053 for (i
= 0; i
< size
; i
++)
1055 saved_state
.asregs
.memory
[MMASKB
& (addr
+ i
)] = buffer
[i
];
1061 sim_read (sd
, addr
, buffer
, size
)
1064 unsigned char *buffer
;
1071 for (i
= 0; i
< size
; i
++)
1073 buffer
[i
] = saved_state
.asregs
.memory
[MMASKB
& (addr
+ i
)];
1079 sim_store_register (sd
, rn
, memory
)
1082 unsigned char *memory
;
1085 saved_state
.asregs
.regs
[rn
] = RLAT(0);
1089 sim_fetch_register (sd
, rn
, memory
)
1092 unsigned char *memory
;
1095 WLAT (0, saved_state
.asregs
.regs
[rn
]);
1106 sim_stop_reason (sd
, reason
, sigrc
)
1108 enum sim_stop
*reason
;
1111 /* The SH simulator uses SIGQUIT to indicate that the program has
1112 exited, so we must check for it here and translate it to exit. */
1113 if (saved_state
.asregs
.exception
== SIGQUIT
)
1115 *reason
= sim_exited
;
1116 *sigrc
= saved_state
.asregs
.regs
[5];
1120 *reason
= sim_stopped
;
1121 *sigrc
= saved_state
.asregs
.exception
;
1126 sim_info (sd
, verbose
)
1130 double timetaken
= (double) saved_state
.asregs
.ticks
/ (double) now_persec ();
1131 double virttime
= saved_state
.asregs
.cycles
/ 36.0e6
;
1133 callback
->printf_filtered (callback
, "\n\n# instructions executed %10d\n",
1134 saved_state
.asregs
.insts
);
1135 callback
->printf_filtered (callback
, "# cycles %10d\n",
1136 saved_state
.asregs
.cycles
);
1137 callback
->printf_filtered (callback
, "# pipeline stalls %10d\n",
1138 saved_state
.asregs
.stalls
);
1139 callback
->printf_filtered (callback
, "# misaligned load/store %10d\n",
1140 saved_state
.asregs
.memstalls
);
1141 callback
->printf_filtered (callback
, "# real time taken %10.4f\n",
1143 callback
->printf_filtered (callback
, "# virtual time taken %10.4f\n",
1145 callback
->printf_filtered (callback
, "# profiling size %10d\n",
1147 callback
->printf_filtered (callback
, "# profiling frequency %10d\n",
1148 saved_state
.asregs
.profile
);
1149 callback
->printf_filtered (callback
, "# profile maxpc %10x\n",
1150 (1 << sim_profile_size
) << PROFILE_SHIFT
);
1154 callback
->printf_filtered (callback
, "# cycles/second %10d\n",
1155 (int) (saved_state
.asregs
.cycles
/ timetaken
));
1156 callback
->printf_filtered (callback
, "# simulation ratio %10.4f\n",
1157 virttime
/ timetaken
);
1165 saved_state
.asregs
.profile
= n
;
1169 sim_set_profile_size (n
)
1172 sim_profile_size
= n
;
1176 sim_open (kind
, cb
, abfd
, argv
)
1188 for (p
= argv
+ 1; *p
!= NULL
; ++p
)
1190 if (strcmp (*p
, "-E") == 0)
1195 /* FIXME: This doesn't use stderr, but then the rest of the
1196 file doesn't either. */
1197 callback
->printf_filtered (callback
, "Missing argument to `-E'.\n");
1200 little_endian_p
= strcmp (*p
, "big") != 0;
1202 else if (isdigit (**p
))
1203 parse_and_set_memory_size (*p
);
1206 /* fudge our descriptor for now */
1207 return (SIM_DESC
) 1;
1211 parse_and_set_memory_size (str
)
1216 n
= strtol (str
, NULL
, 10);
1217 if (n
> 0 && n
<= 24)
1218 sim_memory_size
= n
;
1220 callback
->printf_filtered (callback
, "Bad memory size %d; must be 1 to 24, inclusive\n", n
);
1224 sim_close (sd
, quitting
)
1232 sim_load (sd
, prog
, abfd
, from_tty
)
1238 extern bfd
*sim_load_file (); /* ??? Don't know where this should live. */
1241 prog_bfd
= sim_load_file (sd
, myname
, callback
, prog
, abfd
,
1242 sim_kind
== SIM_OPEN_DEBUG
);
1243 if (prog_bfd
== NULL
)
1246 bfd_close (prog_bfd
);
1251 sim_create_inferior (sd
, abfd
, argv
, env
)
1258 saved_state
.asregs
.pc
= bfd_get_start_address (abfd
);
1260 saved_state
.asregs
.pc
= 0;
1265 sim_do_command (sd
, cmd
)
1269 char *sms_cmd
= "set-memory-size";
1272 if (cmd
== NULL
|| *cmd
== '\0')
1277 cmdsize
= strlen (sms_cmd
);
1278 if (strncmp (cmd
, sms_cmd
, cmdsize
) == 0 && strchr (" \t", cmd
[cmdsize
]) != NULL
)
1280 parse_and_set_memory_size (cmd
+ cmdsize
+ 1);
1282 else if (strcmp (cmd
, "help") == 0)
1284 (callback
->printf_filtered
) (callback
, "List of SH simulator commands:\n\n");
1285 (callback
->printf_filtered
) (callback
, "set-memory-size <n> -- Set the number of address bits to use\n");
1286 (callback
->printf_filtered
) (callback
, "\n");
1290 (callback
->printf_filtered
) (callback
, "Error: \"%s\" is not a valid SH simulator command.\n", cmd
);
1295 sim_set_callbacks (p
)