/[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 20 - (hide annotations)
Mon Oct 8 16:19:23 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 17193 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1055 2005/11/25 22:48:36 debug Exp $
20051031	Adding disassembly support for more ARM instructions (clz,
		smul* etc), and adding a hack to support "new tiny" pages
		for StrongARM.
20051101	Minor documentation updates (NetBSD 2.0.2 -> 2.1, and OpenBSD
		3.7 -> 3.8, and lots of testing).
		Changing from 1-sector PIO mode 0 transfers to 128-sector PIO
		mode 3 (in dev_wdc).
		Various minor ARM dyntrans updates (pc-relative loads from
		within the same page as the instruction are now treated as
		constant "mov").
20051102	Re-enabling instruction combinations (they were accidentally
		disabled).
		Dyntrans TLB entries are now overwritten using a round-robin
		scheme instead of randomly. This increases performance.
		Fixing a typo in file.c (thanks to Chuan-Hua Chang for
		noticing it).
		Experimenting with adding ATAPI support to dev_wdc (to make
		emulated *BSD detect cdroms as cdroms, not harddisks).
20051104	Various minor updates.
20051105	Continuing on the ATAPI emulation. Seems to work well enough
		for a NetBSD/cats installation, but not OpenBSD/cats.
		Various other updates.
20051106	Modifying the -Y command line option to allow scaleup with
		certain graphic controllers (only dev_vga so far), not just
		scaledown.
		Some minor dyntrans cleanups.
20051107	Beginning a cleanup up the PCI subsystem (removing the
		read_register hack, etc).
20051108	Continuing the cleanup; splitting up some pci devices into a
		normal autodev device and some separate pci glue code.
20051109	Continuing on the PCI bus stuff; all old pci_*.c have been
		incorporated into normal devices and/or rewritten as glue code
		only, adding a dummy Intel 82371AB PIIX4 for Malta (not really
		tested yet).
		Minor pckbc fix so that Linux doesn't complain.
		Working on the DEC 21143 NIC (ethernet mac rom stuff mostly).
		Various other minor fixes.
20051110	Some more ARM dyntrans fine-tuning (e.g. some instruction
		combinations (cmps followed by conditional branch within the
		same page) and special cases for DPIs with regform when the
		shifter isn't used).
20051111	ARM dyntrans updates: O(n)->O(1) for just-mark-as-non-
		writable in the generic pc_to_pointers function, and some other
		minor hacks.
		Merging Cobalt and evbmips (Malta) ISA interrupt handling,
		and some minor fixes to allow Linux to accept harddisk irqs.
20051112	Minor device updates (pckbc, dec21143, lpt, ...), most
		importantly fixing the ALI M1543/M5229 so that harddisk irqs
		work with Linux/CATS.
20051113	Some more generalizations of the PCI subsystem.
		Finally took the time to add a hack for SCSI CDROM TOCs; this
		enables OpenBSD to use partition 'a' (as needed by the OpenBSD
		installer), and Windows NT's installer to get a bit further.
		Also fixing dev_wdc to allow Linux to detect ATAPI CDROMs.
		Continuing on the DEC 21143.
20051114	Minor ARM dyntrans tweaks; ARM cmps+branch optimization when
		comparing with 0, and generalizing the xchg instr. comb.
		Adding disassembly of ARM mrrc/mcrr and q{,d}{add,sub}.
20051115	Continuing on various PPC things (BATs, other address trans-
		lation things, various loads/stores, BeBox emulation, etc.).
		Beginning to work on PPC interrupt/exception support.
20051116	Factoring out some code which initializes legacy ISA devices
		from those machines that use them (bus_isa).
		Continuing on PPC interrupt/exception support.
20051117	Minor Malta fixes: RTC year offset = 80, disabling a speed hack
		which caused NetBSD to detect a too fast cpu, and adding a new
		hack to make Linux detect a faster cpu.
		Continuing on the Artesyn PM/PPC emulation mode.
		Adding an Algor emulation skeleton (P4032 and P5064);
		implementing some of the basics.
		Continuing on PPC emulation in general; usage of unimplemented
		SPRs is now easier to track, continuing on memory/exception
		related issues, etc.
20051118	More work on PPC emulation (tgpr0..3, exception handling,
		memory stuff, syscalls, etc.).
20051119	Changing the ARM dyntrans code to mostly use cpu->pc, and not
		necessarily use arm reg 15. Seems to work.
		Various PPC updates; continuing on the PReP emulation mode.
20051120	Adding a workaround/hack to dev_mc146818 to allow NetBSD/prep
		to detect the clock.
20051121	More cleanup of the PCI bus (memory and I/O bases, etc).
		Continuing on various PPC things (decrementer and timebase,
		WDCs on obio (on PReP) use irq 13, not 14/15).
20051122	Continuing on the CPC700 controller (interrupts etc) for PMPPC,
		and on PPC stuff in general.
		Finally! After some bug fixes to the virtual to physical addr
		translation, NetBSD/{prep,pmppc} 2.1 reach userland and are
		stable enough to be interacted with.
		More PCI updates; reverse-endian device access for PowerPC etc.
20051123	Generalizing the IEEE floating point subsystem (moving it out
		from src/cpus/cpu_mips_coproc.c into a new src/float_emul.c).
		Input via slave xterms was sometimes not really working; fixing
		this for ns16550, and a warning message is now displayed if
		multiple non-xterm consoles are active.
		Adding some PPC floating point support, etc.
		Various interrupt related updates (dev_wdc, _ns16550, _8259,
		and the isa32 common code in machine.c).
		NetBSD/prep can now be installed! :-) (Well, with some manual
		commands necessary before running sysinst.) Updating the
		documentation and various other things to reflect this.
20051124	Various minor documentation updates.
		Continuing the work on the DEC 21143 NIC.
20051125	LOTS of work on the 21143. Both OpenBSD and NetBSD work fine
		with it now, except that OpenBSD sometimes gives a time-out
		warning.
		Minor documentation updates.

==============  RELEASE 0.3.7  ==============


1 dpavlin 14 /*
2     * Copyright (C) 2005 Anders Gavare. All rights reserved.
3     *
4     * Redistribution and use in source and binary forms, with or without
5     * modification, are permitted provided that the following conditions are met:
6     *
7     * 1. Redistributions of source code must retain the above copyright
8     * notice, this list of conditions and the following disclaimer.
9     * 2. Redistributions in binary form must reproduce the above copyright
10     * notice, this list of conditions and the following disclaimer in the
11     * documentation and/or other materials provided with the distribution.
12     * 3. The name of the author may not be used to endorse or promote products
13     * derived from this software without specific prior written permission.
14     *
15     * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16     * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17     * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18     * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19     * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20     * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21     * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22     * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23     * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24     * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25     * SUCH DAMAGE.
26     *
27     *
28 dpavlin 20 * $Id: cpu_alpha.c,v 1.3 2005/11/13 00:14:07 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     case 0x080: mnem = "adds"; break;
491     case 0x081: mnem = "subs"; break;
492     case 0x082: mnem = "muls"; break;
493     case 0x083: mnem = "mult"; break;
494     case 0x0a0: mnem = "addt"; break;
495     case 0x0a1: mnem = "subt"; break;
496     case 0x0a2: mnem = "mult"; break;
497     case 0x0a3: mnem = "divt"; break;
498     case 0x0be: mnem = "cvtqt"; rbrc = 1; break;
499     default:debug("UNIMPLEMENTED opcode 0x%x func 0x%x\n",
500     opcode, func);
501     }
502     if (mnem == NULL)
503     break;
504     if (rbrc)
505     debug("%s\tf%i,f%i\n", mnem, rb, rc);
506     else
507     debug("%s\tf%i,f%i,f%i\n", mnem, ra, rb, rc);
508     break;
509     case 0x17:
510     switch (func & 0x7ff) {
511     case 0x020: mnem = "fabs"; rbrc = 1; break;
512     default:debug("UNIMPLEMENTED opcode 0x%x func 0x%x\n",
513     opcode, func);
514     }
515     if (mnem == NULL)
516     break;
517     if ((func & 0x7ff) == 0x020 && ra == 31 && rb == 31)
518     debug("fclr\tf%i\n", rc);
519     else if (rbrc)
520     debug("%s\tf%i,f%i\n", mnem, rb, rc);
521     else
522     debug("%s\tf%i,f%i,f%i\n", mnem, ra, rb, rc);
523     break;
524     case 0x18:
525     switch (iw & 0xffff) {
526     case 0x0000: mnem = "trapb"; break;
527     case 0x0400: mnem = "excb"; break;
528     case 0x4000: mnem = "mb"; break;
529     case 0x4400: mnem = "wmb"; break;
530     case 0x8000: mnem = "fetch"; indir = 1; break;
531     case 0xa000: mnem = "fetch_m"; indir = 1; break;
532     case 0xc000: mnem = "rpcc"; break;
533     case 0xe000: mnem = "rc"; break;
534     case 0xe800: mnem = "ecb"; indir = 1; break;
535     case 0xf000: mnem = "rs"; break;
536     case 0xf800: mnem = "wh64"; indir = 1; break;
537     default:debug("UNIMPLEMENTED opcode 0x%x func 0x%x\n",
538     opcode, func);
539     }
540     if (mnem == NULL)
541     break;
542     debug("%s", mnem);
543     if ((iw & 0xffff) >= 0x8000) {
544     debug("\t");
545     if (indir)
546     debug("(%s)", alpha_regname[rb]);
547     else
548     debug("%s", alpha_regname[ra]);
549     }
550     debug("\n");
551     break;
552     case 0x1a:
553     tmp = iw & 0x3fff;
554     if (tmp & 0x2000)
555     tmp |= 0xffffffffffffc000ULL;
556     tmp <<= 2;
557     tmp += dumpaddr + sizeof(uint32_t);
558     switch ((iw >> 14) & 3) {
559     case 0:
560     case 1: if (((iw >> 14) & 3) == 0)
561     debug("jmp");
562     else
563     debug("jsr");
564     debug("\t%s,", alpha_regname[ra]);
565     debug("(%s),", alpha_regname[rb]);
566     debug("0x%llx", (long long)tmp);
567     symbol = get_symbol_name(&cpu->machine->symbol_context,
568     tmp, &offset);
569     if (symbol != NULL)
570     debug("\t<%s>", symbol);
571     break;
572     case 2: debug("ret");
573     break;
574     default:fatal("unimpl JSR!");
575     }
576     debug("\n");
577     break;
578     case 0x30:
579     case 0x34:
580     tmp = iw & 0x1fffff;
581     if (tmp & 0x100000)
582     tmp |= 0xffffffffffe00000ULL;
583     tmp <<= 2;
584     tmp += dumpaddr + sizeof(uint32_t);
585     debug("%s\t", opcode==0x30? "br" : "bsr");
586     if (ra != ALPHA_ZERO)
587     debug("%s,", alpha_regname[ra]);
588     debug("0x%llx", (long long)tmp);
589     symbol = get_symbol_name(&cpu->machine->symbol_context,
590     tmp, &offset);
591     if (symbol != NULL)
592     debug("\t<%s>", symbol);
593     debug("\n");
594     break;
595     case 0x38:
596     case 0x39:
597     case 0x3a:
598     case 0x3b:
599     case 0x3c:
600     case 0x3d:
601     case 0x3e:
602     case 0x3f:
603     switch (opcode) {
604     case 0x38: mnem = "blbc"; break;
605     case 0x39: mnem = "beq"; break;
606     case 0x3a: mnem = "blt"; break;
607     case 0x3b: mnem = "ble"; break;
608     case 0x3c: mnem = "blbs"; break;
609     case 0x3d: mnem = "bne"; break;
610     case 0x3e: mnem = "bge"; break;
611     case 0x3f: mnem = "bgt"; break;
612     }
613     tmp = iw & 0x1fffff;
614     if (tmp & 0x100000)
615     tmp |= 0xffffffffffe00000ULL;
616     tmp <<= 2;
617     tmp += dumpaddr + sizeof(uint32_t);
618     debug("%s\t%s,", mnem, alpha_regname[ra]);
619     debug("0x%llx", (long long)tmp);
620     symbol = get_symbol_name(&cpu->machine->symbol_context,
621     tmp, &offset);
622     if (symbol != NULL)
623     debug("\t<%s>", symbol);
624     debug("\n");
625     break;
626     default:debug("UNIMPLEMENTED opcode 0x%x\n", opcode);
627     }
628    
629     return sizeof(uint32_t);
630     }
631    
632    
633     #define MEMORY_RW alpha_userland_memory_rw
634     #define MEM_ALPHA
635     #define MEM_USERLAND
636     #include "../memory_rw.c"
637     #undef MEM_USERLAND
638     #undef MEM_ALPHA
639     #undef MEMORY_RW
640    
641    
642     #include "tmp_alpha_tail.c"
643    

  ViewVC Help
Powered by ViewVC 1.1.26