/[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 44 - (hide annotations)
Mon Oct 8 16:22:56 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 18662 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1632 2007/09/11 21:46:35 debug Exp $
20070616	Implementing the MIPS32/64 revision 2 "ror" instruction.
20070617	Adding a struct for each physpage which keeps track of which
		ranges within that page (base offset, length) that are
		continuously translatable. When running with native code
		generation enabled (-b), a range is added after each read-
		ahead loop.
		Experimenting with using the physical program counter sample
		data (implemented 20070608) together with the "translatable
		range" information, to figure out which physical address ranges
		would be worth translating to native code (if the number of
		samples falling within a range is above a certain threshold).
20070618	Adding automagic building of .index comment files for
		src/file/, src/promemul/, src src/useremul/ as well.
		Adding a "has been translated" bit to the ranges, so that only
		not-yet-translated ranges will be sampled.
20070619	Moving src/cpu.c and src/memory_rw.c into src/cpus/,
		src/device.c into src/devices/, and src/machine.c into
		src/machines/.
		Creating a skeleton cc/ld native backend module; beginning on
		the function which will detect cc command line, etc.
20070620	Continuing on the native code generation infrastructure.
20070621	Moving src/x11.c and src/console.c into a new src/console/
		subdir (for everything that is console or framebuffer related).
		Moving src/symbol*.c into a new src/symbol/, which should
		contain anything that is symbol handling related.
20070624	Making the program counter sampling threshold a "settings
		variable" (sampling_threshold), i.e. it can now be changed
		during runtime.
		Switching the RELEASE notes format from plain text to HTML.
		If the TMPDIR environment variable is set, it is used instead
		of "/tmp" for temporary files.
		Continuing on the cc/ld backend: simple .c code is generated,
		the compiler and linker are called, etc.
		Adding detection of host architecture to the configure script
		(again), and adding icache invalidation support (only
		implemented for Alpha hosts so far).
20070625	Simplifying the program counter sampling mechanism.
20070626	Removing the cc/ld native code generation stuff, program
		counter sampling, etc; it would not have worked well in the
		general case.
20070627	Removing everything related to native code generation.
20070629	Removing the (practically unusable) support for multiple
		emulations. (The single emulation allowed now still supports
		multiple simultaneous machines, as before.)
		Beginning on PCCTWO and M88K interrupts.
20070723	Adding a dummy skeleton for emulation of M32R processors.
20070901	Fixing a warning found by "gcc version 4.3.0 20070817
		(experimental)" on amd64.
20070905	Removing some more traces of the old "multiple emulations"
		code.
		Also looking in /usr/local/include and /usr/local/lib for
		X11 libs, when running configure.
20070909	Minor updates to the guest OS install instructions, in
		preparation for the NetBSD 4.0 release.
20070918	More testing of NetBSD 4.0 RC1.

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

  ViewVC Help
Powered by ViewVC 1.1.26