]>
Commit | Line | Data |
---|---|---|
594266fc SC |
1 | /* Simulator for the Hitachi SH architecture. |
2 | ||
3 | Written by Steve Chamberlain of Cygnus Support. | |
4 | [email protected] | |
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 | */ | |
fe031f82 | 20 | |
631f6b24 | 21 | #include <signal.h> |
90fe361f | 22 | #include "sysdep.h" |
594266fc SC |
23 | #include <sys/times.h> |
24 | #include <sys/param.h> | |
631f6b24 | 25 | #include "bfd.h" |
fe031f82 DE |
26 | #include "remote-sim.h" |
27 | #include "../../newlib/libc/sys/sh/sys/syscall.h" | |
594266fc SC |
28 | #define O_RECOMPILE 85 |
29 | #define DEFINE_TABLE | |
4d0be1f5 | 30 | /*#define ACE_FAST*/ |
594266fc SC |
31 | #define DISASSEMBLER_TABLE |
32 | ||
33 | #define SBIT(x) ((x)&sbit) | |
90fe361f SC |
34 | #define R0 saved_state.asregs.regs[0] |
35 | #define Rn saved_state.asregs.regs[n] | |
36 | #define Rm saved_state.asregs.regs[m] | |
37 | #define UR0 (unsigned int)(saved_state.asregs.regs[0]) | |
38 | #define UR (unsigned int)R | |
39 | #define UR (unsigned int)R | |
40 | #define SR0 saved_state.asregs.regs[0] | |
41 | #define GBR saved_state.asregs.gbr | |
42 | #define VBR saved_state.asregs.vbr | |
43 | #define MACH saved_state.asregs.mach | |
44 | #define MACL saved_state.asregs.macl | |
45 | #define M saved_state.asregs.sr.bits.m | |
46 | #define Q saved_state.asregs.sr.bits.q | |
0fb39e84 | 47 | #define S saved_state.asregs.sr.bits.s |
594266fc | 48 | |
594266fc SC |
49 | #define GET_SR() (saved_state.asregs.sr.bits.t = T, saved_state.asregs.sr.word) |
50 | #define SET_SR(x) {saved_state.asregs.sr.word = (x); T =saved_state.asregs.sr.bits.t;} | |
51 | ||
52 | #define PC pc | |
53 | #define C cycles | |
54 | ||
4d0be1f5 SC |
55 | int |
56 | fail () | |
fe031f82 | 57 | { |
4d0be1f5 | 58 | abort (); |
fe031f82 DE |
59 | |
60 | } | |
61 | ||
4d0be1f5 SC |
62 | #define BUSERROR(addr, mask) \ |
63 | if (addr & ~mask) { saved_state.asregs.exception = SIGBUS;} | |
fe031f82 DE |
64 | |
65 | /* Define this to enable register lifetime checking. | |
4d0be1f5 | 66 | The compiler generates "add #0,rn" insns to mark registers as invalid, |
fe031f82 DE |
67 | the simulator uses this info to call fail if it finds a ref to an invalid |
68 | register before a def | |
4d0be1f5 | 69 | |
fe031f82 DE |
70 | #define PARANOID |
71 | */ | |
72 | ||
73 | #ifdef PARANOID | |
74 | int valid[16]; | |
75 | #define CREF(x) if(!valid[x]) fail(); | |
76 | #define CDEF(x) valid[x] = 1; | |
77 | #define UNDEF(x) valid[x] = 0; | |
78 | #else | |
79 | #define CREF(x) | |
80 | #define CDEF(x) | |
81 | #define UNDEF(x) | |
82 | #endif | |
83 | ||
0fb39e84 | 84 | static int IOMEM PARAMS ((int addr, int write, int value)); |
90fe361f | 85 | |
4d0be1f5 SC |
86 | /* These variables are at file scope so that functions other than |
87 | sim_resume can use the fetch/store macros */ | |
90fe361f | 88 | |
4d0be1f5 | 89 | static int little_endian; |
90fe361f | 90 | |
4d0be1f5 SC |
91 | #if 1 |
92 | static int maskl = ~0; | |
93 | static int maskw = ~0; | |
94 | #endif | |
95 | typedef union | |
96 | { | |
90fe361f | 97 | |
4d0be1f5 SC |
98 | struct |
99 | { | |
90fe361f | 100 | |
4d0be1f5 SC |
101 | int regs[16]; |
102 | int pc; | |
103 | int pr; | |
90fe361f | 104 | |
4d0be1f5 SC |
105 | int gbr; |
106 | int vbr; | |
107 | int mach; | |
108 | int macl; | |
109 | ||
110 | ||
111 | union | |
112 | { | |
113 | struct | |
114 | { | |
115 | unsigned int d0:22; | |
116 | unsigned int m:1; | |
117 | unsigned int q:1; | |
118 | unsigned int i:4; | |
119 | unsigned int d1:2; | |
120 | unsigned int s:1; | |
121 | unsigned int t:1; | |
122 | } | |
123 | bits; | |
124 | int word; | |
125 | } | |
126 | sr; | |
127 | int ticks; | |
128 | int stalls; | |
129 | int cycles; | |
130 | int insts; | |
131 | ||
132 | ||
133 | int prevlock; | |
134 | int thislock; | |
135 | int exception; | |
136 | int msize; | |
137 | #define PROFILE_FREQ 1 | |
138 | #define PROFILE_SHIFT 2 | |
139 | int profile; | |
140 | unsigned short *profile_hist; | |
141 | unsigned char *memory; | |
142 | ||
143 | } | |
144 | asregs; | |
145 | int asints[28]; | |
146 | ||
147 | } saved_state_type; | |
148 | saved_state_type saved_state; | |
149 | ||
150 | static void INLINE | |
151 | wlat_little (memory, x, value, maskl) | |
152 | unsigned char *memory; | |
153 | { | |
154 | int v = value; | |
155 | unsigned char *p = memory + ((x) & maskl); | |
156 | BUSERROR(x, maskl); | |
157 | p[3] = v >> 24; | |
158 | p[2] = v >> 16; | |
159 | p[1] = v >> 8; | |
160 | p[0] = v; | |
161 | } | |
162 | ||
163 | static void INLINE | |
164 | wwat_little (memory, x, value, maskw) | |
165 | unsigned char *memory; | |
166 | { | |
167 | int v = value; | |
168 | unsigned char *p = memory + ((x) & maskw); | |
169 | BUSERROR(x, maskw); | |
170 | ||
171 | p[1] = v >> 8; | |
172 | p[0] = v; | |
173 | } | |
174 | ||
175 | ||
176 | static void INLINE | |
177 | wbat_any (memory, x, value, maskb) | |
178 | unsigned char *memory; | |
179 | { | |
180 | unsigned char *p = memory + (x & maskb); | |
181 | if (x > 0x5000000) | |
182 | IOMEM (x, 1, value); | |
183 | BUSERROR(x, maskb); | |
184 | ||
185 | p[0] = value; | |
186 | } | |
90fe361f | 187 | |
90fe361f SC |
188 | |
189 | ||
4d0be1f5 SC |
190 | static void INLINE |
191 | wlat_big (memory, x, value, maskl) | |
192 | unsigned char *memory; | |
193 | { | |
194 | int v = value; | |
195 | unsigned char *p = memory + ((x) & maskl); | |
196 | BUSERROR(x, maskl); | |
197 | ||
198 | p[0] = v >> 24; | |
199 | p[1] = v >> 16; | |
200 | p[2] = v >> 8; | |
201 | p[3] = v; | |
202 | } | |
203 | ||
204 | static void INLINE | |
205 | wwat_big (memory, x, value, maskw) | |
206 | unsigned char *memory; | |
207 | { | |
208 | int v = value; | |
209 | unsigned char *p = memory + ((x) & maskw); | |
210 | BUSERROR(x, maskw); | |
211 | ||
212 | p[0] = v >> 8; | |
213 | p[1] = v; | |
214 | } | |
215 | ||
216 | ||
217 | static void INLINE | |
218 | wbat_big (memory, x, value, maskb) | |
219 | unsigned char *memory; | |
220 | { | |
221 | unsigned char *p = memory + (x & maskb); | |
222 | BUSERROR(x, maskb); | |
223 | ||
224 | if (x > 0x5000000) | |
225 | IOMEM (x, 1, value); | |
226 | p[0] = value; | |
227 | } | |
228 | ||
229 | ||
230 | ||
231 | /* Read functions */ | |
232 | static int INLINE | |
233 | rlat_little (memory, x, maskl) | |
234 | unsigned char *memory; | |
235 | { | |
236 | unsigned char *p = memory + ((x) & maskl); | |
237 | BUSERROR(x, maskl); | |
238 | ||
239 | return (p[3] << 24) | (p[2] << 16) | (p[1] << 8) | p[0]; | |
240 | ||
241 | } | |
242 | ||
243 | static int INLINE | |
244 | rwat_little (memory, x, maskw) | |
245 | unsigned char *memory; | |
246 | { | |
247 | unsigned char *p = memory + ((x) & maskw); | |
248 | BUSERROR(x, maskw); | |
249 | ||
250 | return (p[1] << 8) | p[0]; | |
251 | } | |
252 | ||
253 | static int INLINE | |
254 | rbat_any (memory, x, maskb) | |
255 | unsigned char *memory; | |
256 | { | |
257 | unsigned char *p = memory + ((x) & maskb); | |
258 | BUSERROR(x, maskb); | |
259 | ||
260 | return p[0]; | |
261 | } | |
262 | ||
263 | static int INLINE | |
264 | rlat_big (memory, x, maskl) | |
265 | unsigned char *memory; | |
266 | { | |
267 | unsigned char *p = memory + ((x) & maskl); | |
268 | BUSERROR(x, maskl); | |
269 | ||
270 | return (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]; | |
271 | ||
272 | } | |
273 | ||
274 | static int INLINE | |
275 | rwat_big (memory, x, maskw) | |
276 | unsigned char *memory; | |
277 | { | |
278 | unsigned char *p = memory + ((x) & maskw); | |
279 | BUSERROR(x, maskw); | |
280 | ||
281 | return (p[0] << 8) | p[1]; | |
282 | } | |
283 | ||
284 | ||
285 | #define RWAT(x) (little_endian ? rwat_little(memory, x, maskw): rwat_big(memory, x, maskw)) | |
286 | #define RLAT(x) (little_endian ? rlat_little(memory, x, maskl): rlat_big(memory, x, maskl)) | |
287 | #define RBAT(x) (rbat_any (memory, x, maskb)) | |
288 | #define WWAT(x,v) (little_endian ? wwat_little(memory, x, v, maskw): wwat_big(memory, x, v, maskw)) | |
289 | #define WLAT(x,v) (little_endian ? wlat_little(memory, x, v, maskl): wlat_big(memory, x, v, maskl)) | |
290 | #define WBAT(x,v) (wbat_any (memory, x, v, maskb)) | |
291 | ||
292 | #define RUWAT(x) (RWAT(x) & 0xffff) | |
293 | #define RSWAT(x) ((short)(RWAT(x))) | |
294 | #define RSBAT(x) (SEXT(RBAT(x))) | |
90fe361f SC |
295 | |
296 | #define SEXT(x) (((x&0xff) ^ (~0x7f))+0x80) | |
297 | #define SEXTW(y) ((int)((short)y)) | |
298 | ||
299 | #define SL(TEMPPC) iword= RUWAT(TEMPPC); goto top; | |
300 | ||
301 | ||
fe031f82 DE |
302 | int empty[16]; |
303 | ||
90fe361f SC |
304 | #define L(x) thislock = x; |
305 | #define TL(x) if ((x) == prevlock) stalls++; | |
306 | #define TB(x,y) if ((x) == prevlock || (y)==prevlock) stalls++; | |
fe031f82 DE |
307 | |
308 | #ifdef __GO32__ | |
90fe361f | 309 | int sim_memory_size = 19; |
fe031f82 DE |
310 | #else |
311 | int sim_memory_size = 24; | |
312 | #endif | |
313 | ||
90fe361f SC |
314 | static int sim_profile_size = 17; |
315 | static int nsamples; | |
631f6b24 | 316 | |
4d0be1f5 SC |
317 | #undef TB |
318 | #define TB(x,y) | |
594266fc | 319 | |
4d0be1f5 SC |
320 | #define SMR1 (0x05FFFEC8) /* Channel 1 serial mode register */ |
321 | #define BRR1 (0x05FFFEC9) /* Channel 1 bit rate register */ | |
322 | #define SCR1 (0x05FFFECA) /* Channel 1 serial control register */ | |
323 | #define TDR1 (0x05FFFECB) /* Channel 1 transmit data register */ | |
324 | #define SSR1 (0x05FFFECC) /* Channel 1 serial status register */ | |
325 | #define RDR1 (0x05FFFECD) /* Channel 1 receive data register */ | |
594266fc | 326 | |
4d0be1f5 SC |
327 | #define SCI_RDRF 0x40 /* Recieve data register full */ |
328 | #define SCI_TDRE 0x80 /* Transmit data register empty */ | |
594266fc | 329 | |
4d0be1f5 SC |
330 | static int |
331 | IOMEM (addr, write, value) | |
332 | int addr; | |
333 | int write; | |
334 | int value; | |
335 | { | |
336 | static int io; | |
337 | static char ssr1; | |
338 | int x; | |
339 | static char lastchar; | |
594266fc | 340 | |
4d0be1f5 SC |
341 | if (write) |
342 | { | |
343 | switch (addr) | |
594266fc | 344 | { |
4d0be1f5 SC |
345 | case TDR1: |
346 | if (value != '\r') | |
594266fc | 347 | { |
4d0be1f5 SC |
348 | putchar (value); |
349 | fflush (stdout); | |
594266fc | 350 | } |
4d0be1f5 SC |
351 | break; |
352 | } | |
353 | } | |
354 | else | |
355 | { | |
356 | switch (addr) | |
357 | { | |
358 | case RDR1: | |
359 | return getchar (); | |
594266fc | 360 | } |
594266fc | 361 | } |
594266fc SC |
362 | } |
363 | ||
4d0be1f5 | 364 | |
594266fc | 365 | |
594266fc SC |
366 | static int |
367 | get_now () | |
368 | { | |
4d0be1f5 | 369 | return time ((long *) 0); |
594266fc SC |
370 | } |
371 | ||
372 | static int | |
373 | now_persec () | |
374 | { | |
631f6b24 | 375 | return 1; |
90fe361f SC |
376 | } |
377 | ||
378 | ||
379 | ||
380 | static FILE *profile_file; | |
381 | ||
4d0be1f5 SC |
382 | static void |
383 | swap (memory, n) | |
384 | unsigned char *memory; | |
90fe361f | 385 | int n; |
fdc506e6 | 386 | { |
4d0be1f5 | 387 | WLAT (0, n); |
90fe361f | 388 | } |
4d0be1f5 SC |
389 | static void |
390 | swap16 (memory, n) | |
391 | unsigned char *memory; | |
90fe361f | 392 | int n; |
fdc506e6 | 393 | { |
4d0be1f5 | 394 | WWAT (0, n); |
594266fc SC |
395 | } |
396 | ||
90fe361f | 397 | static void |
fdc506e6 | 398 | swapout (n) |
90fe361f SC |
399 | int n; |
400 | { | |
fdc506e6 | 401 | if (profile_file) |
90fe361f SC |
402 | { |
403 | char b[4]; | |
fdc506e6 SC |
404 | swap (b, n); |
405 | fwrite (b, 4, 1, profile_file); | |
90fe361f | 406 | } |
fdc506e6 | 407 | } |
90fe361f SC |
408 | |
409 | static void | |
fdc506e6 | 410 | swapout16 (n) |
90fe361f SC |
411 | int n; |
412 | { | |
413 | char b[4]; | |
fdc506e6 SC |
414 | swap16 (b, n); |
415 | fwrite (b, 2, 1, profile_file); | |
416 | } | |
90fe361f SC |
417 | |
418 | ||
419 | /* Turn a pointer in a register into a pointer into real memory. */ | |
420 | ||
421 | static char * | |
422 | ptr (x) | |
423 | int x; | |
424 | { | |
fdc506e6 | 425 | return (char *) (x + saved_state.asregs.memory); |
90fe361f SC |
426 | } |
427 | ||
fe031f82 DE |
428 | |
429 | /* Simulate a monitor trap, put the result into r0 and errno into r1 */ | |
90fe361f | 430 | static void |
4d0be1f5 | 431 | trap (i, regs, memory, maskl, maskw, little_endian) |
90fe361f | 432 | int i; |
594266fc | 433 | int *regs; |
4d0be1f5 | 434 | unsigned char *memory; |
594266fc SC |
435 | { |
436 | switch (i) | |
437 | { | |
438 | case 1: | |
439 | printf ("%c", regs[0]); | |
440 | break; | |
441 | case 2: | |
442 | saved_state.asregs.exception = SIGQUIT; | |
443 | break; | |
4d0be1f5 SC |
444 | #if 0 |
445 | case 8: | |
446 | trap8 (ptr (regs[4])); | |
447 | break; | |
448 | case 9: | |
449 | trap9 (ptr (regs[4])); | |
450 | break; | |
451 | case 10: | |
452 | trap10 (); | |
453 | break; | |
454 | case 11: | |
455 | regs[0] = trap11 (); | |
456 | break; | |
457 | case 12: | |
458 | regs[0] = trap12 (); | |
459 | break; | |
460 | #endif | |
90fe361f SC |
461 | case 3: |
462 | { | |
463 | extern int errno; | |
464 | int perrno = errno; | |
465 | errno = 0; | |
466 | ||
467 | switch (regs[4]) | |
468 | { | |
4d0be1f5 | 469 | |
fe031f82 | 470 | #ifndef __GO32__ |
fe031f82 | 471 | |
4d0be1f5 SC |
472 | case SYS_fork: |
473 | regs[0] = fork (); | |
474 | break; | |
fe031f82 | 475 | case SYS_execve: |
4d0be1f5 | 476 | regs[0] = execve (ptr (regs[5]), ptr (regs[6]), ptr (regs[7])); |
fe031f82 DE |
477 | break; |
478 | case SYS_execv: | |
4d0be1f5 | 479 | regs[0] = execv (ptr (regs[5]), ptr (regs[6])); |
fe031f82 DE |
480 | break; |
481 | case SYS_pipe: | |
482 | { | |
4d0be1f5 | 483 | char *buf; |
fe031f82 DE |
484 | int host_fd[2]; |
485 | ||
4d0be1f5 | 486 | buf = ptr (regs[5]); |
fe031f82 | 487 | |
4d0be1f5 | 488 | regs[0] = pipe (host_fd); |
fe031f82 | 489 | |
4d0be1f5 SC |
490 | WLAT (buf, host_fd[0]); |
491 | buf += 4; | |
492 | WLAT (buf, host_fd[1]); | |
fe031f82 DE |
493 | } |
494 | break; | |
495 | ||
4d0be1f5 SC |
496 | case SYS_wait: |
497 | regs[0] = wait (ptr (regs[5])); | |
fe031f82 DE |
498 | break; |
499 | #endif | |
4d0be1f5 | 500 | |
fe031f82 DE |
501 | case SYS_read: |
502 | regs[0] = read (regs[5], ptr (regs[6]), regs[7]); | |
90fe361f | 503 | break; |
fe031f82 DE |
504 | case SYS_write: |
505 | regs[0] = write (regs[5], ptr (regs[6]), regs[7]); | |
90fe361f | 506 | break; |
fe031f82 DE |
507 | case SYS_lseek: |
508 | regs[0] = lseek (regs[5], regs[6], regs[7]); | |
90fe361f | 509 | break; |
fe031f82 DE |
510 | case SYS_close: |
511 | regs[0] = close (regs[5]); | |
90fe361f | 512 | break; |
fe031f82 DE |
513 | case SYS_open: |
514 | regs[0] = open (ptr (regs[5]), regs[6]); | |
90fe361f | 515 | break; |
fe031f82 | 516 | case SYS_exit: |
4d0be1f5 SC |
517 | /* EXIT - caller can look in r5 to work out the |
518 | reason */ | |
631f6b24 | 519 | saved_state.asregs.exception = SIGQUIT; |
631f6b24 | 520 | break; |
4d0be1f5 SC |
521 | |
522 | case SYS_stat: /* added at hmsi */ | |
fe031f82 | 523 | /* stat system call */ |
4d0be1f5 | 524 | { |
fe031f82 DE |
525 | struct stat host_stat; |
526 | char *buf; | |
527 | ||
4d0be1f5 SC |
528 | regs[0] = stat (ptr (regs[5]), &host_stat); |
529 | ||
530 | buf = ptr (regs[6]); | |
531 | ||
532 | WWAT (buf, host_stat.st_dev); | |
533 | buf += 2; | |
534 | WWAT (buf, host_stat.st_ino); | |
535 | buf += 2; | |
536 | WLAT (buf, host_stat.st_mode); | |
537 | buf += 4; | |
538 | WWAT (buf, host_stat.st_nlink); | |
539 | buf += 2; | |
540 | WWAT (buf, host_stat.st_uid); | |
541 | buf += 2; | |
542 | WWAT (buf, host_stat.st_gid); | |
543 | buf += 2; | |
544 | WWAT (buf, host_stat.st_rdev); | |
545 | buf += 2; | |
546 | WLAT (buf, host_stat.st_size); | |
547 | buf += 4; | |
548 | WLAT (buf, host_stat.st_atime); | |
549 | buf += 4; | |
550 | WLAT (buf, 0); | |
551 | buf += 4; | |
552 | WLAT (buf, host_stat.st_mtime); | |
553 | buf += 4; | |
554 | WLAT (buf, 0); | |
555 | buf += 4; | |
556 | WLAT (buf, host_stat.st_ctime); | |
557 | buf += 4; | |
558 | WLAT (buf, 0); | |
559 | buf += 4; | |
560 | WLAT (buf, 0); | |
561 | buf += 4; | |
562 | WLAT (buf, 0); | |
563 | buf += 4; | |
564 | } | |
565 | break; | |
fe031f82 | 566 | |
4d0be1f5 SC |
567 | case SYS_chown: |
568 | regs[0] = chown (ptr (regs[5]), regs[6], regs[7]); | |
fe031f82 DE |
569 | break; |
570 | case SYS_chmod: | |
4d0be1f5 SC |
571 | regs[0] = chmod (ptr (regs[5]), regs[6]); |
572 | break; | |
573 | case SYS_utime: | |
574 | regs[0] = utime (ptr (regs[5]), ptr (regs[6])); | |
fe031f82 | 575 | break; |
90fe361f SC |
576 | default: |
577 | abort (); | |
578 | } | |
fe031f82 | 579 | regs[1] = errno; |
90fe361f SC |
580 | errno = perrno; |
581 | } | |
582 | ||
583 | break; | |
584 | ||
4d0be1f5 | 585 | case 0xc3: |
594266fc | 586 | case 255: |
631f6b24 | 587 | saved_state.asregs.exception = SIGTRAP; |
594266fc SC |
588 | break; |
589 | } | |
590 | ||
591 | } | |
592 | void | |
593 | control_c (sig, code, scp, addr) | |
594 | int sig; | |
595 | int code; | |
596 | char *scp; | |
597 | char *addr; | |
598 | { | |
599 | saved_state.asregs.exception = SIGINT; | |
600 | } | |
601 | ||
602 | ||
fdc506e6 | 603 | static int |
90fe361f | 604 | div1 (R, iRn2, iRn1, T) |
594266fc | 605 | int *R; |
90fe361f SC |
606 | int iRn1; |
607 | int iRn2; | |
594266fc SC |
608 | int T; |
609 | { | |
610 | unsigned long tmp0; | |
611 | unsigned char old_q, tmp1; | |
90fe361f | 612 | |
594266fc | 613 | old_q = Q; |
90fe361f SC |
614 | Q = (unsigned char) ((0x80000000 & R[iRn1]) != 0); |
615 | R[iRn1] <<= 1; | |
616 | R[iRn1] |= (unsigned long) T; | |
617 | ||
618 | switch (old_q) | |
594266fc | 619 | { |
fdc506e6 | 620 | case 0: |
90fe361f | 621 | switch (M) |
fdc506e6 SC |
622 | { |
623 | case 0: | |
624 | tmp0 = R[iRn1]; | |
625 | R[iRn1] -= R[iRn2]; | |
626 | tmp1 = (R[iRn1] > tmp0); | |
627 | switch (Q) | |
628 | { | |
629 | case 0: | |
630 | Q = tmp1; | |
631 | break; | |
632 | case 1: | |
633 | Q = (unsigned char) (tmp1 == 0); | |
634 | break; | |
635 | } | |
636 | break; | |
637 | case 1: | |
638 | tmp0 = R[iRn1]; | |
639 | R[iRn1] += R[iRn2]; | |
640 | tmp1 = (R[iRn1] < tmp0); | |
641 | switch (Q) | |
642 | { | |
643 | case 0: | |
644 | Q = (unsigned char) (tmp1 == 0); | |
645 | break; | |
646 | case 1: | |
647 | Q = tmp1; | |
648 | break; | |
649 | } | |
650 | break; | |
651 | } | |
594266fc SC |
652 | break; |
653 | case 1: | |
654 | switch (M) | |
655 | { | |
fdc506e6 | 656 | case 0: |
90fe361f SC |
657 | tmp0 = R[iRn1]; |
658 | R[iRn1] += R[iRn2]; | |
659 | tmp1 = (R[iRn1] < tmp0); | |
660 | switch (Q) | |
661 | { | |
662 | case 0: | |
663 | Q = tmp1; | |
664 | break; | |
665 | case 1: | |
666 | Q = (unsigned char) (tmp1 == 0); | |
fdc506e6 | 667 | break; |
90fe361f | 668 | } |
594266fc | 669 | break; |
fdc506e6 | 670 | case 1: |
90fe361f SC |
671 | tmp0 = R[iRn1]; |
672 | R[iRn1] -= R[iRn2]; | |
673 | tmp1 = (R[iRn1] > tmp0); | |
674 | switch (Q) | |
675 | { | |
676 | case 0: | |
677 | Q = (unsigned char) (tmp1 == 0); | |
678 | break; | |
679 | case 1: | |
680 | Q = tmp1; | |
681 | break; | |
682 | } | |
594266fc SC |
683 | break; |
684 | } | |
685 | break; | |
90fe361f SC |
686 | } |
687 | T = (Q == M); | |
688 | return T; | |
689 | } | |
690 | ||
90fe361f | 691 | |
4d0be1f5 | 692 | static void |
fdc506e6 SC |
693 | dmul (sign, rm, rn) |
694 | int sign; | |
695 | unsigned int rm; | |
696 | unsigned int rn; | |
697 | { | |
698 | unsigned long RnL, RnH; | |
699 | unsigned long RmL, RmH; | |
700 | unsigned long temp0, temp1, temp2, temp3; | |
701 | unsigned long Res2, Res1, Res0; | |
90fe361f | 702 | |
0fb39e84 TG |
703 | RnL = rn & 0xffff; |
704 | RnH = (rn >> 16) & 0xffff; | |
705 | RmL = rm & 0xffff; | |
706 | RmH = (rm >> 16) & 0xffff; | |
707 | temp0 = RmL * RnL; | |
708 | temp1 = RmH * RnL; | |
709 | temp2 = RmL * RnH; | |
710 | temp3 = RmH * RnH; | |
711 | Res2 = 0; | |
712 | Res1 = temp1 + temp2; | |
713 | if (Res1 < temp1) | |
714 | Res2 += 0x00010000; | |
715 | temp1 = (Res1 << 16) & 0xffff0000; | |
716 | Res0 = temp0 + temp1; | |
717 | if (Res0 < temp0) | |
718 | Res2 += 1; | |
719 | Res2 += ((Res1 >> 16) & 0xffff) + temp3; | |
720 | ||
721 | if (sign) | |
90fe361f | 722 | { |
0fb39e84 TG |
723 | if (rn & 0x80000000) |
724 | Res2 -= rm; | |
725 | if (rm & 0x80000000) | |
726 | Res2 -= rn; | |
727 | } | |
594266fc | 728 | |
0fb39e84 TG |
729 | MACH = Res2; |
730 | MACL = Res0; | |
731 | } | |
594266fc | 732 | |
0fb39e84 TG |
733 | static void |
734 | macw (regs, memory, n, m) | |
735 | int *regs; | |
736 | unsigned char *memory; | |
737 | int m, n; | |
738 | { | |
739 | long tempm, tempn; | |
740 | long prod, macl, sum; | |
fdc506e6 | 741 | |
0fb39e84 TG |
742 | tempm=RSWAT(regs[m]); regs[m]+=2; |
743 | tempn=RSWAT(regs[n]); regs[n]+=2; | |
744 | ||
745 | macl = MACL; | |
746 | prod = (long)(short) tempm * (long)(short) tempn; | |
747 | sum = prod + macl; | |
748 | if (S) | |
749 | { | |
750 | if ((~(prod ^ macl) & (sum ^ prod)) < 0) | |
751 | { | |
752 | /* MACH's lsb is a sticky overflow bit. */ | |
753 | MACH |= 1; | |
754 | /* Store the smallest negative number in MACL if prod is | |
755 | negative, and the largest positive number otherwise. */ | |
756 | sum = 0x7fffffff + (prod < 0); | |
757 | } | |
758 | } | |
fdc506e6 | 759 | else |
90fe361f | 760 | { |
0fb39e84 TG |
761 | /* Add to MACH the sign extended product, and carry from low sum. */ |
762 | MACH += (-(prod < 0)) + ((unsigned long) sum < prod); | |
90fe361f | 763 | } |
0fb39e84 | 764 | MACL = sum; |
594266fc SC |
765 | } |
766 | ||
90fe361f SC |
767 | /* Set the memory size to the power of two provided. */ |
768 | ||
769 | void | |
770 | sim_size (power) | |
771 | int power; | |
772 | ||
773 | { | |
774 | saved_state.asregs.msize = 1 << power; | |
775 | ||
fdc506e6 | 776 | sim_memory_size = power; |
90fe361f SC |
777 | |
778 | ||
779 | if (saved_state.asregs.memory) | |
780 | { | |
781 | free (saved_state.asregs.memory); | |
782 | } | |
783 | ||
784 | saved_state.asregs.memory = | |
785 | (unsigned char *) calloc (64, saved_state.asregs.msize / 64); | |
786 | ||
787 | if (!saved_state.asregs.memory) | |
788 | { | |
789 | fprintf (stderr, | |
4d0be1f5 | 790 | "Not enough VM for simulation of %d bytes of RAM\n", |
90fe361f SC |
791 | saved_state.asregs.msize); |
792 | ||
793 | saved_state.asregs.msize = 1; | |
fdc506e6 | 794 | saved_state.asregs.memory = (unsigned char *) calloc (1, 1); |
90fe361f SC |
795 | } |
796 | } | |
797 | ||
798 | ||
4d0be1f5 SC |
799 | extern int target_byte_order; |
800 | ||
801 | static void | |
802 | set_static_little_endian(x) | |
803 | int x; | |
804 | { | |
805 | little_endian = x; | |
806 | } | |
90fe361f | 807 | |
fdc506e6 | 808 | static |
90fe361f SC |
809 | void |
810 | init_pointers () | |
811 | { | |
4d0be1f5 SC |
812 | register int little_endian = target_byte_order == 1234; |
813 | set_static_little_endian (little_endian); | |
90fe361f SC |
814 | if (saved_state.asregs.msize != 1 << sim_memory_size) |
815 | { | |
816 | sim_size (sim_memory_size); | |
817 | } | |
818 | ||
819 | if (saved_state.asregs.profile && !profile_file) | |
820 | { | |
fdc506e6 | 821 | profile_file = fopen ("gmon.out", "wb"); |
90fe361f | 822 | /* Seek to where to put the call arc data */ |
fdc506e6 | 823 | nsamples = (1 << sim_profile_size); |
90fe361f | 824 | |
fdc506e6 SC |
825 | fseek (profile_file, nsamples * 2 + 12, 0); |
826 | ||
827 | if (!profile_file) | |
90fe361f | 828 | { |
fdc506e6 | 829 | fprintf (stderr, "Can't open gmon.out\n"); |
90fe361f | 830 | } |
fdc506e6 | 831 | else |
90fe361f SC |
832 | { |
833 | saved_state.asregs.profile_hist = | |
fdc506e6 | 834 | (unsigned short *) calloc (64, (nsamples * sizeof (short) / 64)); |
90fe361f SC |
835 | } |
836 | } | |
837 | } | |
838 | ||
839 | static void | |
fdc506e6 | 840 | dump_profile () |
90fe361f | 841 | { |
fdc506e6 | 842 | unsigned int minpc; |
90fe361f SC |
843 | unsigned int maxpc; |
844 | unsigned short *p; | |
845 | ||
846 | int thisshift; | |
fdc506e6 | 847 | |
90fe361f SC |
848 | unsigned short *first; |
849 | ||
850 | int i; | |
851 | p = saved_state.asregs.profile_hist; | |
fdc506e6 SC |
852 | minpc = 0; |
853 | maxpc = (1 << sim_profile_size); | |
854 | ||
855 | fseek (profile_file, 0L, 0); | |
856 | swapout (minpc << PROFILE_SHIFT); | |
857 | swapout (maxpc << PROFILE_SHIFT); | |
858 | swapout (nsamples * 2 + 12); | |
859 | for (i = 0; i < nsamples; i++) | |
860 | swapout16 (saved_state.asregs.profile_hist[i]); | |
861 | ||
90fe361f SC |
862 | } |
863 | ||
4d0be1f5 | 864 | static int |
fdc506e6 | 865 | gotcall (from, to) |
90fe361f SC |
866 | int from; |
867 | int to; | |
868 | { | |
fdc506e6 SC |
869 | swapout (from); |
870 | swapout (to); | |
871 | swapout (1); | |
90fe361f SC |
872 | } |
873 | ||
874 | #define MMASKB ((saved_state.asregs.msize -1) & ~0) | |
fe031f82 | 875 | |
4d0be1f5 | 876 | |
90fe361f | 877 | void |
fe031f82 DE |
878 | sim_resume (step, siggnal) |
879 | int step, siggnal; | |
594266fc | 880 | { |
fdc506e6 | 881 | register unsigned int pc; |
90fe361f SC |
882 | register int cycles = 0; |
883 | register int stalls = 0; | |
884 | register int insts = 0; | |
885 | register int prevlock; | |
fdc506e6 SC |
886 | register int thislock; |
887 | register unsigned int doprofile; | |
4d0be1f5 SC |
888 | #ifdef __GO32__ |
889 | register int pollcount = 0; | |
890 | #endif | |
891 | register int little_endian = target_byte_order == 1234; | |
892 | ||
90fe361f | 893 | |
594266fc SC |
894 | int tick_start = get_now (); |
895 | void (*prev) (); | |
896 | extern unsigned char sh_jump_table0[]; | |
897 | ||
898 | register unsigned char *jump_table = sh_jump_table0; | |
899 | ||
900 | register int *R = &(saved_state.asregs.regs[0]); | |
901 | register int T; | |
902 | register int PR; | |
903 | ||
90fe361f SC |
904 | register int maskb = ((saved_state.asregs.msize - 1) & ~0); |
905 | register int maskw = ((saved_state.asregs.msize - 1) & ~1); | |
906 | register int maskl = ((saved_state.asregs.msize - 1) & ~3); | |
4d0be1f5 | 907 | register unsigned char *memory; |
90fe361f SC |
908 | register unsigned int sbit = (1 << 31); |
909 | ||
594266fc SC |
910 | prev = signal (SIGINT, control_c); |
911 | ||
fdc506e6 SC |
912 | init_pointers (); |
913 | ||
631f6b24 DE |
914 | memory = saved_state.asregs.memory; |
915 | ||
594266fc SC |
916 | if (step) |
917 | { | |
918 | saved_state.asregs.exception = SIGTRAP; | |
919 | } | |
920 | else | |
921 | { | |
922 | saved_state.asregs.exception = 0; | |
923 | } | |
924 | ||
925 | pc = saved_state.asregs.pc; | |
926 | PR = saved_state.asregs.pr; | |
927 | T = saved_state.asregs.sr.bits.t; | |
90fe361f SC |
928 | prevlock = saved_state.asregs.prevlock; |
929 | thislock = saved_state.asregs.thislock; | |
930 | doprofile = saved_state.asregs.profile; | |
931 | ||
932 | /* If profiling not enabled, disable it by asking for | |
933 | profiles infrequently. */ | |
fdc506e6 | 934 | if (doprofile == 0) |
90fe361f | 935 | doprofile = ~0; |
fdc506e6 | 936 | |
594266fc SC |
937 | do |
938 | { | |
fdc506e6 SC |
939 | register unsigned int iword = RUWAT (pc); |
940 | register unsigned int ult; | |
4d0be1f5 | 941 | #ifndef ACE_FAST |
594266fc | 942 | insts++; |
4d0be1f5 | 943 | #endif |
594266fc SC |
944 | top: |
945 | ||
946 | #include "code.c" | |
947 | ||
90fe361f | 948 | |
594266fc | 949 | pc += 2; |
4d0be1f5 SC |
950 | |
951 | #ifdef __GO32__ | |
952 | pollcount++; | |
953 | if (pollcount > 1000) | |
954 | { | |
955 | pollcount = 0; | |
956 | if (kbhit()) { | |
957 | int k = getkey(); | |
958 | if (k == 1) | |
959 | saved_state.asregs.exception = SIGINT; | |
960 | ||
961 | } | |
962 | } | |
963 | #endif | |
964 | ||
965 | #ifndef ACE_FAST | |
90fe361f SC |
966 | prevlock = thislock; |
967 | thislock = 30; | |
594266fc | 968 | cycles++; |
90fe361f SC |
969 | |
970 | if (cycles >= doprofile) | |
971 | { | |
4d0be1f5 | 972 | |
90fe361f SC |
973 | saved_state.asregs.cycles += doprofile; |
974 | cycles -= doprofile; | |
fdc506e6 | 975 | if (saved_state.asregs.profile_hist) |
90fe361f SC |
976 | { |
977 | int n = pc >> PROFILE_SHIFT; | |
fdc506e6 | 978 | if (n < nsamples) |
90fe361f SC |
979 | { |
980 | int i = saved_state.asregs.profile_hist[n]; | |
981 | if (i < 65000) | |
fdc506e6 | 982 | saved_state.asregs.profile_hist[n] = i + 1; |
90fe361f | 983 | } |
fdc506e6 | 984 | |
90fe361f SC |
985 | } |
986 | } | |
4d0be1f5 | 987 | #endif |
594266fc SC |
988 | } |
989 | while (!saved_state.asregs.exception); | |
990 | ||
4d0be1f5 SC |
991 | if (saved_state.asregs.exception == SIGILL |
992 | || saved_state.asregs.exception == SIGBUS | |
993 | || (saved_state.asregs.exception == SIGTRAP && !step)) | |
594266fc | 994 | { |
90fe361f | 995 | pc -= 2; |
594266fc | 996 | } |
90fe361f | 997 | |
594266fc SC |
998 | saved_state.asregs.ticks += get_now () - tick_start; |
999 | saved_state.asregs.cycles += cycles; | |
90fe361f | 1000 | saved_state.asregs.stalls += stalls; |
594266fc SC |
1001 | saved_state.asregs.insts += insts; |
1002 | saved_state.asregs.pc = pc; | |
1003 | saved_state.asregs.sr.bits.t = T; | |
1004 | saved_state.asregs.pr = PR; | |
1005 | ||
90fe361f SC |
1006 | saved_state.asregs.prevlock = prevlock; |
1007 | saved_state.asregs.thislock = thislock; | |
1008 | ||
1009 | ||
1010 | if (profile_file) | |
1011 | { | |
fdc506e6 | 1012 | dump_profile (); |
90fe361f | 1013 | } |
fdc506e6 | 1014 | |
594266fc SC |
1015 | signal (SIGINT, prev); |
1016 | } | |
1017 | ||
1018 | ||
1019 | ||
90fe361f | 1020 | |
631f6b24 | 1021 | int |
594266fc | 1022 | sim_write (addr, buffer, size) |
fe031f82 | 1023 | SIM_ADDR addr; |
594266fc SC |
1024 | unsigned char *buffer; |
1025 | int size; | |
1026 | { | |
1027 | int i; | |
1028 | init_pointers (); | |
1029 | ||
1030 | for (i = 0; i < size; i++) | |
1031 | { | |
1032 | saved_state.asregs.memory[MMASKB & (addr + i)] = buffer[i]; | |
1033 | } | |
fe031f82 | 1034 | return size; |
594266fc SC |
1035 | } |
1036 | ||
631f6b24 | 1037 | int |
594266fc | 1038 | sim_read (addr, buffer, size) |
fe031f82 DE |
1039 | SIM_ADDR addr; |
1040 | unsigned char *buffer; | |
594266fc SC |
1041 | int size; |
1042 | { | |
1043 | int i; | |
1044 | ||
1045 | init_pointers (); | |
1046 | ||
1047 | for (i = 0; i < size; i++) | |
1048 | { | |
1049 | buffer[i] = saved_state.asregs.memory[MMASKB & (addr + i)]; | |
1050 | } | |
fe031f82 | 1051 | return size; |
594266fc SC |
1052 | } |
1053 | ||
1054 | ||
90fe361f | 1055 | void |
4d0be1f5 | 1056 | sim_store_register (rn, memory) |
594266fc | 1057 | int rn; |
4d0be1f5 | 1058 | unsigned char *memory; |
594266fc | 1059 | { |
4d0be1f5 SC |
1060 | init_pointers(); |
1061 | saved_state.asregs.regs[rn]=RLAT(0); | |
594266fc SC |
1062 | } |
1063 | ||
90fe361f | 1064 | void |
4d0be1f5 | 1065 | sim_fetch_register (rn, memory) |
594266fc | 1066 | int rn; |
4d0be1f5 | 1067 | unsigned char *memory; |
594266fc | 1068 | { |
4d0be1f5 SC |
1069 | init_pointers(); |
1070 | WLAT (0, saved_state.asregs.regs[rn]); | |
594266fc SC |
1071 | } |
1072 | ||
90fe361f | 1073 | |
594266fc SC |
1074 | int |
1075 | sim_trace () | |
1076 | { | |
594266fc | 1077 | return 0; |
594266fc SC |
1078 | } |
1079 | ||
fe031f82 DE |
1080 | void |
1081 | sim_stop_reason (reason, sigrc) | |
1082 | enum sim_stop *reason; | |
631f6b24 | 1083 | int *sigrc; |
594266fc | 1084 | { |
fe031f82 | 1085 | *reason = sim_stopped; |
631f6b24 | 1086 | *sigrc = saved_state.asregs.exception; |
594266fc SC |
1087 | } |
1088 | ||
1089 | ||
90fe361f | 1090 | void |
fe031f82 DE |
1091 | sim_info (verbose) |
1092 | int verbose; | |
594266fc SC |
1093 | { |
1094 | double timetaken = (double) saved_state.asregs.ticks / (double) now_persec (); | |
90fe361f SC |
1095 | double virttime = saved_state.asregs.cycles / 36.0e6; |
1096 | ||
fe031f82 DE |
1097 | printf_filtered ("\n\n# instructions executed %10d\n", saved_state.asregs.insts); |
1098 | printf_filtered ("# cycles %10d\n", saved_state.asregs.cycles); | |
1099 | printf_filtered ("# pipeline stalls %10d\n", saved_state.asregs.stalls); | |
1100 | printf_filtered ("# real time taken %10.4f\n", timetaken); | |
1101 | printf_filtered ("# virtual time taken %10.4f\n", virttime); | |
1102 | printf_filtered ("# profiling size %10d\n", sim_profile_size); | |
1103 | printf_filtered ("# profiling frequency %10d\n", saved_state.asregs.profile); | |
1104 | printf_filtered ("# profile maxpc %10x\n", (1 << sim_profile_size) << PROFILE_SHIFT); | |
fdc506e6 SC |
1105 | |
1106 | if (timetaken != 0) | |
90fe361f | 1107 | { |
fe031f82 DE |
1108 | printf_filtered ("# cycles/second %10d\n", (int) (saved_state.asregs.cycles / timetaken)); |
1109 | printf_filtered ("# simulation ratio %10.4f\n", virttime / timetaken); | |
90fe361f | 1110 | } |
594266fc SC |
1111 | } |
1112 | ||
90fe361f SC |
1113 | |
1114 | void | |
fdc506e6 | 1115 | sim_set_profile (n) |
631f6b24 | 1116 | int n; |
594266fc | 1117 | { |
90fe361f SC |
1118 | saved_state.asregs.profile = n; |
1119 | } | |
1120 | ||
1121 | void | |
fdc506e6 | 1122 | sim_set_profile_size (n) |
631f6b24 | 1123 | int n; |
90fe361f SC |
1124 | { |
1125 | sim_profile_size = n; | |
594266fc | 1126 | } |
631f6b24 DE |
1127 | |
1128 | ||
1129 | void | |
fe031f82 DE |
1130 | sim_open (name) |
1131 | char *name; | |
631f6b24 | 1132 | { |
fe031f82 DE |
1133 | /* nothing to do */ |
1134 | } | |
631f6b24 | 1135 | |
fe031f82 DE |
1136 | void |
1137 | sim_close (quitting) | |
1138 | int quitting; | |
1139 | { | |
1140 | /* nothing to do */ | |
631f6b24 DE |
1141 | } |
1142 | ||
1143 | int | |
fe031f82 DE |
1144 | sim_load (prog, from_tty) |
1145 | char *prog; | |
1146 | int from_tty; | |
631f6b24 | 1147 | { |
fe031f82 DE |
1148 | /* Return nonzero so GDB will handle it. */ |
1149 | return 1; | |
631f6b24 | 1150 | } |
fe031f82 DE |
1151 | |
1152 | void | |
1153 | sim_create_inferior (start_address, argv, env) | |
1154 | SIM_ADDR start_address; | |
1155 | char **argv; | |
1156 | char **env; | |
631f6b24 | 1157 | { |
fe031f82 | 1158 | saved_state.asregs.pc = start_address; |
631f6b24 DE |
1159 | } |
1160 | ||
fe031f82 DE |
1161 | void |
1162 | sim_kill () | |
1163 | { | |
1164 | /* nothing to do */ | |
1165 | } |