/[gxemul]/upstream/0.3.5/src/cpu_alpha_instr.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Contents of /upstream/0.3.5/src/cpu_alpha_instr.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 13 - (show annotations)
Mon Oct 8 16:18:43 2007 UTC (16 years, 8 months ago) by dpavlin
File MIME type: text/plain
File size: 29764 byte(s)
0.3.5
1 /*
2 * Copyright (C) 2005 Anders Gavare. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * 3. The name of the author may not be used to endorse or promote products
13 * derived from this software without specific prior written permission.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 *
27 *
28 * $Id: cpu_alpha_instr.c,v 1.41 2005/08/16 05:37:09 debug Exp $
29 *
30 * Alpha instructions.
31 *
32 * Individual functions should keep track of cpu->n_translated_instrs.
33 * (If no instruction was executed, then it should be decreased. If, say, 4
34 * instructions were combined into one function and executed, then it should
35 * be increased by 3.)
36 */
37
38
39 /*
40 * nop: Do nothing.
41 */
42 X(nop)
43 {
44 }
45
46
47 /*
48 * call_pal: PALcode call
49 *
50 * arg[0] = pal nr
51 */
52 X(call_pal)
53 {
54 uint64_t low_pc;
55
56 /* Synchronize PC first: */
57 low_pc = ((size_t)ic - (size_t)
58 cpu->cd.alpha.cur_ic_page) / sizeof(struct alpha_instr_call);
59 cpu->pc &= ~((ALPHA_IC_ENTRIES_PER_PAGE-1) << 2);
60 cpu->pc += (low_pc << 2) + 4;
61
62 alpha_palcode(cpu, ic->arg[0]);
63
64 if (!cpu->running) {
65 cpu->running_translated = 0;
66 cpu->n_translated_instrs --;
67 cpu->cd.alpha.next_ic = &nothing_call;
68 } else {
69 /* PC might have been changed by the palcode call. */
70 /* Find the new physical page and update the translation
71 pointers: */
72 alpha_pc_to_pointers(cpu);
73 }
74 }
75
76
77 /*
78 * jsr: Jump to SubRoutine
79 *
80 * arg[0] = ptr to uint64_t where to store return PC
81 * arg[1] = ptr to uint64_t of new PC
82 */
83 X(jsr)
84 {
85 uint64_t old_pc = cpu->pc, low_pc;
86 uint64_t mask_within_page = ((ALPHA_IC_ENTRIES_PER_PAGE-1) << 2) | 3;
87
88 low_pc = ((size_t)ic - (size_t)
89 cpu->cd.alpha.cur_ic_page) / sizeof(struct alpha_instr_call);
90 cpu->pc &= ~((ALPHA_IC_ENTRIES_PER_PAGE-1) << 2);
91 cpu->pc += (low_pc << 2) + 4;
92
93 *((int64_t *)ic->arg[0]) = cpu->pc;
94 cpu->pc = *((int64_t *)ic->arg[1]);
95
96 /*
97 * If this is a jump/return into the same code page as we were
98 * already in, then just set cpu->cd.alpha.next_ic.
99 */
100 if ((old_pc & ~mask_within_page) == (cpu->pc & ~mask_within_page)) {
101 cpu->cd.alpha.next_ic = cpu->cd.alpha.cur_ic_page +
102 ((cpu->pc & mask_within_page) >> 2);
103 } else {
104 /* Find the new physical page and update pointers: */
105 alpha_pc_to_pointers(cpu);
106 }
107 }
108
109
110 /*
111 * jsr_trace: Jump to SubRoutine (with function call trace enabled)
112 *
113 * Arguments same as for jsr.
114 */
115 X(jsr_trace)
116 {
117 cpu_functioncall_trace(cpu, *((int64_t *)ic->arg[1]));
118 instr(jsr)(cpu, ic);
119 }
120
121
122 /*
123 * jsr_0: JSR/RET, don't store return PC.
124 *
125 * arg[0] = ignored
126 * arg[1] = ptr to uint64_t of new PC
127 */
128 X(jsr_0)
129 {
130 uint64_t old_pc = cpu->pc;
131 uint64_t mask_within_page = ((ALPHA_IC_ENTRIES_PER_PAGE-1) << 2) | 3;
132
133 cpu->pc = *((int64_t *)ic->arg[1]);
134
135 /*
136 * If this is a jump/return into the same code page as we were
137 * already in, then just set cpu->cd.alpha.next_ic.
138 */
139 if ((old_pc & ~mask_within_page) == (cpu->pc & ~mask_within_page)) {
140 cpu->cd.alpha.next_ic = cpu->cd.alpha.cur_ic_page +
141 ((cpu->pc & mask_within_page) >> 2);
142 } else {
143 /* Find the new physical page and update pointers: */
144 alpha_pc_to_pointers(cpu);
145 }
146 }
147
148
149 /*
150 * jsr_0_trace: JSR/RET (with function call trace enabled)
151 *
152 * Arguments same as for jsr_0.
153 */
154 X(jsr_0_trace)
155 {
156 cpu_functioncall_trace_return(cpu);
157 instr(jsr_0)(cpu, ic);
158 }
159
160
161 /*
162 * br: Branch (to a different translated page)
163 *
164 * arg[0] = relative offset (as an int32_t)
165 */
166 X(br)
167 {
168 uint64_t low_pc;
169
170 /* Calculate new PC from this instruction + arg[0] */
171 low_pc = ((size_t)ic - (size_t)
172 cpu->cd.alpha.cur_ic_page) / sizeof(struct alpha_instr_call);
173 cpu->pc &= ~((ALPHA_IC_ENTRIES_PER_PAGE-1) << 2);
174 cpu->pc += (low_pc << 2);
175 cpu->pc += (int32_t)ic->arg[0];
176
177 /* Find the new physical page and update the translation pointers: */
178 alpha_pc_to_pointers(cpu);
179 }
180
181
182 /*
183 * br: Branch (to a different translated page), write return address
184 *
185 * arg[0] = relative offset (as an int32_t)
186 * arg[1] = pointer to uint64_t where to write return address
187 */
188 X(br_return)
189 {
190 uint64_t low_pc;
191
192 /* Calculate new PC from this instruction + arg[0] */
193 low_pc = ((size_t)ic - (size_t)
194 cpu->cd.alpha.cur_ic_page) / sizeof(struct alpha_instr_call);
195 cpu->pc &= ~((ALPHA_IC_ENTRIES_PER_PAGE-1) << 2);
196 cpu->pc += (low_pc << 2);
197
198 /* ... but first, save away the return address: */
199 *((int64_t *)ic->arg[1]) = cpu->pc + 4;
200
201 cpu->pc += (int32_t)ic->arg[0];
202
203 /* Find the new physical page and update the translation pointers: */
204 alpha_pc_to_pointers(cpu);
205 }
206
207
208 /*
209 * beq: Branch (to a different translated page) if Equal
210 *
211 * arg[0] = relative offset (as an int32_t)
212 * arg[1] = pointer to int64_t register
213 */
214 X(beq)
215 {
216 if (*((int64_t *)ic->arg[1]) == 0)
217 instr(br)(cpu, ic);
218 }
219
220
221 /*
222 * blbs: Branch (to a different translated page) if Low Bit Set
223 *
224 * arg[0] = relative offset (as an int32_t)
225 * arg[1] = pointer to int64_t register
226 */
227 X(blbs)
228 {
229 if (*((int64_t *)ic->arg[1]) & 1)
230 instr(br)(cpu, ic);
231 }
232
233
234 /*
235 * blbc: Branch (to a different translated page) if Low Bit Clear
236 *
237 * arg[0] = relative offset (as an int32_t)
238 * arg[1] = pointer to int64_t register
239 */
240 X(blbc)
241 {
242 if (!(*((int64_t *)ic->arg[1]) & 1))
243 instr(br)(cpu, ic);
244 }
245
246
247 /*
248 * bne: Branch (to a different translated page) if Not Equal
249 *
250 * arg[0] = relative offset (as an int32_t)
251 * arg[1] = pointer to int64_t register
252 */
253 X(bne)
254 {
255 if (*((int64_t *)ic->arg[1]) != 0)
256 instr(br)(cpu, ic);
257 }
258
259
260 /*
261 * ble: Branch (to a different translated page) if Less or Equal
262 *
263 * arg[0] = relative offset (as an int32_t)
264 * arg[1] = pointer to int64_t register
265 */
266 X(ble)
267 {
268 if (*((int64_t *)ic->arg[1]) <= 0)
269 instr(br)(cpu, ic);
270 }
271
272
273 /*
274 * blt: Branch (to a different translated page) if Less Than
275 *
276 * arg[0] = relative offset (as an int32_t)
277 * arg[1] = pointer to int64_t register
278 */
279 X(blt)
280 {
281 if (*((int64_t *)ic->arg[1]) < 0)
282 instr(br)(cpu, ic);
283 }
284
285
286 /*
287 * bge: Branch (to a different translated page) if Greater or Equal
288 *
289 * arg[0] = relative offset (as an int32_t)
290 * arg[1] = pointer to int64_t register
291 */
292 X(bge)
293 {
294 if (*((int64_t *)ic->arg[1]) >= 0)
295 instr(br)(cpu, ic);
296 }
297
298
299 /*
300 * bgt: Branch (to a different translated page) if Greater Than
301 *
302 * arg[0] = relative offset (as an int32_t)
303 * arg[1] = pointer to int64_t register
304 */
305 X(bgt)
306 {
307 if (*((int64_t *)ic->arg[1]) > 0)
308 instr(br)(cpu, ic);
309 }
310
311
312 /*
313 * br_samepage: Branch (to within the same translated page)
314 *
315 * arg[0] = pointer to new alpha_instr_call
316 */
317 X(br_samepage)
318 {
319 cpu->cd.alpha.next_ic = (struct alpha_instr_call *) ic->arg[0];
320 }
321
322
323 /*
324 * br_return_samepage: Branch (to within the same translated page),
325 * and save return address
326 *
327 * arg[0] = pointer to new alpha_instr_call
328 * arg[1] = pointer to uint64_t where to store return address
329 */
330 X(br_return_samepage)
331 {
332 uint64_t low_pc;
333
334 low_pc = ((size_t)ic - (size_t)
335 cpu->cd.alpha.cur_ic_page) / sizeof(struct alpha_instr_call);
336 cpu->pc &= ~((ALPHA_IC_ENTRIES_PER_PAGE-1) << 2);
337 cpu->pc += (low_pc << 2);
338 *((int64_t *)ic->arg[1]) = cpu->pc + 4;
339
340 cpu->cd.alpha.next_ic = (struct alpha_instr_call *) ic->arg[0];
341 }
342
343
344 /*
345 * beq_samepage: Branch (to within the same translated page) if Equal
346 *
347 * arg[0] = pointer to new alpha_instr_call
348 * arg[1] = pointer to int64_t register
349 */
350 X(beq_samepage)
351 {
352 if (*((int64_t *)ic->arg[1]) == 0)
353 instr(br_samepage)(cpu, ic);
354 }
355
356
357 /*
358 * blbs_samepage: Branch (to within the same translated page) if Low Bit Set
359 *
360 * arg[0] = pointer to new alpha_instr_call
361 * arg[1] = pointer to int64_t register
362 */
363 X(blbs_samepage)
364 {
365 if (*((int64_t *)ic->arg[1]) & 1)
366 instr(br_samepage)(cpu, ic);
367 }
368
369
370 /*
371 * blbc_samepage: Branch (to within the same translated page) if Low Bit Clear
372 *
373 * arg[0] = pointer to new alpha_instr_call
374 * arg[1] = pointer to int64_t register
375 */
376 X(blbc_samepage)
377 {
378 if (!(*((int64_t *)ic->arg[1]) & 1))
379 instr(br_samepage)(cpu, ic);
380 }
381
382
383 /*
384 * bne_samepage: Branch (to within the same translated page) if Not Equal
385 *
386 * arg[0] = pointer to new alpha_instr_call
387 * arg[1] = pointer to int64_t register
388 */
389 X(bne_samepage)
390 {
391 if (*((int64_t *)ic->arg[1]) != 0)
392 instr(br_samepage)(cpu, ic);
393 }
394
395
396 /*
397 * ble_samepage: Branch (to within the same translated page) if Less or Equal
398 *
399 * arg[0] = pointer to new alpha_instr_call
400 * arg[1] = pointer to int64_t register
401 */
402 X(ble_samepage)
403 {
404 if (*((int64_t *)ic->arg[1]) <= 0)
405 instr(br_samepage)(cpu, ic);
406 }
407
408
409 /*
410 * blt_samepage: Branch (to within the same translated page) if Less Than
411 *
412 * arg[0] = pointer to new alpha_instr_call
413 * arg[1] = pointer to int64_t register
414 */
415 X(blt_samepage)
416 {
417 if (*((int64_t *)ic->arg[1]) < 0)
418 instr(br_samepage)(cpu, ic);
419 }
420
421
422 /*
423 * bge_samepage: Branch (to within the same translated page)
424 * if Greater or Equal
425 *
426 * arg[0] = pointer to new alpha_instr_call
427 * arg[1] = pointer to int64_t register
428 */
429 X(bge_samepage)
430 {
431 if (*((int64_t *)ic->arg[1]) >= 0)
432 instr(br_samepage)(cpu, ic);
433 }
434
435
436 /*
437 * bgt_samepage: Branch (to within the same translated page) if Greater Than
438 *
439 * arg[0] = pointer to new alpha_instr_call
440 * arg[1] = pointer to int64_t register
441 */
442 X(bgt_samepage)
443 {
444 if (*((int64_t *)ic->arg[1]) > 0)
445 instr(br_samepage)(cpu, ic);
446 }
447
448
449 /*
450 * mull: Signed Multiply 32x32 => 32.
451 *
452 * arg[0] = pointer to destination uint64_t
453 * arg[1] = pointer to source uint64_t
454 * arg[2] = pointer to source uint64_t
455 */
456 X(mull)
457 {
458 int32_t a = reg(ic->arg[1]);
459 int32_t b = reg(ic->arg[2]);
460 reg(ic->arg[0]) = (int64_t)(int32_t)(a * b);
461 }
462
463
464 /*
465 * mulq: Unsigned Multiply 64x64 => 64.
466 *
467 * arg[0] = pointer to destination uint64_t
468 * arg[1] = pointer to source uint64_t
469 * arg[2] = pointer to source uint64_t
470 */
471 X(mulq)
472 {
473 reg(ic->arg[0]) = reg(ic->arg[1]) * reg(ic->arg[2]);
474 }
475
476
477 /*
478 * umulh: Unsigned Multiply 64x64 => 128. Store high part in dest reg.
479 *
480 * arg[0] = pointer to destination uint64_t
481 * arg[1] = pointer to source uint64_t
482 * arg[2] = pointer to source uint64_t
483 */
484 X(umulh)
485 {
486 uint64_t reshi = 0, reslo = 0;
487 uint64_t s1 = reg(ic->arg[1]), s2 = reg(ic->arg[2]);
488 int i, bit;
489
490 for (i=0; i<64; i++) {
491 bit = (s1 & 0x8000000000000000ULL)? 1 : 0;
492 s1 <<= 1;
493
494 /* If bit in s1 set, then add s2 to reshi/lo: */
495 if (bit) {
496 uint64_t old_reslo = reslo;
497 reslo += s2;
498 if (reslo < old_reslo)
499 reshi ++;
500 }
501
502 if (i != 63) {
503 reshi <<= 1;
504 reshi += (reslo & 0x8000000000000000ULL? 1 : 0);
505 reslo <<= 1;
506 }
507 }
508
509 reg(ic->arg[0]) = reshi;
510 }
511
512
513 /*
514 * lda: Load address.
515 *
516 * arg[0] = pointer to destination uint64_t
517 * arg[1] = pointer to source uint64_t
518 * arg[2] = offset (possibly as an int32_t)
519 */
520 X(lda)
521 {
522 reg(ic->arg[0]) = reg(ic->arg[1]) + (int64_t)(int32_t)ic->arg[2];
523 }
524
525
526 /*
527 * lda_0: Load address compared to the zero register.
528 *
529 * arg[0] = pointer to destination uint64_t
530 * arg[1] = ignored
531 * arg[2] = offset (possibly as an int32_t)
532 */
533 X(lda_0)
534 {
535 reg(ic->arg[0]) = (int64_t)(int32_t)ic->arg[2];
536 }
537
538
539 /*
540 * clear: Clear a 64-bit register.
541 *
542 * arg[0] = pointer to destination uint64_t
543 */
544 X(clear)
545 {
546 reg(ic->arg[0]) = 0;
547 }
548
549
550 /*
551 * rdcc: Read the Cycle Counter into a 64-bit register.
552 *
553 * arg[0] = pointer to destination uint64_t
554 */
555 X(rdcc)
556 {
557 reg(ic->arg[0]) = cpu->cd.alpha.pcc;
558
559 /* TODO: actually keep the pcc updated! */
560 cpu->cd.alpha.pcc += 20;
561 }
562
563
564 #include "tmp_alpha_misc.c"
565
566
567 /*****************************************************************************/
568
569
570 X(end_of_page)
571 {
572 /* Update the PC: (offset 0, but on the next page) */
573 cpu->pc &= ~((ALPHA_IC_ENTRIES_PER_PAGE-1) << 2);
574 cpu->pc += (ALPHA_IC_ENTRIES_PER_PAGE << 2);
575
576 /* Find the new physical page and update the translation pointers: */
577 alpha_pc_to_pointers(cpu);
578
579 /* end_of_page doesn't count as an executed instruction: */
580 cpu->n_translated_instrs --;
581 }
582
583
584 /*****************************************************************************/
585
586
587 /*
588 * alpha_combine_instructions():
589 *
590 * Combine two or more instructions, if possible, into a single function call.
591 */
592 void alpha_combine_instructions(struct cpu *cpu, struct alpha_instr_call *ic,
593 uint64_t addr)
594 {
595 int n_back;
596 n_back = (addr >> 2) & (ALPHA_IC_ENTRIES_PER_PAGE-1);
597
598 if (n_back >= 1) {
599 }
600
601 /* TODO: Combine forward as well */
602 }
603
604
605 /*****************************************************************************/
606
607
608 /*
609 * alpha_instr_to_be_translated():
610 *
611 * Translate an instruction word into an alpha_instr_call. ic is filled in with
612 * valid data for the translated instruction, or a "nothing" instruction if
613 * there was a translation failure. The newly translated instruction is then
614 * executed.
615 */
616 X(to_be_translated)
617 {
618 uint64_t addr, low_pc;
619 uint32_t iword;
620 struct alpha_vph_page *vph_p;
621 unsigned char *page;
622 unsigned char ib[4];
623 void (*samepage_function)(struct cpu *, struct alpha_instr_call *);
624 int opcode, ra, rb, func, rc, imm, load, loadstore_type, fp, llsc;
625
626 /* Figure out the (virtual) address of the instruction: */
627 low_pc = ((size_t)ic - (size_t)cpu->cd.alpha.cur_ic_page)
628 / sizeof(struct alpha_instr_call);
629 addr = cpu->pc & ~((ALPHA_IC_ENTRIES_PER_PAGE-1) <<
630 ALPHA_INSTR_ALIGNMENT_SHIFT);
631 addr += (low_pc << ALPHA_INSTR_ALIGNMENT_SHIFT);
632 addr &= ~0x3;
633 cpu->pc = addr;
634
635 /* Read the instruction word from memory: */
636 if ((addr >> ALPHA_TOPSHIFT) == 0) {
637 vph_p = cpu->cd.alpha.vph_table0[(addr >>
638 ALPHA_LEVEL0_SHIFT) & 8191];
639 page = vph_p->host_load[(addr >> ALPHA_LEVEL1_SHIFT) & 8191];
640 } else if ((addr >> ALPHA_TOPSHIFT) == ALPHA_TOP_KERNEL) {
641 vph_p = cpu->cd.alpha.vph_table0_kernel[(addr >>
642 ALPHA_LEVEL0_SHIFT) & 8191];
643 page = vph_p->host_load[(addr >> ALPHA_LEVEL1_SHIFT) & 8191];
644 } else
645 page = NULL;
646
647 if (page != NULL) {
648 /* fatal("TRANSLATION HIT!\n"); */
649 memcpy(ib, page + (addr & 8191), sizeof(ib));
650 } else {
651 /* fatal("TRANSLATION MISS!\n"); */
652 if (!cpu->memory_rw(cpu, cpu->mem, addr, &ib[0],
653 sizeof(ib), MEM_READ, CACHE_INSTRUCTION)) {
654 fatal("to_be_translated(): read failed: TODO\n");
655 goto bad;
656 }
657 }
658
659 #ifdef HOST_LITTLE_ENDIAN
660 iword = *((uint32_t *)&ib[0]);
661 #else
662 iword = ib[0] + (ib[1]<<8) + (ib[2]<<16) + (ib[3]<<24);
663 #endif
664
665 /* fatal("{ Alpha: translating pc=0x%016llx iword=0x%08x }\n",
666 (long long)addr, (int)iword); */
667
668
669 #define DYNTRANS_TO_BE_TRANSLATED_HEAD
670 #include "cpu_dyntrans.c"
671 #undef DYNTRANS_TO_BE_TRANSLATED_HEAD
672
673
674 opcode = (iword >> 26) & 63;
675 ra = (iword >> 21) & 31;
676 rb = (iword >> 16) & 31;
677 func = (iword >> 5) & 0x7ff;
678 rc = iword & 31;
679 imm = iword & 0xffff;
680
681 switch (opcode) {
682 case 0x00: /* CALL_PAL */
683 ic->f = instr(call_pal);
684 ic->arg[0] = (size_t) (iword & 0x3ffffff);
685 break;
686 case 0x08: /* LDA */
687 case 0x09: /* LDAH */
688 if (ra == ALPHA_ZERO) {
689 ic->f = instr(nop);
690 break;
691 }
692 /* TODO: A special case which is common is to add or subtract
693 a small offset from sp. */
694 ic->f = instr(lda);
695 ic->arg[0] = (size_t) &cpu->cd.alpha.r[ra];
696 ic->arg[1] = (size_t) &cpu->cd.alpha.r[rb];
697 if (rb == ALPHA_ZERO)
698 ic->f = instr(lda_0);
699 ic->arg[2] = (ssize_t)(int16_t)imm;
700 if (opcode == 0x09)
701 ic->arg[2] <<= 16;
702 break;
703 case 0x0b: /* LDQ_U */
704 case 0x0f: /* STQ_U */
705 if (ra == ALPHA_ZERO && opcode == 0x0b) {
706 ic->f = instr(nop);
707 break;
708 }
709 if (opcode == 0x0b)
710 ic->f = instr(ldq_u);
711 else
712 ic->f = instr(stq_u);
713 ic->arg[0] = (size_t) &cpu->cd.alpha.r[ra];
714 ic->arg[1] = (size_t) &cpu->cd.alpha.r[rb];
715 ic->arg[2] = (ssize_t)(int16_t)imm;
716 break;
717 case 0x0a:
718 case 0x0c:
719 case 0x0d:
720 case 0x0e:
721 case 0x22:
722 case 0x23:
723 case 0x26:
724 case 0x27:
725 case 0x28:
726 case 0x29:
727 case 0x2a:
728 case 0x2b:
729 case 0x2c:
730 case 0x2d:
731 case 0x2e:
732 case 0x2f:
733 loadstore_type = 0; fp = 0; load = 0; llsc = 0;
734 switch (opcode) {
735 case 0x0a: loadstore_type = 0; load = 1; break; /* ldbu */
736 case 0x0c: loadstore_type = 1; load = 1; break; /* ldwu */
737 case 0x0d: loadstore_type = 1; break; /* stw */
738 case 0x0e: loadstore_type = 0; break; /* stb */
739 case 0x22: loadstore_type = 2; load = 1; fp = 1; break; /*lds*/
740 case 0x23: loadstore_type = 3; load = 1; fp = 1; break; /*ldt*/
741 case 0x26: loadstore_type = 2; fp = 1; break; /* sts */
742 case 0x27: loadstore_type = 3; fp = 1; break; /* stt */
743 case 0x28: loadstore_type = 2; load = 1; break; /* ldl */
744 case 0x29: loadstore_type = 3; load = 1; break; /* ldq */
745 case 0x2a: loadstore_type = 2; load = llsc = 1; break;/* ldl_l*/
746 case 0x2b: loadstore_type = 3; load = llsc = 1; break;/* ldq_l*/
747 case 0x2c: loadstore_type = 2; break; /* stl */
748 case 0x2d: loadstore_type = 3; break; /* stq */
749 case 0x2e: loadstore_type = 2; llsc = 1; break; /* stl_c */
750 case 0x2f: loadstore_type = 3; llsc = 1; break; /* stq_c */
751 }
752 ic->f = alpha_loadstore[
753 loadstore_type + (imm==0? 4 : 0) + 8 * load
754 + (cpu->machine->dyntrans_alignment_check? 16:0)
755 + 32 * llsc];
756 /* Load to the zero register is treated as a prefetch
757 hint. It is ignored here. */
758 if (load && ra == ALPHA_ZERO) {
759 ic->f = instr(nop);
760 break;
761 }
762 if (fp)
763 ic->arg[0] = (size_t) &cpu->cd.alpha.f[ra];
764 else
765 ic->arg[0] = (size_t) &cpu->cd.alpha.r[ra];
766 ic->arg[1] = (size_t) &cpu->cd.alpha.r[rb];
767 ic->arg[2] = (ssize_t)(int16_t)imm;
768 break;
769 case 0x10:
770 if (rc == ALPHA_ZERO) {
771 ic->f = instr(nop);
772 break;
773 }
774 ic->arg[0] = (size_t) &cpu->cd.alpha.r[rc];
775 ic->arg[1] = (size_t) &cpu->cd.alpha.r[ra];
776 if (func & 0x80)
777 ic->arg[2] = (size_t)((rb << 3) + (func >> 8));
778 else
779 ic->arg[2] = (size_t) &cpu->cd.alpha.r[rb];
780 switch (func & 0xff) {
781 case 0x00: ic->f = instr(addl); break;
782 case 0x02: ic->f = instr(s4addl); break;
783 case 0x09: ic->f = instr(subl); break;
784 case 0x0b: ic->f = instr(s4subl); break;
785 case 0x12: ic->f = instr(s8addl); break;
786 case 0x1b: ic->f = instr(s8subl); break;
787 case 0x1d: ic->f = instr(cmpult); break;
788 case 0x20: ic->f = instr(addq); break;
789 case 0x22: ic->f = instr(s4addq); break;
790 case 0x29: ic->f = instr(subq); break;
791 case 0x2b: ic->f = instr(s4subq); break;
792 case 0x2d: ic->f = instr(cmpeq); break;
793 case 0x32: ic->f = instr(s8addq); break;
794 case 0x3b: ic->f = instr(s8subq); break;
795 case 0x3d: ic->f = instr(cmpule); break;
796 case 0x4d: ic->f = instr(cmplt); break;
797 case 0x6d: ic->f = instr(cmple); break;
798
799 case 0x80: ic->f = instr(addl_imm); break;
800 case 0x82: ic->f = instr(s4addl_imm); break;
801 case 0x89: ic->f = instr(subl_imm); break;
802 case 0x8b: ic->f = instr(s4subl_imm); break;
803 case 0x92: ic->f = instr(s8addl_imm); break;
804 case 0x9b: ic->f = instr(s8subl_imm); break;
805 case 0x9d: ic->f = instr(cmpult_imm); break;
806 case 0xa0: ic->f = instr(addq_imm); break;
807 case 0xa2: ic->f = instr(s4addq_imm); break;
808 case 0xa9: ic->f = instr(subq_imm); break;
809 case 0xab: ic->f = instr(s4subq_imm); break;
810 case 0xad: ic->f = instr(cmpeq_imm); break;
811 case 0xb2: ic->f = instr(s8addq_imm); break;
812 case 0xbb: ic->f = instr(s8subq_imm); break;
813 case 0xbd: ic->f = instr(cmpule_imm); break;
814 case 0xcd: ic->f = instr(cmplt_imm); break;
815 case 0xed: ic->f = instr(cmple_imm); break;
816
817 default:fatal("[ Alpha: unimplemented function 0x%03x for"
818 " opcode 0x%02x ]\n", func, opcode);
819 goto bad;
820 }
821 break;
822 case 0x11:
823 if (rc == ALPHA_ZERO) {
824 ic->f = instr(nop);
825 break;
826 }
827 ic->arg[0] = (size_t) &cpu->cd.alpha.r[rc];
828 ic->arg[1] = (size_t) &cpu->cd.alpha.r[ra];
829 if (func & 0x80)
830 ic->arg[2] = (size_t)((rb << 3) + (func >> 8));
831 else
832 ic->arg[2] = (size_t) &cpu->cd.alpha.r[rb];
833 switch (func & 0xff) {
834 case 0x00: ic->f = instr(and); break;
835 case 0x08: ic->f = instr(andnot); break;
836 case 0x14: ic->f = instr(cmovlbs); break;
837 case 0x16: ic->f = instr(cmovlbc); break;
838 case 0x20: ic->f = instr(or);
839 if (ra == ALPHA_ZERO || rb == ALPHA_ZERO) {
840 if (ra == ALPHA_ZERO)
841 ra = rb;
842 ic->f = alpha_mov_r_r[ra + rc*32];
843 }
844 break;
845 case 0x24: ic->f = instr(cmoveq); break;
846 case 0x26: ic->f = instr(cmovne); break;
847 case 0x28: ic->f = instr(ornot); break;
848 case 0x40: ic->f = instr(xor); break;
849 case 0x44: ic->f = instr(cmovlt); break;
850 case 0x46: ic->f = instr(cmovge); break;
851 case 0x48: ic->f = instr(xornot); break;
852 case 0x64: ic->f = instr(cmovle); break;
853 case 0x66: ic->f = instr(cmovgt); break;
854 case 0x80: ic->f = instr(and_imm); break;
855 case 0x88: ic->f = instr(andnot_imm); break;
856 case 0x94: ic->f = instr(cmovlbs_imm); break;
857 case 0x96: ic->f = instr(cmovlbc_imm); break;
858 case 0xa0: ic->f = instr(or_imm); break;
859 case 0xa4: ic->f = instr(cmoveq_imm); break;
860 case 0xa6: ic->f = instr(cmovne_imm); break;
861 case 0xa8: ic->f = instr(ornot_imm); break;
862 case 0xc0: ic->f = instr(xor_imm); break;
863 case 0xc4: ic->f = instr(cmovlt_imm); break;
864 case 0xc6: ic->f = instr(cmovge_imm); break;
865 case 0xc8: ic->f = instr(xornot_imm); break;
866 case 0xe4: ic->f = instr(cmovle_imm); break;
867 case 0xe6: ic->f = instr(cmovgt_imm); break;
868 default:fatal("[ Alpha: unimplemented function 0x%03x for"
869 " opcode 0x%02x ]\n", func, opcode);
870 goto bad;
871 }
872 break;
873 case 0x12:
874 if (rc == ALPHA_ZERO) {
875 ic->f = instr(nop);
876 break;
877 }
878 ic->arg[0] = (size_t) &cpu->cd.alpha.r[rc];
879 ic->arg[1] = (size_t) &cpu->cd.alpha.r[ra];
880 if (func & 0x80)
881 ic->arg[2] = (size_t)((rb << 3) + (func >> 8));
882 else
883 ic->arg[2] = (size_t) &cpu->cd.alpha.r[rb];
884 switch (func & 0xff) {
885 case 0x02: ic->f = instr(mskbl); break;
886 case 0x06: ic->f = instr(extbl); break;
887 case 0x0b: ic->f = instr(insbl); break;
888 case 0x12: ic->f = instr(mskwl); break;
889 case 0x16: ic->f = instr(extwl); break;
890 case 0x1b: ic->f = instr(inswl); break;
891 case 0x22: ic->f = instr(mskll); break;
892 case 0x26: ic->f = instr(extll); break;
893 case 0x2b: ic->f = instr(insll); break;
894 case 0x30: ic->f = instr(zap); break;
895 case 0x31: ic->f = instr(zapnot); break;
896 case 0x32: ic->f = instr(mskql); break;
897 case 0x34: ic->f = instr(srl); break;
898 case 0x36: ic->f = instr(extql); break;
899 case 0x39: ic->f = instr(sll); break;
900 case 0x3b: ic->f = instr(insql); break;
901 case 0x3c: ic->f = instr(sra); break;
902 case 0x52: ic->f = instr(mskwh); break;
903 case 0x57: ic->f = instr(inswh); break;
904 case 0x5a: ic->f = instr(extwh); break;
905 case 0x62: ic->f = instr(msklh); break;
906 case 0x67: ic->f = instr(inslh); break;
907 case 0x6a: ic->f = instr(extlh); break;
908 case 0x72: ic->f = instr(mskqh); break;
909 case 0x77: ic->f = instr(insqh); break;
910 case 0x7a: ic->f = instr(extqh); break;
911 case 0x82: ic->f = instr(mskbl_imm); break;
912 case 0x86: ic->f = instr(extbl_imm); break;
913 case 0x8b: ic->f = instr(insbl_imm); break;
914 case 0x92: ic->f = instr(mskwl_imm); break;
915 case 0x96: ic->f = instr(extwl_imm); break;
916 case 0x9b: ic->f = instr(inswl_imm); break;
917 case 0xa2: ic->f = instr(mskll_imm); break;
918 case 0xa6: ic->f = instr(extll_imm); break;
919 case 0xab: ic->f = instr(insll_imm); break;
920 case 0xb0: ic->f = instr(zap_imm); break;
921 case 0xb1: ic->f = instr(zapnot_imm); break;
922 case 0xb2: ic->f = instr(mskql_imm); break;
923 case 0xb4: ic->f = instr(srl_imm); break;
924 case 0xb6: ic->f = instr(extql_imm); break;
925 case 0xb9: ic->f = instr(sll_imm); break;
926 case 0xbb: ic->f = instr(insql_imm); break;
927 case 0xbc: ic->f = instr(sra_imm); break;
928 case 0xd2: ic->f = instr(mskwh_imm); break;
929 case 0xd7: ic->f = instr(inswh_imm); break;
930 case 0xda: ic->f = instr(extwh_imm); break;
931 case 0xe2: ic->f = instr(msklh_imm); break;
932 case 0xe7: ic->f = instr(inslh_imm); break;
933 case 0xea: ic->f = instr(extlh_imm); break;
934 case 0xf2: ic->f = instr(mskqh_imm); break;
935 case 0xf7: ic->f = instr(insqh_imm); break;
936 case 0xfa: ic->f = instr(extqh_imm); break;
937 default:fatal("[ Alpha: unimplemented function 0x%03x for"
938 " opcode 0x%02x ]\n", func, opcode);
939 goto bad;
940 }
941 break;
942 case 0x13:
943 if (rc == ALPHA_ZERO) {
944 ic->f = instr(nop);
945 break;
946 }
947 ic->arg[0] = (size_t) &cpu->cd.alpha.r[rc];
948 ic->arg[1] = (size_t) &cpu->cd.alpha.r[ra];
949 if (func & 0x80)
950 ic->arg[2] = (size_t)((rb << 3) + (func >> 8));
951 else
952 ic->arg[2] = (size_t) &cpu->cd.alpha.r[rb];
953 switch (func & 0xff) {
954 case 0x00: ic->f = instr(mull); break;
955 case 0x20: ic->f = instr(mulq); break;
956 case 0x30: ic->f = instr(umulh); break;
957 default:fatal("[ Alpha: unimplemented function 0x%03x for"
958 " opcode 0x%02x ]\n", func, opcode);
959 goto bad;
960 }
961 break;
962 case 0x16:
963 if (rc == ALPHA_ZERO) {
964 ic->f = instr(nop);
965 break;
966 }
967 ic->arg[0] = (size_t) &cpu->cd.alpha.f[rc];
968 ic->arg[1] = (size_t) &cpu->cd.alpha.f[ra];
969 ic->arg[2] = (size_t) &cpu->cd.alpha.f[rb];
970 switch (func & 0x7ff) {
971 default:fatal("[ Alpha: unimplemented function 0x%03x for"
972 " opcode 0x%02x ]\n", func, opcode);
973 goto bad;
974 }
975 break;
976 case 0x17:
977 if (rc == ALPHA_ZERO) {
978 ic->f = instr(nop);
979 break;
980 }
981 ic->arg[0] = (size_t) &cpu->cd.alpha.f[rc];
982 ic->arg[1] = (size_t) &cpu->cd.alpha.f[ra];
983 ic->arg[2] = (size_t) &cpu->cd.alpha.f[rb];
984 switch (func & 0x7ff) {
985 case 0x020:
986 /* fclr: */
987 if (ra == 31 && rb == 31)
988 ic->f = instr(clear);
989 else {
990 /* fabs: */
991 goto bad;
992 }
993 break;
994 default:fatal("[ Alpha: unimplemented function 0x%03x for"
995 " opcode 0x%02x ]\n", func, opcode);
996 goto bad;
997 }
998 break;
999 case 0x18:
1000 switch (iword & 0xffff) {
1001 case 0x4000: /* mb */
1002 case 0x4400: /* wmb */
1003 ic->f = instr(nop);
1004 break;
1005 case 0xc000: /* rdcc ra */
1006 if (ra == ALPHA_ZERO) {
1007 ic->f = instr(nop);
1008 break;
1009 }
1010 ic->arg[0] = (size_t) &cpu->cd.alpha.r[ra];
1011 ic->f = instr(rdcc);
1012 break;
1013 default:fatal("[ Alpha: unimplemented function 0x%03x for"
1014 " opcode 0x%02x ]\n", func, opcode);
1015 goto bad;
1016 }
1017 break;
1018 case 0x1a:
1019 switch ((iword >> 14) & 3) {
1020 case 0: /* JMP */
1021 case 1: /* JSR */
1022 case 2: /* RET */
1023 ic->arg[0] = (size_t) &cpu->cd.alpha.r[ra];
1024 ic->arg[1] = (size_t) &cpu->cd.alpha.r[rb];
1025 if (ra == ALPHA_ZERO) {
1026 if (cpu->machine->show_trace_tree &&
1027 rb == ALPHA_RA)
1028 ic->f = instr(jsr_0_trace);
1029 else
1030 ic->f = instr(jsr_0);
1031 } else {
1032 if (cpu->machine->show_trace_tree)
1033 ic->f = instr(jsr_trace);
1034 else
1035 ic->f = instr(jsr);
1036 }
1037 break;
1038 default:fatal("[ Alpha: unimpl JSR type %i, ra=%i rb=%i ]\n",
1039 ((iword >> 14) & 3), ra, rb);
1040 goto bad;
1041 }
1042 break;
1043 case 0x30: /* BR */
1044 case 0x34: /* BSR */
1045 case 0x38: /* BLBC */
1046 case 0x39: /* BEQ */
1047 case 0x3a: /* BLT */
1048 case 0x3b: /* BLE */
1049 case 0x3c: /* BLBS */
1050 case 0x3d: /* BNE */
1051 case 0x3e: /* BGE */
1052 case 0x3f: /* BGT */
1053 /* To avoid a GCC warning: */
1054 samepage_function = instr(nop);
1055 switch (opcode) {
1056 case 0x30:
1057 case 0x34:
1058 ic->f = instr(br);
1059 samepage_function = instr(br_samepage);
1060 if (ra != ALPHA_ZERO) {
1061 ic->f = instr(br_return);
1062 samepage_function = instr(br_return_samepage);
1063 }
1064 break;
1065 case 0x38:
1066 ic->f = instr(blbc);
1067 samepage_function = instr(blbc_samepage);
1068 break;
1069 case 0x39:
1070 ic->f = instr(beq);
1071 samepage_function = instr(beq_samepage);
1072 break;
1073 case 0x3a:
1074 ic->f = instr(blt);
1075 samepage_function = instr(blt_samepage);
1076 break;
1077 case 0x3b:
1078 ic->f = instr(ble);
1079 samepage_function = instr(ble_samepage);
1080 break;
1081 case 0x3c:
1082 ic->f = instr(blbs);
1083 samepage_function = instr(blbs_samepage);
1084 break;
1085 case 0x3d:
1086 ic->f = instr(bne);
1087 samepage_function = instr(bne_samepage);
1088 break;
1089 case 0x3e:
1090 ic->f = instr(bge);
1091 samepage_function = instr(bge_samepage);
1092 break;
1093 case 0x3f:
1094 ic->f = instr(bgt);
1095 samepage_function = instr(bgt_samepage);
1096 break;
1097 }
1098 ic->arg[1] = (size_t) &cpu->cd.alpha.r[ra];
1099 ic->arg[0] = (iword & 0x001fffff) << 2;
1100 /* Sign-extend: */
1101 if (ic->arg[0] & 0x00400000)
1102 ic->arg[0] |= 0xffffffffff800000ULL;
1103 /* Branches are calculated as PC + 4 + offset. */
1104 ic->arg[0] = (size_t)(ic->arg[0] + 4);
1105 /* Special case: branch within the same page: */
1106 {
1107 uint64_t mask_within_page =
1108 ((ALPHA_IC_ENTRIES_PER_PAGE-1) << 2) | 3;
1109 uint64_t old_pc = addr;
1110 uint64_t new_pc = old_pc + (int32_t)ic->arg[0];
1111 if ((old_pc & ~mask_within_page) ==
1112 (new_pc & ~mask_within_page)) {
1113 ic->f = samepage_function;
1114 ic->arg[0] = (size_t) (
1115 cpu->cd.alpha.cur_ic_page +
1116 ((new_pc & mask_within_page) >> 2));
1117 }
1118 }
1119 break;
1120 default:fatal("[ UNIMPLEMENTED Alpha opcode 0x%x ]\n", opcode);
1121 goto bad;
1122 }
1123
1124
1125 #define DYNTRANS_TO_BE_TRANSLATED_TAIL
1126 #include "cpu_dyntrans.c"
1127 #undef DYNTRANS_TO_BE_TRANSLATED_TAIL
1128 }
1129

  ViewVC Help
Powered by ViewVC 1.1.26