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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 22 - (hide annotations)
Mon Oct 8 16:19:37 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 17607 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.c,v 1.5 2006/01/01 16:08:25 debug Exp $
29 dpavlin 14 *
30     * Alpha CPU emulation.
31     *
32     * TODO: Many things.
33     *
34     * See http://www.eecs.harvard.edu/~nr/toolkit/specs/alpha.html for info
35     * on instruction formats etc.
36     */
37    
38     #include <stdio.h>
39     #include <stdlib.h>
40     #include <string.h>
41     #include <ctype.h>
42    
43     #include "cpu.h"
44     #include "machine.h"
45     #include "memory.h"
46     #include "misc.h"
47     #include "symbol.h"
48    
49     #define DYNTRANS_8K
50     #define DYNTRANS_PAGESIZE 8192
51     #include "tmp_alpha_head.c"
52    
53    
54     /* Alpha symbolic register names: */
55     static char *alpha_regname[N_ALPHA_REGS] = ALPHA_REG_NAMES;
56    
57    
58     /*
59     * alpha_cpu_new():
60     *
61     * Create a new Alpha CPU object by filling the CPU struct.
62     * Return 1 on success, 0 if cpu_type_name isn't a valid Alpha processor.
63     */
64     int alpha_cpu_new(struct cpu *cpu, struct memory *mem,
65     struct machine *machine, int cpu_id, char *cpu_type_name)
66     {
67     int i;
68    
69     if (strcasecmp(cpu_type_name, "Alpha") != 0)
70     return 0;
71    
72     cpu->memory_rw = alpha_memory_rw;
73     cpu->update_translation_table = alpha_update_translation_table;
74 dpavlin 18 cpu->invalidate_translation_caches =
75     alpha_invalidate_translation_caches;
76 dpavlin 14 cpu->invalidate_code_translation = alpha_invalidate_code_translation;
77     cpu->is_32bit = 0;
78    
79     /* Only show name and caches etc for CPU nr 0: */
80     if (cpu_id == 0) {
81     debug("%s", cpu->name);
82     }
83    
84     /* Create the default virtual->physical->host translation: */
85     cpu->cd.alpha.vph_default_page = malloc(sizeof(struct alpha_vph_page));
86     if (cpu->cd.alpha.vph_default_page == NULL) {
87     fprintf(stderr, "out of memory in alpha_cpu_new()\n");
88     exit(1);
89     }
90     memset(cpu->cd.alpha.vph_default_page, 0,
91     sizeof(struct alpha_vph_page));
92     for (i=0; i<ALPHA_LEVEL0; i++)
93     cpu->cd.alpha.vph_table0[i] = cpu->cd.alpha.vph_table0_kernel[i]
94     = cpu->cd.alpha.vph_default_page;
95    
96     cpu->cd.alpha.r[ALPHA_SP] = 0xfffffc000000ff00ULL;
97    
98     return 1;
99     }
100    
101    
102     /*
103     * alpha_cpu_dumpinfo():
104     */
105     void alpha_cpu_dumpinfo(struct cpu *cpu)
106     {
107     /* TODO */
108     debug("\n");
109     }
110    
111    
112     /*
113     * alpha_cpu_list_available_types():
114     *
115     * Print a list of available Alpha CPU types.
116     */
117     void alpha_cpu_list_available_types(void)
118     {
119     /* TODO */
120    
121     debug("Alpha\n");
122     }
123    
124    
125     /*
126     * alpha_cpu_register_match():
127     */
128     void alpha_cpu_register_match(struct machine *m, char *name,
129     int writeflag, uint64_t *valuep, int *match_register)
130     {
131     int i, cpunr = 0;
132    
133     /* CPU number: */
134    
135     /* TODO */
136    
137     if (strcasecmp(name, "pc") == 0) {
138     if (writeflag) {
139     m->cpus[cpunr]->pc = *valuep;
140     } else
141     *valuep = m->cpus[cpunr]->pc;
142     *match_register = 1;
143     }
144    
145     /* Register names: */
146     for (i=0; i<N_ALPHA_REGS; i++) {
147     if (strcasecmp(name, alpha_regname[i]) == 0) {
148     if (writeflag)
149     m->cpus[cpunr]->cd.alpha.r[i] = *valuep;
150     else
151     *valuep = m->cpus[cpunr]->cd.alpha.r[i];
152     *match_register = 1;
153     }
154     }
155     }
156    
157    
158     /*
159     * alpha_cpu_register_dump():
160     *
161     * Dump cpu registers in a relatively readable format.
162     *
163     * gprs: set to non-zero to dump GPRs and some special-purpose registers.
164     * coprocs: set bit 0..3 to dump registers in coproc 0..3.
165     */
166     void alpha_cpu_register_dump(struct cpu *cpu, int gprs, int coprocs)
167     {
168     char *symbol;
169     uint64_t offset;
170     int i, x = cpu->cpu_id;
171    
172     if (gprs) {
173     symbol = get_symbol_name(&cpu->machine->symbol_context,
174     cpu->pc, &offset);
175     debug("cpu%i:\t pc = 0x%016llx", x, (long long)cpu->pc);
176     debug(" <%s>\n", symbol != NULL? symbol : " no symbol ");
177     for (i=0; i<N_ALPHA_REGS; i++) {
178     int r = (i >> 1) + ((i & 1) << 4);
179     if ((i % 2) == 0)
180     debug("cpu%i:\t", x);
181     if (r != ALPHA_ZERO)
182     debug("%3s = 0x%016llx", alpha_regname[r],
183     (long long)cpu->cd.alpha.r[r]);
184     debug((i % 2) == 1? "\n" : " ");
185     }
186     }
187     }
188    
189    
190     /*
191     * alpha_cpu_interrupt():
192     */
193     int alpha_cpu_interrupt(struct cpu *cpu, uint64_t irq_nr)
194     {
195     fatal("alpha_cpu_interrupt(): TODO\n");
196     return 0;
197     }
198    
199    
200     /*
201     * alpha_cpu_interrupt_ack():
202     */
203     int alpha_cpu_interrupt_ack(struct cpu *cpu, uint64_t irq_nr)
204     {
205     /* fatal("alpha_cpu_interrupt_ack(): TODO\n"); */
206     return 0;
207     }
208    
209    
210     /*
211     * alpha_print_imm16_disp():
212     *
213     * Used internally by alpha_cpu_disassemble_instr().
214     */
215     static void alpha_print_imm16_disp(int imm, int rb)
216     {
217     imm = (int16_t)imm;
218    
219     if (imm < 0) {
220     debug("-");
221     imm = -imm;
222     }
223     if (imm <= 256)
224     debug("%i", imm);
225     else
226     debug("0x%x", imm);
227     if (rb != ALPHA_ZERO)
228     debug("(%s)", alpha_regname[rb]);
229     }
230    
231    
232     /*
233     * alpha_cpu_disassemble_instr():
234     *
235     * Convert an instruction word into human readable format, for instruction
236     * tracing.
237     *
238     * If running is 1, cpu->pc should be the address of the instruction.
239     *
240     * If running is 0, things that depend on the runtime environment (eg.
241     * register contents) will not be shown, and addr will be used instead of
242     * cpu->pc for relative addresses.
243     */
244     int alpha_cpu_disassemble_instr(struct cpu *cpu, unsigned char *ib,
245     int running, uint64_t dumpaddr, int bintrans)
246     {
247     uint32_t iw;
248     uint64_t offset, tmp;
249     int opcode, ra, rb, func, rc, imm, floating, rbrc = 0, indir = 0;
250     char *symbol, *mnem = NULL;
251     char palcode_name[30];
252    
253     if (running)
254     dumpaddr = cpu->pc;
255    
256     symbol = get_symbol_name(&cpu->machine->symbol_context,
257     dumpaddr, &offset);
258     if (symbol != NULL && offset == 0)
259     debug("<%s>\n", symbol);
260    
261     if (cpu->machine->ncpus > 1 && running)
262     debug("cpu%i:\t", cpu->cpu_id);
263    
264     debug("%016llx: ", (long long)dumpaddr);
265    
266     iw = ib[0] + (ib[1]<<8) + (ib[2]<<16) + (ib[3]<<24);
267     debug("%08x\t", (int)iw);
268    
269     opcode = iw >> 26;
270     ra = (iw >> 21) & 31;
271     rb = (iw >> 16) & 31;
272     func = (iw >> 5) & 0x7ff;
273     rc = iw & 31;
274     imm = iw & 0xffff;
275    
276     switch (opcode) {
277     case 0x00:
278     alpha_palcode_name(iw & 0x3ffffff, palcode_name,
279     sizeof(palcode_name));
280     debug("call_pal %s\n", palcode_name);
281     break;
282     case 0x08:
283     case 0x09:
284     debug("lda%s\t%s,", opcode == 9? "h" : "", alpha_regname[ra]);
285     alpha_print_imm16_disp(imm, rb);
286     debug("\n");
287     break;
288     case 0x0a:
289     case 0x0b:
290     case 0x0c:
291     case 0x0d:
292     case 0x0e:
293     case 0x0f:
294     case 0x20:
295     case 0x21:
296     case 0x22:
297     case 0x23:
298     case 0x24:
299     case 0x25:
300     case 0x26:
301     case 0x27:
302     case 0x28:
303     case 0x29:
304     case 0x2a:
305     case 0x2b:
306     case 0x2c:
307     case 0x2d:
308     case 0x2e:
309     case 0x2f:
310     floating = 0;
311     switch (opcode) {
312     case 0x0a: mnem = "ldbu"; break;
313     case 0x0b: mnem = "ldq_u"; break;
314     case 0x0c: mnem = "ldwu"; break;
315     case 0x0d: mnem = "stw"; break;
316     case 0x0e: mnem = "stb"; break;
317     case 0x0f: mnem = "stq_u"; break;
318     case 0x20: mnem = "ldf"; floating = 1; break;
319     case 0x21: mnem = "ldg"; floating = 1; break;
320     case 0x22: mnem = "lds"; floating = 1; break;
321     case 0x23: mnem = "ldt"; floating = 1; break;
322     case 0x24: mnem = "stf"; floating = 1; break;
323     case 0x25: mnem = "stg"; floating = 1; break;
324     case 0x26: mnem = "sts"; floating = 1; break;
325     case 0x27: mnem = "stt"; floating = 1; break;
326     case 0x28: mnem = "ldl"; break;
327     case 0x29: mnem = "ldq"; break;
328     case 0x2a: mnem = "ldl_l"; break;
329     case 0x2b: mnem = "ldq_l"; break;
330     case 0x2c: mnem = "stl"; break;
331     case 0x2d: mnem = "stq"; break;
332     case 0x2e: mnem = "stl_c"; break;
333     case 0x2f: mnem = "stq_c"; break;
334     }
335     if (opcode == 0x0b && ra == ALPHA_ZERO) {
336     debug("unop");
337     } else {
338     debug("%s\t", mnem);
339     if (floating)
340     debug("f%i,", ra);
341     else
342     debug("%s,", alpha_regname[ra]);
343     alpha_print_imm16_disp(imm, rb);
344     }
345     debug("\n");
346     break;
347     case 0x10:
348     switch (func & 0x7f) {
349     case 0x00: mnem = "addl"; break;
350     case 0x02: mnem = "s4addl"; break;
351     case 0x09: mnem = "subl"; break;
352     case 0x0b: mnem = "s4subl"; break;
353     case 0x0f: mnem = "cmpbge"; break;
354     case 0x12: mnem = "s8addl"; break;
355     case 0x1b: mnem = "s8subl"; break;
356     case 0x1d: mnem = "cmpult"; break;
357     case 0x20: mnem = "addq"; break;
358     case 0x22: mnem = "s4addq"; break;
359     case 0x29: mnem = "subq"; break;
360     case 0x2b: mnem = "s4subq"; break;
361     case 0x2d: mnem = "cmpeq"; break;
362     case 0x32: mnem = "s8addq"; break;
363     case 0x3b: mnem = "s8subq"; break;
364     case 0x3d: mnem = "cmpule"; break;
365     case 0x40: mnem = "addl/v"; break;
366     case 0x49: mnem = "subl/v"; break;
367     case 0x4d: mnem = "cmplt"; break;
368     case 0x60: mnem = "addq/v"; break;
369     case 0x69: mnem = "subq/v"; break;
370     case 0x6d: mnem = "cmple"; break;
371     default:debug("UNIMPLEMENTED opcode 0x%x func 0x%x\n",
372     opcode, func);
373     }
374     if (mnem == NULL)
375     break;
376     if (func & 0x80)
377     debug("%s\t%s,0x%x,%s\n", mnem,
378     alpha_regname[ra], (rb << 3) + (func >> 8),
379     alpha_regname[rc]);
380     else
381     debug("%s\t%s,%s,%s\n", mnem, alpha_regname[ra],
382     alpha_regname[rb], alpha_regname[rc]);
383     break;
384     case 0x11:
385     switch (func & 0x7f) {
386     case 0x000: mnem = "and"; break;
387     case 0x008: mnem = "andnot"; break;
388     case 0x014: mnem = "cmovlbs"; break;
389     case 0x016: mnem = "cmovlbc"; break;
390     case 0x020: mnem = "or"; break;
391     case 0x024: mnem = "cmoveq"; break;
392     case 0x026: mnem = "cmovne"; break;
393     case 0x028: mnem = "ornot"; break;
394     case 0x040: mnem = "xor"; break;
395     case 0x044: mnem = "cmovlt"; break;
396     case 0x046: mnem = "cmovge"; break;
397     case 0x048: mnem = "eqv"; break;
398     case 0x061: mnem = "amask"; break;
399     case 0x064: mnem = "cmovle"; break;
400     case 0x066: mnem = "cmovgt"; break;
401     default:debug("UNIMPLEMENTED opcode 0x%x func 0x%x\n",
402     opcode, func);
403     }
404     if (mnem == NULL)
405     break;
406     /* Special cases: "nop" etc: */
407     if (func == 0x020 && rc == ALPHA_ZERO)
408     debug("nop\n");
409     else if (func == 0x020 && (ra == ALPHA_ZERO
410     || rb == ALPHA_ZERO)) {
411     if (ra == ALPHA_ZERO && rb == ALPHA_ZERO)
412     debug("clr\t%s\n", alpha_regname[rc]);
413     else if (ra == ALPHA_ZERO)
414     debug("mov\t%s,%s\n", alpha_regname[rb],
415     alpha_regname[rc]);
416     else
417     debug("mov\t%s,%s\n", alpha_regname[ra],
418     alpha_regname[rc]);
419     } else if (func & 0x80)
420     debug("%s\t%s,0x%x,%s\n", mnem,
421     alpha_regname[ra], (rb << 3) + (func >> 8),
422     alpha_regname[rc]);
423     else
424     debug("%s\t%s,%s,%s\n", mnem, alpha_regname[ra],
425     alpha_regname[rb], alpha_regname[rc]);
426     break;
427     case 0x12:
428     switch (func & 0x7f) {
429     case 0x02: mnem = "mskbl"; break;
430     case 0x06: mnem = "extbl"; break;
431     case 0x0b: mnem = "insbl"; break;
432     case 0x12: mnem = "mskwl"; break;
433     case 0x16: mnem = "extwl"; break;
434     case 0x1b: mnem = "inswl"; break;
435     case 0x22: mnem = "mskll"; break;
436     case 0x26: mnem = "extll"; break;
437     case 0x2b: mnem = "insll"; break;
438     case 0x30: mnem = "zap"; break;
439     case 0x31: mnem = "zapnot"; break;
440     case 0x32: mnem = "mskql"; break;
441     case 0x34: mnem = "srl"; break;
442     case 0x36: mnem = "extql"; break;
443     case 0x39: mnem = "sll"; break;
444     case 0x3b: mnem = "insql"; break;
445     case 0x3c: mnem = "sra"; break;
446     case 0x52: mnem = "mskwh"; break;
447     case 0x57: mnem = "inswh"; break;
448     case 0x5a: mnem = "extwh"; break;
449     case 0x62: mnem = "msklh"; break;
450     case 0x67: mnem = "inslh"; break;
451     case 0x6a: mnem = "extlh"; break;
452     case 0x72: mnem = "mskqh"; break;
453     case 0x77: mnem = "insqh"; break;
454     case 0x7a: mnem = "extqh"; break;
455     default:debug("UNIMPLEMENTED opcode 0x%x func 0x%x\n",
456     opcode, func);
457     }
458     if (mnem == NULL)
459     break;
460     if (func & 0x80)
461     debug("%s\t%s,0x%x,%s\n", mnem,
462     alpha_regname[ra], (rb << 3) + (func >> 8),
463     alpha_regname[rc]);
464     else
465     debug("%s\t%s,%s,%s\n", mnem, alpha_regname[ra],
466     alpha_regname[rb], alpha_regname[rc]);
467     break;
468     case 0x13:
469     switch (func & 0x7f) {
470     case 0x00: mnem = "mull"; break;
471     case 0x20: mnem = "mulq"; break;
472     case 0x30: mnem = "umulh"; break;
473     case 0x40: mnem = "mull/v"; break;
474     case 0x60: mnem = "mulq/v"; break;
475     default:debug("UNIMPLEMENTED opcode 0x%x func 0x%x\n",
476     opcode, func);
477     }
478     if (mnem == NULL)
479     break;
480     if (func & 0x80)
481     debug("%s\t%s,0x%x,%s\n", mnem,
482     alpha_regname[ra], (rb << 3) + (func >> 8),
483     alpha_regname[rc]);
484     else
485     debug("%s\t%s,%s,%s\n", mnem, alpha_regname[ra],
486     alpha_regname[rb], alpha_regname[rc]);
487     break;
488     case 0x16:
489     switch (func & 0x7ff) {
490 dpavlin 22 case 0x02f: mnem = "cvttq/c"; rbrc = 1; break;
491 dpavlin 14 case 0x080: mnem = "adds"; break;
492     case 0x081: mnem = "subs"; break;
493     case 0x082: mnem = "muls"; break;
494 dpavlin 22 case 0x083: mnem = "XXXx083"; break;
495 dpavlin 14 case 0x0a0: mnem = "addt"; break;
496     case 0x0a1: mnem = "subt"; break;
497     case 0x0a2: mnem = "mult"; break;
498     case 0x0a3: mnem = "divt"; break;
499 dpavlin 22 case 0x0a5: mnem = "cmpteq"; break;
500     case 0x0a6: mnem = "cmptlt"; break;
501     case 0x0a7: mnem = "cmptle"; break;
502 dpavlin 14 case 0x0be: mnem = "cvtqt"; rbrc = 1; break;
503     default:debug("UNIMPLEMENTED opcode 0x%x func 0x%x\n",
504     opcode, func);
505     }
506     if (mnem == NULL)
507     break;
508     if (rbrc)
509     debug("%s\tf%i,f%i\n", mnem, rb, rc);
510     else
511     debug("%s\tf%i,f%i,f%i\n", mnem, ra, rb, rc);
512     break;
513     case 0x17:
514     switch (func & 0x7ff) {
515     case 0x020: mnem = "fabs"; rbrc = 1; break;
516 dpavlin 22 case 0x021: mnem = "fneg"; rbrc = 1; break;
517 dpavlin 14 default:debug("UNIMPLEMENTED opcode 0x%x func 0x%x\n",
518     opcode, func);
519     }
520     if (mnem == NULL)
521     break;
522     if ((func & 0x7ff) == 0x020 && ra == 31 && rb == 31)
523     debug("fclr\tf%i\n", rc);
524     else if (rbrc)
525     debug("%s\tf%i,f%i\n", mnem, rb, rc);
526     else
527     debug("%s\tf%i,f%i,f%i\n", mnem, ra, rb, rc);
528     break;
529     case 0x18:
530     switch (iw & 0xffff) {
531     case 0x0000: mnem = "trapb"; break;
532     case 0x0400: mnem = "excb"; break;
533     case 0x4000: mnem = "mb"; break;
534     case 0x4400: mnem = "wmb"; break;
535     case 0x8000: mnem = "fetch"; indir = 1; break;
536     case 0xa000: mnem = "fetch_m"; indir = 1; break;
537     case 0xc000: mnem = "rpcc"; break;
538     case 0xe000: mnem = "rc"; break;
539     case 0xe800: mnem = "ecb"; indir = 1; break;
540     case 0xf000: mnem = "rs"; break;
541     case 0xf800: mnem = "wh64"; indir = 1; break;
542     default:debug("UNIMPLEMENTED opcode 0x%x func 0x%x\n",
543     opcode, func);
544     }
545     if (mnem == NULL)
546     break;
547     debug("%s", mnem);
548     if ((iw & 0xffff) >= 0x8000) {
549     debug("\t");
550     if (indir)
551     debug("(%s)", alpha_regname[rb]);
552     else
553     debug("%s", alpha_regname[ra]);
554     }
555     debug("\n");
556     break;
557     case 0x1a:
558     tmp = iw & 0x3fff;
559     if (tmp & 0x2000)
560     tmp |= 0xffffffffffffc000ULL;
561     tmp <<= 2;
562     tmp += dumpaddr + sizeof(uint32_t);
563     switch ((iw >> 14) & 3) {
564     case 0:
565     case 1: if (((iw >> 14) & 3) == 0)
566     debug("jmp");
567     else
568     debug("jsr");
569     debug("\t%s,", alpha_regname[ra]);
570     debug("(%s),", alpha_regname[rb]);
571     debug("0x%llx", (long long)tmp);
572     symbol = get_symbol_name(&cpu->machine->symbol_context,
573     tmp, &offset);
574     if (symbol != NULL)
575     debug("\t<%s>", symbol);
576     break;
577     case 2: debug("ret");
578     break;
579     default:fatal("unimpl JSR!");
580     }
581     debug("\n");
582     break;
583     case 0x30:
584     case 0x34:
585     tmp = iw & 0x1fffff;
586     if (tmp & 0x100000)
587     tmp |= 0xffffffffffe00000ULL;
588     tmp <<= 2;
589     tmp += dumpaddr + sizeof(uint32_t);
590     debug("%s\t", opcode==0x30? "br" : "bsr");
591     if (ra != ALPHA_ZERO)
592     debug("%s,", alpha_regname[ra]);
593     debug("0x%llx", (long long)tmp);
594     symbol = get_symbol_name(&cpu->machine->symbol_context,
595     tmp, &offset);
596     if (symbol != NULL)
597     debug("\t<%s>", symbol);
598     debug("\n");
599     break;
600 dpavlin 22 case 0x31:
601     case 0x35:
602 dpavlin 14 case 0x38:
603     case 0x39:
604     case 0x3a:
605     case 0x3b:
606     case 0x3c:
607     case 0x3d:
608     case 0x3e:
609     case 0x3f:
610 dpavlin 22 floating = 0;
611 dpavlin 14 switch (opcode) {
612 dpavlin 22 case 0x31: mnem = "fbeq"; floating = 1; break;
613     case 0x35: mnem = "fbne"; floating = 1; break;
614 dpavlin 14 case 0x38: mnem = "blbc"; break;
615     case 0x39: mnem = "beq"; break;
616     case 0x3a: mnem = "blt"; break;
617     case 0x3b: mnem = "ble"; break;
618     case 0x3c: mnem = "blbs"; break;
619     case 0x3d: mnem = "bne"; break;
620     case 0x3e: mnem = "bge"; break;
621     case 0x3f: mnem = "bgt"; break;
622     }
623     tmp = iw & 0x1fffff;
624     if (tmp & 0x100000)
625     tmp |= 0xffffffffffe00000ULL;
626     tmp <<= 2;
627     tmp += dumpaddr + sizeof(uint32_t);
628 dpavlin 22 debug("%s\t", mnem);
629     if (floating)
630     debug("f%i,", ra);
631     else
632     debug("%s,", alpha_regname[ra]);
633 dpavlin 14 debug("0x%llx", (long long)tmp);
634     symbol = get_symbol_name(&cpu->machine->symbol_context,
635     tmp, &offset);
636     if (symbol != NULL)
637     debug("\t<%s>", symbol);
638     debug("\n");
639     break;
640     default:debug("UNIMPLEMENTED opcode 0x%x\n", opcode);
641     }
642    
643     return sizeof(uint32_t);
644     }
645    
646    
647     #define MEMORY_RW alpha_userland_memory_rw
648     #define MEM_ALPHA
649     #define MEM_USERLAND
650     #include "../memory_rw.c"
651     #undef MEM_USERLAND
652     #undef MEM_ALPHA
653     #undef MEMORY_RW
654    
655    
656     #include "tmp_alpha_tail.c"
657    

  ViewVC Help
Powered by ViewVC 1.1.26