/[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 22 - (show annotations)
Mon Oct 8 16:19:37 2007 UTC (13 years, 1 month ago) by dpavlin
File MIME type: text/plain
File size: 17607 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1121 2006/02/18 21:03:08 debug Exp $
20051126	Cobalt and PReP now work with the 21143 NIC.
		Continuing on Alpha dyntrans things.
		Fixing some more left-shift-by-24 to unsigned.
20051127	Working on OpenFirmware emulation; major cleanup/redesign.
		Progress on MacPPC emulation: NetBSD detects two CPUs (when
		running with -n 2), framebuffer output (for text) works.
		Adding quick-hack Bandit PCI controller and "gc" interrupt
		controller for MacPPC.
20051128	Changing from a Bandit to a Uni-North controller for macppc.
		Continuing on OpenFirmware and MacPPC emulation in general
		(obio controller, and wdc attached to the obio seems to work).
20051129	More work on MacPPC emulation (adding a dummy ADB controller).
		Continuing the PCI bus cleanup (endianness and tag composition)
		and rewriting all PCI controllers' access functions.
20051130	Various minor PPC dyntrans optimizations.
		Manually inlining some parts of the framebuffer redraw routine.
		Slowly beginning the conversion of the old MIPS emulation into
		dyntrans (but this will take quite some time to get right).
		Generalizing quick_pc_to_pointers.
20051201	Documentation update (David Muse has made available a kernel
		which simplifies Debian/DECstation installation).
		Continuing on the ADB bus controller.
20051202	Beginning a rewrite of the Zilog serial controller (dev_zs).
20051203	Continuing on the zs rewrite (now called dev_z8530); conversion
		to devinit style.
		Reworking some of the input-only vs output-only vs input-output
		details of src/console.c, better warning messages, and adding
		a debug dump.
		Removing the concept of "device state"; it wasn't really used.
		Changing some debug output (-vv should now be used to show all
		details about devices and busses; not shown during normal
		startup anymore).
		Beginning on some SPARC instruction disassembly support.
20051204	Minor PPC updates (WALNUT skeleton stuff).
		Continuing on the MIPS dyntrans rewrite.
		More progress on the ADB controller (a keyboard is "detected"
		by NetBSD and OpenBSD).
		Downgrading OpenBSD/arc as a guest OS from "working" to
		"almost working" in the documentation.
		Progress on Algor emulation ("v3" PCI controller).
20051205	Minor updates.
20051207	Sorting devices according to address; this reduces complexity
		of device lookups from O(n) to O(log n) in memory_rw (but no
		real performance increase (yet) in experiments).
20051210	Beginning the work on native dyntrans backends (by making a
		simple skeleton; so far only for Alpha hosts).
20051211	Some very minor SPARC updates.
20051215	Fixing a bug in the MIPS mul (note: not mult) instruction,
		so it also works with non-64-bit emulation. (Thanks to Alec
		Voropay for noticing the problem.)
20051216	More work on the fake/empty/simple/skeleton/whatever backend;
		performance doesn't increase, so this isn't really worth it,
		but it was probably worth it to prepare for a real backend
		later.
20051219	More instr call statistics gathering and analysis stuff.
20051220	Another fix for MIPS 'mul'. Also converting mul and {d,}cl{o,z}
		to dyntrans.
		memory_ppc.c syntax error fix (noticed by Peter Valchev).
		Beginning to move out machines from src/machine.c into
		individual files in src/machines (in a way similar to the
		autodev system for devices).
20051222	Updating the documentation regarding NetBSD/pmax 3.0.
20051223	- " - NetBSD/cats 3.0.
20051225	- " - NetBSD/hpcmips 3.0.
20051226	Continuing on the machine registry redesign.
		Adding support for ARM rrx (33-bit rotate).
		Fixing some signed/unsigned issues (exposed by gcc -W).
20051227	Fixing the bug which prevented a NetBSD/prep 3.0 install kernel
		from starting (triggered when an mtmsr was the last instruction
		on a page). Unfortunately not enough to get the kernel to run
		as well as the 2.1 kernels did.
20051230	Some dyntrans refactoring.
20051231	Continuing on the machine registry redesign.
20060101-10	Continuing... moving more machines. Moving MD interrupt stuff
		from machine.c into a new src/machines/interrupts.c.
20060114	Adding various mvmeppc machine skeletons.
20060115	Continuing on mvme* stuff. NetBSD/mvmeppc prints boot messages
		(for MVME1600) and reaches the root device prompt, but no
		specific hardware devices are emulated yet.
20060116	Minor updates to the mvme1600 emulation mode; the Eagle PCI bus
		seems to work without much modification, and a 21143 can be
		detected, interrupts might work (but untested so far).
		Adding a fake MK48Txx (mkclock) device, for NetBSD/mvmeppc.
20060121	Adding an aux control register for ARM. (A BIG thank you to
		Olivier Houchard for tracking down this bug.)
20060122	Adding more ARM instructions (smulXY), and dev_iq80321_7seg.
20060124	Adding disassembly of more ARM instructions (mia*, mra/mar),
		and some semi-bogus XScale and i80321 registers.
20060201-02	Various minor updates. Moving the last machines out of
		machine.c.
20060204	Adding a -c command line option, for running debugger commands
		before the simulation starts, but after all files have been
		loaded.
		Minor iq80321-related updates.
20060209	Minor hacks (DEVINIT macro, etc).
		Preparing for the generalization of the 64-bit dyntrans address
		translation subsystem.
20060216	Adding ARM ldrd (double-register load).
20060217	Continuing on various ARM-related stuff.
20060218	More progress on the ATA/wdc emulation for NetBSD/iq80321.
		NetBSD/evbarm can now be installed :-)  Updating the docs, etc.
		Continuing on Algor emulation.

==============  RELEASE 0.3.8  ==============


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.5 2006/01/01 16:08:25 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;
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 cpu->invalidate_translation_caches =
75 alpha_invalidate_translation_caches;
76 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_interrupt():
192 */
193 int alpha_cpu_interrupt(struct cpu *cpu, uint64_t irq_nr)
194 {
195 fatal("alpha_cpu_interrupt(): TODO\n");
196 return 0;
197 }
198
199
200 /*
201 * alpha_cpu_interrupt_ack():
202 */
203 int alpha_cpu_interrupt_ack(struct cpu *cpu, uint64_t irq_nr)
204 {
205 /* fatal("alpha_cpu_interrupt_ack(): TODO\n"); */
206 return 0;
207 }
208
209
210 /*
211 * alpha_print_imm16_disp():
212 *
213 * Used internally by alpha_cpu_disassemble_instr().
214 */
215 static void alpha_print_imm16_disp(int imm, int rb)
216 {
217 imm = (int16_t)imm;
218
219 if (imm < 0) {
220 debug("-");
221 imm = -imm;
222 }
223 if (imm <= 256)
224 debug("%i", imm);
225 else
226 debug("0x%x", imm);
227 if (rb != ALPHA_ZERO)
228 debug("(%s)", alpha_regname[rb]);
229 }
230
231
232 /*
233 * alpha_cpu_disassemble_instr():
234 *
235 * Convert an instruction word into human readable format, for instruction
236 * tracing.
237 *
238 * If running is 1, cpu->pc should be the address of the instruction.
239 *
240 * If running is 0, things that depend on the runtime environment (eg.
241 * register contents) will not be shown, and addr will be used instead of
242 * cpu->pc for relative addresses.
243 */
244 int alpha_cpu_disassemble_instr(struct cpu *cpu, unsigned char *ib,
245 int running, uint64_t dumpaddr, int bintrans)
246 {
247 uint32_t iw;
248 uint64_t offset, tmp;
249 int opcode, ra, rb, func, rc, imm, floating, rbrc = 0, indir = 0;
250 char *symbol, *mnem = NULL;
251 char palcode_name[30];
252
253 if (running)
254 dumpaddr = cpu->pc;
255
256 symbol = get_symbol_name(&cpu->machine->symbol_context,
257 dumpaddr, &offset);
258 if (symbol != NULL && offset == 0)
259 debug("<%s>\n", symbol);
260
261 if (cpu->machine->ncpus > 1 && running)
262 debug("cpu%i:\t", cpu->cpu_id);
263
264 debug("%016llx: ", (long long)dumpaddr);
265
266 iw = ib[0] + (ib[1]<<8) + (ib[2]<<16) + (ib[3]<<24);
267 debug("%08x\t", (int)iw);
268
269 opcode = iw >> 26;
270 ra = (iw >> 21) & 31;
271 rb = (iw >> 16) & 31;
272 func = (iw >> 5) & 0x7ff;
273 rc = iw & 31;
274 imm = iw & 0xffff;
275
276 switch (opcode) {
277 case 0x00:
278 alpha_palcode_name(iw & 0x3ffffff, palcode_name,
279 sizeof(palcode_name));
280 debug("call_pal %s\n", palcode_name);
281 break;
282 case 0x08:
283 case 0x09:
284 debug("lda%s\t%s,", opcode == 9? "h" : "", alpha_regname[ra]);
285 alpha_print_imm16_disp(imm, rb);
286 debug("\n");
287 break;
288 case 0x0a:
289 case 0x0b:
290 case 0x0c:
291 case 0x0d:
292 case 0x0e:
293 case 0x0f:
294 case 0x20:
295 case 0x21:
296 case 0x22:
297 case 0x23:
298 case 0x24:
299 case 0x25:
300 case 0x26:
301 case 0x27:
302 case 0x28:
303 case 0x29:
304 case 0x2a:
305 case 0x2b:
306 case 0x2c:
307 case 0x2d:
308 case 0x2e:
309 case 0x2f:
310 floating = 0;
311 switch (opcode) {
312 case 0x0a: mnem = "ldbu"; break;
313 case 0x0b: mnem = "ldq_u"; break;
314 case 0x0c: mnem = "ldwu"; break;
315 case 0x0d: mnem = "stw"; break;
316 case 0x0e: mnem = "stb"; break;
317 case 0x0f: mnem = "stq_u"; break;
318 case 0x20: mnem = "ldf"; floating = 1; break;
319 case 0x21: mnem = "ldg"; floating = 1; break;
320 case 0x22: mnem = "lds"; floating = 1; break;
321 case 0x23: mnem = "ldt"; floating = 1; break;
322 case 0x24: mnem = "stf"; floating = 1; break;
323 case 0x25: mnem = "stg"; floating = 1; break;
324 case 0x26: mnem = "sts"; floating = 1; break;
325 case 0x27: mnem = "stt"; floating = 1; break;
326 case 0x28: mnem = "ldl"; break;
327 case 0x29: mnem = "ldq"; break;
328 case 0x2a: mnem = "ldl_l"; break;
329 case 0x2b: mnem = "ldq_l"; break;
330 case 0x2c: mnem = "stl"; break;
331 case 0x2d: mnem = "stq"; break;
332 case 0x2e: mnem = "stl_c"; break;
333 case 0x2f: mnem = "stq_c"; break;
334 }
335 if (opcode == 0x0b && ra == ALPHA_ZERO) {
336 debug("unop");
337 } else {
338 debug("%s\t", mnem);
339 if (floating)
340 debug("f%i,", ra);
341 else
342 debug("%s,", alpha_regname[ra]);
343 alpha_print_imm16_disp(imm, rb);
344 }
345 debug("\n");
346 break;
347 case 0x10:
348 switch (func & 0x7f) {
349 case 0x00: mnem = "addl"; break;
350 case 0x02: mnem = "s4addl"; break;
351 case 0x09: mnem = "subl"; break;
352 case 0x0b: mnem = "s4subl"; break;
353 case 0x0f: mnem = "cmpbge"; break;
354 case 0x12: mnem = "s8addl"; break;
355 case 0x1b: mnem = "s8subl"; break;
356 case 0x1d: mnem = "cmpult"; break;
357 case 0x20: mnem = "addq"; break;
358 case 0x22: mnem = "s4addq"; break;
359 case 0x29: mnem = "subq"; break;
360 case 0x2b: mnem = "s4subq"; break;
361 case 0x2d: mnem = "cmpeq"; break;
362 case 0x32: mnem = "s8addq"; break;
363 case 0x3b: mnem = "s8subq"; break;
364 case 0x3d: mnem = "cmpule"; break;
365 case 0x40: mnem = "addl/v"; break;
366 case 0x49: mnem = "subl/v"; break;
367 case 0x4d: mnem = "cmplt"; break;
368 case 0x60: mnem = "addq/v"; break;
369 case 0x69: mnem = "subq/v"; break;
370 case 0x6d: mnem = "cmple"; break;
371 default:debug("UNIMPLEMENTED opcode 0x%x func 0x%x\n",
372 opcode, func);
373 }
374 if (mnem == NULL)
375 break;
376 if (func & 0x80)
377 debug("%s\t%s,0x%x,%s\n", mnem,
378 alpha_regname[ra], (rb << 3) + (func >> 8),
379 alpha_regname[rc]);
380 else
381 debug("%s\t%s,%s,%s\n", mnem, alpha_regname[ra],
382 alpha_regname[rb], alpha_regname[rc]);
383 break;
384 case 0x11:
385 switch (func & 0x7f) {
386 case 0x000: mnem = "and"; break;
387 case 0x008: mnem = "andnot"; break;
388 case 0x014: mnem = "cmovlbs"; break;
389 case 0x016: mnem = "cmovlbc"; break;
390 case 0x020: mnem = "or"; break;
391 case 0x024: mnem = "cmoveq"; break;
392 case 0x026: mnem = "cmovne"; break;
393 case 0x028: mnem = "ornot"; break;
394 case 0x040: mnem = "xor"; break;
395 case 0x044: mnem = "cmovlt"; break;
396 case 0x046: mnem = "cmovge"; break;
397 case 0x048: mnem = "eqv"; break;
398 case 0x061: mnem = "amask"; break;
399 case 0x064: mnem = "cmovle"; break;
400 case 0x066: mnem = "cmovgt"; break;
401 default:debug("UNIMPLEMENTED opcode 0x%x func 0x%x\n",
402 opcode, func);
403 }
404 if (mnem == NULL)
405 break;
406 /* Special cases: "nop" etc: */
407 if (func == 0x020 && rc == ALPHA_ZERO)
408 debug("nop\n");
409 else if (func == 0x020 && (ra == ALPHA_ZERO
410 || rb == ALPHA_ZERO)) {
411 if (ra == ALPHA_ZERO && rb == ALPHA_ZERO)
412 debug("clr\t%s\n", alpha_regname[rc]);
413 else if (ra == ALPHA_ZERO)
414 debug("mov\t%s,%s\n", alpha_regname[rb],
415 alpha_regname[rc]);
416 else
417 debug("mov\t%s,%s\n", alpha_regname[ra],
418 alpha_regname[rc]);
419 } else if (func & 0x80)
420 debug("%s\t%s,0x%x,%s\n", mnem,
421 alpha_regname[ra], (rb << 3) + (func >> 8),
422 alpha_regname[rc]);
423 else
424 debug("%s\t%s,%s,%s\n", mnem, alpha_regname[ra],
425 alpha_regname[rb], alpha_regname[rc]);
426 break;
427 case 0x12:
428 switch (func & 0x7f) {
429 case 0x02: mnem = "mskbl"; break;
430 case 0x06: mnem = "extbl"; break;
431 case 0x0b: mnem = "insbl"; break;
432 case 0x12: mnem = "mskwl"; break;
433 case 0x16: mnem = "extwl"; break;
434 case 0x1b: mnem = "inswl"; break;
435 case 0x22: mnem = "mskll"; break;
436 case 0x26: mnem = "extll"; break;
437 case 0x2b: mnem = "insll"; break;
438 case 0x30: mnem = "zap"; break;
439 case 0x31: mnem = "zapnot"; break;
440 case 0x32: mnem = "mskql"; break;
441 case 0x34: mnem = "srl"; break;
442 case 0x36: mnem = "extql"; break;
443 case 0x39: mnem = "sll"; break;
444 case 0x3b: mnem = "insql"; break;
445 case 0x3c: mnem = "sra"; break;
446 case 0x52: mnem = "mskwh"; break;
447 case 0x57: mnem = "inswh"; break;
448 case 0x5a: mnem = "extwh"; break;
449 case 0x62: mnem = "msklh"; break;
450 case 0x67: mnem = "inslh"; break;
451 case 0x6a: mnem = "extlh"; break;
452 case 0x72: mnem = "mskqh"; break;
453 case 0x77: mnem = "insqh"; break;
454 case 0x7a: mnem = "extqh"; break;
455 default:debug("UNIMPLEMENTED opcode 0x%x func 0x%x\n",
456 opcode, func);
457 }
458 if (mnem == NULL)
459 break;
460 if (func & 0x80)
461 debug("%s\t%s,0x%x,%s\n", mnem,
462 alpha_regname[ra], (rb << 3) + (func >> 8),
463 alpha_regname[rc]);
464 else
465 debug("%s\t%s,%s,%s\n", mnem, alpha_regname[ra],
466 alpha_regname[rb], alpha_regname[rc]);
467 break;
468 case 0x13:
469 switch (func & 0x7f) {
470 case 0x00: mnem = "mull"; break;
471 case 0x20: mnem = "mulq"; break;
472 case 0x30: mnem = "umulh"; break;
473 case 0x40: mnem = "mull/v"; break;
474 case 0x60: mnem = "mulq/v"; break;
475 default:debug("UNIMPLEMENTED opcode 0x%x func 0x%x\n",
476 opcode, func);
477 }
478 if (mnem == NULL)
479 break;
480 if (func & 0x80)
481 debug("%s\t%s,0x%x,%s\n", mnem,
482 alpha_regname[ra], (rb << 3) + (func >> 8),
483 alpha_regname[rc]);
484 else
485 debug("%s\t%s,%s,%s\n", mnem, alpha_regname[ra],
486 alpha_regname[rb], alpha_regname[rc]);
487 break;
488 case 0x16:
489 switch (func & 0x7ff) {
490 case 0x02f: mnem = "cvttq/c"; rbrc = 1; break;
491 case 0x080: mnem = "adds"; break;
492 case 0x081: mnem = "subs"; break;
493 case 0x082: mnem = "muls"; break;
494 case 0x083: mnem = "XXXx083"; break;
495 case 0x0a0: mnem = "addt"; break;
496 case 0x0a1: mnem = "subt"; break;
497 case 0x0a2: mnem = "mult"; break;
498 case 0x0a3: mnem = "divt"; break;
499 case 0x0a5: mnem = "cmpteq"; break;
500 case 0x0a6: mnem = "cmptlt"; break;
501 case 0x0a7: mnem = "cmptle"; break;
502 case 0x0be: mnem = "cvtqt"; rbrc = 1; break;
503 default:debug("UNIMPLEMENTED opcode 0x%x func 0x%x\n",
504 opcode, func);
505 }
506 if (mnem == NULL)
507 break;
508 if (rbrc)
509 debug("%s\tf%i,f%i\n", mnem, rb, rc);
510 else
511 debug("%s\tf%i,f%i,f%i\n", mnem, ra, rb, rc);
512 break;
513 case 0x17:
514 switch (func & 0x7ff) {
515 case 0x020: mnem = "fabs"; rbrc = 1; break;
516 case 0x021: mnem = "fneg"; rbrc = 1; break;
517 default:debug("UNIMPLEMENTED opcode 0x%x func 0x%x\n",
518 opcode, func);
519 }
520 if (mnem == NULL)
521 break;
522 if ((func & 0x7ff) == 0x020 && ra == 31 && rb == 31)
523 debug("fclr\tf%i\n", rc);
524 else if (rbrc)
525 debug("%s\tf%i,f%i\n", mnem, rb, rc);
526 else
527 debug("%s\tf%i,f%i,f%i\n", mnem, ra, rb, rc);
528 break;
529 case 0x18:
530 switch (iw & 0xffff) {
531 case 0x0000: mnem = "trapb"; break;
532 case 0x0400: mnem = "excb"; break;
533 case 0x4000: mnem = "mb"; break;
534 case 0x4400: mnem = "wmb"; break;
535 case 0x8000: mnem = "fetch"; indir = 1; break;
536 case 0xa000: mnem = "fetch_m"; indir = 1; break;
537 case 0xc000: mnem = "rpcc"; break;
538 case 0xe000: mnem = "rc"; break;
539 case 0xe800: mnem = "ecb"; indir = 1; break;
540 case 0xf000: mnem = "rs"; break;
541 case 0xf800: mnem = "wh64"; indir = 1; break;
542 default:debug("UNIMPLEMENTED opcode 0x%x func 0x%x\n",
543 opcode, func);
544 }
545 if (mnem == NULL)
546 break;
547 debug("%s", mnem);
548 if ((iw & 0xffff) >= 0x8000) {
549 debug("\t");
550 if (indir)
551 debug("(%s)", alpha_regname[rb]);
552 else
553 debug("%s", alpha_regname[ra]);
554 }
555 debug("\n");
556 break;
557 case 0x1a:
558 tmp = iw & 0x3fff;
559 if (tmp & 0x2000)
560 tmp |= 0xffffffffffffc000ULL;
561 tmp <<= 2;
562 tmp += dumpaddr + sizeof(uint32_t);
563 switch ((iw >> 14) & 3) {
564 case 0:
565 case 1: if (((iw >> 14) & 3) == 0)
566 debug("jmp");
567 else
568 debug("jsr");
569 debug("\t%s,", alpha_regname[ra]);
570 debug("(%s),", alpha_regname[rb]);
571 debug("0x%llx", (long long)tmp);
572 symbol = get_symbol_name(&cpu->machine->symbol_context,
573 tmp, &offset);
574 if (symbol != NULL)
575 debug("\t<%s>", symbol);
576 break;
577 case 2: debug("ret");
578 break;
579 default:fatal("unimpl JSR!");
580 }
581 debug("\n");
582 break;
583 case 0x30:
584 case 0x34:
585 tmp = iw & 0x1fffff;
586 if (tmp & 0x100000)
587 tmp |= 0xffffffffffe00000ULL;
588 tmp <<= 2;
589 tmp += dumpaddr + sizeof(uint32_t);
590 debug("%s\t", opcode==0x30? "br" : "bsr");
591 if (ra != ALPHA_ZERO)
592 debug("%s,", alpha_regname[ra]);
593 debug("0x%llx", (long long)tmp);
594 symbol = get_symbol_name(&cpu->machine->symbol_context,
595 tmp, &offset);
596 if (symbol != NULL)
597 debug("\t<%s>", symbol);
598 debug("\n");
599 break;
600 case 0x31:
601 case 0x35:
602 case 0x38:
603 case 0x39:
604 case 0x3a:
605 case 0x3b:
606 case 0x3c:
607 case 0x3d:
608 case 0x3e:
609 case 0x3f:
610 floating = 0;
611 switch (opcode) {
612 case 0x31: mnem = "fbeq"; floating = 1; break;
613 case 0x35: mnem = "fbne"; floating = 1; break;
614 case 0x38: mnem = "blbc"; break;
615 case 0x39: mnem = "beq"; break;
616 case 0x3a: mnem = "blt"; break;
617 case 0x3b: mnem = "ble"; break;
618 case 0x3c: mnem = "blbs"; break;
619 case 0x3d: mnem = "bne"; break;
620 case 0x3e: mnem = "bge"; break;
621 case 0x3f: mnem = "bgt"; break;
622 }
623 tmp = iw & 0x1fffff;
624 if (tmp & 0x100000)
625 tmp |= 0xffffffffffe00000ULL;
626 tmp <<= 2;
627 tmp += dumpaddr + sizeof(uint32_t);
628 debug("%s\t", mnem);
629 if (floating)
630 debug("f%i,", ra);
631 else
632 debug("%s,", alpha_regname[ra]);
633 debug("0x%llx", (long long)tmp);
634 symbol = get_symbol_name(&cpu->machine->symbol_context,
635 tmp, &offset);
636 if (symbol != NULL)
637 debug("\t<%s>", symbol);
638 debug("\n");
639 break;
640 default:debug("UNIMPLEMENTED opcode 0x%x\n", opcode);
641 }
642
643 return sizeof(uint32_t);
644 }
645
646
647 #define MEMORY_RW alpha_userland_memory_rw
648 #define MEM_ALPHA
649 #define MEM_USERLAND
650 #include "../memory_rw.c"
651 #undef MEM_USERLAND
652 #undef MEM_ALPHA
653 #undef MEMORY_RW
654
655
656 #include "tmp_alpha_tail.c"
657

  ViewVC Help
Powered by ViewVC 1.1.26