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