/[gxemul]/trunk/src/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/cpu_alpha.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 12 - (show annotations)
Mon Oct 8 16:18:38 2007 UTC (12 years, 2 months ago) by dpavlin
File MIME type: text/plain
File size: 18056 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.905 2005/08/16 09:16:24 debug Exp $
20050628	Continuing the work on the ARM translation engine. end_of_page
		works. Experimenting with load/store translation caches
		(virtual -> physical -> host).
20050629	More ARM stuff (memory access translation cache, mostly). This
		might break a lot of stuff elsewhere, probably some MIPS-
		related translation things.
20050630	Many load/stores are now automatically generated and included
		into cpu_arm_instr.c; 1024 functions in total (!).
		Fixes based on feedback from Alec Voropay: only print 8 hex
		digits instead of 16 in some cases when emulating 32-bit
		machines; similar 8 vs 16 digit fix for breakpoint addresses;
		4Kc has 16 TLB entries, not 48; the MIPS config select1
		register is now printed with "reg ,0".
		Also changing many other occurances of 16 vs 8 digit output.
		Adding cache associativity fields to mips_cpu_types.h; updating
		some other cache fields; making the output of
		mips_cpu_dumpinfo() look nicer.
		Generalizing the bintrans stuff for device accesses to also
		work with the new translation system. (This might also break
		some MIPS things.)
		Adding multi-load/store instructions to the ARM disassembler
		and the translator, and some optimizations of various kinds.
20050701	Adding a simple dev_disk (it can read/write sectors from
		disk images).
20050712	Adding dev_ether (a simple ethernet send/receive device).
		Debugger command "ninstrs" for toggling show_nr_of_instructions
		during runtime.
		Removing the framebuffer logo.
20050713	Continuing on dev_ether.
		Adding a dummy cpu_alpha (again).
20050714	More work on cpu_alpha.
20050715	More work on cpu_alpha. Many instructions work, enough to run
		a simple framebuffer fill test (similar to the ARM test).
20050716	More Alpha stuff.
20050717	Minor updates (Alpha stuff).
20050718	Minor updates (Alpha stuff).
20050719	Generalizing some Alpha instructions.
20050720	More Alpha-related updates.
20050721	Continuing on cpu_alpha. Importing rpb.h from NetBSD/alpha.
20050722	Alpha-related updates: userland stuff (Hello World using
		write() compiled statically for FreeBSD/Alpha runs fine), and
		more instructions are now implemented.
20050723	Fixing ldq_u and stq_u.
		Adding more instructions (conditional moves, masks, extracts,
		shifts).
20050724	More FreeBSD/Alpha userland stuff, and adding some more
		instructions (inserts).
20050725	Continuing on the Alpha stuff. (Adding dummy ldt/stt.)
		Adding a -A command line option to turn off alignment checks
		in some cases (for translated code).
		Trying to remove the old bintrans code which updated the pc
		and nr_of_executed_instructions for every instruction.
20050726	Making another attempt att removing the pc/nr of instructions
		code. This time it worked, huge performance increase for
		artificial test code, but performance loss for real-world
		code :-( so I'm scrapping that code for now.
		Tiny performance increase on Alpha (by using ret instead of
		jmp, to play nice with the Alpha's branch prediction) for the
		old MIPS bintrans backend.
20050727	Various minor fixes and cleanups.
20050728	Switching from a 2-level virtual to host/physical translation
		system for ARM emulation, to a 1-level translation.
		Trying to switch from 2-level to 1-level for the MIPS bintrans
		system as well (Alpha only, so far), but there is at least one
		problem: caches and/or how they work with device mappings.
20050730	Doing the 2-level to 1-level conversion for the i386 backend.
		The cache/device bug is still there for R2K/3K :(
		Various other minor updates (Malta etc).
		The mc146818 clock now updates the UIP bit in a way which works
		better with Linux for at least sgimips and Malta emulation.
		Beginning the work on refactoring the dyntrans system.
20050731	Continuing the dyntrans refactoring.
		Fixing a small but serious host alignment bug in memory_rw.
		Adding support for big-endian load/stores to the i386 bintrans
		backend.
		Another minor i386 bintrans backend update: stores from the
		zero register are now one (or two) loads shorter.
		The slt and sltu instructions were incorrectly implemented for
		the i386 backend; only using them for 32-bit mode for now.
20050801	Continuing the dyntrans refactoring.
		Cleanup of the ns16550 serial controller (removing unnecessary
		code).
		Bugfix (memory corruption bug) in dev_gt, and a patch/hack from
		Alec Voropay for Linux/Malta.
20050802	More cleanup/refactoring of the dyntrans subsystem: adding
		phys_page pointers to the lookup tables, for quick jumps
		between translated pages.
		Better fix for the ns16550 device (but still no real FIFO
		functionality).
		Converting cpu_ppc to the new dyntrans system. This means that
		I will have to start from scratch with implementing each
		instruction, and figure out how to implement dual 64/32-bit
		modes etc.
		Removing the URISC CPU family, because it was useless.
20050803	When selecting a machine type, the main type can now be omitted
		if the subtype name is unique. (I.e. -E can be omitted.)
		Fixing a dyntrans/device update bug. (Writes to offset 0 of
		a device could sometimes go unnoticed.)
		Adding an experimental "instruction combination" hack for
		ARM for memset-like byte fill loops.
20050804	Minor progress on cpu_alpha and related things.
		Finally fixing the MIPS dmult/dmultu bugs.
		Fixing some minor TODOs.
20050805	Generalizing the 8259 PIC. It now also works with Cobalt
		and evbmips emulation, in addition to the x86 hack.
		Finally converting the ns16550 device to use devinit.
		Continuing the work on the dyntrans system. Thinking about
		how to add breakpoints.
20050806	More dyntrans updates. Breakpoints seem to work now.
20050807	Minor updates: cpu_alpha and related things; removing
		dev_malta (as it isn't used any more).
		Dyntrans: working on general "show trace tree" support.
		The trace tree stuff now works with both the old MIPS code and
		with newer dyntrans modes. :)
		Continuing on Alpha-related stuff (trying to get *BSD to boot
		a bit further, adding more instructions, etc).
20050808	Adding a dummy IA64 cpu family, and continuing the refactoring
		of the dyntrans system.
		Removing the regression test stuff, because it was more or
		less useless.
		Adding loadlinked/storeconditional type instructions to the
		Alpha emulation. (Needed for Linux/alpha. Not very well tested
		yet.)
20050809	The function call trace tree now prints a per-function nr of
		arguments. (Semi-meaningless, since that data isn't read yet
		from the ELFs; some hardcoded symbols such as memcpy() and
		strlen() work fine, though.)
		More dyntrans refactoring; taking out more of the things that
		are common to all cpu families.
20050810	Working on adding support for "dual mode" for PPC dyntrans
		(i.e. both 64-bit and 32-bit modes).
		(Re)adding some simple PPC instructions.
20050811	Adding a dummy M68K cpu family. The dyntrans system isn't ready
		for variable-length ISAs yet, so it's completely bogus so far.
		Re-adding more PPC instructions.
		Adding a hack to src/file.c which allows OpenBSD/mac68k a.out
		kernels to be loaded.
		Beginning to add PPC loads/stores. So far they only work in
		32-bit mode.
20050812	The configure file option "add_remote" now accepts symbolic
		host names, in addition to numeric IPv4 addresses.
		Re-adding more PPC instructions.
20050814	Continuing to port back more PPC instructions.
		Found and fixed the cache/device write-update bug for 32-bit
		MIPS bintrans. :-)
		Triggered a really weird and annoying bug in Compaq's C
		compiler; ccc sometimes outputs code which loads from an
		address _before_ checking whether the pointer was NULL or not.
		(I'm not sure how to handle this problem.)
20050815	Removing all of the old x86 instruction execution code; adding
		a new (dummy) dyntrans module for x86.
		Taking the first steps to extend the dyntrans system to support
		variable-length instructions.
		Slowly preparing for the next release.
20050816	Adding a dummy SPARC cpu module.
		Minor updates (documentation etc) for the release.

==============  RELEASE 0.3.5  ==============


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

  ViewVC Help
Powered by ViewVC 1.1.26