Add PC-relative branch instructions to moxie port.
[deliverable/binutils-gdb.git] / sim / moxie / interp.c
CommitLineData
fdd6fa61
AG
1/* Simulator for the moxie processor
2 Copyright (C) 2008, 2009 Free Software Foundation, Inc.
3 Contributed by Anthony Green
4
5This file is part of GDB, the GNU debugger.
6
7This program is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
9the Free Software Foundation; either version 3 of the License, or
10(at your option) any later version.
11
12This program is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along 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
31typedef int word;
32typedef unsigned int uword;
33
34host_callback * callback;
35
36FILE *tracefile;
37
38#define EXTRACT_WORD(addr) (((addr)[0] << 24) \
39 + ((addr)[1] << 16) \
40 + ((addr)[2] << 8) \
41 + ((addr)[3]))
42
43unsigned long
44moxie_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
67void
68moxie_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. */
85static 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. */
104struct 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
121union
122{
123 struct moxie_regset asregs;
124 word asints [1]; /* but accessed larger... */
125} cpu;
126
127static char *myname;
128static SIM_OPEN_KIND sim_kind;
129static int issue_messages = 0;
130
131/* Default to a 8 Mbyte (== 2^23) memory space. */
132static int sim_memory_size = 23;
133
134#define MEM_SIZE_FLOOR 64
135void
136sim_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
164static void
165init_pointers ()
166{
167 if (cpu.asregs.msize != (1 << sim_memory_size))
168 sim_size (sim_memory_size);
169}
170
171
172static void
173set_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
197static void
198interrupt ()
199{
200 cpu.asregs.exception = SIGINT;
201}
202
203/* Write a 1 byte value to memory. */
204
205static void INLINE
206wbat (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
227static void INLINE
228wsat (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
257static void INLINE
258wlat (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
289static int INLINE
290rsat (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
320static int INLINE
321rbat (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
341static int INLINE
342rlat (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
372unsigned int
373convert_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
395static int tracing = 0;
396
397void
398sim_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 }
77176dfc 463 break;
fdd6fa61
AG
464 case 0x03: /* ssr */
465 {
466 int a = (inst >> 8) & 0xf;
467 unsigned v = (inst & 0xff);
468 TRACE("ssr");
469 cpu.asregs.sregs[v] = cpu.asregs.regs[a];
470 }
77176dfc 471 break;
fdd6fa61
AG
472 default:
473 TRACE("SIGILL2");
474 cpu.asregs.exception = SIGILL;
475 break;
476 }
477 }
478 }
479 else
480 {
481 /* This is a Form 1 instruction. */
482 int opcode = inst >> 8;
483 switch (opcode)
484 {
485 case 0x00: /* nop */
486 break;
487 case 0x01: /* ldi.l (immediate) */
488 {
489 int reg = (inst >> 4) & 0xf;
490 TRACE("ldi.l");
491 unsigned int val = EXTRACT_WORD(&(memory[pc + 2]));
492 cpu.asregs.regs[reg] = val;
493 pc += 4;
494 }
495 break;
496 case 0x02: /* mov (register-to-register) */
497 {
498 int dest = (inst >> 4) & 0xf;
499 int src = (inst ) & 0xf;
500 TRACE("mov");
501 cpu.asregs.regs[dest] = cpu.asregs.regs[src];
502 }
503 break;
504 case 0x03: /* jsra */
505 {
506 unsigned int fn = EXTRACT_WORD(&(memory[pc + 2]));
507 unsigned int sp = cpu.asregs.regs[1];
508 TRACE("jsra");
509 /* Save a slot for the static chain. */
510 sp -= 4;
511
512 /* Push the return address. */
513 sp -= 4;
514 wlat (opc, sp, pc + 6);
515
516 /* Push the current frame pointer. */
517 sp -= 4;
518 wlat (opc, sp, cpu.asregs.regs[0]);
519
520 /* Uncache the stack pointer and set the pc and $fp. */
521 cpu.asregs.regs[1] = sp;
522 cpu.asregs.regs[0] = sp;
523 pc = fn - 2;
524 }
525 break;
526 case 0x04: /* ret */
527 {
528 unsigned int sp = cpu.asregs.regs[0];
529
530 TRACE("ret");
531
532 /* Pop the frame pointer. */
533 cpu.asregs.regs[0] = rlat (opc, sp);
534 sp += 4;
535
536 /* Pop the return address. */
537 pc = rlat (opc, sp) - 2;
538 sp += 4;
539
540 /* Skip over the static chain slot. */
541 sp += 4;
542
543 /* Uncache the stack pointer. */
544 cpu.asregs.regs[1] = sp;
545 }
546 break;
547 case 0x05: /* add.l */
548 {
549 int a = (inst >> 4) & 0xf;
550 int b = inst & 0xf;
551 unsigned av = cpu.asregs.regs[a];
552 unsigned bv = cpu.asregs.regs[b];
553 TRACE("add.l");
554 cpu.asregs.regs[a] = av + bv;
555 }
556 break;
557 case 0x06: /* push */
558 {
559 int a = (inst >> 4) & 0xf;
560 int b = inst & 0xf;
561 int sp = cpu.asregs.regs[a] - 4;
562 TRACE("push");
563 wlat (opc, sp, cpu.asregs.regs[b]);
564 cpu.asregs.regs[a] = sp;
565 }
566 break;
567 case 0x07: /* pop */
568 {
569 int a = (inst >> 4) & 0xf;
570 int b = inst & 0xf;
571 int sp = cpu.asregs.regs[a];
572 TRACE("pop");
573 cpu.asregs.regs[b] = rlat (opc, sp);
574 cpu.asregs.regs[a] = sp + 4;
575 }
576 break;
577 case 0x08: /* lda.l */
578 {
579 int reg = (inst >> 4) & 0xf;
580 unsigned int addr = EXTRACT_WORD(&memory[pc+2]);
581 TRACE("lda.l");
582 cpu.asregs.regs[reg] = rlat (opc, addr);
583 pc += 4;
584 }
585 break;
586 case 0x09: /* sta.l */
587 {
588 int reg = (inst >> 4) & 0xf;
589 unsigned int addr = EXTRACT_WORD(&memory[pc+2]);
590 TRACE("sta.l");
591 wlat (opc, addr, cpu.asregs.regs[reg]);
592 pc += 4;
593 }
594 break;
595 case 0x0a: /* ld.l (register indirect) */
596 {
597 int src = inst & 0xf;
598 int dest = (inst >> 4) & 0xf;
599 int xv;
600 TRACE("ld.l");
601 xv = cpu.asregs.regs[src];
602 cpu.asregs.regs[dest] = rlat (opc, xv);
603 }
604 break;
605 case 0x0b: /* st.l */
606 {
607 int dest = (inst >> 4) & 0xf;
608 int val = inst & 0xf;
609 TRACE("st.l");
610 wlat (opc, cpu.asregs.regs[dest], cpu.asregs.regs[val]);
611 }
612 break;
613 case 0x0c: /* ldo.l */
614 {
615 unsigned int addr = EXTRACT_WORD(&memory[pc+2]);
616 int a = (inst >> 4) & 0xf;
617 int b = inst & 0xf;
618 TRACE("ldo.l");
619 addr += cpu.asregs.regs[b];
620 cpu.asregs.regs[a] = rlat(opc, addr);
621 pc += 4;
622 }
623 break;
624 case 0x0d: /* sto.l */
625 {
626 unsigned int addr = EXTRACT_WORD(&memory[pc+2]);
627 int a = (inst >> 4) & 0xf;
628 int b = inst & 0xf;
629 TRACE("sto.l");
630 addr += cpu.asregs.regs[a];
631 wlat(opc, addr, cpu.asregs.regs[b]);
632 pc += 4;
633 }
634 break;
635 case 0x0e: /* cmp */
636 {
637 int a = (inst >> 4) & 0xf;
638 int b = inst & 0xf;
639 int cc = 0;
640 int va = cpu.asregs.regs[a];
641 int vb = cpu.asregs.regs[b];
642
643 TRACE("cmp");
644
645 if (va == vb)
646 cc = CC_EQ;
647 else
648 {
649 cc |= (va < vb ? CC_LT : 0);
650 cc |= (va > vb ? CC_GT : 0);
651 cc |= ((unsigned int) va < (unsigned int) vb ? CC_LTU : 0);
652 cc |= ((unsigned int) va > (unsigned int) vb ? CC_GTU : 0);
653 }
654
655 cpu.asregs.cc = cc;
656 }
657 break;
658 case 0x0f: /* beq */
659 {
660 unsigned int tgt = EXTRACT_WORD(&memory[pc+2]);
661 TRACE("beq");
662 if (cpu.asregs.cc & CC_EQ)
663 {
664 pc = tgt - 2;
665 }
666 else
667 pc += 4;
668 }
669 break;
670 case 0x10: /* bne */
671 {
672 unsigned int tgt = EXTRACT_WORD(&memory[pc+2]);
673 TRACE("bne");
674 if (! (cpu.asregs.cc & CC_EQ))
675 {
676 pc = tgt - 2;
677 }
678 else
679 pc += 4;
680 }
681 break;
682 case 0x11: /* blt */
683 {
684 unsigned int tgt = EXTRACT_WORD(&memory[pc+2]);
685 TRACE("blt");
686 if (cpu.asregs.cc & CC_LT)
687 {
688 pc = tgt - 2;
689 }
690 else
691 pc += 4;
692 }
693 break;
694 case 0x12: /* bgt */
695 {
696 unsigned int tgt = EXTRACT_WORD(&memory[pc+2]);
697 TRACE("bgt");
698 if (cpu.asregs.cc & CC_GT)
699 {
700 pc = tgt - 2;
701 }
702 else
703 pc += 4;
704 }
705 break;
706 case 0x13: /* bltu */
707 {
708 unsigned int tgt = EXTRACT_WORD(&memory[pc+2]);
709 TRACE("bltu");
710 if (cpu.asregs.cc & CC_LTU)
711 {
712 pc = tgt - 2;
713 }
714 else
715 pc += 4;
716 }
717 break;
718 case 0x14: /* bgtu */
719 {
720 unsigned int tgt = EXTRACT_WORD(&memory[pc+2]);
721 TRACE("bgtu");
722 if (cpu.asregs.cc & CC_GTU)
723 {
724 pc = tgt - 2;
725 }
726 else
727 pc += 4;
728 }
729 break;
730 case 0x15: /* bge */
731 {
732 unsigned int tgt = EXTRACT_WORD(&memory[pc+2]);
733 TRACE("bge");
734 if ((cpu.asregs.cc & CC_GT) || (cpu.asregs.cc & CC_EQ))
735 {
736 pc = tgt - 2;
737 }
738 else
739 pc += 4;
740 }
741 break;
742 case 0x16: /* ble */
743 {
744 unsigned int tgt = EXTRACT_WORD(&memory[pc+2]);
745 TRACE("ble");
746 if ((cpu.asregs.cc & CC_LT) || (cpu.asregs.cc & CC_EQ))
747 {
748 pc = tgt - 2;
749 }
750 else
751 pc += 4;
752 }
753 break;
754 case 0x17: /* bgeu */
755 {
756 unsigned int tgt = EXTRACT_WORD(&memory[pc+2]);
757 TRACE("bgeu");
758 if ((cpu.asregs.cc & CC_GTU) || (cpu.asregs.cc & CC_EQ))
759 {
760 pc = tgt - 2;
761 }
762 else
763 pc += 4;
764 }
765 break;
766 case 0x18: /* bleu */
767 {
768 unsigned int tgt = EXTRACT_WORD(&memory[pc+2]);
769 TRACE("bleu");
770 if ((cpu.asregs.cc & CC_LTU) || (cpu.asregs.cc & CC_EQ))
771 {
772 pc = tgt - 2;
773 }
774 else
775 pc += 4;
776 }
777 break;
778 case 0x19: /* jsr */
779 {
780 unsigned int fn = cpu.asregs.regs[(inst >> 4) & 0xf];
781 unsigned int sp = cpu.asregs.regs[1];
782
783 TRACE("jsr");
784
785 /* Save a slot for the static chain. */
786 sp -= 4;
787
788 /* Push the return address. */
789 sp -= 4;
790 wlat (opc, sp, pc + 2);
791
792 /* Push the current frame pointer. */
793 sp -= 4;
794 wlat (opc, sp, cpu.asregs.regs[0]);
795
796 /* Uncache the stack pointer and set the fp & pc. */
797 cpu.asregs.regs[1] = sp;
798 cpu.asregs.regs[0] = sp;
799 pc = fn - 2;
800 }
801 break;
802 case 0x1a: /* jmpa */
803 {
804 unsigned int tgt = EXTRACT_WORD(&memory[pc+2]);
805 TRACE("jmpa");
806 pc = tgt - 2;
807 }
808 break;
809 case 0x1b: /* ldi.b (immediate) */
810 {
811 int reg = (inst >> 4) & 0xf;
812
813 unsigned int val = EXTRACT_WORD(&(memory[pc + 2]));
814 TRACE("ldi.b");
815 cpu.asregs.regs[reg] = val;
816 pc += 4;
817 }
818 break;
819 case 0x1c: /* ld.b (register indirect) */
820 {
821 int src = inst & 0xf;
822 int dest = (inst >> 4) & 0xf;
823 int xv;
824 TRACE("ld.b");
825 xv = cpu.asregs.regs[src];
826 cpu.asregs.regs[dest] = rbat (opc, xv);
827 }
828 break;
829 case 0x1d: /* lda.b */
830 {
831 int reg = (inst >> 4) & 0xf;
832 unsigned int addr = EXTRACT_WORD(&memory[pc+2]);
833 TRACE("lda.b");
834 cpu.asregs.regs[reg] = rbat (opc, addr);
835 pc += 4;
836 }
837 break;
838 case 0x1e: /* st.b */
839 {
840 int dest = (inst >> 4) & 0xf;
841 int val = inst & 0xf;
842 TRACE("st.b");
843 wbat (opc, cpu.asregs.regs[dest], cpu.asregs.regs[val]);
844 }
845 break;
846 case 0x1f: /* sta.b */
847 {
848 int reg = (inst >> 4) & 0xf;
849 unsigned int addr = EXTRACT_WORD(&memory[pc+2]);
850 TRACE("sta.b");
851 wbat (opc, addr, cpu.asregs.regs[reg]);
852 pc += 4;
853 }
854 break;
855 case 0x20: /* ldi.s (immediate) */
856 {
857 int reg = (inst >> 4) & 0xf;
858
859 unsigned int val = EXTRACT_WORD(&(memory[pc + 2]));
860 TRACE("ldi.s");
861 cpu.asregs.regs[reg] = val;
862 pc += 4;
863 }
864 break;
865 case 0x21: /* ld.s (register indirect) */
866 {
867 int src = inst & 0xf;
868 int dest = (inst >> 4) & 0xf;
869 int xv;
870 TRACE("ld.s");
871 xv = cpu.asregs.regs[src];
872 cpu.asregs.regs[dest] = rsat (opc, xv);
873 }
874 break;
875 case 0x22: /* lda.s */
876 {
877 int reg = (inst >> 4) & 0xf;
878 unsigned int addr = EXTRACT_WORD(&memory[pc+2]);
879 TRACE("lda.s");
880 cpu.asregs.regs[reg] = rsat (opc, addr);
881 pc += 4;
882 }
883 break;
884 case 0x23: /* st.s */
885 {
886 int dest = (inst >> 4) & 0xf;
887 int val = inst & 0xf;
888 TRACE("st.s");
889 wsat (opc, cpu.asregs.regs[dest], cpu.asregs.regs[val]);
890 }
891 break;
892 case 0x24: /* sta.s */
893 {
894 int reg = (inst >> 4) & 0xf;
895 unsigned int addr = EXTRACT_WORD(&memory[pc+2]);
896 TRACE("sta.s");
897 wsat (opc, addr, cpu.asregs.regs[reg]);
898 pc += 4;
899 }
900 break;
901 case 0x25: /* jmp */
902 {
903 int reg = (inst >> 4) & 0xf;
904 TRACE("jmp");
905 pc = cpu.asregs.regs[reg] - 2;
906 }
907 break;
908 case 0x26: /* and */
909 {
910 int a = (inst >> 4) & 0xf;
911 int b = inst & 0xf;
912 int av, bv;
913 TRACE("and");
914 av = cpu.asregs.regs[a];
915 bv = cpu.asregs.regs[b];
916 cpu.asregs.regs[a] = av & bv;
917 }
918 break;
919 case 0x27: /* lshr */
920 {
921 int a = (inst >> 4) & 0xf;
922 int b = inst & 0xf;
923 int av = cpu.asregs.regs[a];
924 int bv = cpu.asregs.regs[b];
925 TRACE("lshr");
926 cpu.asregs.regs[a] = (unsigned) ((unsigned) av >> bv);
927 }
928 break;
929 case 0x28: /* ashl */
930 {
931 int a = (inst >> 4) & 0xf;
932 int b = inst & 0xf;
933 int av = cpu.asregs.regs[a];
934 int bv = cpu.asregs.regs[b];
935 TRACE("ashl");
936 cpu.asregs.regs[a] = av << bv;
937 }
938 break;
939 case 0x29: /* sub.l */
940 {
941 int a = (inst >> 4) & 0xf;
942 int b = inst & 0xf;
943 unsigned av = cpu.asregs.regs[a];
944 unsigned bv = cpu.asregs.regs[b];
945 TRACE("sub.l");
946 cpu.asregs.regs[a] = av - bv;
947 }
948 break;
949 case 0x2a: /* neg */
950 {
951 int a = (inst >> 4) & 0xf;
952 int b = inst & 0xf;
953 int bv = cpu.asregs.regs[b];
954 TRACE("neg");
955 cpu.asregs.regs[a] = - bv;
956 }
957 break;
958 case 0x2b: /* or */
959 {
960 int a = (inst >> 4) & 0xf;
961 int b = inst & 0xf;
962 int av, bv;
963 TRACE("or");
964 av = cpu.asregs.regs[a];
965 bv = cpu.asregs.regs[b];
966 cpu.asregs.regs[a] = av | bv;
967 }
968 break;
969 case 0x2c: /* not */
970 {
971 int a = (inst >> 4) & 0xf;
972 int b = inst & 0xf;
973 int bv = cpu.asregs.regs[b];
974 TRACE("not");
975 cpu.asregs.regs[a] = 0xffffffff ^ bv;
976 }
977 break;
978 case 0x2d: /* ashr */
979 {
980 int a = (inst >> 4) & 0xf;
981 int b = inst & 0xf;
982 int av = cpu.asregs.regs[a];
983 int bv = cpu.asregs.regs[b];
984 TRACE("ashr");
985 cpu.asregs.regs[a] = av >> bv;
986 }
987 break;
988 case 0x2e: /* xor */
989 {
990 int a = (inst >> 4) & 0xf;
991 int b = inst & 0xf;
992 int av, bv;
993 TRACE("xor");
994 av = cpu.asregs.regs[a];
995 bv = cpu.asregs.regs[b];
996 cpu.asregs.regs[a] = av ^ bv;
997 }
998 break;
999 case 0x2f: /* mul.l */
1000 {
1001 int a = (inst >> 4) & 0xf;
1002 int b = inst & 0xf;
1003 unsigned av = cpu.asregs.regs[a];
1004 unsigned bv = cpu.asregs.regs[b];
1005 TRACE("mul.l");
1006 cpu.asregs.regs[a] = av * bv;
1007 }
1008 break;
1009 case 0x30: /* swi */
1010 {
1011 unsigned int inum = EXTRACT_WORD(&memory[pc+2]);
1012 TRACE("swi");
1013 switch (inum)
1014 {
1015 case 0x1: /* SYS_exit */
1016 {
1017 cpu.asregs.exception = SIGQUIT;
1018 break;
1019 }
1020 case 0x2: /* SYS_open */
1021 {
1022 char *fname = &memory[cpu.asregs.regs[2]];
1023 int mode = (int) convert_target_flags ((unsigned) cpu.asregs.regs[3]);
1024 /* Permission bits are at 0x12($fp) */
1025 int perm = (int) EXTRACT_WORD(&memory[cpu.asregs.regs[0] + 20]);
1026 int fd = open (fname, mode, perm);
1027#if 0
1028 fprintf(stderr, "open(\"%s\", 0x%x, 0x%x) = %d\n", fname, mode, perm, fd);
1029#endif
1030 /* FIXME - set errno */
1031 cpu.asregs.regs[2] = fd;
1032 break;
1033 }
1034 case 0x4: /* SYS_read */
1035 {
1036 int fd = cpu.asregs.regs[2];
1037 char *buf = &memory[cpu.asregs.regs[3]];
1038 /* String length is at 0x12($fp) */
1039 unsigned len = EXTRACT_WORD(&memory[cpu.asregs.regs[0] + 20]);
1040 cpu.asregs.regs[2] = read (fd, buf, len);
1041 break;
1042 }
1043 case 0x5: /* SYS_write */
1044 {
1045 char *str = &memory[cpu.asregs.regs[3]];
1046 /* String length is at 0x12($fp) */
1047 unsigned count, len = EXTRACT_WORD(&memory[cpu.asregs.regs[0] + 20]);
1048 count = write (cpu.asregs.regs[2], str, len);
1049 cpu.asregs.regs[2] = count;
1050 break;
1051 }
1052 default:
1053 break;
1054 }
1055 pc += 4;
1056 }
1057 break;
1058 case 0x31: /* div.l */
1059 {
1060 int a = (inst >> 4) & 0xf;
1061 int b = inst & 0xf;
1062 int av = cpu.asregs.regs[a];
1063 int bv = cpu.asregs.regs[b];
1064 TRACE("div.l");
1065 cpu.asregs.regs[a] = av / bv;
1066 }
1067 break;
1068 case 0x32: /* udiv.l */
1069 {
1070 int a = (inst >> 4) & 0xf;
1071 int b = inst & 0xf;
1072 unsigned int av = cpu.asregs.regs[a];
1073 unsigned int bv = cpu.asregs.regs[b];
1074 TRACE("udiv.l");
1075 cpu.asregs.regs[a] = (av / bv);
1076 }
1077 break;
1078 case 0x33: /* mod.l */
1079 {
1080 int a = (inst >> 4) & 0xf;
1081 int b = inst & 0xf;
1082 int av = cpu.asregs.regs[a];
1083 int bv = cpu.asregs.regs[b];
1084 TRACE("mod.l");
1085 cpu.asregs.regs[a] = av % bv;
1086 }
1087 break;
1088 case 0x34: /* umod.l */
1089 {
1090 int a = (inst >> 4) & 0xf;
1091 int b = inst & 0xf;
1092 unsigned int av = cpu.asregs.regs[a];
1093 unsigned int bv = cpu.asregs.regs[b];
1094 TRACE("umod.l");
1095 cpu.asregs.regs[a] = (av % bv);
1096 }
1097 break;
1098 case 0x35: /* brk */
1099 TRACE("brk");
1100 cpu.asregs.exception = SIGTRAP;
1101 pc -= 2; /* Adjust pc */
1102 break;
1103 case 0x36: /* ldo.b */
1104 {
1105 unsigned int addr = EXTRACT_WORD(&memory[pc+2]);
1106 int a = (inst >> 4) & 0xf;
1107 int b = inst & 0xf;
1108 TRACE("ldo.b");
1109 addr += cpu.asregs.regs[b];
1110 cpu.asregs.regs[a] = rbat(opc, addr);
1111 pc += 4;
1112 }
1113 break;
1114 case 0x37: /* sto.b */
1115 {
1116 unsigned int addr = EXTRACT_WORD(&memory[pc+2]);
1117 int a = (inst >> 4) & 0xf;
1118 int b = inst & 0xf;
1119 TRACE("sto.b");
1120 addr += cpu.asregs.regs[a];
1121 wbat(opc, addr, cpu.asregs.regs[b]);
1122 pc += 4;
1123 }
1124 break;
1125 case 0x38: /* ldo.s */
1126 {
1127 unsigned int addr = EXTRACT_WORD(&memory[pc+2]);
1128 int a = (inst >> 4) & 0xf;
1129 int b = inst & 0xf;
1130 TRACE("ldo.s");
1131 addr += cpu.asregs.regs[b];
1132 cpu.asregs.regs[a] = rsat(opc, addr);
1133 pc += 4;
1134 }
1135 break;
1136 case 0x39: /* sto.s */
1137 {
1138 unsigned int addr = EXTRACT_WORD(&memory[pc+2]);
1139 int a = (inst >> 4) & 0xf;
1140 int b = inst & 0xf;
1141 TRACE("sto.s");
1142 addr += cpu.asregs.regs[a];
1143 wsat(opc, addr, cpu.asregs.regs[b]);
1144 pc += 4;
1145 }
1146 break;
1147 default:
1148 opc = opcode;
1149 TRACE("SIGILL1");
1150 cpu.asregs.exception = SIGILL;
1151 break;
1152 }
1153 }
1154
1155 insts++;
1156 pc += 2;
1157
1158 } while (!cpu.asregs.exception);
1159
1160 /* Hide away the things we've cached while executing. */
1161 cpu.asregs.regs[PC_REGNO] = pc;
1162 cpu.asregs.insts += insts; /* instructions done ... */
1163
1164 signal (SIGINT, sigsave);
1165}
1166
1167int
1168sim_write (sd, addr, buffer, size)
1169 SIM_DESC sd;
1170 SIM_ADDR addr;
1171 unsigned char * buffer;
1172 int size;
1173{
1174 int i;
1175 init_pointers ();
1176
1177 memcpy (& cpu.asregs.memory[addr], buffer, size);
1178
1179 return size;
1180}
1181
1182int
1183sim_read (sd, addr, buffer, size)
1184 SIM_DESC sd;
1185 SIM_ADDR addr;
1186 unsigned char * buffer;
1187 int size;
1188{
1189 int i;
1190 init_pointers ();
1191
1192 memcpy (buffer, & cpu.asregs.memory[addr], size);
1193
1194 return size;
1195}
1196
1197
1198int
1199sim_store_register (sd, rn, memory, length)
1200 SIM_DESC sd;
1201 int rn;
1202 unsigned char * memory;
1203 int length;
1204{
1205 init_pointers ();
1206
1207 if (rn < NUM_MOXIE_REGS && rn >= 0)
1208 {
1209 if (length == 4)
1210 {
1211 long ival;
1212
1213 /* misalignment safe */
1214 ival = moxie_extract_unsigned_integer (memory, 4);
1215 cpu.asints[rn] = ival;
1216 }
1217
1218 return 4;
1219 }
1220 else
1221 return 0;
1222}
1223
1224int
1225sim_fetch_register (sd, rn, memory, length)
1226 SIM_DESC sd;
1227 int rn;
1228 unsigned char * memory;
1229 int length;
1230{
1231 init_pointers ();
1232
1233 if (rn < NUM_MOXIE_REGS && rn >= 0)
1234 {
1235 if (length == 4)
1236 {
1237 long ival = cpu.asints[rn];
1238
1239 /* misalignment-safe */
1240 moxie_store_unsigned_integer (memory, 4, ival);
1241 }
1242
1243 return 4;
1244 }
1245 else
1246 return 0;
1247}
1248
1249
1250int
1251sim_trace (sd)
1252 SIM_DESC sd;
1253{
1254 if (tracefile == 0)
1255 tracefile = fopen("trace.csv", "wb");
1256
1257 tracing = 1;
1258
1259 sim_resume (sd, 0, 0);
1260
1261 tracing = 0;
1262
1263 return 1;
1264}
1265
1266void
1267sim_stop_reason (sd, reason, sigrc)
1268 SIM_DESC sd;
1269 enum sim_stop * reason;
1270 int * sigrc;
1271{
1272 if (cpu.asregs.exception == SIGQUIT)
1273 {
1274 * reason = sim_exited;
1275 * sigrc = cpu.asregs.regs[2];
1276 }
1277 else
1278 {
1279 * reason = sim_stopped;
1280 * sigrc = cpu.asregs.exception;
1281 }
1282}
1283
1284
1285int
1286sim_stop (sd)
1287 SIM_DESC sd;
1288{
1289 cpu.asregs.exception = SIGINT;
1290 return 1;
1291}
1292
1293
1294void
1295sim_info (sd, verbose)
1296 SIM_DESC sd;
1297 int verbose;
1298{
1299 callback->printf_filtered (callback, "\n\n# instructions executed %llu\n",
1300 cpu.asregs.insts);
1301}
1302
1303
1304SIM_DESC
1305sim_open (kind, cb, abfd, argv)
1306 SIM_OPEN_KIND kind;
1307 host_callback * cb;
1308 struct bfd * abfd;
1309 char ** argv;
1310{
1311 int osize = sim_memory_size;
1312 myname = argv[0];
1313 callback = cb;
1314
1315 if (kind == SIM_OPEN_STANDALONE)
1316 issue_messages = 1;
1317
1318 /* Discard and reacquire memory -- start with a clean slate. */
1319 sim_size (1); /* small */
1320 sim_size (osize); /* and back again */
1321
1322 set_initial_gprs (); /* Reset the GPR registers. */
1323
1324 /* Fudge our descriptor for now. */
1325 return (SIM_DESC) 1;
1326}
1327
1328void
1329sim_close (sd, quitting)
1330 SIM_DESC sd;
1331 int quitting;
1332{
1333 /* nothing to do */
1334}
1335
1336SIM_RC
1337sim_load (sd, prog, abfd, from_tty)
1338 SIM_DESC sd;
1339 char * prog;
1340 bfd * abfd;
1341 int from_tty;
1342{
1343
1344 /* Do the right thing for ELF executables; this turns out to be
1345 just about the right thing for any object format that:
1346 - we crack using BFD routines
1347 - follows the traditional UNIX text/data/bss layout
1348 - calls the bss section ".bss". */
1349
1350 extern bfd * sim_load_file (); /* ??? Don't know where this should live. */
1351 bfd * prog_bfd;
1352
1353 {
1354 bfd * handle;
1355 handle = bfd_openr (prog, 0); /* could be "moxie" */
1356
1357 if (!handle)
1358 {
1359 printf("``%s'' could not be opened.\n", prog);
1360 return SIM_RC_FAIL;
1361 }
1362
1363 /* Makes sure that we have an object file, also cleans gets the
1364 section headers in place. */
1365 if (!bfd_check_format (handle, bfd_object))
1366 {
1367 /* wasn't an object file */
1368 bfd_close (handle);
1369 printf ("``%s'' is not appropriate object file.\n", prog);
1370 return SIM_RC_FAIL;
1371 }
1372
1373 /* Clean up after ourselves. */
1374 bfd_close (handle);
1375 }
1376
1377 /* from sh -- dac */
1378 prog_bfd = sim_load_file (sd, myname, callback, prog, abfd,
1379 sim_kind == SIM_OPEN_DEBUG,
1380 0, sim_write);
1381 if (prog_bfd == NULL)
1382 return SIM_RC_FAIL;
1383
1384 if (abfd == NULL)
1385 bfd_close (prog_bfd);
1386
1387 return SIM_RC_OK;
1388}
1389
1390SIM_RC
1391sim_create_inferior (sd, prog_bfd, argv, env)
1392 SIM_DESC sd;
1393 struct bfd * prog_bfd;
1394 char ** argv;
1395 char ** env;
1396{
1397 char ** avp;
1398 int l, argc, i, tp;
1399
1400 /* Set the initial register set. */
1401 l = issue_messages;
1402 issue_messages = 0;
1403 set_initial_gprs ();
1404 issue_messages = l;
1405
1406 cpu.asregs.regs[PC_REGNO] = bfd_get_start_address (prog_bfd);
1407
1408 /* Copy args into target memory. */
1409 avp = argv;
1410 for (argc = 0; *avp; avp++)
1411 argc++;
1412
1413 /* Target memory looks like this:
1414 0x00000000 zero word
1415 0x00000004 argc word
1416 0x00000008 start of argv
1417 .
1418 0x0000???? end of argv
1419 0x0000???? zero word
1420 0x0000???? start of data pointed to by argv */
1421
1422 wlat (0, 0, 0);
1423 wlat (0, 4, argc);
1424
1425 /* tp is the offset of our first argv data. */
1426 tp = 4 + 4 + argc * 4 + 4;
1427
1428 for (i = 0; i < argc; i++)
1429 {
1430 /* Set the argv value. */
1431 wlat (0, 4 + 4 + i * 4, tp);
1432
1433 /* Store the string. */
1434 strcpy (&cpu.asregs.memory[tp], argv[i]);
1435 tp += strlen (argv[i]) + 1;
1436 }
1437
1438 wlat (0, 4 + 4 + i * 4, 0);
1439
1440 return SIM_RC_OK;
1441}
1442
1443void
1444sim_kill (sd)
1445 SIM_DESC sd;
1446{
1447 if (tracefile)
1448 fclose(tracefile);
1449}
1450
1451void
1452sim_do_command (sd, cmd)
1453 SIM_DESC sd;
1454 char * cmd;
1455{
1456 /* Nothing there yet; it's all an error. */
1457
1458 if (cmd != NULL)
1459 {
1460 char ** simargv = buildargv (cmd);
1461 if (strcmp (simargv[0], "verbose") == 0)
1462 {
1463 issue_messages = 2;
1464 }
1465 else
1466 {
1467 fprintf (stderr,"Error: \"%s\" is not a valid moxie simulator command.\n",
1468 cmd);
1469 }
1470 }
1471 else
1472 {
1473 fprintf (stderr, "moxie sim commands: \n");
1474 fprintf (stderr, " verbose\n");
1475 }
1476}
1477
1478void
1479sim_set_callbacks (ptr)
1480 host_callback * ptr;
1481{
1482 callback = ptr;
1483}
This page took 0.116625 seconds and 4 git commands to generate.