/[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 18 - (hide annotations)
Mon Oct 8 16:19:11 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 17770 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1004 2005/10/27 14:01:10 debug Exp $
20051011        Passing -A as the default boot arg for CATS (works fine with
                OpenBSD/cats).
20051012	Fixing the VGA cursor offset bug, and speeding up framebuffer
		redraws if character cells contain the same thing as during
		the last redraw.
20051013	Adding a slow strd ARM instruction hack.
20051017	Minor updates: Adding a dummy i80321 Verde controller (for
		XScale emulation), fixing the disassembly of the ARM "ldrd"
		instruction, adding "support" for less-than-4KB pages for ARM
		(by not adding them to translation tables).
20051020	Continuing on some HPCarm stuff. A NetBSD/hpcarm kernel prints
		some boot messages on an emulated Jornada 720.
		Making dev_ram work better with dyntrans (speeds up some things
		quite a bit).
20051021	Automatically generating some of the most common ARM load/store
		multiple instructions.
20051022	Better statistics gathering for the ARM load/store multiple.
		Various other dyntrans and device updates.
20051023	Various minor updates.
20051024	Continuing; minor device and dyntrans fine-tuning. Adding the
		first "reasonable" instruction combination hacks for ARM (the
		cores of NetBSD/cats' memset and memcpy).
20051025	Fixing a dyntrans-related bug in dev_vga. Also changing the
		dyntrans low/high access notification to only be updated on
		writes, not reads. Hopefully it will be enough. (dev_vga in
		charcell mode now seems to work correctly with both reads and
		writes.)
		Experimenting with gathering dyntrans statistics (which parts
		of emulated RAM that are actually executed), and adding
		instruction combination hacks for cache cleaning and a part of
		NetBSD's scanc() function.
20051026	Adding a bitmap for ARM emulation which indicates if a page is
		(specifically) user accessible; loads and stores with the t-
		flag set can now use the translation arrays, which results in
		a measurable speedup.
20051027	Dyntrans updates; adding an extra bitmap array for 32-bit
		emulation modes, speeding up the check whether a physical page
		has any code translations or not (O(n) -> O(1)). Doing a
		similar reduction of O(n) to O(1) by avoiding the scan through
		the translation entries on a translation update (32-bit mode
		only).
		Various other minor hacks.
20051029	Quick release, without any testing at all.

==============  RELEASE 0.3.6.2  ==============


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

  ViewVC Help
Powered by ViewVC 1.1.26