/[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

Contents of /trunk/src/cpus/cpu_alpha.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 26 - (show annotations)
Mon Oct 8 16:20:10 2007 UTC (16 years, 5 months ago) by dpavlin
File MIME type: text/plain
File size: 20108 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1264 2006/06/25 11:08:04 debug Exp $
20060624	Replacing the error-prone machine type initialization stuff
		with something more reasonable.
		Finally removing the old "cpu_run" kludge; moving around stuff
		in machine.c and emul.c to better suit the dyntrans system.
		Various minor dyntrans cleanups (renaming translate_address to
		translate_v2p, and experimenting with template physpages).
20060625	Removing the speed hack which separated the vph entries into
		two halves (code vs data); things seem a lot more stable now.
		Minor performance hack: R2000/R3000 cache isolation now only
		clears address translations when going into isolation, not
		when going out of it.
		Fixing the MIPS interrupt problems by letting mtc0 immediately
		cause interrupts.

==============  RELEASE 0.4.0.1  ==============


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

  ViewVC Help
Powered by ViewVC 1.1.26