/[gxemul]/upstream/0.3.6/src/cpus/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.6/src/cpus/cpu_alpha_instr.c

Parent Directory Parent Directory | Revision Log Revision Log


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

  ViewVC Help
Powered by ViewVC 1.1.26