/[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 28 - (show annotations)
Mon Oct 8 16:20:26 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 33733 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1298 2006/07/22 11:27:46 debug Exp $
20060626	Continuing on SPARC emulation (beginning on the 'save'
		instruction, register windows, etc).
20060629	Planning statistics gathering (new -s command line option),
		and renaming speed_tricks to allow_instruction_combinations.
20060630	Some minor manual page updates.
		Various cleanups.
		Implementing the -s command line option.
20060701	FINALLY found the bug which prevented Linux and Ultrix from
		running without the ugly hack in the R2000/R3000 cache isol
		code; it was the phystranslation hint array which was buggy.
		Removing the phystranslation hint code completely, for now.
20060702	Minor dyntrans cleanups; invalidation of physpages now only
		invalidate those parts of a page that have actually been
		translated. (32 parts per page.)
		Some MIPS non-R3000 speed fixes.
		Experimenting with MIPS instruction combination for some
		addiu+bne+sw loops, and sw+sw+sw.
		Adding support (again) for larger-than-4KB pages in MIPS tlbw*.
		Continuing on SPARC emulation: adding load/store instructions.
20060704	Fixing a virtual vs physical page shift bug in the new tlbw*
		implementation. Problem noticed by Jakub Jermar. (Many thanks.)
		Moving rfe and eret to cpu_mips_instr.c, since that is the
		only place that uses them nowadays.
20060705	Removing the BSD license from the "testmachine" include files,
		placing them in the public domain instead; this enables the
		testmachine stuff to be used from projects which are
		incompatible with the BSD license for some reason.
20060707	Adding instruction combinations for the R2000/R3000 L1
		I-cache invalidation code used by NetBSD/pmax 3.0, lui+addiu,
		various branches followed by addiu or nop, and jr ra followed
		by addiu. The time it takes to perform a full NetBSD/pmax R3000
		install on the laptop has dropped from 573 seconds to 539. :-)
20060708	Adding a framebuffer controller device (dev_fbctrl), which so
		far can be used to change the fb resolution during runtime, but
		in the future will also be useful for accelerated block fill/
		copy, and possibly also simplified character output.
		Adding an instruction combination for NetBSD/pmax' strlen.
20060709	Minor fixes: reading raw files in src/file.c wasn't memblock
		aligned, removing buggy multi_sw MIPS instruction combination,
		etc.
20060711	Adding a machine_qemu.c, which contains a "qemu_mips" machine.
		(It mimics QEMU's MIPS machine mode, so that a test kernel
		made for QEMU_MIPS also can run in GXemul... at least to some
		extent.)  Adding a short section about how to run this mode to
		doc/guestoses.html.
20060714	Misc. minor code cleanups.
20060715	Applying a patch which adds getchar() to promemul/yamon.c
		(from Oleksandr Tymoshenko).
		Adding yamon.h from NetBSD, and rewriting yamon.c to use it
		(instead of ugly hardcoded numbers) + some cleanup.
20060716	Found and fixed the bug which broke single-stepping of 64-bit
		programs between 0.4.0 and 0.4.0.1 (caused by too quick
		refactoring and no testing). Hopefully this fix will not
		break too many other things.
20060718	Continuing on the 8253 PIT; it now works with Linux/QEMU_MIPS.
		Re-adding the sw+sw+sw instr comb (the problem was that I had
		ignored endian issues); however, it doesn't seem to give any
		big performance gain.
20060720	Adding a dummy Transputer mode (T414, T800 etc) skeleton (only
		the 'j' and 'ldc' instructions are implemented so far). :-}
20060721	Adding gtreg.h from NetBSD, updating dev_gt.c to use it, plus
		misc. other updates to get Linux 2.6 for evbmips/malta working
		(thanks to Alec Voropay for the details).
		FINALLY found and fixed the bug which made tlbw* for non-R3000
		buggy; it was a reference count problem in the dyntrans core.
20060722	Testing stuff; things seem stable enough for a new release.

==============  RELEASE 0.4.1  ==============


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

  ViewVC Help
Powered by ViewVC 1.1.26