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