1 /* Simulator for the moxie processor
2 Copyright (C) 2008-2021 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. */
27 #include <sys/param.h>
30 #include "libiberty.h"
35 #include "sim-options.h"
37 #include "sim-signal.h"
38 #include "targ-vals.h"
41 typedef unsigned int uword
;
43 /* Extract the signed 10-bit offset from a 16-bit branch
45 #define INST2OFFSET(o) ((((signed short)((o & ((1<<10)-1))<<6))>>6)<<1)
47 #define EXTRACT_WORD(addr) \
48 ((sim_core_read_aligned_1 (scpu, cia, read_map, addr) << 24) \
49 + (sim_core_read_aligned_1 (scpu, cia, read_map, addr+1) << 16) \
50 + (sim_core_read_aligned_1 (scpu, cia, read_map, addr+2) << 8) \
51 + (sim_core_read_aligned_1 (scpu, cia, read_map, addr+3)))
53 #define EXTRACT_OFFSET(addr) \
56 ((sim_core_read_aligned_1 (scpu, cia, read_map, addr) << 8) \
57 + (sim_core_read_aligned_1 (scpu, cia, read_map, addr+1))) << 16) >> 16)
60 moxie_extract_unsigned_integer (unsigned char *addr
, int len
)
64 unsigned char * startaddr
= (unsigned char *)addr
;
65 unsigned char * endaddr
= startaddr
+ len
;
67 if (len
> (int) sizeof (unsigned long))
68 printf ("That operation is not available on integers of more than %zu bytes.",
69 sizeof (unsigned long));
71 /* Start at the most significant end of the integer, and work towards
72 the least significant. */
75 for (p
= endaddr
; p
> startaddr
;)
76 retval
= (retval
<< 8) | * -- p
;
82 moxie_store_unsigned_integer (unsigned char *addr
, int len
, unsigned long val
)
85 unsigned char * startaddr
= (unsigned char *)addr
;
86 unsigned char * endaddr
= startaddr
+ len
;
88 for (p
= endaddr
; p
> startaddr
;)
95 /* moxie register names. */
96 static const char *reg_names
[16] =
97 { "$fp", "$sp", "$r0", "$r1", "$r2", "$r3", "$r4", "$r5",
98 "$r6", "$r7", "$r8", "$r9", "$r10", "$r11", "$r12", "$r13" };
100 /* The machine state.
102 This state is maintained in host byte order. The fetch/store
103 register functions must translate between host byte order and the
104 target processor byte order. Keeping this data in target byte
105 order simplifies the register read/write functions. Keeping this
106 data in native order improves the performance of the simulator.
107 Simulation speed is deemed more important. */
109 #define NUM_MOXIE_REGS 17 /* Including PC */
110 #define NUM_MOXIE_SREGS 256 /* The special registers */
113 /* The ordering of the moxie_regset structure is matched in the
114 gdb/config/moxie/tm-moxie.h file in the REGISTER_NAMES macro. */
115 /* TODO: This should be moved to sim-main.h:_sim_cpu. */
118 word regs
[NUM_MOXIE_REGS
+ 1]; /* primary registers */
119 word sregs
[256]; /* special registers */
120 word cc
; /* the condition code reg */
121 unsigned long long insts
; /* instruction counter */
130 /* TODO: This should be moved to sim-main.h:_sim_cpu. */
133 struct moxie_regset asregs
;
134 word asints
[1]; /* but accessed larger... */
138 set_initial_gprs (void)
143 /* Set up machine just out of reset. */
144 cpu
.asregs
.regs
[PC_REGNO
] = 0;
146 /* Clean out the register contents. */
147 for (i
= 0; i
< NUM_MOXIE_REGS
; i
++)
148 cpu
.asregs
.regs
[i
] = 0;
149 for (i
= 0; i
< NUM_MOXIE_SREGS
; i
++)
150 cpu
.asregs
.sregs
[i
] = 0;
153 /* Write a 1 byte value to memory. */
156 wbat (sim_cpu
*scpu
, word pc
, word x
, word v
)
158 address_word cia
= CPU_PC_GET (scpu
);
160 sim_core_write_aligned_1 (scpu
, cia
, write_map
, x
, v
);
163 /* Write a 2 byte value to memory. */
166 wsat (sim_cpu
*scpu
, word pc
, word x
, word v
)
168 address_word cia
= CPU_PC_GET (scpu
);
170 sim_core_write_aligned_2 (scpu
, cia
, write_map
, x
, v
);
173 /* Write a 4 byte value to memory. */
176 wlat (sim_cpu
*scpu
, word pc
, word x
, word v
)
178 address_word cia
= CPU_PC_GET (scpu
);
180 sim_core_write_aligned_4 (scpu
, cia
, write_map
, x
, v
);
183 /* Read 2 bytes from memory. */
186 rsat (sim_cpu
*scpu
, word pc
, word x
)
188 address_word cia
= CPU_PC_GET (scpu
);
190 return (sim_core_read_aligned_2 (scpu
, cia
, read_map
, x
));
193 /* Read 1 byte from memory. */
196 rbat (sim_cpu
*scpu
, word pc
, word x
)
198 address_word cia
= CPU_PC_GET (scpu
);
200 return (sim_core_read_aligned_1 (scpu
, cia
, read_map
, x
));
203 /* Read 4 bytes from memory. */
206 rlat (sim_cpu
*scpu
, word pc
, word x
)
208 address_word cia
= CPU_PC_GET (scpu
);
210 return (sim_core_read_aligned_4 (scpu
, cia
, read_map
, x
));
213 #define CHECK_FLAG(T,H) if (tflags & T) { hflags |= H; tflags ^= T; }
216 convert_target_flags (unsigned int tflags
)
218 unsigned int hflags
= 0x0;
220 CHECK_FLAG(0x0001, O_WRONLY
);
221 CHECK_FLAG(0x0002, O_RDWR
);
222 CHECK_FLAG(0x0008, O_APPEND
);
223 CHECK_FLAG(0x0200, O_CREAT
);
224 CHECK_FLAG(0x0400, O_TRUNC
);
225 CHECK_FLAG(0x0800, O_EXCL
);
226 CHECK_FLAG(0x2000, O_SYNC
);
230 "Simulator Error: problem converting target open flags for host. 0x%x\n",
236 /* TODO: Split this up into finger trace levels than just insn. */
237 #define MOXIE_TRACE_INSN(str) \
238 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", \
239 opc, str, cpu.asregs.regs[0], cpu.asregs.regs[1], \
240 cpu.asregs.regs[2], cpu.asregs.regs[3], cpu.asregs.regs[4], \
241 cpu.asregs.regs[5], cpu.asregs.regs[6], cpu.asregs.regs[7], \
242 cpu.asregs.regs[8], cpu.asregs.regs[9], cpu.asregs.regs[10], \
243 cpu.asregs.regs[11], cpu.asregs.regs[12], cpu.asregs.regs[13], \
244 cpu.asregs.regs[14], cpu.asregs.regs[15])
247 sim_engine_run (SIM_DESC sd
,
248 int next_cpu_nr
, /* ignore */
249 int nr_cpus
, /* ignore */
250 int siggnal
) /* ignore */
254 sim_cpu
*scpu
= STATE_CPU (sd
, 0); /* FIXME */
255 address_word cia
= CPU_PC_GET (scpu
);
257 pc
= cpu
.asregs
.regs
[PC_REGNO
];
259 /* Run instructions here. */
264 /* Fetch the instruction at pc. */
265 inst
= (sim_core_read_aligned_1 (scpu
, cia
, read_map
, pc
) << 8)
266 + sim_core_read_aligned_1 (scpu
, cia
, read_map
, pc
+1);
268 /* Decode instruction. */
269 if (inst
& (1 << 15))
271 if (inst
& (1 << 14))
273 /* This is a Form 3 instruction. */
274 int opcode
= (inst
>> 10 & 0xf);
280 MOXIE_TRACE_INSN ("beq");
281 if (cpu
.asregs
.cc
& CC_EQ
)
282 pc
+= INST2OFFSET(inst
);
287 MOXIE_TRACE_INSN ("bne");
288 if (! (cpu
.asregs
.cc
& CC_EQ
))
289 pc
+= INST2OFFSET(inst
);
294 MOXIE_TRACE_INSN ("blt");
295 if (cpu
.asregs
.cc
& CC_LT
)
296 pc
+= INST2OFFSET(inst
);
300 MOXIE_TRACE_INSN ("bgt");
301 if (cpu
.asregs
.cc
& CC_GT
)
302 pc
+= INST2OFFSET(inst
);
305 case 0x04: /* bltu */
307 MOXIE_TRACE_INSN ("bltu");
308 if (cpu
.asregs
.cc
& CC_LTU
)
309 pc
+= INST2OFFSET(inst
);
312 case 0x05: /* bgtu */
314 MOXIE_TRACE_INSN ("bgtu");
315 if (cpu
.asregs
.cc
& CC_GTU
)
316 pc
+= INST2OFFSET(inst
);
321 MOXIE_TRACE_INSN ("bge");
322 if (cpu
.asregs
.cc
& (CC_GT
| CC_EQ
))
323 pc
+= INST2OFFSET(inst
);
328 MOXIE_TRACE_INSN ("ble");
329 if (cpu
.asregs
.cc
& (CC_LT
| CC_EQ
))
330 pc
+= INST2OFFSET(inst
);
333 case 0x08: /* bgeu */
335 MOXIE_TRACE_INSN ("bgeu");
336 if (cpu
.asregs
.cc
& (CC_GTU
| CC_EQ
))
337 pc
+= INST2OFFSET(inst
);
340 case 0x09: /* bleu */
342 MOXIE_TRACE_INSN ("bleu");
343 if (cpu
.asregs
.cc
& (CC_LTU
| CC_EQ
))
344 pc
+= INST2OFFSET(inst
);
349 MOXIE_TRACE_INSN ("SIGILL3");
350 sim_engine_halt (sd
, scpu
, NULL
, pc
, sim_stopped
, SIM_SIGILL
);
357 /* This is a Form 2 instruction. */
358 int opcode
= (inst
>> 12 & 0x3);
363 int a
= (inst
>> 8) & 0xf;
364 unsigned av
= cpu
.asregs
.regs
[a
];
365 unsigned v
= (inst
& 0xff);
367 MOXIE_TRACE_INSN ("inc");
368 cpu
.asregs
.regs
[a
] = av
+ v
;
373 int a
= (inst
>> 8) & 0xf;
374 unsigned av
= cpu
.asregs
.regs
[a
];
375 unsigned v
= (inst
& 0xff);
377 MOXIE_TRACE_INSN ("dec");
378 cpu
.asregs
.regs
[a
] = av
- v
;
383 int a
= (inst
>> 8) & 0xf;
384 unsigned v
= (inst
& 0xff);
386 MOXIE_TRACE_INSN ("gsr");
387 cpu
.asregs
.regs
[a
] = cpu
.asregs
.sregs
[v
];
392 int a
= (inst
>> 8) & 0xf;
393 unsigned v
= (inst
& 0xff);
395 MOXIE_TRACE_INSN ("ssr");
396 cpu
.asregs
.sregs
[v
] = cpu
.asregs
.regs
[a
];
400 MOXIE_TRACE_INSN ("SIGILL2");
401 sim_engine_halt (sd
, scpu
, NULL
, pc
, sim_stopped
, SIM_SIGILL
);
408 /* This is a Form 1 instruction. */
409 int opcode
= inst
>> 8;
414 MOXIE_TRACE_INSN ("SIGILL0");
415 sim_engine_halt (sd
, scpu
, NULL
, pc
, sim_stopped
, SIM_SIGILL
);
417 case 0x01: /* ldi.l (immediate) */
419 int reg
= (inst
>> 4) & 0xf;
420 unsigned int val
= EXTRACT_WORD(pc
+2);
422 MOXIE_TRACE_INSN ("ldi.l");
423 cpu
.asregs
.regs
[reg
] = val
;
427 case 0x02: /* mov (register-to-register) */
429 int dest
= (inst
>> 4) & 0xf;
430 int src
= (inst
) & 0xf;
432 MOXIE_TRACE_INSN ("mov");
433 cpu
.asregs
.regs
[dest
] = cpu
.asregs
.regs
[src
];
436 case 0x03: /* jsra */
438 unsigned int fn
= EXTRACT_WORD(pc
+2);
439 unsigned int sp
= cpu
.asregs
.regs
[1];
441 MOXIE_TRACE_INSN ("jsra");
442 /* Save a slot for the static chain. */
445 /* Push the return address. */
447 wlat (scpu
, opc
, sp
, pc
+ 6);
449 /* Push the current frame pointer. */
451 wlat (scpu
, opc
, sp
, cpu
.asregs
.regs
[0]);
453 /* Uncache the stack pointer and set the pc and $fp. */
454 cpu
.asregs
.regs
[1] = sp
;
455 cpu
.asregs
.regs
[0] = sp
;
461 unsigned int sp
= cpu
.asregs
.regs
[0];
463 MOXIE_TRACE_INSN ("ret");
465 /* Pop the frame pointer. */
466 cpu
.asregs
.regs
[0] = rlat (scpu
, opc
, sp
);
469 /* Pop the return address. */
470 pc
= rlat (scpu
, opc
, sp
) - 2;
473 /* Skip over the static chain slot. */
476 /* Uncache the stack pointer. */
477 cpu
.asregs
.regs
[1] = sp
;
480 case 0x05: /* add.l */
482 int a
= (inst
>> 4) & 0xf;
484 unsigned av
= cpu
.asregs
.regs
[a
];
485 unsigned bv
= cpu
.asregs
.regs
[b
];
487 MOXIE_TRACE_INSN ("add.l");
488 cpu
.asregs
.regs
[a
] = av
+ bv
;
491 case 0x06: /* push */
493 int a
= (inst
>> 4) & 0xf;
495 int sp
= cpu
.asregs
.regs
[a
] - 4;
497 MOXIE_TRACE_INSN ("push");
498 wlat (scpu
, opc
, sp
, cpu
.asregs
.regs
[b
]);
499 cpu
.asregs
.regs
[a
] = sp
;
504 int a
= (inst
>> 4) & 0xf;
506 int sp
= cpu
.asregs
.regs
[a
];
508 MOXIE_TRACE_INSN ("pop");
509 cpu
.asregs
.regs
[b
] = rlat (scpu
, opc
, sp
);
510 cpu
.asregs
.regs
[a
] = sp
+ 4;
513 case 0x08: /* lda.l */
515 int reg
= (inst
>> 4) & 0xf;
516 unsigned int addr
= EXTRACT_WORD(pc
+2);
518 MOXIE_TRACE_INSN ("lda.l");
519 cpu
.asregs
.regs
[reg
] = rlat (scpu
, opc
, addr
);
523 case 0x09: /* sta.l */
525 int reg
= (inst
>> 4) & 0xf;
526 unsigned int addr
= EXTRACT_WORD(pc
+2);
528 MOXIE_TRACE_INSN ("sta.l");
529 wlat (scpu
, opc
, addr
, cpu
.asregs
.regs
[reg
]);
533 case 0x0a: /* ld.l (register indirect) */
535 int src
= inst
& 0xf;
536 int dest
= (inst
>> 4) & 0xf;
539 MOXIE_TRACE_INSN ("ld.l");
540 xv
= cpu
.asregs
.regs
[src
];
541 cpu
.asregs
.regs
[dest
] = rlat (scpu
, opc
, xv
);
544 case 0x0b: /* st.l */
546 int dest
= (inst
>> 4) & 0xf;
547 int val
= inst
& 0xf;
549 MOXIE_TRACE_INSN ("st.l");
550 wlat (scpu
, opc
, cpu
.asregs
.regs
[dest
], cpu
.asregs
.regs
[val
]);
553 case 0x0c: /* ldo.l */
555 unsigned int addr
= EXTRACT_OFFSET(pc
+2);
556 int a
= (inst
>> 4) & 0xf;
559 MOXIE_TRACE_INSN ("ldo.l");
560 addr
+= cpu
.asregs
.regs
[b
];
561 cpu
.asregs
.regs
[a
] = rlat (scpu
, opc
, addr
);
565 case 0x0d: /* sto.l */
567 unsigned int addr
= EXTRACT_OFFSET(pc
+2);
568 int a
= (inst
>> 4) & 0xf;
571 MOXIE_TRACE_INSN ("sto.l");
572 addr
+= cpu
.asregs
.regs
[a
];
573 wlat (scpu
, opc
, addr
, cpu
.asregs
.regs
[b
]);
579 int a
= (inst
>> 4) & 0xf;
582 int va
= cpu
.asregs
.regs
[a
];
583 int vb
= cpu
.asregs
.regs
[b
];
585 MOXIE_TRACE_INSN ("cmp");
590 cc
|= (va
< vb
? CC_LT
: 0);
591 cc
|= (va
> vb
? CC_GT
: 0);
592 cc
|= ((unsigned int) va
< (unsigned int) vb
? CC_LTU
: 0);
593 cc
|= ((unsigned int) va
> (unsigned int) vb
? CC_GTU
: 0);
601 case 0x10: /* sex.b */
603 int a
= (inst
>> 4) & 0xf;
605 signed char bv
= cpu
.asregs
.regs
[b
];
607 MOXIE_TRACE_INSN ("sex.b");
608 cpu
.asregs
.regs
[a
] = (int) bv
;
611 case 0x11: /* sex.s */
613 int a
= (inst
>> 4) & 0xf;
615 signed short bv
= cpu
.asregs
.regs
[b
];
617 MOXIE_TRACE_INSN ("sex.s");
618 cpu
.asregs
.regs
[a
] = (int) bv
;
621 case 0x12: /* zex.b */
623 int a
= (inst
>> 4) & 0xf;
625 signed char bv
= cpu
.asregs
.regs
[b
];
627 MOXIE_TRACE_INSN ("zex.b");
628 cpu
.asregs
.regs
[a
] = (int) bv
& 0xff;
631 case 0x13: /* zex.s */
633 int a
= (inst
>> 4) & 0xf;
635 signed short bv
= cpu
.asregs
.regs
[b
];
637 MOXIE_TRACE_INSN ("zex.s");
638 cpu
.asregs
.regs
[a
] = (int) bv
& 0xffff;
641 case 0x14: /* umul.x */
643 int a
= (inst
>> 4) & 0xf;
645 unsigned av
= cpu
.asregs
.regs
[a
];
646 unsigned bv
= cpu
.asregs
.regs
[b
];
647 unsigned long long r
=
648 (unsigned long long) av
* (unsigned long long) bv
;
650 MOXIE_TRACE_INSN ("umul.x");
651 cpu
.asregs
.regs
[a
] = r
>> 32;
654 case 0x15: /* mul.x */
656 int a
= (inst
>> 4) & 0xf;
658 unsigned av
= cpu
.asregs
.regs
[a
];
659 unsigned bv
= cpu
.asregs
.regs
[b
];
661 (signed long long) av
* (signed long long) bv
;
663 MOXIE_TRACE_INSN ("mul.x");
664 cpu
.asregs
.regs
[a
] = r
>> 32;
672 MOXIE_TRACE_INSN ("SIGILL0");
673 sim_engine_halt (sd
, scpu
, NULL
, pc
, sim_stopped
, SIM_SIGILL
);
678 unsigned int fn
= cpu
.asregs
.regs
[(inst
>> 4) & 0xf];
679 unsigned int sp
= cpu
.asregs
.regs
[1];
681 MOXIE_TRACE_INSN ("jsr");
683 /* Save a slot for the static chain. */
686 /* Push the return address. */
688 wlat (scpu
, opc
, sp
, pc
+ 2);
690 /* Push the current frame pointer. */
692 wlat (scpu
, opc
, sp
, cpu
.asregs
.regs
[0]);
694 /* Uncache the stack pointer and set the fp & pc. */
695 cpu
.asregs
.regs
[1] = sp
;
696 cpu
.asregs
.regs
[0] = sp
;
700 case 0x1a: /* jmpa */
702 unsigned int tgt
= EXTRACT_WORD(pc
+2);
704 MOXIE_TRACE_INSN ("jmpa");
708 case 0x1b: /* ldi.b (immediate) */
710 int reg
= (inst
>> 4) & 0xf;
711 unsigned int val
= EXTRACT_WORD(pc
+2);
713 MOXIE_TRACE_INSN ("ldi.b");
714 cpu
.asregs
.regs
[reg
] = val
;
718 case 0x1c: /* ld.b (register indirect) */
720 int src
= inst
& 0xf;
721 int dest
= (inst
>> 4) & 0xf;
724 MOXIE_TRACE_INSN ("ld.b");
725 xv
= cpu
.asregs
.regs
[src
];
726 cpu
.asregs
.regs
[dest
] = rbat (scpu
, opc
, xv
);
729 case 0x1d: /* lda.b */
731 int reg
= (inst
>> 4) & 0xf;
732 unsigned int addr
= EXTRACT_WORD(pc
+2);
734 MOXIE_TRACE_INSN ("lda.b");
735 cpu
.asregs
.regs
[reg
] = rbat (scpu
, opc
, addr
);
739 case 0x1e: /* st.b */
741 int dest
= (inst
>> 4) & 0xf;
742 int val
= inst
& 0xf;
744 MOXIE_TRACE_INSN ("st.b");
745 wbat (scpu
, opc
, cpu
.asregs
.regs
[dest
], cpu
.asregs
.regs
[val
]);
748 case 0x1f: /* sta.b */
750 int reg
= (inst
>> 4) & 0xf;
751 unsigned int addr
= EXTRACT_WORD(pc
+2);
753 MOXIE_TRACE_INSN ("sta.b");
754 wbat (scpu
, opc
, addr
, cpu
.asregs
.regs
[reg
]);
758 case 0x20: /* ldi.s (immediate) */
760 int reg
= (inst
>> 4) & 0xf;
762 unsigned int val
= EXTRACT_WORD(pc
+2);
764 MOXIE_TRACE_INSN ("ldi.s");
765 cpu
.asregs
.regs
[reg
] = val
;
769 case 0x21: /* ld.s (register indirect) */
771 int src
= inst
& 0xf;
772 int dest
= (inst
>> 4) & 0xf;
775 MOXIE_TRACE_INSN ("ld.s");
776 xv
= cpu
.asregs
.regs
[src
];
777 cpu
.asregs
.regs
[dest
] = rsat (scpu
, opc
, xv
);
780 case 0x22: /* lda.s */
782 int reg
= (inst
>> 4) & 0xf;
783 unsigned int addr
= EXTRACT_WORD(pc
+2);
785 MOXIE_TRACE_INSN ("lda.s");
786 cpu
.asregs
.regs
[reg
] = rsat (scpu
, opc
, addr
);
790 case 0x23: /* st.s */
792 int dest
= (inst
>> 4) & 0xf;
793 int val
= inst
& 0xf;
795 MOXIE_TRACE_INSN ("st.s");
796 wsat (scpu
, opc
, cpu
.asregs
.regs
[dest
], cpu
.asregs
.regs
[val
]);
799 case 0x24: /* sta.s */
801 int reg
= (inst
>> 4) & 0xf;
802 unsigned int addr
= EXTRACT_WORD(pc
+2);
804 MOXIE_TRACE_INSN ("sta.s");
805 wsat (scpu
, opc
, addr
, cpu
.asregs
.regs
[reg
]);
811 int reg
= (inst
>> 4) & 0xf;
813 MOXIE_TRACE_INSN ("jmp");
814 pc
= cpu
.asregs
.regs
[reg
] - 2;
819 int a
= (inst
>> 4) & 0xf;
823 MOXIE_TRACE_INSN ("and");
824 av
= cpu
.asregs
.regs
[a
];
825 bv
= cpu
.asregs
.regs
[b
];
826 cpu
.asregs
.regs
[a
] = av
& bv
;
829 case 0x27: /* lshr */
831 int a
= (inst
>> 4) & 0xf;
833 int av
= cpu
.asregs
.regs
[a
];
834 int bv
= cpu
.asregs
.regs
[b
];
836 MOXIE_TRACE_INSN ("lshr");
837 cpu
.asregs
.regs
[a
] = (unsigned) ((unsigned) av
>> bv
);
840 case 0x28: /* ashl */
842 int a
= (inst
>> 4) & 0xf;
844 int av
= cpu
.asregs
.regs
[a
];
845 int bv
= cpu
.asregs
.regs
[b
];
847 MOXIE_TRACE_INSN ("ashl");
848 cpu
.asregs
.regs
[a
] = av
<< bv
;
851 case 0x29: /* sub.l */
853 int a
= (inst
>> 4) & 0xf;
855 unsigned av
= cpu
.asregs
.regs
[a
];
856 unsigned bv
= cpu
.asregs
.regs
[b
];
858 MOXIE_TRACE_INSN ("sub.l");
859 cpu
.asregs
.regs
[a
] = av
- bv
;
864 int a
= (inst
>> 4) & 0xf;
866 int bv
= cpu
.asregs
.regs
[b
];
868 MOXIE_TRACE_INSN ("neg");
869 cpu
.asregs
.regs
[a
] = - bv
;
874 int a
= (inst
>> 4) & 0xf;
878 MOXIE_TRACE_INSN ("or");
879 av
= cpu
.asregs
.regs
[a
];
880 bv
= cpu
.asregs
.regs
[b
];
881 cpu
.asregs
.regs
[a
] = av
| bv
;
886 int a
= (inst
>> 4) & 0xf;
888 int bv
= cpu
.asregs
.regs
[b
];
890 MOXIE_TRACE_INSN ("not");
891 cpu
.asregs
.regs
[a
] = 0xffffffff ^ bv
;
894 case 0x2d: /* ashr */
896 int a
= (inst
>> 4) & 0xf;
898 int av
= cpu
.asregs
.regs
[a
];
899 int bv
= cpu
.asregs
.regs
[b
];
901 MOXIE_TRACE_INSN ("ashr");
902 cpu
.asregs
.regs
[a
] = av
>> bv
;
907 int a
= (inst
>> 4) & 0xf;
911 MOXIE_TRACE_INSN ("xor");
912 av
= cpu
.asregs
.regs
[a
];
913 bv
= cpu
.asregs
.regs
[b
];
914 cpu
.asregs
.regs
[a
] = av
^ bv
;
917 case 0x2f: /* mul.l */
919 int a
= (inst
>> 4) & 0xf;
921 unsigned av
= cpu
.asregs
.regs
[a
];
922 unsigned bv
= cpu
.asregs
.regs
[b
];
924 MOXIE_TRACE_INSN ("mul.l");
925 cpu
.asregs
.regs
[a
] = av
* bv
;
930 unsigned int inum
= EXTRACT_WORD(pc
+2);
932 MOXIE_TRACE_INSN ("swi");
933 /* Set the special registers appropriately. */
934 cpu
.asregs
.sregs
[2] = 3; /* MOXIE_EX_SWI */
935 cpu
.asregs
.sregs
[3] = inum
;
938 case TARGET_SYS_exit
:
940 sim_engine_halt (sd
, scpu
, NULL
, pc
, sim_exited
,
944 case TARGET_SYS_open
:
947 int mode
= (int) convert_target_flags ((unsigned) cpu
.asregs
.regs
[3]);
948 int perm
= (int) cpu
.asregs
.regs
[4];
950 sim_core_read_buffer (sd
, scpu
, read_map
, fname
,
951 cpu
.asregs
.regs
[2], 1024);
952 fd
= sim_io_open (sd
, fname
, mode
);
953 /* FIXME - set errno */
954 cpu
.asregs
.regs
[2] = fd
;
957 case TARGET_SYS_read
:
959 int fd
= cpu
.asregs
.regs
[2];
960 unsigned len
= (unsigned) cpu
.asregs
.regs
[4];
961 char *buf
= malloc (len
);
962 cpu
.asregs
.regs
[2] = sim_io_read (sd
, fd
, buf
, len
);
963 sim_core_write_buffer (sd
, scpu
, write_map
, buf
,
964 cpu
.asregs
.regs
[3], len
);
968 case TARGET_SYS_write
:
971 /* String length is at 0x12($fp) */
972 unsigned count
, len
= (unsigned) cpu
.asregs
.regs
[4];
974 sim_core_read_buffer (sd
, scpu
, read_map
, str
,
975 cpu
.asregs
.regs
[3], len
);
976 count
= sim_io_write (sd
, cpu
.asregs
.regs
[2], str
, len
);
978 cpu
.asregs
.regs
[2] = count
;
981 case TARGET_SYS_unlink
:
985 sim_core_read_buffer (sd
, scpu
, read_map
, fname
,
986 cpu
.asregs
.regs
[2], 1024);
987 fd
= sim_io_unlink (sd
, fname
);
988 /* FIXME - set errno */
989 cpu
.asregs
.regs
[2] = fd
;
992 case 0xffffffff: /* Linux System Call */
994 unsigned int handler
= cpu
.asregs
.sregs
[1];
995 unsigned int sp
= cpu
.asregs
.regs
[1];
997 /* Save a slot for the static chain. */
1000 /* Push the return address. */
1002 wlat (scpu
, opc
, sp
, pc
+ 6);
1004 /* Push the current frame pointer. */
1006 wlat (scpu
, opc
, sp
, cpu
.asregs
.regs
[0]);
1008 /* Uncache the stack pointer and set the fp & pc. */
1009 cpu
.asregs
.regs
[1] = sp
;
1010 cpu
.asregs
.regs
[0] = sp
;
1019 case 0x31: /* div.l */
1021 int a
= (inst
>> 4) & 0xf;
1023 int av
= cpu
.asregs
.regs
[a
];
1024 int bv
= cpu
.asregs
.regs
[b
];
1026 MOXIE_TRACE_INSN ("div.l");
1027 cpu
.asregs
.regs
[a
] = av
/ bv
;
1030 case 0x32: /* udiv.l */
1032 int a
= (inst
>> 4) & 0xf;
1034 unsigned int av
= cpu
.asregs
.regs
[a
];
1035 unsigned int bv
= cpu
.asregs
.regs
[b
];
1037 MOXIE_TRACE_INSN ("udiv.l");
1038 cpu
.asregs
.regs
[a
] = (av
/ bv
);
1041 case 0x33: /* mod.l */
1043 int a
= (inst
>> 4) & 0xf;
1045 int av
= cpu
.asregs
.regs
[a
];
1046 int bv
= cpu
.asregs
.regs
[b
];
1048 MOXIE_TRACE_INSN ("mod.l");
1049 cpu
.asregs
.regs
[a
] = av
% bv
;
1052 case 0x34: /* umod.l */
1054 int a
= (inst
>> 4) & 0xf;
1056 unsigned int av
= cpu
.asregs
.regs
[a
];
1057 unsigned int bv
= cpu
.asregs
.regs
[b
];
1059 MOXIE_TRACE_INSN ("umod.l");
1060 cpu
.asregs
.regs
[a
] = (av
% bv
);
1063 case 0x35: /* brk */
1064 MOXIE_TRACE_INSN ("brk");
1065 sim_engine_halt (sd
, scpu
, NULL
, pc
, sim_stopped
, SIM_SIGTRAP
);
1066 pc
-= 2; /* Adjust pc */
1068 case 0x36: /* ldo.b */
1070 unsigned int addr
= EXTRACT_OFFSET(pc
+2);
1071 int a
= (inst
>> 4) & 0xf;
1074 MOXIE_TRACE_INSN ("ldo.b");
1075 addr
+= cpu
.asregs
.regs
[b
];
1076 cpu
.asregs
.regs
[a
] = rbat (scpu
, opc
, addr
);
1080 case 0x37: /* sto.b */
1082 unsigned int addr
= EXTRACT_OFFSET(pc
+2);
1083 int a
= (inst
>> 4) & 0xf;
1086 MOXIE_TRACE_INSN ("sto.b");
1087 addr
+= cpu
.asregs
.regs
[a
];
1088 wbat (scpu
, opc
, addr
, cpu
.asregs
.regs
[b
]);
1092 case 0x38: /* ldo.s */
1094 unsigned int addr
= EXTRACT_OFFSET(pc
+2);
1095 int a
= (inst
>> 4) & 0xf;
1098 MOXIE_TRACE_INSN ("ldo.s");
1099 addr
+= cpu
.asregs
.regs
[b
];
1100 cpu
.asregs
.regs
[a
] = rsat (scpu
, opc
, addr
);
1104 case 0x39: /* sto.s */
1106 unsigned int addr
= EXTRACT_OFFSET(pc
+2);
1107 int a
= (inst
>> 4) & 0xf;
1110 MOXIE_TRACE_INSN ("sto.s");
1111 addr
+= cpu
.asregs
.regs
[a
];
1112 wsat (scpu
, opc
, addr
, cpu
.asregs
.regs
[b
]);
1118 MOXIE_TRACE_INSN ("SIGILL1");
1119 sim_engine_halt (sd
, scpu
, NULL
, pc
, sim_stopped
, SIM_SIGILL
);
1126 cpu
.asregs
.regs
[PC_REGNO
] = pc
;
1128 if (sim_events_tick (sd
))
1129 sim_events_process (sd
);
1135 moxie_reg_store (SIM_CPU
*scpu
, int rn
, unsigned char *memory
, int length
)
1137 if (rn
< NUM_MOXIE_REGS
&& rn
>= 0)
1143 /* misalignment safe */
1144 ival
= moxie_extract_unsigned_integer (memory
, 4);
1145 cpu
.asints
[rn
] = ival
;
1155 moxie_reg_fetch (SIM_CPU
*scpu
, int rn
, unsigned char *memory
, int length
)
1157 if (rn
< NUM_MOXIE_REGS
&& rn
>= 0)
1161 long ival
= cpu
.asints
[rn
];
1163 /* misalignment-safe */
1164 moxie_store_unsigned_integer (memory
, 4, ival
);
1174 moxie_pc_get (sim_cpu
*cpu
)
1176 return cpu
->registers
[PCIDX
];
1180 moxie_pc_set (sim_cpu
*cpu
, sim_cia pc
)
1182 cpu
->registers
[PCIDX
] = pc
;
1186 free_state (SIM_DESC sd
)
1188 if (STATE_MODULES (sd
) != NULL
)
1189 sim_module_uninstall (sd
);
1190 sim_cpu_free_all (sd
);
1191 sim_state_free (sd
);
1195 sim_open (SIM_OPEN_KIND kind
, host_callback
*cb
,
1196 struct bfd
*abfd
, char * const *argv
)
1199 SIM_DESC sd
= sim_state_alloc (kind
, cb
);
1200 SIM_ASSERT (STATE_MAGIC (sd
) == SIM_MAGIC_NUMBER
);
1202 /* Set default options before parsing user options. */
1203 current_target_byte_order
= BFD_ENDIAN_BIG
;
1205 /* The cpu data is kept in a separately allocated chunk of memory. */
1206 if (sim_cpu_alloc_all (sd
, 1) != SIM_RC_OK
)
1212 if (sim_pre_argv_init (sd
, argv
[0]) != SIM_RC_OK
)
1218 /* The parser will print an error message for us, so we silently return. */
1219 if (sim_parse_args (sd
, argv
) != SIM_RC_OK
)
1225 sim_do_command(sd
," memory region 0x00000000,0x4000000") ;
1226 sim_do_command(sd
," memory region 0xE0000000,0x10000") ;
1228 /* Check for/establish the a reference program image. */
1229 if (sim_analyze_program (sd
,
1230 (STATE_PROG_ARGV (sd
) != NULL
1231 ? *STATE_PROG_ARGV (sd
)
1232 : NULL
), abfd
) != SIM_RC_OK
)
1238 /* Configure/verify the target byte order and other runtime
1239 configuration options. */
1240 if (sim_config (sd
) != SIM_RC_OK
)
1242 sim_module_uninstall (sd
);
1246 if (sim_post_argv_init (sd
) != SIM_RC_OK
)
1248 /* Uninstall the modules to avoid memory leaks,
1249 file descriptor leaks, etc. */
1250 sim_module_uninstall (sd
);
1254 /* CPU specific initialization. */
1255 for (i
= 0; i
< MAX_NR_PROCESSORS
; ++i
)
1257 SIM_CPU
*cpu
= STATE_CPU (sd
, i
);
1259 CPU_REG_FETCH (cpu
) = moxie_reg_fetch
;
1260 CPU_REG_STORE (cpu
) = moxie_reg_store
;
1261 CPU_PC_FETCH (cpu
) = moxie_pc_get
;
1262 CPU_PC_STORE (cpu
) = moxie_pc_set
;
1264 set_initial_gprs (); /* Reset the GPR registers. */
1270 /* Load the device tree blob. */
1273 load_dtb (SIM_DESC sd
, const char *filename
)
1276 FILE *f
= fopen (filename
, "rb");
1278 sim_cpu
*scpu
= STATE_CPU (sd
, 0); /* FIXME */
1280 /* Don't warn as the sim works fine w/out a device tree. */
1283 fseek (f
, 0, SEEK_END
);
1285 fseek (f
, 0, SEEK_SET
);
1286 buf
= alloca (size
);
1287 if (size
!= fread (buf
, 1, size
, f
))
1289 sim_io_eprintf (sd
, "ERROR: error reading ``%s''.\n", filename
);
1293 sim_core_write_buffer (sd
, scpu
, write_map
, buf
, 0xE0000000, size
);
1294 cpu
.asregs
.sregs
[9] = 0xE0000000;
1299 sim_create_inferior (SIM_DESC sd
, struct bfd
*prog_bfd
,
1300 char * const *argv
, char * const *env
)
1304 sim_cpu
*scpu
= STATE_CPU (sd
, 0); /* FIXME */
1306 if (prog_bfd
!= NULL
)
1307 cpu
.asregs
.regs
[PC_REGNO
] = bfd_get_start_address (prog_bfd
);
1309 /* Copy args into target memory. */
1311 for (argc
= 0; avp
&& *avp
; avp
++)
1314 /* Target memory looks like this:
1315 0x00000000 zero word
1316 0x00000004 argc word
1317 0x00000008 start of argv
1319 0x0000???? end of argv
1320 0x0000???? zero word
1321 0x0000???? start of data pointed to by argv */
1323 wlat (scpu
, 0, 0, 0);
1324 wlat (scpu
, 0, 4, argc
);
1326 /* tp is the offset of our first argv data. */
1327 tp
= 4 + 4 + argc
* 4 + 4;
1329 for (i
= 0; i
< argc
; i
++)
1331 /* Set the argv value. */
1332 wlat (scpu
, 0, 4 + 4 + i
* 4, tp
);
1334 /* Store the string. */
1335 sim_core_write_buffer (sd
, scpu
, write_map
, argv
[i
],
1336 tp
, strlen(argv
[i
])+1);
1337 tp
+= strlen (argv
[i
]) + 1;
1340 wlat (scpu
, 0, 4 + 4 + i
* 4, 0);