/[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 30 - (hide annotations)
Mon Oct 8 16:20:40 2007 UTC (16 years, 7 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 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 30 * $Id: cpu_alpha_instr.c,v 1.13 2006/07/26 23:21:47 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->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 dpavlin 22 * 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 dpavlin 14 * 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 dpavlin 24 {
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 dpavlin 14
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 dpavlin 24 /* Alpha instruction words are always little-endian. Convert
792     to host order: */
793     iword = LE32_TO_HOST( *((uint32_t *)&ib[0]) );
794 dpavlin 14
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 dpavlin 28 + 16 * llsc];
882 dpavlin 14 /* 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 dpavlin 24 case 0x0f: ic->f = instr(cmpbge); break;
912 dpavlin 14 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 dpavlin 24 case 0x8f: ic->f = instr(cmpbge_imm); break;
931 dpavlin 14 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 dpavlin 22 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 dpavlin 14 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 dpavlin 22 /* fabs (or fclr): */
1124 dpavlin 14 if (ra == 31 && rb == 31)
1125     ic->f = instr(clear);
1126 dpavlin 22 else
1127     ic->f = instr(fabs);
1128 dpavlin 14 break;
1129 dpavlin 22 case 0x021:
1130     ic->f = instr(fneg);
1131     break;
1132 dpavlin 14 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 dpavlin 22 case 0x30: /* BR */
1182     case 0x31: /* FBEQ */
1183     case 0x34: /* BSR */
1184     case 0x35: /* FBNE */
1185 dpavlin 14 case 0x38: /* BLBC */
1186 dpavlin 22 case 0x39: /* BEQ */
1187     case 0x3a: /* BLT */
1188     case 0x3b: /* BLE */
1189 dpavlin 14 case 0x3c: /* BLBS */
1190 dpavlin 22 case 0x3d: /* BNE */
1191     case 0x3e: /* BGE */
1192     case 0x3f: /* BGT */
1193 dpavlin 14 /* To avoid a GCC warning: */
1194     samepage_function = instr(nop);
1195 dpavlin 22 fp = 0;
1196 dpavlin 14 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 dpavlin 22 case 0x31:
1211     fp = 1;
1212 dpavlin 14 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 dpavlin 22 case 0x35:
1229     fp = 1;
1230 dpavlin 14 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 dpavlin 22 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 dpavlin 14 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