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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 12 - (hide annotations)
Mon Oct 8 16:18:38 2007 UTC (12 years, 3 months ago) by dpavlin
File MIME type: text/plain
File size: 18056 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.905 2005/08/16 09:16:24 debug Exp $
20050628	Continuing the work on the ARM translation engine. end_of_page
		works. Experimenting with load/store translation caches
		(virtual -> physical -> host).
20050629	More ARM stuff (memory access translation cache, mostly). This
		might break a lot of stuff elsewhere, probably some MIPS-
		related translation things.
20050630	Many load/stores are now automatically generated and included
		into cpu_arm_instr.c; 1024 functions in total (!).
		Fixes based on feedback from Alec Voropay: only print 8 hex
		digits instead of 16 in some cases when emulating 32-bit
		machines; similar 8 vs 16 digit fix for breakpoint addresses;
		4Kc has 16 TLB entries, not 48; the MIPS config select1
		register is now printed with "reg ,0".
		Also changing many other occurances of 16 vs 8 digit output.
		Adding cache associativity fields to mips_cpu_types.h; updating
		some other cache fields; making the output of
		mips_cpu_dumpinfo() look nicer.
		Generalizing the bintrans stuff for device accesses to also
		work with the new translation system. (This might also break
		some MIPS things.)
		Adding multi-load/store instructions to the ARM disassembler
		and the translator, and some optimizations of various kinds.
20050701	Adding a simple dev_disk (it can read/write sectors from
		disk images).
20050712	Adding dev_ether (a simple ethernet send/receive device).
		Debugger command "ninstrs" for toggling show_nr_of_instructions
		during runtime.
		Removing the framebuffer logo.
20050713	Continuing on dev_ether.
		Adding a dummy cpu_alpha (again).
20050714	More work on cpu_alpha.
20050715	More work on cpu_alpha. Many instructions work, enough to run
		a simple framebuffer fill test (similar to the ARM test).
20050716	More Alpha stuff.
20050717	Minor updates (Alpha stuff).
20050718	Minor updates (Alpha stuff).
20050719	Generalizing some Alpha instructions.
20050720	More Alpha-related updates.
20050721	Continuing on cpu_alpha. Importing rpb.h from NetBSD/alpha.
20050722	Alpha-related updates: userland stuff (Hello World using
		write() compiled statically for FreeBSD/Alpha runs fine), and
		more instructions are now implemented.
20050723	Fixing ldq_u and stq_u.
		Adding more instructions (conditional moves, masks, extracts,
		shifts).
20050724	More FreeBSD/Alpha userland stuff, and adding some more
		instructions (inserts).
20050725	Continuing on the Alpha stuff. (Adding dummy ldt/stt.)
		Adding a -A command line option to turn off alignment checks
		in some cases (for translated code).
		Trying to remove the old bintrans code which updated the pc
		and nr_of_executed_instructions for every instruction.
20050726	Making another attempt att removing the pc/nr of instructions
		code. This time it worked, huge performance increase for
		artificial test code, but performance loss for real-world
		code :-( so I'm scrapping that code for now.
		Tiny performance increase on Alpha (by using ret instead of
		jmp, to play nice with the Alpha's branch prediction) for the
		old MIPS bintrans backend.
20050727	Various minor fixes and cleanups.
20050728	Switching from a 2-level virtual to host/physical translation
		system for ARM emulation, to a 1-level translation.
		Trying to switch from 2-level to 1-level for the MIPS bintrans
		system as well (Alpha only, so far), but there is at least one
		problem: caches and/or how they work with device mappings.
20050730	Doing the 2-level to 1-level conversion for the i386 backend.
		The cache/device bug is still there for R2K/3K :(
		Various other minor updates (Malta etc).
		The mc146818 clock now updates the UIP bit in a way which works
		better with Linux for at least sgimips and Malta emulation.
		Beginning the work on refactoring the dyntrans system.
20050731	Continuing the dyntrans refactoring.
		Fixing a small but serious host alignment bug in memory_rw.
		Adding support for big-endian load/stores to the i386 bintrans
		backend.
		Another minor i386 bintrans backend update: stores from the
		zero register are now one (or two) loads shorter.
		The slt and sltu instructions were incorrectly implemented for
		the i386 backend; only using them for 32-bit mode for now.
20050801	Continuing the dyntrans refactoring.
		Cleanup of the ns16550 serial controller (removing unnecessary
		code).
		Bugfix (memory corruption bug) in dev_gt, and a patch/hack from
		Alec Voropay for Linux/Malta.
20050802	More cleanup/refactoring of the dyntrans subsystem: adding
		phys_page pointers to the lookup tables, for quick jumps
		between translated pages.
		Better fix for the ns16550 device (but still no real FIFO
		functionality).
		Converting cpu_ppc to the new dyntrans system. This means that
		I will have to start from scratch with implementing each
		instruction, and figure out how to implement dual 64/32-bit
		modes etc.
		Removing the URISC CPU family, because it was useless.
20050803	When selecting a machine type, the main type can now be omitted
		if the subtype name is unique. (I.e. -E can be omitted.)
		Fixing a dyntrans/device update bug. (Writes to offset 0 of
		a device could sometimes go unnoticed.)
		Adding an experimental "instruction combination" hack for
		ARM for memset-like byte fill loops.
20050804	Minor progress on cpu_alpha and related things.
		Finally fixing the MIPS dmult/dmultu bugs.
		Fixing some minor TODOs.
20050805	Generalizing the 8259 PIC. It now also works with Cobalt
		and evbmips emulation, in addition to the x86 hack.
		Finally converting the ns16550 device to use devinit.
		Continuing the work on the dyntrans system. Thinking about
		how to add breakpoints.
20050806	More dyntrans updates. Breakpoints seem to work now.
20050807	Minor updates: cpu_alpha and related things; removing
		dev_malta (as it isn't used any more).
		Dyntrans: working on general "show trace tree" support.
		The trace tree stuff now works with both the old MIPS code and
		with newer dyntrans modes. :)
		Continuing on Alpha-related stuff (trying to get *BSD to boot
		a bit further, adding more instructions, etc).
20050808	Adding a dummy IA64 cpu family, and continuing the refactoring
		of the dyntrans system.
		Removing the regression test stuff, because it was more or
		less useless.
		Adding loadlinked/storeconditional type instructions to the
		Alpha emulation. (Needed for Linux/alpha. Not very well tested
		yet.)
20050809	The function call trace tree now prints a per-function nr of
		arguments. (Semi-meaningless, since that data isn't read yet
		from the ELFs; some hardcoded symbols such as memcpy() and
		strlen() work fine, though.)
		More dyntrans refactoring; taking out more of the things that
		are common to all cpu families.
20050810	Working on adding support for "dual mode" for PPC dyntrans
		(i.e. both 64-bit and 32-bit modes).
		(Re)adding some simple PPC instructions.
20050811	Adding a dummy M68K cpu family. The dyntrans system isn't ready
		for variable-length ISAs yet, so it's completely bogus so far.
		Re-adding more PPC instructions.
		Adding a hack to src/file.c which allows OpenBSD/mac68k a.out
		kernels to be loaded.
		Beginning to add PPC loads/stores. So far they only work in
		32-bit mode.
20050812	The configure file option "add_remote" now accepts symbolic
		host names, in addition to numeric IPv4 addresses.
		Re-adding more PPC instructions.
20050814	Continuing to port back more PPC instructions.
		Found and fixed the cache/device write-update bug for 32-bit
		MIPS bintrans. :-)
		Triggered a really weird and annoying bug in Compaq's C
		compiler; ccc sometimes outputs code which loads from an
		address _before_ checking whether the pointer was NULL or not.
		(I'm not sure how to handle this problem.)
20050815	Removing all of the old x86 instruction execution code; adding
		a new (dummy) dyntrans module for x86.
		Taking the first steps to extend the dyntrans system to support
		variable-length instructions.
		Slowly preparing for the next release.
20050816	Adding a dummy SPARC cpu module.
		Minor updates (documentation etc) for the release.

==============  RELEASE 0.3.5  ==============


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

  ViewVC Help
Powered by ViewVC 1.1.26