Updated French translations for GOLD and LD
[binutils-gdb.git] / sim / moxie / interp.c
blob6f46f9c70c4fe1c450036bda309ab5c8fafaa90d
1 /* Simulator for the moxie processor
2 Copyright (C) 2008-2024 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 /* This must come before any other includes. */
21 #include "defs.h"
23 #include <fcntl.h>
24 #include <signal.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <sys/param.h>
28 #include <unistd.h>
29 #include "bfd.h"
30 #include "libiberty.h"
31 #include "sim/sim.h"
33 #include "sim-main.h"
34 #include "sim-base.h"
35 #include "sim-options.h"
36 #include "sim-io.h"
37 #include "sim-signal.h"
38 #include "target-newlib-syscall.h"
40 #include "moxie-sim.h"
42 /* Extract the signed 10-bit offset from a 16-bit branch
43 instruction. */
44 #define INST2OFFSET(o) ((((signed short)((o & ((1<<10)-1))<<6))>>6)<<1)
46 #define EXTRACT_WORD(addr) \
47 ((sim_core_read_aligned_1 (scpu, cia, read_map, addr) << 24) \
48 + (sim_core_read_aligned_1 (scpu, cia, read_map, addr+1) << 16) \
49 + (sim_core_read_aligned_1 (scpu, cia, read_map, addr+2) << 8) \
50 + (sim_core_read_aligned_1 (scpu, cia, read_map, addr+3)))
52 #define EXTRACT_OFFSET(addr) \
53 (unsigned int) \
54 (((signed short) \
55 ((sim_core_read_aligned_1 (scpu, cia, read_map, addr) << 8) \
56 + (sim_core_read_aligned_1 (scpu, cia, read_map, addr+1))) << 16) >> 16)
58 static unsigned long
59 moxie_extract_unsigned_integer (const unsigned char *addr, int len)
61 unsigned long retval;
62 unsigned char * p;
63 unsigned char * startaddr = (unsigned char *)addr;
64 unsigned char * endaddr = startaddr + len;
66 if (len > (int) sizeof (unsigned long))
67 printf ("That operation is not available on integers of more than %zu bytes.",
68 sizeof (unsigned long));
70 /* Start at the most significant end of the integer, and work towards
71 the least significant. */
72 retval = 0;
74 for (p = endaddr; p > startaddr;)
75 retval = (retval << 8) | * -- p;
77 return retval;
80 static void
81 moxie_store_unsigned_integer (unsigned char *addr, int len, unsigned long val)
83 unsigned char * p;
84 unsigned char * startaddr = (unsigned char *)addr;
85 unsigned char * endaddr = startaddr + len;
87 for (p = endaddr; p > startaddr;)
89 * -- p = val & 0xff;
90 val >>= 8;
94 /* The machine state.
96 This state is maintained in host byte order. The fetch/store
97 register functions must translate between host byte order and the
98 target processor byte order. Keeping this data in target byte
99 order simplifies the register read/write functions. Keeping this
100 data in native order improves the performance of the simulator.
101 Simulation speed is deemed more important. */
103 #define NUM_MOXIE_REGS 17 /* Including PC */
104 #define NUM_MOXIE_SREGS 256 /* The special registers */
105 #define PC_REGNO 16
107 /* The ordering of the moxie_regset structure is matched in the
108 gdb/config/moxie/tm-moxie.h file in the REGISTER_NAMES macro. */
109 /* TODO: This should be moved to sim-main.h:_sim_cpu. */
110 struct moxie_regset
112 int32_t regs[NUM_MOXIE_REGS + 1]; /* primary registers */
113 int32_t sregs[256]; /* special registers */
114 int32_t cc; /* the condition code reg */
115 unsigned long long insts; /* instruction counter */
118 #define CC_GT 1<<0
119 #define CC_LT 1<<1
120 #define CC_EQ 1<<2
121 #define CC_GTU 1<<3
122 #define CC_LTU 1<<4
124 /* TODO: This should be moved to sim-main.h:moxie_sim_cpu. */
125 union
127 struct moxie_regset asregs;
128 int32_t asints [1]; /* but accessed larger... */
129 } cpu;
131 static void
132 set_initial_gprs (void)
134 int i;
136 /* Set up machine just out of reset. */
137 cpu.asregs.regs[PC_REGNO] = 0;
139 /* Clean out the register contents. */
140 for (i = 0; i < NUM_MOXIE_REGS; i++)
141 cpu.asregs.regs[i] = 0;
142 for (i = 0; i < NUM_MOXIE_SREGS; i++)
143 cpu.asregs.sregs[i] = 0;
146 /* Write a 1 byte value to memory. */
148 static INLINE void
149 wbat (sim_cpu *scpu, int32_t pc, int32_t x, int32_t v)
151 address_word cia = CPU_PC_GET (scpu);
153 sim_core_write_aligned_1 (scpu, cia, write_map, x, v);
156 /* Write a 2 byte value to memory. */
158 static INLINE void
159 wsat (sim_cpu *scpu, int32_t pc, int32_t x, int32_t v)
161 address_word cia = CPU_PC_GET (scpu);
163 sim_core_write_aligned_2 (scpu, cia, write_map, x, v);
166 /* Write a 4 byte value to memory. */
168 static INLINE void
169 wlat (sim_cpu *scpu, int32_t pc, int32_t x, int32_t v)
171 address_word cia = CPU_PC_GET (scpu);
173 sim_core_write_aligned_4 (scpu, cia, write_map, x, v);
176 /* Read 2 bytes from memory. */
178 static INLINE int
179 rsat (sim_cpu *scpu, int32_t pc, int32_t x)
181 address_word cia = CPU_PC_GET (scpu);
183 return (sim_core_read_aligned_2 (scpu, cia, read_map, x));
186 /* Read 1 byte from memory. */
188 static INLINE int
189 rbat (sim_cpu *scpu, int32_t pc, int32_t x)
191 address_word cia = CPU_PC_GET (scpu);
193 return (sim_core_read_aligned_1 (scpu, cia, read_map, x));
196 /* Read 4 bytes from memory. */
198 static INLINE int
199 rlat (sim_cpu *scpu, int32_t pc, int32_t x)
201 address_word cia = CPU_PC_GET (scpu);
203 return (sim_core_read_aligned_4 (scpu, cia, read_map, x));
206 #define CHECK_FLAG(T,H) if (tflags & T) { hflags |= H; tflags ^= T; }
208 static unsigned int
209 convert_target_flags (unsigned int tflags)
211 unsigned int hflags = 0x0;
213 CHECK_FLAG(0x0001, O_WRONLY);
214 CHECK_FLAG(0x0002, O_RDWR);
215 CHECK_FLAG(0x0008, O_APPEND);
216 CHECK_FLAG(0x0200, O_CREAT);
217 CHECK_FLAG(0x0400, O_TRUNC);
218 CHECK_FLAG(0x0800, O_EXCL);
219 CHECK_FLAG(0x2000, O_SYNC);
221 if (tflags != 0x0)
222 fprintf (stderr,
223 "Simulator Error: problem converting target open flags for host. 0x%x\n",
224 tflags);
226 return hflags;
229 /* TODO: Split this up into finger trace levels than just insn. */
230 #define MOXIE_TRACE_INSN(str) \
231 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", \
232 opc, str, cpu.asregs.regs[0], cpu.asregs.regs[1], \
233 cpu.asregs.regs[2], cpu.asregs.regs[3], cpu.asregs.regs[4], \
234 cpu.asregs.regs[5], cpu.asregs.regs[6], cpu.asregs.regs[7], \
235 cpu.asregs.regs[8], cpu.asregs.regs[9], cpu.asregs.regs[10], \
236 cpu.asregs.regs[11], cpu.asregs.regs[12], cpu.asregs.regs[13], \
237 cpu.asregs.regs[14], cpu.asregs.regs[15])
239 void
240 sim_engine_run (SIM_DESC sd,
241 int next_cpu_nr, /* ignore */
242 int nr_cpus, /* ignore */
243 int siggnal) /* ignore */
245 int32_t pc, opc;
246 unsigned short inst;
247 sim_cpu *scpu = STATE_CPU (sd, 0); /* FIXME */
248 address_word cia = CPU_PC_GET (scpu);
250 pc = cpu.asregs.regs[PC_REGNO];
252 /* Run instructions here. */
255 opc = pc;
257 /* Fetch the instruction at pc. */
258 inst = (sim_core_read_aligned_1 (scpu, cia, read_map, pc) << 8)
259 + sim_core_read_aligned_1 (scpu, cia, read_map, pc+1);
261 /* Decode instruction. */
262 if (inst & (1 << 15))
264 if (inst & (1 << 14))
266 /* This is a Form 3 instruction. */
267 int opcode = (inst >> 10 & 0xf);
269 switch (opcode)
271 case 0x00: /* beq */
273 MOXIE_TRACE_INSN ("beq");
274 if (cpu.asregs.cc & CC_EQ)
275 pc += INST2OFFSET(inst);
277 break;
278 case 0x01: /* bne */
280 MOXIE_TRACE_INSN ("bne");
281 if (! (cpu.asregs.cc & CC_EQ))
282 pc += INST2OFFSET(inst);
284 break;
285 case 0x02: /* blt */
287 MOXIE_TRACE_INSN ("blt");
288 if (cpu.asregs.cc & CC_LT)
289 pc += INST2OFFSET(inst);
290 } break;
291 case 0x03: /* bgt */
293 MOXIE_TRACE_INSN ("bgt");
294 if (cpu.asregs.cc & CC_GT)
295 pc += INST2OFFSET(inst);
297 break;
298 case 0x04: /* bltu */
300 MOXIE_TRACE_INSN ("bltu");
301 if (cpu.asregs.cc & CC_LTU)
302 pc += INST2OFFSET(inst);
304 break;
305 case 0x05: /* bgtu */
307 MOXIE_TRACE_INSN ("bgtu");
308 if (cpu.asregs.cc & CC_GTU)
309 pc += INST2OFFSET(inst);
311 break;
312 case 0x06: /* bge */
314 MOXIE_TRACE_INSN ("bge");
315 if (cpu.asregs.cc & (CC_GT | CC_EQ))
316 pc += INST2OFFSET(inst);
318 break;
319 case 0x07: /* ble */
321 MOXIE_TRACE_INSN ("ble");
322 if (cpu.asregs.cc & (CC_LT | CC_EQ))
323 pc += INST2OFFSET(inst);
325 break;
326 case 0x08: /* bgeu */
328 MOXIE_TRACE_INSN ("bgeu");
329 if (cpu.asregs.cc & (CC_GTU | CC_EQ))
330 pc += INST2OFFSET(inst);
332 break;
333 case 0x09: /* bleu */
335 MOXIE_TRACE_INSN ("bleu");
336 if (cpu.asregs.cc & (CC_LTU | CC_EQ))
337 pc += INST2OFFSET(inst);
339 break;
340 default:
342 MOXIE_TRACE_INSN ("SIGILL3");
343 sim_engine_halt (sd, scpu, NULL, pc, sim_stopped, SIM_SIGILL);
344 break;
348 else
350 /* This is a Form 2 instruction. */
351 int opcode = (inst >> 12 & 0x3);
352 switch (opcode)
354 case 0x00: /* inc */
356 int a = (inst >> 8) & 0xf;
357 unsigned av = cpu.asregs.regs[a];
358 unsigned v = (inst & 0xff);
360 MOXIE_TRACE_INSN ("inc");
361 cpu.asregs.regs[a] = av + v;
363 break;
364 case 0x01: /* dec */
366 int a = (inst >> 8) & 0xf;
367 unsigned av = cpu.asregs.regs[a];
368 unsigned v = (inst & 0xff);
370 MOXIE_TRACE_INSN ("dec");
371 cpu.asregs.regs[a] = av - v;
373 break;
374 case 0x02: /* gsr */
376 int a = (inst >> 8) & 0xf;
377 unsigned v = (inst & 0xff);
379 MOXIE_TRACE_INSN ("gsr");
380 cpu.asregs.regs[a] = cpu.asregs.sregs[v];
382 break;
383 case 0x03: /* ssr */
385 int a = (inst >> 8) & 0xf;
386 unsigned v = (inst & 0xff);
388 MOXIE_TRACE_INSN ("ssr");
389 cpu.asregs.sregs[v] = cpu.asregs.regs[a];
391 break;
392 default:
393 MOXIE_TRACE_INSN ("SIGILL2");
394 sim_engine_halt (sd, scpu, NULL, pc, sim_stopped, SIM_SIGILL);
395 break;
399 else
401 /* This is a Form 1 instruction. */
402 int opcode = inst >> 8;
403 switch (opcode)
405 case 0x00: /* bad */
406 opc = opcode;
407 MOXIE_TRACE_INSN ("SIGILL0");
408 sim_engine_halt (sd, scpu, NULL, pc, sim_stopped, SIM_SIGILL);
409 break;
410 case 0x01: /* ldi.l (immediate) */
412 int reg = (inst >> 4) & 0xf;
413 unsigned int val = EXTRACT_WORD(pc+2);
415 MOXIE_TRACE_INSN ("ldi.l");
416 cpu.asregs.regs[reg] = val;
417 pc += 4;
419 break;
420 case 0x02: /* mov (register-to-register) */
422 int dest = (inst >> 4) & 0xf;
423 int src = (inst ) & 0xf;
425 MOXIE_TRACE_INSN ("mov");
426 cpu.asregs.regs[dest] = cpu.asregs.regs[src];
428 break;
429 case 0x03: /* jsra */
431 unsigned int fn = EXTRACT_WORD(pc+2);
432 unsigned int sp = cpu.asregs.regs[1];
434 MOXIE_TRACE_INSN ("jsra");
435 /* Save a slot for the static chain. */
436 sp -= 4;
438 /* Push the return address. */
439 sp -= 4;
440 wlat (scpu, opc, sp, pc + 6);
442 /* Push the current frame pointer. */
443 sp -= 4;
444 wlat (scpu, opc, sp, cpu.asregs.regs[0]);
446 /* Uncache the stack pointer and set the pc and $fp. */
447 cpu.asregs.regs[1] = sp;
448 cpu.asregs.regs[0] = sp;
449 pc = fn - 2;
451 break;
452 case 0x04: /* ret */
454 unsigned int sp = cpu.asregs.regs[0];
456 MOXIE_TRACE_INSN ("ret");
458 /* Pop the frame pointer. */
459 cpu.asregs.regs[0] = rlat (scpu, opc, sp);
460 sp += 4;
462 /* Pop the return address. */
463 pc = rlat (scpu, opc, sp) - 2;
464 sp += 4;
466 /* Skip over the static chain slot. */
467 sp += 4;
469 /* Uncache the stack pointer. */
470 cpu.asregs.regs[1] = sp;
472 break;
473 case 0x05: /* add.l */
475 int a = (inst >> 4) & 0xf;
476 int b = inst & 0xf;
477 unsigned av = cpu.asregs.regs[a];
478 unsigned bv = cpu.asregs.regs[b];
480 MOXIE_TRACE_INSN ("add.l");
481 cpu.asregs.regs[a] = av + bv;
483 break;
484 case 0x06: /* push */
486 int a = (inst >> 4) & 0xf;
487 int b = inst & 0xf;
488 int sp = cpu.asregs.regs[a] - 4;
490 MOXIE_TRACE_INSN ("push");
491 wlat (scpu, opc, sp, cpu.asregs.regs[b]);
492 cpu.asregs.regs[a] = sp;
494 break;
495 case 0x07: /* pop */
497 int a = (inst >> 4) & 0xf;
498 int b = inst & 0xf;
499 int sp = cpu.asregs.regs[a];
501 MOXIE_TRACE_INSN ("pop");
502 cpu.asregs.regs[b] = rlat (scpu, opc, sp);
503 cpu.asregs.regs[a] = sp + 4;
505 break;
506 case 0x08: /* lda.l */
508 int reg = (inst >> 4) & 0xf;
509 unsigned int addr = EXTRACT_WORD(pc+2);
511 MOXIE_TRACE_INSN ("lda.l");
512 cpu.asregs.regs[reg] = rlat (scpu, opc, addr);
513 pc += 4;
515 break;
516 case 0x09: /* sta.l */
518 int reg = (inst >> 4) & 0xf;
519 unsigned int addr = EXTRACT_WORD(pc+2);
521 MOXIE_TRACE_INSN ("sta.l");
522 wlat (scpu, opc, addr, cpu.asregs.regs[reg]);
523 pc += 4;
525 break;
526 case 0x0a: /* ld.l (register indirect) */
528 int src = inst & 0xf;
529 int dest = (inst >> 4) & 0xf;
530 int xv;
532 MOXIE_TRACE_INSN ("ld.l");
533 xv = cpu.asregs.regs[src];
534 cpu.asregs.regs[dest] = rlat (scpu, opc, xv);
536 break;
537 case 0x0b: /* st.l */
539 int dest = (inst >> 4) & 0xf;
540 int val = inst & 0xf;
542 MOXIE_TRACE_INSN ("st.l");
543 wlat (scpu, opc, cpu.asregs.regs[dest], cpu.asregs.regs[val]);
545 break;
546 case 0x0c: /* ldo.l */
548 unsigned int addr = EXTRACT_OFFSET(pc+2);
549 int a = (inst >> 4) & 0xf;
550 int b = inst & 0xf;
552 MOXIE_TRACE_INSN ("ldo.l");
553 addr += cpu.asregs.regs[b];
554 cpu.asregs.regs[a] = rlat (scpu, opc, addr);
555 pc += 2;
557 break;
558 case 0x0d: /* sto.l */
560 unsigned int addr = EXTRACT_OFFSET(pc+2);
561 int a = (inst >> 4) & 0xf;
562 int b = inst & 0xf;
564 MOXIE_TRACE_INSN ("sto.l");
565 addr += cpu.asregs.regs[a];
566 wlat (scpu, opc, addr, cpu.asregs.regs[b]);
567 pc += 2;
569 break;
570 case 0x0e: /* cmp */
572 int a = (inst >> 4) & 0xf;
573 int b = inst & 0xf;
574 int cc = 0;
575 int va = cpu.asregs.regs[a];
576 int vb = cpu.asregs.regs[b];
578 MOXIE_TRACE_INSN ("cmp");
579 if (va == vb)
580 cc = CC_EQ;
581 else
583 cc |= (va < vb ? CC_LT : 0);
584 cc |= (va > vb ? CC_GT : 0);
585 cc |= ((unsigned int) va < (unsigned int) vb ? CC_LTU : 0);
586 cc |= ((unsigned int) va > (unsigned int) vb ? CC_GTU : 0);
589 cpu.asregs.cc = cc;
591 break;
592 case 0x0f: /* nop */
593 break;
594 case 0x10: /* sex.b */
596 int a = (inst >> 4) & 0xf;
597 int b = inst & 0xf;
598 signed char bv = cpu.asregs.regs[b];
600 MOXIE_TRACE_INSN ("sex.b");
601 cpu.asregs.regs[a] = (int) bv;
603 break;
604 case 0x11: /* sex.s */
606 int a = (inst >> 4) & 0xf;
607 int b = inst & 0xf;
608 signed short bv = cpu.asregs.regs[b];
610 MOXIE_TRACE_INSN ("sex.s");
611 cpu.asregs.regs[a] = (int) bv;
613 break;
614 case 0x12: /* zex.b */
616 int a = (inst >> 4) & 0xf;
617 int b = inst & 0xf;
618 signed char bv = cpu.asregs.regs[b];
620 MOXIE_TRACE_INSN ("zex.b");
621 cpu.asregs.regs[a] = (int) bv & 0xff;
623 break;
624 case 0x13: /* zex.s */
626 int a = (inst >> 4) & 0xf;
627 int b = inst & 0xf;
628 signed short bv = cpu.asregs.regs[b];
630 MOXIE_TRACE_INSN ("zex.s");
631 cpu.asregs.regs[a] = (int) bv & 0xffff;
633 break;
634 case 0x14: /* umul.x */
636 int a = (inst >> 4) & 0xf;
637 int b = inst & 0xf;
638 unsigned av = cpu.asregs.regs[a];
639 unsigned bv = cpu.asregs.regs[b];
640 unsigned long long r =
641 (unsigned long long) av * (unsigned long long) bv;
643 MOXIE_TRACE_INSN ("umul.x");
644 cpu.asregs.regs[a] = r >> 32;
646 break;
647 case 0x15: /* mul.x */
649 int a = (inst >> 4) & 0xf;
650 int b = inst & 0xf;
651 unsigned av = cpu.asregs.regs[a];
652 unsigned bv = cpu.asregs.regs[b];
653 signed long long r =
654 (signed long long) av * (signed long long) bv;
656 MOXIE_TRACE_INSN ("mul.x");
657 cpu.asregs.regs[a] = r >> 32;
659 break;
660 case 0x16: /* bad */
661 case 0x17: /* bad */
662 case 0x18: /* bad */
664 opc = opcode;
665 MOXIE_TRACE_INSN ("SIGILL0");
666 sim_engine_halt (sd, scpu, NULL, pc, sim_stopped, SIM_SIGILL);
667 break;
669 case 0x19: /* jsr */
671 unsigned int fn = cpu.asregs.regs[(inst >> 4) & 0xf];
672 unsigned int sp = cpu.asregs.regs[1];
674 MOXIE_TRACE_INSN ("jsr");
676 /* Save a slot for the static chain. */
677 sp -= 4;
679 /* Push the return address. */
680 sp -= 4;
681 wlat (scpu, opc, sp, pc + 2);
683 /* Push the current frame pointer. */
684 sp -= 4;
685 wlat (scpu, opc, sp, cpu.asregs.regs[0]);
687 /* Uncache the stack pointer and set the fp & pc. */
688 cpu.asregs.regs[1] = sp;
689 cpu.asregs.regs[0] = sp;
690 pc = fn - 2;
692 break;
693 case 0x1a: /* jmpa */
695 unsigned int tgt = EXTRACT_WORD(pc+2);
697 MOXIE_TRACE_INSN ("jmpa");
698 pc = tgt - 2;
700 break;
701 case 0x1b: /* ldi.b (immediate) */
703 int reg = (inst >> 4) & 0xf;
704 unsigned int val = EXTRACT_WORD(pc+2);
706 MOXIE_TRACE_INSN ("ldi.b");
707 cpu.asregs.regs[reg] = val;
708 pc += 4;
710 break;
711 case 0x1c: /* ld.b (register indirect) */
713 int src = inst & 0xf;
714 int dest = (inst >> 4) & 0xf;
715 int xv;
717 MOXIE_TRACE_INSN ("ld.b");
718 xv = cpu.asregs.regs[src];
719 cpu.asregs.regs[dest] = rbat (scpu, opc, xv);
721 break;
722 case 0x1d: /* lda.b */
724 int reg = (inst >> 4) & 0xf;
725 unsigned int addr = EXTRACT_WORD(pc+2);
727 MOXIE_TRACE_INSN ("lda.b");
728 cpu.asregs.regs[reg] = rbat (scpu, opc, addr);
729 pc += 4;
731 break;
732 case 0x1e: /* st.b */
734 int dest = (inst >> 4) & 0xf;
735 int val = inst & 0xf;
737 MOXIE_TRACE_INSN ("st.b");
738 wbat (scpu, opc, cpu.asregs.regs[dest], cpu.asregs.regs[val]);
740 break;
741 case 0x1f: /* sta.b */
743 int reg = (inst >> 4) & 0xf;
744 unsigned int addr = EXTRACT_WORD(pc+2);
746 MOXIE_TRACE_INSN ("sta.b");
747 wbat (scpu, opc, addr, cpu.asregs.regs[reg]);
748 pc += 4;
750 break;
751 case 0x20: /* ldi.s (immediate) */
753 int reg = (inst >> 4) & 0xf;
755 unsigned int val = EXTRACT_WORD(pc+2);
757 MOXIE_TRACE_INSN ("ldi.s");
758 cpu.asregs.regs[reg] = val;
759 pc += 4;
761 break;
762 case 0x21: /* ld.s (register indirect) */
764 int src = inst & 0xf;
765 int dest = (inst >> 4) & 0xf;
766 int xv;
768 MOXIE_TRACE_INSN ("ld.s");
769 xv = cpu.asregs.regs[src];
770 cpu.asregs.regs[dest] = rsat (scpu, opc, xv);
772 break;
773 case 0x22: /* lda.s */
775 int reg = (inst >> 4) & 0xf;
776 unsigned int addr = EXTRACT_WORD(pc+2);
778 MOXIE_TRACE_INSN ("lda.s");
779 cpu.asregs.regs[reg] = rsat (scpu, opc, addr);
780 pc += 4;
782 break;
783 case 0x23: /* st.s */
785 int dest = (inst >> 4) & 0xf;
786 int val = inst & 0xf;
788 MOXIE_TRACE_INSN ("st.s");
789 wsat (scpu, opc, cpu.asregs.regs[dest], cpu.asregs.regs[val]);
791 break;
792 case 0x24: /* sta.s */
794 int reg = (inst >> 4) & 0xf;
795 unsigned int addr = EXTRACT_WORD(pc+2);
797 MOXIE_TRACE_INSN ("sta.s");
798 wsat (scpu, opc, addr, cpu.asregs.regs[reg]);
799 pc += 4;
801 break;
802 case 0x25: /* jmp */
804 int reg = (inst >> 4) & 0xf;
806 MOXIE_TRACE_INSN ("jmp");
807 pc = cpu.asregs.regs[reg] - 2;
809 break;
810 case 0x26: /* and */
812 int a = (inst >> 4) & 0xf;
813 int b = inst & 0xf;
814 int av, bv;
816 MOXIE_TRACE_INSN ("and");
817 av = cpu.asregs.regs[a];
818 bv = cpu.asregs.regs[b];
819 cpu.asregs.regs[a] = av & bv;
821 break;
822 case 0x27: /* lshr */
824 int a = (inst >> 4) & 0xf;
825 int b = inst & 0xf;
826 int av = cpu.asregs.regs[a];
827 int bv = cpu.asregs.regs[b];
829 MOXIE_TRACE_INSN ("lshr");
830 cpu.asregs.regs[a] = (unsigned) ((unsigned) av >> bv);
832 break;
833 case 0x28: /* ashl */
835 int a = (inst >> 4) & 0xf;
836 int b = inst & 0xf;
837 int av = cpu.asregs.regs[a];
838 int bv = cpu.asregs.regs[b];
840 MOXIE_TRACE_INSN ("ashl");
841 cpu.asregs.regs[a] = av << bv;
843 break;
844 case 0x29: /* sub.l */
846 int a = (inst >> 4) & 0xf;
847 int b = inst & 0xf;
848 unsigned av = cpu.asregs.regs[a];
849 unsigned bv = cpu.asregs.regs[b];
851 MOXIE_TRACE_INSN ("sub.l");
852 cpu.asregs.regs[a] = av - bv;
854 break;
855 case 0x2a: /* neg */
857 int a = (inst >> 4) & 0xf;
858 int b = inst & 0xf;
859 int bv = cpu.asregs.regs[b];
861 MOXIE_TRACE_INSN ("neg");
862 cpu.asregs.regs[a] = - bv;
864 break;
865 case 0x2b: /* or */
867 int a = (inst >> 4) & 0xf;
868 int b = inst & 0xf;
869 int av, bv;
871 MOXIE_TRACE_INSN ("or");
872 av = cpu.asregs.regs[a];
873 bv = cpu.asregs.regs[b];
874 cpu.asregs.regs[a] = av | bv;
876 break;
877 case 0x2c: /* not */
879 int a = (inst >> 4) & 0xf;
880 int b = inst & 0xf;
881 int bv = cpu.asregs.regs[b];
883 MOXIE_TRACE_INSN ("not");
884 cpu.asregs.regs[a] = 0xffffffff ^ bv;
886 break;
887 case 0x2d: /* ashr */
889 int a = (inst >> 4) & 0xf;
890 int b = inst & 0xf;
891 int av = cpu.asregs.regs[a];
892 int bv = cpu.asregs.regs[b];
894 MOXIE_TRACE_INSN ("ashr");
895 cpu.asregs.regs[a] = av >> bv;
897 break;
898 case 0x2e: /* xor */
900 int a = (inst >> 4) & 0xf;
901 int b = inst & 0xf;
902 int av, bv;
904 MOXIE_TRACE_INSN ("xor");
905 av = cpu.asregs.regs[a];
906 bv = cpu.asregs.regs[b];
907 cpu.asregs.regs[a] = av ^ bv;
909 break;
910 case 0x2f: /* mul.l */
912 int a = (inst >> 4) & 0xf;
913 int b = inst & 0xf;
914 unsigned av = cpu.asregs.regs[a];
915 unsigned bv = cpu.asregs.regs[b];
917 MOXIE_TRACE_INSN ("mul.l");
918 cpu.asregs.regs[a] = av * bv;
920 break;
921 case 0x30: /* swi */
923 unsigned int inum = EXTRACT_WORD(pc+2);
925 MOXIE_TRACE_INSN ("swi");
926 /* Set the special registers appropriately. */
927 cpu.asregs.sregs[2] = 3; /* MOXIE_EX_SWI */
928 cpu.asregs.sregs[3] = inum;
929 switch (inum)
931 case TARGET_NEWLIB_SYS_exit:
933 sim_engine_halt (sd, scpu, NULL, pc, sim_exited,
934 cpu.asregs.regs[2]);
935 break;
937 case TARGET_NEWLIB_SYS_open:
939 char fname[1024];
940 int mode = (int) convert_target_flags ((unsigned) cpu.asregs.regs[3]);
941 int fd;
942 sim_core_read_buffer (sd, scpu, read_map, fname,
943 cpu.asregs.regs[2], 1024);
944 fd = sim_io_open (sd, fname, mode);
945 /* FIXME - set errno */
946 cpu.asregs.regs[2] = fd;
947 break;
949 case TARGET_NEWLIB_SYS_read:
951 int fd = cpu.asregs.regs[2];
952 unsigned len = (unsigned) cpu.asregs.regs[4];
953 char *buf = malloc (len);
954 cpu.asregs.regs[2] = sim_io_read (sd, fd, buf, len);
955 sim_core_write_buffer (sd, scpu, write_map, buf,
956 cpu.asregs.regs[3], len);
957 free (buf);
958 break;
960 case TARGET_NEWLIB_SYS_write:
962 char *str;
963 /* String length is at 0x12($fp) */
964 unsigned count, len = (unsigned) cpu.asregs.regs[4];
965 str = malloc (len);
966 sim_core_read_buffer (sd, scpu, read_map, str,
967 cpu.asregs.regs[3], len);
968 count = sim_io_write (sd, cpu.asregs.regs[2], str, len);
969 free (str);
970 cpu.asregs.regs[2] = count;
971 break;
973 case TARGET_NEWLIB_SYS_unlink:
975 char fname[1024];
976 int fd;
977 sim_core_read_buffer (sd, scpu, read_map, fname,
978 cpu.asregs.regs[2], 1024);
979 fd = sim_io_unlink (sd, fname);
980 /* FIXME - set errno */
981 cpu.asregs.regs[2] = fd;
982 break;
984 case 0xffffffff: /* Linux System Call */
986 unsigned int handler = cpu.asregs.sregs[1];
987 unsigned int sp = cpu.asregs.regs[1];
989 /* Save a slot for the static chain. */
990 sp -= 4;
992 /* Push the return address. */
993 sp -= 4;
994 wlat (scpu, opc, sp, pc + 6);
996 /* Push the current frame pointer. */
997 sp -= 4;
998 wlat (scpu, opc, sp, cpu.asregs.regs[0]);
1000 /* Uncache the stack pointer and set the fp & pc. */
1001 cpu.asregs.regs[1] = sp;
1002 cpu.asregs.regs[0] = sp;
1003 pc = handler - 6;
1005 default:
1006 break;
1008 pc += 4;
1010 break;
1011 case 0x31: /* div.l */
1013 int a = (inst >> 4) & 0xf;
1014 int b = inst & 0xf;
1015 int av = cpu.asregs.regs[a];
1016 int bv = cpu.asregs.regs[b];
1018 MOXIE_TRACE_INSN ("div.l");
1019 cpu.asregs.regs[a] = av / bv;
1021 break;
1022 case 0x32: /* udiv.l */
1024 int a = (inst >> 4) & 0xf;
1025 int b = inst & 0xf;
1026 unsigned int av = cpu.asregs.regs[a];
1027 unsigned int bv = cpu.asregs.regs[b];
1029 MOXIE_TRACE_INSN ("udiv.l");
1030 cpu.asregs.regs[a] = (av / bv);
1032 break;
1033 case 0x33: /* mod.l */
1035 int a = (inst >> 4) & 0xf;
1036 int b = inst & 0xf;
1037 int av = cpu.asregs.regs[a];
1038 int bv = cpu.asregs.regs[b];
1040 MOXIE_TRACE_INSN ("mod.l");
1041 cpu.asregs.regs[a] = av % bv;
1043 break;
1044 case 0x34: /* umod.l */
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];
1051 MOXIE_TRACE_INSN ("umod.l");
1052 cpu.asregs.regs[a] = (av % bv);
1054 break;
1055 case 0x35: /* brk */
1056 MOXIE_TRACE_INSN ("brk");
1057 sim_engine_halt (sd, scpu, NULL, pc, sim_stopped, SIM_SIGTRAP);
1058 pc -= 2; /* Adjust pc */
1059 break;
1060 case 0x36: /* ldo.b */
1062 unsigned int addr = EXTRACT_OFFSET(pc+2);
1063 int a = (inst >> 4) & 0xf;
1064 int b = inst & 0xf;
1066 MOXIE_TRACE_INSN ("ldo.b");
1067 addr += cpu.asregs.regs[b];
1068 cpu.asregs.regs[a] = rbat (scpu, opc, addr);
1069 pc += 2;
1071 break;
1072 case 0x37: /* sto.b */
1074 unsigned int addr = EXTRACT_OFFSET(pc+2);
1075 int a = (inst >> 4) & 0xf;
1076 int b = inst & 0xf;
1078 MOXIE_TRACE_INSN ("sto.b");
1079 addr += cpu.asregs.regs[a];
1080 wbat (scpu, opc, addr, cpu.asregs.regs[b]);
1081 pc += 2;
1083 break;
1084 case 0x38: /* ldo.s */
1086 unsigned int addr = EXTRACT_OFFSET(pc+2);
1087 int a = (inst >> 4) & 0xf;
1088 int b = inst & 0xf;
1090 MOXIE_TRACE_INSN ("ldo.s");
1091 addr += cpu.asregs.regs[b];
1092 cpu.asregs.regs[a] = rsat (scpu, opc, addr);
1093 pc += 2;
1095 break;
1096 case 0x39: /* sto.s */
1098 unsigned int addr = EXTRACT_OFFSET(pc+2);
1099 int a = (inst >> 4) & 0xf;
1100 int b = inst & 0xf;
1102 MOXIE_TRACE_INSN ("sto.s");
1103 addr += cpu.asregs.regs[a];
1104 wsat (scpu, opc, addr, cpu.asregs.regs[b]);
1105 pc += 2;
1107 break;
1108 default:
1109 opc = opcode;
1110 MOXIE_TRACE_INSN ("SIGILL1");
1111 sim_engine_halt (sd, scpu, NULL, pc, sim_stopped, SIM_SIGILL);
1112 break;
1116 cpu.asregs.insts++;
1117 pc += 2;
1118 cpu.asregs.regs[PC_REGNO] = pc;
1120 if (sim_events_tick (sd))
1121 sim_events_process (sd);
1123 } while (1);
1126 static int
1127 moxie_reg_store (SIM_CPU *scpu, int rn, const void *memory, int length)
1129 if (rn < NUM_MOXIE_REGS && rn >= 0)
1131 if (length == 4)
1133 long ival;
1135 /* misalignment safe */
1136 ival = moxie_extract_unsigned_integer (memory, 4);
1137 cpu.asints[rn] = ival;
1140 return 4;
1142 else
1143 return 0;
1146 static int
1147 moxie_reg_fetch (SIM_CPU *scpu, int rn, void *memory, int length)
1149 if (rn < NUM_MOXIE_REGS && rn >= 0)
1151 if (length == 4)
1153 long ival = cpu.asints[rn];
1155 /* misalignment-safe */
1156 moxie_store_unsigned_integer (memory, 4, ival);
1159 return 4;
1161 else
1162 return 0;
1165 static sim_cia
1166 moxie_pc_get (sim_cpu *cpu)
1168 return MOXIE_SIM_CPU (cpu)->registers[PCIDX];
1171 static void
1172 moxie_pc_set (sim_cpu *cpu, sim_cia pc)
1174 MOXIE_SIM_CPU (cpu)->registers[PCIDX] = pc;
1177 static void
1178 free_state (SIM_DESC sd)
1180 if (STATE_MODULES (sd) != NULL)
1181 sim_module_uninstall (sd);
1182 sim_cpu_free_all (sd);
1183 sim_state_free (sd);
1186 SIM_DESC
1187 sim_open (SIM_OPEN_KIND kind, host_callback *cb,
1188 struct bfd *abfd, char * const *argv)
1190 int i;
1191 SIM_DESC sd = sim_state_alloc (kind, cb);
1192 SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
1194 /* Set default options before parsing user options. */
1195 current_target_byte_order = BFD_ENDIAN_BIG;
1197 /* The cpu data is kept in a separately allocated chunk of memory. */
1198 if (sim_cpu_alloc_all_extra (sd, 0, sizeof (struct moxie_sim_cpu))
1199 != SIM_RC_OK)
1201 free_state (sd);
1202 return 0;
1205 if (sim_pre_argv_init (sd, argv[0]) != SIM_RC_OK)
1207 free_state (sd);
1208 return 0;
1211 /* The parser will print an error message for us, so we silently return. */
1212 if (sim_parse_args (sd, argv) != SIM_RC_OK)
1214 free_state (sd);
1215 return 0;
1218 sim_do_command(sd," memory region 0x00000000,0x4000000") ;
1219 sim_do_command(sd," memory region 0xE0000000,0x10000") ;
1221 /* Check for/establish the a reference program image. */
1222 if (sim_analyze_program (sd, STATE_PROG_FILE (sd), abfd) != SIM_RC_OK)
1224 free_state (sd);
1225 return 0;
1228 /* Configure/verify the target byte order and other runtime
1229 configuration options. */
1230 if (sim_config (sd) != SIM_RC_OK)
1232 sim_module_uninstall (sd);
1233 return 0;
1236 if (sim_post_argv_init (sd) != SIM_RC_OK)
1238 /* Uninstall the modules to avoid memory leaks,
1239 file descriptor leaks, etc. */
1240 sim_module_uninstall (sd);
1241 return 0;
1244 /* CPU specific initialization. */
1245 for (i = 0; i < MAX_NR_PROCESSORS; ++i)
1247 SIM_CPU *cpu = STATE_CPU (sd, i);
1249 CPU_REG_FETCH (cpu) = moxie_reg_fetch;
1250 CPU_REG_STORE (cpu) = moxie_reg_store;
1251 CPU_PC_FETCH (cpu) = moxie_pc_get;
1252 CPU_PC_STORE (cpu) = moxie_pc_set;
1254 set_initial_gprs (); /* Reset the GPR registers. */
1257 return sd;
1260 /* Load the device tree blob. */
1262 static void
1263 load_dtb (SIM_DESC sd, const char *filename)
1265 int size = 0;
1266 FILE *f = fopen (filename, "rb");
1267 char *buf;
1268 sim_cpu *scpu = STATE_CPU (sd, 0); /* FIXME */
1270 /* Don't warn as the sim works fine w/out a device tree. */
1271 if (f == NULL)
1272 return;
1273 fseek (f, 0, SEEK_END);
1274 size = ftell(f);
1275 fseek (f, 0, SEEK_SET);
1276 buf = alloca (size);
1277 if (size != fread (buf, 1, size, f))
1279 sim_io_eprintf (sd, "ERROR: error reading ``%s''.\n", filename);
1280 fclose (f);
1281 return;
1283 sim_core_write_buffer (sd, scpu, write_map, buf, 0xE0000000, size);
1284 cpu.asregs.sregs[9] = 0xE0000000;
1285 fclose (f);
1288 SIM_RC
1289 sim_create_inferior (SIM_DESC sd, struct bfd *prog_bfd,
1290 char * const *argv, char * const *env)
1292 char * const *avp;
1293 int argc, i, tp;
1294 sim_cpu *scpu = STATE_CPU (sd, 0); /* FIXME */
1296 if (prog_bfd != NULL)
1297 cpu.asregs.regs[PC_REGNO] = bfd_get_start_address (prog_bfd);
1299 /* Copy args into target memory. */
1300 avp = argv;
1301 for (argc = 0; avp && *avp; avp++)
1302 argc++;
1304 /* Target memory looks like this:
1305 0x00000000 zero word
1306 0x00000004 argc word
1307 0x00000008 start of argv
1309 0x0000???? end of argv
1310 0x0000???? zero word
1311 0x0000???? start of data pointed to by argv */
1313 wlat (scpu, 0, 0, 0);
1314 wlat (scpu, 0, 4, argc);
1316 /* tp is the offset of our first argv data. */
1317 tp = 4 + 4 + argc * 4 + 4;
1319 for (i = 0; i < argc; i++)
1321 /* Set the argv value. */
1322 wlat (scpu, 0, 4 + 4 + i * 4, tp);
1324 /* Store the string. */
1325 sim_core_write_buffer (sd, scpu, write_map, argv[i],
1326 tp, strlen(argv[i])+1);
1327 tp += strlen (argv[i]) + 1;
1330 wlat (scpu, 0, 4 + 4 + i * 4, 0);
1332 load_dtb (sd, DTB);
1334 return SIM_RC_OK;