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

Parent Directory Parent Directory | Revision Log Revision Log


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

  ViewVC Help
Powered by ViewVC 1.1.26