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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 30 - (show annotations)
Mon Oct 8 16:20:40 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 33702 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1325 2006/08/15 15:38:37 debug Exp $
20060723	More Transputer instructions (pfix, nfix, opr, mint, ldl, ldlp,
		eqc, rev, ajw, stl, stlf, sthf, sub, ldnl, ldnlp, ldpi, move,
		wcnt, add, bcnt).
		Adding more SPARC instructions (andcc, addcc, bl, rdpr).
		Progress on the igsfb framebuffer used by NetBSD/netwinder.
		Enabling 8-bit fills in dev_fb.
		NetBSD/netwinder 3.0.1 can now run from a disk image :-)
20060724	Cleanup/performance fix for 64-bit virtual translation table
		updates (by removing the "timestamp" stuff). A full NetBSD/pmax
		3.0.1 install for R4400 has dropped from 667 seconds to 584 :)
		Fixing the igsfb "almost vga" color (it is 24-bit, not 18-bit).
		Adding some MIPS instruction combinations (3*lw, and 3*addu).
		The 8048 keyboard now turns off interrupt enable between the
		KBR_ACK and the KBR_RSTDONE, to work better with Linux 2.6.
		Not causing PPC DEC interrupts if PPC_NO_DEC is set for a
		specific CPU; NetBSD/bebox gets slightly further than before.
		Adding some more SPARC instructions: branches, udiv.
20060725	Refreshing dev_pckbc.c a little.
		Cleanups for the SH emulation mode, and adding the first
		"compact" (16-bit) instructions: various simple movs, nop,
		shll, stc, or, ldc.
20060726	Adding dummy "pcn" (AMD PCnet NIC) PCI glue.
20060727	Various cleanups; removing stuff from cpu.h, such as
		running_translated (not really meaningful anymore), and
		page flags (breaking into the debugger clears all translations
		anyway).
		Minor MIPS instruction combination updates.
20060807	Expanding the 3*sw and 3*lw MIPS instruction combinations to
		work with 2* and 4* too, resulting in a minor performance gain.
		Implementing a usleep hack for the RM52xx/MIPS32/MIPS64 "wait"
		instruction (when emulating 1 cpu).
20060808	Experimenting with some more MIPS instruction combinations.
		Implementing support for showing a (hardcoded 12x22) text
		cursor in igsfb.
20060809	Simplifying the NetBSD/evbmips (Malta) install instructions
		somewhat (by using a NetBSD/pmax ramdisk install kernel).
20060812	Experimenting more with the MIPS 'wait' instruction.
		PCI configuration register writes can now be handled, which
		allow PCI IDE controllers to work with NetBSD/Malta 3.0.1 and
		NetBSD/cobalt 3.0.1. (Previously only NetBSD 2.1 worked.)
20060813	Updating dev_gt.c based on numbers from Alec Voropay, to enable
		Linux 2.6 to use PCI on Malta.
		Continuing on Algor interrupt stuff.
20060814	Adding support for routing ISA interrupts to two different
		interrupts, making it possible to run NetBSD/algor :-)
20060814-15	Testing for the release.

==============  RELEASE 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