/[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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 28 - (show annotations)
Mon Oct 8 16:20:26 2007 UTC (16 years, 5 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 /*
2 * Copyright (C) 2005-2006 Anders Gavare. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * 3. The name of the author may not be used to endorse or promote products
13 * derived from this software without specific prior written permission.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 *
27 *
28 * $Id: cpu_avr.c,v 1.20 2006/07/16 13:32:26 debug Exp $
29 *
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 #define DYNTRANS_VARIABLE_INSTRUCTION_LENGTH
47 #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 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 return 0;
73
74 cpu->run_instr = avr_run_instr;
75 cpu->memory_rw = avr_memory_rw;
76 cpu->update_translation_table = avr_update_translation_table;
77 cpu->invalidate_translation_caches =
78 avr_invalidate_translation_caches;
79 cpu->invalidate_code_translation = avr_invalidate_code_translation;
80 cpu->is_32bit = 1;
81
82 cpu->byte_order = EMUL_LITTLE_ENDIAN;
83
84 cpu->cd.avr.is_22bit = (type == 22);
85 cpu->cd.avr.pc_mask = cpu->cd.avr.is_22bit? 0x3fffff : 0xffff;
86
87 cpu->cd.avr.sram_mask = 0xff; /* 256 bytes ram */
88 cpu->cd.avr.sp = cpu->cd.avr.sram_mask - 2;
89
90 /* 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 debug("AVR\tAVR16\tAVR22\n");
107 }
108
109
110 /*
111 * avr_cpu_dumpinfo():
112 */
113 void avr_cpu_dumpinfo(struct cpu *cpu)
114 {
115 debug(" (%i-bit program counter)\n",
116 cpu->cd.avr.is_22bit? 22 : 16);
117 }
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 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 debug(" <%s>\n", symbol != NULL? symbol : " no symbol ");
153
154 for (i=0; i<N_AVR_REGS; i++) {
155 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 }
162
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 }
169
170 debug("cpu%i: nr of instructions: %lli\n", x,
171 (long long)cpu->machine->ninstrs);
172 debug("cpu%i: nr of cycles: %lli\n", x,
173 (long long)(cpu->machine->ninstrs + cpu->cd.avr.extra_cycles));
174 }
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 * 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 * 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 int running, uint64_t dumpaddr)
275 {
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 } else if ((iw & 0xff00) == 0x0100) {
302 print_spaces(len);
303 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 rd = (iw & 0x1f0) >> 4;
334 rr = ((iw & 0x200) >> 5) | (iw & 0xf);
335 debug("cp%s\tr%i,r%i\n", iw & 0x1000? "" : "c", rd, rr);
336 } else if ((iw & 0xec00) == 0x0800) {
337 print_spaces(len);
338 rd = (iw & 0x1f0) >> 4;
339 rr = ((iw & 0x200) >> 5) | (iw & 0xf);
340 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 } 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 } 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 } 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 } 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 } 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 } else if ((iw & 0xfe0f) == 0x8208) {
400 print_spaces(len);
401 rd = (iw >> 4) & 31;
402 debug("st\tY,r%i\n", rd);
403 } 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 } else if ((iw & 0xfe0f) == 0x9000) {
412 print_two(ib, &len);
413 addr = (ib[3] << 8) + ib[2];
414 print_spaces(len);
415 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 } else if ((iw & 0xfe0f) == 0x9402) {
432 print_spaces(len);
433 rd = (iw >> 4) & 31;
434 debug("swap\tr%i\n", rd);
435 } else if ((iw & 0xfe0f) == 0x9403) {
436 print_spaces(len);
437 rd = (iw >> 4) & 31;
438 debug("inc\tr%i\n", rd);
439 } 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 } 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 } 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 } else if ((iw & 0xffff) == 0x9598) {
461 print_spaces(len);
462 debug("break\n");
463 } else if ((iw & 0xffff) == 0x95a8) {
464 print_spaces(len);
465 debug("wdr\n");
466 } else if ((iw & 0xffef) == 0x95c8) {
467 print_spaces(len);
468 debug("%slpm\n", iw & 0x0010? "e" : "");
469 } 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 } 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 } 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 } 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 } 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