/[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 42 - (show annotations)
Mon Oct 8 16:22:32 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 18860 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1613 2007/06/15 20:11:26 debug Exp $
20070501	Continuing a little on m88k disassembly (control registers,
		more instructions).
		Adding a dummy mvme88k machine mode.
20070502	Re-adding MIPS load/store alignment exceptions.
20070503	Implementing more of the M88K disassembly code.
20070504	Adding disassembly of some more M88K load/store instructions.
		Implementing some relatively simple M88K instructions (br.n,
		xor[.u] imm, and[.u] imm).
20070505	Implementing M88K three-register and, or, xor, and jmp[.n],
		bsr[.n] including function call trace stuff.
		Applying a patch from Bruce M. Simpson which implements the
		SYSCON_BOARD_CPU_CLOCK_FREQ_ID object of the syscon call in
		the yamon PROM emulation.
20070506	Implementing M88K bb0[.n] and bb1[.n], and skeletons for
		ldcr and stcr (although no control regs are implemented yet).
20070509	Found and fixed the bug which caused Linux for QEMU_MIPS to
		stop working in 0.4.5.1: It was a faulty change to the MIPS
		'sc' and 'scd' instructions I made while going through gcc -W
		warnings on 20070428.
20070510	Updating the Linux/QEMU_MIPS section in guestoses.html to
		use mips-test-0.2.tar.gz instead of 0.1.
		A big thank you to Miod Vallat for sending me M88K manuals.
		Implementing more M88K instructions (addu, subu, div[u], mulu,
		ext[u], clr, set, cmp).
20070511	Fixing bugs in the M88K "and" and "and.u" instructions (found
		by comparing against the manual).
		Implementing more M88K instructions (mask[.u], mak, bcnd (auto-
		generated)) and some more control register details.
		Cleanup: Removing the experimental AVR emulation mode and
		corresponding devices; AVR emulation wasn't really meaningful.
		Implementing autogeneration of most M88K loads/stores. The
		rectangle drawing demo (with -O0) for M88K runs :-)
		Beginning on M88K exception handling.
		More M88K instructions: tb0, tb1, rte, sub, jsr[.n].
		Adding some skeleton MVME PROM ("BUG") emulation.
20070512	Fixing a bug in the M88K cmp instruction.
		Adding the M88K lda (scaled register) instruction.
		Fixing bugs in 64-bit (32-bit pairs) M88K loads/stores.
		Removing the unused tick_hz stuff from the machine struct.
		Implementing the M88K xmem instruction. OpenBSD/mvme88k gets
		far enough to display the Copyright banner :-)
		Implementing subu.co (guess), addu.co, addu.ci, ff0, and ff1.
		Adding a dev_mvme187, for MVME187-specific devices/registers.
		OpenBSD/mvme88k prints more boot messages. :)
20070515	Continuing on MVME187 emulation (adding more devices, beginning
		on the CMMUs, etc).
		Adding the M88K and.c, xor.c, and or.c instructions, and making
		sure that mul, div, etc cause exceptions if executed when SFD1
		is disabled.
20070517	Continuing on M88K and MVME187 emulation in general; moving
		the CMMU registers to the CPU struct, separating dev_pcc2 from
		dev_mvme187, and beginning on memory_m88k.c (BATC and PATC).
		Fixing a bug in 64-bit (32-bit pairs) M88K fast stores.
		Implementing the clock part of dev_mk48txx.
		Implementing the M88K fstcr and xcr instructions.
		Implementing m88k_cpu_tlbdump().
		Beginning on the implementation of a separate address space
		for M88K .usr loads/stores.
20070520	Removing the non-working (skeleton) Sandpoint, SonyNEWS, SHARK
		Dnard, and Zaurus machine modes.
		Experimenting with dyntrans to_be_translated read-ahead. It
		seems to give a very small performance increase for MIPS
		emulation, but a large performance degradation for SuperH. Hm.
20070522	Disabling correct SuperH ITLB emulation; it does not seem to be
		necessary in order to let SH4 guest OSes run, and it slows down
		userspace code.
		Implementing "samepage" branches for SuperH emulation, and some
		other minor speed hacks.
20070525	Continuing on M88K memory-related stuff: exceptions, memory
		transaction register contents, etc.
		Implementing the M88K subu.ci instruction.
		Removing the non-working (skeleton) Iyonix machine mode.
		OpenBSD/mvme88k reaches userland :-), starts executing
		/sbin/init's instructions, and issues a few syscalls, before
		crashing.
20070526	Fixing bugs in dev_mk48txx, so that OpenBSD/mvme88k detects
		the correct time-of-day.
		Implementing a generic IRQ controller for the test machines
		(dev_irqc), similar to a proposed patch from Petr Stepan.
		Experimenting some more with translation read-ahead.
		Adding an "expect" script for automated OpenBSD/landisk
		install regression/performance tests.
20070527	Adding a dummy mmEye (SH3) machine mode skeleton.
		FINALLY found the strange M88K bug I have been hunting: I had
		not emulated the SNIP value for exceptions occurring in
		branch delay slots correctly.
		Implementing correct exceptions for 64-bit M88K loads/stores.
		Address to symbol lookups are now disabled when M88K is
		running in usermode (because usermode addresses don't have
		anything to do with supervisor addresses).
20070531	Removing the mmEye machine mode skeleton.
20070604	Some minor code cleanup.
20070605	Moving src/useremul.c into a subdir (src/useremul/), and
		cleaning up some more legacy constructs.
		Adding -Wstrict-aliasing and -fstrict-aliasing detection to
		the configure script.
20070606	Adding a check for broken GCC on Solaris to the configure
		script. (GCC 3.4.3 on Solaris cannot handle static variables
		which are initialized to 0 or NULL. :-/)
		Removing the old (non-working) ARC emulation modes: NEC RD94,
		R94, R96, and R98, and the last traces of Olivetti M700 and
		Deskstation Tyne.
		Removing the non-working skeleton WDSC device (dev_wdsc).
20070607	Thinking about how to use the host's cc + ld at runtime to
		generate native code. (See experiments/native_cc_ld_test.i
		for an example.)
20070608	Adding a program counter sampling timer, which could be useful
		for native code generation experiments.
		The KN02_CSR_NRMMOD bit in the DECstation 5000/200 (KN02) CSR
		should always be set, to allow a 5000/200 PROM to boot.
20070609	Moving out breakpoint details from the machine struct into
		a helper struct, and removing the limit on max nr of
		breakpoints.
20070610	Moving out tick functions into a helper struct as well (which
		also gets rid of the max limit).
20070612	FINALLY figured out why Debian/DECstation stopped working when
		translation read-ahead was enabled: in src/memory_rw.c, the
		call to invalidate_code_translation was made also if the
		memory access was an instruction load (if the page was mapped
		as writable); it shouldn't be called in that case.
20070613	Implementing some more MIPS32/64 revision 2 instructions: di,
		ei, ext, dext, dextm, dextu, and ins.
20070614	Implementing an instruction combination for the NetBSD/arm
		idle loop (making the host not use any cpu if NetBSD/arm
		inside the emulator is not using any cpu).
		Increasing the nr of ARM VPH entries from 128 to 384.
20070615	Removing the ENABLE_arch stuff from the configure script, so
		that all included architectures are included in both release
		and development builds.
		Moving memory related helper functions from misc.c to memory.c.
		Adding preliminary instructions for netbooting NetBSD/pmppc to
		guestoses.html; it doesn't work yet, there are weird timeouts.
		Beginning a total rewrite of the userland emulation modes
		(removing all emulation modes, beginning from scratch with
		NetBSD/MIPS and FreeBSD/Alpha only).
20070616	After fixing a bug in the DEC21143 NIC (the TDSTAT_OWN bit was
		only cleared for the last segment when transmitting, not all
		segments), NetBSD/pmppc boots with root-on-nfs without the
		timeouts. Updating guestoses.html.
		Removing the skeleton PSP (Playstation Portable) mode.
		Moving X11-related stuff in the machine struct into a helper
		struct.
		Cleanup of out-of-memory checks, to use a new CHECK_ALLOCATION
		macro (which prints a meaningful error message).
		Adding a COMMENT to each machine and device (for automagic
		.index comment generation).
		Doing regression testing for the next release.

==============  RELEASE 0.4.6  ==============


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

  ViewVC Help
Powered by ViewVC 1.1.26