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