/[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 42 - (hide annotations)
Mon Oct 8 16:22:32 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 18860 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1613 2007/06/15 20:11:26 debug Exp $
20070501	Continuing a little on m88k disassembly (control registers,
		more instructions).
		Adding a dummy mvme88k machine mode.
20070502	Re-adding MIPS load/store alignment exceptions.
20070503	Implementing more of the M88K disassembly code.
20070504	Adding disassembly of some more M88K load/store instructions.
		Implementing some relatively simple M88K instructions (br.n,
		xor[.u] imm, and[.u] imm).
20070505	Implementing M88K three-register and, or, xor, and jmp[.n],
		bsr[.n] including function call trace stuff.
		Applying a patch from Bruce M. Simpson which implements the
		SYSCON_BOARD_CPU_CLOCK_FREQ_ID object of the syscon call in
		the yamon PROM emulation.
20070506	Implementing M88K bb0[.n] and bb1[.n], and skeletons for
		ldcr and stcr (although no control regs are implemented yet).
20070509	Found and fixed the bug which caused Linux for QEMU_MIPS to
		stop working in 0.4.5.1: It was a faulty change to the MIPS
		'sc' and 'scd' instructions I made while going through gcc -W
		warnings on 20070428.
20070510	Updating the Linux/QEMU_MIPS section in guestoses.html to
		use mips-test-0.2.tar.gz instead of 0.1.
		A big thank you to Miod Vallat for sending me M88K manuals.
		Implementing more M88K instructions (addu, subu, div[u], mulu,
		ext[u], clr, set, cmp).
20070511	Fixing bugs in the M88K "and" and "and.u" instructions (found
		by comparing against the manual).
		Implementing more M88K instructions (mask[.u], mak, bcnd (auto-
		generated)) and some more control register details.
		Cleanup: Removing the experimental AVR emulation mode and
		corresponding devices; AVR emulation wasn't really meaningful.
		Implementing autogeneration of most M88K loads/stores. The
		rectangle drawing demo (with -O0) for M88K runs :-)
		Beginning on M88K exception handling.
		More M88K instructions: tb0, tb1, rte, sub, jsr[.n].
		Adding some skeleton MVME PROM ("BUG") emulation.
20070512	Fixing a bug in the M88K cmp instruction.
		Adding the M88K lda (scaled register) instruction.
		Fixing bugs in 64-bit (32-bit pairs) M88K loads/stores.
		Removing the unused tick_hz stuff from the machine struct.
		Implementing the M88K xmem instruction. OpenBSD/mvme88k gets
		far enough to display the Copyright banner :-)
		Implementing subu.co (guess), addu.co, addu.ci, ff0, and ff1.
		Adding a dev_mvme187, for MVME187-specific devices/registers.
		OpenBSD/mvme88k prints more boot messages. :)
20070515	Continuing on MVME187 emulation (adding more devices, beginning
		on the CMMUs, etc).
		Adding the M88K and.c, xor.c, and or.c instructions, and making
		sure that mul, div, etc cause exceptions if executed when SFD1
		is disabled.
20070517	Continuing on M88K and MVME187 emulation in general; moving
		the CMMU registers to the CPU struct, separating dev_pcc2 from
		dev_mvme187, and beginning on memory_m88k.c (BATC and PATC).
		Fixing a bug in 64-bit (32-bit pairs) M88K fast stores.
		Implementing the clock part of dev_mk48txx.
		Implementing the M88K fstcr and xcr instructions.
		Implementing m88k_cpu_tlbdump().
		Beginning on the implementation of a separate address space
		for M88K .usr loads/stores.
20070520	Removing the non-working (skeleton) Sandpoint, SonyNEWS, SHARK
		Dnard, and Zaurus machine modes.
		Experimenting with dyntrans to_be_translated read-ahead. It
		seems to give a very small performance increase for MIPS
		emulation, but a large performance degradation for SuperH. Hm.
20070522	Disabling correct SuperH ITLB emulation; it does not seem to be
		necessary in order to let SH4 guest OSes run, and it slows down
		userspace code.
		Implementing "samepage" branches for SuperH emulation, and some
		other minor speed hacks.
20070525	Continuing on M88K memory-related stuff: exceptions, memory
		transaction register contents, etc.
		Implementing the M88K subu.ci instruction.
		Removing the non-working (skeleton) Iyonix machine mode.
		OpenBSD/mvme88k reaches userland :-), starts executing
		/sbin/init's instructions, and issues a few syscalls, before
		crashing.
20070526	Fixing bugs in dev_mk48txx, so that OpenBSD/mvme88k detects
		the correct time-of-day.
		Implementing a generic IRQ controller for the test machines
		(dev_irqc), similar to a proposed patch from Petr Stepan.
		Experimenting some more with translation read-ahead.
		Adding an "expect" script for automated OpenBSD/landisk
		install regression/performance tests.
20070527	Adding a dummy mmEye (SH3) machine mode skeleton.
		FINALLY found the strange M88K bug I have been hunting: I had
		not emulated the SNIP value for exceptions occurring in
		branch delay slots correctly.
		Implementing correct exceptions for 64-bit M88K loads/stores.
		Address to symbol lookups are now disabled when M88K is
		running in usermode (because usermode addresses don't have
		anything to do with supervisor addresses).
20070531	Removing the mmEye machine mode skeleton.
20070604	Some minor code cleanup.
20070605	Moving src/useremul.c into a subdir (src/useremul/), and
		cleaning up some more legacy constructs.
		Adding -Wstrict-aliasing and -fstrict-aliasing detection to
		the configure script.
20070606	Adding a check for broken GCC on Solaris to the configure
		script. (GCC 3.4.3 on Solaris cannot handle static variables
		which are initialized to 0 or NULL. :-/)
		Removing the old (non-working) ARC emulation modes: NEC RD94,
		R94, R96, and R98, and the last traces of Olivetti M700 and
		Deskstation Tyne.
		Removing the non-working skeleton WDSC device (dev_wdsc).
20070607	Thinking about how to use the host's cc + ld at runtime to
		generate native code. (See experiments/native_cc_ld_test.i
		for an example.)
20070608	Adding a program counter sampling timer, which could be useful
		for native code generation experiments.
		The KN02_CSR_NRMMOD bit in the DECstation 5000/200 (KN02) CSR
		should always be set, to allow a 5000/200 PROM to boot.
20070609	Moving out breakpoint details from the machine struct into
		a helper struct, and removing the limit on max nr of
		breakpoints.
20070610	Moving out tick functions into a helper struct as well (which
		also gets rid of the max limit).
20070612	FINALLY figured out why Debian/DECstation stopped working when
		translation read-ahead was enabled: in src/memory_rw.c, the
		call to invalidate_code_translation was made also if the
		memory access was an instruction load (if the page was mapped
		as writable); it shouldn't be called in that case.
20070613	Implementing some more MIPS32/64 revision 2 instructions: di,
		ei, ext, dext, dextm, dextu, and ins.
20070614	Implementing an instruction combination for the NetBSD/arm
		idle loop (making the host not use any cpu if NetBSD/arm
		inside the emulator is not using any cpu).
		Increasing the nr of ARM VPH entries from 128 to 384.
20070615	Removing the ENABLE_arch stuff from the configure script, so
		that all included architectures are included in both release
		and development builds.
		Moving memory related helper functions from misc.c to memory.c.
		Adding preliminary instructions for netbooting NetBSD/pmppc to
		guestoses.html; it doesn't work yet, there are weird timeouts.
		Beginning a total rewrite of the userland emulation modes
		(removing all emulation modes, beginning from scratch with
		NetBSD/MIPS and FreeBSD/Alpha only).
20070616	After fixing a bug in the DEC21143 NIC (the TDSTAT_OWN bit was
		only cleared for the last segment when transmitting, not all
		segments), NetBSD/pmppc boots with root-on-nfs without the
		timeouts. Updating guestoses.html.
		Removing the skeleton PSP (Playstation Portable) mode.
		Moving X11-related stuff in the machine struct into a helper
		struct.
		Cleanup of out-of-memory checks, to use a new CHECK_ALLOCATION
		macro (which prints a meaningful error message).
		Adding a COMMENT to each machine and device (for automagic
		.index comment generation).
		Doing regression testing for the next release.

==============  RELEASE 0.4.6  ==============


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

  ViewVC Help
Powered by ViewVC 1.1.26