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/>. */
25 #include <sys/times.h>
26 #include <sys/param.h>
29 #include "libiberty.h"
30 #include "gdb/remote-sim.h"
34 #include "sim-options.h"
37 typedef unsigned int uword
;
39 /* Extract the signed 10-bit offset from a 16-bit branch
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) \
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)
56 moxie_extract_unsigned_integer (unsigned char *addr
, int len
)
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. */
71 for (p
= endaddr
; p
> startaddr
;)
72 retval
= (retval
<< 8) | * -- p
;
78 moxie_store_unsigned_integer (unsigned char *addr
, int len
, unsigned long val
)
81 unsigned char * startaddr
= (unsigned char *)addr
;
82 unsigned char * endaddr
= startaddr
+ len
;
84 for (p
= endaddr
; p
> startaddr
;)
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" };
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 */
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. */
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 */
126 /* TODO: This should be moved to sim-main.h:_sim_cpu. */
129 struct moxie_regset asregs
;
130 word asints
[1]; /* but accessed larger... */
134 set_initial_gprs (void)
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. */
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. */
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. */
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. */
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. */
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. */
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; }
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
);
226 "Simulator Error: problem converting target open flags for host. 0x%x\n",
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])
243 sim_engine_run (SIM_DESC sd
,
244 int next_cpu_nr
, /* ignore */
245 int nr_cpus
, /* ignore */
246 int siggnal
) /* ignore */
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. */
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);
276 MOXIE_TRACE_INSN ("beq");
277 if (cpu
.asregs
.cc
& CC_EQ
)
278 pc
+= INST2OFFSET(inst
);
283 MOXIE_TRACE_INSN ("bne");
284 if (! (cpu
.asregs
.cc
& CC_EQ
))
285 pc
+= INST2OFFSET(inst
);
290 MOXIE_TRACE_INSN ("blt");
291 if (cpu
.asregs
.cc
& CC_LT
)
292 pc
+= INST2OFFSET(inst
);
296 MOXIE_TRACE_INSN ("bgt");
297 if (cpu
.asregs
.cc
& CC_GT
)
298 pc
+= INST2OFFSET(inst
);
301 case 0x04: /* bltu */
303 MOXIE_TRACE_INSN ("bltu");
304 if (cpu
.asregs
.cc
& CC_LTU
)
305 pc
+= INST2OFFSET(inst
);
308 case 0x05: /* bgtu */
310 MOXIE_TRACE_INSN ("bgtu");
311 if (cpu
.asregs
.cc
& CC_GTU
)
312 pc
+= INST2OFFSET(inst
);
317 MOXIE_TRACE_INSN ("bge");
318 if (cpu
.asregs
.cc
& (CC_GT
| CC_EQ
))
319 pc
+= INST2OFFSET(inst
);
324 MOXIE_TRACE_INSN ("ble");
325 if (cpu
.asregs
.cc
& (CC_LT
| CC_EQ
))
326 pc
+= INST2OFFSET(inst
);
329 case 0x08: /* bgeu */
331 MOXIE_TRACE_INSN ("bgeu");
332 if (cpu
.asregs
.cc
& (CC_GTU
| CC_EQ
))
333 pc
+= INST2OFFSET(inst
);
336 case 0x09: /* bleu */
338 MOXIE_TRACE_INSN ("bleu");
339 if (cpu
.asregs
.cc
& (CC_LTU
| CC_EQ
))
340 pc
+= INST2OFFSET(inst
);
345 MOXIE_TRACE_INSN ("SIGILL3");
346 sim_engine_halt (sd
, scpu
, NULL
, pc
, sim_stopped
, SIM_SIGILL
);
353 /* This is a Form 2 instruction. */
354 int opcode
= (inst
>> 12 & 0x3);
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
;
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
;
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
];
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
];
396 MOXIE_TRACE_INSN ("SIGILL2");
397 sim_engine_halt (sd
, scpu
, NULL
, pc
, sim_stopped
, SIM_SIGILL
);
404 /* This is a Form 1 instruction. */
405 int opcode
= inst
>> 8;
410 MOXIE_TRACE_INSN ("SIGILL0");
411 sim_engine_halt (sd
, scpu
, NULL
, pc
, sim_stopped
, SIM_SIGILL
);
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
;
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
];
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. */
441 /* Push the return address. */
443 wlat (scpu
, opc
, sp
, pc
+ 6);
445 /* Push the current frame pointer. */
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
;
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
);
465 /* Pop the return address. */
466 pc
= rlat (scpu
, opc
, sp
) - 2;
469 /* Skip over the static chain slot. */
472 /* Uncache the stack pointer. */
473 cpu
.asregs
.regs
[1] = sp
;
476 case 0x05: /* add.l */
478 int a
= (inst
>> 4) & 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
;
487 case 0x06: /* push */
489 int a
= (inst
>> 4) & 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
;
500 int a
= (inst
>> 4) & 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;
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
);
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
]);
529 case 0x0a: /* ld.l (register indirect) */
531 int src
= inst
& 0xf;
532 int dest
= (inst
>> 4) & 0xf;
535 MOXIE_TRACE_INSN ("ld.l");
536 xv
= cpu
.asregs
.regs
[src
];
537 cpu
.asregs
.regs
[dest
] = rlat (scpu
, opc
, xv
);
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
]);
549 case 0x0c: /* ldo.l */
551 unsigned int addr
= EXTRACT_OFFSET(pc
+2);
552 int a
= (inst
>> 4) & 0xf;
555 MOXIE_TRACE_INSN ("ldo.l");
556 addr
+= cpu
.asregs
.regs
[b
];
557 cpu
.asregs
.regs
[a
] = rlat (scpu
, opc
, addr
);
561 case 0x0d: /* sto.l */
563 unsigned int addr
= EXTRACT_OFFSET(pc
+2);
564 int a
= (inst
>> 4) & 0xf;
567 MOXIE_TRACE_INSN ("sto.l");
568 addr
+= cpu
.asregs
.regs
[a
];
569 wlat (scpu
, opc
, addr
, cpu
.asregs
.regs
[b
]);
575 int a
= (inst
>> 4) & 0xf;
578 int va
= cpu
.asregs
.regs
[a
];
579 int vb
= cpu
.asregs
.regs
[b
];
581 MOXIE_TRACE_INSN ("cmp");
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);
597 case 0x10: /* sex.b */
599 int a
= (inst
>> 4) & 0xf;
601 signed char bv
= cpu
.asregs
.regs
[b
];
603 MOXIE_TRACE_INSN ("sex.b");
604 cpu
.asregs
.regs
[a
] = (int) bv
;
607 case 0x11: /* sex.s */
609 int a
= (inst
>> 4) & 0xf;
611 signed short bv
= cpu
.asregs
.regs
[b
];
613 MOXIE_TRACE_INSN ("sex.s");
614 cpu
.asregs
.regs
[a
] = (int) bv
;
617 case 0x12: /* zex.b */
619 int a
= (inst
>> 4) & 0xf;
621 signed char bv
= cpu
.asregs
.regs
[b
];
623 MOXIE_TRACE_INSN ("zex.b");
624 cpu
.asregs
.regs
[a
] = (int) bv
& 0xff;
627 case 0x13: /* zex.s */
629 int a
= (inst
>> 4) & 0xf;
631 signed short bv
= cpu
.asregs
.regs
[b
];
633 MOXIE_TRACE_INSN ("zex.s");
634 cpu
.asregs
.regs
[a
] = (int) bv
& 0xffff;
637 case 0x14: /* umul.x */
639 int a
= (inst
>> 4) & 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;
650 case 0x15: /* mul.x */
652 int a
= (inst
>> 4) & 0xf;
654 unsigned av
= cpu
.asregs
.regs
[a
];
655 unsigned bv
= cpu
.asregs
.regs
[b
];
657 (signed long long) av
* (signed long long) bv
;
659 MOXIE_TRACE_INSN ("mul.x");
660 cpu
.asregs
.regs
[a
] = r
>> 32;
668 MOXIE_TRACE_INSN ("SIGILL0");
669 sim_engine_halt (sd
, scpu
, NULL
, pc
, sim_stopped
, SIM_SIGILL
);
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. */
682 /* Push the return address. */
684 wlat (scpu
, opc
, sp
, pc
+ 2);
686 /* Push the current frame pointer. */
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
;
696 case 0x1a: /* jmpa */
698 unsigned int tgt
= EXTRACT_WORD(pc
+2);
700 MOXIE_TRACE_INSN ("jmpa");
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
;
714 case 0x1c: /* ld.b (register indirect) */
716 int src
= inst
& 0xf;
717 int dest
= (inst
>> 4) & 0xf;
720 MOXIE_TRACE_INSN ("ld.b");
721 xv
= cpu
.asregs
.regs
[src
];
722 cpu
.asregs
.regs
[dest
] = rbat (scpu
, opc
, xv
);
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
);
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
]);
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
]);
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
;
765 case 0x21: /* ld.s (register indirect) */
767 int src
= inst
& 0xf;
768 int dest
= (inst
>> 4) & 0xf;
771 MOXIE_TRACE_INSN ("ld.s");
772 xv
= cpu
.asregs
.regs
[src
];
773 cpu
.asregs
.regs
[dest
] = rsat (scpu
, opc
, xv
);
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
);
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
]);
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
]);
807 int reg
= (inst
>> 4) & 0xf;
809 MOXIE_TRACE_INSN ("jmp");
810 pc
= cpu
.asregs
.regs
[reg
] - 2;
815 int a
= (inst
>> 4) & 0xf;
819 MOXIE_TRACE_INSN ("and");
820 av
= cpu
.asregs
.regs
[a
];
821 bv
= cpu
.asregs
.regs
[b
];
822 cpu
.asregs
.regs
[a
] = av
& bv
;
825 case 0x27: /* lshr */
827 int a
= (inst
>> 4) & 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
);
836 case 0x28: /* ashl */
838 int a
= (inst
>> 4) & 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
;
847 case 0x29: /* sub.l */
849 int a
= (inst
>> 4) & 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
;
860 int a
= (inst
>> 4) & 0xf;
862 int bv
= cpu
.asregs
.regs
[b
];
864 MOXIE_TRACE_INSN ("neg");
865 cpu
.asregs
.regs
[a
] = - bv
;
870 int a
= (inst
>> 4) & 0xf;
874 MOXIE_TRACE_INSN ("or");
875 av
= cpu
.asregs
.regs
[a
];
876 bv
= cpu
.asregs
.regs
[b
];
877 cpu
.asregs
.regs
[a
] = av
| bv
;
882 int a
= (inst
>> 4) & 0xf;
884 int bv
= cpu
.asregs
.regs
[b
];
886 MOXIE_TRACE_INSN ("not");
887 cpu
.asregs
.regs
[a
] = 0xffffffff ^ bv
;
890 case 0x2d: /* ashr */
892 int a
= (inst
>> 4) & 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
;
903 int a
= (inst
>> 4) & 0xf;
907 MOXIE_TRACE_INSN ("xor");
908 av
= cpu
.asregs
.regs
[a
];
909 bv
= cpu
.asregs
.regs
[b
];
910 cpu
.asregs
.regs
[a
] = av
^ bv
;
913 case 0x2f: /* mul.l */
915 int a
= (inst
>> 4) & 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
;
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
;
934 case 0x1: /* SYS_exit */
936 sim_engine_halt (sd
, scpu
, NULL
, pc
, sim_exited
,
940 case 0x2: /* SYS_open */
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
;
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
);
963 case 0x5: /* SYS_write */
966 /* String length is at 0x12($fp) */
967 unsigned count
, len
= (unsigned) cpu
.asregs
.regs
[4];
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
);
973 cpu
.asregs
.regs
[2] = count
;
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. */
984 /* Push the return address. */
986 wlat (scpu
, opc
, sp
, pc
+ 6);
988 /* Push the current frame pointer. */
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
;
1003 case 0x31: /* div.l */
1005 int a
= (inst
>> 4) & 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
;
1014 case 0x32: /* udiv.l */
1016 int a
= (inst
>> 4) & 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
);
1025 case 0x33: /* mod.l */
1027 int a
= (inst
>> 4) & 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
;
1036 case 0x34: /* umod.l */
1038 int a
= (inst
>> 4) & 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
);
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 */
1052 case 0x36: /* ldo.b */
1054 unsigned int addr
= EXTRACT_OFFSET(pc
+2);
1055 int a
= (inst
>> 4) & 0xf;
1058 MOXIE_TRACE_INSN ("ldo.b");
1059 addr
+= cpu
.asregs
.regs
[b
];
1060 cpu
.asregs
.regs
[a
] = rbat (scpu
, opc
, addr
);
1064 case 0x37: /* sto.b */
1066 unsigned int addr
= EXTRACT_OFFSET(pc
+2);
1067 int a
= (inst
>> 4) & 0xf;
1070 MOXIE_TRACE_INSN ("sto.b");
1071 addr
+= cpu
.asregs
.regs
[a
];
1072 wbat (scpu
, opc
, addr
, cpu
.asregs
.regs
[b
]);
1076 case 0x38: /* ldo.s */
1078 unsigned int addr
= EXTRACT_OFFSET(pc
+2);
1079 int a
= (inst
>> 4) & 0xf;
1082 MOXIE_TRACE_INSN ("ldo.s");
1083 addr
+= cpu
.asregs
.regs
[b
];
1084 cpu
.asregs
.regs
[a
] = rsat (scpu
, opc
, addr
);
1088 case 0x39: /* sto.s */
1090 unsigned int addr
= EXTRACT_OFFSET(pc
+2);
1091 int a
= (inst
>> 4) & 0xf;
1094 MOXIE_TRACE_INSN ("sto.s");
1095 addr
+= cpu
.asregs
.regs
[a
];
1096 wsat (scpu
, opc
, addr
, cpu
.asregs
.regs
[b
]);
1102 MOXIE_TRACE_INSN ("SIGILL1");
1103 sim_engine_halt (sd
, scpu
, NULL
, pc
, sim_stopped
, SIM_SIGILL
);
1110 cpu
.asregs
.regs
[PC_REGNO
] = pc
;
1112 if (sim_events_tick (sd
))
1113 sim_events_process (sd
);
1119 moxie_reg_store (SIM_CPU
*scpu
, int rn
, unsigned char *memory
, int length
)
1121 if (rn
< NUM_MOXIE_REGS
&& rn
>= 0)
1127 /* misalignment safe */
1128 ival
= moxie_extract_unsigned_integer (memory
, 4);
1129 cpu
.asints
[rn
] = ival
;
1139 moxie_reg_fetch (SIM_CPU
*scpu
, int rn
, unsigned char *memory
, int length
)
1141 if (rn
< NUM_MOXIE_REGS
&& rn
>= 0)
1145 long ival
= cpu
.asints
[rn
];
1147 /* misalignment-safe */
1148 moxie_store_unsigned_integer (memory
, 4, ival
);
1158 moxie_pc_get (sim_cpu
*cpu
)
1160 return cpu
->registers
[PCIDX
];
1164 moxie_pc_set (sim_cpu
*cpu
, sim_cia pc
)
1166 cpu
->registers
[PCIDX
] = pc
;
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
);
1179 sim_open (SIM_OPEN_KIND kind
, host_callback
*cb
,
1180 struct bfd
*abfd
, char * const *argv
)
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
)
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
)
1202 /* The parser will print an error message for us, so we silently return. */
1203 if (sim_parse_args (sd
, argv
) != SIM_RC_OK
)
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
)
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
);
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
);
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. */
1254 /* Load the device tree blob. */
1257 load_dtb (SIM_DESC sd
, const char *filename
)
1260 FILE *f
= fopen (filename
, "rb");
1262 sim_cpu
*scpu
= STATE_CPU (sd
, 0); /* FIXME */
1264 /* Don't warn as the sim works fine w/out a device tree. */
1267 fseek (f
, 0, SEEK_END
);
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
);
1277 sim_core_write_buffer (sd
, scpu
, write_map
, buf
, 0xE0000000, size
);
1278 cpu
.asregs
.sregs
[9] = 0xE0000000;
1283 sim_create_inferior (SIM_DESC sd
, struct bfd
*prog_bfd
,
1284 char * const *argv
, char * const *env
)
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. */
1295 for (argc
= 0; avp
&& *avp
; avp
++)
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);