OSDN Git Service

dd01fb3a119b60cda6c9cb75527533ed8ae72997
[pf3gnuchains/pf3gnuchains4x.git] / sid / component / cgen-cpu / sh / sh.cxx
1 // sh.cxx - Implementations of hand-written functions for the sh
2 // simulator. -*- C++ -*-
3
4 // Copyright (C) 2006 Red Hat.
5 // This file is part of SID and is licensed under the GPL.
6 // See the file COPYING.SID for conditions for redistribution.
7
8 #include "sh.h"
9 #include "fp.h"
10
11 extern "C" {
12 #include "bfd.h"
13 #include "dis-asm.h"
14 }
15
16 using namespace std;
17 using namespace sid;
18 using namespace sidutil;
19 using namespace sh;
20
21 template<class CGEN_CPU>
22 sh_cpu<CGEN_CPU>::sh_cpu () :
23   pending_latency (0)
24 {
25 #if 0
26   for (unsigned i = 0; i < 16; ++i)
27     {
28       string name = string ("GR") + make_numeric_attribute (i);
29       SI* value = & this->hardware.h_gr[i];
30       this->add_watchable_register (name, value);
31     }
32 #endif
33   // add syscall registers
34   this->add_watchable_register (string("syscall-arg0"), &syscall_arg0);
35   this->add_watchable_register (string("syscall-arg1"), &syscall_arg1);
36   this->add_watchable_register (string("syscall-arg2"), &syscall_arg2);
37   this->add_watchable_register (string("syscall-arg3"), &syscall_arg3);
38   this->add_watchable_register (string("syscall-result"), &syscall_result);
39   this->add_watchable_register (string("syscall-error"), &syscall_error);
40   syscall_trap_num = 34;
41   this->add_attribute (string("syscall-trap"), &syscall_trap_num, "setting");
42
43   add_watchable_pin ("cache-prefetch", &cache_prefetch_pin);
44
45 #if 0 // customize this  
46   this->create_gdb_register_attrs (17, "", & this->hardware.h_pc);
47 #endif
48 }
49
50 template<class CGEN_CPU>
51 void
52 sh_cpu<CGEN_CPU>::reset()
53 {
54   this->hardware.h_sr = 0xf0;
55   write_stacks_reset ();
56   if (UNLIKELY (this->trace_counter_p || this->final_insn_count_p))
57     this->set_total_latency (2); // Initial IF + ID
58   else
59     this->set_total_latency (0);
60 }
61
62 template<class CGEN_CPU>
63 void
64 sh_cpu<CGEN_CPU>::set_eflags(sid::host_int_4 flags)
65 {
66   this->eflags = flags;
67 }
68
69 static int ef_to_bfd_mach_table [] = { EF_SH_BFD_TABLE };
70
71 template<class CGEN_CPU>
72 int
73 sh_cpu<CGEN_CPU>::bfd_machine () const
74 {
75   return ef_to_bfd_mach_table[elf_machine ()];
76 }
77
78 template<class CGEN_CPU>
79 void
80 sh_cpu<CGEN_CPU>::invalid_insn (PCADDR pc)
81 {
82   this->h_pc_set (pc);
83
84   cpu_trap_disposition whatnext = this->signal_trap (cpu_trap_invalid_insn, pc);
85
86   switch (whatnext)
87     {
88     case cpu_trap_unhandled:
89       cerr << "sh: unhandled invalid insn, pc=" << pc << endl;
90       break;
91
92     case cpu_trap_skip:
93       {
94         PCADDR npc = pc + insn_size (pc);
95         this->h_pc_set (npc);
96       }
97       break;
98
99     case cpu_trap_handled:
100     case cpu_trap_reissue:
101       break;
102
103     default:
104       abort ();
105     }
106
107   this->yield();
108   throw cpu_exception ();
109 }
110
111 // Memory trap(/fault) handling.
112 template<class CGEN_CPU>
113 void
114 sh_cpu<CGEN_CPU>::memory_trap (const cpu_memory_fault& t)
115 {
116   this->h_pc_set (t.pc);
117
118   cpu_trap_disposition whatnext = this->signal_trap (cpu_trap_memory_fault, t.address);
119
120   switch (whatnext)
121     {
122     case cpu_trap_unhandled:
123       cerr << "sh: unhandled memory trap, pc=" << t.pc << endl;
124       break;
125
126     case cpu_trap_skip:
127       {
128         PCADDR pc = t.pc + insn_size (pc);
129         this->h_pc_set (pc);
130       }
131       break;
132
133     case cpu_trap_handled:
134     case cpu_trap_reissue:
135       break;
136
137     default:
138       abort ();
139     }
140
141   this->yield();
142 }
143
144 template<class CGEN_CPU>
145 string
146 sh_cpu<CGEN_CPU>::dbg_get_reg (host_int_4 reg)
147 {
148   string attr;
149   host_int_4 val;
150   int size = reg < 16 ? 2 : 4;
151 #if 0 // customize this
152   /* Bank zero regs */
153   if (reg < 16)
154     val = h_gr_get (reg);
155   else if (reg == 16)
156     val = h_pc_get ();
157   else
158 #endif
159     val = 0;
160
161   // Change to "target endian".
162   little_int_4 v = val;
163   for (unsigned i = 0; i < size; i++)
164     attr += v.read_byte (i);
165
166   return attr;
167 }
168
169 template<class CGEN_CPU>
170 component::status
171 sh_cpu<CGEN_CPU>::dbg_set_reg (host_int_4 reg, const string& attr)
172 {
173   // change from "target endian"
174   little_int_4 v;
175   int size = reg < 16 ? 2 : 4;
176   for (unsigned i = 0; i < size; i++)
177     v.write_byte (i, attr[i]);
178   host_int_4 val = v;
179
180 #if 0 // customize this
181   /* Bank zero regs */
182   if (reg < 16)
183     h_gr_set (reg, val);
184   else if (reg == 16)
185     h_pc_set (val);
186   else
187 #endif
188     return component::bad_value;
189
190   return component::ok;
191 }
192
193 // C++ implementations of instructions follow here
194 template<class CGEN_CPU>
195 void
196 sh_cpu<CGEN_CPU>::sh64_break (PCADDR pc)
197 {
198   this->yield();
199   throw cpu_exception ();
200 }
201
202 template<class CGEN_CPU>
203 SF
204 sh_cpu<CGEN_CPU>::sh64_fldi0 ()
205 {
206   return this->fpu.ops->floatsisf (& this->fpu, 0);
207 }
208
209 template<class CGEN_CPU>
210 SF
211 sh_cpu<CGEN_CPU>::sh64_fldi1 ()
212 {
213   return this->fpu.ops->floatsisf (& this->fpu, 1);
214 }
215
216 template<class CGEN_CPU>
217 DF
218 sh_cpu<CGEN_CPU>::sh64_fabsd(DF drgh)
219 {
220   return this->fpu.ops->absdf (& this->fpu, drgh);
221 }
222
223 template<class CGEN_CPU>
224 SF
225 sh_cpu<CGEN_CPU>::sh64_fabss(SF frgh)
226 {
227   return this->fpu.ops->abssf (& this->fpu, frgh);
228 }
229
230 template<class CGEN_CPU>
231 DF
232 sh_cpu<CGEN_CPU>::sh64_faddd(DF drg, DF drh)
233 {
234   return this->fpu.ops->adddf (& this->fpu, drg, drh);
235 }
236
237 template<class CGEN_CPU>
238 SF
239 sh_cpu<CGEN_CPU>::sh64_fadds(SF frg, SF frh)
240 {
241   return this->fpu.ops->addsf (& this->fpu, frg, frh);
242 }
243
244 template<class CGEN_CPU>
245 BI
246 sh_cpu<CGEN_CPU>::sh64_fcmpeqd(DF drg, DF drh)
247 {
248   return this->fpu.ops->eqdf (& this->fpu, drg, drh);
249 }
250
251 template<class CGEN_CPU>
252 BI
253 sh_cpu<CGEN_CPU>::sh64_fcmpeqs(SF frg, SF frh)
254 {
255   return this->fpu.ops->eqsf (& this->fpu, frg, frh);
256 }
257
258 template<class CGEN_CPU>
259 BI
260 sh_cpu<CGEN_CPU>::sh64_fcmpged(DF drg, DF drh)
261 {
262   return this->fpu.ops->gedf (& this->fpu, drg, drh);
263 }
264
265 template<class CGEN_CPU>
266 BI
267 sh_cpu<CGEN_CPU>::sh64_fcmpges(SF frg, SF frh)
268 {
269   return this->fpu.ops->gesf (& this->fpu, frg, frh);
270 }
271
272 template<class CGEN_CPU>
273 BI
274 sh_cpu<CGEN_CPU>::sh64_fcmpgtd(DF drg, DF drh)
275 {
276   return this->fpu.ops->gtdf (& this->fpu, drg, drh);
277 }
278
279 template<class CGEN_CPU>
280 BI
281 sh_cpu<CGEN_CPU>::sh64_fcmpgts(SF frg, SF frh)
282 {
283   return this->fpu.ops->gtsf (& this->fpu, frg, frh);
284 }
285
286 template<class CGEN_CPU>
287 BI
288 sh_cpu<CGEN_CPU>::sh64_fcmpund(DF drg, DF drh)
289 {
290   return this->fpu.ops->unordereddf (& this->fpu, drg, drh);
291 }
292
293 template<class CGEN_CPU>
294 BI
295 sh_cpu<CGEN_CPU>::sh64_fcmpuns(SF frg, SF frh)
296 {
297   return this->fpu.ops->unorderedsf (& this->fpu, frg, frh);
298 }  
299
300 template<class CGEN_CPU>
301 SF
302 sh_cpu<CGEN_CPU>::sh64_fcnvds(DF drgh)
303 {
304   return this->fpu.ops->ftruncdfsf (& this->fpu, drgh);
305 }
306
307 template<class CGEN_CPU>
308 DF
309 sh_cpu<CGEN_CPU>::sh64_fcnvsd(SF frgh)
310 {
311   return this->fpu.ops->fextsfdf (& this->fpu, frgh);
312 }
313
314 template<class CGEN_CPU>
315 DF
316 sh_cpu<CGEN_CPU>::sh64_fdivd(DF drg, DF drh)
317 {
318   return this->fpu.ops->divdf (& this->fpu, drg, drh);
319 }
320
321 template<class CGEN_CPU>
322 SF
323 sh_cpu<CGEN_CPU>::sh64_fdivs(SF frg, SF frh)
324 {
325   return this->fpu.ops->divsf (& this->fpu, frg, frh);
326 }
327
328 template<class CGEN_CPU>
329 DF
330 sh_cpu<CGEN_CPU>::sh64_floatld(SF frgh)
331 {
332   return this->fpu.ops->floatsidf (& this->fpu, frgh);
333 }
334
335 template<class CGEN_CPU>
336 SF
337 sh_cpu<CGEN_CPU>::sh64_floatls(SF frgh)
338 {
339   return this->fpu.ops->floatsisf (& this->fpu, frgh);
340 }
341
342 template<class CGEN_CPU>
343 DF
344 sh_cpu<CGEN_CPU>::sh64_floatqd(DF drgh)
345 {
346   return this->fpu.ops->floatdidf (& this->fpu, drgh);
347 }
348
349 template<class CGEN_CPU>
350 SF
351 sh_cpu<CGEN_CPU>::sh64_floatqs(DF drgh)
352 {
353   return this->fpu.ops->floatdisf (& this->fpu, drgh);
354 }
355
356 template<class CGEN_CPU>
357 SF
358 sh_cpu<CGEN_CPU>::sh64_fmacs(SF fr0, SF frm, SF frn)
359 {
360   SF result = this->fpu.ops->mulsf (& this->fpu, fr0, frm);
361   result = this->fpu.ops->addsf (& this->fpu, result, frn);
362   return result;
363 }
364
365 template<class CGEN_CPU>
366 DF
367 sh_cpu<CGEN_CPU>::sh64_fmuld(DF drg, DF drh)
368 {
369   return this->fpu.ops->muldf (& this->fpu, drg, drh);
370 }
371
372 template<class CGEN_CPU>
373 SF
374 sh_cpu<CGEN_CPU>::sh64_fmuls(SF frg, SF frh)
375 {
376   return this->fpu.ops->mulsf (& this->fpu, frg, frh);
377 }
378
379 template<class CGEN_CPU>
380 DF
381 sh_cpu<CGEN_CPU>::sh64_fnegd(DF drgh)
382 {
383   return this->fpu.ops->negdf (& this->fpu, drgh);
384 }
385
386 template<class CGEN_CPU>
387 SF
388 sh_cpu<CGEN_CPU>::sh64_fnegs(SF frgh)
389 {
390   return this->fpu.ops->negsf (& this->fpu, frgh);
391 }
392
393 template<class CGEN_CPU>
394 DF
395 sh_cpu<CGEN_CPU>::sh64_fsqrtd(DF drgh)
396 {
397   return this->fpu.ops->sqrtdf (& this->fpu, drgh);
398 }
399
400 template<class CGEN_CPU>
401 SF
402 sh_cpu<CGEN_CPU>::sh64_fsqrts(SF frgh)
403 {
404   return this->fpu.ops->sqrtsf (& this->fpu, frgh);
405 }
406
407 template<class CGEN_CPU>
408 DF
409 sh_cpu<CGEN_CPU>::sh64_fsubd(DF drg, DF drh)
410 {
411   return this->fpu.ops->subdf (& this->fpu, drg, drh);
412 }
413
414 template<class CGEN_CPU>
415 SF
416 sh_cpu<CGEN_CPU>::sh64_fsubs(SF frg, SF frh)
417 {
418   return this->fpu.ops->subsf (& this->fpu, frg, frh);
419 }
420
421 template<class CGEN_CPU>
422 SF
423 sh_cpu<CGEN_CPU>::sh64_ftrcdl(DF drgh)
424 {
425   return this->fpu.ops->fixdfsi (& this->fpu, drgh);
426 }
427
428 template<class CGEN_CPU>
429 SF
430 sh_cpu<CGEN_CPU>::sh64_ftrcsl(SF frgh)
431 {
432   return this->fpu.ops->fixsfsi (& this->fpu, frgh);
433 }
434
435 template<class CGEN_CPU>
436 DF
437 sh_cpu<CGEN_CPU>::sh64_ftrcdq(DF drgh)
438 {
439   return this->fpu.ops->fixdfdi (& this->fpu, drgh);
440 }
441
442 template<class CGEN_CPU>
443 DF
444 sh_cpu<CGEN_CPU>::sh64_ftrcsq(SF frgh)
445 {
446   return this->fpu.ops->fixsfdi (& this->fpu, frgh);
447 }
448
449 template<class CGEN_CPU>
450 void
451 sh_cpu<CGEN_CPU>::sh64_ftrvs(unsigned g, unsigned h, unsigned f)
452 {
453   int i, j;
454   SF zero = this->fpu.ops->floatsisf (& this->fpu, 0);
455   for (i = 0; i < 4; i++)
456     {
457       SF result = zero;
458       for (j = 0; j < 4; j++)
459         {
460           SF f1, f2, temp;
461           f1 = this->h_fr_get ((g + i) + (j * 4));
462           f2 = this->h_fr_get (h + j);
463           temp = this->fpu.ops->mulsf (& this->fpu, f1, f2);
464           result = this->fpu.ops->addsf (& this->fpu, result, temp);
465         }
466       this->h_fr_set (f + i, result);
467     }
468 }
469
470 template<class CGEN_CPU>
471 void
472 sh_cpu<CGEN_CPU>::sh64_pref (DI addr)
473 {
474   cache_prefetch_pin.drive (addr);
475 }
476
477 template <class CGEN_CPU>
478 SI
479 sh_cpu<CGEN_CPU>::sh64_movua (PCADDR pc, SI rn)
480 {
481   // Move the data one byte at a time to avoid alignment problems.
482   // Be aware of endianness.
483   if (this->current_endianness() == endian_big)
484     {
485       big_int_4 v;
486       for (int i = 0; i < 4; ++i)
487         v.write_byte (i, GETMEMQI (pc, rn + i));
488       return v.integer_value ();
489     }
490
491   little_int_4 v;
492   for (int i = 0; i < 4; ++i)
493     v.write_byte (i, GETMEMQI (pc, rn + i));
494   return v.integer_value ();
495 }
496
497 // Explicit instantiations
498 template class sh_cpu<sh2_cpu_cgen>;
499 template class sh_cpu<sh2e_cpu_cgen>;
500 template class sh_cpu<sh2a_fpu_cpu_cgen>;
501 template class sh_cpu<sh2a_nofpu_cpu_cgen>;
502 template class sh_cpu<sh3_cpu_cgen>;
503 template class sh_cpu<sh3e_cpu_cgen>;
504 template class sh_cpu<sh4_nofpu_cpu_cgen>;
505 template class sh_cpu<sh4_cpu_cgen>;
506 template class sh_cpu<sh4a_nofpu_cpu_cgen>;
507 template class sh_cpu<sh4a_cpu_cgen>;
508 template class sh_cpu<sh4al_cpu_cgen>;
509 template class sh_cpu<sh5_cpu_cgen>;
510
511 template class sh_cpu_impl<sh2_cpu_cgen>;
512 template class sh_cpu_impl<sh2e_cpu_cgen>;
513 template class sh_cpu_impl<sh2a_fpu_cpu_cgen>;
514 template class sh_cpu_impl<sh2a_nofpu_cpu_cgen>;
515 template class sh_cpu_impl<sh3_cpu_cgen>;
516 template class sh_cpu_impl<sh3e_cpu_cgen>;
517 template class sh_cpu_impl<sh4_nofpu_cpu_cgen>;
518 template class sh_cpu_impl<sh4_cpu_cgen>;
519 template class sh_cpu_impl<sh4a_nofpu_cpu_cgen>;
520 template class sh_cpu_impl<sh4a_cpu_cgen>;
521 template class sh_cpu_impl<sh4al_cpu_cgen>;
522 template class sh_cpu_impl<sh5_cpu_cgen>;
523
524 // Used by the disassembler. The real definitions are in opcodes/sh-opc.h
525 // which we don't pull in here.
526 #define MASK(LO,HI)  (  LO < 1   ? ((1 << (HI + 1)) - 1) \
527                       : HI > 30  ? (-1 << LO) \
528                       : LO == HI ? (1 << LO) \
529                       :            (((1 << (HI + 1)) - 1) & (-1 << LO)))
530 #define arch_sh1_base       (1 << 0)
531 #define arch_sh2_base       (1 << 1)
532 #define arch_sh2a_sh3_base  (1 << 2)
533 #define arch_sh3_base       (1 << 3)
534 #define arch_sh2a_sh4_base  (1 << 4)
535 #define arch_sh4_base       (1 << 5)
536 #define arch_sh4a_base      (1 << 6)
537 #define arch_sh2a_base      (1 << 7)
538 #define arch_sh_base_mask   MASK (0, 7)
539
540 /* Bits 8 ... 24 are currently free.  */
541
542 /* This is an annotation on instruction types, but we
543    abuse the arch field in instructions to denote it.  */
544 #define arch_op32          (1 << 25)  /* This is a 32-bit opcode.  */
545 #define arch_opann_mask    MASK (25, 25)
546
547 #define arch_sh_no_mmu     (1 << 26)
548 #define arch_sh_has_mmu    (1 << 27)
549 #define arch_sh_mmu_mask   MASK (26, 27)
550
551 #define arch_sh_no_co      (1 << 28)  /* Neither FPU nor DSP co-processor.  */
552 #define arch_sh_sp_fpu     (1 << 29)  /* Single precision FPU.  */
553 #define arch_sh_dp_fpu     (1 << 30)  /* Double precision FPU.  */
554 #define arch_sh_has_dsp    (1 << 31)
555 #define arch_sh_co_mask    MASK (28, 31)
556
557
558 #define arch_sh1                           (arch_sh1_base     |arch_sh_no_mmu |arch_sh_no_co)
559 #define arch_sh2                           (arch_sh2_base     |arch_sh_no_mmu |arch_sh_no_co)
560 #define arch_sh2a                          (arch_sh2a_base    |arch_sh_no_mmu |arch_sh_dp_fpu)
561 #define arch_sh2a_nofpu                    (arch_sh2a_base    |arch_sh_no_mmu |arch_sh_no_co)
562 #define arch_sh2e                          (arch_sh2_base     |arch_sh_no_mmu |arch_sh_sp_fpu)
563 #define arch_sh_dsp                        (arch_sh2_base     |arch_sh_no_mmu |arch_sh_has_dsp)
564 #define arch_sh3_nommu                     (arch_sh3_base     |arch_sh_no_mmu |arch_sh_no_co)
565 #define arch_sh3                           (arch_sh3_base     |arch_sh_has_mmu|arch_sh_no_co)
566 #define arch_sh3e                          (arch_sh3_base     |arch_sh_has_mmu|arch_sh_sp_fpu)
567 #define arch_sh3_dsp                       (arch_sh3_base     |arch_sh_has_mmu|arch_sh_has_dsp)
568 #define arch_sh4                           (arch_sh4_base     |arch_sh_has_mmu|arch_sh_dp_fpu)
569 #define arch_sh4a                          (arch_sh4a_base    |arch_sh_has_mmu|arch_sh_dp_fpu)
570 #define arch_sh4al_dsp                     (arch_sh4a_base    |arch_sh_has_mmu|arch_sh_has_dsp)
571 #define arch_sh4_nofpu                     (arch_sh4_base     |arch_sh_has_mmu|arch_sh_no_co)
572 #define arch_sh4a_nofpu                    (arch_sh4a_base    |arch_sh_has_mmu|arch_sh_no_co)
573 #define arch_sh4_nommu_nofpu               (arch_sh4_base     |arch_sh_no_mmu |arch_sh_no_co)
574 #define arch_sh2a_nofpu_or_sh4_nommu_nofpu (arch_sh2a_sh4_base|arch_sh_no_mmu |arch_sh_no_co)
575 #define arch_sh2a_nofpu_or_sh3_nommu       (arch_sh2a_sh3_base|arch_sh_no_mmu |arch_sh_no_co)
576 #define arch_sh2a_or_sh3e                  (arch_sh2a_sh4_base|arch_sh_no_mmu |arch_sh_sp_fpu)
577 #define arch_sh2a_or_sh4                   (arch_sh2a_sh4_base|arch_sh_no_mmu |arch_sh_dp_fpu)
578
579 #define SH_ARCH_UNKNOWN_ARCH 0xffffffff
580
581 // Used by the disassembler. The real version is in bfd/cpu-sh.c
582 // which we don't pull in here.
583 static struct { unsigned long bfd_mach, arch; } bfd_to_arch_table[] =
584 {
585   { bfd_mach_sh,              arch_sh1 },
586   { bfd_mach_sh2,             arch_sh2 },
587   { bfd_mach_sh2e,            arch_sh2e },
588   { bfd_mach_sh_dsp,          arch_sh_dsp },
589   { bfd_mach_sh2a,            arch_sh2a },
590   { bfd_mach_sh2a_nofpu,      arch_sh2a_nofpu },
591
592   { bfd_mach_sh2a_nofpu_or_sh4_nommu_nofpu,         arch_sh2a_nofpu_or_sh4_nommu_nofpu },
593   { bfd_mach_sh2a_nofpu_or_sh3_nommu,               arch_sh2a_nofpu_or_sh3_nommu },
594   { bfd_mach_sh2a_or_sh4,     arch_sh2a_or_sh4 },
595   { bfd_mach_sh2a_or_sh3e,    arch_sh2a_or_sh3e },
596   
597   { bfd_mach_sh3,             arch_sh3 },
598   { bfd_mach_sh3_nommu,       arch_sh3_nommu },
599   { bfd_mach_sh3_dsp,         arch_sh3_dsp },
600   { bfd_mach_sh3e,            arch_sh3e },
601   { bfd_mach_sh4,             arch_sh4 },
602   { bfd_mach_sh4a,            arch_sh4a },
603   { bfd_mach_sh4al_dsp,       arch_sh4al_dsp },
604   { bfd_mach_sh4_nofpu,       arch_sh4_nofpu },
605   { bfd_mach_sh4_nommu_nofpu, arch_sh4_nommu_nofpu },
606   { bfd_mach_sh4a_nofpu,      arch_sh4a_nofpu },
607   { 0, 0 }   /* Terminator.  */
608 };
609
610 // Convert a BFD mach number into the right opcodes arch flags
611 // using the table above.
612 extern "C"
613 unsigned int
614 sh_get_arch_from_bfd_mach (unsigned long mach)
615 {
616   int i = 0;
617
618   while (bfd_to_arch_table[i].bfd_mach != 0)
619     {
620       if (bfd_to_arch_table[i].bfd_mach == mach)
621         return bfd_to_arch_table[i].arch;
622       i++;
623     }
624
625   return SH_ARCH_UNKNOWN_ARCH;
626 }