[binutils, ARM, 5/16] BF insns infrastructure with new global reloc R_ARM_THM_BF16
[binutils-gdb.git] / sim / moxie / interp.c
blobecea5b42f38f629ee98ce62a8ad574e8e431f2b5
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"
36 typedef int word;
37 typedef unsigned int uword;
39 /* Extract the signed 10-bit offset from a 16-bit branch
40 instruction. */
41 #define INST2OFFSET(o) ((((signed short)((o & ((1<<10)-1))<<6))>>6)<<1)
43 #define EXTRACT_WORD(addr) \
44 ((sim_core_read_aligned_1 (scpu, cia, read_map, addr) << 24) \
45 + (sim_core_read_aligned_1 (scpu, cia, read_map, addr+1) << 16) \
46 + (sim_core_read_aligned_1 (scpu, cia, read_map, addr+2) << 8) \
47 + (sim_core_read_aligned_1 (scpu, cia, read_map, addr+3)))
49 #define EXTRACT_OFFSET(addr) \
50 (unsigned int) \
51 (((signed short) \
52 ((sim_core_read_aligned_1 (scpu, cia, read_map, addr) << 8) \
53 + (sim_core_read_aligned_1 (scpu, cia, read_map, addr+1))) << 16) >> 16)
55 static unsigned long
56 moxie_extract_unsigned_integer (unsigned char *addr, int len)
58 unsigned long retval;
59 unsigned char * p;
60 unsigned char * startaddr = (unsigned char *)addr;
61 unsigned char * endaddr = startaddr + len;
63 if (len > (int) sizeof (unsigned long))
64 printf ("That operation is not available on integers of more than %zu bytes.",
65 sizeof (unsigned long));
67 /* Start at the most significant end of the integer, and work towards
68 the least significant. */
69 retval = 0;
71 for (p = endaddr; p > startaddr;)
72 retval = (retval << 8) | * -- p;
74 return retval;
77 static void
78 moxie_store_unsigned_integer (unsigned char *addr, int len, unsigned long val)
80 unsigned char * p;
81 unsigned char * startaddr = (unsigned char *)addr;
82 unsigned char * endaddr = startaddr + len;
84 for (p = endaddr; p > startaddr;)
86 * -- p = val & 0xff;
87 val >>= 8;
91 /* moxie register names. */
92 static const char *reg_names[16] =
93 { "$fp", "$sp", "$r0", "$r1", "$r2", "$r3", "$r4", "$r5",
94 "$r6", "$r7", "$r8", "$r9", "$r10", "$r11", "$r12", "$r13" };
96 /* The machine state.
98 This state is maintained in host byte order. The fetch/store
99 register functions must translate between host byte order and the
100 target processor byte order. Keeping this data in target byte
101 order simplifies the register read/write functions. Keeping this
102 data in native order improves the performance of the simulator.
103 Simulation speed is deemed more important. */
105 #define NUM_MOXIE_REGS 17 /* Including PC */
106 #define NUM_MOXIE_SREGS 256 /* The special registers */
107 #define PC_REGNO 16
109 /* The ordering of the moxie_regset structure is matched in the
110 gdb/config/moxie/tm-moxie.h file in the REGISTER_NAMES macro. */
111 /* TODO: This should be moved to sim-main.h:_sim_cpu. */
112 struct moxie_regset
114 word regs[NUM_MOXIE_REGS + 1]; /* primary registers */
115 word sregs[256]; /* special registers */
116 word cc; /* the condition code reg */
117 unsigned long long insts; /* instruction counter */
120 #define CC_GT 1<<0
121 #define CC_LT 1<<1
122 #define CC_EQ 1<<2
123 #define CC_GTU 1<<3
124 #define CC_LTU 1<<4
126 /* TODO: This should be moved to sim-main.h:_sim_cpu. */
127 union
129 struct moxie_regset asregs;
130 word asints [1]; /* but accessed larger... */
131 } cpu;
133 static void
134 set_initial_gprs (void)
136 int i;
137 long space;
139 /* Set up machine just out of reset. */
140 cpu.asregs.regs[PC_REGNO] = 0;
142 /* Clean out the register contents. */
143 for (i = 0; i < NUM_MOXIE_REGS; i++)
144 cpu.asregs.regs[i] = 0;
145 for (i = 0; i < NUM_MOXIE_SREGS; i++)
146 cpu.asregs.sregs[i] = 0;
149 /* Write a 1 byte value to memory. */
151 static INLINE void
152 wbat (sim_cpu *scpu, word pc, word x, word v)
154 address_word cia = CPU_PC_GET (scpu);
156 sim_core_write_aligned_1 (scpu, cia, write_map, x, v);
159 /* Write a 2 byte value to memory. */
161 static INLINE void
162 wsat (sim_cpu *scpu, word pc, word x, word v)
164 address_word cia = CPU_PC_GET (scpu);
166 sim_core_write_aligned_2 (scpu, cia, write_map, x, v);
169 /* Write a 4 byte value to memory. */
171 static INLINE void
172 wlat (sim_cpu *scpu, word pc, word x, word v)
174 address_word cia = CPU_PC_GET (scpu);
176 sim_core_write_aligned_4 (scpu, cia, write_map, x, v);
179 /* Read 2 bytes from memory. */
181 static INLINE int
182 rsat (sim_cpu *scpu, word pc, word x)
184 address_word cia = CPU_PC_GET (scpu);
186 return (sim_core_read_aligned_2 (scpu, cia, read_map, x));
189 /* Read 1 byte from memory. */
191 static INLINE int
192 rbat (sim_cpu *scpu, word pc, word x)
194 address_word cia = CPU_PC_GET (scpu);
196 return (sim_core_read_aligned_1 (scpu, cia, read_map, x));
199 /* Read 4 bytes from memory. */
201 static INLINE int
202 rlat (sim_cpu *scpu, word pc, word x)
204 address_word cia = CPU_PC_GET (scpu);
206 return (sim_core_read_aligned_4 (scpu, cia, read_map, x));
209 #define CHECK_FLAG(T,H) if (tflags & T) { hflags |= H; tflags ^= T; }
211 static unsigned int
212 convert_target_flags (unsigned int tflags)
214 unsigned int hflags = 0x0;
216 CHECK_FLAG(0x0001, O_WRONLY);
217 CHECK_FLAG(0x0002, O_RDWR);
218 CHECK_FLAG(0x0008, O_APPEND);
219 CHECK_FLAG(0x0200, O_CREAT);
220 CHECK_FLAG(0x0400, O_TRUNC);
221 CHECK_FLAG(0x0800, O_EXCL);
222 CHECK_FLAG(0x2000, O_SYNC);
224 if (tflags != 0x0)
225 fprintf (stderr,
226 "Simulator Error: problem converting target open flags for host. 0x%x\n",
227 tflags);
229 return hflags;
232 /* TODO: Split this up into finger trace levels than just insn. */
233 #define MOXIE_TRACE_INSN(str) \
234 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", \
235 opc, str, cpu.asregs.regs[0], cpu.asregs.regs[1], \
236 cpu.asregs.regs[2], cpu.asregs.regs[3], cpu.asregs.regs[4], \
237 cpu.asregs.regs[5], cpu.asregs.regs[6], cpu.asregs.regs[7], \
238 cpu.asregs.regs[8], cpu.asregs.regs[9], cpu.asregs.regs[10], \
239 cpu.asregs.regs[11], cpu.asregs.regs[12], cpu.asregs.regs[13], \
240 cpu.asregs.regs[14], cpu.asregs.regs[15])
242 void
243 sim_engine_run (SIM_DESC sd,
244 int next_cpu_nr, /* ignore */
245 int nr_cpus, /* ignore */
246 int siggnal) /* ignore */
248 word pc, opc;
249 unsigned short inst;
250 sim_cpu *scpu = STATE_CPU (sd, 0); /* FIXME */
251 address_word cia = CPU_PC_GET (scpu);
253 pc = cpu.asregs.regs[PC_REGNO];
255 /* Run instructions here. */
258 opc = pc;
260 /* Fetch the instruction at pc. */
261 inst = (sim_core_read_aligned_1 (scpu, cia, read_map, pc) << 8)
262 + sim_core_read_aligned_1 (scpu, cia, read_map, pc+1);
264 /* Decode instruction. */
265 if (inst & (1 << 15))
267 if (inst & (1 << 14))
269 /* This is a Form 3 instruction. */
270 int opcode = (inst >> 10 & 0xf);
272 switch (opcode)
274 case 0x00: /* beq */
276 MOXIE_TRACE_INSN ("beq");
277 if (cpu.asregs.cc & CC_EQ)
278 pc += INST2OFFSET(inst);
280 break;
281 case 0x01: /* bne */
283 MOXIE_TRACE_INSN ("bne");
284 if (! (cpu.asregs.cc & CC_EQ))
285 pc += INST2OFFSET(inst);
287 break;
288 case 0x02: /* blt */
290 MOXIE_TRACE_INSN ("blt");
291 if (cpu.asregs.cc & CC_LT)
292 pc += INST2OFFSET(inst);
293 } break;
294 case 0x03: /* bgt */
296 MOXIE_TRACE_INSN ("bgt");
297 if (cpu.asregs.cc & CC_GT)
298 pc += INST2OFFSET(inst);
300 break;
301 case 0x04: /* bltu */
303 MOXIE_TRACE_INSN ("bltu");
304 if (cpu.asregs.cc & CC_LTU)
305 pc += INST2OFFSET(inst);
307 break;
308 case 0x05: /* bgtu */
310 MOXIE_TRACE_INSN ("bgtu");
311 if (cpu.asregs.cc & CC_GTU)
312 pc += INST2OFFSET(inst);
314 break;
315 case 0x06: /* bge */
317 MOXIE_TRACE_INSN ("bge");
318 if (cpu.asregs.cc & (CC_GT | CC_EQ))
319 pc += INST2OFFSET(inst);
321 break;
322 case 0x07: /* ble */
324 MOXIE_TRACE_INSN ("ble");
325 if (cpu.asregs.cc & (CC_LT | CC_EQ))
326 pc += INST2OFFSET(inst);
328 break;
329 case 0x08: /* bgeu */
331 MOXIE_TRACE_INSN ("bgeu");
332 if (cpu.asregs.cc & (CC_GTU | CC_EQ))
333 pc += INST2OFFSET(inst);
335 break;
336 case 0x09: /* bleu */
338 MOXIE_TRACE_INSN ("bleu");
339 if (cpu.asregs.cc & (CC_LTU | CC_EQ))
340 pc += INST2OFFSET(inst);
342 break;
343 default:
345 MOXIE_TRACE_INSN ("SIGILL3");
346 sim_engine_halt (sd, scpu, NULL, pc, sim_stopped, SIM_SIGILL);
347 break;
351 else
353 /* This is a Form 2 instruction. */
354 int opcode = (inst >> 12 & 0x3);
355 switch (opcode)
357 case 0x00: /* inc */
359 int a = (inst >> 8) & 0xf;
360 unsigned av = cpu.asregs.regs[a];
361 unsigned v = (inst & 0xff);
363 MOXIE_TRACE_INSN ("inc");
364 cpu.asregs.regs[a] = av + v;
366 break;
367 case 0x01: /* dec */
369 int a = (inst >> 8) & 0xf;
370 unsigned av = cpu.asregs.regs[a];
371 unsigned v = (inst & 0xff);
373 MOXIE_TRACE_INSN ("dec");
374 cpu.asregs.regs[a] = av - v;
376 break;
377 case 0x02: /* gsr */
379 int a = (inst >> 8) & 0xf;
380 unsigned v = (inst & 0xff);
382 MOXIE_TRACE_INSN ("gsr");
383 cpu.asregs.regs[a] = cpu.asregs.sregs[v];
385 break;
386 case 0x03: /* ssr */
388 int a = (inst >> 8) & 0xf;
389 unsigned v = (inst & 0xff);
391 MOXIE_TRACE_INSN ("ssr");
392 cpu.asregs.sregs[v] = cpu.asregs.regs[a];
394 break;
395 default:
396 MOXIE_TRACE_INSN ("SIGILL2");
397 sim_engine_halt (sd, scpu, NULL, pc, sim_stopped, SIM_SIGILL);
398 break;
402 else
404 /* This is a Form 1 instruction. */
405 int opcode = inst >> 8;
406 switch (opcode)
408 case 0x00: /* bad */
409 opc = opcode;
410 MOXIE_TRACE_INSN ("SIGILL0");
411 sim_engine_halt (sd, scpu, NULL, pc, sim_stopped, SIM_SIGILL);
412 break;
413 case 0x01: /* ldi.l (immediate) */
415 int reg = (inst >> 4) & 0xf;
416 unsigned int val = EXTRACT_WORD(pc+2);
418 MOXIE_TRACE_INSN ("ldi.l");
419 cpu.asregs.regs[reg] = val;
420 pc += 4;
422 break;
423 case 0x02: /* mov (register-to-register) */
425 int dest = (inst >> 4) & 0xf;
426 int src = (inst ) & 0xf;
428 MOXIE_TRACE_INSN ("mov");
429 cpu.asregs.regs[dest] = cpu.asregs.regs[src];
431 break;
432 case 0x03: /* jsra */
434 unsigned int fn = EXTRACT_WORD(pc+2);
435 unsigned int sp = cpu.asregs.regs[1];
437 MOXIE_TRACE_INSN ("jsra");
438 /* Save a slot for the static chain. */
439 sp -= 4;
441 /* Push the return address. */
442 sp -= 4;
443 wlat (scpu, opc, sp, pc + 6);
445 /* Push the current frame pointer. */
446 sp -= 4;
447 wlat (scpu, opc, sp, cpu.asregs.regs[0]);
449 /* Uncache the stack pointer and set the pc and $fp. */
450 cpu.asregs.regs[1] = sp;
451 cpu.asregs.regs[0] = sp;
452 pc = fn - 2;
454 break;
455 case 0x04: /* ret */
457 unsigned int sp = cpu.asregs.regs[0];
459 MOXIE_TRACE_INSN ("ret");
461 /* Pop the frame pointer. */
462 cpu.asregs.regs[0] = rlat (scpu, opc, sp);
463 sp += 4;
465 /* Pop the return address. */
466 pc = rlat (scpu, opc, sp) - 2;
467 sp += 4;
469 /* Skip over the static chain slot. */
470 sp += 4;
472 /* Uncache the stack pointer. */
473 cpu.asregs.regs[1] = sp;
475 break;
476 case 0x05: /* add.l */
478 int a = (inst >> 4) & 0xf;
479 int b = inst & 0xf;
480 unsigned av = cpu.asregs.regs[a];
481 unsigned bv = cpu.asregs.regs[b];
483 MOXIE_TRACE_INSN ("add.l");
484 cpu.asregs.regs[a] = av + bv;
486 break;
487 case 0x06: /* push */
489 int a = (inst >> 4) & 0xf;
490 int b = inst & 0xf;
491 int sp = cpu.asregs.regs[a] - 4;
493 MOXIE_TRACE_INSN ("push");
494 wlat (scpu, opc, sp, cpu.asregs.regs[b]);
495 cpu.asregs.regs[a] = sp;
497 break;
498 case 0x07: /* pop */
500 int a = (inst >> 4) & 0xf;
501 int b = inst & 0xf;
502 int sp = cpu.asregs.regs[a];
504 MOXIE_TRACE_INSN ("pop");
505 cpu.asregs.regs[b] = rlat (scpu, opc, sp);
506 cpu.asregs.regs[a] = sp + 4;
508 break;
509 case 0x08: /* lda.l */
511 int reg = (inst >> 4) & 0xf;
512 unsigned int addr = EXTRACT_WORD(pc+2);
514 MOXIE_TRACE_INSN ("lda.l");
515 cpu.asregs.regs[reg] = rlat (scpu, opc, addr);
516 pc += 4;
518 break;
519 case 0x09: /* sta.l */
521 int reg = (inst >> 4) & 0xf;
522 unsigned int addr = EXTRACT_WORD(pc+2);
524 MOXIE_TRACE_INSN ("sta.l");
525 wlat (scpu, opc, addr, cpu.asregs.regs[reg]);
526 pc += 4;
528 break;
529 case 0x0a: /* ld.l (register indirect) */
531 int src = inst & 0xf;
532 int dest = (inst >> 4) & 0xf;
533 int xv;
535 MOXIE_TRACE_INSN ("ld.l");
536 xv = cpu.asregs.regs[src];
537 cpu.asregs.regs[dest] = rlat (scpu, opc, xv);
539 break;
540 case 0x0b: /* st.l */
542 int dest = (inst >> 4) & 0xf;
543 int val = inst & 0xf;
545 MOXIE_TRACE_INSN ("st.l");
546 wlat (scpu, opc, cpu.asregs.regs[dest], cpu.asregs.regs[val]);
548 break;
549 case 0x0c: /* ldo.l */
551 unsigned int addr = EXTRACT_OFFSET(pc+2);
552 int a = (inst >> 4) & 0xf;
553 int b = inst & 0xf;
555 MOXIE_TRACE_INSN ("ldo.l");
556 addr += cpu.asregs.regs[b];
557 cpu.asregs.regs[a] = rlat (scpu, opc, addr);
558 pc += 2;
560 break;
561 case 0x0d: /* sto.l */
563 unsigned int addr = EXTRACT_OFFSET(pc+2);
564 int a = (inst >> 4) & 0xf;
565 int b = inst & 0xf;
567 MOXIE_TRACE_INSN ("sto.l");
568 addr += cpu.asregs.regs[a];
569 wlat (scpu, opc, addr, cpu.asregs.regs[b]);
570 pc += 2;
572 break;
573 case 0x0e: /* cmp */
575 int a = (inst >> 4) & 0xf;
576 int b = inst & 0xf;
577 int cc = 0;
578 int va = cpu.asregs.regs[a];
579 int vb = cpu.asregs.regs[b];
581 MOXIE_TRACE_INSN ("cmp");
582 if (va == vb)
583 cc = CC_EQ;
584 else
586 cc |= (va < vb ? CC_LT : 0);
587 cc |= (va > vb ? CC_GT : 0);
588 cc |= ((unsigned int) va < (unsigned int) vb ? CC_LTU : 0);
589 cc |= ((unsigned int) va > (unsigned int) vb ? CC_GTU : 0);
592 cpu.asregs.cc = cc;
594 break;
595 case 0x0f: /* nop */
596 break;
597 case 0x10: /* sex.b */
599 int a = (inst >> 4) & 0xf;
600 int b = inst & 0xf;
601 signed char bv = cpu.asregs.regs[b];
603 MOXIE_TRACE_INSN ("sex.b");
604 cpu.asregs.regs[a] = (int) bv;
606 break;
607 case 0x11: /* sex.s */
609 int a = (inst >> 4) & 0xf;
610 int b = inst & 0xf;
611 signed short bv = cpu.asregs.regs[b];
613 MOXIE_TRACE_INSN ("sex.s");
614 cpu.asregs.regs[a] = (int) bv;
616 break;
617 case 0x12: /* zex.b */
619 int a = (inst >> 4) & 0xf;
620 int b = inst & 0xf;
621 signed char bv = cpu.asregs.regs[b];
623 MOXIE_TRACE_INSN ("zex.b");
624 cpu.asregs.regs[a] = (int) bv & 0xff;
626 break;
627 case 0x13: /* zex.s */
629 int a = (inst >> 4) & 0xf;
630 int b = inst & 0xf;
631 signed short bv = cpu.asregs.regs[b];
633 MOXIE_TRACE_INSN ("zex.s");
634 cpu.asregs.regs[a] = (int) bv & 0xffff;
636 break;
637 case 0x14: /* umul.x */
639 int a = (inst >> 4) & 0xf;
640 int b = inst & 0xf;
641 unsigned av = cpu.asregs.regs[a];
642 unsigned bv = cpu.asregs.regs[b];
643 unsigned long long r =
644 (unsigned long long) av * (unsigned long long) bv;
646 MOXIE_TRACE_INSN ("umul.x");
647 cpu.asregs.regs[a] = r >> 32;
649 break;
650 case 0x15: /* mul.x */
652 int a = (inst >> 4) & 0xf;
653 int b = inst & 0xf;
654 unsigned av = cpu.asregs.regs[a];
655 unsigned bv = cpu.asregs.regs[b];
656 signed long long r =
657 (signed long long) av * (signed long long) bv;
659 MOXIE_TRACE_INSN ("mul.x");
660 cpu.asregs.regs[a] = r >> 32;
662 break;
663 case 0x16: /* bad */
664 case 0x17: /* bad */
665 case 0x18: /* bad */
667 opc = opcode;
668 MOXIE_TRACE_INSN ("SIGILL0");
669 sim_engine_halt (sd, scpu, NULL, pc, sim_stopped, SIM_SIGILL);
670 break;
672 case 0x19: /* jsr */
674 unsigned int fn = cpu.asregs.regs[(inst >> 4) & 0xf];
675 unsigned int sp = cpu.asregs.regs[1];
677 MOXIE_TRACE_INSN ("jsr");
679 /* Save a slot for the static chain. */
680 sp -= 4;
682 /* Push the return address. */
683 sp -= 4;
684 wlat (scpu, opc, sp, pc + 2);
686 /* Push the current frame pointer. */
687 sp -= 4;
688 wlat (scpu, opc, sp, cpu.asregs.regs[0]);
690 /* Uncache the stack pointer and set the fp & pc. */
691 cpu.asregs.regs[1] = sp;
692 cpu.asregs.regs[0] = sp;
693 pc = fn - 2;
695 break;
696 case 0x1a: /* jmpa */
698 unsigned int tgt = EXTRACT_WORD(pc+2);
700 MOXIE_TRACE_INSN ("jmpa");
701 pc = tgt - 2;
703 break;
704 case 0x1b: /* ldi.b (immediate) */
706 int reg = (inst >> 4) & 0xf;
707 unsigned int val = EXTRACT_WORD(pc+2);
709 MOXIE_TRACE_INSN ("ldi.b");
710 cpu.asregs.regs[reg] = val;
711 pc += 4;
713 break;
714 case 0x1c: /* ld.b (register indirect) */
716 int src = inst & 0xf;
717 int dest = (inst >> 4) & 0xf;
718 int xv;
720 MOXIE_TRACE_INSN ("ld.b");
721 xv = cpu.asregs.regs[src];
722 cpu.asregs.regs[dest] = rbat (scpu, opc, xv);
724 break;
725 case 0x1d: /* lda.b */
727 int reg = (inst >> 4) & 0xf;
728 unsigned int addr = EXTRACT_WORD(pc+2);
730 MOXIE_TRACE_INSN ("lda.b");
731 cpu.asregs.regs[reg] = rbat (scpu, opc, addr);
732 pc += 4;
734 break;
735 case 0x1e: /* st.b */
737 int dest = (inst >> 4) & 0xf;
738 int val = inst & 0xf;
740 MOXIE_TRACE_INSN ("st.b");
741 wbat (scpu, opc, cpu.asregs.regs[dest], cpu.asregs.regs[val]);
743 break;
744 case 0x1f: /* sta.b */
746 int reg = (inst >> 4) & 0xf;
747 unsigned int addr = EXTRACT_WORD(pc+2);
749 MOXIE_TRACE_INSN ("sta.b");
750 wbat (scpu, opc, addr, cpu.asregs.regs[reg]);
751 pc += 4;
753 break;
754 case 0x20: /* ldi.s (immediate) */
756 int reg = (inst >> 4) & 0xf;
758 unsigned int val = EXTRACT_WORD(pc+2);
760 MOXIE_TRACE_INSN ("ldi.s");
761 cpu.asregs.regs[reg] = val;
762 pc += 4;
764 break;
765 case 0x21: /* ld.s (register indirect) */
767 int src = inst & 0xf;
768 int dest = (inst >> 4) & 0xf;
769 int xv;
771 MOXIE_TRACE_INSN ("ld.s");
772 xv = cpu.asregs.regs[src];
773 cpu.asregs.regs[dest] = rsat (scpu, opc, xv);
775 break;
776 case 0x22: /* lda.s */
778 int reg = (inst >> 4) & 0xf;
779 unsigned int addr = EXTRACT_WORD(pc+2);
781 MOXIE_TRACE_INSN ("lda.s");
782 cpu.asregs.regs[reg] = rsat (scpu, opc, addr);
783 pc += 4;
785 break;
786 case 0x23: /* st.s */
788 int dest = (inst >> 4) & 0xf;
789 int val = inst & 0xf;
791 MOXIE_TRACE_INSN ("st.s");
792 wsat (scpu, opc, cpu.asregs.regs[dest], cpu.asregs.regs[val]);
794 break;
795 case 0x24: /* sta.s */
797 int reg = (inst >> 4) & 0xf;
798 unsigned int addr = EXTRACT_WORD(pc+2);
800 MOXIE_TRACE_INSN ("sta.s");
801 wsat (scpu, opc, addr, cpu.asregs.regs[reg]);
802 pc += 4;
804 break;
805 case 0x25: /* jmp */
807 int reg = (inst >> 4) & 0xf;
809 MOXIE_TRACE_INSN ("jmp");
810 pc = cpu.asregs.regs[reg] - 2;
812 break;
813 case 0x26: /* and */
815 int a = (inst >> 4) & 0xf;
816 int b = inst & 0xf;
817 int av, bv;
819 MOXIE_TRACE_INSN ("and");
820 av = cpu.asregs.regs[a];
821 bv = cpu.asregs.regs[b];
822 cpu.asregs.regs[a] = av & bv;
824 break;
825 case 0x27: /* lshr */
827 int a = (inst >> 4) & 0xf;
828 int b = inst & 0xf;
829 int av = cpu.asregs.regs[a];
830 int bv = cpu.asregs.regs[b];
832 MOXIE_TRACE_INSN ("lshr");
833 cpu.asregs.regs[a] = (unsigned) ((unsigned) av >> bv);
835 break;
836 case 0x28: /* ashl */
838 int a = (inst >> 4) & 0xf;
839 int b = inst & 0xf;
840 int av = cpu.asregs.regs[a];
841 int bv = cpu.asregs.regs[b];
843 MOXIE_TRACE_INSN ("ashl");
844 cpu.asregs.regs[a] = av << bv;
846 break;
847 case 0x29: /* sub.l */
849 int a = (inst >> 4) & 0xf;
850 int b = inst & 0xf;
851 unsigned av = cpu.asregs.regs[a];
852 unsigned bv = cpu.asregs.regs[b];
854 MOXIE_TRACE_INSN ("sub.l");
855 cpu.asregs.regs[a] = av - bv;
857 break;
858 case 0x2a: /* neg */
860 int a = (inst >> 4) & 0xf;
861 int b = inst & 0xf;
862 int bv = cpu.asregs.regs[b];
864 MOXIE_TRACE_INSN ("neg");
865 cpu.asregs.regs[a] = - bv;
867 break;
868 case 0x2b: /* or */
870 int a = (inst >> 4) & 0xf;
871 int b = inst & 0xf;
872 int av, bv;
874 MOXIE_TRACE_INSN ("or");
875 av = cpu.asregs.regs[a];
876 bv = cpu.asregs.regs[b];
877 cpu.asregs.regs[a] = av | bv;
879 break;
880 case 0x2c: /* not */
882 int a = (inst >> 4) & 0xf;
883 int b = inst & 0xf;
884 int bv = cpu.asregs.regs[b];
886 MOXIE_TRACE_INSN ("not");
887 cpu.asregs.regs[a] = 0xffffffff ^ bv;
889 break;
890 case 0x2d: /* ashr */
892 int a = (inst >> 4) & 0xf;
893 int b = inst & 0xf;
894 int av = cpu.asregs.regs[a];
895 int bv = cpu.asregs.regs[b];
897 MOXIE_TRACE_INSN ("ashr");
898 cpu.asregs.regs[a] = av >> bv;
900 break;
901 case 0x2e: /* xor */
903 int a = (inst >> 4) & 0xf;
904 int b = inst & 0xf;
905 int av, bv;
907 MOXIE_TRACE_INSN ("xor");
908 av = cpu.asregs.regs[a];
909 bv = cpu.asregs.regs[b];
910 cpu.asregs.regs[a] = av ^ bv;
912 break;
913 case 0x2f: /* mul.l */
915 int a = (inst >> 4) & 0xf;
916 int b = inst & 0xf;
917 unsigned av = cpu.asregs.regs[a];
918 unsigned bv = cpu.asregs.regs[b];
920 MOXIE_TRACE_INSN ("mul.l");
921 cpu.asregs.regs[a] = av * bv;
923 break;
924 case 0x30: /* swi */
926 unsigned int inum = EXTRACT_WORD(pc+2);
928 MOXIE_TRACE_INSN ("swi");
929 /* Set the special registers appropriately. */
930 cpu.asregs.sregs[2] = 3; /* MOXIE_EX_SWI */
931 cpu.asregs.sregs[3] = inum;
932 switch (inum)
934 case 0x1: /* SYS_exit */
936 sim_engine_halt (sd, scpu, NULL, pc, sim_exited,
937 cpu.asregs.regs[2]);
938 break;
940 case 0x2: /* SYS_open */
942 char fname[1024];
943 int mode = (int) convert_target_flags ((unsigned) cpu.asregs.regs[3]);
944 int perm = (int) cpu.asregs.regs[4];
945 int fd = open (fname, mode, perm);
946 sim_core_read_buffer (sd, scpu, read_map, fname,
947 cpu.asregs.regs[2], 1024);
948 /* FIXME - set errno */
949 cpu.asregs.regs[2] = fd;
950 break;
952 case 0x4: /* SYS_read */
954 int fd = cpu.asregs.regs[2];
955 unsigned len = (unsigned) cpu.asregs.regs[4];
956 char *buf = malloc (len);
957 cpu.asregs.regs[2] = read (fd, buf, len);
958 sim_core_write_buffer (sd, scpu, write_map, buf,
959 cpu.asregs.regs[3], len);
960 free (buf);
961 break;
963 case 0x5: /* SYS_write */
965 char *str;
966 /* String length is at 0x12($fp) */
967 unsigned count, len = (unsigned) cpu.asregs.regs[4];
968 str = malloc (len);
969 sim_core_read_buffer (sd, scpu, read_map, str,
970 cpu.asregs.regs[3], len);
971 count = write (cpu.asregs.regs[2], str, len);
972 free (str);
973 cpu.asregs.regs[2] = count;
974 break;
976 case 0xffffffff: /* Linux System Call */
978 unsigned int handler = cpu.asregs.sregs[1];
979 unsigned int sp = cpu.asregs.regs[1];
981 /* Save a slot for the static chain. */
982 sp -= 4;
984 /* Push the return address. */
985 sp -= 4;
986 wlat (scpu, opc, sp, pc + 6);
988 /* Push the current frame pointer. */
989 sp -= 4;
990 wlat (scpu, opc, sp, cpu.asregs.regs[0]);
992 /* Uncache the stack pointer and set the fp & pc. */
993 cpu.asregs.regs[1] = sp;
994 cpu.asregs.regs[0] = sp;
995 pc = handler - 6;
997 default:
998 break;
1000 pc += 4;
1002 break;
1003 case 0x31: /* div.l */
1005 int a = (inst >> 4) & 0xf;
1006 int b = inst & 0xf;
1007 int av = cpu.asregs.regs[a];
1008 int bv = cpu.asregs.regs[b];
1010 MOXIE_TRACE_INSN ("div.l");
1011 cpu.asregs.regs[a] = av / bv;
1013 break;
1014 case 0x32: /* udiv.l */
1016 int a = (inst >> 4) & 0xf;
1017 int b = inst & 0xf;
1018 unsigned int av = cpu.asregs.regs[a];
1019 unsigned int bv = cpu.asregs.regs[b];
1021 MOXIE_TRACE_INSN ("udiv.l");
1022 cpu.asregs.regs[a] = (av / bv);
1024 break;
1025 case 0x33: /* mod.l */
1027 int a = (inst >> 4) & 0xf;
1028 int b = inst & 0xf;
1029 int av = cpu.asregs.regs[a];
1030 int bv = cpu.asregs.regs[b];
1032 MOXIE_TRACE_INSN ("mod.l");
1033 cpu.asregs.regs[a] = av % bv;
1035 break;
1036 case 0x34: /* umod.l */
1038 int a = (inst >> 4) & 0xf;
1039 int b = inst & 0xf;
1040 unsigned int av = cpu.asregs.regs[a];
1041 unsigned int bv = cpu.asregs.regs[b];
1043 MOXIE_TRACE_INSN ("umod.l");
1044 cpu.asregs.regs[a] = (av % bv);
1046 break;
1047 case 0x35: /* brk */
1048 MOXIE_TRACE_INSN ("brk");
1049 sim_engine_halt (sd, scpu, NULL, pc, sim_stopped, SIM_SIGTRAP);
1050 pc -= 2; /* Adjust pc */
1051 break;
1052 case 0x36: /* ldo.b */
1054 unsigned int addr = EXTRACT_OFFSET(pc+2);
1055 int a = (inst >> 4) & 0xf;
1056 int b = inst & 0xf;
1058 MOXIE_TRACE_INSN ("ldo.b");
1059 addr += cpu.asregs.regs[b];
1060 cpu.asregs.regs[a] = rbat (scpu, opc, addr);
1061 pc += 2;
1063 break;
1064 case 0x37: /* sto.b */
1066 unsigned int addr = EXTRACT_OFFSET(pc+2);
1067 int a = (inst >> 4) & 0xf;
1068 int b = inst & 0xf;
1070 MOXIE_TRACE_INSN ("sto.b");
1071 addr += cpu.asregs.regs[a];
1072 wbat (scpu, opc, addr, cpu.asregs.regs[b]);
1073 pc += 2;
1075 break;
1076 case 0x38: /* ldo.s */
1078 unsigned int addr = EXTRACT_OFFSET(pc+2);
1079 int a = (inst >> 4) & 0xf;
1080 int b = inst & 0xf;
1082 MOXIE_TRACE_INSN ("ldo.s");
1083 addr += cpu.asregs.regs[b];
1084 cpu.asregs.regs[a] = rsat (scpu, opc, addr);
1085 pc += 2;
1087 break;
1088 case 0x39: /* sto.s */
1090 unsigned int addr = EXTRACT_OFFSET(pc+2);
1091 int a = (inst >> 4) & 0xf;
1092 int b = inst & 0xf;
1094 MOXIE_TRACE_INSN ("sto.s");
1095 addr += cpu.asregs.regs[a];
1096 wsat (scpu, opc, addr, cpu.asregs.regs[b]);
1097 pc += 2;
1099 break;
1100 default:
1101 opc = opcode;
1102 MOXIE_TRACE_INSN ("SIGILL1");
1103 sim_engine_halt (sd, scpu, NULL, pc, sim_stopped, SIM_SIGILL);
1104 break;
1108 cpu.asregs.insts++;
1109 pc += 2;
1110 cpu.asregs.regs[PC_REGNO] = pc;
1112 if (sim_events_tick (sd))
1113 sim_events_process (sd);
1115 } while (1);
1118 static int
1119 moxie_reg_store (SIM_CPU *scpu, int rn, unsigned char *memory, int length)
1121 if (rn < NUM_MOXIE_REGS && rn >= 0)
1123 if (length == 4)
1125 long ival;
1127 /* misalignment safe */
1128 ival = moxie_extract_unsigned_integer (memory, 4);
1129 cpu.asints[rn] = ival;
1132 return 4;
1134 else
1135 return 0;
1138 static int
1139 moxie_reg_fetch (SIM_CPU *scpu, int rn, unsigned char *memory, int length)
1141 if (rn < NUM_MOXIE_REGS && rn >= 0)
1143 if (length == 4)
1145 long ival = cpu.asints[rn];
1147 /* misalignment-safe */
1148 moxie_store_unsigned_integer (memory, 4, ival);
1151 return 4;
1153 else
1154 return 0;
1157 static sim_cia
1158 moxie_pc_get (sim_cpu *cpu)
1160 return cpu->registers[PCIDX];
1163 static void
1164 moxie_pc_set (sim_cpu *cpu, sim_cia pc)
1166 cpu->registers[PCIDX] = pc;
1169 static void
1170 free_state (SIM_DESC sd)
1172 if (STATE_MODULES (sd) != NULL)
1173 sim_module_uninstall (sd);
1174 sim_cpu_free_all (sd);
1175 sim_state_free (sd);
1178 SIM_DESC
1179 sim_open (SIM_OPEN_KIND kind, host_callback *cb,
1180 struct bfd *abfd, char * const *argv)
1182 int i;
1183 SIM_DESC sd = sim_state_alloc (kind, cb);
1184 SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
1186 /* The cpu data is kept in a separately allocated chunk of memory. */
1187 if (sim_cpu_alloc_all (sd, 1, /*cgen_cpu_max_extra_bytes ()*/0) != SIM_RC_OK)
1189 free_state (sd);
1190 return 0;
1193 STATE_WATCHPOINTS (sd)->pc = &cpu.asregs.regs[PC_REGNO];
1194 STATE_WATCHPOINTS (sd)->sizeof_pc = sizeof (word);
1196 if (sim_pre_argv_init (sd, argv[0]) != SIM_RC_OK)
1198 free_state (sd);
1199 return 0;
1202 /* The parser will print an error message for us, so we silently return. */
1203 if (sim_parse_args (sd, argv) != SIM_RC_OK)
1205 free_state (sd);
1206 return 0;
1209 sim_do_command(sd," memory region 0x00000000,0x4000000") ;
1210 sim_do_command(sd," memory region 0xE0000000,0x10000") ;
1212 /* Check for/establish the a reference program image. */
1213 if (sim_analyze_program (sd,
1214 (STATE_PROG_ARGV (sd) != NULL
1215 ? *STATE_PROG_ARGV (sd)
1216 : NULL), abfd) != SIM_RC_OK)
1218 free_state (sd);
1219 return 0;
1222 /* Configure/verify the target byte order and other runtime
1223 configuration options. */
1224 if (sim_config (sd) != SIM_RC_OK)
1226 sim_module_uninstall (sd);
1227 return 0;
1230 if (sim_post_argv_init (sd) != SIM_RC_OK)
1232 /* Uninstall the modules to avoid memory leaks,
1233 file descriptor leaks, etc. */
1234 sim_module_uninstall (sd);
1235 return 0;
1238 /* CPU specific initialization. */
1239 for (i = 0; i < MAX_NR_PROCESSORS; ++i)
1241 SIM_CPU *cpu = STATE_CPU (sd, i);
1243 CPU_REG_FETCH (cpu) = moxie_reg_fetch;
1244 CPU_REG_STORE (cpu) = moxie_reg_store;
1245 CPU_PC_FETCH (cpu) = moxie_pc_get;
1246 CPU_PC_STORE (cpu) = moxie_pc_set;
1248 set_initial_gprs (); /* Reset the GPR registers. */
1251 return sd;
1254 /* Load the device tree blob. */
1256 static void
1257 load_dtb (SIM_DESC sd, const char *filename)
1259 int size = 0;
1260 FILE *f = fopen (filename, "rb");
1261 char *buf;
1262 sim_cpu *scpu = STATE_CPU (sd, 0); /* FIXME */
1264 /* Don't warn as the sim works fine w/out a device tree. */
1265 if (f == NULL)
1266 return;
1267 fseek (f, 0, SEEK_END);
1268 size = ftell(f);
1269 fseek (f, 0, SEEK_SET);
1270 buf = alloca (size);
1271 if (size != fread (buf, 1, size, f))
1273 sim_io_eprintf (sd, "ERROR: error reading ``%s''.\n", filename);
1274 fclose (f);
1275 return;
1277 sim_core_write_buffer (sd, scpu, write_map, buf, 0xE0000000, size);
1278 cpu.asregs.sregs[9] = 0xE0000000;
1279 fclose (f);
1282 SIM_RC
1283 sim_create_inferior (SIM_DESC sd, struct bfd *prog_bfd,
1284 char * const *argv, char * const *env)
1286 char ** avp;
1287 int l, argc, i, tp;
1288 sim_cpu *scpu = STATE_CPU (sd, 0); /* FIXME */
1290 if (prog_bfd != NULL)
1291 cpu.asregs.regs[PC_REGNO] = bfd_get_start_address (prog_bfd);
1293 /* Copy args into target memory. */
1294 avp = argv;
1295 for (argc = 0; avp && *avp; avp++)
1296 argc++;
1298 /* Target memory looks like this:
1299 0x00000000 zero word
1300 0x00000004 argc word
1301 0x00000008 start of argv
1303 0x0000???? end of argv
1304 0x0000???? zero word
1305 0x0000???? start of data pointed to by argv */
1307 wlat (scpu, 0, 0, 0);
1308 wlat (scpu, 0, 4, argc);
1310 /* tp is the offset of our first argv data. */
1311 tp = 4 + 4 + argc * 4 + 4;
1313 for (i = 0; i < argc; i++)
1315 /* Set the argv value. */
1316 wlat (scpu, 0, 4 + 4 + i * 4, tp);
1318 /* Store the string. */
1319 sim_core_write_buffer (sd, scpu, write_map, argv[i],
1320 tp, strlen(argv[i])+1);
1321 tp += strlen (argv[i]) + 1;
1324 wlat (scpu, 0, 4 + 4 + i * 4, 0);
1326 load_dtb (sd, DTB);
1328 return SIM_RC_OK;