Commit | Line | Data |
---|---|---|
cbb38b47 | 1 | /* SH5 simulator support code |
dc3cf14f JB |
2 | Copyright (C) 2000, 2001, 2006, 2008, 2009, 2010 |
3 | Free Software Foundation, Inc. | |
cbb38b47 BE |
4 | Contributed by Red Hat, Inc. |
5 | ||
6 | This file is part of the GNU simulators. | |
7 | ||
8 | This program is free software; you can redistribute it and/or modify | |
9 | it under the terms of the GNU General Public License as published by | |
4744ac1b JB |
10 | the Free Software Foundation; either version 3 of the License, or |
11 | (at your option) any later version. | |
cbb38b47 BE |
12 | |
13 | This program is distributed in the hope that it will be useful, | |
14 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
16 | GNU General Public License for more details. | |
17 | ||
4744ac1b JB |
18 | You should have received a copy of the GNU General Public License |
19 | along with this program. If not, see <http://www.gnu.org/licenses/>. */ | |
cbb38b47 BE |
20 | |
21 | #define WANT_CPU | |
22 | #define WANT_CPU_SH64 | |
23 | ||
24 | #include "sim-main.h" | |
25 | #include "sim-fpu.h" | |
26 | #include "cgen-mem.h" | |
27 | #include "cgen-ops.h" | |
28 | ||
65044526 | 29 | #include "gdb/callback.h" |
cbb38b47 BE |
30 | #include "defs-compact.h" |
31 | ||
32 | #include "bfd.h" | |
65044526 EZ |
33 | /* From include/gdb/. */ |
34 | #include "gdb/sim-sh.h" | |
cbb38b47 BE |
35 | |
36 | #define SYS_exit 1 | |
37 | #define SYS_read 3 | |
38 | #define SYS_write 4 | |
39 | #define SYS_open 5 | |
40 | #define SYS_close 6 | |
41 | #define SYS_lseek 19 | |
42 | #define SYS_time 23 | |
43 | #define SYS_argc 172 | |
44 | #define SYS_argnlen 173 | |
45 | #define SYS_argn 174 | |
46 | ||
47 | IDESC * sh64_idesc_media; | |
48 | IDESC * sh64_idesc_compact; | |
49 | ||
50 | BI | |
51 | sh64_endian (SIM_CPU *current_cpu) | |
52 | { | |
53 | return (CURRENT_TARGET_BYTE_ORDER == BIG_ENDIAN); | |
54 | } | |
55 | ||
56 | SF | |
57 | sh64_fldi0 (SIM_CPU *current_cpu) | |
58 | { | |
59 | SF result; | |
60 | sim_fpu_to32 (&result, &sim_fpu_zero); | |
61 | return result; | |
62 | } | |
63 | ||
64 | SF | |
65 | sh64_fldi1 (SIM_CPU *current_cpu) | |
66 | { | |
67 | SF result; | |
68 | sim_fpu_to32 (&result, &sim_fpu_one); | |
69 | return result; | |
70 | } | |
71 | ||
72 | DF | |
73 | sh64_fabsd(SIM_CPU *current_cpu, DF drgh) | |
74 | { | |
75 | DF result; | |
76 | sim_fpu f, fres; | |
77 | ||
78 | sim_fpu_64to (&f, drgh); | |
79 | sim_fpu_abs (&fres, &f); | |
80 | sim_fpu_to64 (&result, &fres); | |
81 | return result; | |
82 | } | |
83 | ||
84 | SF | |
85 | sh64_fabss(SIM_CPU *current_cpu, SF frgh) | |
86 | { | |
87 | SF result; | |
88 | sim_fpu f, fres; | |
89 | ||
90 | sim_fpu_32to (&f, frgh); | |
91 | sim_fpu_abs (&fres, &f); | |
92 | sim_fpu_to32 (&result, &fres); | |
93 | return result; | |
94 | } | |
95 | ||
96 | DF | |
97 | sh64_faddd(SIM_CPU *current_cpu, DF drg, DF drh) | |
98 | { | |
99 | DF result; | |
100 | sim_fpu f1, f2, fres; | |
101 | ||
102 | sim_fpu_64to (&f1, drg); | |
103 | sim_fpu_64to (&f2, drh); | |
104 | sim_fpu_add (&fres, &f1, &f2); | |
105 | sim_fpu_to64 (&result, &fres); | |
106 | return result; | |
107 | } | |
108 | ||
109 | SF | |
110 | sh64_fadds(SIM_CPU *current_cpu, SF frg, SF frh) | |
111 | { | |
112 | SF result; | |
113 | sim_fpu f1, f2, fres; | |
114 | ||
115 | sim_fpu_32to (&f1, frg); | |
116 | sim_fpu_32to (&f2, frh); | |
117 | sim_fpu_add (&fres, &f1, &f2); | |
118 | sim_fpu_to32 (&result, &fres); | |
119 | return result; | |
120 | } | |
121 | ||
122 | BI | |
123 | sh64_fcmpeqd(SIM_CPU *current_cpu, DF drg, DF drh) | |
124 | { | |
125 | sim_fpu f1, f2; | |
126 | ||
127 | sim_fpu_64to (&f1, drg); | |
128 | sim_fpu_64to (&f2, drh); | |
129 | return sim_fpu_is_eq (&f1, &f2); | |
130 | } | |
131 | ||
132 | BI | |
133 | sh64_fcmpeqs(SIM_CPU *current_cpu, SF frg, SF frh) | |
134 | { | |
135 | sim_fpu f1, f2; | |
136 | ||
137 | sim_fpu_32to (&f1, frg); | |
138 | sim_fpu_32to (&f2, frh); | |
139 | return sim_fpu_is_eq (&f1, &f2); | |
140 | } | |
141 | ||
142 | BI | |
143 | sh64_fcmpged(SIM_CPU *current_cpu, DF drg, DF drh) | |
144 | { | |
145 | sim_fpu f1, f2; | |
146 | ||
147 | sim_fpu_64to (&f1, drg); | |
148 | sim_fpu_64to (&f2, drh); | |
149 | return sim_fpu_is_ge (&f1, &f2); | |
150 | } | |
151 | ||
152 | BI | |
153 | sh64_fcmpges(SIM_CPU *current_cpu, SF frg, SF frh) | |
154 | { | |
155 | sim_fpu f1, f2; | |
156 | ||
157 | sim_fpu_32to (&f1, frg); | |
158 | sim_fpu_32to (&f2, frh); | |
159 | return sim_fpu_is_ge (&f1, &f2); | |
160 | } | |
161 | ||
162 | BI | |
163 | sh64_fcmpgtd(SIM_CPU *current_cpu, DF drg, DF drh) | |
164 | { | |
165 | sim_fpu f1, f2; | |
166 | ||
167 | sim_fpu_64to (&f1, drg); | |
168 | sim_fpu_64to (&f2, drh); | |
169 | return sim_fpu_is_gt (&f1, &f2); | |
170 | } | |
171 | ||
172 | BI | |
173 | sh64_fcmpgts(SIM_CPU *current_cpu, SF frg, SF frh) | |
174 | { | |
175 | sim_fpu f1, f2; | |
176 | ||
177 | sim_fpu_32to (&f1, frg); | |
178 | sim_fpu_32to (&f2, frh); | |
179 | return sim_fpu_is_gt (&f1, &f2); | |
180 | } | |
181 | ||
182 | BI | |
183 | sh64_fcmpund(SIM_CPU *current_cpu, DF drg, DF drh) | |
184 | { | |
185 | sim_fpu f1, f2; | |
186 | ||
187 | sim_fpu_64to (&f1, drg); | |
188 | sim_fpu_64to (&f2, drh); | |
189 | return (sim_fpu_is_nan (&f1) || sim_fpu_is_nan (&f2)); | |
190 | } | |
191 | ||
192 | BI | |
193 | sh64_fcmpuns(SIM_CPU *current_cpu, SF frg, SF frh) | |
194 | { | |
195 | sim_fpu f1, f2; | |
196 | ||
197 | sim_fpu_32to (&f1, frg); | |
198 | sim_fpu_32to (&f2, frh); | |
199 | return (sim_fpu_is_nan (&f1) || sim_fpu_is_nan (&f2)); | |
200 | } | |
201 | ||
202 | SF | |
203 | sh64_fcnvds(SIM_CPU *current_cpu, DF drgh) | |
204 | { | |
205 | union { | |
206 | unsigned long long ll; | |
207 | double d; | |
208 | } f1; | |
209 | ||
210 | union { | |
211 | unsigned long l; | |
212 | float f; | |
213 | } f2; | |
214 | ||
215 | f1.ll = drgh; | |
216 | f2.f = (float) f1.d; | |
217 | ||
218 | return (SF) f2.l; | |
219 | } | |
220 | ||
221 | DF | |
222 | sh64_fcnvsd(SIM_CPU *current_cpu, SF frgh) | |
223 | { | |
224 | DF result; | |
225 | sim_fpu f; | |
226 | ||
227 | sim_fpu_32to (&f, frgh); | |
228 | sim_fpu_to64 (&result, &f); | |
229 | return result; | |
230 | } | |
231 | ||
232 | DF | |
233 | sh64_fdivd(SIM_CPU *current_cpu, DF drg, DF drh) | |
234 | { | |
235 | DF result; | |
236 | sim_fpu f1, f2, fres; | |
237 | ||
238 | sim_fpu_64to (&f1, drg); | |
239 | sim_fpu_64to (&f2, drh); | |
240 | sim_fpu_div (&fres, &f1, &f2); | |
241 | sim_fpu_to64 (&result, &fres); | |
242 | return result; | |
243 | } | |
244 | ||
245 | SF | |
246 | sh64_fdivs(SIM_CPU *current_cpu, SF frg, SF frh) | |
247 | { | |
248 | SF result; | |
249 | sim_fpu f1, f2, fres; | |
250 | ||
251 | sim_fpu_32to (&f1, frg); | |
252 | sim_fpu_32to (&f2, frh); | |
253 | sim_fpu_div (&fres, &f1, &f2); | |
254 | sim_fpu_to32 (&result, &fres); | |
255 | return result; | |
256 | } | |
257 | ||
258 | DF | |
259 | sh64_floatld(SIM_CPU *current_cpu, SF frgh) | |
260 | { | |
261 | DF result; | |
262 | sim_fpu f; | |
263 | ||
264 | sim_fpu_i32to (&f, frgh, sim_fpu_round_default); | |
265 | sim_fpu_to64 (&result, &f); | |
266 | return result; | |
267 | } | |
268 | ||
269 | SF | |
270 | sh64_floatls(SIM_CPU *current_cpu, SF frgh) | |
271 | { | |
272 | SF result; | |
273 | sim_fpu f; | |
274 | ||
275 | sim_fpu_i32to (&f, frgh, sim_fpu_round_default); | |
276 | sim_fpu_to32 (&result, &f); | |
277 | return result; | |
278 | } | |
279 | ||
280 | DF | |
281 | sh64_floatqd(SIM_CPU *current_cpu, DF drgh) | |
282 | { | |
283 | DF result; | |
284 | sim_fpu f; | |
285 | ||
286 | sim_fpu_i64to (&f, drgh, sim_fpu_round_default); | |
287 | sim_fpu_to64 (&result, &f); | |
288 | return result; | |
289 | } | |
290 | ||
291 | SF | |
292 | sh64_floatqs(SIM_CPU *current_cpu, DF drgh) | |
293 | { | |
294 | SF result; | |
295 | sim_fpu f; | |
296 | ||
297 | sim_fpu_i64to (&f, drgh, sim_fpu_round_default); | |
298 | sim_fpu_to32 (&result, &f); | |
299 | return result; | |
300 | } | |
301 | ||
302 | SF | |
303 | sh64_fmacs(SIM_CPU *current_cpu, SF fr0, SF frm, SF frn) | |
304 | { | |
305 | SF result; | |
306 | sim_fpu m1, m2, a1, fres; | |
307 | ||
308 | sim_fpu_32to (&m1, fr0); | |
309 | sim_fpu_32to (&m2, frm); | |
310 | sim_fpu_32to (&a1, frn); | |
311 | ||
312 | sim_fpu_mul (&fres, &m1, &m2); | |
313 | sim_fpu_add (&fres, &fres, &a1); | |
314 | ||
315 | sim_fpu_to32 (&result, &fres); | |
316 | return result; | |
317 | } | |
318 | ||
319 | DF | |
320 | sh64_fmuld(SIM_CPU *current_cpu, DF drg, DF drh) | |
321 | { | |
322 | DF result; | |
323 | sim_fpu f1, f2, fres; | |
324 | ||
325 | sim_fpu_64to (&f1, drg); | |
326 | sim_fpu_64to (&f2, drh); | |
327 | sim_fpu_mul (&fres, &f1, &f2); | |
328 | sim_fpu_to64 (&result, &fres); | |
329 | return result; | |
330 | } | |
331 | ||
332 | SF | |
333 | sh64_fmuls(SIM_CPU *current_cpu, SF frg, SF frh) | |
334 | { | |
335 | SF result; | |
336 | sim_fpu f1, f2, fres; | |
337 | ||
338 | sim_fpu_32to (&f1, frg); | |
339 | sim_fpu_32to (&f2, frh); | |
340 | sim_fpu_mul (&fres, &f1, &f2); | |
341 | sim_fpu_to32 (&result, &fres); | |
342 | return result; | |
343 | } | |
344 | ||
345 | DF | |
346 | sh64_fnegd(SIM_CPU *current_cpu, DF drgh) | |
347 | { | |
348 | DF result; | |
349 | sim_fpu f1, f2; | |
350 | ||
351 | sim_fpu_64to (&f1, drgh); | |
352 | sim_fpu_neg (&f2, &f1); | |
353 | sim_fpu_to64 (&result, &f2); | |
354 | return result; | |
355 | } | |
356 | ||
357 | SF | |
358 | sh64_fnegs(SIM_CPU *current_cpu, SF frgh) | |
359 | { | |
360 | SF result; | |
361 | sim_fpu f, fres; | |
362 | ||
363 | sim_fpu_32to (&f, frgh); | |
364 | sim_fpu_neg (&fres, &f); | |
365 | sim_fpu_to32 (&result, &fres); | |
366 | return result; | |
367 | } | |
368 | ||
369 | DF | |
370 | sh64_fsqrtd(SIM_CPU *current_cpu, DF drgh) | |
371 | { | |
372 | DF result; | |
373 | sim_fpu f, fres; | |
374 | ||
375 | sim_fpu_64to (&f, drgh); | |
376 | sim_fpu_sqrt (&fres, &f); | |
377 | sim_fpu_to64 (&result, &fres); | |
378 | return result; | |
379 | } | |
380 | ||
381 | SF | |
382 | sh64_fsqrts(SIM_CPU *current_cpu, SF frgh) | |
383 | { | |
384 | SF result; | |
385 | sim_fpu f, fres; | |
386 | ||
387 | sim_fpu_32to (&f, frgh); | |
388 | sim_fpu_sqrt (&fres, &f); | |
389 | sim_fpu_to32 (&result, &fres); | |
390 | return result; | |
391 | } | |
392 | ||
393 | DF | |
394 | sh64_fsubd(SIM_CPU *current_cpu, DF drg, DF drh) | |
395 | { | |
396 | DF result; | |
397 | sim_fpu f1, f2, fres; | |
398 | ||
399 | sim_fpu_64to (&f1, drg); | |
400 | sim_fpu_64to (&f2, drh); | |
401 | sim_fpu_sub (&fres, &f1, &f2); | |
402 | sim_fpu_to64 (&result, &fres); | |
403 | return result; | |
404 | } | |
405 | ||
406 | SF | |
407 | sh64_fsubs(SIM_CPU *current_cpu, SF frg, SF frh) | |
408 | { | |
409 | SF result; | |
410 | sim_fpu f1, f2, fres; | |
411 | ||
412 | sim_fpu_32to (&f1, frg); | |
413 | sim_fpu_32to (&f2, frh); | |
414 | sim_fpu_sub (&fres, &f1, &f2); | |
415 | sim_fpu_to32 (&result, &fres); | |
416 | return result; | |
417 | } | |
418 | ||
419 | SF | |
420 | sh64_ftrcdl(SIM_CPU *current_cpu, DF drgh) | |
421 | { | |
422 | SI result; | |
423 | sim_fpu f; | |
424 | ||
425 | sim_fpu_64to (&f, drgh); | |
426 | sim_fpu_to32i (&result, &f, sim_fpu_round_zero); | |
427 | return (SF) result; | |
428 | } | |
429 | ||
430 | SF | |
431 | sh64_ftrcsl(SIM_CPU *current_cpu, SF frgh) | |
432 | { | |
433 | SI result; | |
434 | sim_fpu f; | |
435 | ||
436 | sim_fpu_32to (&f, frgh); | |
437 | sim_fpu_to32i (&result, &f, sim_fpu_round_zero); | |
438 | return (SF) result; | |
439 | } | |
440 | ||
441 | DF | |
442 | sh64_ftrcdq(SIM_CPU *current_cpu, DF drgh) | |
443 | { | |
444 | DI result; | |
445 | sim_fpu f; | |
446 | ||
447 | sim_fpu_64to (&f, drgh); | |
448 | sim_fpu_to64i (&result, &f, sim_fpu_round_zero); | |
449 | return (DF) result; | |
450 | } | |
451 | ||
452 | DF | |
453 | sh64_ftrcsq(SIM_CPU *current_cpu, SF frgh) | |
454 | { | |
455 | DI result; | |
456 | sim_fpu f; | |
457 | ||
458 | sim_fpu_32to (&f, frgh); | |
459 | sim_fpu_to64i (&result, &f, sim_fpu_round_zero); | |
460 | return (DF) result; | |
461 | } | |
462 | ||
c7e628df | 463 | VOID |
cbb38b47 BE |
464 | sh64_ftrvs(SIM_CPU *cpu, unsigned g, unsigned h, unsigned f) |
465 | { | |
466 | int i, j; | |
467 | ||
468 | for (i = 0; i < 4; i++) | |
469 | { | |
470 | SF result; | |
471 | sim_fpu sum; | |
472 | sim_fpu_32to (&sum, 0); | |
473 | ||
474 | for (j = 0; j < 4; j++) | |
475 | { | |
476 | sim_fpu f1, f2, temp; | |
477 | sim_fpu_32to (&f1, sh64_h_fr_get (cpu, (g + i) + (j * 4))); | |
478 | sim_fpu_32to (&f2, sh64_h_fr_get (cpu, h + j)); | |
479 | sim_fpu_mul (&temp, &f1, &f2); | |
480 | sim_fpu_add (&sum, &sum, &temp); | |
481 | } | |
482 | sim_fpu_to32 (&result, &sum); | |
483 | sh64_h_fr_set (cpu, f + i, result); | |
484 | } | |
485 | } | |
486 | ||
c7e628df DB |
487 | VOID |
488 | sh64_fipr (SIM_CPU *cpu, unsigned m, unsigned n) | |
489 | { | |
490 | SF result = sh64_fmuls (cpu, sh64_h_fvc_get (cpu, m), sh64_h_fvc_get (cpu, n)); | |
491 | result = sh64_fadds (cpu, result, sh64_fmuls (cpu, sh64_h_frc_get (cpu, m + 1), sh64_h_frc_get (cpu, n + 1))); | |
492 | result = sh64_fadds (cpu, result, sh64_fmuls (cpu, sh64_h_frc_get (cpu, m + 2), sh64_h_frc_get (cpu, n + 2))); | |
493 | result = sh64_fadds (cpu, result, sh64_fmuls (cpu, sh64_h_frc_get (cpu, m + 3), sh64_h_frc_get (cpu, n + 3))); | |
494 | sh64_h_frc_set (cpu, n + 3, result); | |
495 | } | |
496 | ||
497 | SF | |
498 | sh64_fiprs (SIM_CPU *cpu, unsigned g, unsigned h) | |
499 | { | |
500 | SF temp = sh64_fmuls (cpu, sh64_h_fr_get (cpu, g), sh64_h_fr_get (cpu, h)); | |
501 | temp = sh64_fadds (cpu, temp, sh64_fmuls (cpu, sh64_h_fr_get (cpu, g + 1), sh64_h_fr_get (cpu, h + 1))); | |
502 | temp = sh64_fadds (cpu, temp, sh64_fmuls (cpu, sh64_h_fr_get (cpu, g + 2), sh64_h_fr_get (cpu, h + 2))); | |
503 | temp = sh64_fadds (cpu, temp, sh64_fmuls (cpu, sh64_h_fr_get (cpu, g + 3), sh64_h_fr_get (cpu, h + 3))); | |
504 | return temp; | |
505 | } | |
506 | ||
507 | VOID | |
508 | sh64_fldp (SIM_CPU *cpu, PCADDR pc, DI rm, DI rn, unsigned f) | |
509 | { | |
510 | sh64_h_fr_set (cpu, f, GETMEMSF (cpu, pc, rm + rn)); | |
511 | sh64_h_fr_set (cpu, f + 1, GETMEMSF (cpu, pc, rm + rn + 4)); | |
512 | } | |
513 | ||
514 | VOID | |
515 | sh64_fstp (SIM_CPU *cpu, PCADDR pc, DI rm, DI rn, unsigned f) | |
516 | { | |
517 | SETMEMSF (cpu, pc, rm + rn, sh64_h_fr_get (cpu, f)); | |
518 | SETMEMSF (cpu, pc, rm + rn + 4, sh64_h_fr_get (cpu, f + 1)); | |
519 | } | |
520 | ||
521 | VOID | |
522 | sh64_ftrv (SIM_CPU *cpu, UINT ignored) | |
523 | { | |
524 | /* TODO: Unimplemented. */ | |
525 | } | |
526 | ||
527 | VOID | |
528 | sh64_pref (SIM_CPU *cpu, SI addr) | |
529 | { | |
530 | /* TODO: Unimplemented. */ | |
531 | } | |
532 | ||
cbb38b47 BE |
533 | /* Count the number of arguments. */ |
534 | static int | |
535 | count_argc (cpu) | |
536 | SIM_CPU *cpu; | |
537 | { | |
538 | int i = 0; | |
539 | ||
540 | if (! STATE_PROG_ARGV (CPU_STATE (cpu))) | |
541 | return -1; | |
542 | ||
543 | while (STATE_PROG_ARGV (CPU_STATE (cpu)) [i] != NULL) | |
544 | ++i; | |
545 | ||
546 | return i; | |
547 | } | |
548 | ||
549 | /* Read a null terminated string from memory, return in a buffer */ | |
550 | static char * | |
551 | fetch_str (current_cpu, pc, addr) | |
552 | SIM_CPU *current_cpu; | |
553 | PCADDR pc; | |
554 | DI addr; | |
555 | { | |
556 | char *buf; | |
557 | int nr = 0; | |
558 | while (sim_core_read_1 (current_cpu, | |
559 | pc, read_map, addr + nr) != 0) | |
560 | nr++; | |
561 | buf = NZALLOC (char, nr + 1); | |
562 | sim_read (CPU_STATE (current_cpu), addr, buf, nr); | |
563 | return buf; | |
564 | } | |
565 | ||
566 | static void | |
567 | trap_handler (SIM_CPU *current_cpu, int shmedia_abi_p, UQI trapnum, PCADDR pc) | |
568 | { | |
569 | char ch; | |
570 | switch (trapnum) | |
571 | { | |
572 | case 1: | |
573 | ch = GET_H_GRC (0); | |
574 | sim_io_write_stdout (CPU_STATE (current_cpu), &ch, 1); | |
575 | fflush (stdout); | |
576 | break; | |
577 | case 2: | |
578 | sim_engine_halt (CPU_STATE (current_cpu), current_cpu, NULL, pc, sim_stopped, SIM_SIGTRAP); | |
579 | break; | |
580 | case 34: | |
581 | { | |
582 | int i; | |
583 | int ret_reg = (shmedia_abi_p) ? 2 : 0; | |
584 | char *buf; | |
585 | DI PARM1 = GET_H_GR ((shmedia_abi_p) ? 3 : 5); | |
586 | DI PARM2 = GET_H_GR ((shmedia_abi_p) ? 4 : 6); | |
587 | DI PARM3 = GET_H_GR ((shmedia_abi_p) ? 5 : 7); | |
588 | ||
589 | switch (GET_H_GR ((shmedia_abi_p) ? 2 : 4)) | |
590 | { | |
591 | case SYS_write: | |
592 | buf = zalloc (PARM3); | |
593 | sim_read (CPU_STATE (current_cpu), PARM2, buf, PARM3); | |
594 | SET_H_GR (ret_reg, | |
595 | sim_io_write (CPU_STATE (current_cpu), | |
596 | PARM1, buf, PARM3)); | |
597 | zfree (buf); | |
598 | break; | |
599 | ||
600 | case SYS_lseek: | |
601 | SET_H_GR (ret_reg, | |
602 | sim_io_lseek (CPU_STATE (current_cpu), | |
603 | PARM1, PARM2, PARM3)); | |
604 | break; | |
605 | ||
606 | case SYS_exit: | |
607 | sim_engine_halt (CPU_STATE (current_cpu), current_cpu, | |
608 | NULL, pc, sim_exited, PARM1); | |
609 | break; | |
610 | ||
611 | case SYS_read: | |
612 | buf = zalloc (PARM3); | |
613 | SET_H_GR (ret_reg, | |
614 | sim_io_read (CPU_STATE (current_cpu), | |
615 | PARM1, buf, PARM3)); | |
616 | sim_write (CPU_STATE (current_cpu), PARM2, buf, PARM3); | |
617 | zfree (buf); | |
618 | break; | |
619 | ||
620 | case SYS_open: | |
621 | buf = fetch_str (current_cpu, pc, PARM1); | |
622 | SET_H_GR (ret_reg, | |
623 | sim_io_open (CPU_STATE (current_cpu), | |
624 | buf, PARM2)); | |
625 | zfree (buf); | |
626 | break; | |
627 | ||
628 | case SYS_close: | |
629 | SET_H_GR (ret_reg, | |
630 | sim_io_close (CPU_STATE (current_cpu), PARM1)); | |
631 | break; | |
632 | ||
633 | case SYS_time: | |
634 | SET_H_GR (ret_reg, time (0)); | |
635 | break; | |
636 | ||
637 | case SYS_argc: | |
638 | SET_H_GR (ret_reg, count_argc (current_cpu)); | |
639 | break; | |
640 | ||
641 | case SYS_argnlen: | |
642 | if (PARM1 < count_argc (current_cpu)) | |
643 | SET_H_GR (ret_reg, | |
644 | strlen (STATE_PROG_ARGV (CPU_STATE (current_cpu)) [PARM1])); | |
645 | else | |
646 | SET_H_GR (ret_reg, -1); | |
647 | break; | |
648 | ||
649 | case SYS_argn: | |
650 | if (PARM1 < count_argc (current_cpu)) | |
651 | { | |
652 | /* Include the NULL byte. */ | |
653 | i = strlen (STATE_PROG_ARGV (CPU_STATE (current_cpu)) [PARM1]) + 1; | |
654 | sim_write (CPU_STATE (current_cpu), | |
655 | PARM2, | |
656 | STATE_PROG_ARGV (CPU_STATE (current_cpu)) [PARM1], | |
657 | i); | |
658 | ||
659 | /* Just for good measure. */ | |
660 | SET_H_GR (ret_reg, i); | |
661 | break; | |
662 | } | |
663 | else | |
664 | SET_H_GR (ret_reg, -1); | |
665 | break; | |
666 | ||
667 | default: | |
668 | SET_H_GR (ret_reg, -1); | |
669 | } | |
670 | } | |
671 | break; | |
672 | case 253: | |
673 | puts ("pass"); | |
674 | exit (0); | |
675 | case 254: | |
676 | puts ("fail"); | |
677 | exit (1); | |
678 | case 0xc3: | |
679 | /* fall through. */ | |
680 | case 255: | |
681 | sim_engine_halt (CPU_STATE (current_cpu), current_cpu, NULL, pc, sim_stopped, SIM_SIGTRAP); | |
682 | break; | |
683 | } | |
684 | } | |
685 | ||
686 | void | |
687 | sh64_trapa (SIM_CPU *current_cpu, DI rm, PCADDR pc) | |
688 | { | |
689 | trap_handler (current_cpu, 1, (UQI) rm & 0xff, pc); | |
690 | } | |
691 | ||
692 | void | |
693 | sh64_compact_trapa (SIM_CPU *current_cpu, UQI trapnum, PCADDR pc) | |
694 | { | |
695 | int mach_sh5_p; | |
696 | ||
697 | /* If this is an SH5 executable, this is SHcompact code running in | |
698 | the SHmedia ABI. */ | |
699 | ||
700 | mach_sh5_p = | |
701 | (bfd_get_mach (STATE_PROG_BFD (CPU_STATE (current_cpu))) == bfd_mach_sh5); | |
702 | ||
703 | trap_handler (current_cpu, mach_sh5_p, trapnum, pc); | |
704 | } | |
705 | ||
706 | DI | |
707 | sh64_nsb (SIM_CPU *current_cpu, DI rm) | |
708 | { | |
709 | int result = 0, count; | |
710 | UDI source = (UDI) rm; | |
711 | ||
712 | if ((source >> 63)) | |
713 | source = ~source; | |
714 | source <<= 1; | |
715 | ||
716 | for (count = 32; count; count >>= 1) | |
717 | { | |
718 | UDI newval = source << count; | |
719 | ||
720 | if ((newval >> count) == source) | |
721 | { | |
722 | result |= count; | |
723 | source = newval; | |
724 | } | |
725 | } | |
726 | ||
727 | return result; | |
728 | } | |
729 | ||
730 | void | |
731 | sh64_break (SIM_CPU *current_cpu, PCADDR pc) | |
732 | { | |
733 | SIM_DESC sd = CPU_STATE (current_cpu); | |
734 | sim_engine_halt (sd, current_cpu, NULL, pc, sim_stopped, SIM_SIGTRAP); | |
735 | } | |
736 | ||
c7e628df DB |
737 | SI |
738 | sh64_movua (SIM_CPU *current_cpu, PCADDR pc, SI rn) | |
739 | { | |
740 | SI v; | |
741 | int i; | |
742 | ||
743 | /* Move the data one byte at a time to avoid alignment problems. | |
744 | Be aware of endianness. */ | |
745 | v = 0; | |
746 | for (i = 0; i < 4; ++i) | |
747 | v = (v << 8) | (GETMEMQI (current_cpu, pc, rn + i) & 0xff); | |
748 | ||
749 | v = T2H_4 (v); | |
750 | return v; | |
751 | } | |
752 | ||
cbb38b47 BE |
753 | void |
754 | set_isa (SIM_CPU *current_cpu, int mode) | |
755 | { | |
756 | /* Do nothing. */ | |
757 | } | |
758 | ||
759 | /* The semantic code invokes this for invalid (unrecognized) instructions. */ | |
760 | ||
761 | SEM_PC | |
762 | sim_engine_invalid_insn (SIM_CPU *current_cpu, IADDR cia, SEM_PC vpc) | |
763 | { | |
764 | SIM_DESC sd = CPU_STATE (current_cpu); | |
765 | sim_engine_halt (sd, current_cpu, NULL, cia, sim_stopped, SIM_SIGILL); | |
766 | ||
767 | return vpc; | |
768 | } | |
769 | ||
770 | ||
771 | /* Process an address exception. */ | |
772 | ||
773 | void | |
774 | sh64_core_signal (SIM_DESC sd, SIM_CPU *current_cpu, sim_cia cia, | |
775 | unsigned int map, int nr_bytes, address_word addr, | |
776 | transfer_type transfer, sim_core_signals sig) | |
777 | { | |
778 | sim_core_signal (sd, current_cpu, cia, map, nr_bytes, addr, | |
779 | transfer, sig); | |
780 | } | |
781 | ||
782 | ||
783 | /* Initialize cycle counting for an insn. | |
784 | FIRST_P is non-zero if this is the first insn in a set of parallel | |
785 | insns. */ | |
786 | ||
787 | void | |
788 | sh64_compact_model_insn_before (SIM_CPU *cpu, int first_p) | |
789 | { | |
790 | /* Do nothing. */ | |
791 | } | |
792 | ||
793 | void | |
794 | sh64_media_model_insn_before (SIM_CPU *cpu, int first_p) | |
795 | { | |
796 | /* Do nothing. */ | |
797 | } | |
798 | ||
799 | /* Record the cycles computed for an insn. | |
800 | LAST_P is non-zero if this is the last insn in a set of parallel insns, | |
801 | and we update the total cycle count. | |
802 | CYCLES is the cycle count of the insn. */ | |
803 | ||
804 | void | |
805 | sh64_compact_model_insn_after(SIM_CPU *cpu, int last_p, int cycles) | |
806 | { | |
807 | /* Do nothing. */ | |
808 | } | |
809 | ||
810 | void | |
811 | sh64_media_model_insn_after(SIM_CPU *cpu, int last_p, int cycles) | |
812 | { | |
813 | /* Do nothing. */ | |
814 | } | |
815 | ||
816 | int | |
817 | sh64_fetch_register (SIM_CPU *cpu, int nr, unsigned char *buf, int len) | |
818 | { | |
819 | /* Fetch general purpose registers. */ | |
820 | if (nr >= SIM_SH64_R0_REGNUM | |
821 | && nr < (SIM_SH64_R0_REGNUM + SIM_SH64_NR_R_REGS) | |
822 | && len == 8) | |
823 | { | |
824 | *((unsigned64*) buf) = | |
825 | H2T_8 (sh64_h_gr_get (cpu, nr - SIM_SH64_R0_REGNUM)); | |
826 | return len; | |
827 | } | |
828 | ||
829 | /* Fetch PC. */ | |
830 | if (nr == SIM_SH64_PC_REGNUM && len == 8) | |
831 | { | |
832 | *((unsigned64*) buf) = H2T_8 (sh64_h_pc_get (cpu) | sh64_h_ism_get (cpu)); | |
833 | return len; | |
834 | } | |
835 | ||
836 | /* Fetch status register (SR). */ | |
837 | if (nr == SIM_SH64_SR_REGNUM && len == 8) | |
838 | { | |
839 | *((unsigned64*) buf) = H2T_8 (sh64_h_sr_get (cpu)); | |
840 | return len; | |
841 | } | |
842 | ||
843 | /* Fetch saved status register (SSR) and PC (SPC). */ | |
844 | if ((nr == SIM_SH64_SSR_REGNUM || nr == SIM_SH64_SPC_REGNUM) | |
845 | && len == 8) | |
846 | { | |
847 | *((unsigned64*) buf) = 0; | |
848 | return len; | |
849 | } | |
850 | ||
851 | /* Fetch target registers. */ | |
852 | if (nr >= SIM_SH64_TR0_REGNUM | |
853 | && nr < (SIM_SH64_TR0_REGNUM + SIM_SH64_NR_TR_REGS) | |
854 | && len == 8) | |
855 | { | |
856 | *((unsigned64*) buf) = | |
857 | H2T_8 (sh64_h_tr_get (cpu, nr - SIM_SH64_TR0_REGNUM)); | |
858 | return len; | |
859 | } | |
860 | ||
861 | /* Fetch floating point registers. */ | |
862 | if (nr >= SIM_SH64_FR0_REGNUM | |
863 | && nr < (SIM_SH64_FR0_REGNUM + SIM_SH64_NR_FP_REGS) | |
864 | && len == 4) | |
865 | { | |
866 | *((unsigned32*) buf) = | |
867 | H2T_4 (sh64_h_fr_get (cpu, nr - SIM_SH64_FR0_REGNUM)); | |
868 | return len; | |
869 | } | |
870 | ||
871 | /* We should never get here. */ | |
872 | return 0; | |
873 | } | |
874 | ||
875 | int | |
876 | sh64_store_register (SIM_CPU *cpu, int nr, unsigned char *buf, int len) | |
877 | { | |
878 | /* Store general purpose registers. */ | |
879 | if (nr >= SIM_SH64_R0_REGNUM | |
880 | && nr < (SIM_SH64_R0_REGNUM + SIM_SH64_NR_R_REGS) | |
881 | && len == 8) | |
882 | { | |
883 | sh64_h_gr_set (cpu, nr - SIM_SH64_R0_REGNUM, T2H_8 (*((unsigned64*)buf))); | |
884 | return len; | |
885 | } | |
886 | ||
887 | /* Store PC. */ | |
888 | if (nr == SIM_SH64_PC_REGNUM && len == 8) | |
889 | { | |
890 | unsigned64 new_pc = T2H_8 (*((unsigned64*)buf)); | |
891 | sh64_h_pc_set (cpu, new_pc); | |
892 | return len; | |
893 | } | |
894 | ||
895 | /* Store status register (SR). */ | |
896 | if (nr == SIM_SH64_SR_REGNUM && len == 8) | |
897 | { | |
898 | sh64_h_sr_set (cpu, T2H_8 (*((unsigned64*)buf))); | |
899 | return len; | |
900 | } | |
901 | ||
902 | /* Store saved status register (SSR) and PC (SPC). */ | |
903 | if (nr == SIM_SH64_SSR_REGNUM || nr == SIM_SH64_SPC_REGNUM) | |
904 | { | |
905 | /* Do nothing. */ | |
906 | return len; | |
907 | } | |
908 | ||
909 | /* Store target registers. */ | |
910 | if (nr >= SIM_SH64_TR0_REGNUM | |
911 | && nr < (SIM_SH64_TR0_REGNUM + SIM_SH64_NR_TR_REGS) | |
912 | && len == 8) | |
913 | { | |
914 | sh64_h_tr_set (cpu, nr - SIM_SH64_TR0_REGNUM, T2H_8 (*((unsigned64*)buf))); | |
915 | return len; | |
916 | } | |
917 | ||
918 | /* Store floating point registers. */ | |
919 | if (nr >= SIM_SH64_FR0_REGNUM | |
920 | && nr < (SIM_SH64_FR0_REGNUM + SIM_SH64_NR_FP_REGS) | |
921 | && len == 4) | |
922 | { | |
923 | sh64_h_fr_set (cpu, nr - SIM_SH64_FR0_REGNUM, T2H_4 (*((unsigned32*)buf))); | |
924 | return len; | |
925 | } | |
926 | ||
927 | /* We should never get here. */ | |
928 | return 0; | |
929 | } | |
930 | ||
931 | void | |
932 | sh64_engine_run_full(SIM_CPU *cpu) | |
933 | { | |
934 | if (sh64_h_ism_get (cpu) == ISM_MEDIA) | |
935 | { | |
936 | if (!sh64_idesc_media) | |
937 | { | |
938 | sh64_media_init_idesc_table (cpu); | |
939 | sh64_idesc_media = CPU_IDESC (cpu); | |
940 | } | |
941 | else | |
942 | CPU_IDESC (cpu) = sh64_idesc_media; | |
943 | sh64_media_engine_run_full (cpu); | |
944 | } | |
945 | else | |
946 | { | |
947 | if (!sh64_idesc_compact) | |
948 | { | |
949 | sh64_compact_init_idesc_table (cpu); | |
950 | sh64_idesc_compact = CPU_IDESC (cpu); | |
951 | } | |
952 | else | |
953 | CPU_IDESC (cpu) = sh64_idesc_compact; | |
954 | sh64_compact_engine_run_full (cpu); | |
955 | } | |
956 | } | |
957 | ||
958 | void | |
959 | sh64_engine_run_fast (SIM_CPU *cpu) | |
960 | { | |
961 | if (sh64_h_ism_get (cpu) == ISM_MEDIA) | |
962 | { | |
963 | if (!sh64_idesc_media) | |
964 | { | |
965 | sh64_media_init_idesc_table (cpu); | |
966 | sh64_idesc_media = CPU_IDESC (cpu); | |
967 | } | |
968 | else | |
969 | CPU_IDESC (cpu) = sh64_idesc_media; | |
970 | sh64_media_engine_run_fast (cpu); | |
971 | } | |
972 | else | |
973 | { | |
974 | if (!sh64_idesc_compact) | |
975 | { | |
976 | sh64_compact_init_idesc_table (cpu); | |
977 | sh64_idesc_compact = CPU_IDESC (cpu); | |
978 | } | |
979 | else | |
980 | CPU_IDESC (cpu) = sh64_idesc_compact; | |
981 | sh64_compact_engine_run_fast (cpu); | |
982 | } | |
983 | } | |
984 | ||
985 | static void | |
986 | sh64_prepare_run (SIM_CPU *cpu) | |
987 | { | |
988 | /* Nothing. */ | |
989 | } | |
990 | ||
991 | static const CGEN_INSN * | |
992 | sh64_get_idata (SIM_CPU *cpu, int inum) | |
993 | { | |
994 | return CPU_IDESC (cpu) [inum].idata; | |
995 | } | |
996 | ||
997 | static void | |
998 | sh64_init_cpu (SIM_CPU *cpu) | |
999 | { | |
1000 | CPU_REG_FETCH (cpu) = sh64_fetch_register; | |
1001 | CPU_REG_STORE (cpu) = sh64_store_register; | |
1002 | CPU_PC_FETCH (cpu) = sh64_h_pc_get; | |
1003 | CPU_PC_STORE (cpu) = sh64_h_pc_set; | |
1004 | CPU_GET_IDATA (cpu) = sh64_get_idata; | |
1005 | /* Only used by profiling. 0 disables it. */ | |
1006 | CPU_MAX_INSNS (cpu) = 0; | |
1007 | CPU_INSN_NAME (cpu) = cgen_insn_name; | |
1008 | CPU_FULL_ENGINE_FN (cpu) = sh64_engine_run_full; | |
1009 | #if WITH_FAST | |
1010 | CPU_FAST_ENGINE_FN (cpu) = sh64_engine_run_fast; | |
1011 | #else | |
1012 | CPU_FAST_ENGINE_FN (cpu) = sh64_engine_run_full; | |
1013 | #endif | |
1014 | } | |
1015 | ||
1016 | static void | |
1017 | shmedia_init_cpu (SIM_CPU *cpu) | |
1018 | { | |
1019 | sh64_init_cpu (cpu); | |
1020 | } | |
1021 | ||
1022 | static void | |
1023 | shcompact_init_cpu (SIM_CPU *cpu) | |
1024 | { | |
1025 | sh64_init_cpu (cpu); | |
1026 | } | |
1027 | ||
1028 | static void | |
1029 | sh64_model_init() | |
1030 | { | |
1031 | /* Do nothing. */ | |
1032 | } | |
1033 | ||
1034 | static const MODEL sh_models [] = | |
1035 | { | |
c7e628df DB |
1036 | { "sh2", & sh2_mach, MODEL_SH5, NULL, sh64_model_init }, |
1037 | { "sh2e", & sh2e_mach, MODEL_SH5, NULL, sh64_model_init }, | |
1038 | { "sh2a", & sh2a_fpu_mach, MODEL_SH5, NULL, sh64_model_init }, | |
1039 | { "sh2a_nofpu", & sh2a_nofpu_mach, MODEL_SH5, NULL, sh64_model_init }, | |
1040 | { "sh3", & sh3_mach, MODEL_SH5, NULL, sh64_model_init }, | |
1041 | { "sh3e", & sh3_mach, MODEL_SH5, NULL, sh64_model_init }, | |
1042 | { "sh4", & sh4_mach, MODEL_SH5, NULL, sh64_model_init }, | |
1043 | { "sh4_nofpu", & sh4_nofpu_mach, MODEL_SH5, NULL, sh64_model_init }, | |
1044 | { "sh4a", & sh4a_mach, MODEL_SH5, NULL, sh64_model_init }, | |
1045 | { "sh4a_nofpu", & sh4a_nofpu_mach, MODEL_SH5, NULL, sh64_model_init }, | |
1046 | { "sh4al", & sh4al_mach, MODEL_SH5, NULL, sh64_model_init }, | |
1047 | { "sh5", & sh5_mach, MODEL_SH5, NULL, sh64_model_init }, | |
cbb38b47 BE |
1048 | { 0 } |
1049 | }; | |
1050 | ||
1051 | static const MACH_IMP_PROPERTIES sh5_imp_properties = | |
1052 | { | |
1053 | sizeof (SIM_CPU), | |
1054 | #if WITH_SCACHE | |
1055 | sizeof (SCACHE) | |
1056 | #else | |
1057 | 0 | |
1058 | #endif | |
1059 | }; | |
1060 | ||
1061 | const MACH sh2_mach = | |
1062 | { | |
1063 | "sh2", "sh2", MACH_SH5, | |
1064 | 16, 16, &sh_models[0], &sh5_imp_properties, | |
1065 | shcompact_init_cpu, | |
1066 | sh64_prepare_run | |
1067 | }; | |
1068 | ||
c7e628df DB |
1069 | const MACH sh2e_mach = |
1070 | { | |
1071 | "sh2e", "sh2e", MACH_SH5, | |
1072 | 16, 16, &sh_models[1], &sh5_imp_properties, | |
1073 | shcompact_init_cpu, | |
1074 | sh64_prepare_run | |
1075 | }; | |
1076 | ||
1077 | const MACH sh2a_fpu_mach = | |
1078 | { | |
1079 | "sh2a", "sh2a", MACH_SH5, | |
1080 | 16, 16, &sh_models[2], &sh5_imp_properties, | |
1081 | shcompact_init_cpu, | |
1082 | sh64_prepare_run | |
1083 | }; | |
1084 | ||
1085 | const MACH sh2a_nofpu_mach = | |
1086 | { | |
1087 | "sh2a_nofpu", "sh2a_nofpu", MACH_SH5, | |
1088 | 16, 16, &sh_models[3], &sh5_imp_properties, | |
1089 | shcompact_init_cpu, | |
1090 | sh64_prepare_run | |
1091 | }; | |
1092 | ||
cbb38b47 BE |
1093 | const MACH sh3_mach = |
1094 | { | |
1095 | "sh3", "sh3", MACH_SH5, | |
c7e628df | 1096 | 16, 16, &sh_models[4], &sh5_imp_properties, |
cbb38b47 BE |
1097 | shcompact_init_cpu, |
1098 | sh64_prepare_run | |
1099 | }; | |
1100 | ||
1101 | const MACH sh3e_mach = | |
1102 | { | |
1103 | "sh3e", "sh3e", MACH_SH5, | |
c7e628df | 1104 | 16, 16, &sh_models[5], &sh5_imp_properties, |
cbb38b47 BE |
1105 | shcompact_init_cpu, |
1106 | sh64_prepare_run | |
1107 | }; | |
1108 | ||
1109 | const MACH sh4_mach = | |
1110 | { | |
1111 | "sh4", "sh4", MACH_SH5, | |
c7e628df DB |
1112 | 16, 16, &sh_models[6], &sh5_imp_properties, |
1113 | shcompact_init_cpu, | |
1114 | sh64_prepare_run | |
1115 | }; | |
1116 | ||
1117 | const MACH sh4_nofpu_mach = | |
1118 | { | |
1119 | "sh4_nofpu", "sh4_nofpu", MACH_SH5, | |
1120 | 16, 16, &sh_models[7], &sh5_imp_properties, | |
1121 | shcompact_init_cpu, | |
1122 | sh64_prepare_run | |
1123 | }; | |
1124 | ||
1125 | const MACH sh4a_mach = | |
1126 | { | |
1127 | "sh4a", "sh4a", MACH_SH5, | |
1128 | 16, 16, &sh_models[8], &sh5_imp_properties, | |
1129 | shcompact_init_cpu, | |
1130 | sh64_prepare_run | |
1131 | }; | |
1132 | ||
1133 | const MACH sh4a_nofpu_mach = | |
1134 | { | |
1135 | "sh4a_nofpu", "sh4a_nofpu", MACH_SH5, | |
1136 | 16, 16, &sh_models[9], &sh5_imp_properties, | |
1137 | shcompact_init_cpu, | |
1138 | sh64_prepare_run | |
1139 | }; | |
1140 | ||
1141 | const MACH sh4al_mach = | |
1142 | { | |
1143 | "sh4al", "sh4al", MACH_SH5, | |
1144 | 16, 16, &sh_models[10], &sh5_imp_properties, | |
cbb38b47 BE |
1145 | shcompact_init_cpu, |
1146 | sh64_prepare_run | |
1147 | }; | |
1148 | ||
1149 | const MACH sh5_mach = | |
1150 | { | |
1151 | "sh5", "sh5", MACH_SH5, | |
c7e628df | 1152 | 32, 32, &sh_models[11], &sh5_imp_properties, |
cbb38b47 BE |
1153 | shmedia_init_cpu, |
1154 | sh64_prepare_run | |
1155 | }; |