/[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 28 - (hide annotations)
Mon Oct 8 16:20:26 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 20143 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1298 2006/07/22 11:27:46 debug Exp $
20060626	Continuing on SPARC emulation (beginning on the 'save'
		instruction, register windows, etc).
20060629	Planning statistics gathering (new -s command line option),
		and renaming speed_tricks to allow_instruction_combinations.
20060630	Some minor manual page updates.
		Various cleanups.
		Implementing the -s command line option.
20060701	FINALLY found the bug which prevented Linux and Ultrix from
		running without the ugly hack in the R2000/R3000 cache isol
		code; it was the phystranslation hint array which was buggy.
		Removing the phystranslation hint code completely, for now.
20060702	Minor dyntrans cleanups; invalidation of physpages now only
		invalidate those parts of a page that have actually been
		translated. (32 parts per page.)
		Some MIPS non-R3000 speed fixes.
		Experimenting with MIPS instruction combination for some
		addiu+bne+sw loops, and sw+sw+sw.
		Adding support (again) for larger-than-4KB pages in MIPS tlbw*.
		Continuing on SPARC emulation: adding load/store instructions.
20060704	Fixing a virtual vs physical page shift bug in the new tlbw*
		implementation. Problem noticed by Jakub Jermar. (Many thanks.)
		Moving rfe and eret to cpu_mips_instr.c, since that is the
		only place that uses them nowadays.
20060705	Removing the BSD license from the "testmachine" include files,
		placing them in the public domain instead; this enables the
		testmachine stuff to be used from projects which are
		incompatible with the BSD license for some reason.
20060707	Adding instruction combinations for the R2000/R3000 L1
		I-cache invalidation code used by NetBSD/pmax 3.0, lui+addiu,
		various branches followed by addiu or nop, and jr ra followed
		by addiu. The time it takes to perform a full NetBSD/pmax R3000
		install on the laptop has dropped from 573 seconds to 539. :-)
20060708	Adding a framebuffer controller device (dev_fbctrl), which so
		far can be used to change the fb resolution during runtime, but
		in the future will also be useful for accelerated block fill/
		copy, and possibly also simplified character output.
		Adding an instruction combination for NetBSD/pmax' strlen.
20060709	Minor fixes: reading raw files in src/file.c wasn't memblock
		aligned, removing buggy multi_sw MIPS instruction combination,
		etc.
20060711	Adding a machine_qemu.c, which contains a "qemu_mips" machine.
		(It mimics QEMU's MIPS machine mode, so that a test kernel
		made for QEMU_MIPS also can run in GXemul... at least to some
		extent.)  Adding a short section about how to run this mode to
		doc/guestoses.html.
20060714	Misc. minor code cleanups.
20060715	Applying a patch which adds getchar() to promemul/yamon.c
		(from Oleksandr Tymoshenko).
		Adding yamon.h from NetBSD, and rewriting yamon.c to use it
		(instead of ugly hardcoded numbers) + some cleanup.
20060716	Found and fixed the bug which broke single-stepping of 64-bit
		programs between 0.4.0 and 0.4.0.1 (caused by too quick
		refactoring and no testing). Hopefully this fix will not
		break too many other things.
20060718	Continuing on the 8253 PIT; it now works with Linux/QEMU_MIPS.
		Re-adding the sw+sw+sw instr comb (the problem was that I had
		ignored endian issues); however, it doesn't seem to give any
		big performance gain.
20060720	Adding a dummy Transputer mode (T414, T800 etc) skeleton (only
		the 'j' and 'ldc' instructions are implemented so far). :-}
20060721	Adding gtreg.h from NetBSD, updating dev_gt.c to use it, plus
		misc. other updates to get Linux 2.6 for evbmips/malta working
		(thanks to Alec Voropay for the details).
		FINALLY found and fixed the bug which made tlbw* for non-R3000
		buggy; it was a reference count problem in the dyntrans core.
20060722	Testing stuff; things seem stable enough for a new release.

==============  RELEASE 0.4.1  ==============


1 dpavlin 14 /*
2 dpavlin 22 * Copyright (C) 2005-2006 Anders Gavare. All rights reserved.
3 dpavlin 14 *
4     * Redistribution and use in source and binary forms, with or without
5     * modification, are permitted provided that the following conditions are met:
6     *
7     * 1. Redistributions of source code must retain the above copyright
8     * notice, this list of conditions and the following disclaimer.
9     * 2. Redistributions in binary form must reproduce the above copyright
10     * notice, this list of conditions and the following disclaimer in the
11     * documentation and/or other materials provided with the distribution.
12     * 3. The name of the author may not be used to endorse or promote products
13     * derived from this software without specific prior written permission.
14     *
15     * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16     * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17     * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18     * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19     * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20     * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21     * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22     * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23     * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24     * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25     * SUCH DAMAGE.
26     *
27     *
28 dpavlin 28 * $Id: cpu_alpha.c,v 1.19 2006/07/20 21:52:59 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 dpavlin 24 int i = 0;
68     struct alpha_cpu_type_def cpu_type_defs[] = ALPHA_CPU_TYPE_DEFS;
69 dpavlin 14
70 dpavlin 24 /* Scan the cpu_type_defs list for this cpu type: */
71     while (cpu_type_defs[i].name != NULL) {
72     if (strcasecmp(cpu_type_defs[i].name, cpu_type_name) == 0) {
73     break;
74     }
75     i++;
76     }
77     if (cpu_type_defs[i].name == NULL)
78 dpavlin 14 return 0;
79    
80     cpu->memory_rw = alpha_memory_rw;
81 dpavlin 28 cpu->run_instr = alpha_run_instr;
82 dpavlin 26 cpu->translate_v2p = alpha_translate_v2p;
83 dpavlin 14 cpu->update_translation_table = alpha_update_translation_table;
84 dpavlin 18 cpu->invalidate_translation_caches =
85     alpha_invalidate_translation_caches;
86 dpavlin 14 cpu->invalidate_code_translation = alpha_invalidate_code_translation;
87     cpu->is_32bit = 0;
88    
89     /* Only show name and caches etc for CPU nr 0: */
90     if (cpu_id == 0) {
91     debug("%s", cpu->name);
92     }
93    
94     cpu->cd.alpha.r[ALPHA_SP] = 0xfffffc000000ff00ULL;
95    
96     return 1;
97     }
98    
99    
100     /*
101     * alpha_cpu_dumpinfo():
102     */
103     void alpha_cpu_dumpinfo(struct cpu *cpu)
104     {
105     /* TODO */
106     debug("\n");
107     }
108    
109    
110     /*
111     * alpha_cpu_list_available_types():
112     *
113     * Print a list of available Alpha CPU types.
114     */
115     void alpha_cpu_list_available_types(void)
116     {
117 dpavlin 24 int i, j;
118     struct alpha_cpu_type_def tdefs[] = ALPHA_CPU_TYPE_DEFS;
119 dpavlin 14
120 dpavlin 24 i = 0;
121     while (tdefs[i].name != NULL) {
122     debug("%s", tdefs[i].name);
123 dpavlin 28 for (j=13 - strlen(tdefs[i].name); j>0; j--)
124 dpavlin 24 debug(" ");
125     i++;
126     if ((i % 4) == 0 || tdefs[i].name == NULL)
127     debug("\n");
128     }
129 dpavlin 14 }
130    
131    
132     /*
133     * alpha_cpu_register_match():
134     */
135     void alpha_cpu_register_match(struct machine *m, char *name,
136     int writeflag, uint64_t *valuep, int *match_register)
137     {
138     int i, cpunr = 0;
139    
140     /* CPU number: */
141    
142     /* TODO */
143    
144     if (strcasecmp(name, "pc") == 0) {
145     if (writeflag) {
146     m->cpus[cpunr]->pc = *valuep;
147     } else
148     *valuep = m->cpus[cpunr]->pc;
149     *match_register = 1;
150     }
151    
152     /* Register names: */
153     for (i=0; i<N_ALPHA_REGS; i++) {
154     if (strcasecmp(name, alpha_regname[i]) == 0) {
155     if (writeflag)
156     m->cpus[cpunr]->cd.alpha.r[i] = *valuep;
157     else
158     *valuep = m->cpus[cpunr]->cd.alpha.r[i];
159     *match_register = 1;
160     }
161     }
162     }
163    
164    
165     /*
166     * alpha_cpu_register_dump():
167     *
168     * Dump cpu registers in a relatively readable format.
169     *
170     * gprs: set to non-zero to dump GPRs and some special-purpose registers.
171     * coprocs: set bit 0..3 to dump registers in coproc 0..3.
172     */
173     void alpha_cpu_register_dump(struct cpu *cpu, int gprs, int coprocs)
174     {
175     char *symbol;
176     uint64_t offset;
177     int i, x = cpu->cpu_id;
178    
179     if (gprs) {
180     symbol = get_symbol_name(&cpu->machine->symbol_context,
181     cpu->pc, &offset);
182 dpavlin 24 debug("cpu%i:\t pc = 0x%016"PRIx64, x, (uint64_t) cpu->pc);
183 dpavlin 14 debug(" <%s>\n", symbol != NULL? symbol : " no symbol ");
184     for (i=0; i<N_ALPHA_REGS; i++) {
185     int r = (i >> 1) + ((i & 1) << 4);
186     if ((i % 2) == 0)
187     debug("cpu%i:\t", x);
188     if (r != ALPHA_ZERO)
189 dpavlin 24 debug("%3s = 0x%016"PRIx64, alpha_regname[r],
190     (uint64_t) cpu->cd.alpha.r[r]);
191 dpavlin 14 debug((i % 2) == 1? "\n" : " ");
192     }
193     }
194     }
195    
196    
197     /*
198 dpavlin 24 * alpha_cpu_tlbdump():
199     *
200     * Called from the debugger to dump the TLB in a readable format.
201     * x is the cpu number to dump, or -1 to dump all CPUs.
202     *
203     * If rawflag is nonzero, then the TLB contents isn't formated nicely,
204     * just dumped.
205     */
206     void alpha_cpu_tlbdump(struct machine *m, int x, int rawflag)
207     {
208     }
209    
210    
211     static void add_response_word(struct cpu *cpu, char *r, uint64_t value,
212     size_t maxlen, int len)
213     {
214     char *format = (len == 4)? "%08"PRIx64 : "%016"PRIx64;
215     if (len == 4)
216     value &= 0xffffffffULL;
217     if (cpu->byte_order == EMUL_LITTLE_ENDIAN) {
218     if (len == 4) {
219     value = ((value & 0xff) << 24) +
220     ((value & 0xff00) << 8) +
221     ((value & 0xff0000) >> 8) +
222     ((value & 0xff000000) >> 24);
223     } else {
224     value = ((value & 0xff) << 56) +
225     ((value & 0xff00) << 40) +
226     ((value & 0xff0000) << 24) +
227     ((value & 0xff000000ULL) << 8) +
228     ((value & 0xff00000000ULL) >> 8) +
229     ((value & 0xff0000000000ULL) >> 24) +
230     ((value & 0xff000000000000ULL) >> 40) +
231     ((value & 0xff00000000000000ULL) >> 56);
232     }
233     }
234     snprintf(r + strlen(r), maxlen - strlen(r), format, (uint64_t)value);
235     }
236    
237    
238     /*
239     * alpha_cpu_gdb_stub():
240     *
241     * Execute a "remote GDB" command. Returns a newly allocated response string
242     * on success, NULL on failure.
243     */
244     char *alpha_cpu_gdb_stub(struct cpu *cpu, char *cmd)
245     {
246     if (strcmp(cmd, "g") == 0) {
247     int i;
248     char *r;
249     size_t wlen = cpu->is_32bit?
250     sizeof(uint32_t) : sizeof(uint64_t);
251     size_t len = 1 + 76 * wlen;
252     r = malloc(len);
253     if (r == NULL) {
254     fprintf(stderr, "out of memory\n");
255     exit(1);
256     }
257     r[0] = '\0';
258     for (i=0; i<128; i++)
259     add_response_word(cpu, r, i, len, wlen);
260     return r;
261     }
262    
263     if (cmd[0] == 'p') {
264     int regnr = strtol(cmd + 1, NULL, 16);
265     size_t wlen = cpu->is_32bit?
266     sizeof(uint32_t) : sizeof(uint64_t);
267     size_t len = 2 * wlen + 1;
268     char *r = malloc(len);
269     r[0] = '\0';
270     if (regnr >= 0 && regnr <= 31) {
271     add_response_word(cpu, r,
272     cpu->cd.alpha.r[regnr], len, wlen);
273     } else if (regnr >= 32 && regnr <= 62) {
274     add_response_word(cpu, r,
275     cpu->cd.alpha.f[regnr - 32], len, wlen);
276     } else if (regnr == 0x3f) {
277     add_response_word(cpu, r, cpu->cd.alpha.fpcr,
278     len, wlen);
279     } else if (regnr == 0x40) {
280     add_response_word(cpu, r, cpu->pc, len, wlen);
281     } else {
282     /* Unimplemented: */
283     add_response_word(cpu, r, 0xcc000 + regnr, len, wlen);
284     }
285     return r;
286     }
287    
288     fatal("alpha_cpu_gdb_stub(): TODO\n");
289     return NULL;
290     }
291    
292    
293     /*
294 dpavlin 14 * alpha_cpu_interrupt():
295     */
296     int alpha_cpu_interrupt(struct cpu *cpu, uint64_t irq_nr)
297     {
298     fatal("alpha_cpu_interrupt(): TODO\n");
299     return 0;
300     }
301    
302    
303     /*
304     * alpha_cpu_interrupt_ack():
305     */
306     int alpha_cpu_interrupt_ack(struct cpu *cpu, uint64_t irq_nr)
307     {
308     /* fatal("alpha_cpu_interrupt_ack(): TODO\n"); */
309     return 0;
310     }
311    
312    
313     /*
314     * alpha_print_imm16_disp():
315     *
316     * Used internally by alpha_cpu_disassemble_instr().
317     */
318     static void alpha_print_imm16_disp(int imm, int rb)
319     {
320     imm = (int16_t)imm;
321    
322     if (imm < 0) {
323     debug("-");
324     imm = -imm;
325     }
326     if (imm <= 256)
327     debug("%i", imm);
328     else
329     debug("0x%x", imm);
330     if (rb != ALPHA_ZERO)
331     debug("(%s)", alpha_regname[rb]);
332     }
333    
334    
335     /*
336     * alpha_cpu_disassemble_instr():
337     *
338     * Convert an instruction word into human readable format, for instruction
339     * tracing.
340     *
341     * If running is 1, cpu->pc should be the address of the instruction.
342     *
343     * If running is 0, things that depend on the runtime environment (eg.
344     * register contents) will not be shown, and addr will be used instead of
345     * cpu->pc for relative addresses.
346     */
347     int alpha_cpu_disassemble_instr(struct cpu *cpu, unsigned char *ib,
348 dpavlin 24 int running, uint64_t dumpaddr)
349 dpavlin 14 {
350     uint32_t iw;
351     uint64_t offset, tmp;
352     int opcode, ra, rb, func, rc, imm, floating, rbrc = 0, indir = 0;
353     char *symbol, *mnem = NULL;
354     char palcode_name[30];
355    
356     if (running)
357     dumpaddr = cpu->pc;
358    
359     symbol = get_symbol_name(&cpu->machine->symbol_context,
360     dumpaddr, &offset);
361     if (symbol != NULL && offset == 0)
362     debug("<%s>\n", symbol);
363    
364     if (cpu->machine->ncpus > 1 && running)
365     debug("cpu%i:\t", cpu->cpu_id);
366    
367 dpavlin 24 debug("%016"PRIx64": ", (uint64_t) dumpaddr);
368 dpavlin 14
369     iw = ib[0] + (ib[1]<<8) + (ib[2]<<16) + (ib[3]<<24);
370     debug("%08x\t", (int)iw);
371    
372     opcode = iw >> 26;
373     ra = (iw >> 21) & 31;
374     rb = (iw >> 16) & 31;
375     func = (iw >> 5) & 0x7ff;
376     rc = iw & 31;
377     imm = iw & 0xffff;
378    
379     switch (opcode) {
380     case 0x00:
381     alpha_palcode_name(iw & 0x3ffffff, palcode_name,
382     sizeof(palcode_name));
383     debug("call_pal %s\n", palcode_name);
384     break;
385     case 0x08:
386     case 0x09:
387     debug("lda%s\t%s,", opcode == 9? "h" : "", alpha_regname[ra]);
388     alpha_print_imm16_disp(imm, rb);
389     debug("\n");
390     break;
391     case 0x0a:
392     case 0x0b:
393     case 0x0c:
394     case 0x0d:
395     case 0x0e:
396     case 0x0f:
397     case 0x20:
398     case 0x21:
399     case 0x22:
400     case 0x23:
401     case 0x24:
402     case 0x25:
403     case 0x26:
404     case 0x27:
405     case 0x28:
406     case 0x29:
407     case 0x2a:
408     case 0x2b:
409     case 0x2c:
410     case 0x2d:
411     case 0x2e:
412     case 0x2f:
413     floating = 0;
414     switch (opcode) {
415     case 0x0a: mnem = "ldbu"; break;
416     case 0x0b: mnem = "ldq_u"; break;
417     case 0x0c: mnem = "ldwu"; break;
418     case 0x0d: mnem = "stw"; break;
419     case 0x0e: mnem = "stb"; break;
420     case 0x0f: mnem = "stq_u"; break;
421     case 0x20: mnem = "ldf"; floating = 1; break;
422     case 0x21: mnem = "ldg"; floating = 1; break;
423     case 0x22: mnem = "lds"; floating = 1; break;
424     case 0x23: mnem = "ldt"; floating = 1; break;
425     case 0x24: mnem = "stf"; floating = 1; break;
426     case 0x25: mnem = "stg"; floating = 1; break;
427     case 0x26: mnem = "sts"; floating = 1; break;
428     case 0x27: mnem = "stt"; floating = 1; break;
429     case 0x28: mnem = "ldl"; break;
430     case 0x29: mnem = "ldq"; break;
431     case 0x2a: mnem = "ldl_l"; break;
432     case 0x2b: mnem = "ldq_l"; break;
433     case 0x2c: mnem = "stl"; break;
434     case 0x2d: mnem = "stq"; break;
435     case 0x2e: mnem = "stl_c"; break;
436     case 0x2f: mnem = "stq_c"; break;
437     }
438     if (opcode == 0x0b && ra == ALPHA_ZERO) {
439     debug("unop");
440     } else {
441     debug("%s\t", mnem);
442     if (floating)
443     debug("f%i,", ra);
444     else
445     debug("%s,", alpha_regname[ra]);
446     alpha_print_imm16_disp(imm, rb);
447     }
448     debug("\n");
449     break;
450     case 0x10:
451     switch (func & 0x7f) {
452     case 0x00: mnem = "addl"; break;
453     case 0x02: mnem = "s4addl"; break;
454     case 0x09: mnem = "subl"; break;
455     case 0x0b: mnem = "s4subl"; break;
456     case 0x0f: mnem = "cmpbge"; break;
457     case 0x12: mnem = "s8addl"; break;
458     case 0x1b: mnem = "s8subl"; break;
459     case 0x1d: mnem = "cmpult"; break;
460     case 0x20: mnem = "addq"; break;
461     case 0x22: mnem = "s4addq"; break;
462     case 0x29: mnem = "subq"; break;
463     case 0x2b: mnem = "s4subq"; break;
464     case 0x2d: mnem = "cmpeq"; break;
465     case 0x32: mnem = "s8addq"; break;
466     case 0x3b: mnem = "s8subq"; break;
467     case 0x3d: mnem = "cmpule"; break;
468     case 0x40: mnem = "addl/v"; break;
469     case 0x49: mnem = "subl/v"; break;
470     case 0x4d: mnem = "cmplt"; break;
471     case 0x60: mnem = "addq/v"; break;
472     case 0x69: mnem = "subq/v"; break;
473     case 0x6d: mnem = "cmple"; break;
474     default:debug("UNIMPLEMENTED opcode 0x%x func 0x%x\n",
475     opcode, func);
476     }
477     if (mnem == NULL)
478     break;
479     if (func & 0x80)
480     debug("%s\t%s,0x%x,%s\n", mnem,
481     alpha_regname[ra], (rb << 3) + (func >> 8),
482     alpha_regname[rc]);
483     else
484     debug("%s\t%s,%s,%s\n", mnem, alpha_regname[ra],
485     alpha_regname[rb], alpha_regname[rc]);
486     break;
487     case 0x11:
488     switch (func & 0x7f) {
489     case 0x000: mnem = "and"; break;
490     case 0x008: mnem = "andnot"; break;
491     case 0x014: mnem = "cmovlbs"; break;
492     case 0x016: mnem = "cmovlbc"; break;
493     case 0x020: mnem = "or"; break;
494     case 0x024: mnem = "cmoveq"; break;
495     case 0x026: mnem = "cmovne"; break;
496     case 0x028: mnem = "ornot"; break;
497     case 0x040: mnem = "xor"; break;
498     case 0x044: mnem = "cmovlt"; break;
499     case 0x046: mnem = "cmovge"; break;
500     case 0x048: mnem = "eqv"; break;
501     case 0x061: mnem = "amask"; break;
502     case 0x064: mnem = "cmovle"; break;
503     case 0x066: mnem = "cmovgt"; break;
504     default:debug("UNIMPLEMENTED opcode 0x%x func 0x%x\n",
505     opcode, func);
506     }
507     if (mnem == NULL)
508     break;
509     /* Special cases: "nop" etc: */
510     if (func == 0x020 && rc == ALPHA_ZERO)
511     debug("nop\n");
512     else if (func == 0x020 && (ra == ALPHA_ZERO
513     || rb == ALPHA_ZERO)) {
514     if (ra == ALPHA_ZERO && rb == ALPHA_ZERO)
515     debug("clr\t%s\n", alpha_regname[rc]);
516     else if (ra == ALPHA_ZERO)
517     debug("mov\t%s,%s\n", alpha_regname[rb],
518     alpha_regname[rc]);
519     else
520     debug("mov\t%s,%s\n", alpha_regname[ra],
521     alpha_regname[rc]);
522     } else if (func & 0x80)
523     debug("%s\t%s,0x%x,%s\n", mnem,
524     alpha_regname[ra], (rb << 3) + (func >> 8),
525     alpha_regname[rc]);
526     else
527     debug("%s\t%s,%s,%s\n", mnem, alpha_regname[ra],
528     alpha_regname[rb], alpha_regname[rc]);
529     break;
530     case 0x12:
531     switch (func & 0x7f) {
532     case 0x02: mnem = "mskbl"; break;
533     case 0x06: mnem = "extbl"; break;
534     case 0x0b: mnem = "insbl"; break;
535     case 0x12: mnem = "mskwl"; break;
536     case 0x16: mnem = "extwl"; break;
537     case 0x1b: mnem = "inswl"; break;
538     case 0x22: mnem = "mskll"; break;
539     case 0x26: mnem = "extll"; break;
540     case 0x2b: mnem = "insll"; break;
541     case 0x30: mnem = "zap"; break;
542     case 0x31: mnem = "zapnot"; break;
543     case 0x32: mnem = "mskql"; break;
544     case 0x34: mnem = "srl"; break;
545     case 0x36: mnem = "extql"; break;
546     case 0x39: mnem = "sll"; break;
547     case 0x3b: mnem = "insql"; break;
548     case 0x3c: mnem = "sra"; break;
549     case 0x52: mnem = "mskwh"; break;
550     case 0x57: mnem = "inswh"; break;
551     case 0x5a: mnem = "extwh"; break;
552     case 0x62: mnem = "msklh"; break;
553     case 0x67: mnem = "inslh"; break;
554     case 0x6a: mnem = "extlh"; break;
555     case 0x72: mnem = "mskqh"; break;
556     case 0x77: mnem = "insqh"; break;
557     case 0x7a: mnem = "extqh"; break;
558     default:debug("UNIMPLEMENTED opcode 0x%x func 0x%x\n",
559     opcode, func);
560     }
561     if (mnem == NULL)
562     break;
563     if (func & 0x80)
564     debug("%s\t%s,0x%x,%s\n", mnem,
565     alpha_regname[ra], (rb << 3) + (func >> 8),
566     alpha_regname[rc]);
567     else
568     debug("%s\t%s,%s,%s\n", mnem, alpha_regname[ra],
569     alpha_regname[rb], alpha_regname[rc]);
570     break;
571     case 0x13:
572     switch (func & 0x7f) {
573     case 0x00: mnem = "mull"; break;
574     case 0x20: mnem = "mulq"; break;
575     case 0x30: mnem = "umulh"; break;
576     case 0x40: mnem = "mull/v"; break;
577     case 0x60: mnem = "mulq/v"; break;
578     default:debug("UNIMPLEMENTED opcode 0x%x func 0x%x\n",
579     opcode, func);
580     }
581     if (mnem == NULL)
582     break;
583     if (func & 0x80)
584     debug("%s\t%s,0x%x,%s\n", mnem,
585     alpha_regname[ra], (rb << 3) + (func >> 8),
586     alpha_regname[rc]);
587     else
588     debug("%s\t%s,%s,%s\n", mnem, alpha_regname[ra],
589     alpha_regname[rb], alpha_regname[rc]);
590     break;
591     case 0x16:
592     switch (func & 0x7ff) {
593 dpavlin 22 case 0x02f: mnem = "cvttq/c"; rbrc = 1; break;
594 dpavlin 14 case 0x080: mnem = "adds"; break;
595     case 0x081: mnem = "subs"; break;
596     case 0x082: mnem = "muls"; break;
597 dpavlin 22 case 0x083: mnem = "XXXx083"; break;
598 dpavlin 14 case 0x0a0: mnem = "addt"; break;
599     case 0x0a1: mnem = "subt"; break;
600     case 0x0a2: mnem = "mult"; break;
601     case 0x0a3: mnem = "divt"; break;
602 dpavlin 22 case 0x0a5: mnem = "cmpteq"; break;
603     case 0x0a6: mnem = "cmptlt"; break;
604     case 0x0a7: mnem = "cmptle"; break;
605 dpavlin 14 case 0x0be: mnem = "cvtqt"; rbrc = 1; break;
606     default:debug("UNIMPLEMENTED opcode 0x%x func 0x%x\n",
607     opcode, func);
608     }
609     if (mnem == NULL)
610     break;
611     if (rbrc)
612     debug("%s\tf%i,f%i\n", mnem, rb, rc);
613     else
614     debug("%s\tf%i,f%i,f%i\n", mnem, ra, rb, rc);
615     break;
616     case 0x17:
617     switch (func & 0x7ff) {
618     case 0x020: mnem = "fabs"; rbrc = 1; break;
619 dpavlin 22 case 0x021: mnem = "fneg"; rbrc = 1; break;
620 dpavlin 14 default:debug("UNIMPLEMENTED opcode 0x%x func 0x%x\n",
621     opcode, func);
622     }
623     if (mnem == NULL)
624     break;
625     if ((func & 0x7ff) == 0x020 && ra == 31 && rb == 31)
626     debug("fclr\tf%i\n", rc);
627     else if (rbrc)
628     debug("%s\tf%i,f%i\n", mnem, rb, rc);
629     else
630     debug("%s\tf%i,f%i,f%i\n", mnem, ra, rb, rc);
631     break;
632     case 0x18:
633     switch (iw & 0xffff) {
634     case 0x0000: mnem = "trapb"; break;
635     case 0x0400: mnem = "excb"; break;
636     case 0x4000: mnem = "mb"; break;
637     case 0x4400: mnem = "wmb"; break;
638     case 0x8000: mnem = "fetch"; indir = 1; break;
639     case 0xa000: mnem = "fetch_m"; indir = 1; break;
640     case 0xc000: mnem = "rpcc"; break;
641     case 0xe000: mnem = "rc"; break;
642     case 0xe800: mnem = "ecb"; indir = 1; break;
643     case 0xf000: mnem = "rs"; break;
644     case 0xf800: mnem = "wh64"; indir = 1; break;
645     default:debug("UNIMPLEMENTED opcode 0x%x func 0x%x\n",
646     opcode, func);
647     }
648     if (mnem == NULL)
649     break;
650     debug("%s", mnem);
651     if ((iw & 0xffff) >= 0x8000) {
652     debug("\t");
653     if (indir)
654     debug("(%s)", alpha_regname[rb]);
655     else
656     debug("%s", alpha_regname[ra]);
657     }
658     debug("\n");
659     break;
660     case 0x1a:
661     tmp = iw & 0x3fff;
662     if (tmp & 0x2000)
663     tmp |= 0xffffffffffffc000ULL;
664     tmp <<= 2;
665     tmp += dumpaddr + sizeof(uint32_t);
666     switch ((iw >> 14) & 3) {
667     case 0:
668     case 1: if (((iw >> 14) & 3) == 0)
669     debug("jmp");
670     else
671     debug("jsr");
672     debug("\t%s,", alpha_regname[ra]);
673     debug("(%s),", alpha_regname[rb]);
674 dpavlin 24 debug("0x%"PRIx64, (uint64_t) tmp);
675 dpavlin 14 symbol = get_symbol_name(&cpu->machine->symbol_context,
676     tmp, &offset);
677     if (symbol != NULL)
678     debug("\t<%s>", symbol);
679     break;
680     case 2: debug("ret");
681     break;
682     default:fatal("unimpl JSR!");
683     }
684     debug("\n");
685     break;
686     case 0x30:
687     case 0x34:
688     tmp = iw & 0x1fffff;
689     if (tmp & 0x100000)
690     tmp |= 0xffffffffffe00000ULL;
691     tmp <<= 2;
692     tmp += dumpaddr + sizeof(uint32_t);
693     debug("%s\t", opcode==0x30? "br" : "bsr");
694     if (ra != ALPHA_ZERO)
695     debug("%s,", alpha_regname[ra]);
696 dpavlin 24 debug("0x%"PRIx64, (uint64_t) tmp);
697 dpavlin 14 symbol = get_symbol_name(&cpu->machine->symbol_context,
698     tmp, &offset);
699     if (symbol != NULL)
700     debug("\t<%s>", symbol);
701     debug("\n");
702     break;
703 dpavlin 22 case 0x31:
704     case 0x35:
705 dpavlin 14 case 0x38:
706     case 0x39:
707     case 0x3a:
708     case 0x3b:
709     case 0x3c:
710     case 0x3d:
711     case 0x3e:
712     case 0x3f:
713 dpavlin 22 floating = 0;
714 dpavlin 14 switch (opcode) {
715 dpavlin 22 case 0x31: mnem = "fbeq"; floating = 1; break;
716     case 0x35: mnem = "fbne"; floating = 1; break;
717 dpavlin 14 case 0x38: mnem = "blbc"; break;
718     case 0x39: mnem = "beq"; break;
719     case 0x3a: mnem = "blt"; break;
720     case 0x3b: mnem = "ble"; break;
721     case 0x3c: mnem = "blbs"; break;
722     case 0x3d: mnem = "bne"; break;
723     case 0x3e: mnem = "bge"; break;
724     case 0x3f: mnem = "bgt"; break;
725     }
726     tmp = iw & 0x1fffff;
727     if (tmp & 0x100000)
728     tmp |= 0xffffffffffe00000ULL;
729     tmp <<= 2;
730     tmp += dumpaddr + sizeof(uint32_t);
731 dpavlin 22 debug("%s\t", mnem);
732     if (floating)
733     debug("f%i,", ra);
734     else
735     debug("%s,", alpha_regname[ra]);
736 dpavlin 24 debug("0x%"PRIx64, (uint64_t) tmp);
737 dpavlin 14 symbol = get_symbol_name(&cpu->machine->symbol_context,
738     tmp, &offset);
739     if (symbol != NULL)
740     debug("\t<%s>", symbol);
741     debug("\n");
742     break;
743     default:debug("UNIMPLEMENTED opcode 0x%x\n", opcode);
744     }
745    
746     return sizeof(uint32_t);
747     }
748    
749    
750     #define MEMORY_RW alpha_userland_memory_rw
751     #define MEM_ALPHA
752     #define MEM_USERLAND
753     #include "../memory_rw.c"
754     #undef MEM_USERLAND
755     #undef MEM_ALPHA
756     #undef MEMORY_RW
757    
758    
759     #include "tmp_alpha_tail.c"
760    

  ViewVC Help
Powered by ViewVC 1.1.26