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