/[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 22 - (hide annotations)
Mon Oct 8 16:19:37 2007 UTC (13 years, 3 months ago) by dpavlin
File MIME type: text/plain
File size: 33790 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1121 2006/02/18 21:03:08 debug Exp $
20051126	Cobalt and PReP now work with the 21143 NIC.
		Continuing on Alpha dyntrans things.
		Fixing some more left-shift-by-24 to unsigned.
20051127	Working on OpenFirmware emulation; major cleanup/redesign.
		Progress on MacPPC emulation: NetBSD detects two CPUs (when
		running with -n 2), framebuffer output (for text) works.
		Adding quick-hack Bandit PCI controller and "gc" interrupt
		controller for MacPPC.
20051128	Changing from a Bandit to a Uni-North controller for macppc.
		Continuing on OpenFirmware and MacPPC emulation in general
		(obio controller, and wdc attached to the obio seems to work).
20051129	More work on MacPPC emulation (adding a dummy ADB controller).
		Continuing the PCI bus cleanup (endianness and tag composition)
		and rewriting all PCI controllers' access functions.
20051130	Various minor PPC dyntrans optimizations.
		Manually inlining some parts of the framebuffer redraw routine.
		Slowly beginning the conversion of the old MIPS emulation into
		dyntrans (but this will take quite some time to get right).
		Generalizing quick_pc_to_pointers.
20051201	Documentation update (David Muse has made available a kernel
		which simplifies Debian/DECstation installation).
		Continuing on the ADB bus controller.
20051202	Beginning a rewrite of the Zilog serial controller (dev_zs).
20051203	Continuing on the zs rewrite (now called dev_z8530); conversion
		to devinit style.
		Reworking some of the input-only vs output-only vs input-output
		details of src/console.c, better warning messages, and adding
		a debug dump.
		Removing the concept of "device state"; it wasn't really used.
		Changing some debug output (-vv should now be used to show all
		details about devices and busses; not shown during normal
		startup anymore).
		Beginning on some SPARC instruction disassembly support.
20051204	Minor PPC updates (WALNUT skeleton stuff).
		Continuing on the MIPS dyntrans rewrite.
		More progress on the ADB controller (a keyboard is "detected"
		by NetBSD and OpenBSD).
		Downgrading OpenBSD/arc as a guest OS from "working" to
		"almost working" in the documentation.
		Progress on Algor emulation ("v3" PCI controller).
20051205	Minor updates.
20051207	Sorting devices according to address; this reduces complexity
		of device lookups from O(n) to O(log n) in memory_rw (but no
		real performance increase (yet) in experiments).
20051210	Beginning the work on native dyntrans backends (by making a
		simple skeleton; so far only for Alpha hosts).
20051211	Some very minor SPARC updates.
20051215	Fixing a bug in the MIPS mul (note: not mult) instruction,
		so it also works with non-64-bit emulation. (Thanks to Alec
		Voropay for noticing the problem.)
20051216	More work on the fake/empty/simple/skeleton/whatever backend;
		performance doesn't increase, so this isn't really worth it,
		but it was probably worth it to prepare for a real backend
		later.
20051219	More instr call statistics gathering and analysis stuff.
20051220	Another fix for MIPS 'mul'. Also converting mul and {d,}cl{o,z}
		to dyntrans.
		memory_ppc.c syntax error fix (noticed by Peter Valchev).
		Beginning to move out machines from src/machine.c into
		individual files in src/machines (in a way similar to the
		autodev system for devices).
20051222	Updating the documentation regarding NetBSD/pmax 3.0.
20051223	- " - NetBSD/cats 3.0.
20051225	- " - NetBSD/hpcmips 3.0.
20051226	Continuing on the machine registry redesign.
		Adding support for ARM rrx (33-bit rotate).
		Fixing some signed/unsigned issues (exposed by gcc -W).
20051227	Fixing the bug which prevented a NetBSD/prep 3.0 install kernel
		from starting (triggered when an mtmsr was the last instruction
		on a page). Unfortunately not enough to get the kernel to run
		as well as the 2.1 kernels did.
20051230	Some dyntrans refactoring.
20051231	Continuing on the machine registry redesign.
20060101-10	Continuing... moving more machines. Moving MD interrupt stuff
		from machine.c into a new src/machines/interrupts.c.
20060114	Adding various mvmeppc machine skeletons.
20060115	Continuing on mvme* stuff. NetBSD/mvmeppc prints boot messages
		(for MVME1600) and reaches the root device prompt, but no
		specific hardware devices are emulated yet.
20060116	Minor updates to the mvme1600 emulation mode; the Eagle PCI bus
		seems to work without much modification, and a 21143 can be
		detected, interrupts might work (but untested so far).
		Adding a fake MK48Txx (mkclock) device, for NetBSD/mvmeppc.
20060121	Adding an aux control register for ARM. (A BIG thank you to
		Olivier Houchard for tracking down this bug.)
20060122	Adding more ARM instructions (smulXY), and dev_iq80321_7seg.
20060124	Adding disassembly of more ARM instructions (mia*, mra/mar),
		and some semi-bogus XScale and i80321 registers.
20060201-02	Various minor updates. Moving the last machines out of
		machine.c.
20060204	Adding a -c command line option, for running debugger commands
		before the simulation starts, but after all files have been
		loaded.
		Minor iq80321-related updates.
20060209	Minor hacks (DEVINIT macro, etc).
		Preparing for the generalization of the 64-bit dyntrans address
		translation subsystem.
20060216	Adding ARM ldrd (double-register load).
20060217	Continuing on various ARM-related stuff.
20060218	More progress on the ATA/wdc emulation for NetBSD/iq80321.
		NetBSD/evbarm can now be installed :-)  Updating the docs, etc.
		Continuing on Algor emulation.

==============  RELEASE 0.3.8  ==============


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 22 * $Id: cpu_alpha_instr.c,v 1.7 2006/02/09 22:40:27 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     struct alpha_vph_page *vph_p;
753     unsigned char *page;
754     unsigned char ib[4];
755     void (*samepage_function)(struct cpu *, struct alpha_instr_call *);
756     int opcode, ra, rb, func, rc, imm, load, loadstore_type, fp, llsc;
757 dpavlin 22 #ifdef DYNTRANS_BACKEND
758     int simple = 0;
759     #endif
760 dpavlin 14
761     /* Figure out the (virtual) address of the instruction: */
762     low_pc = ((size_t)ic - (size_t)cpu->cd.alpha.cur_ic_page)
763     / sizeof(struct alpha_instr_call);
764     addr = cpu->pc & ~((ALPHA_IC_ENTRIES_PER_PAGE-1) <<
765     ALPHA_INSTR_ALIGNMENT_SHIFT);
766     addr += (low_pc << ALPHA_INSTR_ALIGNMENT_SHIFT);
767     addr &= ~((1 << ALPHA_INSTR_ALIGNMENT_SHIFT) - 1);
768     cpu->pc = addr;
769    
770     /* Read the instruction word from memory: */
771     if ((addr >> ALPHA_TOPSHIFT) == 0) {
772     vph_p = cpu->cd.alpha.vph_table0[(addr >>
773     ALPHA_LEVEL0_SHIFT) & 8191];
774     page = vph_p->host_load[(addr >> ALPHA_LEVEL1_SHIFT) & 8191];
775     } else if ((addr >> ALPHA_TOPSHIFT) == ALPHA_TOP_KERNEL) {
776     vph_p = cpu->cd.alpha.vph_table0_kernel[(addr >>
777     ALPHA_LEVEL0_SHIFT) & 8191];
778     page = vph_p->host_load[(addr >> ALPHA_LEVEL1_SHIFT) & 8191];
779     } else
780     page = NULL;
781    
782     if (page != NULL) {
783     /* fatal("TRANSLATION HIT!\n"); */
784     memcpy(ib, page + (addr & 8191), sizeof(ib));
785     } else {
786     /* fatal("TRANSLATION MISS!\n"); */
787     if (!cpu->memory_rw(cpu, cpu->mem, addr, &ib[0],
788     sizeof(ib), MEM_READ, CACHE_INSTRUCTION)) {
789     fatal("to_be_translated(): read failed: TODO\n");
790     goto bad;
791     }
792     }
793    
794     #ifdef HOST_LITTLE_ENDIAN
795     iword = *((uint32_t *)&ib[0]);
796     #else
797     iword = ib[0] + (ib[1]<<8) + (ib[2]<<16) + (ib[3]<<24);
798     #endif
799    
800     /* fatal("{ Alpha: translating pc=0x%016llx iword=0x%08x }\n",
801     (long long)addr, (int)iword); */
802    
803    
804     #define DYNTRANS_TO_BE_TRANSLATED_HEAD
805     #include "cpu_dyntrans.c"
806     #undef DYNTRANS_TO_BE_TRANSLATED_HEAD
807    
808    
809     opcode = (iword >> 26) & 63;
810     ra = (iword >> 21) & 31;
811     rb = (iword >> 16) & 31;
812     func = (iword >> 5) & 0x7ff;
813     rc = iword & 31;
814     imm = iword & 0xffff;
815    
816     switch (opcode) {
817     case 0x00: /* CALL_PAL */
818     ic->f = instr(call_pal);
819     ic->arg[0] = (size_t) (iword & 0x3ffffff);
820     break;
821     case 0x08: /* LDA */
822     case 0x09: /* LDAH */
823     if (ra == ALPHA_ZERO) {
824     ic->f = instr(nop);
825     break;
826     }
827     /* TODO: A special case which is common is to add or subtract
828     a small offset from sp. */
829     ic->f = instr(lda);
830     ic->arg[0] = (size_t) &cpu->cd.alpha.r[ra];
831     ic->arg[1] = (size_t) &cpu->cd.alpha.r[rb];
832     if (rb == ALPHA_ZERO)
833     ic->f = instr(lda_0);
834     ic->arg[2] = (ssize_t)(int16_t)imm;
835     if (opcode == 0x09)
836     ic->arg[2] <<= 16;
837     break;
838     case 0x0b: /* LDQ_U */
839     case 0x0f: /* STQ_U */
840     if (ra == ALPHA_ZERO && opcode == 0x0b) {
841     ic->f = instr(nop);
842     break;
843     }
844     if (opcode == 0x0b)
845     ic->f = instr(ldq_u);
846     else
847     ic->f = instr(stq_u);
848     ic->arg[0] = (size_t) &cpu->cd.alpha.r[ra];
849     ic->arg[1] = (size_t) &cpu->cd.alpha.r[rb];
850     ic->arg[2] = (ssize_t)(int16_t)imm;
851     break;
852     case 0x0a:
853     case 0x0c:
854     case 0x0d:
855     case 0x0e:
856     case 0x22:
857     case 0x23:
858     case 0x26:
859     case 0x27:
860     case 0x28:
861     case 0x29:
862     case 0x2a:
863     case 0x2b:
864     case 0x2c:
865     case 0x2d:
866     case 0x2e:
867     case 0x2f:
868     loadstore_type = 0; fp = 0; load = 0; llsc = 0;
869     switch (opcode) {
870     case 0x0a: loadstore_type = 0; load = 1; break; /* ldbu */
871     case 0x0c: loadstore_type = 1; load = 1; break; /* ldwu */
872     case 0x0d: loadstore_type = 1; break; /* stw */
873     case 0x0e: loadstore_type = 0; break; /* stb */
874     case 0x22: loadstore_type = 2; load = 1; fp = 1; break; /*lds*/
875     case 0x23: loadstore_type = 3; load = 1; fp = 1; break; /*ldt*/
876     case 0x26: loadstore_type = 2; fp = 1; break; /* sts */
877     case 0x27: loadstore_type = 3; fp = 1; break; /* stt */
878     case 0x28: loadstore_type = 2; load = 1; break; /* ldl */
879     case 0x29: loadstore_type = 3; load = 1; break; /* ldq */
880     case 0x2a: loadstore_type = 2; load = llsc = 1; break;/* ldl_l*/
881     case 0x2b: loadstore_type = 3; load = llsc = 1; break;/* ldq_l*/
882     case 0x2c: loadstore_type = 2; break; /* stl */
883     case 0x2d: loadstore_type = 3; break; /* stq */
884     case 0x2e: loadstore_type = 2; llsc = 1; break; /* stl_c */
885     case 0x2f: loadstore_type = 3; llsc = 1; break; /* stq_c */
886     }
887     ic->f = alpha_loadstore[
888     loadstore_type + (imm==0? 4 : 0) + 8 * load
889     + (cpu->machine->dyntrans_alignment_check? 16:0)
890     + 32 * llsc];
891     /* Load to the zero register is treated as a prefetch
892     hint. It is ignored here. */
893     if (load && ra == ALPHA_ZERO) {
894     ic->f = instr(nop);
895     break;
896     }
897     if (fp)
898     ic->arg[0] = (size_t) &cpu->cd.alpha.f[ra];
899     else
900     ic->arg[0] = (size_t) &cpu->cd.alpha.r[ra];
901     ic->arg[1] = (size_t) &cpu->cd.alpha.r[rb];
902     ic->arg[2] = (ssize_t)(int16_t)imm;
903     break;
904     case 0x10:
905     if (rc == ALPHA_ZERO) {
906     ic->f = instr(nop);
907     break;
908     }
909     ic->arg[0] = (size_t) &cpu->cd.alpha.r[rc];
910     ic->arg[1] = (size_t) &cpu->cd.alpha.r[ra];
911     if (func & 0x80)
912     ic->arg[2] = (size_t)((rb << 3) + (func >> 8));
913     else
914     ic->arg[2] = (size_t) &cpu->cd.alpha.r[rb];
915     switch (func & 0xff) {
916     case 0x00: ic->f = instr(addl); break;
917     case 0x02: ic->f = instr(s4addl); break;
918     case 0x09: ic->f = instr(subl); break;
919     case 0x0b: ic->f = instr(s4subl); break;
920     case 0x12: ic->f = instr(s8addl); break;
921     case 0x1b: ic->f = instr(s8subl); break;
922     case 0x1d: ic->f = instr(cmpult); break;
923     case 0x20: ic->f = instr(addq); break;
924     case 0x22: ic->f = instr(s4addq); break;
925     case 0x29: ic->f = instr(subq); break;
926     case 0x2b: ic->f = instr(s4subq); break;
927     case 0x2d: ic->f = instr(cmpeq); break;
928     case 0x32: ic->f = instr(s8addq); break;
929     case 0x3b: ic->f = instr(s8subq); break;
930     case 0x3d: ic->f = instr(cmpule); break;
931     case 0x4d: ic->f = instr(cmplt); break;
932     case 0x6d: ic->f = instr(cmple); break;
933    
934     case 0x80: ic->f = instr(addl_imm); break;
935     case 0x82: ic->f = instr(s4addl_imm); break;
936     case 0x89: ic->f = instr(subl_imm); break;
937     case 0x8b: ic->f = instr(s4subl_imm); break;
938     case 0x92: ic->f = instr(s8addl_imm); break;
939     case 0x9b: ic->f = instr(s8subl_imm); break;
940     case 0x9d: ic->f = instr(cmpult_imm); break;
941     case 0xa0: ic->f = instr(addq_imm); break;
942     case 0xa2: ic->f = instr(s4addq_imm); break;
943     case 0xa9: ic->f = instr(subq_imm); break;
944     case 0xab: ic->f = instr(s4subq_imm); break;
945     case 0xad: ic->f = instr(cmpeq_imm); break;
946     case 0xb2: ic->f = instr(s8addq_imm); break;
947     case 0xbb: ic->f = instr(s8subq_imm); break;
948     case 0xbd: ic->f = instr(cmpule_imm); break;
949     case 0xcd: ic->f = instr(cmplt_imm); break;
950     case 0xed: ic->f = instr(cmple_imm); break;
951    
952     default:fatal("[ Alpha: unimplemented function 0x%03x for"
953     " opcode 0x%02x ]\n", func, opcode);
954     goto bad;
955     }
956     break;
957     case 0x11:
958     if (rc == ALPHA_ZERO) {
959     ic->f = instr(nop);
960     break;
961     }
962     ic->arg[0] = (size_t) &cpu->cd.alpha.r[rc];
963     ic->arg[1] = (size_t) &cpu->cd.alpha.r[ra];
964     if (func & 0x80)
965     ic->arg[2] = (size_t)((rb << 3) + (func >> 8));
966     else
967     ic->arg[2] = (size_t) &cpu->cd.alpha.r[rb];
968     switch (func & 0xff) {
969     case 0x00: ic->f = instr(and); break;
970     case 0x08: ic->f = instr(andnot); break;
971     case 0x14: ic->f = instr(cmovlbs); break;
972     case 0x16: ic->f = instr(cmovlbc); break;
973     case 0x20: ic->f = instr(or);
974     if (ra == ALPHA_ZERO || rb == ALPHA_ZERO) {
975     if (ra == ALPHA_ZERO)
976     ra = rb;
977     ic->f = alpha_mov_r_r[ra + rc*32];
978     }
979     break;
980     case 0x24: ic->f = instr(cmoveq); break;
981     case 0x26: ic->f = instr(cmovne); break;
982     case 0x28: ic->f = instr(ornot); break;
983     case 0x40: ic->f = instr(xor); break;
984     case 0x44: ic->f = instr(cmovlt); break;
985     case 0x46: ic->f = instr(cmovge); break;
986     case 0x48: ic->f = instr(xornot); break;
987     case 0x64: ic->f = instr(cmovle); break;
988     case 0x66: ic->f = instr(cmovgt); break;
989     case 0x80: ic->f = instr(and_imm); break;
990     case 0x88: ic->f = instr(andnot_imm); break;
991     case 0x94: ic->f = instr(cmovlbs_imm); break;
992     case 0x96: ic->f = instr(cmovlbc_imm); break;
993     case 0xa0: ic->f = instr(or_imm); break;
994     case 0xa4: ic->f = instr(cmoveq_imm); break;
995     case 0xa6: ic->f = instr(cmovne_imm); break;
996     case 0xa8: ic->f = instr(ornot_imm); break;
997     case 0xc0: ic->f = instr(xor_imm); break;
998     case 0xc4: ic->f = instr(cmovlt_imm); break;
999     case 0xc6: ic->f = instr(cmovge_imm); break;
1000     case 0xc8: ic->f = instr(xornot_imm); break;
1001     case 0xe4: ic->f = instr(cmovle_imm); break;
1002     case 0xe6: ic->f = instr(cmovgt_imm); break;
1003     default:fatal("[ Alpha: unimplemented function 0x%03x for"
1004     " opcode 0x%02x ]\n", func, opcode);
1005     goto bad;
1006     }
1007     break;
1008     case 0x12:
1009     if (rc == ALPHA_ZERO) {
1010     ic->f = instr(nop);
1011     break;
1012     }
1013     ic->arg[0] = (size_t) &cpu->cd.alpha.r[rc];
1014     ic->arg[1] = (size_t) &cpu->cd.alpha.r[ra];
1015     if (func & 0x80)
1016     ic->arg[2] = (size_t)((rb << 3) + (func >> 8));
1017     else
1018     ic->arg[2] = (size_t) &cpu->cd.alpha.r[rb];
1019     switch (func & 0xff) {
1020     case 0x02: ic->f = instr(mskbl); break;
1021     case 0x06: ic->f = instr(extbl); break;
1022     case 0x0b: ic->f = instr(insbl); break;
1023     case 0x12: ic->f = instr(mskwl); break;
1024     case 0x16: ic->f = instr(extwl); break;
1025     case 0x1b: ic->f = instr(inswl); break;
1026     case 0x22: ic->f = instr(mskll); break;
1027     case 0x26: ic->f = instr(extll); break;
1028     case 0x2b: ic->f = instr(insll); break;
1029     case 0x30: ic->f = instr(zap); break;
1030     case 0x31: ic->f = instr(zapnot); break;
1031     case 0x32: ic->f = instr(mskql); break;
1032     case 0x34: ic->f = instr(srl); break;
1033     case 0x36: ic->f = instr(extql); break;
1034     case 0x39: ic->f = instr(sll); break;
1035     case 0x3b: ic->f = instr(insql); break;
1036     case 0x3c: ic->f = instr(sra); break;
1037     case 0x52: ic->f = instr(mskwh); break;
1038     case 0x57: ic->f = instr(inswh); break;
1039     case 0x5a: ic->f = instr(extwh); break;
1040     case 0x62: ic->f = instr(msklh); break;
1041     case 0x67: ic->f = instr(inslh); break;
1042     case 0x6a: ic->f = instr(extlh); break;
1043     case 0x72: ic->f = instr(mskqh); break;
1044     case 0x77: ic->f = instr(insqh); break;
1045     case 0x7a: ic->f = instr(extqh); break;
1046     case 0x82: ic->f = instr(mskbl_imm); break;
1047     case 0x86: ic->f = instr(extbl_imm); break;
1048     case 0x8b: ic->f = instr(insbl_imm); break;
1049     case 0x92: ic->f = instr(mskwl_imm); break;
1050     case 0x96: ic->f = instr(extwl_imm); break;
1051     case 0x9b: ic->f = instr(inswl_imm); break;
1052     case 0xa2: ic->f = instr(mskll_imm); break;
1053     case 0xa6: ic->f = instr(extll_imm); break;
1054     case 0xab: ic->f = instr(insll_imm); break;
1055     case 0xb0: ic->f = instr(zap_imm); break;
1056     case 0xb1: ic->f = instr(zapnot_imm); break;
1057     case 0xb2: ic->f = instr(mskql_imm); break;
1058     case 0xb4: ic->f = instr(srl_imm); break;
1059     case 0xb6: ic->f = instr(extql_imm); break;
1060     case 0xb9: ic->f = instr(sll_imm); break;
1061     case 0xbb: ic->f = instr(insql_imm); break;
1062     case 0xbc: ic->f = instr(sra_imm); break;
1063     case 0xd2: ic->f = instr(mskwh_imm); break;
1064     case 0xd7: ic->f = instr(inswh_imm); break;
1065     case 0xda: ic->f = instr(extwh_imm); break;
1066     case 0xe2: ic->f = instr(msklh_imm); break;
1067     case 0xe7: ic->f = instr(inslh_imm); break;
1068     case 0xea: ic->f = instr(extlh_imm); break;
1069     case 0xf2: ic->f = instr(mskqh_imm); break;
1070     case 0xf7: ic->f = instr(insqh_imm); break;
1071     case 0xfa: ic->f = instr(extqh_imm); break;
1072     default:fatal("[ Alpha: unimplemented function 0x%03x for"
1073     " opcode 0x%02x ]\n", func, opcode);
1074     goto bad;
1075     }
1076     break;
1077     case 0x13:
1078     if (rc == ALPHA_ZERO) {
1079     ic->f = instr(nop);
1080     break;
1081     }
1082     ic->arg[0] = (size_t) &cpu->cd.alpha.r[rc];
1083     ic->arg[1] = (size_t) &cpu->cd.alpha.r[ra];
1084     if (func & 0x80)
1085     ic->arg[2] = (size_t)((rb << 3) + (func >> 8));
1086     else
1087     ic->arg[2] = (size_t) &cpu->cd.alpha.r[rb];
1088     switch (func & 0xff) {
1089     case 0x00: ic->f = instr(mull); break;
1090     case 0x20: ic->f = instr(mulq); break;
1091     case 0x30: ic->f = instr(umulh); break;
1092     default:fatal("[ Alpha: unimplemented function 0x%03x for"
1093     " opcode 0x%02x ]\n", func, opcode);
1094     goto bad;
1095     }
1096     break;
1097     case 0x16:
1098     if (rc == ALPHA_ZERO) {
1099     ic->f = instr(nop);
1100     break;
1101     }
1102     ic->arg[0] = (size_t) &cpu->cd.alpha.f[rc];
1103     ic->arg[1] = (size_t) &cpu->cd.alpha.f[ra];
1104     ic->arg[2] = (size_t) &cpu->cd.alpha.f[rb];
1105     switch (func & 0x7ff) {
1106 dpavlin 22 case 0x02f: ic->f = instr(cvttq_c); break;
1107     case 0x0a0: ic->f = instr(addt); break;
1108     case 0x0a1: ic->f = instr(subt); break;
1109     case 0x0a2: ic->f = instr(mult); break;
1110     case 0x0a3: ic->f = instr(divt); break;
1111     case 0x0a5: ic->f = instr(cmpteq); break;
1112     case 0x0a6: ic->f = instr(cmptlt); break;
1113     case 0x0a7: ic->f = instr(cmptle); break;
1114     case 0x0be: ic->f = instr(cvtqt); break;
1115 dpavlin 14 default:fatal("[ Alpha: unimplemented function 0x%03x for"
1116     " opcode 0x%02x ]\n", func, opcode);
1117     goto bad;
1118     }
1119     break;
1120     case 0x17:
1121     if (rc == ALPHA_ZERO) {
1122     ic->f = instr(nop);
1123     break;
1124     }
1125     ic->arg[0] = (size_t) &cpu->cd.alpha.f[rc];
1126     ic->arg[1] = (size_t) &cpu->cd.alpha.f[ra];
1127     ic->arg[2] = (size_t) &cpu->cd.alpha.f[rb];
1128     switch (func & 0x7ff) {
1129     case 0x020:
1130 dpavlin 22 /* fabs (or fclr): */
1131 dpavlin 14 if (ra == 31 && rb == 31)
1132     ic->f = instr(clear);
1133 dpavlin 22 else
1134     ic->f = instr(fabs);
1135 dpavlin 14 break;
1136 dpavlin 22 case 0x021:
1137     ic->f = instr(fneg);
1138     break;
1139 dpavlin 14 default:fatal("[ Alpha: unimplemented function 0x%03x for"
1140     " opcode 0x%02x ]\n", func, opcode);
1141     goto bad;
1142     }
1143     break;
1144     case 0x18:
1145     switch (iword & 0xffff) {
1146     case 0x4000: /* mb */
1147     case 0x4400: /* wmb */
1148     ic->f = instr(nop);
1149     break;
1150     case 0xc000: /* rdcc ra */
1151     if (ra == ALPHA_ZERO) {
1152     ic->f = instr(nop);
1153     break;
1154     }
1155     ic->arg[0] = (size_t) &cpu->cd.alpha.r[ra];
1156     ic->f = instr(rdcc);
1157     break;
1158     default:fatal("[ Alpha: unimplemented function 0x%03x for"
1159     " opcode 0x%02x ]\n", func, opcode);
1160     goto bad;
1161     }
1162     break;
1163     case 0x1a:
1164     switch ((iword >> 14) & 3) {
1165     case 0: /* JMP */
1166     case 1: /* JSR */
1167     case 2: /* RET */
1168     ic->arg[0] = (size_t) &cpu->cd.alpha.r[ra];
1169     ic->arg[1] = (size_t) &cpu->cd.alpha.r[rb];
1170     if (ra == ALPHA_ZERO) {
1171     if (cpu->machine->show_trace_tree &&
1172     rb == ALPHA_RA)
1173     ic->f = instr(jsr_0_trace);
1174     else
1175     ic->f = instr(jsr_0);
1176     } else {
1177     if (cpu->machine->show_trace_tree)
1178     ic->f = instr(jsr_trace);
1179     else
1180     ic->f = instr(jsr);
1181     }
1182     break;
1183     default:fatal("[ Alpha: unimpl JSR type %i, ra=%i rb=%i ]\n",
1184     ((iword >> 14) & 3), ra, rb);
1185     goto bad;
1186     }
1187     break;
1188 dpavlin 22 case 0x30: /* BR */
1189     case 0x31: /* FBEQ */
1190     case 0x34: /* BSR */
1191     case 0x35: /* FBNE */
1192 dpavlin 14 case 0x38: /* BLBC */
1193 dpavlin 22 case 0x39: /* BEQ */
1194     case 0x3a: /* BLT */
1195     case 0x3b: /* BLE */
1196 dpavlin 14 case 0x3c: /* BLBS */
1197 dpavlin 22 case 0x3d: /* BNE */
1198     case 0x3e: /* BGE */
1199     case 0x3f: /* BGT */
1200 dpavlin 14 /* To avoid a GCC warning: */
1201     samepage_function = instr(nop);
1202 dpavlin 22 fp = 0;
1203 dpavlin 14 switch (opcode) {
1204     case 0x30:
1205     case 0x34:
1206     ic->f = instr(br);
1207     samepage_function = instr(br_samepage);
1208     if (ra != ALPHA_ZERO) {
1209     ic->f = instr(br_return);
1210     samepage_function = instr(br_return_samepage);
1211     }
1212     break;
1213     case 0x38:
1214     ic->f = instr(blbc);
1215     samepage_function = instr(blbc_samepage);
1216     break;
1217 dpavlin 22 case 0x31:
1218     fp = 1;
1219 dpavlin 14 case 0x39:
1220     ic->f = instr(beq);
1221     samepage_function = instr(beq_samepage);
1222     break;
1223     case 0x3a:
1224     ic->f = instr(blt);
1225     samepage_function = instr(blt_samepage);
1226     break;
1227     case 0x3b:
1228     ic->f = instr(ble);
1229     samepage_function = instr(ble_samepage);
1230     break;
1231     case 0x3c:
1232     ic->f = instr(blbs);
1233     samepage_function = instr(blbs_samepage);
1234     break;
1235 dpavlin 22 case 0x35:
1236     fp = 1;
1237 dpavlin 14 case 0x3d:
1238     ic->f = instr(bne);
1239     samepage_function = instr(bne_samepage);
1240     break;
1241     case 0x3e:
1242     ic->f = instr(bge);
1243     samepage_function = instr(bge_samepage);
1244     break;
1245     case 0x3f:
1246     ic->f = instr(bgt);
1247     samepage_function = instr(bgt_samepage);
1248     break;
1249     }
1250 dpavlin 22 if (fp)
1251     ic->arg[1] = (size_t) &cpu->cd.alpha.f[ra];
1252     else
1253     ic->arg[1] = (size_t) &cpu->cd.alpha.r[ra];
1254 dpavlin 14 ic->arg[0] = (iword & 0x001fffff) << 2;
1255     /* Sign-extend: */
1256     if (ic->arg[0] & 0x00400000)
1257     ic->arg[0] |= 0xffffffffff800000ULL;
1258     /* Branches are calculated as PC + 4 + offset. */
1259     ic->arg[0] = (size_t)(ic->arg[0] + 4);
1260     /* Special case: branch within the same page: */
1261     {
1262     uint64_t mask_within_page =
1263     ((ALPHA_IC_ENTRIES_PER_PAGE-1) << 2) | 3;
1264     uint64_t old_pc = addr;
1265     uint64_t new_pc = old_pc + (int32_t)ic->arg[0];
1266     if ((old_pc & ~mask_within_page) ==
1267     (new_pc & ~mask_within_page)) {
1268     ic->f = samepage_function;
1269     ic->arg[0] = (size_t) (
1270     cpu->cd.alpha.cur_ic_page +
1271     ((new_pc & mask_within_page) >> 2));
1272     }
1273     }
1274     break;
1275     default:fatal("[ UNIMPLEMENTED Alpha opcode 0x%x ]\n", opcode);
1276     goto bad;
1277     }
1278    
1279    
1280     #define DYNTRANS_TO_BE_TRANSLATED_TAIL
1281     #include "cpu_dyntrans.c"
1282     #undef DYNTRANS_TO_BE_TRANSLATED_TAIL
1283     }
1284    

  ViewVC Help
Powered by ViewVC 1.1.26