]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - sim/moxie/interp.c
Add moxie simulator
[thirdparty/binutils-gdb.git] / sim / moxie / interp.c
1 /* Simulator for the moxie processor
2 Copyright (C) 2008, 2009 Free Software Foundation, Inc.
3 Contributed by Anthony Green
4
5 This file is part of GDB, the GNU debugger.
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>. */
19
20 #include <signal.h>
21 #include <stdlib.h>
22 #include "sysdep.h"
23 #include <sys/times.h>
24 #include <sys/param.h>
25 #include <netinet/in.h> /* for byte ordering macros */
26 #include "bfd.h"
27 #include "gdb/callback.h"
28 #include "libiberty.h"
29 #include "gdb/remote-sim.h"
30
31 typedef int word;
32 typedef unsigned int uword;
33
34 host_callback * callback;
35
36 FILE *tracefile;
37
38 #define EXTRACT_WORD(addr) (((addr)[0] << 24) \
39 + ((addr)[1] << 16) \
40 + ((addr)[2] << 8) \
41 + ((addr)[3]))
42
43 unsigned long
44 moxie_extract_unsigned_integer (addr, len)
45 unsigned char * addr;
46 int len;
47 {
48 unsigned long retval;
49 unsigned char * p;
50 unsigned char * startaddr = (unsigned char *)addr;
51 unsigned char * endaddr = startaddr + len;
52
53 if (len > (int) sizeof (unsigned long))
54 printf ("That operation is not available on integers of more than %d bytes.",
55 sizeof (unsigned long));
56
57 /* Start at the most significant end of the integer, and work towards
58 the least significant. */
59 retval = 0;
60
61 for (p = endaddr; p > startaddr;)
62 retval = (retval << 8) | * -- p;
63
64 return retval;
65 }
66
67 void
68 moxie_store_unsigned_integer (addr, len, val)
69 unsigned char * addr;
70 int len;
71 unsigned long val;
72 {
73 unsigned char * p;
74 unsigned char * startaddr = (unsigned char *)addr;
75 unsigned char * endaddr = startaddr + len;
76
77 for (p = endaddr; p > startaddr;)
78 {
79 * -- p = val & 0xff;
80 val >>= 8;
81 }
82 }
83
84 /* moxie register names. */
85 static const char *reg_names[16] =
86 { "$fp", "$sp", "$r0", "$r1", "$r2", "$r3", "$r4", "$r5",
87 "$r6", "$r7", "$r8", "$r9", "$r10", "$r11", "$r12", "$r13" };
88
89 /* The machine state.
90
91 This state is maintained in host byte order. The fetch/store
92 register functions must translate between host byte order and the
93 target processor byte order. Keeping this data in target byte
94 order simplifies the register read/write functions. Keeping this
95 data in native order improves the performance of the simulator.
96 Simulation speed is deemed more important. */
97
98 #define NUM_MOXIE_REGS 17 /* Including PC */
99 #define NUM_MOXIE_SREGS 256 /* The special registers */
100 #define PC_REGNO 16
101
102 /* The ordering of the moxie_regset structure is matched in the
103 gdb/config/moxie/tm-moxie.h file in the REGISTER_NAMES macro. */
104 struct moxie_regset
105 {
106 word regs[NUM_MOXIE_REGS + 1]; /* primary registers */
107 word sregs[256]; /* special registers */
108 word cc; /* the condition code reg */
109 int exception;
110 unsigned long msize;
111 unsigned char * memory;
112 unsigned long long insts; /* instruction counter */
113 };
114
115 #define CC_GT 1<<0
116 #define CC_LT 1<<1
117 #define CC_EQ 1<<2
118 #define CC_GTU 1<<3
119 #define CC_LTU 1<<4
120
121 union
122 {
123 struct moxie_regset asregs;
124 word asints [1]; /* but accessed larger... */
125 } cpu;
126
127 static char *myname;
128 static SIM_OPEN_KIND sim_kind;
129 static int issue_messages = 0;
130
131 /* Default to a 8 Mbyte (== 2^23) memory space. */
132 static int sim_memory_size = 23;
133
134 #define MEM_SIZE_FLOOR 64
135 void
136 sim_size (power)
137 int power;
138 {
139 sim_memory_size = power;
140 cpu.asregs.msize = 1 << sim_memory_size;
141
142 if (cpu.asregs.memory)
143 free (cpu.asregs.memory);
144
145 /* Watch out for the '0 count' problem. There's probably a better
146 way.. e.g., why do we use 64 here? */
147 if (cpu.asregs.msize < 64) /* Ensure a boundary. */
148 cpu.asregs.memory = (unsigned char *) calloc (64, (64 + cpu.asregs.msize) / 64);
149 else
150 cpu.asregs.memory = (unsigned char *) calloc (64, cpu.asregs.msize / 64);
151
152 if (!cpu.asregs.memory)
153 {
154 if (issue_messages)
155 fprintf (stderr,
156 "Not enough VM for simulation of %d bytes of RAM\n",
157 cpu.asregs.msize);
158
159 cpu.asregs.msize = 1;
160 cpu.asregs.memory = (unsigned char *) calloc (1, 1);
161 }
162 }
163
164 static void
165 init_pointers ()
166 {
167 if (cpu.asregs.msize != (1 << sim_memory_size))
168 sim_size (sim_memory_size);
169 }
170
171
172 static void
173 set_initial_gprs ()
174 {
175 int i;
176 long space;
177 unsigned long memsize;
178
179 init_pointers ();
180
181 /* Set up machine just out of reset. */
182 cpu.asregs.regs[PC_REGNO] = 0;
183
184 memsize = cpu.asregs.msize / (1024 * 1024);
185
186 if (issue_messages > 1)
187 fprintf (stderr, "Simulated memory of %d Mbytes (0x0 .. 0x%08x)\n",
188 memsize, cpu.asregs.msize - 1);
189
190 /* Clean out the register contents. */
191 for (i = 0; i < NUM_MOXIE_REGS; i++)
192 cpu.asregs.regs[i] = 0;
193 for (i = 0; i < NUM_MOXIE_SREGS; i++)
194 cpu.asregs.sregs[i] = 0;
195 }
196
197 static void
198 interrupt ()
199 {
200 cpu.asregs.exception = SIGINT;
201 }
202
203 /* Write a 1 byte value to memory. */
204
205 static void INLINE
206 wbat (pc, x, v)
207 word pc, x, v;
208 {
209 if (((uword)x) >= cpu.asregs.msize)
210 {
211 if (issue_messages)
212 fprintf (stderr, "byte write to 0x%x outside memory range\n", x);
213
214 cpu.asregs.exception = SIGSEGV;
215 }
216 else
217 {
218 {
219 unsigned char * p = cpu.asregs.memory + x;
220 *p = v;
221 }
222 }
223 }
224
225 /* Write a 2 byte value to memory. */
226
227 static void INLINE
228 wsat (pc, x, v)
229 word pc, x, v;
230 {
231 if (((uword)x) >= cpu.asregs.msize)
232 {
233 if (issue_messages)
234 fprintf (stderr, "short word write to 0x%x outside memory range\n", x);
235
236 cpu.asregs.exception = SIGSEGV;
237 }
238 else
239 {
240 if ((x & 1) != 0)
241 {
242 if (issue_messages)
243 fprintf (stderr, "short word write to unaligned memory address: 0x%x\n", x);
244
245 cpu.asregs.exception = SIGBUS;
246 }
247 {
248 unsigned char * p = cpu.asregs.memory + x;
249 p[0] = v >> 8;
250 p[1] = v;
251 }
252 }
253 }
254
255 /* Write a 4 byte value to memory. */
256
257 static void INLINE
258 wlat (pc, x, v)
259 word pc, x, v;
260 {
261 if (((uword)x) >= cpu.asregs.msize)
262 {
263 if (issue_messages)
264 fprintf (stderr, "word write to 0x%x outside memory range\n", x);
265
266 cpu.asregs.exception = SIGSEGV;
267 }
268 else
269 {
270 if ((x & 1) != 0)
271 {
272 if (issue_messages)
273 fprintf (stderr, "word write to unaligned memory address: 0x%x\n", x);
274
275 cpu.asregs.exception = SIGBUS;
276 }
277 {
278 unsigned char * p = cpu.asregs.memory + x;
279 p[0] = v >> 24;
280 p[1] = v >> 16;
281 p[2] = v >> 8;
282 p[3] = v;
283 }
284 }
285 }
286
287 /* Read 2 bytes from memory. */
288
289 static int INLINE
290 rsat (pc, x)
291 word pc, x;
292 {
293 if (((uword) x) >= cpu.asregs.msize)
294 {
295 if (issue_messages)
296 fprintf (stderr, "short word read from 0x%x outside memory range\n", x);
297
298 cpu.asregs.exception = SIGSEGV;
299 return 0;
300 }
301 else
302 {
303 if ((x & 1) != 0)
304 {
305 if (issue_messages)
306 fprintf (stderr, "short word read from unaligned address: 0x%x\n", x);
307
308 cpu.asregs.exception = SIGBUS;
309 return 0;
310 }
311 {
312 unsigned char * p = cpu.asregs.memory + x;
313 return (p[0] << 8) | p[1];
314 }
315 }
316 }
317
318 /* Read 1 byte from memory. */
319
320 static int INLINE
321 rbat (pc, x)
322 word pc, x;
323 {
324 if (((uword) x) >= cpu.asregs.msize)
325 {
326 if (issue_messages)
327 fprintf (stderr, "byte read from 0x%x outside memory range\n", x);
328
329 cpu.asregs.exception = SIGSEGV;
330 return 0;
331 }
332 else
333 {
334 unsigned char * p = cpu.asregs.memory + x;
335 return *p;
336 }
337 }
338
339 /* Read 4 bytes from memory. */
340
341 static int INLINE
342 rlat (pc, x)
343 word pc, x;
344 {
345 if (((uword) x) >= cpu.asregs.msize)
346 {
347 if (issue_messages)
348 fprintf (stderr, "word read from 0x%x outside memory range\n", x);
349
350 cpu.asregs.exception = SIGSEGV;
351 return 0;
352 }
353 else
354 {
355 if ((x & 3) != 0)
356 {
357 if (issue_messages)
358 fprintf (stderr, "word read from unaligned address: 0x%x\n", x);
359
360 cpu.asregs.exception = SIGBUS;
361 return 0;
362 }
363 {
364 unsigned char * p = cpu.asregs.memory + x;
365 return (EXTRACT_WORD(p));
366 }
367 }
368 }
369
370 #define CHECK_FLAG(T,H) if (tflags & T) { hflags |= H; tflags ^= T; }
371
372 unsigned int
373 convert_target_flags (unsigned int tflags)
374 {
375 unsigned int hflags = 0x0;
376
377 CHECK_FLAG(0x0001, O_WRONLY);
378 CHECK_FLAG(0x0002, O_RDWR);
379 CHECK_FLAG(0x0008, O_APPEND);
380 CHECK_FLAG(0x0200, O_CREAT);
381 CHECK_FLAG(0x0400, O_TRUNC);
382 CHECK_FLAG(0x0800, O_EXCL);
383 CHECK_FLAG(0x2000, O_SYNC);
384
385 if (tflags != 0x0)
386 fprintf (stderr,
387 "Simulator Error: problem converting target open flags for host. 0x%x\n",
388 tflags);
389
390 return hflags;
391 }
392
393 #define TRACE(str) if (tracing) fprintf(tracefile,"0x%08x, %s, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x\n", opc, str, cpu.asregs.regs[0], cpu.asregs.regs[1], cpu.asregs.regs[2], cpu.asregs.regs[3], cpu.asregs.regs[4], cpu.asregs.regs[5], cpu.asregs.regs[6], cpu.asregs.regs[7], cpu.asregs.regs[8], cpu.asregs.regs[9], cpu.asregs.regs[10], cpu.asregs.regs[11], cpu.asregs.regs[12], cpu.asregs.regs[13], cpu.asregs.regs[14], cpu.asregs.regs[15]);
394
395 static int tracing = 0;
396
397 void
398 sim_resume (sd, step, siggnal)
399 SIM_DESC sd;
400 int step, siggnal;
401 {
402 word pc, opc;
403 unsigned long long insts;
404 unsigned short inst;
405 void (* sigsave)();
406
407 sigsave = signal (SIGINT, interrupt);
408 cpu.asregs.exception = step ? SIGTRAP: 0;
409 pc = cpu.asregs.regs[PC_REGNO];
410 insts = cpu.asregs.insts;
411 unsigned char *memory = cpu.asregs.memory;
412
413 /* Run instructions here. */
414 do
415 {
416 opc = pc;
417
418 /* Fetch the instruction at pc. */
419 inst = (memory[pc] << 8) + memory[pc + 1];
420
421 /* Decode instruction. */
422 if (inst & (1 << 15))
423 {
424 if (inst & (1 << 14))
425 {
426 /* This is a Form 3 instruction. */
427 /* We haven't implemented any yet, so just SIGILL for now. */
428 TRACE("SIGILL3");
429 cpu.asregs.exception = SIGILL;
430 break;
431 }
432 else
433 {
434 /* This is a Form 2 instruction. */
435 int opcode = (inst >> 12 & 0x3);
436 switch (opcode)
437 {
438 case 0x00: /* inc */
439 {
440 int a = (inst >> 8) & 0xf;
441 unsigned av = cpu.asregs.regs[a];
442 unsigned v = (inst & 0xff);
443 TRACE("inc");
444 cpu.asregs.regs[a] = av + v;
445 }
446 break;
447 case 0x01: /* dec */
448 {
449 int a = (inst >> 8) & 0xf;
450 unsigned av = cpu.asregs.regs[a];
451 unsigned v = (inst & 0xff);
452 TRACE("dec");
453 cpu.asregs.regs[a] = av - v;
454 }
455 break;
456 case 0x02: /* gsr */
457 {
458 int a = (inst >> 8) & 0xf;
459 unsigned v = (inst & 0xff);
460 TRACE("gsr");
461 cpu.asregs.regs[a] = cpu.asregs.sregs[v];
462 }
463 case 0x03: /* ssr */
464 {
465 int a = (inst >> 8) & 0xf;
466 unsigned v = (inst & 0xff);
467 TRACE("ssr");
468 cpu.asregs.sregs[v] = cpu.asregs.regs[a];
469 }
470 default:
471 TRACE("SIGILL2");
472 cpu.asregs.exception = SIGILL;
473 break;
474 }
475 }
476 }
477 else
478 {
479 /* This is a Form 1 instruction. */
480 int opcode = inst >> 8;
481 switch (opcode)
482 {
483 case 0x00: /* nop */
484 break;
485 case 0x01: /* ldi.l (immediate) */
486 {
487 int reg = (inst >> 4) & 0xf;
488 TRACE("ldi.l");
489 unsigned int val = EXTRACT_WORD(&(memory[pc + 2]));
490 cpu.asregs.regs[reg] = val;
491 pc += 4;
492 }
493 break;
494 case 0x02: /* mov (register-to-register) */
495 {
496 int dest = (inst >> 4) & 0xf;
497 int src = (inst ) & 0xf;
498 TRACE("mov");
499 cpu.asregs.regs[dest] = cpu.asregs.regs[src];
500 }
501 break;
502 case 0x03: /* jsra */
503 {
504 unsigned int fn = EXTRACT_WORD(&(memory[pc + 2]));
505 unsigned int sp = cpu.asregs.regs[1];
506 TRACE("jsra");
507 /* Save a slot for the static chain. */
508 sp -= 4;
509
510 /* Push the return address. */
511 sp -= 4;
512 wlat (opc, sp, pc + 6);
513
514 /* Push the current frame pointer. */
515 sp -= 4;
516 wlat (opc, sp, cpu.asregs.regs[0]);
517
518 /* Uncache the stack pointer and set the pc and $fp. */
519 cpu.asregs.regs[1] = sp;
520 cpu.asregs.regs[0] = sp;
521 pc = fn - 2;
522 }
523 break;
524 case 0x04: /* ret */
525 {
526 unsigned int sp = cpu.asregs.regs[0];
527
528 TRACE("ret");
529
530 /* Pop the frame pointer. */
531 cpu.asregs.regs[0] = rlat (opc, sp);
532 sp += 4;
533
534 /* Pop the return address. */
535 pc = rlat (opc, sp) - 2;
536 sp += 4;
537
538 /* Skip over the static chain slot. */
539 sp += 4;
540
541 /* Uncache the stack pointer. */
542 cpu.asregs.regs[1] = sp;
543 }
544 break;
545 case 0x05: /* add.l */
546 {
547 int a = (inst >> 4) & 0xf;
548 int b = inst & 0xf;
549 unsigned av = cpu.asregs.regs[a];
550 unsigned bv = cpu.asregs.regs[b];
551 TRACE("add.l");
552 cpu.asregs.regs[a] = av + bv;
553 }
554 break;
555 case 0x06: /* push */
556 {
557 int a = (inst >> 4) & 0xf;
558 int b = inst & 0xf;
559 int sp = cpu.asregs.regs[a] - 4;
560 TRACE("push");
561 wlat (opc, sp, cpu.asregs.regs[b]);
562 cpu.asregs.regs[a] = sp;
563 }
564 break;
565 case 0x07: /* pop */
566 {
567 int a = (inst >> 4) & 0xf;
568 int b = inst & 0xf;
569 int sp = cpu.asregs.regs[a];
570 TRACE("pop");
571 cpu.asregs.regs[b] = rlat (opc, sp);
572 cpu.asregs.regs[a] = sp + 4;
573 }
574 break;
575 case 0x08: /* lda.l */
576 {
577 int reg = (inst >> 4) & 0xf;
578 unsigned int addr = EXTRACT_WORD(&memory[pc+2]);
579 TRACE("lda.l");
580 cpu.asregs.regs[reg] = rlat (opc, addr);
581 pc += 4;
582 }
583 break;
584 case 0x09: /* sta.l */
585 {
586 int reg = (inst >> 4) & 0xf;
587 unsigned int addr = EXTRACT_WORD(&memory[pc+2]);
588 TRACE("sta.l");
589 wlat (opc, addr, cpu.asregs.regs[reg]);
590 pc += 4;
591 }
592 break;
593 case 0x0a: /* ld.l (register indirect) */
594 {
595 int src = inst & 0xf;
596 int dest = (inst >> 4) & 0xf;
597 int xv;
598 TRACE("ld.l");
599 xv = cpu.asregs.regs[src];
600 cpu.asregs.regs[dest] = rlat (opc, xv);
601 }
602 break;
603 case 0x0b: /* st.l */
604 {
605 int dest = (inst >> 4) & 0xf;
606 int val = inst & 0xf;
607 TRACE("st.l");
608 wlat (opc, cpu.asregs.regs[dest], cpu.asregs.regs[val]);
609 }
610 break;
611 case 0x0c: /* ldo.l */
612 {
613 unsigned int addr = EXTRACT_WORD(&memory[pc+2]);
614 int a = (inst >> 4) & 0xf;
615 int b = inst & 0xf;
616 TRACE("ldo.l");
617 addr += cpu.asregs.regs[b];
618 cpu.asregs.regs[a] = rlat(opc, addr);
619 pc += 4;
620 }
621 break;
622 case 0x0d: /* sto.l */
623 {
624 unsigned int addr = EXTRACT_WORD(&memory[pc+2]);
625 int a = (inst >> 4) & 0xf;
626 int b = inst & 0xf;
627 TRACE("sto.l");
628 addr += cpu.asregs.regs[a];
629 wlat(opc, addr, cpu.asregs.regs[b]);
630 pc += 4;
631 }
632 break;
633 case 0x0e: /* cmp */
634 {
635 int a = (inst >> 4) & 0xf;
636 int b = inst & 0xf;
637 int cc = 0;
638 int va = cpu.asregs.regs[a];
639 int vb = cpu.asregs.regs[b];
640
641 TRACE("cmp");
642
643 if (va == vb)
644 cc = CC_EQ;
645 else
646 {
647 cc |= (va < vb ? CC_LT : 0);
648 cc |= (va > vb ? CC_GT : 0);
649 cc |= ((unsigned int) va < (unsigned int) vb ? CC_LTU : 0);
650 cc |= ((unsigned int) va > (unsigned int) vb ? CC_GTU : 0);
651 }
652
653 cpu.asregs.cc = cc;
654 }
655 break;
656 case 0x0f: /* beq */
657 {
658 unsigned int tgt = EXTRACT_WORD(&memory[pc+2]);
659 TRACE("beq");
660 if (cpu.asregs.cc & CC_EQ)
661 {
662 pc = tgt - 2;
663 }
664 else
665 pc += 4;
666 }
667 break;
668 case 0x10: /* bne */
669 {
670 unsigned int tgt = EXTRACT_WORD(&memory[pc+2]);
671 TRACE("bne");
672 if (! (cpu.asregs.cc & CC_EQ))
673 {
674 pc = tgt - 2;
675 }
676 else
677 pc += 4;
678 }
679 break;
680 case 0x11: /* blt */
681 {
682 unsigned int tgt = EXTRACT_WORD(&memory[pc+2]);
683 TRACE("blt");
684 if (cpu.asregs.cc & CC_LT)
685 {
686 pc = tgt - 2;
687 }
688 else
689 pc += 4;
690 }
691 break;
692 case 0x12: /* bgt */
693 {
694 unsigned int tgt = EXTRACT_WORD(&memory[pc+2]);
695 TRACE("bgt");
696 if (cpu.asregs.cc & CC_GT)
697 {
698 pc = tgt - 2;
699 }
700 else
701 pc += 4;
702 }
703 break;
704 case 0x13: /* bltu */
705 {
706 unsigned int tgt = EXTRACT_WORD(&memory[pc+2]);
707 TRACE("bltu");
708 if (cpu.asregs.cc & CC_LTU)
709 {
710 pc = tgt - 2;
711 }
712 else
713 pc += 4;
714 }
715 break;
716 case 0x14: /* bgtu */
717 {
718 unsigned int tgt = EXTRACT_WORD(&memory[pc+2]);
719 TRACE("bgtu");
720 if (cpu.asregs.cc & CC_GTU)
721 {
722 pc = tgt - 2;
723 }
724 else
725 pc += 4;
726 }
727 break;
728 case 0x15: /* bge */
729 {
730 unsigned int tgt = EXTRACT_WORD(&memory[pc+2]);
731 TRACE("bge");
732 if ((cpu.asregs.cc & CC_GT) || (cpu.asregs.cc & CC_EQ))
733 {
734 pc = tgt - 2;
735 }
736 else
737 pc += 4;
738 }
739 break;
740 case 0x16: /* ble */
741 {
742 unsigned int tgt = EXTRACT_WORD(&memory[pc+2]);
743 TRACE("ble");
744 if ((cpu.asregs.cc & CC_LT) || (cpu.asregs.cc & CC_EQ))
745 {
746 pc = tgt - 2;
747 }
748 else
749 pc += 4;
750 }
751 break;
752 case 0x17: /* bgeu */
753 {
754 unsigned int tgt = EXTRACT_WORD(&memory[pc+2]);
755 TRACE("bgeu");
756 if ((cpu.asregs.cc & CC_GTU) || (cpu.asregs.cc & CC_EQ))
757 {
758 pc = tgt - 2;
759 }
760 else
761 pc += 4;
762 }
763 break;
764 case 0x18: /* bleu */
765 {
766 unsigned int tgt = EXTRACT_WORD(&memory[pc+2]);
767 TRACE("bleu");
768 if ((cpu.asregs.cc & CC_LTU) || (cpu.asregs.cc & CC_EQ))
769 {
770 pc = tgt - 2;
771 }
772 else
773 pc += 4;
774 }
775 break;
776 case 0x19: /* jsr */
777 {
778 unsigned int fn = cpu.asregs.regs[(inst >> 4) & 0xf];
779 unsigned int sp = cpu.asregs.regs[1];
780
781 TRACE("jsr");
782
783 /* Save a slot for the static chain. */
784 sp -= 4;
785
786 /* Push the return address. */
787 sp -= 4;
788 wlat (opc, sp, pc + 2);
789
790 /* Push the current frame pointer. */
791 sp -= 4;
792 wlat (opc, sp, cpu.asregs.regs[0]);
793
794 /* Uncache the stack pointer and set the fp & pc. */
795 cpu.asregs.regs[1] = sp;
796 cpu.asregs.regs[0] = sp;
797 pc = fn - 2;
798 }
799 break;
800 case 0x1a: /* jmpa */
801 {
802 unsigned int tgt = EXTRACT_WORD(&memory[pc+2]);
803 TRACE("jmpa");
804 pc = tgt - 2;
805 }
806 break;
807 case 0x1b: /* ldi.b (immediate) */
808 {
809 int reg = (inst >> 4) & 0xf;
810
811 unsigned int val = EXTRACT_WORD(&(memory[pc + 2]));
812 TRACE("ldi.b");
813 cpu.asregs.regs[reg] = val;
814 pc += 4;
815 }
816 break;
817 case 0x1c: /* ld.b (register indirect) */
818 {
819 int src = inst & 0xf;
820 int dest = (inst >> 4) & 0xf;
821 int xv;
822 TRACE("ld.b");
823 xv = cpu.asregs.regs[src];
824 cpu.asregs.regs[dest] = rbat (opc, xv);
825 }
826 break;
827 case 0x1d: /* lda.b */
828 {
829 int reg = (inst >> 4) & 0xf;
830 unsigned int addr = EXTRACT_WORD(&memory[pc+2]);
831 TRACE("lda.b");
832 cpu.asregs.regs[reg] = rbat (opc, addr);
833 pc += 4;
834 }
835 break;
836 case 0x1e: /* st.b */
837 {
838 int dest = (inst >> 4) & 0xf;
839 int val = inst & 0xf;
840 TRACE("st.b");
841 wbat (opc, cpu.asregs.regs[dest], cpu.asregs.regs[val]);
842 }
843 break;
844 case 0x1f: /* sta.b */
845 {
846 int reg = (inst >> 4) & 0xf;
847 unsigned int addr = EXTRACT_WORD(&memory[pc+2]);
848 TRACE("sta.b");
849 wbat (opc, addr, cpu.asregs.regs[reg]);
850 pc += 4;
851 }
852 break;
853 case 0x20: /* ldi.s (immediate) */
854 {
855 int reg = (inst >> 4) & 0xf;
856
857 unsigned int val = EXTRACT_WORD(&(memory[pc + 2]));
858 TRACE("ldi.s");
859 cpu.asregs.regs[reg] = val;
860 pc += 4;
861 }
862 break;
863 case 0x21: /* ld.s (register indirect) */
864 {
865 int src = inst & 0xf;
866 int dest = (inst >> 4) & 0xf;
867 int xv;
868 TRACE("ld.s");
869 xv = cpu.asregs.regs[src];
870 cpu.asregs.regs[dest] = rsat (opc, xv);
871 }
872 break;
873 case 0x22: /* lda.s */
874 {
875 int reg = (inst >> 4) & 0xf;
876 unsigned int addr = EXTRACT_WORD(&memory[pc+2]);
877 TRACE("lda.s");
878 cpu.asregs.regs[reg] = rsat (opc, addr);
879 pc += 4;
880 }
881 break;
882 case 0x23: /* st.s */
883 {
884 int dest = (inst >> 4) & 0xf;
885 int val = inst & 0xf;
886 TRACE("st.s");
887 wsat (opc, cpu.asregs.regs[dest], cpu.asregs.regs[val]);
888 }
889 break;
890 case 0x24: /* sta.s */
891 {
892 int reg = (inst >> 4) & 0xf;
893 unsigned int addr = EXTRACT_WORD(&memory[pc+2]);
894 TRACE("sta.s");
895 wsat (opc, addr, cpu.asregs.regs[reg]);
896 pc += 4;
897 }
898 break;
899 case 0x25: /* jmp */
900 {
901 int reg = (inst >> 4) & 0xf;
902 TRACE("jmp");
903 pc = cpu.asregs.regs[reg] - 2;
904 }
905 break;
906 case 0x26: /* and */
907 {
908 int a = (inst >> 4) & 0xf;
909 int b = inst & 0xf;
910 int av, bv;
911 TRACE("and");
912 av = cpu.asregs.regs[a];
913 bv = cpu.asregs.regs[b];
914 cpu.asregs.regs[a] = av & bv;
915 }
916 break;
917 case 0x27: /* lshr */
918 {
919 int a = (inst >> 4) & 0xf;
920 int b = inst & 0xf;
921 int av = cpu.asregs.regs[a];
922 int bv = cpu.asregs.regs[b];
923 TRACE("lshr");
924 cpu.asregs.regs[a] = (unsigned) ((unsigned) av >> bv);
925 }
926 break;
927 case 0x28: /* ashl */
928 {
929 int a = (inst >> 4) & 0xf;
930 int b = inst & 0xf;
931 int av = cpu.asregs.regs[a];
932 int bv = cpu.asregs.regs[b];
933 TRACE("ashl");
934 cpu.asregs.regs[a] = av << bv;
935 }
936 break;
937 case 0x29: /* sub.l */
938 {
939 int a = (inst >> 4) & 0xf;
940 int b = inst & 0xf;
941 unsigned av = cpu.asregs.regs[a];
942 unsigned bv = cpu.asregs.regs[b];
943 TRACE("sub.l");
944 cpu.asregs.regs[a] = av - bv;
945 }
946 break;
947 case 0x2a: /* neg */
948 {
949 int a = (inst >> 4) & 0xf;
950 int b = inst & 0xf;
951 int bv = cpu.asregs.regs[b];
952 TRACE("neg");
953 cpu.asregs.regs[a] = - bv;
954 }
955 break;
956 case 0x2b: /* or */
957 {
958 int a = (inst >> 4) & 0xf;
959 int b = inst & 0xf;
960 int av, bv;
961 TRACE("or");
962 av = cpu.asregs.regs[a];
963 bv = cpu.asregs.regs[b];
964 cpu.asregs.regs[a] = av | bv;
965 }
966 break;
967 case 0x2c: /* not */
968 {
969 int a = (inst >> 4) & 0xf;
970 int b = inst & 0xf;
971 int bv = cpu.asregs.regs[b];
972 TRACE("not");
973 cpu.asregs.regs[a] = 0xffffffff ^ bv;
974 }
975 break;
976 case 0x2d: /* ashr */
977 {
978 int a = (inst >> 4) & 0xf;
979 int b = inst & 0xf;
980 int av = cpu.asregs.regs[a];
981 int bv = cpu.asregs.regs[b];
982 TRACE("ashr");
983 cpu.asregs.regs[a] = av >> bv;
984 }
985 break;
986 case 0x2e: /* xor */
987 {
988 int a = (inst >> 4) & 0xf;
989 int b = inst & 0xf;
990 int av, bv;
991 TRACE("xor");
992 av = cpu.asregs.regs[a];
993 bv = cpu.asregs.regs[b];
994 cpu.asregs.regs[a] = av ^ bv;
995 }
996 break;
997 case 0x2f: /* mul.l */
998 {
999 int a = (inst >> 4) & 0xf;
1000 int b = inst & 0xf;
1001 unsigned av = cpu.asregs.regs[a];
1002 unsigned bv = cpu.asregs.regs[b];
1003 TRACE("mul.l");
1004 cpu.asregs.regs[a] = av * bv;
1005 }
1006 break;
1007 case 0x30: /* swi */
1008 {
1009 unsigned int inum = EXTRACT_WORD(&memory[pc+2]);
1010 TRACE("swi");
1011 switch (inum)
1012 {
1013 case 0x1: /* SYS_exit */
1014 {
1015 cpu.asregs.exception = SIGQUIT;
1016 break;
1017 }
1018 case 0x2: /* SYS_open */
1019 {
1020 char *fname = &memory[cpu.asregs.regs[2]];
1021 int mode = (int) convert_target_flags ((unsigned) cpu.asregs.regs[3]);
1022 /* Permission bits are at 0x12($fp) */
1023 int perm = (int) EXTRACT_WORD(&memory[cpu.asregs.regs[0] + 20]);
1024 int fd = open (fname, mode, perm);
1025 #if 0
1026 fprintf(stderr, "open(\"%s\", 0x%x, 0x%x) = %d\n", fname, mode, perm, fd);
1027 #endif
1028 /* FIXME - set errno */
1029 cpu.asregs.regs[2] = fd;
1030 break;
1031 }
1032 case 0x4: /* SYS_read */
1033 {
1034 int fd = cpu.asregs.regs[2];
1035 char *buf = &memory[cpu.asregs.regs[3]];
1036 /* String length is at 0x12($fp) */
1037 unsigned len = EXTRACT_WORD(&memory[cpu.asregs.regs[0] + 20]);
1038 cpu.asregs.regs[2] = read (fd, buf, len);
1039 break;
1040 }
1041 case 0x5: /* SYS_write */
1042 {
1043 char *str = &memory[cpu.asregs.regs[3]];
1044 /* String length is at 0x12($fp) */
1045 unsigned count, len = EXTRACT_WORD(&memory[cpu.asregs.regs[0] + 20]);
1046 count = write (cpu.asregs.regs[2], str, len);
1047 cpu.asregs.regs[2] = count;
1048 break;
1049 }
1050 default:
1051 break;
1052 }
1053 pc += 4;
1054 }
1055 break;
1056 case 0x31: /* div.l */
1057 {
1058 int a = (inst >> 4) & 0xf;
1059 int b = inst & 0xf;
1060 int av = cpu.asregs.regs[a];
1061 int bv = cpu.asregs.regs[b];
1062 TRACE("div.l");
1063 cpu.asregs.regs[a] = av / bv;
1064 }
1065 break;
1066 case 0x32: /* udiv.l */
1067 {
1068 int a = (inst >> 4) & 0xf;
1069 int b = inst & 0xf;
1070 unsigned int av = cpu.asregs.regs[a];
1071 unsigned int bv = cpu.asregs.regs[b];
1072 TRACE("udiv.l");
1073 cpu.asregs.regs[a] = (av / bv);
1074 }
1075 break;
1076 case 0x33: /* mod.l */
1077 {
1078 int a = (inst >> 4) & 0xf;
1079 int b = inst & 0xf;
1080 int av = cpu.asregs.regs[a];
1081 int bv = cpu.asregs.regs[b];
1082 TRACE("mod.l");
1083 cpu.asregs.regs[a] = av % bv;
1084 }
1085 break;
1086 case 0x34: /* umod.l */
1087 {
1088 int a = (inst >> 4) & 0xf;
1089 int b = inst & 0xf;
1090 unsigned int av = cpu.asregs.regs[a];
1091 unsigned int bv = cpu.asregs.regs[b];
1092 TRACE("umod.l");
1093 cpu.asregs.regs[a] = (av % bv);
1094 }
1095 break;
1096 case 0x35: /* brk */
1097 TRACE("brk");
1098 cpu.asregs.exception = SIGTRAP;
1099 pc -= 2; /* Adjust pc */
1100 break;
1101 case 0x36: /* ldo.b */
1102 {
1103 unsigned int addr = EXTRACT_WORD(&memory[pc+2]);
1104 int a = (inst >> 4) & 0xf;
1105 int b = inst & 0xf;
1106 TRACE("ldo.b");
1107 addr += cpu.asregs.regs[b];
1108 cpu.asregs.regs[a] = rbat(opc, addr);
1109 pc += 4;
1110 }
1111 break;
1112 case 0x37: /* sto.b */
1113 {
1114 unsigned int addr = EXTRACT_WORD(&memory[pc+2]);
1115 int a = (inst >> 4) & 0xf;
1116 int b = inst & 0xf;
1117 TRACE("sto.b");
1118 addr += cpu.asregs.regs[a];
1119 wbat(opc, addr, cpu.asregs.regs[b]);
1120 pc += 4;
1121 }
1122 break;
1123 case 0x38: /* ldo.s */
1124 {
1125 unsigned int addr = EXTRACT_WORD(&memory[pc+2]);
1126 int a = (inst >> 4) & 0xf;
1127 int b = inst & 0xf;
1128 TRACE("ldo.s");
1129 addr += cpu.asregs.regs[b];
1130 cpu.asregs.regs[a] = rsat(opc, addr);
1131 pc += 4;
1132 }
1133 break;
1134 case 0x39: /* sto.s */
1135 {
1136 unsigned int addr = EXTRACT_WORD(&memory[pc+2]);
1137 int a = (inst >> 4) & 0xf;
1138 int b = inst & 0xf;
1139 TRACE("sto.s");
1140 addr += cpu.asregs.regs[a];
1141 wsat(opc, addr, cpu.asregs.regs[b]);
1142 pc += 4;
1143 }
1144 break;
1145 default:
1146 opc = opcode;
1147 TRACE("SIGILL1");
1148 cpu.asregs.exception = SIGILL;
1149 break;
1150 }
1151 }
1152
1153 insts++;
1154 pc += 2;
1155
1156 } while (!cpu.asregs.exception);
1157
1158 /* Hide away the things we've cached while executing. */
1159 cpu.asregs.regs[PC_REGNO] = pc;
1160 cpu.asregs.insts += insts; /* instructions done ... */
1161
1162 signal (SIGINT, sigsave);
1163 }
1164
1165 int
1166 sim_write (sd, addr, buffer, size)
1167 SIM_DESC sd;
1168 SIM_ADDR addr;
1169 unsigned char * buffer;
1170 int size;
1171 {
1172 int i;
1173 init_pointers ();
1174
1175 memcpy (& cpu.asregs.memory[addr], buffer, size);
1176
1177 return size;
1178 }
1179
1180 int
1181 sim_read (sd, addr, buffer, size)
1182 SIM_DESC sd;
1183 SIM_ADDR addr;
1184 unsigned char * buffer;
1185 int size;
1186 {
1187 int i;
1188 init_pointers ();
1189
1190 memcpy (buffer, & cpu.asregs.memory[addr], size);
1191
1192 return size;
1193 }
1194
1195
1196 int
1197 sim_store_register (sd, rn, memory, length)
1198 SIM_DESC sd;
1199 int rn;
1200 unsigned char * memory;
1201 int length;
1202 {
1203 init_pointers ();
1204
1205 if (rn < NUM_MOXIE_REGS && rn >= 0)
1206 {
1207 if (length == 4)
1208 {
1209 long ival;
1210
1211 /* misalignment safe */
1212 ival = moxie_extract_unsigned_integer (memory, 4);
1213 cpu.asints[rn] = ival;
1214 }
1215
1216 return 4;
1217 }
1218 else
1219 return 0;
1220 }
1221
1222 int
1223 sim_fetch_register (sd, rn, memory, length)
1224 SIM_DESC sd;
1225 int rn;
1226 unsigned char * memory;
1227 int length;
1228 {
1229 init_pointers ();
1230
1231 if (rn < NUM_MOXIE_REGS && rn >= 0)
1232 {
1233 if (length == 4)
1234 {
1235 long ival = cpu.asints[rn];
1236
1237 /* misalignment-safe */
1238 moxie_store_unsigned_integer (memory, 4, ival);
1239 }
1240
1241 return 4;
1242 }
1243 else
1244 return 0;
1245 }
1246
1247
1248 int
1249 sim_trace (sd)
1250 SIM_DESC sd;
1251 {
1252 if (tracefile == 0)
1253 tracefile = fopen("trace.csv", "wb");
1254
1255 tracing = 1;
1256
1257 sim_resume (sd, 0, 0);
1258
1259 tracing = 0;
1260
1261 return 1;
1262 }
1263
1264 void
1265 sim_stop_reason (sd, reason, sigrc)
1266 SIM_DESC sd;
1267 enum sim_stop * reason;
1268 int * sigrc;
1269 {
1270 if (cpu.asregs.exception == SIGQUIT)
1271 {
1272 * reason = sim_exited;
1273 * sigrc = cpu.asregs.regs[2];
1274 }
1275 else
1276 {
1277 * reason = sim_stopped;
1278 * sigrc = cpu.asregs.exception;
1279 }
1280 }
1281
1282
1283 int
1284 sim_stop (sd)
1285 SIM_DESC sd;
1286 {
1287 cpu.asregs.exception = SIGINT;
1288 return 1;
1289 }
1290
1291
1292 void
1293 sim_info (sd, verbose)
1294 SIM_DESC sd;
1295 int verbose;
1296 {
1297 callback->printf_filtered (callback, "\n\n# instructions executed %llu\n",
1298 cpu.asregs.insts);
1299 }
1300
1301
1302 SIM_DESC
1303 sim_open (kind, cb, abfd, argv)
1304 SIM_OPEN_KIND kind;
1305 host_callback * cb;
1306 struct bfd * abfd;
1307 char ** argv;
1308 {
1309 int osize = sim_memory_size;
1310 myname = argv[0];
1311 callback = cb;
1312
1313 if (kind == SIM_OPEN_STANDALONE)
1314 issue_messages = 1;
1315
1316 /* Discard and reacquire memory -- start with a clean slate. */
1317 sim_size (1); /* small */
1318 sim_size (osize); /* and back again */
1319
1320 set_initial_gprs (); /* Reset the GPR registers. */
1321
1322 /* Fudge our descriptor for now. */
1323 return (SIM_DESC) 1;
1324 }
1325
1326 void
1327 sim_close (sd, quitting)
1328 SIM_DESC sd;
1329 int quitting;
1330 {
1331 /* nothing to do */
1332 }
1333
1334 SIM_RC
1335 sim_load (sd, prog, abfd, from_tty)
1336 SIM_DESC sd;
1337 char * prog;
1338 bfd * abfd;
1339 int from_tty;
1340 {
1341
1342 /* Do the right thing for ELF executables; this turns out to be
1343 just about the right thing for any object format that:
1344 - we crack using BFD routines
1345 - follows the traditional UNIX text/data/bss layout
1346 - calls the bss section ".bss". */
1347
1348 extern bfd * sim_load_file (); /* ??? Don't know where this should live. */
1349 bfd * prog_bfd;
1350
1351 {
1352 bfd * handle;
1353 handle = bfd_openr (prog, 0); /* could be "moxie" */
1354
1355 if (!handle)
1356 {
1357 printf("``%s'' could not be opened.\n", prog);
1358 return SIM_RC_FAIL;
1359 }
1360
1361 /* Makes sure that we have an object file, also cleans gets the
1362 section headers in place. */
1363 if (!bfd_check_format (handle, bfd_object))
1364 {
1365 /* wasn't an object file */
1366 bfd_close (handle);
1367 printf ("``%s'' is not appropriate object file.\n", prog);
1368 return SIM_RC_FAIL;
1369 }
1370
1371 /* Clean up after ourselves. */
1372 bfd_close (handle);
1373 }
1374
1375 /* from sh -- dac */
1376 prog_bfd = sim_load_file (sd, myname, callback, prog, abfd,
1377 sim_kind == SIM_OPEN_DEBUG,
1378 0, sim_write);
1379 if (prog_bfd == NULL)
1380 return SIM_RC_FAIL;
1381
1382 if (abfd == NULL)
1383 bfd_close (prog_bfd);
1384
1385 return SIM_RC_OK;
1386 }
1387
1388 SIM_RC
1389 sim_create_inferior (sd, prog_bfd, argv, env)
1390 SIM_DESC sd;
1391 struct bfd * prog_bfd;
1392 char ** argv;
1393 char ** env;
1394 {
1395 char ** avp;
1396 int l, argc, i, tp;
1397
1398 /* Set the initial register set. */
1399 l = issue_messages;
1400 issue_messages = 0;
1401 set_initial_gprs ();
1402 issue_messages = l;
1403
1404 cpu.asregs.regs[PC_REGNO] = bfd_get_start_address (prog_bfd);
1405
1406 /* Copy args into target memory. */
1407 avp = argv;
1408 for (argc = 0; *avp; avp++)
1409 argc++;
1410
1411 /* Target memory looks like this:
1412 0x00000000 zero word
1413 0x00000004 argc word
1414 0x00000008 start of argv
1415 .
1416 0x0000???? end of argv
1417 0x0000???? zero word
1418 0x0000???? start of data pointed to by argv */
1419
1420 wlat (0, 0, 0);
1421 wlat (0, 4, argc);
1422
1423 /* tp is the offset of our first argv data. */
1424 tp = 4 + 4 + argc * 4 + 4;
1425
1426 for (i = 0; i < argc; i++)
1427 {
1428 /* Set the argv value. */
1429 wlat (0, 4 + 4 + i * 4, tp);
1430
1431 /* Store the string. */
1432 strcpy (&cpu.asregs.memory[tp], argv[i]);
1433 tp += strlen (argv[i]) + 1;
1434 }
1435
1436 wlat (0, 4 + 4 + i * 4, 0);
1437
1438 return SIM_RC_OK;
1439 }
1440
1441 void
1442 sim_kill (sd)
1443 SIM_DESC sd;
1444 {
1445 if (tracefile)
1446 fclose(tracefile);
1447 }
1448
1449 void
1450 sim_do_command (sd, cmd)
1451 SIM_DESC sd;
1452 char * cmd;
1453 {
1454 /* Nothing there yet; it's all an error. */
1455
1456 if (cmd != NULL)
1457 {
1458 char ** simargv = buildargv (cmd);
1459 if (strcmp (simargv[0], "verbose") == 0)
1460 {
1461 issue_messages = 2;
1462 }
1463 else
1464 {
1465 fprintf (stderr,"Error: \"%s\" is not a valid moxie simulator command.\n",
1466 cmd);
1467 }
1468 }
1469 else
1470 {
1471 fprintf (stderr, "moxie sim commands: \n");
1472 fprintf (stderr, " verbose\n");
1473 }
1474 }
1475
1476 void
1477 sim_set_callbacks (ptr)
1478 host_callback * ptr;
1479 {
1480 callback = ptr;
1481 }