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