/[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

Annotation of /trunk/src/cpus/cpu_alpha_instr.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 28 - (hide 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 dpavlin 14 /*
2 dpavlin 22 * Copyright (C) 2005-2006 Anders Gavare. All rights reserved.
3 dpavlin 14 *
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 dpavlin 28 * $Id: cpu_alpha_instr.c,v 1.12 2006/06/30 20:22:53 debug Exp $
29 dpavlin 14 *
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 dpavlin 22 #include "float_emul.h"
40    
41    
42 dpavlin 14 /*
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 dpavlin 22 * 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 dpavlin 14 * 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 dpavlin 24 {
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 dpavlin 14
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 dpavlin 24 /* Alpha instruction words are always little-endian. Convert
793     to host order: */
794     iword = LE32_TO_HOST( *((uint32_t *)&ib[0]) );
795 dpavlin 14
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 dpavlin 28 + 16 * llsc];
883 dpavlin 14 /* 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 dpavlin 24 case 0x0f: ic->f = instr(cmpbge); break;
913 dpavlin 14 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 dpavlin 24 case 0x8f: ic->f = instr(cmpbge_imm); break;
932 dpavlin 14 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 dpavlin 22 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 dpavlin 14 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 dpavlin 22 /* fabs (or fclr): */
1125 dpavlin 14 if (ra == 31 && rb == 31)
1126     ic->f = instr(clear);
1127 dpavlin 22 else
1128     ic->f = instr(fabs);
1129 dpavlin 14 break;
1130 dpavlin 22 case 0x021:
1131     ic->f = instr(fneg);
1132     break;
1133 dpavlin 14 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 dpavlin 22 case 0x30: /* BR */
1183     case 0x31: /* FBEQ */
1184     case 0x34: /* BSR */
1185     case 0x35: /* FBNE */
1186 dpavlin 14 case 0x38: /* BLBC */
1187 dpavlin 22 case 0x39: /* BEQ */
1188     case 0x3a: /* BLT */
1189     case 0x3b: /* BLE */
1190 dpavlin 14 case 0x3c: /* BLBS */
1191 dpavlin 22 case 0x3d: /* BNE */
1192     case 0x3e: /* BGE */
1193     case 0x3f: /* BGT */
1194 dpavlin 14 /* To avoid a GCC warning: */
1195     samepage_function = instr(nop);
1196 dpavlin 22 fp = 0;
1197 dpavlin 14 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 dpavlin 22 case 0x31:
1212     fp = 1;
1213 dpavlin 14 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 dpavlin 22 case 0x35:
1230     fp = 1;
1231 dpavlin 14 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 dpavlin 22 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 dpavlin 14 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