Rotate gdb/ChangeLog (start of New Year procedure)
[binutils-gdb.git] / sim / moxie / interp.c
blobfe770093e533d3ede553191c91584f2e8abab602
1 /* Simulator for the moxie processor
2 Copyright (C) 2008-2019 Free Software Foundation, Inc.
3 Contributed by Anthony Green
5 This file is part of GDB, the GNU debugger.
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.
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.
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/>. */
20 #include "config.h"
21 #include <fcntl.h>
22 #include <signal.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <sys/times.h>
26 #include <sys/param.h>
27 #include <unistd.h>
28 #include "bfd.h"
29 #include "libiberty.h"
30 #include "gdb/remote-sim.h"
32 #include "sim-main.h"
33 #include "sim-base.h"
34 #include "sim-options.h"
35 #include "sim-io.h"
37 typedef int word;
38 typedef unsigned int uword;
40 /* Extract the signed 10-bit offset from a 16-bit branch
41 instruction. */
42 #define INST2OFFSET(o) ((((signed short)((o & ((1<<10)-1))<<6))>>6)<<1)
44 #define EXTRACT_WORD(addr) \
45 ((sim_core_read_aligned_1 (scpu, cia, read_map, addr) << 24) \
46 + (sim_core_read_aligned_1 (scpu, cia, read_map, addr+1) << 16) \
47 + (sim_core_read_aligned_1 (scpu, cia, read_map, addr+2) << 8) \
48 + (sim_core_read_aligned_1 (scpu, cia, read_map, addr+3)))
50 #define EXTRACT_OFFSET(addr) \
51 (unsigned int) \
52 (((signed short) \
53 ((sim_core_read_aligned_1 (scpu, cia, read_map, addr) << 8) \
54 + (sim_core_read_aligned_1 (scpu, cia, read_map, addr+1))) << 16) >> 16)
56 static unsigned long
57 moxie_extract_unsigned_integer (unsigned char *addr, int len)
59 unsigned long retval;
60 unsigned char * p;
61 unsigned char * startaddr = (unsigned char *)addr;
62 unsigned char * endaddr = startaddr + len;
64 if (len > (int) sizeof (unsigned long))
65 printf ("That operation is not available on integers of more than %zu bytes.",
66 sizeof (unsigned long));
68 /* Start at the most significant end of the integer, and work towards
69 the least significant. */
70 retval = 0;
72 for (p = endaddr; p > startaddr;)
73 retval = (retval << 8) | * -- p;
75 return retval;
78 static void
79 moxie_store_unsigned_integer (unsigned char *addr, int len, unsigned long val)
81 unsigned char * p;
82 unsigned char * startaddr = (unsigned char *)addr;
83 unsigned char * endaddr = startaddr + len;
85 for (p = endaddr; p > startaddr;)
87 * -- p = val & 0xff;
88 val >>= 8;
92 /* moxie register names. */
93 static const char *reg_names[16] =
94 { "$fp", "$sp", "$r0", "$r1", "$r2", "$r3", "$r4", "$r5",
95 "$r6", "$r7", "$r8", "$r9", "$r10", "$r11", "$r12", "$r13" };
97 /* The machine state.
99 This state is maintained in host byte order. The fetch/store
100 register functions must translate between host byte order and the
101 target processor byte order. Keeping this data in target byte
102 order simplifies the register read/write functions. Keeping this
103 data in native order improves the performance of the simulator.
104 Simulation speed is deemed more important. */
106 #define NUM_MOXIE_REGS 17 /* Including PC */
107 #define NUM_MOXIE_SREGS 256 /* The special registers */
108 #define PC_REGNO 16
110 /* The ordering of the moxie_regset structure is matched in the
111 gdb/config/moxie/tm-moxie.h file in the REGISTER_NAMES macro. */
112 /* TODO: This should be moved to sim-main.h:_sim_cpu. */
113 struct moxie_regset
115 word regs[NUM_MOXIE_REGS + 1]; /* primary registers */
116 word sregs[256]; /* special registers */
117 word cc; /* the condition code reg */
118 unsigned long long insts; /* instruction counter */
121 #define CC_GT 1<<0
122 #define CC_LT 1<<1
123 #define CC_EQ 1<<2
124 #define CC_GTU 1<<3
125 #define CC_LTU 1<<4
127 /* TODO: This should be moved to sim-main.h:_sim_cpu. */
128 union
130 struct moxie_regset asregs;
131 word asints [1]; /* but accessed larger... */
132 } cpu;
134 static void
135 set_initial_gprs (void)
137 int i;
138 long space;
140 /* Set up machine just out of reset. */
141 cpu.asregs.regs[PC_REGNO] = 0;
143 /* Clean out the register contents. */
144 for (i = 0; i < NUM_MOXIE_REGS; i++)
145 cpu.asregs.regs[i] = 0;
146 for (i = 0; i < NUM_MOXIE_SREGS; i++)
147 cpu.asregs.sregs[i] = 0;
150 /* Write a 1 byte value to memory. */
152 static INLINE void
153 wbat (sim_cpu *scpu, word pc, word x, word v)
155 address_word cia = CPU_PC_GET (scpu);
157 sim_core_write_aligned_1 (scpu, cia, write_map, x, v);
160 /* Write a 2 byte value to memory. */
162 static INLINE void
163 wsat (sim_cpu *scpu, word pc, word x, word v)
165 address_word cia = CPU_PC_GET (scpu);
167 sim_core_write_aligned_2 (scpu, cia, write_map, x, v);
170 /* Write a 4 byte value to memory. */
172 static INLINE void
173 wlat (sim_cpu *scpu, word pc, word x, word v)
175 address_word cia = CPU_PC_GET (scpu);
177 sim_core_write_aligned_4 (scpu, cia, write_map, x, v);
180 /* Read 2 bytes from memory. */
182 static INLINE int
183 rsat (sim_cpu *scpu, word pc, word x)
185 address_word cia = CPU_PC_GET (scpu);
187 return (sim_core_read_aligned_2 (scpu, cia, read_map, x));
190 /* Read 1 byte from memory. */
192 static INLINE int
193 rbat (sim_cpu *scpu, word pc, word x)
195 address_word cia = CPU_PC_GET (scpu);
197 return (sim_core_read_aligned_1 (scpu, cia, read_map, x));
200 /* Read 4 bytes from memory. */
202 static INLINE int
203 rlat (sim_cpu *scpu, word pc, word x)
205 address_word cia = CPU_PC_GET (scpu);
207 return (sim_core_read_aligned_4 (scpu, cia, read_map, x));
210 #define CHECK_FLAG(T,H) if (tflags & T) { hflags |= H; tflags ^= T; }
212 static unsigned int
213 convert_target_flags (unsigned int tflags)
215 unsigned int hflags = 0x0;
217 CHECK_FLAG(0x0001, O_WRONLY);
218 CHECK_FLAG(0x0002, O_RDWR);
219 CHECK_FLAG(0x0008, O_APPEND);
220 CHECK_FLAG(0x0200, O_CREAT);
221 CHECK_FLAG(0x0400, O_TRUNC);
222 CHECK_FLAG(0x0800, O_EXCL);
223 CHECK_FLAG(0x2000, O_SYNC);
225 if (tflags != 0x0)
226 fprintf (stderr,
227 "Simulator Error: problem converting target open flags for host. 0x%x\n",
228 tflags);
230 return hflags;
233 /* TODO: Split this up into finger trace levels than just insn. */
234 #define MOXIE_TRACE_INSN(str) \
235 TRACE_INSN (scpu, "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", \
236 opc, str, cpu.asregs.regs[0], cpu.asregs.regs[1], \
237 cpu.asregs.regs[2], cpu.asregs.regs[3], cpu.asregs.regs[4], \
238 cpu.asregs.regs[5], cpu.asregs.regs[6], cpu.asregs.regs[7], \
239 cpu.asregs.regs[8], cpu.asregs.regs[9], cpu.asregs.regs[10], \
240 cpu.asregs.regs[11], cpu.asregs.regs[12], cpu.asregs.regs[13], \
241 cpu.asregs.regs[14], cpu.asregs.regs[15])
243 void
244 sim_engine_run (SIM_DESC sd,
245 int next_cpu_nr, /* ignore */
246 int nr_cpus, /* ignore */
247 int siggnal) /* ignore */
249 word pc, opc;
250 unsigned short inst;
251 sim_cpu *scpu = STATE_CPU (sd, 0); /* FIXME */
252 address_word cia = CPU_PC_GET (scpu);
254 pc = cpu.asregs.regs[PC_REGNO];
256 /* Run instructions here. */
259 opc = pc;
261 /* Fetch the instruction at pc. */
262 inst = (sim_core_read_aligned_1 (scpu, cia, read_map, pc) << 8)
263 + sim_core_read_aligned_1 (scpu, cia, read_map, pc+1);
265 /* Decode instruction. */
266 if (inst & (1 << 15))
268 if (inst & (1 << 14))
270 /* This is a Form 3 instruction. */
271 int opcode = (inst >> 10 & 0xf);
273 switch (opcode)
275 case 0x00: /* beq */
277 MOXIE_TRACE_INSN ("beq");
278 if (cpu.asregs.cc & CC_EQ)
279 pc += INST2OFFSET(inst);
281 break;
282 case 0x01: /* bne */
284 MOXIE_TRACE_INSN ("bne");
285 if (! (cpu.asregs.cc & CC_EQ))
286 pc += INST2OFFSET(inst);
288 break;
289 case 0x02: /* blt */
291 MOXIE_TRACE_INSN ("blt");
292 if (cpu.asregs.cc & CC_LT)
293 pc += INST2OFFSET(inst);
294 } break;
295 case 0x03: /* bgt */
297 MOXIE_TRACE_INSN ("bgt");
298 if (cpu.asregs.cc & CC_GT)
299 pc += INST2OFFSET(inst);
301 break;
302 case 0x04: /* bltu */
304 MOXIE_TRACE_INSN ("bltu");
305 if (cpu.asregs.cc & CC_LTU)
306 pc += INST2OFFSET(inst);
308 break;
309 case 0x05: /* bgtu */
311 MOXIE_TRACE_INSN ("bgtu");
312 if (cpu.asregs.cc & CC_GTU)
313 pc += INST2OFFSET(inst);
315 break;
316 case 0x06: /* bge */
318 MOXIE_TRACE_INSN ("bge");
319 if (cpu.asregs.cc & (CC_GT | CC_EQ))
320 pc += INST2OFFSET(inst);
322 break;
323 case 0x07: /* ble */
325 MOXIE_TRACE_INSN ("ble");
326 if (cpu.asregs.cc & (CC_LT | CC_EQ))
327 pc += INST2OFFSET(inst);
329 break;
330 case 0x08: /* bgeu */
332 MOXIE_TRACE_INSN ("bgeu");
333 if (cpu.asregs.cc & (CC_GTU | CC_EQ))
334 pc += INST2OFFSET(inst);
336 break;
337 case 0x09: /* bleu */
339 MOXIE_TRACE_INSN ("bleu");
340 if (cpu.asregs.cc & (CC_LTU | CC_EQ))
341 pc += INST2OFFSET(inst);
343 break;
344 default:
346 MOXIE_TRACE_INSN ("SIGILL3");
347 sim_engine_halt (sd, scpu, NULL, pc, sim_stopped, SIM_SIGILL);
348 break;
352 else
354 /* This is a Form 2 instruction. */
355 int opcode = (inst >> 12 & 0x3);
356 switch (opcode)
358 case 0x00: /* inc */
360 int a = (inst >> 8) & 0xf;
361 unsigned av = cpu.asregs.regs[a];
362 unsigned v = (inst & 0xff);
364 MOXIE_TRACE_INSN ("inc");
365 cpu.asregs.regs[a] = av + v;
367 break;
368 case 0x01: /* dec */
370 int a = (inst >> 8) & 0xf;
371 unsigned av = cpu.asregs.regs[a];
372 unsigned v = (inst & 0xff);
374 MOXIE_TRACE_INSN ("dec");
375 cpu.asregs.regs[a] = av - v;
377 break;
378 case 0x02: /* gsr */
380 int a = (inst >> 8) & 0xf;
381 unsigned v = (inst & 0xff);
383 MOXIE_TRACE_INSN ("gsr");
384 cpu.asregs.regs[a] = cpu.asregs.sregs[v];
386 break;
387 case 0x03: /* ssr */
389 int a = (inst >> 8) & 0xf;
390 unsigned v = (inst & 0xff);
392 MOXIE_TRACE_INSN ("ssr");
393 cpu.asregs.sregs[v] = cpu.asregs.regs[a];
395 break;
396 default:
397 MOXIE_TRACE_INSN ("SIGILL2");
398 sim_engine_halt (sd, scpu, NULL, pc, sim_stopped, SIM_SIGILL);
399 break;
403 else
405 /* This is a Form 1 instruction. */
406 int opcode = inst >> 8;
407 switch (opcode)
409 case 0x00: /* bad */
410 opc = opcode;
411 MOXIE_TRACE_INSN ("SIGILL0");
412 sim_engine_halt (sd, scpu, NULL, pc, sim_stopped, SIM_SIGILL);
413 break;
414 case 0x01: /* ldi.l (immediate) */
416 int reg = (inst >> 4) & 0xf;
417 unsigned int val = EXTRACT_WORD(pc+2);
419 MOXIE_TRACE_INSN ("ldi.l");
420 cpu.asregs.regs[reg] = val;
421 pc += 4;
423 break;
424 case 0x02: /* mov (register-to-register) */
426 int dest = (inst >> 4) & 0xf;
427 int src = (inst ) & 0xf;
429 MOXIE_TRACE_INSN ("mov");
430 cpu.asregs.regs[dest] = cpu.asregs.regs[src];
432 break;
433 case 0x03: /* jsra */
435 unsigned int fn = EXTRACT_WORD(pc+2);
436 unsigned int sp = cpu.asregs.regs[1];
438 MOXIE_TRACE_INSN ("jsra");
439 /* Save a slot for the static chain. */
440 sp -= 4;
442 /* Push the return address. */
443 sp -= 4;
444 wlat (scpu, opc, sp, pc + 6);
446 /* Push the current frame pointer. */
447 sp -= 4;
448 wlat (scpu, opc, sp, cpu.asregs.regs[0]);
450 /* Uncache the stack pointer and set the pc and $fp. */
451 cpu.asregs.regs[1] = sp;
452 cpu.asregs.regs[0] = sp;
453 pc = fn - 2;
455 break;
456 case 0x04: /* ret */
458 unsigned int sp = cpu.asregs.regs[0];
460 MOXIE_TRACE_INSN ("ret");
462 /* Pop the frame pointer. */
463 cpu.asregs.regs[0] = rlat (scpu, opc, sp);
464 sp += 4;
466 /* Pop the return address. */
467 pc = rlat (scpu, opc, sp) - 2;
468 sp += 4;
470 /* Skip over the static chain slot. */
471 sp += 4;
473 /* Uncache the stack pointer. */
474 cpu.asregs.regs[1] = sp;
476 break;
477 case 0x05: /* add.l */
479 int a = (inst >> 4) & 0xf;
480 int b = inst & 0xf;
481 unsigned av = cpu.asregs.regs[a];
482 unsigned bv = cpu.asregs.regs[b];
484 MOXIE_TRACE_INSN ("add.l");
485 cpu.asregs.regs[a] = av + bv;
487 break;
488 case 0x06: /* push */
490 int a = (inst >> 4) & 0xf;
491 int b = inst & 0xf;
492 int sp = cpu.asregs.regs[a] - 4;
494 MOXIE_TRACE_INSN ("push");
495 wlat (scpu, opc, sp, cpu.asregs.regs[b]);
496 cpu.asregs.regs[a] = sp;
498 break;
499 case 0x07: /* pop */
501 int a = (inst >> 4) & 0xf;
502 int b = inst & 0xf;
503 int sp = cpu.asregs.regs[a];
505 MOXIE_TRACE_INSN ("pop");
506 cpu.asregs.regs[b] = rlat (scpu, opc, sp);
507 cpu.asregs.regs[a] = sp + 4;
509 break;
510 case 0x08: /* lda.l */
512 int reg = (inst >> 4) & 0xf;
513 unsigned int addr = EXTRACT_WORD(pc+2);
515 MOXIE_TRACE_INSN ("lda.l");
516 cpu.asregs.regs[reg] = rlat (scpu, opc, addr);
517 pc += 4;
519 break;
520 case 0x09: /* sta.l */
522 int reg = (inst >> 4) & 0xf;
523 unsigned int addr = EXTRACT_WORD(pc+2);
525 MOXIE_TRACE_INSN ("sta.l");
526 wlat (scpu, opc, addr, cpu.asregs.regs[reg]);
527 pc += 4;
529 break;
530 case 0x0a: /* ld.l (register indirect) */
532 int src = inst & 0xf;
533 int dest = (inst >> 4) & 0xf;
534 int xv;
536 MOXIE_TRACE_INSN ("ld.l");
537 xv = cpu.asregs.regs[src];
538 cpu.asregs.regs[dest] = rlat (scpu, opc, xv);
540 break;
541 case 0x0b: /* st.l */
543 int dest = (inst >> 4) & 0xf;
544 int val = inst & 0xf;
546 MOXIE_TRACE_INSN ("st.l");
547 wlat (scpu, opc, cpu.asregs.regs[dest], cpu.asregs.regs[val]);
549 break;
550 case 0x0c: /* ldo.l */
552 unsigned int addr = EXTRACT_OFFSET(pc+2);
553 int a = (inst >> 4) & 0xf;
554 int b = inst & 0xf;
556 MOXIE_TRACE_INSN ("ldo.l");
557 addr += cpu.asregs.regs[b];
558 cpu.asregs.regs[a] = rlat (scpu, opc, addr);
559 pc += 2;
561 break;
562 case 0x0d: /* sto.l */
564 unsigned int addr = EXTRACT_OFFSET(pc+2);
565 int a = (inst >> 4) & 0xf;
566 int b = inst & 0xf;
568 MOXIE_TRACE_INSN ("sto.l");
569 addr += cpu.asregs.regs[a];
570 wlat (scpu, opc, addr, cpu.asregs.regs[b]);
571 pc += 2;
573 break;
574 case 0x0e: /* cmp */
576 int a = (inst >> 4) & 0xf;
577 int b = inst & 0xf;
578 int cc = 0;
579 int va = cpu.asregs.regs[a];
580 int vb = cpu.asregs.regs[b];
582 MOXIE_TRACE_INSN ("cmp");
583 if (va == vb)
584 cc = CC_EQ;
585 else
587 cc |= (va < vb ? CC_LT : 0);
588 cc |= (va > vb ? CC_GT : 0);
589 cc |= ((unsigned int) va < (unsigned int) vb ? CC_LTU : 0);
590 cc |= ((unsigned int) va > (unsigned int) vb ? CC_GTU : 0);
593 cpu.asregs.cc = cc;
595 break;
596 case 0x0f: /* nop */
597 break;
598 case 0x10: /* sex.b */
600 int a = (inst >> 4) & 0xf;
601 int b = inst & 0xf;
602 signed char bv = cpu.asregs.regs[b];
604 MOXIE_TRACE_INSN ("sex.b");
605 cpu.asregs.regs[a] = (int) bv;
607 break;
608 case 0x11: /* sex.s */
610 int a = (inst >> 4) & 0xf;
611 int b = inst & 0xf;
612 signed short bv = cpu.asregs.regs[b];
614 MOXIE_TRACE_INSN ("sex.s");
615 cpu.asregs.regs[a] = (int) bv;
617 break;
618 case 0x12: /* zex.b */
620 int a = (inst >> 4) & 0xf;
621 int b = inst & 0xf;
622 signed char bv = cpu.asregs.regs[b];
624 MOXIE_TRACE_INSN ("zex.b");
625 cpu.asregs.regs[a] = (int) bv & 0xff;
627 break;
628 case 0x13: /* zex.s */
630 int a = (inst >> 4) & 0xf;
631 int b = inst & 0xf;
632 signed short bv = cpu.asregs.regs[b];
634 MOXIE_TRACE_INSN ("zex.s");
635 cpu.asregs.regs[a] = (int) bv & 0xffff;
637 break;
638 case 0x14: /* umul.x */
640 int a = (inst >> 4) & 0xf;
641 int b = inst & 0xf;
642 unsigned av = cpu.asregs.regs[a];
643 unsigned bv = cpu.asregs.regs[b];
644 unsigned long long r =
645 (unsigned long long) av * (unsigned long long) bv;
647 MOXIE_TRACE_INSN ("umul.x");
648 cpu.asregs.regs[a] = r >> 32;
650 break;
651 case 0x15: /* mul.x */
653 int a = (inst >> 4) & 0xf;
654 int b = inst & 0xf;
655 unsigned av = cpu.asregs.regs[a];
656 unsigned bv = cpu.asregs.regs[b];
657 signed long long r =
658 (signed long long) av * (signed long long) bv;
660 MOXIE_TRACE_INSN ("mul.x");
661 cpu.asregs.regs[a] = r >> 32;
663 break;
664 case 0x16: /* bad */
665 case 0x17: /* bad */
666 case 0x18: /* bad */
668 opc = opcode;
669 MOXIE_TRACE_INSN ("SIGILL0");
670 sim_engine_halt (sd, scpu, NULL, pc, sim_stopped, SIM_SIGILL);
671 break;
673 case 0x19: /* jsr */
675 unsigned int fn = cpu.asregs.regs[(inst >> 4) & 0xf];
676 unsigned int sp = cpu.asregs.regs[1];
678 MOXIE_TRACE_INSN ("jsr");
680 /* Save a slot for the static chain. */
681 sp -= 4;
683 /* Push the return address. */
684 sp -= 4;
685 wlat (scpu, opc, sp, pc + 2);
687 /* Push the current frame pointer. */
688 sp -= 4;
689 wlat (scpu, opc, sp, cpu.asregs.regs[0]);
691 /* Uncache the stack pointer and set the fp & pc. */
692 cpu.asregs.regs[1] = sp;
693 cpu.asregs.regs[0] = sp;
694 pc = fn - 2;
696 break;
697 case 0x1a: /* jmpa */
699 unsigned int tgt = EXTRACT_WORD(pc+2);
701 MOXIE_TRACE_INSN ("jmpa");
702 pc = tgt - 2;
704 break;
705 case 0x1b: /* ldi.b (immediate) */
707 int reg = (inst >> 4) & 0xf;
708 unsigned int val = EXTRACT_WORD(pc+2);
710 MOXIE_TRACE_INSN ("ldi.b");
711 cpu.asregs.regs[reg] = val;
712 pc += 4;
714 break;
715 case 0x1c: /* ld.b (register indirect) */
717 int src = inst & 0xf;
718 int dest = (inst >> 4) & 0xf;
719 int xv;
721 MOXIE_TRACE_INSN ("ld.b");
722 xv = cpu.asregs.regs[src];
723 cpu.asregs.regs[dest] = rbat (scpu, opc, xv);
725 break;
726 case 0x1d: /* lda.b */
728 int reg = (inst >> 4) & 0xf;
729 unsigned int addr = EXTRACT_WORD(pc+2);
731 MOXIE_TRACE_INSN ("lda.b");
732 cpu.asregs.regs[reg] = rbat (scpu, opc, addr);
733 pc += 4;
735 break;
736 case 0x1e: /* st.b */
738 int dest = (inst >> 4) & 0xf;
739 int val = inst & 0xf;
741 MOXIE_TRACE_INSN ("st.b");
742 wbat (scpu, opc, cpu.asregs.regs[dest], cpu.asregs.regs[val]);
744 break;
745 case 0x1f: /* sta.b */
747 int reg = (inst >> 4) & 0xf;
748 unsigned int addr = EXTRACT_WORD(pc+2);
750 MOXIE_TRACE_INSN ("sta.b");
751 wbat (scpu, opc, addr, cpu.asregs.regs[reg]);
752 pc += 4;
754 break;
755 case 0x20: /* ldi.s (immediate) */
757 int reg = (inst >> 4) & 0xf;
759 unsigned int val = EXTRACT_WORD(pc+2);
761 MOXIE_TRACE_INSN ("ldi.s");
762 cpu.asregs.regs[reg] = val;
763 pc += 4;
765 break;
766 case 0x21: /* ld.s (register indirect) */
768 int src = inst & 0xf;
769 int dest = (inst >> 4) & 0xf;
770 int xv;
772 MOXIE_TRACE_INSN ("ld.s");
773 xv = cpu.asregs.regs[src];
774 cpu.asregs.regs[dest] = rsat (scpu, opc, xv);
776 break;
777 case 0x22: /* lda.s */
779 int reg = (inst >> 4) & 0xf;
780 unsigned int addr = EXTRACT_WORD(pc+2);
782 MOXIE_TRACE_INSN ("lda.s");
783 cpu.asregs.regs[reg] = rsat (scpu, opc, addr);
784 pc += 4;
786 break;
787 case 0x23: /* st.s */
789 int dest = (inst >> 4) & 0xf;
790 int val = inst & 0xf;
792 MOXIE_TRACE_INSN ("st.s");
793 wsat (scpu, opc, cpu.asregs.regs[dest], cpu.asregs.regs[val]);
795 break;
796 case 0x24: /* sta.s */
798 int reg = (inst >> 4) & 0xf;
799 unsigned int addr = EXTRACT_WORD(pc+2);
801 MOXIE_TRACE_INSN ("sta.s");
802 wsat (scpu, opc, addr, cpu.asregs.regs[reg]);
803 pc += 4;
805 break;
806 case 0x25: /* jmp */
808 int reg = (inst >> 4) & 0xf;
810 MOXIE_TRACE_INSN ("jmp");
811 pc = cpu.asregs.regs[reg] - 2;
813 break;
814 case 0x26: /* and */
816 int a = (inst >> 4) & 0xf;
817 int b = inst & 0xf;
818 int av, bv;
820 MOXIE_TRACE_INSN ("and");
821 av = cpu.asregs.regs[a];
822 bv = cpu.asregs.regs[b];
823 cpu.asregs.regs[a] = av & bv;
825 break;
826 case 0x27: /* lshr */
828 int a = (inst >> 4) & 0xf;
829 int b = inst & 0xf;
830 int av = cpu.asregs.regs[a];
831 int bv = cpu.asregs.regs[b];
833 MOXIE_TRACE_INSN ("lshr");
834 cpu.asregs.regs[a] = (unsigned) ((unsigned) av >> bv);
836 break;
837 case 0x28: /* ashl */
839 int a = (inst >> 4) & 0xf;
840 int b = inst & 0xf;
841 int av = cpu.asregs.regs[a];
842 int bv = cpu.asregs.regs[b];
844 MOXIE_TRACE_INSN ("ashl");
845 cpu.asregs.regs[a] = av << bv;
847 break;
848 case 0x29: /* sub.l */
850 int a = (inst >> 4) & 0xf;
851 int b = inst & 0xf;
852 unsigned av = cpu.asregs.regs[a];
853 unsigned bv = cpu.asregs.regs[b];
855 MOXIE_TRACE_INSN ("sub.l");
856 cpu.asregs.regs[a] = av - bv;
858 break;
859 case 0x2a: /* neg */
861 int a = (inst >> 4) & 0xf;
862 int b = inst & 0xf;
863 int bv = cpu.asregs.regs[b];
865 MOXIE_TRACE_INSN ("neg");
866 cpu.asregs.regs[a] = - bv;
868 break;
869 case 0x2b: /* or */
871 int a = (inst >> 4) & 0xf;
872 int b = inst & 0xf;
873 int av, bv;
875 MOXIE_TRACE_INSN ("or");
876 av = cpu.asregs.regs[a];
877 bv = cpu.asregs.regs[b];
878 cpu.asregs.regs[a] = av | bv;
880 break;
881 case 0x2c: /* not */
883 int a = (inst >> 4) & 0xf;
884 int b = inst & 0xf;
885 int bv = cpu.asregs.regs[b];
887 MOXIE_TRACE_INSN ("not");
888 cpu.asregs.regs[a] = 0xffffffff ^ bv;
890 break;
891 case 0x2d: /* ashr */
893 int a = (inst >> 4) & 0xf;
894 int b = inst & 0xf;
895 int av = cpu.asregs.regs[a];
896 int bv = cpu.asregs.regs[b];
898 MOXIE_TRACE_INSN ("ashr");
899 cpu.asregs.regs[a] = av >> bv;
901 break;
902 case 0x2e: /* xor */
904 int a = (inst >> 4) & 0xf;
905 int b = inst & 0xf;
906 int av, bv;
908 MOXIE_TRACE_INSN ("xor");
909 av = cpu.asregs.regs[a];
910 bv = cpu.asregs.regs[b];
911 cpu.asregs.regs[a] = av ^ bv;
913 break;
914 case 0x2f: /* mul.l */
916 int a = (inst >> 4) & 0xf;
917 int b = inst & 0xf;
918 unsigned av = cpu.asregs.regs[a];
919 unsigned bv = cpu.asregs.regs[b];
921 MOXIE_TRACE_INSN ("mul.l");
922 cpu.asregs.regs[a] = av * bv;
924 break;
925 case 0x30: /* swi */
927 unsigned int inum = EXTRACT_WORD(pc+2);
929 MOXIE_TRACE_INSN ("swi");
930 /* Set the special registers appropriately. */
931 cpu.asregs.sregs[2] = 3; /* MOXIE_EX_SWI */
932 cpu.asregs.sregs[3] = inum;
933 switch (inum)
935 case 0x1: /* SYS_exit */
937 sim_engine_halt (sd, scpu, NULL, pc, sim_exited,
938 cpu.asregs.regs[2]);
939 break;
941 case 0x2: /* SYS_open */
943 char fname[1024];
944 int mode = (int) convert_target_flags ((unsigned) cpu.asregs.regs[3]);
945 int perm = (int) cpu.asregs.regs[4];
946 int fd;
947 sim_core_read_buffer (sd, scpu, read_map, fname,
948 cpu.asregs.regs[2], 1024);
949 fd = sim_io_open (sd, fname, mode);
950 /* FIXME - set errno */
951 cpu.asregs.regs[2] = fd;
952 break;
954 case 0x4: /* SYS_read */
956 int fd = cpu.asregs.regs[2];
957 unsigned len = (unsigned) cpu.asregs.regs[4];
958 char *buf = malloc (len);
959 cpu.asregs.regs[2] = sim_io_read (sd, fd, buf, len);
960 sim_core_write_buffer (sd, scpu, write_map, buf,
961 cpu.asregs.regs[3], len);
962 free (buf);
963 break;
965 case 0x5: /* SYS_write */
967 char *str;
968 /* String length is at 0x12($fp) */
969 unsigned count, len = (unsigned) cpu.asregs.regs[4];
970 str = malloc (len);
971 sim_core_read_buffer (sd, scpu, read_map, str,
972 cpu.asregs.regs[3], len);
973 count = sim_io_write (sd, cpu.asregs.regs[2], str, len);
974 free (str);
975 cpu.asregs.regs[2] = count;
976 break;
978 case 0x7: /* SYS_unlink */
980 char fname[1024];
981 int fd;
982 sim_core_read_buffer (sd, scpu, read_map, fname,
983 cpu.asregs.regs[2], 1024);
984 fd = sim_io_unlink (sd, fname);
985 /* FIXME - set errno */
986 cpu.asregs.regs[2] = fd;
987 break;
989 case 0xffffffff: /* Linux System Call */
991 unsigned int handler = cpu.asregs.sregs[1];
992 unsigned int sp = cpu.asregs.regs[1];
994 /* Save a slot for the static chain. */
995 sp -= 4;
997 /* Push the return address. */
998 sp -= 4;
999 wlat (scpu, opc, sp, pc + 6);
1001 /* Push the current frame pointer. */
1002 sp -= 4;
1003 wlat (scpu, opc, sp, cpu.asregs.regs[0]);
1005 /* Uncache the stack pointer and set the fp & pc. */
1006 cpu.asregs.regs[1] = sp;
1007 cpu.asregs.regs[0] = sp;
1008 pc = handler - 6;
1010 default:
1011 break;
1013 pc += 4;
1015 break;
1016 case 0x31: /* div.l */
1018 int a = (inst >> 4) & 0xf;
1019 int b = inst & 0xf;
1020 int av = cpu.asregs.regs[a];
1021 int bv = cpu.asregs.regs[b];
1023 MOXIE_TRACE_INSN ("div.l");
1024 cpu.asregs.regs[a] = av / bv;
1026 break;
1027 case 0x32: /* udiv.l */
1029 int a = (inst >> 4) & 0xf;
1030 int b = inst & 0xf;
1031 unsigned int av = cpu.asregs.regs[a];
1032 unsigned int bv = cpu.asregs.regs[b];
1034 MOXIE_TRACE_INSN ("udiv.l");
1035 cpu.asregs.regs[a] = (av / bv);
1037 break;
1038 case 0x33: /* mod.l */
1040 int a = (inst >> 4) & 0xf;
1041 int b = inst & 0xf;
1042 int av = cpu.asregs.regs[a];
1043 int bv = cpu.asregs.regs[b];
1045 MOXIE_TRACE_INSN ("mod.l");
1046 cpu.asregs.regs[a] = av % bv;
1048 break;
1049 case 0x34: /* umod.l */
1051 int a = (inst >> 4) & 0xf;
1052 int b = inst & 0xf;
1053 unsigned int av = cpu.asregs.regs[a];
1054 unsigned int bv = cpu.asregs.regs[b];
1056 MOXIE_TRACE_INSN ("umod.l");
1057 cpu.asregs.regs[a] = (av % bv);
1059 break;
1060 case 0x35: /* brk */
1061 MOXIE_TRACE_INSN ("brk");
1062 sim_engine_halt (sd, scpu, NULL, pc, sim_stopped, SIM_SIGTRAP);
1063 pc -= 2; /* Adjust pc */
1064 break;
1065 case 0x36: /* ldo.b */
1067 unsigned int addr = EXTRACT_OFFSET(pc+2);
1068 int a = (inst >> 4) & 0xf;
1069 int b = inst & 0xf;
1071 MOXIE_TRACE_INSN ("ldo.b");
1072 addr += cpu.asregs.regs[b];
1073 cpu.asregs.regs[a] = rbat (scpu, opc, addr);
1074 pc += 2;
1076 break;
1077 case 0x37: /* sto.b */
1079 unsigned int addr = EXTRACT_OFFSET(pc+2);
1080 int a = (inst >> 4) & 0xf;
1081 int b = inst & 0xf;
1083 MOXIE_TRACE_INSN ("sto.b");
1084 addr += cpu.asregs.regs[a];
1085 wbat (scpu, opc, addr, cpu.asregs.regs[b]);
1086 pc += 2;
1088 break;
1089 case 0x38: /* ldo.s */
1091 unsigned int addr = EXTRACT_OFFSET(pc+2);
1092 int a = (inst >> 4) & 0xf;
1093 int b = inst & 0xf;
1095 MOXIE_TRACE_INSN ("ldo.s");
1096 addr += cpu.asregs.regs[b];
1097 cpu.asregs.regs[a] = rsat (scpu, opc, addr);
1098 pc += 2;
1100 break;
1101 case 0x39: /* sto.s */
1103 unsigned int addr = EXTRACT_OFFSET(pc+2);
1104 int a = (inst >> 4) & 0xf;
1105 int b = inst & 0xf;
1107 MOXIE_TRACE_INSN ("sto.s");
1108 addr += cpu.asregs.regs[a];
1109 wsat (scpu, opc, addr, cpu.asregs.regs[b]);
1110 pc += 2;
1112 break;
1113 default:
1114 opc = opcode;
1115 MOXIE_TRACE_INSN ("SIGILL1");
1116 sim_engine_halt (sd, scpu, NULL, pc, sim_stopped, SIM_SIGILL);
1117 break;
1121 cpu.asregs.insts++;
1122 pc += 2;
1123 cpu.asregs.regs[PC_REGNO] = pc;
1125 if (sim_events_tick (sd))
1126 sim_events_process (sd);
1128 } while (1);
1131 static int
1132 moxie_reg_store (SIM_CPU *scpu, int rn, unsigned char *memory, int length)
1134 if (rn < NUM_MOXIE_REGS && rn >= 0)
1136 if (length == 4)
1138 long ival;
1140 /* misalignment safe */
1141 ival = moxie_extract_unsigned_integer (memory, 4);
1142 cpu.asints[rn] = ival;
1145 return 4;
1147 else
1148 return 0;
1151 static int
1152 moxie_reg_fetch (SIM_CPU *scpu, int rn, unsigned char *memory, int length)
1154 if (rn < NUM_MOXIE_REGS && rn >= 0)
1156 if (length == 4)
1158 long ival = cpu.asints[rn];
1160 /* misalignment-safe */
1161 moxie_store_unsigned_integer (memory, 4, ival);
1164 return 4;
1166 else
1167 return 0;
1170 static sim_cia
1171 moxie_pc_get (sim_cpu *cpu)
1173 return cpu->registers[PCIDX];
1176 static void
1177 moxie_pc_set (sim_cpu *cpu, sim_cia pc)
1179 cpu->registers[PCIDX] = pc;
1182 static void
1183 free_state (SIM_DESC sd)
1185 if (STATE_MODULES (sd) != NULL)
1186 sim_module_uninstall (sd);
1187 sim_cpu_free_all (sd);
1188 sim_state_free (sd);
1191 SIM_DESC
1192 sim_open (SIM_OPEN_KIND kind, host_callback *cb,
1193 struct bfd *abfd, char * const *argv)
1195 int i;
1196 SIM_DESC sd = sim_state_alloc (kind, cb);
1197 SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
1199 /* The cpu data is kept in a separately allocated chunk of memory. */
1200 if (sim_cpu_alloc_all (sd, 1, /*cgen_cpu_max_extra_bytes ()*/0) != SIM_RC_OK)
1202 free_state (sd);
1203 return 0;
1206 STATE_WATCHPOINTS (sd)->pc = &cpu.asregs.regs[PC_REGNO];
1207 STATE_WATCHPOINTS (sd)->sizeof_pc = sizeof (word);
1209 if (sim_pre_argv_init (sd, argv[0]) != SIM_RC_OK)
1211 free_state (sd);
1212 return 0;
1215 /* The parser will print an error message for us, so we silently return. */
1216 if (sim_parse_args (sd, argv) != SIM_RC_OK)
1218 free_state (sd);
1219 return 0;
1222 sim_do_command(sd," memory region 0x00000000,0x4000000") ;
1223 sim_do_command(sd," memory region 0xE0000000,0x10000") ;
1225 /* Check for/establish the a reference program image. */
1226 if (sim_analyze_program (sd,
1227 (STATE_PROG_ARGV (sd) != NULL
1228 ? *STATE_PROG_ARGV (sd)
1229 : NULL), abfd) != SIM_RC_OK)
1231 free_state (sd);
1232 return 0;
1235 /* Configure/verify the target byte order and other runtime
1236 configuration options. */
1237 if (sim_config (sd) != SIM_RC_OK)
1239 sim_module_uninstall (sd);
1240 return 0;
1243 if (sim_post_argv_init (sd) != SIM_RC_OK)
1245 /* Uninstall the modules to avoid memory leaks,
1246 file descriptor leaks, etc. */
1247 sim_module_uninstall (sd);
1248 return 0;
1251 /* CPU specific initialization. */
1252 for (i = 0; i < MAX_NR_PROCESSORS; ++i)
1254 SIM_CPU *cpu = STATE_CPU (sd, i);
1256 CPU_REG_FETCH (cpu) = moxie_reg_fetch;
1257 CPU_REG_STORE (cpu) = moxie_reg_store;
1258 CPU_PC_FETCH (cpu) = moxie_pc_get;
1259 CPU_PC_STORE (cpu) = moxie_pc_set;
1261 set_initial_gprs (); /* Reset the GPR registers. */
1264 return sd;
1267 /* Load the device tree blob. */
1269 static void
1270 load_dtb (SIM_DESC sd, const char *filename)
1272 int size = 0;
1273 FILE *f = fopen (filename, "rb");
1274 char *buf;
1275 sim_cpu *scpu = STATE_CPU (sd, 0); /* FIXME */
1277 /* Don't warn as the sim works fine w/out a device tree. */
1278 if (f == NULL)
1279 return;
1280 fseek (f, 0, SEEK_END);
1281 size = ftell(f);
1282 fseek (f, 0, SEEK_SET);
1283 buf = alloca (size);
1284 if (size != fread (buf, 1, size, f))
1286 sim_io_eprintf (sd, "ERROR: error reading ``%s''.\n", filename);
1287 fclose (f);
1288 return;
1290 sim_core_write_buffer (sd, scpu, write_map, buf, 0xE0000000, size);
1291 cpu.asregs.sregs[9] = 0xE0000000;
1292 fclose (f);
1295 SIM_RC
1296 sim_create_inferior (SIM_DESC sd, struct bfd *prog_bfd,
1297 char * const *argv, char * const *env)
1299 char ** avp;
1300 int l, argc, i, tp;
1301 sim_cpu *scpu = STATE_CPU (sd, 0); /* FIXME */
1303 if (prog_bfd != NULL)
1304 cpu.asregs.regs[PC_REGNO] = bfd_get_start_address (prog_bfd);
1306 /* Copy args into target memory. */
1307 avp = argv;
1308 for (argc = 0; avp && *avp; avp++)
1309 argc++;
1311 /* Target memory looks like this:
1312 0x00000000 zero word
1313 0x00000004 argc word
1314 0x00000008 start of argv
1316 0x0000???? end of argv
1317 0x0000???? zero word
1318 0x0000???? start of data pointed to by argv */
1320 wlat (scpu, 0, 0, 0);
1321 wlat (scpu, 0, 4, argc);
1323 /* tp is the offset of our first argv data. */
1324 tp = 4 + 4 + argc * 4 + 4;
1326 for (i = 0; i < argc; i++)
1328 /* Set the argv value. */
1329 wlat (scpu, 0, 4 + 4 + i * 4, tp);
1331 /* Store the string. */
1332 sim_core_write_buffer (sd, scpu, write_map, argv[i],
1333 tp, strlen(argv[i])+1);
1334 tp += strlen (argv[i]) + 1;
1337 wlat (scpu, 0, 4 + 4 + i * 4, 0);
1339 load_dtb (sd, DTB);
1341 return SIM_RC_OK;