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"
38 typedef unsigned int uword
;
40 /* Extract the signed 10-bit offset from a 16-bit branch
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) \
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)
57 moxie_extract_unsigned_integer (unsigned char *addr
, int len
)
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. */
72 for (p
= endaddr
; p
> startaddr
;)
73 retval
= (retval
<< 8) | * -- p
;
79 moxie_store_unsigned_integer (unsigned char *addr
, int len
, unsigned long val
)
82 unsigned char * startaddr
= (unsigned char *)addr
;
83 unsigned char * endaddr
= startaddr
+ len
;
85 for (p
= endaddr
; p
> startaddr
;)
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" };
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 */
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. */
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 */
127 /* TODO: This should be moved to sim-main.h:_sim_cpu. */
130 struct moxie_regset asregs
;
131 word asints
[1]; /* but accessed larger... */
135 set_initial_gprs (void)
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. */
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. */
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. */
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. */
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. */
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. */
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; }
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
);
227 "Simulator Error: problem converting target open flags for host. 0x%x\n",
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])
244 sim_engine_run (SIM_DESC sd
,
245 int next_cpu_nr
, /* ignore */
246 int nr_cpus
, /* ignore */
247 int siggnal
) /* ignore */
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. */
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);
277 MOXIE_TRACE_INSN ("beq");
278 if (cpu
.asregs
.cc
& CC_EQ
)
279 pc
+= INST2OFFSET(inst
);
284 MOXIE_TRACE_INSN ("bne");
285 if (! (cpu
.asregs
.cc
& CC_EQ
))
286 pc
+= INST2OFFSET(inst
);
291 MOXIE_TRACE_INSN ("blt");
292 if (cpu
.asregs
.cc
& CC_LT
)
293 pc
+= INST2OFFSET(inst
);
297 MOXIE_TRACE_INSN ("bgt");
298 if (cpu
.asregs
.cc
& CC_GT
)
299 pc
+= INST2OFFSET(inst
);
302 case 0x04: /* bltu */
304 MOXIE_TRACE_INSN ("bltu");
305 if (cpu
.asregs
.cc
& CC_LTU
)
306 pc
+= INST2OFFSET(inst
);
309 case 0x05: /* bgtu */
311 MOXIE_TRACE_INSN ("bgtu");
312 if (cpu
.asregs
.cc
& CC_GTU
)
313 pc
+= INST2OFFSET(inst
);
318 MOXIE_TRACE_INSN ("bge");
319 if (cpu
.asregs
.cc
& (CC_GT
| CC_EQ
))
320 pc
+= INST2OFFSET(inst
);
325 MOXIE_TRACE_INSN ("ble");
326 if (cpu
.asregs
.cc
& (CC_LT
| CC_EQ
))
327 pc
+= INST2OFFSET(inst
);
330 case 0x08: /* bgeu */
332 MOXIE_TRACE_INSN ("bgeu");
333 if (cpu
.asregs
.cc
& (CC_GTU
| CC_EQ
))
334 pc
+= INST2OFFSET(inst
);
337 case 0x09: /* bleu */
339 MOXIE_TRACE_INSN ("bleu");
340 if (cpu
.asregs
.cc
& (CC_LTU
| CC_EQ
))
341 pc
+= INST2OFFSET(inst
);
346 MOXIE_TRACE_INSN ("SIGILL3");
347 sim_engine_halt (sd
, scpu
, NULL
, pc
, sim_stopped
, SIM_SIGILL
);
354 /* This is a Form 2 instruction. */
355 int opcode
= (inst
>> 12 & 0x3);
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
;
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
;
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
];
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
];
397 MOXIE_TRACE_INSN ("SIGILL2");
398 sim_engine_halt (sd
, scpu
, NULL
, pc
, sim_stopped
, SIM_SIGILL
);
405 /* This is a Form 1 instruction. */
406 int opcode
= inst
>> 8;
411 MOXIE_TRACE_INSN ("SIGILL0");
412 sim_engine_halt (sd
, scpu
, NULL
, pc
, sim_stopped
, SIM_SIGILL
);
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
;
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
];
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. */
442 /* Push the return address. */
444 wlat (scpu
, opc
, sp
, pc
+ 6);
446 /* Push the current frame pointer. */
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
;
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
);
466 /* Pop the return address. */
467 pc
= rlat (scpu
, opc
, sp
) - 2;
470 /* Skip over the static chain slot. */
473 /* Uncache the stack pointer. */
474 cpu
.asregs
.regs
[1] = sp
;
477 case 0x05: /* add.l */
479 int a
= (inst
>> 4) & 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
;
488 case 0x06: /* push */
490 int a
= (inst
>> 4) & 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
;
501 int a
= (inst
>> 4) & 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;
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
);
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
]);
530 case 0x0a: /* ld.l (register indirect) */
532 int src
= inst
& 0xf;
533 int dest
= (inst
>> 4) & 0xf;
536 MOXIE_TRACE_INSN ("ld.l");
537 xv
= cpu
.asregs
.regs
[src
];
538 cpu
.asregs
.regs
[dest
] = rlat (scpu
, opc
, xv
);
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
]);
550 case 0x0c: /* ldo.l */
552 unsigned int addr
= EXTRACT_OFFSET(pc
+2);
553 int a
= (inst
>> 4) & 0xf;
556 MOXIE_TRACE_INSN ("ldo.l");
557 addr
+= cpu
.asregs
.regs
[b
];
558 cpu
.asregs
.regs
[a
] = rlat (scpu
, opc
, addr
);
562 case 0x0d: /* sto.l */
564 unsigned int addr
= EXTRACT_OFFSET(pc
+2);
565 int a
= (inst
>> 4) & 0xf;
568 MOXIE_TRACE_INSN ("sto.l");
569 addr
+= cpu
.asregs
.regs
[a
];
570 wlat (scpu
, opc
, addr
, cpu
.asregs
.regs
[b
]);
576 int a
= (inst
>> 4) & 0xf;
579 int va
= cpu
.asregs
.regs
[a
];
580 int vb
= cpu
.asregs
.regs
[b
];
582 MOXIE_TRACE_INSN ("cmp");
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);
598 case 0x10: /* sex.b */
600 int a
= (inst
>> 4) & 0xf;
602 signed char bv
= cpu
.asregs
.regs
[b
];
604 MOXIE_TRACE_INSN ("sex.b");
605 cpu
.asregs
.regs
[a
] = (int) bv
;
608 case 0x11: /* sex.s */
610 int a
= (inst
>> 4) & 0xf;
612 signed short bv
= cpu
.asregs
.regs
[b
];
614 MOXIE_TRACE_INSN ("sex.s");
615 cpu
.asregs
.regs
[a
] = (int) bv
;
618 case 0x12: /* zex.b */
620 int a
= (inst
>> 4) & 0xf;
622 signed char bv
= cpu
.asregs
.regs
[b
];
624 MOXIE_TRACE_INSN ("zex.b");
625 cpu
.asregs
.regs
[a
] = (int) bv
& 0xff;
628 case 0x13: /* zex.s */
630 int a
= (inst
>> 4) & 0xf;
632 signed short bv
= cpu
.asregs
.regs
[b
];
634 MOXIE_TRACE_INSN ("zex.s");
635 cpu
.asregs
.regs
[a
] = (int) bv
& 0xffff;
638 case 0x14: /* umul.x */
640 int a
= (inst
>> 4) & 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;
651 case 0x15: /* mul.x */
653 int a
= (inst
>> 4) & 0xf;
655 unsigned av
= cpu
.asregs
.regs
[a
];
656 unsigned bv
= cpu
.asregs
.regs
[b
];
658 (signed long long) av
* (signed long long) bv
;
660 MOXIE_TRACE_INSN ("mul.x");
661 cpu
.asregs
.regs
[a
] = r
>> 32;
669 MOXIE_TRACE_INSN ("SIGILL0");
670 sim_engine_halt (sd
, scpu
, NULL
, pc
, sim_stopped
, SIM_SIGILL
);
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. */
683 /* Push the return address. */
685 wlat (scpu
, opc
, sp
, pc
+ 2);
687 /* Push the current frame pointer. */
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
;
697 case 0x1a: /* jmpa */
699 unsigned int tgt
= EXTRACT_WORD(pc
+2);
701 MOXIE_TRACE_INSN ("jmpa");
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
;
715 case 0x1c: /* ld.b (register indirect) */
717 int src
= inst
& 0xf;
718 int dest
= (inst
>> 4) & 0xf;
721 MOXIE_TRACE_INSN ("ld.b");
722 xv
= cpu
.asregs
.regs
[src
];
723 cpu
.asregs
.regs
[dest
] = rbat (scpu
, opc
, xv
);
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
);
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
]);
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
]);
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
;
766 case 0x21: /* ld.s (register indirect) */
768 int src
= inst
& 0xf;
769 int dest
= (inst
>> 4) & 0xf;
772 MOXIE_TRACE_INSN ("ld.s");
773 xv
= cpu
.asregs
.regs
[src
];
774 cpu
.asregs
.regs
[dest
] = rsat (scpu
, opc
, xv
);
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
);
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
]);
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
]);
808 int reg
= (inst
>> 4) & 0xf;
810 MOXIE_TRACE_INSN ("jmp");
811 pc
= cpu
.asregs
.regs
[reg
] - 2;
816 int a
= (inst
>> 4) & 0xf;
820 MOXIE_TRACE_INSN ("and");
821 av
= cpu
.asregs
.regs
[a
];
822 bv
= cpu
.asregs
.regs
[b
];
823 cpu
.asregs
.regs
[a
] = av
& bv
;
826 case 0x27: /* lshr */
828 int a
= (inst
>> 4) & 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
);
837 case 0x28: /* ashl */
839 int a
= (inst
>> 4) & 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
;
848 case 0x29: /* sub.l */
850 int a
= (inst
>> 4) & 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
;
861 int a
= (inst
>> 4) & 0xf;
863 int bv
= cpu
.asregs
.regs
[b
];
865 MOXIE_TRACE_INSN ("neg");
866 cpu
.asregs
.regs
[a
] = - bv
;
871 int a
= (inst
>> 4) & 0xf;
875 MOXIE_TRACE_INSN ("or");
876 av
= cpu
.asregs
.regs
[a
];
877 bv
= cpu
.asregs
.regs
[b
];
878 cpu
.asregs
.regs
[a
] = av
| bv
;
883 int a
= (inst
>> 4) & 0xf;
885 int bv
= cpu
.asregs
.regs
[b
];
887 MOXIE_TRACE_INSN ("not");
888 cpu
.asregs
.regs
[a
] = 0xffffffff ^ bv
;
891 case 0x2d: /* ashr */
893 int a
= (inst
>> 4) & 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
;
904 int a
= (inst
>> 4) & 0xf;
908 MOXIE_TRACE_INSN ("xor");
909 av
= cpu
.asregs
.regs
[a
];
910 bv
= cpu
.asregs
.regs
[b
];
911 cpu
.asregs
.regs
[a
] = av
^ bv
;
914 case 0x2f: /* mul.l */
916 int a
= (inst
>> 4) & 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
;
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
;
935 case 0x1: /* SYS_exit */
937 sim_engine_halt (sd
, scpu
, NULL
, pc
, sim_exited
,
941 case 0x2: /* SYS_open */
944 int mode
= (int) convert_target_flags ((unsigned) cpu
.asregs
.regs
[3]);
945 int perm
= (int) cpu
.asregs
.regs
[4];
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
;
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
);
965 case 0x5: /* SYS_write */
968 /* String length is at 0x12($fp) */
969 unsigned count
, len
= (unsigned) cpu
.asregs
.regs
[4];
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
);
975 cpu
.asregs
.regs
[2] = count
;
978 case 0x7: /* SYS_unlink */
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
;
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. */
997 /* Push the return address. */
999 wlat (scpu
, opc
, sp
, pc
+ 6);
1001 /* Push the current frame pointer. */
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
;
1016 case 0x31: /* div.l */
1018 int a
= (inst
>> 4) & 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
;
1027 case 0x32: /* udiv.l */
1029 int a
= (inst
>> 4) & 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
);
1038 case 0x33: /* mod.l */
1040 int a
= (inst
>> 4) & 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
;
1049 case 0x34: /* umod.l */
1051 int a
= (inst
>> 4) & 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
);
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 */
1065 case 0x36: /* ldo.b */
1067 unsigned int addr
= EXTRACT_OFFSET(pc
+2);
1068 int a
= (inst
>> 4) & 0xf;
1071 MOXIE_TRACE_INSN ("ldo.b");
1072 addr
+= cpu
.asregs
.regs
[b
];
1073 cpu
.asregs
.regs
[a
] = rbat (scpu
, opc
, addr
);
1077 case 0x37: /* sto.b */
1079 unsigned int addr
= EXTRACT_OFFSET(pc
+2);
1080 int a
= (inst
>> 4) & 0xf;
1083 MOXIE_TRACE_INSN ("sto.b");
1084 addr
+= cpu
.asregs
.regs
[a
];
1085 wbat (scpu
, opc
, addr
, cpu
.asregs
.regs
[b
]);
1089 case 0x38: /* ldo.s */
1091 unsigned int addr
= EXTRACT_OFFSET(pc
+2);
1092 int a
= (inst
>> 4) & 0xf;
1095 MOXIE_TRACE_INSN ("ldo.s");
1096 addr
+= cpu
.asregs
.regs
[b
];
1097 cpu
.asregs
.regs
[a
] = rsat (scpu
, opc
, addr
);
1101 case 0x39: /* sto.s */
1103 unsigned int addr
= EXTRACT_OFFSET(pc
+2);
1104 int a
= (inst
>> 4) & 0xf;
1107 MOXIE_TRACE_INSN ("sto.s");
1108 addr
+= cpu
.asregs
.regs
[a
];
1109 wsat (scpu
, opc
, addr
, cpu
.asregs
.regs
[b
]);
1115 MOXIE_TRACE_INSN ("SIGILL1");
1116 sim_engine_halt (sd
, scpu
, NULL
, pc
, sim_stopped
, SIM_SIGILL
);
1123 cpu
.asregs
.regs
[PC_REGNO
] = pc
;
1125 if (sim_events_tick (sd
))
1126 sim_events_process (sd
);
1132 moxie_reg_store (SIM_CPU
*scpu
, int rn
, unsigned char *memory
, int length
)
1134 if (rn
< NUM_MOXIE_REGS
&& rn
>= 0)
1140 /* misalignment safe */
1141 ival
= moxie_extract_unsigned_integer (memory
, 4);
1142 cpu
.asints
[rn
] = ival
;
1152 moxie_reg_fetch (SIM_CPU
*scpu
, int rn
, unsigned char *memory
, int length
)
1154 if (rn
< NUM_MOXIE_REGS
&& rn
>= 0)
1158 long ival
= cpu
.asints
[rn
];
1160 /* misalignment-safe */
1161 moxie_store_unsigned_integer (memory
, 4, ival
);
1171 moxie_pc_get (sim_cpu
*cpu
)
1173 return cpu
->registers
[PCIDX
];
1177 moxie_pc_set (sim_cpu
*cpu
, sim_cia pc
)
1179 cpu
->registers
[PCIDX
] = pc
;
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
);
1192 sim_open (SIM_OPEN_KIND kind
, host_callback
*cb
,
1193 struct bfd
*abfd
, char * const *argv
)
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
)
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
)
1215 /* The parser will print an error message for us, so we silently return. */
1216 if (sim_parse_args (sd
, argv
) != SIM_RC_OK
)
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
)
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
);
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
);
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. */
1267 /* Load the device tree blob. */
1270 load_dtb (SIM_DESC sd
, const char *filename
)
1273 FILE *f
= fopen (filename
, "rb");
1275 sim_cpu
*scpu
= STATE_CPU (sd
, 0); /* FIXME */
1277 /* Don't warn as the sim works fine w/out a device tree. */
1280 fseek (f
, 0, SEEK_END
);
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
);
1290 sim_core_write_buffer (sd
, scpu
, write_map
, buf
, 0xE0000000, size
);
1291 cpu
.asregs
.sregs
[9] = 0xE0000000;
1296 sim_create_inferior (SIM_DESC sd
, struct bfd
*prog_bfd
,
1297 char * const *argv
, char * const *env
)
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. */
1308 for (argc
= 0; avp
&& *avp
; avp
++)
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);