/[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 14 - (hide annotations)
Mon Oct 8 16:18:51 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 17782 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.982 2005/10/07 22:45:32 debug Exp $
20050816	Some success in decoding the way the SGI O2 PROM draws graphics
		during bootup; lines/rectangles and bitmaps work, enough to
		show the bootlogo etc. :-)
		Adding more PPC instructions, and (dummy) BAT registers.
20050817	Updating the pckbc to support scancode type 3 keyboards
		(required in order to interact with the SGI O2 PROM).
		Adding more PPC instructions.
20050818	Adding more ARM instructions; general register forms.
		Importing armreg.h from NetBSD (ARM cpu ids). Adding a (dummy)
		CATS machine mode (using SA110 as the default CPU).
		Continuing on general dyntrans related stuff.
20050819	Register forms for ARM load/stores. Gaah! The Compaq C Compiler
		bug is triggered for ARM loads as well, not just PPC :-(
		Adding full support for ARM PC-relative load/stores, and load/
		stores where the PC register is the destination register.
		Adding support for ARM a.out binaries.
20050820	Continuing to add more ARM instructions, and correcting some
		bugs. Continuing on CATS emulation.
		More work on the PPC stuff.
20050821	Minor PPC and ARM updates. Adding more machine types.
20050822	All ARM "data processing instructions" are now generated
		automatically.
20050824	Beginning the work on the ARM system control coprocessor.
		Adding support for ARM halfword load/stores, and signed loads.
20050825	Fixing an important bug related to the ARM condition codes.
		OpenBSD/zaurus and NetBSD/netwinder now print some boot
		messages. :)
		Adding a dummy SH (Hitachi SuperH) cpu family.
		Beginning to add some ARM virtual address translation.
		MIPS bugfixes: unaligned PC now cause an ADEL exception (at
		least for non-bintrans execution), and ADEL/ADES (not
		TLBL/TLBS) are used if userland tries to access kernel space.
		(Thanks to Joshua Wise for making me aware of these bugs.)
20050827	More work on the ARM emulation, and various other updates.
20050828	More ARM updates.
		Finally taking the time to work on translation invalidation
		(i.e. invalidating translated code mappings when memory is
		written to). Hopefully this doesn't break anything.
20050829	Moving CPU related files from src/ to a new subdir, src/cpus/.
		Moving PROM emulation stuff from src/ to src/promemul/.
		Better debug instruction trace for ARM loads and stores.
20050830	Various ARM updates (correcting CMP flag calculation, etc).
20050831	PPC instruction updates. (Flag fixes, etc.)
20050901	Various minor PPC and ARM instruction emulation updates.
		Minor OpenFirmware emulation updates.
20050903	Adding support for adding arbitrary ARM coprocessors (with
		the i80321 I/O coprocessor as a first test).
		Various other ARM and PPC updates.
20050904	Adding some SHcompact disassembly routines.
20050907	(Re)adding a dummy HPPA CPU module, and a dummy i960 module.
20050908	Began hacking on some Apple Partition Table support.
20050909	Adding support for loading Mach-O (Darwin PPC) binaries.
20050910	Fixing an ARM bug (Carry flag was incorrectly updated for some
		data processing instructions); OpenBSD/cats and NetBSD/
		netwinder get quite a bit further now.
		Applying a patch to dev_wdc, and a one-liner to dev_pcic, to
		make them work better when emulating new versions of OpenBSD.
		(Thanks to Alexander Yurchenko for the patches.)
		Also doing some other minor updates to dev_wdc. (Some cleanup,
		and finally converting to devinit, etc.)
20050912	IRIX doesn't have u_int64_t by default (noticed by Andreas
		<avr@gnulinux.nl>); configure updated to reflect this.
		Working on ARM register bank switching, CPSR vs SPSR issues,
		and beginning the work on interrupt/exception support.
20050913	Various minor ARM updates (speeding up load/store multiple,
		and fixing a ROR bug in R(); NetBSD/cats now boots as far as
		OpenBSD/cats).
20050917	Adding a dummy Atmel AVR (8-bit) cpu family skeleton.
20050918	Various minor updates.
20050919	Symbols are now loaded from Mach-O executables.
		Continuing the work on adding ARM exception support.
20050920	More work on ARM stuff: OpenBSD/cats and NetBSD/cats reach
		userland! :-)
20050921	Some more progress on ARM interrupt specifics.
20050923	Fixing linesize for VR4121 (patch by Yurchenko). Also fixing
		linesizes/cachesizes for some other VR4xxx.
		Adding a dummy Acer Labs M1543 PCI-ISA bridge (for CATS) and a
		dummy Symphony Labs 83C553 bridge (for Netwinder), usable by 
		dev_footbridge.
20050924	Some PPC progress.
20050925	More PPC progress.
20050926	PPC progress (fixing some bugs etc); Darwin's kernel gets
		slightly further than before.
20050928	Various updates: footbridge/ISA/pciide stuff, and finally
		fixing the VGA text scroll-by-changing-the-base-offset bug.
20050930	Adding a dummy S3 ViRGE pci card for CATS emulation, which
		both NetBSD and OpenBSD detects as VGA.
		Continuing on Footbridge (timers, ISA interrupt stuff).
20051001	Continuing... there are still bugs, probably interrupt-
		related.
20051002	More work on the Footbridge (interrupt stuff).
20051003	Various minor updates. (Trying to find the bug(s).)
20051004	Continuing on the ARM stuff.
20051005	More ARM-related fixes.
20051007	FINALLY! Found and fixed 2 ARM bugs: 1 memory related, and the
		other was because of an error in the ARM manual (load multiple
		with the S-bit set should _NOT_ load usermode registers, as the
		manual says, but it should load saved registers, which may or
		may not happen to be usermode registers).
		NetBSD/cats and OpenBSD/cats seem to install fine now :-)
		except for a minor bug at the end of the OpenBSD/cats install.
		Updating the documentation, preparing for the next release.
20051008	Continuing with release testing and cleanup.

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     * $Id: cpu_alpha.c,v 1.1 2005/08/29 14:36:41 debug Exp $
29     *
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     cpu->invalidate_translation_caches_paddr =
75     alpha_invalidate_translation_caches_paddr;
76     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_show_full_statistics():
192     *
193     * Show detailed statistics on opcode usage on each cpu.
194     */
195     void alpha_cpu_show_full_statistics(struct machine *m)
196     {
197     fatal("alpha_cpu_show_full_statistics(): TODO\n");
198     }
199    
200    
201     /*
202     * alpha_cpu_tlbdump():
203     *
204     * Called from the debugger to dump the TLB in a readable format.
205     * x is the cpu number to dump, or -1 to dump all CPUs.
206     *
207     * If rawflag is nonzero, then the TLB contents isn't formated nicely,
208     * just dumped.
209     */
210     void alpha_cpu_tlbdump(struct machine *m, int x, int rawflag)
211     {
212     fatal("alpha_cpu_tlbdump(): TODO\n");
213     }
214    
215    
216     /*
217     * alpha_cpu_interrupt():
218     */
219     int alpha_cpu_interrupt(struct cpu *cpu, uint64_t irq_nr)
220     {
221     fatal("alpha_cpu_interrupt(): TODO\n");
222     return 0;
223     }
224    
225    
226     /*
227     * alpha_cpu_interrupt_ack():
228     */
229     int alpha_cpu_interrupt_ack(struct cpu *cpu, uint64_t irq_nr)
230     {
231     /* fatal("alpha_cpu_interrupt_ack(): TODO\n"); */
232     return 0;
233     }
234    
235    
236     /*
237     * alpha_print_imm16_disp():
238     *
239     * Used internally by alpha_cpu_disassemble_instr().
240     */
241     static void alpha_print_imm16_disp(int imm, int rb)
242     {
243     imm = (int16_t)imm;
244    
245     if (imm < 0) {
246     debug("-");
247     imm = -imm;
248     }
249     if (imm <= 256)
250     debug("%i", imm);
251     else
252     debug("0x%x", imm);
253     if (rb != ALPHA_ZERO)
254     debug("(%s)", alpha_regname[rb]);
255     }
256    
257    
258     /*
259     * alpha_cpu_disassemble_instr():
260     *
261     * Convert an instruction word into human readable format, for instruction
262     * tracing.
263     *
264     * If running is 1, cpu->pc should be the address of the instruction.
265     *
266     * If running is 0, things that depend on the runtime environment (eg.
267     * register contents) will not be shown, and addr will be used instead of
268     * cpu->pc for relative addresses.
269     */
270     int alpha_cpu_disassemble_instr(struct cpu *cpu, unsigned char *ib,
271     int running, uint64_t dumpaddr, int bintrans)
272     {
273     uint32_t iw;
274     uint64_t offset, tmp;
275     int opcode, ra, rb, func, rc, imm, floating, rbrc = 0, indir = 0;
276     char *symbol, *mnem = NULL;
277     char palcode_name[30];
278    
279     if (running)
280     dumpaddr = cpu->pc;
281    
282     symbol = get_symbol_name(&cpu->machine->symbol_context,
283     dumpaddr, &offset);
284     if (symbol != NULL && offset == 0)
285     debug("<%s>\n", symbol);
286    
287     if (cpu->machine->ncpus > 1 && running)
288     debug("cpu%i:\t", cpu->cpu_id);
289    
290     debug("%016llx: ", (long long)dumpaddr);
291    
292     iw = ib[0] + (ib[1]<<8) + (ib[2]<<16) + (ib[3]<<24);
293     debug("%08x\t", (int)iw);
294    
295     opcode = iw >> 26;
296     ra = (iw >> 21) & 31;
297     rb = (iw >> 16) & 31;
298     func = (iw >> 5) & 0x7ff;
299     rc = iw & 31;
300     imm = iw & 0xffff;
301    
302     switch (opcode) {
303     case 0x00:
304     alpha_palcode_name(iw & 0x3ffffff, palcode_name,
305     sizeof(palcode_name));
306     debug("call_pal %s\n", palcode_name);
307     break;
308     case 0x08:
309     case 0x09:
310     debug("lda%s\t%s,", opcode == 9? "h" : "", alpha_regname[ra]);
311     alpha_print_imm16_disp(imm, rb);
312     debug("\n");
313     break;
314     case 0x0a:
315     case 0x0b:
316     case 0x0c:
317     case 0x0d:
318     case 0x0e:
319     case 0x0f:
320     case 0x20:
321     case 0x21:
322     case 0x22:
323     case 0x23:
324     case 0x24:
325     case 0x25:
326     case 0x26:
327     case 0x27:
328     case 0x28:
329     case 0x29:
330     case 0x2a:
331     case 0x2b:
332     case 0x2c:
333     case 0x2d:
334     case 0x2e:
335     case 0x2f:
336     floating = 0;
337     switch (opcode) {
338     case 0x0a: mnem = "ldbu"; break;
339     case 0x0b: mnem = "ldq_u"; break;
340     case 0x0c: mnem = "ldwu"; break;
341     case 0x0d: mnem = "stw"; break;
342     case 0x0e: mnem = "stb"; break;
343     case 0x0f: mnem = "stq_u"; break;
344     case 0x20: mnem = "ldf"; floating = 1; break;
345     case 0x21: mnem = "ldg"; floating = 1; break;
346     case 0x22: mnem = "lds"; floating = 1; break;
347     case 0x23: mnem = "ldt"; floating = 1; break;
348     case 0x24: mnem = "stf"; floating = 1; break;
349     case 0x25: mnem = "stg"; floating = 1; break;
350     case 0x26: mnem = "sts"; floating = 1; break;
351     case 0x27: mnem = "stt"; floating = 1; break;
352     case 0x28: mnem = "ldl"; break;
353     case 0x29: mnem = "ldq"; break;
354     case 0x2a: mnem = "ldl_l"; break;
355     case 0x2b: mnem = "ldq_l"; break;
356     case 0x2c: mnem = "stl"; break;
357     case 0x2d: mnem = "stq"; break;
358     case 0x2e: mnem = "stl_c"; break;
359     case 0x2f: mnem = "stq_c"; break;
360     }
361     if (opcode == 0x0b && ra == ALPHA_ZERO) {
362     debug("unop");
363     } else {
364     debug("%s\t", mnem);
365     if (floating)
366     debug("f%i,", ra);
367     else
368     debug("%s,", alpha_regname[ra]);
369     alpha_print_imm16_disp(imm, rb);
370     }
371     debug("\n");
372     break;
373     case 0x10:
374     switch (func & 0x7f) {
375     case 0x00: mnem = "addl"; break;
376     case 0x02: mnem = "s4addl"; break;
377     case 0x09: mnem = "subl"; break;
378     case 0x0b: mnem = "s4subl"; break;
379     case 0x0f: mnem = "cmpbge"; break;
380     case 0x12: mnem = "s8addl"; break;
381     case 0x1b: mnem = "s8subl"; break;
382     case 0x1d: mnem = "cmpult"; break;
383     case 0x20: mnem = "addq"; break;
384     case 0x22: mnem = "s4addq"; break;
385     case 0x29: mnem = "subq"; break;
386     case 0x2b: mnem = "s4subq"; break;
387     case 0x2d: mnem = "cmpeq"; break;
388     case 0x32: mnem = "s8addq"; break;
389     case 0x3b: mnem = "s8subq"; break;
390     case 0x3d: mnem = "cmpule"; break;
391     case 0x40: mnem = "addl/v"; break;
392     case 0x49: mnem = "subl/v"; break;
393     case 0x4d: mnem = "cmplt"; break;
394     case 0x60: mnem = "addq/v"; break;
395     case 0x69: mnem = "subq/v"; break;
396     case 0x6d: mnem = "cmple"; break;
397     default:debug("UNIMPLEMENTED opcode 0x%x func 0x%x\n",
398     opcode, func);
399     }
400     if (mnem == NULL)
401     break;
402     if (func & 0x80)
403     debug("%s\t%s,0x%x,%s\n", mnem,
404     alpha_regname[ra], (rb << 3) + (func >> 8),
405     alpha_regname[rc]);
406     else
407     debug("%s\t%s,%s,%s\n", mnem, alpha_regname[ra],
408     alpha_regname[rb], alpha_regname[rc]);
409     break;
410     case 0x11:
411     switch (func & 0x7f) {
412     case 0x000: mnem = "and"; break;
413     case 0x008: mnem = "andnot"; break;
414     case 0x014: mnem = "cmovlbs"; break;
415     case 0x016: mnem = "cmovlbc"; break;
416     case 0x020: mnem = "or"; break;
417     case 0x024: mnem = "cmoveq"; break;
418     case 0x026: mnem = "cmovne"; break;
419     case 0x028: mnem = "ornot"; break;
420     case 0x040: mnem = "xor"; break;
421     case 0x044: mnem = "cmovlt"; break;
422     case 0x046: mnem = "cmovge"; break;
423     case 0x048: mnem = "eqv"; break;
424     case 0x061: mnem = "amask"; break;
425     case 0x064: mnem = "cmovle"; break;
426     case 0x066: mnem = "cmovgt"; break;
427     default:debug("UNIMPLEMENTED opcode 0x%x func 0x%x\n",
428     opcode, func);
429     }
430     if (mnem == NULL)
431     break;
432     /* Special cases: "nop" etc: */
433     if (func == 0x020 && rc == ALPHA_ZERO)
434     debug("nop\n");
435     else if (func == 0x020 && (ra == ALPHA_ZERO
436     || rb == ALPHA_ZERO)) {
437     if (ra == ALPHA_ZERO && rb == ALPHA_ZERO)
438     debug("clr\t%s\n", alpha_regname[rc]);
439     else if (ra == ALPHA_ZERO)
440     debug("mov\t%s,%s\n", alpha_regname[rb],
441     alpha_regname[rc]);
442     else
443     debug("mov\t%s,%s\n", alpha_regname[ra],
444     alpha_regname[rc]);
445     } else if (func & 0x80)
446     debug("%s\t%s,0x%x,%s\n", mnem,
447     alpha_regname[ra], (rb << 3) + (func >> 8),
448     alpha_regname[rc]);
449     else
450     debug("%s\t%s,%s,%s\n", mnem, alpha_regname[ra],
451     alpha_regname[rb], alpha_regname[rc]);
452     break;
453     case 0x12:
454     switch (func & 0x7f) {
455     case 0x02: mnem = "mskbl"; break;
456     case 0x06: mnem = "extbl"; break;
457     case 0x0b: mnem = "insbl"; break;
458     case 0x12: mnem = "mskwl"; break;
459     case 0x16: mnem = "extwl"; break;
460     case 0x1b: mnem = "inswl"; break;
461     case 0x22: mnem = "mskll"; break;
462     case 0x26: mnem = "extll"; break;
463     case 0x2b: mnem = "insll"; break;
464     case 0x30: mnem = "zap"; break;
465     case 0x31: mnem = "zapnot"; break;
466     case 0x32: mnem = "mskql"; break;
467     case 0x34: mnem = "srl"; break;
468     case 0x36: mnem = "extql"; break;
469     case 0x39: mnem = "sll"; break;
470     case 0x3b: mnem = "insql"; break;
471     case 0x3c: mnem = "sra"; break;
472     case 0x52: mnem = "mskwh"; break;
473     case 0x57: mnem = "inswh"; break;
474     case 0x5a: mnem = "extwh"; break;
475     case 0x62: mnem = "msklh"; break;
476     case 0x67: mnem = "inslh"; break;
477     case 0x6a: mnem = "extlh"; break;
478     case 0x72: mnem = "mskqh"; break;
479     case 0x77: mnem = "insqh"; break;
480     case 0x7a: mnem = "extqh"; break;
481     default:debug("UNIMPLEMENTED opcode 0x%x func 0x%x\n",
482     opcode, func);
483     }
484     if (mnem == NULL)
485     break;
486     if (func & 0x80)
487     debug("%s\t%s,0x%x,%s\n", mnem,
488     alpha_regname[ra], (rb << 3) + (func >> 8),
489     alpha_regname[rc]);
490     else
491     debug("%s\t%s,%s,%s\n", mnem, alpha_regname[ra],
492     alpha_regname[rb], alpha_regname[rc]);
493     break;
494     case 0x13:
495     switch (func & 0x7f) {
496     case 0x00: mnem = "mull"; break;
497     case 0x20: mnem = "mulq"; break;
498     case 0x30: mnem = "umulh"; break;
499     case 0x40: mnem = "mull/v"; break;
500     case 0x60: mnem = "mulq/v"; break;
501     default:debug("UNIMPLEMENTED opcode 0x%x func 0x%x\n",
502     opcode, func);
503     }
504     if (mnem == NULL)
505     break;
506     if (func & 0x80)
507     debug("%s\t%s,0x%x,%s\n", mnem,
508     alpha_regname[ra], (rb << 3) + (func >> 8),
509     alpha_regname[rc]);
510     else
511     debug("%s\t%s,%s,%s\n", mnem, alpha_regname[ra],
512     alpha_regname[rb], alpha_regname[rc]);
513     break;
514     case 0x16:
515     switch (func & 0x7ff) {
516     case 0x080: mnem = "adds"; break;
517     case 0x081: mnem = "subs"; break;
518     case 0x082: mnem = "muls"; break;
519     case 0x083: mnem = "mult"; break;
520     case 0x0a0: mnem = "addt"; break;
521     case 0x0a1: mnem = "subt"; break;
522     case 0x0a2: mnem = "mult"; break;
523     case 0x0a3: mnem = "divt"; break;
524     case 0x0be: mnem = "cvtqt"; rbrc = 1; break;
525     default:debug("UNIMPLEMENTED opcode 0x%x func 0x%x\n",
526     opcode, func);
527     }
528     if (mnem == NULL)
529     break;
530     if (rbrc)
531     debug("%s\tf%i,f%i\n", mnem, rb, rc);
532     else
533     debug("%s\tf%i,f%i,f%i\n", mnem, ra, rb, rc);
534     break;
535     case 0x17:
536     switch (func & 0x7ff) {
537     case 0x020: mnem = "fabs"; rbrc = 1; break;
538     default:debug("UNIMPLEMENTED opcode 0x%x func 0x%x\n",
539     opcode, func);
540     }
541     if (mnem == NULL)
542     break;
543     if ((func & 0x7ff) == 0x020 && ra == 31 && rb == 31)
544     debug("fclr\tf%i\n", rc);
545     else if (rbrc)
546     debug("%s\tf%i,f%i\n", mnem, rb, rc);
547     else
548     debug("%s\tf%i,f%i,f%i\n", mnem, ra, rb, rc);
549     break;
550     case 0x18:
551     switch (iw & 0xffff) {
552     case 0x0000: mnem = "trapb"; break;
553     case 0x0400: mnem = "excb"; break;
554     case 0x4000: mnem = "mb"; break;
555     case 0x4400: mnem = "wmb"; break;
556     case 0x8000: mnem = "fetch"; indir = 1; break;
557     case 0xa000: mnem = "fetch_m"; indir = 1; break;
558     case 0xc000: mnem = "rpcc"; break;
559     case 0xe000: mnem = "rc"; break;
560     case 0xe800: mnem = "ecb"; indir = 1; break;
561     case 0xf000: mnem = "rs"; break;
562     case 0xf800: mnem = "wh64"; indir = 1; break;
563     default:debug("UNIMPLEMENTED opcode 0x%x func 0x%x\n",
564     opcode, func);
565     }
566     if (mnem == NULL)
567     break;
568     debug("%s", mnem);
569     if ((iw & 0xffff) >= 0x8000) {
570     debug("\t");
571     if (indir)
572     debug("(%s)", alpha_regname[rb]);
573     else
574     debug("%s", alpha_regname[ra]);
575     }
576     debug("\n");
577     break;
578     case 0x1a:
579     tmp = iw & 0x3fff;
580     if (tmp & 0x2000)
581     tmp |= 0xffffffffffffc000ULL;
582     tmp <<= 2;
583     tmp += dumpaddr + sizeof(uint32_t);
584     switch ((iw >> 14) & 3) {
585     case 0:
586     case 1: if (((iw >> 14) & 3) == 0)
587     debug("jmp");
588     else
589     debug("jsr");
590     debug("\t%s,", alpha_regname[ra]);
591     debug("(%s),", alpha_regname[rb]);
592     debug("0x%llx", (long long)tmp);
593     symbol = get_symbol_name(&cpu->machine->symbol_context,
594     tmp, &offset);
595     if (symbol != NULL)
596     debug("\t<%s>", symbol);
597     break;
598     case 2: debug("ret");
599     break;
600     default:fatal("unimpl JSR!");
601     }
602     debug("\n");
603     break;
604     case 0x30:
605     case 0x34:
606     tmp = iw & 0x1fffff;
607     if (tmp & 0x100000)
608     tmp |= 0xffffffffffe00000ULL;
609     tmp <<= 2;
610     tmp += dumpaddr + sizeof(uint32_t);
611     debug("%s\t", opcode==0x30? "br" : "bsr");
612     if (ra != ALPHA_ZERO)
613     debug("%s,", alpha_regname[ra]);
614     debug("0x%llx", (long long)tmp);
615     symbol = get_symbol_name(&cpu->machine->symbol_context,
616     tmp, &offset);
617     if (symbol != NULL)
618     debug("\t<%s>", symbol);
619     debug("\n");
620     break;
621     case 0x38:
622     case 0x39:
623     case 0x3a:
624     case 0x3b:
625     case 0x3c:
626     case 0x3d:
627     case 0x3e:
628     case 0x3f:
629     switch (opcode) {
630     case 0x38: mnem = "blbc"; break;
631     case 0x39: mnem = "beq"; break;
632     case 0x3a: mnem = "blt"; break;
633     case 0x3b: mnem = "ble"; break;
634     case 0x3c: mnem = "blbs"; break;
635     case 0x3d: mnem = "bne"; break;
636     case 0x3e: mnem = "bge"; break;
637     case 0x3f: mnem = "bgt"; break;
638     }
639     tmp = iw & 0x1fffff;
640     if (tmp & 0x100000)
641     tmp |= 0xffffffffffe00000ULL;
642     tmp <<= 2;
643     tmp += dumpaddr + sizeof(uint32_t);
644     debug("%s\t%s,", mnem, alpha_regname[ra]);
645     debug("0x%llx", (long long)tmp);
646     symbol = get_symbol_name(&cpu->machine->symbol_context,
647     tmp, &offset);
648     if (symbol != NULL)
649     debug("\t<%s>", symbol);
650     debug("\n");
651     break;
652     default:debug("UNIMPLEMENTED opcode 0x%x\n", opcode);
653     }
654    
655     return sizeof(uint32_t);
656     }
657    
658    
659     #define MEMORY_RW alpha_userland_memory_rw
660     #define MEM_ALPHA
661     #define MEM_USERLAND
662     #include "../memory_rw.c"
663     #undef MEM_USERLAND
664     #undef MEM_ALPHA
665     #undef MEMORY_RW
666    
667    
668     #include "tmp_alpha_tail.c"
669    

  ViewVC Help
Powered by ViewVC 1.1.26