5d0daa9521ae5c2b1fe90d66fc622dda32780a44
[qemu] / target-alpha / op.c
1 /*
2  *  Alpha emulation cpu micro-operations for qemu.
3  *
4  *  Copyright (c) 2007 Jocelyn Mayer
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20
21 #define DEBUG_OP
22
23 #include "config.h"
24 #include "exec.h"
25 #include "host-utils.h"
26
27 #include "op_helper.h"
28
29 #define REG 0
30 #include "op_template.h"
31
32 #define REG 1
33 #include "op_template.h"
34
35 #define REG 2
36 #include "op_template.h"
37
38 #define REG 3
39 #include "op_template.h"
40
41 #define REG 4
42 #include "op_template.h"
43
44 #define REG 5
45 #include "op_template.h"
46
47 #define REG 6
48 #include "op_template.h"
49
50 #define REG 7
51 #include "op_template.h"
52
53 #define REG 8
54 #include "op_template.h"
55
56 #define REG 9
57 #include "op_template.h"
58
59 #define REG 10
60 #include "op_template.h"
61
62 #define REG 11
63 #include "op_template.h"
64
65 #define REG 12
66 #include "op_template.h"
67
68 #define REG 13
69 #include "op_template.h"
70
71 #define REG 14
72 #include "op_template.h"
73
74 #define REG 15
75 #include "op_template.h"
76
77 #define REG 16
78 #include "op_template.h"
79
80 #define REG 17
81 #include "op_template.h"
82
83 #define REG 18
84 #include "op_template.h"
85
86 #define REG 19
87 #include "op_template.h"
88
89 #define REG 20
90 #include "op_template.h"
91
92 #define REG 21
93 #include "op_template.h"
94
95 #define REG 22
96 #include "op_template.h"
97
98 #define REG 23
99 #include "op_template.h"
100
101 #define REG 24
102 #include "op_template.h"
103
104 #define REG 25
105 #include "op_template.h"
106
107 #define REG 26
108 #include "op_template.h"
109
110 #define REG 27
111 #include "op_template.h"
112
113 #define REG 28
114 #include "op_template.h"
115
116 #define REG 29
117 #include "op_template.h"
118
119 #define REG 30
120 #include "op_template.h"
121
122 #define REG 31
123 #include "op_template.h"
124
125 /* Debug stuff */
126 void OPPROTO op_no_op (void)
127 {
128 #if !defined (DEBUG_OP)
129     __asm__ __volatile__("nop" : : : "memory");
130 #endif
131     RETURN();
132 }
133
134 /* Load and stores */
135 #define MEMSUFFIX _raw
136 #include "op_mem.h"
137 #if !defined(CONFIG_USER_ONLY)
138 #define MEMSUFFIX _kernel
139 #include "op_mem.h"
140 #define MEMSUFFIX _executive
141 #include "op_mem.h"
142 #define MEMSUFFIX _supervisor
143 #include "op_mem.h"
144 #define MEMSUFFIX _user
145 #include "op_mem.h"
146 /* This is used for pal modes */
147 #define MEMSUFFIX _data
148 #include "op_mem.h"
149 #endif
150
151 /* Misc */
152 void OPPROTO op_excp (void)
153 {
154     helper_excp(PARAM(1), PARAM(2));
155     RETURN();
156 }
157
158 void OPPROTO op_load_pcc (void)
159 {
160     helper_load_pcc();
161     RETURN();
162 }
163
164 void OPPROTO op_load_implver (void)
165 {
166     helper_load_implver();
167     RETURN();
168 }
169
170 void OPPROTO op_load_fpcr (void)
171 {
172     helper_load_fpcr();
173     RETURN();
174 }
175
176 void OPPROTO op_store_fpcr (void)
177 {
178     helper_store_fpcr();
179     RETURN();
180 }
181
182 void OPPROTO op_load_irf (void)
183 {
184     helper_load_irf();
185     RETURN();
186 }
187
188 void OPPROTO op_set_irf (void)
189 {
190     helper_set_irf();
191     RETURN();
192 }
193
194 void OPPROTO op_clear_irf (void)
195 {
196     helper_clear_irf();
197     RETURN();
198 }
199
200 /* Arithmetic */
201 void OPPROTO op_addqv (void)
202 {
203     helper_addqv();
204     RETURN();
205 }
206
207 void OPPROTO op_addlv (void)
208 {
209     helper_addlv();
210     RETURN();
211 }
212
213 void OPPROTO op_subqv (void)
214 {
215     helper_subqv();
216     RETURN();
217 }
218
219 void OPPROTO op_sublv (void)
220 {
221     helper_sublv();
222     RETURN();
223 }
224
225 void OPPROTO op_mullv (void)
226 {
227     helper_mullv();
228     RETURN();
229 }
230
231 void OPPROTO op_mulqv (void)
232 {
233     helper_mulqv();
234     RETURN();
235 }
236
237 void OPPROTO op_umulh (void)
238 {
239     uint64_t tl, th;
240
241     mulu64(&tl, &th, T0, T1);
242     T0 = th;
243     RETURN();
244 }
245
246 /* Tests */
247 void OPPROTO op_cmpult (void)
248 {
249     if (T0 < T1)
250         T0 = 1;
251     else
252         T0 = 0;
253     RETURN();
254 }
255
256 void OPPROTO op_cmpule (void)
257 {
258     if (T0 <= T1)
259         T0 = 1;
260     else
261         T0 = 0;
262     RETURN();
263 }
264
265 void OPPROTO op_cmpeq (void)
266 {
267     if (T0 == T1)
268         T0 = 1;
269     else
270         T0 = 0;
271     RETURN();
272 }
273
274 void OPPROTO op_cmplt (void)
275 {
276     if ((int64_t)T0 < (int64_t)T1)
277         T0 = 1;
278     else
279         T0 = 0;
280     RETURN();
281 }
282
283 void OPPROTO op_cmple (void)
284 {
285     if ((int64_t)T0 <= (int64_t)T1)
286         T0 = 1;
287     else
288         T0 = 0;
289     RETURN();
290 }
291
292 void OPPROTO op_cmpbge (void)
293 {
294     helper_cmpbge();
295     RETURN();
296 }
297
298 #if 0 // Qemu does not know how to do this...
299 void OPPROTO op_bcond (void)
300 {
301     if (T0)
302         env->pc = T1 & ~3;
303     else
304         env->pc = PARAM(1);
305     RETURN();
306 }
307 #else
308 void OPPROTO op_bcond (void)
309 {
310     if (T0)
311         env->pc = T1 & ~3;
312     else
313         env->pc = ((uint64_t)PARAM(1) << 32) | (uint64_t)PARAM(2);
314     RETURN();
315 }
316 #endif
317
318 /* IEEE floating point arithmetic */
319 /* S floating (single) */
320 void OPPROTO op_adds (void)
321 {
322     FT0 = float32_add(FT0, FT1, &FP_STATUS);
323     RETURN();
324 }
325
326 void OPPROTO op_subs (void)
327 {
328     FT0 = float32_sub(FT0, FT1, &FP_STATUS);
329     RETURN();
330 }
331
332 void OPPROTO op_muls (void)
333 {
334     FT0 = float32_mul(FT0, FT1, &FP_STATUS);
335     RETURN();
336 }
337
338 void OPPROTO op_divs (void)
339 {
340     FT0 = float32_div(FT0, FT1, &FP_STATUS);
341     RETURN();
342 }
343
344 void OPPROTO op_sqrts (void)
345 {
346     helper_sqrts();
347     RETURN();
348 }
349
350 void OPPROTO op_cpys (void)
351 {
352     helper_cpys();
353     RETURN();
354 }
355
356 void OPPROTO op_cpysn (void)
357 {
358     helper_cpysn();
359     RETURN();
360 }
361
362 void OPPROTO op_cpyse (void)
363 {
364     helper_cpyse();
365     RETURN();
366 }
367
368 void OPPROTO op_itofs (void)
369 {
370     helper_itofs();
371     RETURN();
372 }
373
374 void OPPROTO op_ftois (void)
375 {
376     helper_ftois();
377     RETURN();
378 }
379
380 /* T floating (double) */
381 void OPPROTO op_addt (void)
382 {
383     FT0 = float64_add(FT0, FT1, &FP_STATUS);
384     RETURN();
385 }
386
387 void OPPROTO op_subt (void)
388 {
389     FT0 = float64_sub(FT0, FT1, &FP_STATUS);
390     RETURN();
391 }
392
393 void OPPROTO op_mult (void)
394 {
395     FT0 = float64_mul(FT0, FT1, &FP_STATUS);
396     RETURN();
397 }
398
399 void OPPROTO op_divt (void)
400 {
401     FT0 = float64_div(FT0, FT1, &FP_STATUS);
402     RETURN();
403 }
404
405 void OPPROTO op_sqrtt (void)
406 {
407     helper_sqrtt();
408     RETURN();
409 }
410
411 void OPPROTO op_cmptun (void)
412 {
413     helper_cmptun();
414     RETURN();
415 }
416
417 void OPPROTO op_cmpteq (void)
418 {
419     helper_cmpteq();
420     RETURN();
421 }
422
423 void OPPROTO op_cmptle (void)
424 {
425     helper_cmptle();
426     RETURN();
427 }
428
429 void OPPROTO op_cmptlt (void)
430 {
431     helper_cmptlt();
432     RETURN();
433 }
434
435 void OPPROTO op_itoft (void)
436 {
437     helper_itoft();
438     RETURN();
439 }
440
441 void OPPROTO op_ftoit (void)
442 {
443     helper_ftoit();
444     RETURN();
445 }
446
447 /* VAX floating point arithmetic */
448 /* F floating */
449 void OPPROTO op_addf (void)
450 {
451     helper_addf();
452     RETURN();
453 }
454
455 void OPPROTO op_subf (void)
456 {
457     helper_subf();
458     RETURN();
459 }
460
461 void OPPROTO op_mulf (void)
462 {
463     helper_mulf();
464     RETURN();
465 }
466
467 void OPPROTO op_divf (void)
468 {
469     helper_divf();
470     RETURN();
471 }
472
473 void OPPROTO op_sqrtf (void)
474 {
475     helper_sqrtf();
476     RETURN();
477 }
478
479 void OPPROTO op_cmpfeq (void)
480 {
481     helper_cmpfeq();
482     RETURN();
483 }
484
485 void OPPROTO op_cmpfne (void)
486 {
487     helper_cmpfne();
488     RETURN();
489 }
490
491 void OPPROTO op_cmpflt (void)
492 {
493     helper_cmpflt();
494     RETURN();
495 }
496
497 void OPPROTO op_cmpfle (void)
498 {
499     helper_cmpfle();
500     RETURN();
501 }
502
503 void OPPROTO op_cmpfgt (void)
504 {
505     helper_cmpfgt();
506     RETURN();
507 }
508
509 void OPPROTO op_cmpfge (void)
510 {
511     helper_cmpfge();
512     RETURN();
513 }
514
515 void OPPROTO op_itoff (void)
516 {
517     helper_itoff();
518     RETURN();
519 }
520
521 /* G floating */
522 void OPPROTO op_addg (void)
523 {
524     helper_addg();
525     RETURN();
526 }
527
528 void OPPROTO op_subg (void)
529 {
530     helper_subg();
531     RETURN();
532 }
533
534 void OPPROTO op_mulg (void)
535 {
536     helper_mulg();
537     RETURN();
538 }
539
540 void OPPROTO op_divg (void)
541 {
542     helper_divg();
543     RETURN();
544 }
545
546 void OPPROTO op_sqrtg (void)
547 {
548     helper_sqrtg();
549     RETURN();
550 }
551
552 void OPPROTO op_cmpgeq (void)
553 {
554     helper_cmpgeq();
555     RETURN();
556 }
557
558 void OPPROTO op_cmpglt (void)
559 {
560     helper_cmpglt();
561     RETURN();
562 }
563
564 void OPPROTO op_cmpgle (void)
565 {
566     helper_cmpgle();
567     RETURN();
568 }
569
570 /* Floating point format conversion */
571 void OPPROTO op_cvtst (void)
572 {
573     FT0 = (float)FT0;
574     RETURN();
575 }
576
577 void OPPROTO op_cvtqs (void)
578 {
579     helper_cvtqs();
580     RETURN();
581 }
582
583 void OPPROTO op_cvtts (void)
584 {
585     FT0 = (float)FT0;
586     RETURN();
587 }
588
589 void OPPROTO op_cvttq (void)
590 {
591     helper_cvttq();
592     RETURN();
593 }
594
595 void OPPROTO op_cvtqt (void)
596 {
597     helper_cvtqt();
598     RETURN();
599 }
600
601 void OPPROTO op_cvtqf (void)
602 {
603     helper_cvtqf();
604     RETURN();
605 }
606
607 void OPPROTO op_cvtgf (void)
608 {
609     helper_cvtgf();
610     RETURN();
611 }
612
613 void OPPROTO op_cvtgd (void)
614 {
615     helper_cvtgd();
616     RETURN();
617 }
618
619 void OPPROTO op_cvtgq (void)
620 {
621     helper_cvtgq();
622     RETURN();
623 }
624
625 void OPPROTO op_cvtqg (void)
626 {
627     helper_cvtqg();
628     RETURN();
629 }
630
631 void OPPROTO op_cvtdg (void)
632 {
633     helper_cvtdg();
634     RETURN();
635 }
636
637 void OPPROTO op_cvtlq (void)
638 {
639     helper_cvtlq();
640     RETURN();
641 }
642
643 void OPPROTO op_cvtql (void)
644 {
645     helper_cvtql();
646     RETURN();
647 }
648
649 void OPPROTO op_cvtqlv (void)
650 {
651     helper_cvtqlv();
652     RETURN();
653 }
654
655 void OPPROTO op_cvtqlsv (void)
656 {
657     helper_cvtqlsv();
658     RETURN();
659 }
660
661 /* PALcode support special instructions */
662 #if !defined (CONFIG_USER_ONLY)
663 void OPPROTO op_hw_rei (void)
664 {
665     env->pc = env->ipr[IPR_EXC_ADDR] & ~3;
666     env->ipr[IPR_EXC_ADDR] = env->ipr[IPR_EXC_ADDR] & 1;
667     /* XXX: re-enable interrupts and memory mapping */
668     RETURN();
669 }
670
671 void OPPROTO op_hw_ret (void)
672 {
673     env->pc = T0 & ~3;
674     env->ipr[IPR_EXC_ADDR] = T0 & 1;
675     /* XXX: re-enable interrupts and memory mapping */
676     RETURN();
677 }
678
679 void OPPROTO op_mfpr (void)
680 {
681     helper_mfpr(PARAM(1));
682     RETURN();
683 }
684
685 void OPPROTO op_mtpr (void)
686 {
687     helper_mtpr(PARAM(1));
688     RETURN();
689 }
690
691 void OPPROTO op_set_alt_mode (void)
692 {
693     env->saved_mode = env->ps & 0xC;
694     env->ps = (env->ps & ~0xC) | (env->ipr[IPR_ALT_MODE] & 0xC);
695     RETURN();
696 }
697
698 void OPPROTO op_restore_mode (void)
699 {
700     env->ps = (env->ps & ~0xC) | env->saved_mode;
701     RETURN();
702 }
703
704 void OPPROTO op_ld_phys_to_virt (void)
705 {
706     helper_ld_phys_to_virt();
707     RETURN();
708 }
709
710 void OPPROTO op_st_phys_to_virt (void)
711 {
712     helper_st_phys_to_virt();
713     RETURN();
714 }
715 #endif /* !defined (CONFIG_USER_ONLY) */