/[gxemul]/trunk/src/cpus/cpu_avr.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

Annotation of /trunk/src/cpus/cpu_avr.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 28 - (hide annotations)
Mon Oct 8 16:20:26 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 15255 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1298 2006/07/22 11:27:46 debug Exp $
20060626	Continuing on SPARC emulation (beginning on the 'save'
		instruction, register windows, etc).
20060629	Planning statistics gathering (new -s command line option),
		and renaming speed_tricks to allow_instruction_combinations.
20060630	Some minor manual page updates.
		Various cleanups.
		Implementing the -s command line option.
20060701	FINALLY found the bug which prevented Linux and Ultrix from
		running without the ugly hack in the R2000/R3000 cache isol
		code; it was the phystranslation hint array which was buggy.
		Removing the phystranslation hint code completely, for now.
20060702	Minor dyntrans cleanups; invalidation of physpages now only
		invalidate those parts of a page that have actually been
		translated. (32 parts per page.)
		Some MIPS non-R3000 speed fixes.
		Experimenting with MIPS instruction combination for some
		addiu+bne+sw loops, and sw+sw+sw.
		Adding support (again) for larger-than-4KB pages in MIPS tlbw*.
		Continuing on SPARC emulation: adding load/store instructions.
20060704	Fixing a virtual vs physical page shift bug in the new tlbw*
		implementation. Problem noticed by Jakub Jermar. (Many thanks.)
		Moving rfe and eret to cpu_mips_instr.c, since that is the
		only place that uses them nowadays.
20060705	Removing the BSD license from the "testmachine" include files,
		placing them in the public domain instead; this enables the
		testmachine stuff to be used from projects which are
		incompatible with the BSD license for some reason.
20060707	Adding instruction combinations for the R2000/R3000 L1
		I-cache invalidation code used by NetBSD/pmax 3.0, lui+addiu,
		various branches followed by addiu or nop, and jr ra followed
		by addiu. The time it takes to perform a full NetBSD/pmax R3000
		install on the laptop has dropped from 573 seconds to 539. :-)
20060708	Adding a framebuffer controller device (dev_fbctrl), which so
		far can be used to change the fb resolution during runtime, but
		in the future will also be useful for accelerated block fill/
		copy, and possibly also simplified character output.
		Adding an instruction combination for NetBSD/pmax' strlen.
20060709	Minor fixes: reading raw files in src/file.c wasn't memblock
		aligned, removing buggy multi_sw MIPS instruction combination,
		etc.
20060711	Adding a machine_qemu.c, which contains a "qemu_mips" machine.
		(It mimics QEMU's MIPS machine mode, so that a test kernel
		made for QEMU_MIPS also can run in GXemul... at least to some
		extent.)  Adding a short section about how to run this mode to
		doc/guestoses.html.
20060714	Misc. minor code cleanups.
20060715	Applying a patch which adds getchar() to promemul/yamon.c
		(from Oleksandr Tymoshenko).
		Adding yamon.h from NetBSD, and rewriting yamon.c to use it
		(instead of ugly hardcoded numbers) + some cleanup.
20060716	Found and fixed the bug which broke single-stepping of 64-bit
		programs between 0.4.0 and 0.4.0.1 (caused by too quick
		refactoring and no testing). Hopefully this fix will not
		break too many other things.
20060718	Continuing on the 8253 PIT; it now works with Linux/QEMU_MIPS.
		Re-adding the sw+sw+sw instr comb (the problem was that I had
		ignored endian issues); however, it doesn't seem to give any
		big performance gain.
20060720	Adding a dummy Transputer mode (T414, T800 etc) skeleton (only
		the 'j' and 'ldc' instructions are implemented so far). :-}
20060721	Adding gtreg.h from NetBSD, updating dev_gt.c to use it, plus
		misc. other updates to get Linux 2.6 for evbmips/malta working
		(thanks to Alec Voropay for the details).
		FINALLY found and fixed the bug which made tlbw* for non-R3000
		buggy; it was a reference count problem in the dyntrans core.
20060722	Testing stuff; things seem stable enough for a new release.

==============  RELEASE 0.4.1  ==============


1 dpavlin 14 /*
2 dpavlin 24 * Copyright (C) 2005-2006 Anders Gavare. All rights reserved.
3 dpavlin 14 *
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 dpavlin 28 * $Id: cpu_avr.c,v 1.20 2006/07/16 13:32:26 debug Exp $
29 dpavlin 14 *
30     * Atmel AVR (8-bit) CPU emulation.
31     */
32    
33     #include <stdio.h>
34     #include <stdlib.h>
35     #include <string.h>
36     #include <ctype.h>
37    
38     #include "cpu.h"
39     #include "machine.h"
40     #include "memory.h"
41     #include "misc.h"
42     #include "symbol.h"
43    
44    
45     #define DYNTRANS_32
46 dpavlin 20 #define DYNTRANS_VARIABLE_INSTRUCTION_LENGTH
47 dpavlin 14 #include "tmp_avr_head.c"
48    
49    
50     /*
51     * avr_cpu_new():
52     *
53     * Create a new AVR cpu object.
54     *
55     * Returns 1 on success, 0 if there was no matching AVR processor with
56     * this cpu_type_name.
57     */
58     int avr_cpu_new(struct cpu *cpu, struct memory *mem, struct machine *machine,
59     int cpu_id, char *cpu_type_name)
60     {
61 dpavlin 24 int type = 0;
62    
63     if (strcasecmp(cpu_type_name, "AVR") == 0 ||
64     strcasecmp(cpu_type_name, "AVR16") == 0 ||
65     strcasecmp(cpu_type_name, "AT90S2313") == 0 ||
66     strcasecmp(cpu_type_name, "AT90S8515") == 0)
67     type = 16;
68     if (strcasecmp(cpu_type_name, "AVR22") == 0)
69     type = 22;
70    
71     if (type == 0)
72 dpavlin 14 return 0;
73    
74 dpavlin 28 cpu->run_instr = avr_run_instr;
75 dpavlin 14 cpu->memory_rw = avr_memory_rw;
76     cpu->update_translation_table = avr_update_translation_table;
77 dpavlin 18 cpu->invalidate_translation_caches =
78     avr_invalidate_translation_caches;
79 dpavlin 14 cpu->invalidate_code_translation = avr_invalidate_code_translation;
80     cpu->is_32bit = 1;
81    
82     cpu->byte_order = EMUL_LITTLE_ENDIAN;
83    
84 dpavlin 24 cpu->cd.avr.is_22bit = (type == 22);
85     cpu->cd.avr.pc_mask = cpu->cd.avr.is_22bit? 0x3fffff : 0xffff;
86 dpavlin 14
87 dpavlin 24 cpu->cd.avr.sram_mask = 0xff; /* 256 bytes ram */
88     cpu->cd.avr.sp = cpu->cd.avr.sram_mask - 2;
89    
90 dpavlin 14 /* Only show name and caches etc for CPU nr 0 (in SMP machines): */
91     if (cpu_id == 0) {
92     debug("%s", cpu->name);
93     }
94    
95     return 1;
96     }
97    
98    
99     /*
100     * avr_cpu_list_available_types():
101     *
102     * Print a list of available AVR CPU types.
103     */
104     void avr_cpu_list_available_types(void)
105     {
106 dpavlin 24 debug("AVR\tAVR16\tAVR22\n");
107 dpavlin 14 }
108    
109    
110     /*
111     * avr_cpu_dumpinfo():
112     */
113     void avr_cpu_dumpinfo(struct cpu *cpu)
114     {
115 dpavlin 24 debug(" (%i-bit program counter)\n",
116     cpu->cd.avr.is_22bit? 22 : 16);
117 dpavlin 14 }
118    
119    
120     /*
121     * avr_cpu_register_dump():
122     *
123     * Dump cpu registers in a relatively readable format.
124     *
125     * gprs: set to non-zero to dump GPRs and some special-purpose registers.
126     * coprocs: set bit 0..3 to dump registers in coproc 0..3.
127     */
128     void avr_cpu_register_dump(struct cpu *cpu, int gprs, int coprocs)
129     {
130     char *symbol;
131     uint64_t offset;
132     int i, x = cpu->cpu_id;
133    
134     if (gprs) {
135     /* Special registers (pc, ...) first: */
136     symbol = get_symbol_name(&cpu->machine->symbol_context,
137     cpu->pc, &offset);
138    
139     debug("cpu%i: sreg = ", x);
140     debug("%c", cpu->cd.avr.sreg & AVR_SREG_I? 'I' : 'i');
141     debug("%c", cpu->cd.avr.sreg & AVR_SREG_T? 'T' : 't');
142     debug("%c", cpu->cd.avr.sreg & AVR_SREG_H? 'H' : 'h');
143     debug("%c", cpu->cd.avr.sreg & AVR_SREG_S? 'S' : 's');
144     debug("%c", cpu->cd.avr.sreg & AVR_SREG_V? 'V' : 'v');
145     debug("%c", cpu->cd.avr.sreg & AVR_SREG_N? 'N' : 'n');
146     debug("%c", cpu->cd.avr.sreg & AVR_SREG_Z? 'Z' : 'z');
147     debug("%c", cpu->cd.avr.sreg & AVR_SREG_C? 'C' : 'c');
148 dpavlin 24 if (cpu->cd.avr.is_22bit)
149     debug(" pc = 0x%06x", (int)cpu->pc);
150     else
151     debug(" pc = 0x%04x", (int)cpu->pc);
152 dpavlin 14 debug(" <%s>\n", symbol != NULL? symbol : " no symbol ");
153    
154     for (i=0; i<N_AVR_REGS; i++) {
155 dpavlin 24 int r = (i >> 3) + ((i & 7) << 2);
156     if ((i % 8) == 0)
157     debug("cpu%i:", x);
158     debug(" r%02i=0x%02x", r, cpu->cd.avr.r[r]);
159     if ((i % 8) == 7)
160     debug("\n");
161 dpavlin 14 }
162 dpavlin 24
163     debug("cpu%i: x=%i, y=%i, z=%i, sp=0x%04x\n", x,
164     (int)(int16_t)(cpu->cd.avr.r[27]*256 + cpu->cd.avr.r[26]),
165     (int)(int16_t)(cpu->cd.avr.r[29]*256 + cpu->cd.avr.r[28]),
166     (int)(int16_t)(cpu->cd.avr.r[31]*256 + cpu->cd.avr.r[30]),
167     cpu->cd.avr.sp);
168 dpavlin 14 }
169    
170     debug("cpu%i: nr of instructions: %lli\n", x,
171 dpavlin 28 (long long)cpu->machine->ninstrs);
172 dpavlin 14 debug("cpu%i: nr of cycles: %lli\n", x,
173 dpavlin 28 (long long)(cpu->machine->ninstrs + cpu->cd.avr.extra_cycles));
174 dpavlin 14 }
175    
176    
177     /*
178     * avr_cpu_register_match():
179     */
180     void avr_cpu_register_match(struct machine *m, char *name,
181     int writeflag, uint64_t *valuep, int *match_register)
182     {
183     int cpunr = 0;
184    
185     /* CPU number: */
186     /* TODO */
187    
188     if (strcasecmp(name, "pc") == 0) {
189     if (writeflag) {
190     m->cpus[cpunr]->pc = *valuep;
191     } else
192     *valuep = m->cpus[cpunr]->pc;
193     *match_register = 1;
194     } else if (name[0] == 'r' && isdigit((int)name[1])) {
195     int nr = atoi(name + 1);
196     if (nr >= 0 && nr < N_AVR_REGS) {
197     if (writeflag)
198     m->cpus[cpunr]->cd.avr.r[nr] = *valuep;
199     else
200     *valuep = m->cpus[cpunr]->cd.avr.r[nr];
201     *match_register = 1;
202     }
203     }
204     }
205    
206    
207     /*
208 dpavlin 24 * avr_cpu_tlbdump():
209     *
210     * Called from the debugger to dump the TLB in a readable format.
211     * x is the cpu number to dump, or -1 to dump all CPUs.
212     *
213     * If rawflag is nonzero, then the TLB contents isn't formated nicely,
214     * just dumped.
215     */
216     void avr_cpu_tlbdump(struct machine *m, int x, int rawflag)
217     {
218     }
219    
220    
221     /*
222     * avr_cpu_gdb_stub():
223     *
224     * Execute a "remote GDB" command. Returns a newly allocated response string
225     * on success, NULL on failure.
226     */
227     char *avr_cpu_gdb_stub(struct cpu *cpu, char *cmd)
228     {
229     fatal("avr_cpu_gdb_stub(): TODO\n");
230     return NULL;
231     }
232    
233    
234     /*
235 dpavlin 14 * avr_cpu_interrupt():
236     */
237     int avr_cpu_interrupt(struct cpu *cpu, uint64_t irq_nr)
238     {
239     fatal("avr_cpu_interrupt(): TODO\n");
240     return 0;
241     }
242    
243    
244     /*
245     * avr_cpu_interrupt_ack():
246     */
247     int avr_cpu_interrupt_ack(struct cpu *cpu, uint64_t irq_nr)
248     {
249     /* fatal("avr_cpu_interrupt_ack(): TODO\n"); */
250     return 0;
251     }
252    
253    
254     /* Helper functions: */
255     static void print_two(unsigned char *instr, int *len)
256     { debug(" %02x %02x", instr[*len], instr[*len+1]); (*len) += 2; }
257     static void print_spaces(int len) { int i; debug(" "); for (i=0; i<15-len/2*6;
258     i++) debug(" "); }
259    
260    
261     /*
262     * avr_cpu_disassemble_instr():
263     *
264     * Convert an instruction word into human readable format, for instruction
265     * tracing and disassembly.
266     *
267     * If running is 1, cpu->pc should be the address of the instruction.
268     *
269     * If running is 0, things that depend on the runtime environment (eg.
270     * register contents) will not be shown, and addr will be used instead of
271     * cpu->pc for relative addresses.
272     */
273     int avr_cpu_disassemble_instr(struct cpu *cpu, unsigned char *ib,
274 dpavlin 24 int running, uint64_t dumpaddr)
275 dpavlin 14 {
276     uint64_t offset;
277     int len = 0, addr, iw, rd, rr, imm;
278     char *symbol;
279     char *sreg_names = SREG_NAMES;
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: ", cpu->cpu_id);
291    
292     /* TODO: 22-bit PC */
293     debug("0x%04x: ", (int)dumpaddr);
294    
295     print_two(ib, &len);
296     iw = (ib[1] << 8) + ib[0];
297    
298     if ((iw & 0xffff) == 0x0000) {
299     print_spaces(len);
300     debug("nop\n");
301 dpavlin 24 } else if ((iw & 0xff00) == 0x0100) {
302 dpavlin 14 print_spaces(len);
303 dpavlin 24 rd = (iw >> 3) & 30;
304     rr = (iw << 1) & 30;
305     debug("movw\tr%i:r%i,r%i:r%i\n", rd+1, rd, rr+1, rr);
306     } else if ((iw & 0xff00) == 0x0200) {
307     print_spaces(len);
308     rd = ((iw >> 4) & 15) + 16;
309     rr = (iw & 15) + 16;
310     debug("muls\tr%i,r%i\n", rd, rr);
311     } else if ((iw & 0xff88) == 0x0300) {
312     print_spaces(len);
313     rd = ((iw >> 4) & 7) + 16;
314     rr = (iw & 7) + 16;
315     debug("mulsu\tr%i,r%i\n", rd, rr);
316     } else if ((iw & 0xff88) == 0x0308) {
317     print_spaces(len);
318     rd = ((iw >> 4) & 7) + 16;
319     rr = (iw & 7) + 16;
320     debug("fmul\tr%i,r%i\n", rd, rr);
321     } else if ((iw & 0xff88) == 0x0380) {
322     print_spaces(len);
323     rd = ((iw >> 4) & 7) + 16;
324     rr = (iw & 7) + 16;
325     debug("fmuls\tr%i,r%i\n", rd, rr);
326     } else if ((iw & 0xff88) == 0x0388) {
327     print_spaces(len);
328     rd = ((iw >> 4) & 7) + 16;
329     rr = (iw & 7) + 16;
330     debug("fmulsu\tr%i,r%i\n", rd, rr);
331     } else if ((iw & 0xec00) == 0x0400) {
332     print_spaces(len);
333 dpavlin 14 rd = (iw & 0x1f0) >> 4;
334     rr = ((iw & 0x200) >> 5) | (iw & 0xf);
335 dpavlin 24 debug("cp%s\tr%i,r%i\n", iw & 0x1000? "" : "c", rd, rr);
336     } else if ((iw & 0xec00) == 0x0800) {
337 dpavlin 14 print_spaces(len);
338     rd = (iw & 0x1f0) >> 4;
339     rr = ((iw & 0x200) >> 5) | (iw & 0xf);
340 dpavlin 24 debug("%s\tr%i,r%i\n", iw & 0x1000? "sub" : "sbc", rd, rr);
341     } else if ((iw & 0xec00) == 0x0c00) {
342     print_spaces(len);
343     rd = (iw & 0x1f0) >> 4;
344     rr = ((iw & 0x200) >> 5) | (iw & 0xf);
345     debug("%s\tr%i,r%i\n", iw & 0x1000? "adc" : "add", rd, rr);
346     } else if ((iw & 0xfc00) == 0x1000) {
347     print_spaces(len);
348     rd = (iw & 0x1f0) >> 4;
349     rr = ((iw & 0x200) >> 5) | (iw & 0xf);
350     debug("cpse\tr%i,r%i\n", rd, rr);
351 dpavlin 14 } else if ((iw & 0xfc00) == 0x2000) {
352     print_spaces(len);
353     rd = (iw & 0x1f0) >> 4;
354     rr = ((iw & 0x200) >> 5) | (iw & 0xf);
355     debug("and\tr%i,r%i\n", rd, rr);
356 dpavlin 24 } else if ((iw & 0xfc00) == 0x2400) {
357     print_spaces(len);
358     rd = (iw & 0x1f0) >> 4;
359     rr = ((iw & 0x200) >> 5) | (iw & 0xf);
360     debug("eor\tr%i,r%i\n", rd, rr);
361     } else if ((iw & 0xfc00) == 0x2800) {
362     print_spaces(len);
363     rd = (iw & 0x1f0) >> 4;
364     rr = ((iw & 0x200) >> 5) | (iw & 0xf);
365     debug("or\tr%i,r%i\n", rd, rr);
366 dpavlin 14 } else if ((iw & 0xfc00) == 0x2c00) {
367     print_spaces(len);
368     rd = (iw & 0x1f0) >> 4;
369     rr = ((iw & 0x200) >> 5) | (iw & 0xf);
370     debug("mov\tr%i,r%i\n", rd, rr);
371 dpavlin 24 } else if ((iw & 0xf000) == 0x3000) {
372     print_spaces(len);
373     rd = ((iw >> 4) & 15) + 16;
374     imm = ((iw >> 4) & 0xf0) + (iw & 15);
375     debug("cpi\tr%i,0x%x\n", rd, imm);
376     } else if ((iw & 0xf000) == 0x4000) {
377     print_spaces(len);
378     rd = ((iw >> 4) & 15) + 16;
379     imm = ((iw >> 4) & 0xf0) + (iw & 15);
380     debug("sbci\tr%i,0x%x\n", rd, imm);
381     } else if ((iw & 0xf000) == 0x5000) {
382     print_spaces(len);
383     rd = ((iw >> 4) & 15) + 16;
384     imm = ((iw >> 4) & 0xf0) + (iw & 15);
385     debug("subi\tr%i,0x%x\n", rd, imm);
386     } else if ((iw & 0xe000) == 0x6000) {
387     print_spaces(len);
388     rd = ((iw >> 4) & 15) + 16;
389     imm = ((iw >> 4) & 0xf0) + (iw & 15);
390     debug("%s\tr%i,0x%x\n", iw & 0x1000? "andi" : "ori", rd, imm);
391 dpavlin 14 } else if ((iw & 0xfe0f) == 0x8000) {
392     print_spaces(len);
393     rd = (iw >> 4) & 31;
394     debug("ld\tr%i,Z\n", rd);
395     } else if ((iw & 0xfe0f) == 0x8008) {
396     print_spaces(len);
397     rd = (iw >> 4) & 31;
398     debug("ld\tr%i,Y\n", rd);
399 dpavlin 24 } else if ((iw & 0xfe0f) == 0x8208) {
400     print_spaces(len);
401     rd = (iw >> 4) & 31;
402     debug("st\tY,r%i\n", rd);
403 dpavlin 14 } else if ((iw & 0xfe0f) == 0x900c) {
404     print_spaces(len);
405     rd = (iw >> 4) & 31;
406     debug("ld\tr%i,X\n", rd);
407     } else if ((iw & 0xfc0f) == 0x900f) {
408     print_spaces(len);
409     rd = (iw >> 4) & 31;
410     debug("%s\tr%i\n", iw & 0x200? "push" : "pop", rd);
411 dpavlin 24 } else if ((iw & 0xfe0f) == 0x9000) {
412 dpavlin 14 print_two(ib, &len);
413     addr = (ib[3] << 8) + ib[2];
414     print_spaces(len);
415 dpavlin 24 if (iw & 0x200)
416     debug("sts\t0x%x,r%i\n", addr, (iw & 0x1f0) >> 4);
417     else
418     debug("lds\tr%i,0x%x\n", (iw & 0x1f0) >> 4, addr);
419     } else if ((iw & 0xfe0f) == 0x9209) {
420     print_spaces(len);
421     rr = (iw >> 4) & 31;
422     debug("st\tY+,r%i\n", rr);
423     } else if ((iw & 0xfe0f) == 0x920a) {
424     print_spaces(len);
425     rr = (iw >> 4) & 31;
426     debug("st\t-Y,r%i\n", rr);
427     } else if ((iw & 0xfe0f) == 0x9401) {
428     print_spaces(len);
429     rd = (iw >> 4) & 31;
430     debug("neg\tr%i\n", rd);
431 dpavlin 14 } else if ((iw & 0xfe0f) == 0x9402) {
432     print_spaces(len);
433     rd = (iw >> 4) & 31;
434     debug("swap\tr%i\n", rd);
435 dpavlin 24 } else if ((iw & 0xfe0f) == 0x9403) {
436     print_spaces(len);
437     rd = (iw >> 4) & 31;
438     debug("inc\tr%i\n", rd);
439 dpavlin 14 } else if ((iw & 0xff0f) == 0x9408) {
440     print_spaces(len);
441     rd = (iw >> 4) & 7;
442     debug("%s%c\n", iw & 0x80? "cl" : "se", sreg_names[rd]);
443 dpavlin 24 } else if ((iw & 0xfe0f) == 0x940a) {
444     print_spaces(len);
445     rd = (iw >> 4) & 31;
446     debug("dec\tr%i\n", rd);
447     } else if ((iw & 0xff8f) == 0x9408) {
448     print_spaces(len);
449     debug("bset\t%i\n", (iw >> 4) & 7);
450     } else if ((iw & 0xff8f) == 0x9488) {
451     print_spaces(len);
452     debug("bclr\t%i\n", (iw >> 4) & 7);
453 dpavlin 14 } else if ((iw & 0xffef) == 0x9508) {
454     /* ret and reti */
455     print_spaces(len);
456     debug("ret%s\n", (iw & 0x10)? "i" : "");
457     } else if ((iw & 0xffff) == 0x9588) {
458     print_spaces(len);
459     debug("sleep\n");
460 dpavlin 24 } else if ((iw & 0xffff) == 0x9598) {
461     print_spaces(len);
462     debug("break\n");
463 dpavlin 14 } else if ((iw & 0xffff) == 0x95a8) {
464     print_spaces(len);
465     debug("wdr\n");
466 dpavlin 24 } else if ((iw & 0xffef) == 0x95c8) {
467     print_spaces(len);
468     debug("%slpm\n", iw & 0x0010? "e" : "");
469 dpavlin 14 } else if ((iw & 0xff00) == 0x9600) {
470     print_spaces(len);
471     imm = ((iw & 0xc0) >> 2) | (iw & 0xf);
472     rd = ((iw >> 4) & 3) * 2 + 24;
473     debug("adiw\tr%i:r%i,0x%x\n", rd, rd+1, imm);
474 dpavlin 24 } else if ((iw & 0xfd00) == 0x9800) {
475     print_spaces(len);
476     imm = iw & 7;
477     rd = (iw >> 3) & 31; /* A */
478     debug("%sbi\t0x%x,%i\n", iw & 0x0200? "s" : "c", rd, imm);
479     } else if ((iw & 0xfd00) == 0x9900) {
480     print_spaces(len);
481     imm = iw & 7;
482     rd = (iw >> 3) & 31; /* A */
483     debug("sbi%s\t0x%x,%i\n", iw & 0x0200? "s" : "c", rd, imm);
484     } else if ((iw & 0xf000) == 0xb000) {
485     print_spaces(len);
486     imm = ((iw & 0x600) >> 5) | (iw & 0xf);
487     rr = (iw >> 4) & 31;
488     if (iw & 0x800)
489     debug("out\t0x%x,r%i\n", imm, rr);
490     else
491     debug("in\tr%i,0x%x\n", rr, imm);
492 dpavlin 14 } else if ((iw & 0xe000) == 0xc000) {
493     print_spaces(len);
494     addr = (int16_t)((iw & 0xfff) << 4);
495     addr = (addr >> 3) + dumpaddr + 2;
496     debug("%s\t0x%x\n", iw & 0x1000? "rcall" : "rjmp", addr);
497     } else if ((iw & 0xf000) == 0xe000) {
498     print_spaces(len);
499     rd = ((iw >> 4) & 0xf) + 16;
500     imm = ((iw >> 4) & 0xf0) | (iw & 0xf);
501     debug("ldi\tr%i,0x%x\n", rd, imm);
502 dpavlin 24 } else if ((iw & 0xfc00) == 0xf000) {
503     print_spaces(len);
504     addr = (iw >> 3) & 0x7f;
505     if (addr >= 64)
506     addr -= 128;
507     addr = (addr + 1) * 2 + dumpaddr;
508     debug("brbs\t%c,0x%x\n", sreg_names[iw & 7], addr);
509     } else if ((iw & 0xfc00) == 0xf400) {
510     print_spaces(len);
511     addr = (iw >> 3) & 0x7f;
512     if (addr >= 64)
513     addr -= 128;
514     addr = (addr + 1) * 2 + dumpaddr;
515     debug("brbc\t%c,0x%x\n", sreg_names[iw & 7], addr);
516     } else if ((iw & 0xfc08) == 0xfc00) {
517     print_spaces(len);
518     rr = (iw >> 4) & 31;
519     imm = iw & 7;
520     debug("sbr%s\tr%i,%i\n", iw & 0x0200 ? "s" : "c", rr, imm);
521 dpavlin 14 } else {
522     print_spaces(len);
523     debug("UNIMPLEMENTED 0x%04x\n", iw);
524     }
525    
526     return len;
527     }
528    
529    
530     #include "tmp_avr_tail.c"
531    

  ViewVC Help
Powered by ViewVC 1.1.26