/[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 44 - (show annotations)
Mon Oct 8 16:22:56 2007 UTC (16 years, 5 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 /*
2 * Copyright (C) 2005-2007 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.29 2007/06/28 13:36:46 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 "interrupt.h"
45 #include "machine.h"
46 #include "memory.h"
47 #include "misc.h"
48 #include "settings.h"
49 #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 void alpha_irq_interrupt_assert(struct interrupt *interrupt);
60 void alpha_irq_interrupt_deassert(struct interrupt *interrupt);
61
62
63 /*
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 int i = 0;
73 struct alpha_cpu_type_def cpu_type_defs[] = ALPHA_CPU_TYPE_DEFS;
74
75 /* 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 return 0;
84
85 cpu->is_32bit = 0;
86 cpu->byte_order = EMUL_LITTLE_ENDIAN;
87
88 cpu->memory_rw = alpha_memory_rw;
89 cpu->run_instr = alpha_run_instr;
90 cpu->translate_v2p = alpha_translate_v2p;
91 cpu->update_translation_table = alpha_update_translation_table;
92 cpu->invalidate_translation_caches =
93 alpha_invalidate_translation_caches;
94 cpu->invalidate_code_translation = alpha_invalidate_code_translation;
95
96 cpu->cd.alpha.cpu_type = cpu_type_defs[i];
97
98 /* 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 /* 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 /* 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 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 int i, j;
155 struct alpha_cpu_type_def tdefs[] = ALPHA_CPU_TYPE_DEFS;
156
157 i = 0;
158 while (tdefs[i].name != NULL) {
159 debug("%s", tdefs[i].name);
160 for (j=13 - strlen(tdefs[i].name); j>0; j--)
161 debug(" ");
162 i++;
163 if ((i % 4) == 0 || tdefs[i].name == NULL)
164 debug("\n");
165 }
166 }
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 debug("cpu%i:\t pc = 0x%016"PRIx64, x, (uint64_t) cpu->pc);
187 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 debug("%3s = 0x%016"PRIx64, alpha_regname[r],
194 (uint64_t) cpu->cd.alpha.r[r]);
195 debug((i % 2) == 1? "\n" : " ");
196 }
197 }
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 }
213
214
215 /*
216 * 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 * 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 int running, uint64_t dumpaddr)
267 {
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 debug("%016"PRIx64": ", (uint64_t) dumpaddr);
286
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 case 0x06c: mnem = "implver"; break;
423 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 } else if (func == 0x1ec) {
442 /* implver */
443 debug("%s\t%s\n", mnem, alpha_regname[rc]);
444 } 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 case 0x02f: mnem = "cvttq/c"; rbrc = 1; break;
516 case 0x080: mnem = "adds"; break;
517 case 0x081: mnem = "subs"; break;
518 case 0x082: mnem = "muls"; break;
519 case 0x083: mnem = "XXXx083"; 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 0x0a5: mnem = "cmpteq"; break;
525 case 0x0a6: mnem = "cmptlt"; break;
526 case 0x0a7: mnem = "cmptle"; break;
527 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 case 0x021: mnem = "fneg"; rbrc = 1; break;
542 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 debug("0x%"PRIx64, (uint64_t) tmp);
597 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 debug("0x%"PRIx64, (uint64_t) tmp);
619 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 case 0x31:
626 case 0x35:
627 case 0x38:
628 case 0x39:
629 case 0x3a:
630 case 0x3b:
631 case 0x3c:
632 case 0x3d:
633 case 0x3e:
634 case 0x3f:
635 floating = 0;
636 switch (opcode) {
637 case 0x31: mnem = "fbeq"; floating = 1; break;
638 case 0x35: mnem = "fbne"; floating = 1; break;
639 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 debug("%s\t", mnem);
654 if (floating)
655 debug("f%i,", ra);
656 else
657 debug("%s,", alpha_regname[ra]);
658 debug("0x%"PRIx64, (uint64_t) tmp);
659 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 #include "memory_rw.c"
676 #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