This commit was generated by cvs2svn to track changes on a CVS vendor
[external/binutils.git] / sim / sh64 / sh64.c
1 /* SH5 simulator support code
2    Copyright (C) 2000, 2001 Free Software Foundation, Inc.
3    Contributed by Red Hat, Inc.
4
5 This file is part of the GNU simulators.
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License along
18 with this program; if not, write to the Free Software Foundation, Inc.,
19 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
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
29 #include "gdb/callback.h"
30 #include "defs-compact.h"
31
32 #include "bfd.h"
33 /* From include/gdb/.  */
34 #include "gdb/sim-sh.h"
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
463 void
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
487 /* Count the number of arguments.  */
488 static int
489 count_argc (cpu)
490      SIM_CPU *cpu;
491 {
492   int i = 0;
493
494   if (! STATE_PROG_ARGV (CPU_STATE (cpu)))
495     return -1;
496   
497   while (STATE_PROG_ARGV (CPU_STATE (cpu)) [i] != NULL)
498     ++i;
499
500   return i;
501 }
502
503 /* Read a null terminated string from memory, return in a buffer */
504 static char *
505 fetch_str (current_cpu, pc, addr)
506      SIM_CPU *current_cpu;
507      PCADDR pc;
508      DI addr;
509 {
510   char *buf;
511   int nr = 0;
512   while (sim_core_read_1 (current_cpu,
513                           pc, read_map, addr + nr) != 0)
514     nr++;
515   buf = NZALLOC (char, nr + 1);
516   sim_read (CPU_STATE (current_cpu), addr, buf, nr);
517   return buf;
518 }
519
520 static void
521 trap_handler (SIM_CPU *current_cpu, int shmedia_abi_p, UQI trapnum, PCADDR pc)
522 {
523   char ch;
524   switch (trapnum)
525     {
526     case 1:
527       ch = GET_H_GRC (0);
528       sim_io_write_stdout (CPU_STATE (current_cpu), &ch, 1);
529       fflush (stdout);
530       break;
531     case 2:
532       sim_engine_halt (CPU_STATE (current_cpu), current_cpu, NULL, pc, sim_stopped, SIM_SIGTRAP);
533       break;
534     case 34:
535       {
536         int i;
537         int ret_reg = (shmedia_abi_p) ? 2 : 0;
538         char *buf;
539         DI PARM1 = GET_H_GR ((shmedia_abi_p) ? 3 : 5);
540         DI PARM2 = GET_H_GR ((shmedia_abi_p) ? 4 : 6);
541         DI PARM3 = GET_H_GR ((shmedia_abi_p) ? 5 : 7);
542         
543         switch (GET_H_GR ((shmedia_abi_p) ? 2 : 4))
544           {
545           case SYS_write:
546             buf = zalloc (PARM3);
547             sim_read (CPU_STATE (current_cpu), PARM2, buf, PARM3);
548             SET_H_GR (ret_reg,
549                       sim_io_write (CPU_STATE (current_cpu),
550                                     PARM1, buf, PARM3));
551             zfree (buf);
552             break;
553
554           case SYS_lseek:
555             SET_H_GR (ret_reg,
556                       sim_io_lseek (CPU_STATE (current_cpu),
557                                     PARM1, PARM2, PARM3));
558             break;
559             
560           case SYS_exit:
561             sim_engine_halt (CPU_STATE (current_cpu), current_cpu,
562                              NULL, pc, sim_exited, PARM1);
563             break;
564
565           case SYS_read:
566             buf = zalloc (PARM3);
567             SET_H_GR (ret_reg,
568                       sim_io_read (CPU_STATE (current_cpu),
569                                    PARM1, buf, PARM3));
570             sim_write (CPU_STATE (current_cpu), PARM2, buf, PARM3);
571             zfree (buf);
572             break;
573             
574           case SYS_open:
575             buf = fetch_str (current_cpu, pc, PARM1);
576             SET_H_GR (ret_reg,
577                       sim_io_open (CPU_STATE (current_cpu),
578                                    buf, PARM2));
579             zfree (buf);
580             break;
581
582           case SYS_close:
583             SET_H_GR (ret_reg,
584                       sim_io_close (CPU_STATE (current_cpu), PARM1));
585             break;
586
587           case SYS_time:
588             SET_H_GR (ret_reg, time (0));
589             break;
590
591           case SYS_argc:
592             SET_H_GR (ret_reg, count_argc (current_cpu));
593             break;
594
595           case SYS_argnlen:
596             if (PARM1 < count_argc (current_cpu))
597               SET_H_GR (ret_reg,
598                         strlen (STATE_PROG_ARGV (CPU_STATE (current_cpu)) [PARM1]));
599             else
600               SET_H_GR (ret_reg, -1);
601             break;
602
603           case SYS_argn:
604             if (PARM1 < count_argc (current_cpu))
605               {
606                 /* Include the NULL byte.  */
607                 i = strlen (STATE_PROG_ARGV (CPU_STATE (current_cpu)) [PARM1]) + 1;
608                 sim_write (CPU_STATE (current_cpu),
609                            PARM2,
610                            STATE_PROG_ARGV (CPU_STATE (current_cpu)) [PARM1],
611                            i);
612
613                 /* Just for good measure.  */
614                 SET_H_GR (ret_reg, i);
615                 break;
616               }
617             else
618               SET_H_GR (ret_reg, -1);
619             break;
620
621           default:
622             SET_H_GR (ret_reg, -1);
623           }
624       }
625       break;
626     case 253:
627       puts ("pass");
628       exit (0);
629     case 254:
630       puts ("fail");
631       exit (1);
632     case 0xc3:
633       /* fall through.  */
634     case 255:
635       sim_engine_halt (CPU_STATE (current_cpu), current_cpu, NULL, pc, sim_stopped, SIM_SIGTRAP);
636       break;
637     }
638 }
639
640 void
641 sh64_trapa (SIM_CPU *current_cpu, DI rm, PCADDR pc)
642 {
643   trap_handler (current_cpu, 1, (UQI) rm & 0xff, pc);
644 }
645
646 void
647 sh64_compact_trapa (SIM_CPU *current_cpu, UQI trapnum, PCADDR pc)
648 {
649   int mach_sh5_p;
650
651   /* If this is an SH5 executable, this is SHcompact code running in
652      the SHmedia ABI.  */
653
654   mach_sh5_p =
655     (bfd_get_mach (STATE_PROG_BFD (CPU_STATE (current_cpu))) == bfd_mach_sh5);
656
657   trap_handler (current_cpu, mach_sh5_p, trapnum, pc);
658 }
659
660 DI
661 sh64_nsb (SIM_CPU *current_cpu, DI rm)
662 {
663   int result = 0, count;
664   UDI source = (UDI) rm;
665
666   if ((source >> 63))
667     source = ~source;
668   source <<= 1;
669
670   for (count = 32; count; count >>= 1)
671     {
672       UDI newval = source << count;
673
674       if ((newval >> count) == source)
675         {
676           result |= count;
677           source = newval;
678         }
679     }
680   
681   return result;
682 }
683
684 void
685 sh64_break (SIM_CPU *current_cpu, PCADDR pc)
686 {
687   SIM_DESC sd = CPU_STATE (current_cpu);
688   sim_engine_halt (sd, current_cpu, NULL, pc, sim_stopped, SIM_SIGTRAP);
689 }
690
691 void
692 set_isa (SIM_CPU *current_cpu, int mode)
693 {
694   /* Do nothing.  */
695 }
696
697 /* The semantic code invokes this for invalid (unrecognized) instructions.  */
698
699 SEM_PC
700 sim_engine_invalid_insn (SIM_CPU *current_cpu, IADDR cia, SEM_PC vpc)
701 {
702   SIM_DESC sd = CPU_STATE (current_cpu);
703   sim_engine_halt (sd, current_cpu, NULL, cia, sim_stopped, SIM_SIGILL);
704
705   return vpc;
706 }
707
708
709 /* Process an address exception.  */
710
711 void
712 sh64_core_signal (SIM_DESC sd, SIM_CPU *current_cpu, sim_cia cia,
713                   unsigned int map, int nr_bytes, address_word addr,
714                   transfer_type transfer, sim_core_signals sig)
715 {
716   sim_core_signal (sd, current_cpu, cia, map, nr_bytes, addr,
717                    transfer, sig);
718 }
719
720
721 /* Initialize cycle counting for an insn.
722    FIRST_P is non-zero if this is the first insn in a set of parallel
723    insns.  */
724
725 void
726 sh64_compact_model_insn_before (SIM_CPU *cpu, int first_p)
727 {
728   /* Do nothing.  */
729 }
730
731 void
732 sh64_media_model_insn_before (SIM_CPU *cpu, int first_p)
733 {
734   /* Do nothing.  */
735 }
736
737 /* Record the cycles computed for an insn.
738    LAST_P is non-zero if this is the last insn in a set of parallel insns,
739    and we update the total cycle count.
740    CYCLES is the cycle count of the insn.  */
741
742 void
743 sh64_compact_model_insn_after(SIM_CPU *cpu, int last_p, int cycles)
744 {
745   /* Do nothing.  */
746 }
747
748 void
749 sh64_media_model_insn_after(SIM_CPU *cpu, int last_p, int cycles)
750 {
751   /* Do nothing.  */
752 }
753
754 int
755 sh64_fetch_register (SIM_CPU *cpu, int nr, unsigned char *buf, int len)
756 {
757   /* Fetch general purpose registers. */
758   if (nr >= SIM_SH64_R0_REGNUM
759       && nr < (SIM_SH64_R0_REGNUM + SIM_SH64_NR_R_REGS)
760       && len == 8)
761     {
762       *((unsigned64*) buf) =
763         H2T_8 (sh64_h_gr_get (cpu, nr - SIM_SH64_R0_REGNUM));
764       return len;
765     }
766
767   /* Fetch PC.  */
768   if (nr == SIM_SH64_PC_REGNUM && len == 8)
769     {
770       *((unsigned64*) buf) = H2T_8 (sh64_h_pc_get (cpu) | sh64_h_ism_get (cpu));
771       return len;
772     }
773
774   /* Fetch status register (SR).  */
775   if (nr == SIM_SH64_SR_REGNUM && len == 8)
776     {
777       *((unsigned64*) buf) = H2T_8 (sh64_h_sr_get (cpu));
778       return len;
779     }
780       
781   /* Fetch saved status register (SSR) and PC (SPC).  */
782   if ((nr == SIM_SH64_SSR_REGNUM || nr == SIM_SH64_SPC_REGNUM)
783       && len == 8)
784     {
785       *((unsigned64*) buf) = 0;
786       return len;
787     }
788
789   /* Fetch target registers.  */
790   if (nr >= SIM_SH64_TR0_REGNUM
791       && nr < (SIM_SH64_TR0_REGNUM + SIM_SH64_NR_TR_REGS)
792       && len == 8)
793     {
794       *((unsigned64*) buf) =
795         H2T_8 (sh64_h_tr_get (cpu, nr - SIM_SH64_TR0_REGNUM));
796       return len;
797     }
798
799   /* Fetch floating point registers.  */
800   if (nr >= SIM_SH64_FR0_REGNUM
801       && nr < (SIM_SH64_FR0_REGNUM + SIM_SH64_NR_FP_REGS)
802       && len == 4)
803     {
804       *((unsigned32*) buf) =
805         H2T_4 (sh64_h_fr_get (cpu, nr - SIM_SH64_FR0_REGNUM));
806       return len;
807     }
808
809   /* We should never get here.  */
810   return 0;
811 }
812
813 int
814 sh64_store_register (SIM_CPU *cpu, int nr, unsigned char *buf, int len)
815 {
816   /* Store general purpose registers. */
817   if (nr >= SIM_SH64_R0_REGNUM
818       && nr < (SIM_SH64_R0_REGNUM + SIM_SH64_NR_R_REGS)
819       && len == 8)
820     {
821       sh64_h_gr_set (cpu, nr - SIM_SH64_R0_REGNUM, T2H_8 (*((unsigned64*)buf)));
822       return len;
823     }
824
825   /* Store PC.  */
826   if (nr == SIM_SH64_PC_REGNUM && len == 8)
827     {
828       unsigned64 new_pc = T2H_8 (*((unsigned64*)buf));
829       sh64_h_pc_set (cpu, new_pc);
830       return len;
831     }
832
833   /* Store status register (SR).  */
834   if (nr == SIM_SH64_SR_REGNUM && len == 8)
835     {
836       sh64_h_sr_set (cpu, T2H_8 (*((unsigned64*)buf)));
837       return len;
838     }
839
840   /* Store saved status register (SSR) and PC (SPC).  */
841   if (nr == SIM_SH64_SSR_REGNUM || nr == SIM_SH64_SPC_REGNUM)
842     {
843       /* Do nothing.  */
844       return len;
845     }
846
847   /* Store target registers.  */
848   if (nr >= SIM_SH64_TR0_REGNUM
849       && nr < (SIM_SH64_TR0_REGNUM + SIM_SH64_NR_TR_REGS)
850       && len == 8)
851     {
852       sh64_h_tr_set (cpu, nr - SIM_SH64_TR0_REGNUM, T2H_8 (*((unsigned64*)buf)));
853       return len;
854     }
855
856   /* Store floating point registers.  */
857   if (nr >= SIM_SH64_FR0_REGNUM
858       && nr < (SIM_SH64_FR0_REGNUM + SIM_SH64_NR_FP_REGS)
859       && len == 4)
860     {
861       sh64_h_fr_set (cpu, nr - SIM_SH64_FR0_REGNUM, T2H_4 (*((unsigned32*)buf)));
862       return len;
863     }
864
865   /* We should never get here.  */
866   return 0;
867 }
868
869 void
870 sh64_engine_run_full(SIM_CPU *cpu)
871 {
872   if (sh64_h_ism_get (cpu) == ISM_MEDIA)
873     {
874       if (!sh64_idesc_media)
875         {
876           sh64_media_init_idesc_table (cpu);
877           sh64_idesc_media = CPU_IDESC (cpu);
878         }
879       else
880         CPU_IDESC (cpu) = sh64_idesc_media;
881       sh64_media_engine_run_full (cpu);
882     }
883   else
884     {
885       if (!sh64_idesc_compact)
886         {
887           sh64_compact_init_idesc_table (cpu);
888           sh64_idesc_compact = CPU_IDESC (cpu);
889         }
890       else
891         CPU_IDESC (cpu) = sh64_idesc_compact;
892       sh64_compact_engine_run_full (cpu);
893     }
894 }
895
896 void
897 sh64_engine_run_fast (SIM_CPU *cpu)
898 {
899   if (sh64_h_ism_get (cpu) == ISM_MEDIA)
900     {
901       if (!sh64_idesc_media)
902         {
903           sh64_media_init_idesc_table (cpu);
904           sh64_idesc_media = CPU_IDESC (cpu);
905         }
906       else
907         CPU_IDESC (cpu) = sh64_idesc_media;
908       sh64_media_engine_run_fast (cpu);
909     }
910   else
911     {
912       if (!sh64_idesc_compact)
913         {
914           sh64_compact_init_idesc_table (cpu);
915           sh64_idesc_compact = CPU_IDESC (cpu);
916         }
917       else
918         CPU_IDESC (cpu) = sh64_idesc_compact;
919       sh64_compact_engine_run_fast (cpu);
920     }
921 }
922
923 static void
924 sh64_prepare_run (SIM_CPU *cpu)
925 {
926   /* Nothing.  */
927 }
928
929 static const CGEN_INSN *
930 sh64_get_idata (SIM_CPU *cpu, int inum)
931 {
932   return CPU_IDESC (cpu) [inum].idata;
933 }
934
935 static void
936 sh64_init_cpu (SIM_CPU *cpu)
937 {
938   CPU_REG_FETCH (cpu) = sh64_fetch_register;
939   CPU_REG_STORE (cpu) = sh64_store_register;
940   CPU_PC_FETCH (cpu) = sh64_h_pc_get;
941   CPU_PC_STORE (cpu) = sh64_h_pc_set;
942   CPU_GET_IDATA (cpu) = sh64_get_idata;
943   /* Only used by profiling.  0 disables it. */
944   CPU_MAX_INSNS (cpu) = 0;
945   CPU_INSN_NAME (cpu) = cgen_insn_name;
946   CPU_FULL_ENGINE_FN (cpu) = sh64_engine_run_full;
947 #if WITH_FAST
948   CPU_FAST_ENGINE_FN (cpu) = sh64_engine_run_fast;
949 #else
950   CPU_FAST_ENGINE_FN (cpu) = sh64_engine_run_full;
951 #endif
952 }
953
954 static void
955 shmedia_init_cpu (SIM_CPU *cpu)
956 {
957   sh64_init_cpu (cpu);
958 }
959
960 static void
961 shcompact_init_cpu (SIM_CPU *cpu)
962
963   sh64_init_cpu (cpu);
964 }
965
966 static void
967 sh64_model_init()
968 {
969   /* Do nothing.  */
970 }
971
972 static const MODEL sh_models [] =
973 {
974   { "sh2",  & sh2_mach,  MODEL_SH5, NULL, sh64_model_init },
975   { "sh3",  & sh3_mach,  MODEL_SH5, NULL, sh64_model_init },
976   { "sh3e", & sh3_mach,  MODEL_SH5, NULL, sh64_model_init },
977   { "sh4",  & sh4_mach,  MODEL_SH5, NULL, sh64_model_init },
978   { "sh5",  & sh5_mach,  MODEL_SH5, NULL, sh64_model_init },
979   { 0 }
980 };
981
982 static const MACH_IMP_PROPERTIES sh5_imp_properties =
983 {
984   sizeof (SIM_CPU),
985 #if WITH_SCACHE
986   sizeof (SCACHE)
987 #else
988   0
989 #endif
990 };
991
992 const MACH sh2_mach =
993 {
994   "sh2", "sh2", MACH_SH5,
995   16, 16, &sh_models[0], &sh5_imp_properties,
996   shcompact_init_cpu,
997   sh64_prepare_run
998 };
999
1000 const MACH sh3_mach =
1001 {
1002   "sh3", "sh3", MACH_SH5,
1003   16, 16, &sh_models[1], &sh5_imp_properties,
1004   shcompact_init_cpu,
1005   sh64_prepare_run
1006 };
1007
1008 const MACH sh3e_mach =
1009 {
1010   "sh3e", "sh3e", MACH_SH5,
1011   16, 16, &sh_models[2], &sh5_imp_properties,
1012   shcompact_init_cpu,
1013   sh64_prepare_run
1014 };
1015
1016 const MACH sh4_mach =
1017 {
1018   "sh4", "sh4", MACH_SH5,
1019   16, 16, &sh_models[3], &sh5_imp_properties,
1020   shcompact_init_cpu,
1021   sh64_prepare_run
1022 };
1023
1024 const MACH sh5_mach =
1025 {
1026   "sh5", "sh5", MACH_SH5,
1027   32, 32, &sh_models[4], &sh5_imp_properties,
1028   shmedia_init_cpu,
1029   sh64_prepare_run
1030 };