/[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 20 - (show annotations)
Mon Oct 8 16:19:23 2007 UTC (16 years, 5 months ago) by dpavlin
File MIME type: text/plain
File size: 17193 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1055 2005/11/25 22:48:36 debug Exp $
20051031	Adding disassembly support for more ARM instructions (clz,
		smul* etc), and adding a hack to support "new tiny" pages
		for StrongARM.
20051101	Minor documentation updates (NetBSD 2.0.2 -> 2.1, and OpenBSD
		3.7 -> 3.8, and lots of testing).
		Changing from 1-sector PIO mode 0 transfers to 128-sector PIO
		mode 3 (in dev_wdc).
		Various minor ARM dyntrans updates (pc-relative loads from
		within the same page as the instruction are now treated as
		constant "mov").
20051102	Re-enabling instruction combinations (they were accidentally
		disabled).
		Dyntrans TLB entries are now overwritten using a round-robin
		scheme instead of randomly. This increases performance.
		Fixing a typo in file.c (thanks to Chuan-Hua Chang for
		noticing it).
		Experimenting with adding ATAPI support to dev_wdc (to make
		emulated *BSD detect cdroms as cdroms, not harddisks).
20051104	Various minor updates.
20051105	Continuing on the ATAPI emulation. Seems to work well enough
		for a NetBSD/cats installation, but not OpenBSD/cats.
		Various other updates.
20051106	Modifying the -Y command line option to allow scaleup with
		certain graphic controllers (only dev_vga so far), not just
		scaledown.
		Some minor dyntrans cleanups.
20051107	Beginning a cleanup up the PCI subsystem (removing the
		read_register hack, etc).
20051108	Continuing the cleanup; splitting up some pci devices into a
		normal autodev device and some separate pci glue code.
20051109	Continuing on the PCI bus stuff; all old pci_*.c have been
		incorporated into normal devices and/or rewritten as glue code
		only, adding a dummy Intel 82371AB PIIX4 for Malta (not really
		tested yet).
		Minor pckbc fix so that Linux doesn't complain.
		Working on the DEC 21143 NIC (ethernet mac rom stuff mostly).
		Various other minor fixes.
20051110	Some more ARM dyntrans fine-tuning (e.g. some instruction
		combinations (cmps followed by conditional branch within the
		same page) and special cases for DPIs with regform when the
		shifter isn't used).
20051111	ARM dyntrans updates: O(n)->O(1) for just-mark-as-non-
		writable in the generic pc_to_pointers function, and some other
		minor hacks.
		Merging Cobalt and evbmips (Malta) ISA interrupt handling,
		and some minor fixes to allow Linux to accept harddisk irqs.
20051112	Minor device updates (pckbc, dec21143, lpt, ...), most
		importantly fixing the ALI M1543/M5229 so that harddisk irqs
		work with Linux/CATS.
20051113	Some more generalizations of the PCI subsystem.
		Finally took the time to add a hack for SCSI CDROM TOCs; this
		enables OpenBSD to use partition 'a' (as needed by the OpenBSD
		installer), and Windows NT's installer to get a bit further.
		Also fixing dev_wdc to allow Linux to detect ATAPI CDROMs.
		Continuing on the DEC 21143.
20051114	Minor ARM dyntrans tweaks; ARM cmps+branch optimization when
		comparing with 0, and generalizing the xchg instr. comb.
		Adding disassembly of ARM mrrc/mcrr and q{,d}{add,sub}.
20051115	Continuing on various PPC things (BATs, other address trans-
		lation things, various loads/stores, BeBox emulation, etc.).
		Beginning to work on PPC interrupt/exception support.
20051116	Factoring out some code which initializes legacy ISA devices
		from those machines that use them (bus_isa).
		Continuing on PPC interrupt/exception support.
20051117	Minor Malta fixes: RTC year offset = 80, disabling a speed hack
		which caused NetBSD to detect a too fast cpu, and adding a new
		hack to make Linux detect a faster cpu.
		Continuing on the Artesyn PM/PPC emulation mode.
		Adding an Algor emulation skeleton (P4032 and P5064);
		implementing some of the basics.
		Continuing on PPC emulation in general; usage of unimplemented
		SPRs is now easier to track, continuing on memory/exception
		related issues, etc.
20051118	More work on PPC emulation (tgpr0..3, exception handling,
		memory stuff, syscalls, etc.).
20051119	Changing the ARM dyntrans code to mostly use cpu->pc, and not
		necessarily use arm reg 15. Seems to work.
		Various PPC updates; continuing on the PReP emulation mode.
20051120	Adding a workaround/hack to dev_mc146818 to allow NetBSD/prep
		to detect the clock.
20051121	More cleanup of the PCI bus (memory and I/O bases, etc).
		Continuing on various PPC things (decrementer and timebase,
		WDCs on obio (on PReP) use irq 13, not 14/15).
20051122	Continuing on the CPC700 controller (interrupts etc) for PMPPC,
		and on PPC stuff in general.
		Finally! After some bug fixes to the virtual to physical addr
		translation, NetBSD/{prep,pmppc} 2.1 reach userland and are
		stable enough to be interacted with.
		More PCI updates; reverse-endian device access for PowerPC etc.
20051123	Generalizing the IEEE floating point subsystem (moving it out
		from src/cpus/cpu_mips_coproc.c into a new src/float_emul.c).
		Input via slave xterms was sometimes not really working; fixing
		this for ns16550, and a warning message is now displayed if
		multiple non-xterm consoles are active.
		Adding some PPC floating point support, etc.
		Various interrupt related updates (dev_wdc, _ns16550, _8259,
		and the isa32 common code in machine.c).
		NetBSD/prep can now be installed! :-) (Well, with some manual
		commands necessary before running sysinst.) Updating the
		documentation and various other things to reflect this.
20051124	Various minor documentation updates.
		Continuing the work on the DEC 21143 NIC.
20051125	LOTS of work on the 21143. Both OpenBSD and NetBSD work fine
		with it now, except that OpenBSD sometimes gives a time-out
		warning.
		Minor documentation updates.

==============  RELEASE 0.3.7  ==============


1 /*
2 * Copyright (C) 2005 Anders Gavare. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * 3. The name of the author may not be used to endorse or promote products
13 * derived from this software without specific prior written permission.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 *
27 *
28 * $Id: cpu_alpha.c,v 1.3 2005/11/13 00:14:07 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 0x080: mnem = "adds"; break;
491 case 0x081: mnem = "subs"; break;
492 case 0x082: mnem = "muls"; break;
493 case 0x083: mnem = "mult"; break;
494 case 0x0a0: mnem = "addt"; break;
495 case 0x0a1: mnem = "subt"; break;
496 case 0x0a2: mnem = "mult"; break;
497 case 0x0a3: mnem = "divt"; break;
498 case 0x0be: mnem = "cvtqt"; rbrc = 1; break;
499 default:debug("UNIMPLEMENTED opcode 0x%x func 0x%x\n",
500 opcode, func);
501 }
502 if (mnem == NULL)
503 break;
504 if (rbrc)
505 debug("%s\tf%i,f%i\n", mnem, rb, rc);
506 else
507 debug("%s\tf%i,f%i,f%i\n", mnem, ra, rb, rc);
508 break;
509 case 0x17:
510 switch (func & 0x7ff) {
511 case 0x020: mnem = "fabs"; rbrc = 1; break;
512 default:debug("UNIMPLEMENTED opcode 0x%x func 0x%x\n",
513 opcode, func);
514 }
515 if (mnem == NULL)
516 break;
517 if ((func & 0x7ff) == 0x020 && ra == 31 && rb == 31)
518 debug("fclr\tf%i\n", rc);
519 else if (rbrc)
520 debug("%s\tf%i,f%i\n", mnem, rb, rc);
521 else
522 debug("%s\tf%i,f%i,f%i\n", mnem, ra, rb, rc);
523 break;
524 case 0x18:
525 switch (iw & 0xffff) {
526 case 0x0000: mnem = "trapb"; break;
527 case 0x0400: mnem = "excb"; break;
528 case 0x4000: mnem = "mb"; break;
529 case 0x4400: mnem = "wmb"; break;
530 case 0x8000: mnem = "fetch"; indir = 1; break;
531 case 0xa000: mnem = "fetch_m"; indir = 1; break;
532 case 0xc000: mnem = "rpcc"; break;
533 case 0xe000: mnem = "rc"; break;
534 case 0xe800: mnem = "ecb"; indir = 1; break;
535 case 0xf000: mnem = "rs"; break;
536 case 0xf800: mnem = "wh64"; indir = 1; break;
537 default:debug("UNIMPLEMENTED opcode 0x%x func 0x%x\n",
538 opcode, func);
539 }
540 if (mnem == NULL)
541 break;
542 debug("%s", mnem);
543 if ((iw & 0xffff) >= 0x8000) {
544 debug("\t");
545 if (indir)
546 debug("(%s)", alpha_regname[rb]);
547 else
548 debug("%s", alpha_regname[ra]);
549 }
550 debug("\n");
551 break;
552 case 0x1a:
553 tmp = iw & 0x3fff;
554 if (tmp & 0x2000)
555 tmp |= 0xffffffffffffc000ULL;
556 tmp <<= 2;
557 tmp += dumpaddr + sizeof(uint32_t);
558 switch ((iw >> 14) & 3) {
559 case 0:
560 case 1: if (((iw >> 14) & 3) == 0)
561 debug("jmp");
562 else
563 debug("jsr");
564 debug("\t%s,", alpha_regname[ra]);
565 debug("(%s),", alpha_regname[rb]);
566 debug("0x%llx", (long long)tmp);
567 symbol = get_symbol_name(&cpu->machine->symbol_context,
568 tmp, &offset);
569 if (symbol != NULL)
570 debug("\t<%s>", symbol);
571 break;
572 case 2: debug("ret");
573 break;
574 default:fatal("unimpl JSR!");
575 }
576 debug("\n");
577 break;
578 case 0x30:
579 case 0x34:
580 tmp = iw & 0x1fffff;
581 if (tmp & 0x100000)
582 tmp |= 0xffffffffffe00000ULL;
583 tmp <<= 2;
584 tmp += dumpaddr + sizeof(uint32_t);
585 debug("%s\t", opcode==0x30? "br" : "bsr");
586 if (ra != ALPHA_ZERO)
587 debug("%s,", alpha_regname[ra]);
588 debug("0x%llx", (long long)tmp);
589 symbol = get_symbol_name(&cpu->machine->symbol_context,
590 tmp, &offset);
591 if (symbol != NULL)
592 debug("\t<%s>", symbol);
593 debug("\n");
594 break;
595 case 0x38:
596 case 0x39:
597 case 0x3a:
598 case 0x3b:
599 case 0x3c:
600 case 0x3d:
601 case 0x3e:
602 case 0x3f:
603 switch (opcode) {
604 case 0x38: mnem = "blbc"; break;
605 case 0x39: mnem = "beq"; break;
606 case 0x3a: mnem = "blt"; break;
607 case 0x3b: mnem = "ble"; break;
608 case 0x3c: mnem = "blbs"; break;
609 case 0x3d: mnem = "bne"; break;
610 case 0x3e: mnem = "bge"; break;
611 case 0x3f: mnem = "bgt"; break;
612 }
613 tmp = iw & 0x1fffff;
614 if (tmp & 0x100000)
615 tmp |= 0xffffffffffe00000ULL;
616 tmp <<= 2;
617 tmp += dumpaddr + sizeof(uint32_t);
618 debug("%s\t%s,", mnem, alpha_regname[ra]);
619 debug("0x%llx", (long long)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 default:debug("UNIMPLEMENTED opcode 0x%x\n", opcode);
627 }
628
629 return sizeof(uint32_t);
630 }
631
632
633 #define MEMORY_RW alpha_userland_memory_rw
634 #define MEM_ALPHA
635 #define MEM_USERLAND
636 #include "../memory_rw.c"
637 #undef MEM_USERLAND
638 #undef MEM_ALPHA
639 #undef MEMORY_RW
640
641
642 #include "tmp_alpha_tail.c"
643

  ViewVC Help
Powered by ViewVC 1.1.26