]>
git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - sim/moxie/interp.c
417ff9ea55033716e04c4b91f5441f62a0b762e3
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/>. */
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"
36 #include "targ-vals.h"
39 typedef unsigned int uword
;
41 /* Extract the signed 10-bit offset from a 16-bit branch
43 #define INST2OFFSET(o) ((((signed short)((o & ((1<<10)-1))<<6))>>6)<<1)
45 #define EXTRACT_WORD(addr) \
46 ((sim_core_read_aligned_1 (scpu, cia, read_map, addr) << 24) \
47 + (sim_core_read_aligned_1 (scpu, cia, read_map, addr+1) << 16) \
48 + (sim_core_read_aligned_1 (scpu, cia, read_map, addr+2) << 8) \
49 + (sim_core_read_aligned_1 (scpu, cia, read_map, addr+3)))
51 #define EXTRACT_OFFSET(addr) \
54 ((sim_core_read_aligned_1 (scpu, cia, read_map, addr) << 8) \
55 + (sim_core_read_aligned_1 (scpu, cia, read_map, addr+1))) << 16) >> 16)
58 moxie_extract_unsigned_integer (unsigned char *addr
, int len
)
62 unsigned char * startaddr
= (unsigned char *)addr
;
63 unsigned char * endaddr
= startaddr
+ len
;
65 if (len
> (int) sizeof (unsigned long))
66 printf ("That operation is not available on integers of more than %zu bytes.",
67 sizeof (unsigned long));
69 /* Start at the most significant end of the integer, and work towards
70 the least significant. */
73 for (p
= endaddr
; p
> startaddr
;)
74 retval
= (retval
<< 8) | * -- p
;
80 moxie_store_unsigned_integer (unsigned char *addr
, int len
, unsigned long val
)
83 unsigned char * startaddr
= (unsigned char *)addr
;
84 unsigned char * endaddr
= startaddr
+ len
;
86 for (p
= endaddr
; p
> startaddr
;)
93 /* moxie register names. */
94 static const char *reg_names
[16] =
95 { "$fp", "$sp", "$r0", "$r1", "$r2", "$r3", "$r4", "$r5",
96 "$r6", "$r7", "$r8", "$r9", "$r10", "$r11", "$r12", "$r13" };
100 This state is maintained in host byte order. The fetch/store
101 register functions must translate between host byte order and the
102 target processor byte order. Keeping this data in target byte
103 order simplifies the register read/write functions. Keeping this
104 data in native order improves the performance of the simulator.
105 Simulation speed is deemed more important. */
107 #define NUM_MOXIE_REGS 17 /* Including PC */
108 #define NUM_MOXIE_SREGS 256 /* The special registers */
111 /* The ordering of the moxie_regset structure is matched in the
112 gdb/config/moxie/tm-moxie.h file in the REGISTER_NAMES macro. */
113 /* TODO: This should be moved to sim-main.h:_sim_cpu. */
116 word regs
[NUM_MOXIE_REGS
+ 1]; /* primary registers */
117 word sregs
[256]; /* special registers */
118 word cc
; /* the condition code reg */
119 unsigned long long insts
; /* instruction counter */
128 /* TODO: This should be moved to sim-main.h:_sim_cpu. */
131 struct moxie_regset asregs
;
132 word asints
[1]; /* but accessed larger... */
136 set_initial_gprs (void)
141 /* Set up machine just out of reset. */
142 cpu
.asregs
.regs
[PC_REGNO
] = 0;
144 /* Clean out the register contents. */
145 for (i
= 0; i
< NUM_MOXIE_REGS
; i
++)
146 cpu
.asregs
.regs
[i
] = 0;
147 for (i
= 0; i
< NUM_MOXIE_SREGS
; i
++)
148 cpu
.asregs
.sregs
[i
] = 0;
151 /* Write a 1 byte value to memory. */
154 wbat (sim_cpu
*scpu
, word pc
, word x
, word v
)
156 address_word cia
= CPU_PC_GET (scpu
);
158 sim_core_write_aligned_1 (scpu
, cia
, write_map
, x
, v
);
161 /* Write a 2 byte value to memory. */
164 wsat (sim_cpu
*scpu
, word pc
, word x
, word v
)
166 address_word cia
= CPU_PC_GET (scpu
);
168 sim_core_write_aligned_2 (scpu
, cia
, write_map
, x
, v
);
171 /* Write a 4 byte value to memory. */
174 wlat (sim_cpu
*scpu
, word pc
, word x
, word v
)
176 address_word cia
= CPU_PC_GET (scpu
);
178 sim_core_write_aligned_4 (scpu
, cia
, write_map
, x
, v
);
181 /* Read 2 bytes from memory. */
184 rsat (sim_cpu
*scpu
, word pc
, word x
)
186 address_word cia
= CPU_PC_GET (scpu
);
188 return (sim_core_read_aligned_2 (scpu
, cia
, read_map
, x
));
191 /* Read 1 byte from memory. */
194 rbat (sim_cpu
*scpu
, word pc
, word x
)
196 address_word cia
= CPU_PC_GET (scpu
);
198 return (sim_core_read_aligned_1 (scpu
, cia
, read_map
, x
));
201 /* Read 4 bytes from memory. */
204 rlat (sim_cpu
*scpu
, word pc
, word x
)
206 address_word cia
= CPU_PC_GET (scpu
);
208 return (sim_core_read_aligned_4 (scpu
, cia
, read_map
, x
));
211 #define CHECK_FLAG(T,H) if (tflags & T) { hflags |= H; tflags ^= T; }
214 convert_target_flags (unsigned int tflags
)
216 unsigned int hflags
= 0x0;
218 CHECK_FLAG(0x0001, O_WRONLY
);
219 CHECK_FLAG(0x0002, O_RDWR
);
220 CHECK_FLAG(0x0008, O_APPEND
);
221 CHECK_FLAG(0x0200, O_CREAT
);
222 CHECK_FLAG(0x0400, O_TRUNC
);
223 CHECK_FLAG(0x0800, O_EXCL
);
224 CHECK_FLAG(0x2000, O_SYNC
);
228 "Simulator Error: problem converting target open flags for host. 0x%x\n",
234 /* TODO: Split this up into finger trace levels than just insn. */
235 #define MOXIE_TRACE_INSN(str) \
236 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", \
237 opc, str, cpu.asregs.regs[0], cpu.asregs.regs[1], \
238 cpu.asregs.regs[2], cpu.asregs.regs[3], cpu.asregs.regs[4], \
239 cpu.asregs.regs[5], cpu.asregs.regs[6], cpu.asregs.regs[7], \
240 cpu.asregs.regs[8], cpu.asregs.regs[9], cpu.asregs.regs[10], \
241 cpu.asregs.regs[11], cpu.asregs.regs[12], cpu.asregs.regs[13], \
242 cpu.asregs.regs[14], cpu.asregs.regs[15])
245 sim_engine_run (SIM_DESC sd
,
246 int next_cpu_nr
, /* ignore */
247 int nr_cpus
, /* ignore */
248 int siggnal
) /* ignore */
252 sim_cpu
*scpu
= STATE_CPU (sd
, 0); /* FIXME */
253 address_word cia
= CPU_PC_GET (scpu
);
255 pc
= cpu
.asregs
.regs
[PC_REGNO
];
257 /* Run instructions here. */
262 /* Fetch the instruction at pc. */
263 inst
= (sim_core_read_aligned_1 (scpu
, cia
, read_map
, pc
) << 8)
264 + sim_core_read_aligned_1 (scpu
, cia
, read_map
, pc
+1);
266 /* Decode instruction. */
267 if (inst
& (1 << 15))
269 if (inst
& (1 << 14))
271 /* This is a Form 3 instruction. */
272 int opcode
= (inst
>> 10 & 0xf);
278 MOXIE_TRACE_INSN ("beq");
279 if (cpu
.asregs
.cc
& CC_EQ
)
280 pc
+= INST2OFFSET(inst
);
285 MOXIE_TRACE_INSN ("bne");
286 if (! (cpu
.asregs
.cc
& CC_EQ
))
287 pc
+= INST2OFFSET(inst
);
292 MOXIE_TRACE_INSN ("blt");
293 if (cpu
.asregs
.cc
& CC_LT
)
294 pc
+= INST2OFFSET(inst
);
298 MOXIE_TRACE_INSN ("bgt");
299 if (cpu
.asregs
.cc
& CC_GT
)
300 pc
+= INST2OFFSET(inst
);
303 case 0x04: /* bltu */
305 MOXIE_TRACE_INSN ("bltu");
306 if (cpu
.asregs
.cc
& CC_LTU
)
307 pc
+= INST2OFFSET(inst
);
310 case 0x05: /* bgtu */
312 MOXIE_TRACE_INSN ("bgtu");
313 if (cpu
.asregs
.cc
& CC_GTU
)
314 pc
+= INST2OFFSET(inst
);
319 MOXIE_TRACE_INSN ("bge");
320 if (cpu
.asregs
.cc
& (CC_GT
| CC_EQ
))
321 pc
+= INST2OFFSET(inst
);
326 MOXIE_TRACE_INSN ("ble");
327 if (cpu
.asregs
.cc
& (CC_LT
| CC_EQ
))
328 pc
+= INST2OFFSET(inst
);
331 case 0x08: /* bgeu */
333 MOXIE_TRACE_INSN ("bgeu");
334 if (cpu
.asregs
.cc
& (CC_GTU
| CC_EQ
))
335 pc
+= INST2OFFSET(inst
);
338 case 0x09: /* bleu */
340 MOXIE_TRACE_INSN ("bleu");
341 if (cpu
.asregs
.cc
& (CC_LTU
| CC_EQ
))
342 pc
+= INST2OFFSET(inst
);
347 MOXIE_TRACE_INSN ("SIGILL3");
348 sim_engine_halt (sd
, scpu
, NULL
, pc
, sim_stopped
, SIM_SIGILL
);
355 /* This is a Form 2 instruction. */
356 int opcode
= (inst
>> 12 & 0x3);
361 int a
= (inst
>> 8) & 0xf;
362 unsigned av
= cpu
.asregs
.regs
[a
];
363 unsigned v
= (inst
& 0xff);
365 MOXIE_TRACE_INSN ("inc");
366 cpu
.asregs
.regs
[a
] = av
+ v
;
371 int a
= (inst
>> 8) & 0xf;
372 unsigned av
= cpu
.asregs
.regs
[a
];
373 unsigned v
= (inst
& 0xff);
375 MOXIE_TRACE_INSN ("dec");
376 cpu
.asregs
.regs
[a
] = av
- v
;
381 int a
= (inst
>> 8) & 0xf;
382 unsigned v
= (inst
& 0xff);
384 MOXIE_TRACE_INSN ("gsr");
385 cpu
.asregs
.regs
[a
] = cpu
.asregs
.sregs
[v
];
390 int a
= (inst
>> 8) & 0xf;
391 unsigned v
= (inst
& 0xff);
393 MOXIE_TRACE_INSN ("ssr");
394 cpu
.asregs
.sregs
[v
] = cpu
.asregs
.regs
[a
];
398 MOXIE_TRACE_INSN ("SIGILL2");
399 sim_engine_halt (sd
, scpu
, NULL
, pc
, sim_stopped
, SIM_SIGILL
);
406 /* This is a Form 1 instruction. */
407 int opcode
= inst
>> 8;
412 MOXIE_TRACE_INSN ("SIGILL0");
413 sim_engine_halt (sd
, scpu
, NULL
, pc
, sim_stopped
, SIM_SIGILL
);
415 case 0x01: /* ldi.l (immediate) */
417 int reg
= (inst
>> 4) & 0xf;
418 unsigned int val
= EXTRACT_WORD(pc
+2);
420 MOXIE_TRACE_INSN ("ldi.l");
421 cpu
.asregs
.regs
[reg
] = val
;
425 case 0x02: /* mov (register-to-register) */
427 int dest
= (inst
>> 4) & 0xf;
428 int src
= (inst
) & 0xf;
430 MOXIE_TRACE_INSN ("mov");
431 cpu
.asregs
.regs
[dest
] = cpu
.asregs
.regs
[src
];
434 case 0x03: /* jsra */
436 unsigned int fn
= EXTRACT_WORD(pc
+2);
437 unsigned int sp
= cpu
.asregs
.regs
[1];
439 MOXIE_TRACE_INSN ("jsra");
440 /* Save a slot for the static chain. */
443 /* Push the return address. */
445 wlat (scpu
, opc
, sp
, pc
+ 6);
447 /* Push the current frame pointer. */
449 wlat (scpu
, opc
, sp
, cpu
.asregs
.regs
[0]);
451 /* Uncache the stack pointer and set the pc and $fp. */
452 cpu
.asregs
.regs
[1] = sp
;
453 cpu
.asregs
.regs
[0] = sp
;
459 unsigned int sp
= cpu
.asregs
.regs
[0];
461 MOXIE_TRACE_INSN ("ret");
463 /* Pop the frame pointer. */
464 cpu
.asregs
.regs
[0] = rlat (scpu
, opc
, sp
);
467 /* Pop the return address. */
468 pc
= rlat (scpu
, opc
, sp
) - 2;
471 /* Skip over the static chain slot. */
474 /* Uncache the stack pointer. */
475 cpu
.asregs
.regs
[1] = sp
;
478 case 0x05: /* add.l */
480 int a
= (inst
>> 4) & 0xf;
482 unsigned av
= cpu
.asregs
.regs
[a
];
483 unsigned bv
= cpu
.asregs
.regs
[b
];
485 MOXIE_TRACE_INSN ("add.l");
486 cpu
.asregs
.regs
[a
] = av
+ bv
;
489 case 0x06: /* push */
491 int a
= (inst
>> 4) & 0xf;
493 int sp
= cpu
.asregs
.regs
[a
] - 4;
495 MOXIE_TRACE_INSN ("push");
496 wlat (scpu
, opc
, sp
, cpu
.asregs
.regs
[b
]);
497 cpu
.asregs
.regs
[a
] = sp
;
502 int a
= (inst
>> 4) & 0xf;
504 int sp
= cpu
.asregs
.regs
[a
];
506 MOXIE_TRACE_INSN ("pop");
507 cpu
.asregs
.regs
[b
] = rlat (scpu
, opc
, sp
);
508 cpu
.asregs
.regs
[a
] = sp
+ 4;
511 case 0x08: /* lda.l */
513 int reg
= (inst
>> 4) & 0xf;
514 unsigned int addr
= EXTRACT_WORD(pc
+2);
516 MOXIE_TRACE_INSN ("lda.l");
517 cpu
.asregs
.regs
[reg
] = rlat (scpu
, opc
, addr
);
521 case 0x09: /* sta.l */
523 int reg
= (inst
>> 4) & 0xf;
524 unsigned int addr
= EXTRACT_WORD(pc
+2);
526 MOXIE_TRACE_INSN ("sta.l");
527 wlat (scpu
, opc
, addr
, cpu
.asregs
.regs
[reg
]);
531 case 0x0a: /* ld.l (register indirect) */
533 int src
= inst
& 0xf;
534 int dest
= (inst
>> 4) & 0xf;
537 MOXIE_TRACE_INSN ("ld.l");
538 xv
= cpu
.asregs
.regs
[src
];
539 cpu
.asregs
.regs
[dest
] = rlat (scpu
, opc
, xv
);
542 case 0x0b: /* st.l */
544 int dest
= (inst
>> 4) & 0xf;
545 int val
= inst
& 0xf;
547 MOXIE_TRACE_INSN ("st.l");
548 wlat (scpu
, opc
, cpu
.asregs
.regs
[dest
], cpu
.asregs
.regs
[val
]);
551 case 0x0c: /* ldo.l */
553 unsigned int addr
= EXTRACT_OFFSET(pc
+2);
554 int a
= (inst
>> 4) & 0xf;
557 MOXIE_TRACE_INSN ("ldo.l");
558 addr
+= cpu
.asregs
.regs
[b
];
559 cpu
.asregs
.regs
[a
] = rlat (scpu
, opc
, addr
);
563 case 0x0d: /* sto.l */
565 unsigned int addr
= EXTRACT_OFFSET(pc
+2);
566 int a
= (inst
>> 4) & 0xf;
569 MOXIE_TRACE_INSN ("sto.l");
570 addr
+= cpu
.asregs
.regs
[a
];
571 wlat (scpu
, opc
, addr
, cpu
.asregs
.regs
[b
]);
577 int a
= (inst
>> 4) & 0xf;
580 int va
= cpu
.asregs
.regs
[a
];
581 int vb
= cpu
.asregs
.regs
[b
];
583 MOXIE_TRACE_INSN ("cmp");
588 cc
|= (va
< vb
? CC_LT
: 0);
589 cc
|= (va
> vb
? CC_GT
: 0);
590 cc
|= ((unsigned int) va
< (unsigned int) vb
? CC_LTU
: 0);
591 cc
|= ((unsigned int) va
> (unsigned int) vb
? CC_GTU
: 0);
599 case 0x10: /* sex.b */
601 int a
= (inst
>> 4) & 0xf;
603 signed char bv
= cpu
.asregs
.regs
[b
];
605 MOXIE_TRACE_INSN ("sex.b");
606 cpu
.asregs
.regs
[a
] = (int) bv
;
609 case 0x11: /* sex.s */
611 int a
= (inst
>> 4) & 0xf;
613 signed short bv
= cpu
.asregs
.regs
[b
];
615 MOXIE_TRACE_INSN ("sex.s");
616 cpu
.asregs
.regs
[a
] = (int) bv
;
619 case 0x12: /* zex.b */
621 int a
= (inst
>> 4) & 0xf;
623 signed char bv
= cpu
.asregs
.regs
[b
];
625 MOXIE_TRACE_INSN ("zex.b");
626 cpu
.asregs
.regs
[a
] = (int) bv
& 0xff;
629 case 0x13: /* zex.s */
631 int a
= (inst
>> 4) & 0xf;
633 signed short bv
= cpu
.asregs
.regs
[b
];
635 MOXIE_TRACE_INSN ("zex.s");
636 cpu
.asregs
.regs
[a
] = (int) bv
& 0xffff;
639 case 0x14: /* umul.x */
641 int a
= (inst
>> 4) & 0xf;
643 unsigned av
= cpu
.asregs
.regs
[a
];
644 unsigned bv
= cpu
.asregs
.regs
[b
];
645 unsigned long long r
=
646 (unsigned long long) av
* (unsigned long long) bv
;
648 MOXIE_TRACE_INSN ("umul.x");
649 cpu
.asregs
.regs
[a
] = r
>> 32;
652 case 0x15: /* mul.x */
654 int a
= (inst
>> 4) & 0xf;
656 unsigned av
= cpu
.asregs
.regs
[a
];
657 unsigned bv
= cpu
.asregs
.regs
[b
];
659 (signed long long) av
* (signed long long) bv
;
661 MOXIE_TRACE_INSN ("mul.x");
662 cpu
.asregs
.regs
[a
] = r
>> 32;
670 MOXIE_TRACE_INSN ("SIGILL0");
671 sim_engine_halt (sd
, scpu
, NULL
, pc
, sim_stopped
, SIM_SIGILL
);
676 unsigned int fn
= cpu
.asregs
.regs
[(inst
>> 4) & 0xf];
677 unsigned int sp
= cpu
.asregs
.regs
[1];
679 MOXIE_TRACE_INSN ("jsr");
681 /* Save a slot for the static chain. */
684 /* Push the return address. */
686 wlat (scpu
, opc
, sp
, pc
+ 2);
688 /* Push the current frame pointer. */
690 wlat (scpu
, opc
, sp
, cpu
.asregs
.regs
[0]);
692 /* Uncache the stack pointer and set the fp & pc. */
693 cpu
.asregs
.regs
[1] = sp
;
694 cpu
.asregs
.regs
[0] = sp
;
698 case 0x1a: /* jmpa */
700 unsigned int tgt
= EXTRACT_WORD(pc
+2);
702 MOXIE_TRACE_INSN ("jmpa");
706 case 0x1b: /* ldi.b (immediate) */
708 int reg
= (inst
>> 4) & 0xf;
709 unsigned int val
= EXTRACT_WORD(pc
+2);
711 MOXIE_TRACE_INSN ("ldi.b");
712 cpu
.asregs
.regs
[reg
] = val
;
716 case 0x1c: /* ld.b (register indirect) */
718 int src
= inst
& 0xf;
719 int dest
= (inst
>> 4) & 0xf;
722 MOXIE_TRACE_INSN ("ld.b");
723 xv
= cpu
.asregs
.regs
[src
];
724 cpu
.asregs
.regs
[dest
] = rbat (scpu
, opc
, xv
);
727 case 0x1d: /* lda.b */
729 int reg
= (inst
>> 4) & 0xf;
730 unsigned int addr
= EXTRACT_WORD(pc
+2);
732 MOXIE_TRACE_INSN ("lda.b");
733 cpu
.asregs
.regs
[reg
] = rbat (scpu
, opc
, addr
);
737 case 0x1e: /* st.b */
739 int dest
= (inst
>> 4) & 0xf;
740 int val
= inst
& 0xf;
742 MOXIE_TRACE_INSN ("st.b");
743 wbat (scpu
, opc
, cpu
.asregs
.regs
[dest
], cpu
.asregs
.regs
[val
]);
746 case 0x1f: /* sta.b */
748 int reg
= (inst
>> 4) & 0xf;
749 unsigned int addr
= EXTRACT_WORD(pc
+2);
751 MOXIE_TRACE_INSN ("sta.b");
752 wbat (scpu
, opc
, addr
, cpu
.asregs
.regs
[reg
]);
756 case 0x20: /* ldi.s (immediate) */
758 int reg
= (inst
>> 4) & 0xf;
760 unsigned int val
= EXTRACT_WORD(pc
+2);
762 MOXIE_TRACE_INSN ("ldi.s");
763 cpu
.asregs
.regs
[reg
] = val
;
767 case 0x21: /* ld.s (register indirect) */
769 int src
= inst
& 0xf;
770 int dest
= (inst
>> 4) & 0xf;
773 MOXIE_TRACE_INSN ("ld.s");
774 xv
= cpu
.asregs
.regs
[src
];
775 cpu
.asregs
.regs
[dest
] = rsat (scpu
, opc
, xv
);
778 case 0x22: /* lda.s */
780 int reg
= (inst
>> 4) & 0xf;
781 unsigned int addr
= EXTRACT_WORD(pc
+2);
783 MOXIE_TRACE_INSN ("lda.s");
784 cpu
.asregs
.regs
[reg
] = rsat (scpu
, opc
, addr
);
788 case 0x23: /* st.s */
790 int dest
= (inst
>> 4) & 0xf;
791 int val
= inst
& 0xf;
793 MOXIE_TRACE_INSN ("st.s");
794 wsat (scpu
, opc
, cpu
.asregs
.regs
[dest
], cpu
.asregs
.regs
[val
]);
797 case 0x24: /* sta.s */
799 int reg
= (inst
>> 4) & 0xf;
800 unsigned int addr
= EXTRACT_WORD(pc
+2);
802 MOXIE_TRACE_INSN ("sta.s");
803 wsat (scpu
, opc
, addr
, cpu
.asregs
.regs
[reg
]);
809 int reg
= (inst
>> 4) & 0xf;
811 MOXIE_TRACE_INSN ("jmp");
812 pc
= cpu
.asregs
.regs
[reg
] - 2;
817 int a
= (inst
>> 4) & 0xf;
821 MOXIE_TRACE_INSN ("and");
822 av
= cpu
.asregs
.regs
[a
];
823 bv
= cpu
.asregs
.regs
[b
];
824 cpu
.asregs
.regs
[a
] = av
& bv
;
827 case 0x27: /* lshr */
829 int a
= (inst
>> 4) & 0xf;
831 int av
= cpu
.asregs
.regs
[a
];
832 int bv
= cpu
.asregs
.regs
[b
];
834 MOXIE_TRACE_INSN ("lshr");
835 cpu
.asregs
.regs
[a
] = (unsigned) ((unsigned) av
>> bv
);
838 case 0x28: /* ashl */
840 int a
= (inst
>> 4) & 0xf;
842 int av
= cpu
.asregs
.regs
[a
];
843 int bv
= cpu
.asregs
.regs
[b
];
845 MOXIE_TRACE_INSN ("ashl");
846 cpu
.asregs
.regs
[a
] = av
<< bv
;
849 case 0x29: /* sub.l */
851 int a
= (inst
>> 4) & 0xf;
853 unsigned av
= cpu
.asregs
.regs
[a
];
854 unsigned bv
= cpu
.asregs
.regs
[b
];
856 MOXIE_TRACE_INSN ("sub.l");
857 cpu
.asregs
.regs
[a
] = av
- bv
;
862 int a
= (inst
>> 4) & 0xf;
864 int bv
= cpu
.asregs
.regs
[b
];
866 MOXIE_TRACE_INSN ("neg");
867 cpu
.asregs
.regs
[a
] = - bv
;
872 int a
= (inst
>> 4) & 0xf;
876 MOXIE_TRACE_INSN ("or");
877 av
= cpu
.asregs
.regs
[a
];
878 bv
= cpu
.asregs
.regs
[b
];
879 cpu
.asregs
.regs
[a
] = av
| bv
;
884 int a
= (inst
>> 4) & 0xf;
886 int bv
= cpu
.asregs
.regs
[b
];
888 MOXIE_TRACE_INSN ("not");
889 cpu
.asregs
.regs
[a
] = 0xffffffff ^ bv
;
892 case 0x2d: /* ashr */
894 int a
= (inst
>> 4) & 0xf;
896 int av
= cpu
.asregs
.regs
[a
];
897 int bv
= cpu
.asregs
.regs
[b
];
899 MOXIE_TRACE_INSN ("ashr");
900 cpu
.asregs
.regs
[a
] = av
>> bv
;
905 int a
= (inst
>> 4) & 0xf;
909 MOXIE_TRACE_INSN ("xor");
910 av
= cpu
.asregs
.regs
[a
];
911 bv
= cpu
.asregs
.regs
[b
];
912 cpu
.asregs
.regs
[a
] = av
^ bv
;
915 case 0x2f: /* mul.l */
917 int a
= (inst
>> 4) & 0xf;
919 unsigned av
= cpu
.asregs
.regs
[a
];
920 unsigned bv
= cpu
.asregs
.regs
[b
];
922 MOXIE_TRACE_INSN ("mul.l");
923 cpu
.asregs
.regs
[a
] = av
* bv
;
928 unsigned int inum
= EXTRACT_WORD(pc
+2);
930 MOXIE_TRACE_INSN ("swi");
931 /* Set the special registers appropriately. */
932 cpu
.asregs
.sregs
[2] = 3; /* MOXIE_EX_SWI */
933 cpu
.asregs
.sregs
[3] = inum
;
936 case TARGET_SYS_exit
:
938 sim_engine_halt (sd
, scpu
, NULL
, pc
, sim_exited
,
942 case TARGET_SYS_open
:
945 int mode
= (int) convert_target_flags ((unsigned) cpu
.asregs
.regs
[3]);
946 int perm
= (int) cpu
.asregs
.regs
[4];
948 sim_core_read_buffer (sd
, scpu
, read_map
, fname
,
949 cpu
.asregs
.regs
[2], 1024);
950 fd
= sim_io_open (sd
, fname
, mode
);
951 /* FIXME - set errno */
952 cpu
.asregs
.regs
[2] = fd
;
955 case TARGET_SYS_read
:
957 int fd
= cpu
.asregs
.regs
[2];
958 unsigned len
= (unsigned) cpu
.asregs
.regs
[4];
959 char *buf
= malloc (len
);
960 cpu
.asregs
.regs
[2] = sim_io_read (sd
, fd
, buf
, len
);
961 sim_core_write_buffer (sd
, scpu
, write_map
, buf
,
962 cpu
.asregs
.regs
[3], len
);
966 case TARGET_SYS_write
:
969 /* String length is at 0x12($fp) */
970 unsigned count
, len
= (unsigned) cpu
.asregs
.regs
[4];
972 sim_core_read_buffer (sd
, scpu
, read_map
, str
,
973 cpu
.asregs
.regs
[3], len
);
974 count
= sim_io_write (sd
, cpu
.asregs
.regs
[2], str
, len
);
976 cpu
.asregs
.regs
[2] = count
;
979 case TARGET_SYS_unlink
:
983 sim_core_read_buffer (sd
, scpu
, read_map
, fname
,
984 cpu
.asregs
.regs
[2], 1024);
985 fd
= sim_io_unlink (sd
, fname
);
986 /* FIXME - set errno */
987 cpu
.asregs
.regs
[2] = fd
;
990 case 0xffffffff: /* Linux System Call */
992 unsigned int handler
= cpu
.asregs
.sregs
[1];
993 unsigned int sp
= cpu
.asregs
.regs
[1];
995 /* Save a slot for the static chain. */
998 /* Push the return address. */
1000 wlat (scpu
, opc
, sp
, pc
+ 6);
1002 /* Push the current frame pointer. */
1004 wlat (scpu
, opc
, sp
, cpu
.asregs
.regs
[0]);
1006 /* Uncache the stack pointer and set the fp & pc. */
1007 cpu
.asregs
.regs
[1] = sp
;
1008 cpu
.asregs
.regs
[0] = sp
;
1017 case 0x31: /* div.l */
1019 int a
= (inst
>> 4) & 0xf;
1021 int av
= cpu
.asregs
.regs
[a
];
1022 int bv
= cpu
.asregs
.regs
[b
];
1024 MOXIE_TRACE_INSN ("div.l");
1025 cpu
.asregs
.regs
[a
] = av
/ bv
;
1028 case 0x32: /* udiv.l */
1030 int a
= (inst
>> 4) & 0xf;
1032 unsigned int av
= cpu
.asregs
.regs
[a
];
1033 unsigned int bv
= cpu
.asregs
.regs
[b
];
1035 MOXIE_TRACE_INSN ("udiv.l");
1036 cpu
.asregs
.regs
[a
] = (av
/ bv
);
1039 case 0x33: /* mod.l */
1041 int a
= (inst
>> 4) & 0xf;
1043 int av
= cpu
.asregs
.regs
[a
];
1044 int bv
= cpu
.asregs
.regs
[b
];
1046 MOXIE_TRACE_INSN ("mod.l");
1047 cpu
.asregs
.regs
[a
] = av
% bv
;
1050 case 0x34: /* umod.l */
1052 int a
= (inst
>> 4) & 0xf;
1054 unsigned int av
= cpu
.asregs
.regs
[a
];
1055 unsigned int bv
= cpu
.asregs
.regs
[b
];
1057 MOXIE_TRACE_INSN ("umod.l");
1058 cpu
.asregs
.regs
[a
] = (av
% bv
);
1061 case 0x35: /* brk */
1062 MOXIE_TRACE_INSN ("brk");
1063 sim_engine_halt (sd
, scpu
, NULL
, pc
, sim_stopped
, SIM_SIGTRAP
);
1064 pc
-= 2; /* Adjust pc */
1066 case 0x36: /* ldo.b */
1068 unsigned int addr
= EXTRACT_OFFSET(pc
+2);
1069 int a
= (inst
>> 4) & 0xf;
1072 MOXIE_TRACE_INSN ("ldo.b");
1073 addr
+= cpu
.asregs
.regs
[b
];
1074 cpu
.asregs
.regs
[a
] = rbat (scpu
, opc
, addr
);
1078 case 0x37: /* sto.b */
1080 unsigned int addr
= EXTRACT_OFFSET(pc
+2);
1081 int a
= (inst
>> 4) & 0xf;
1084 MOXIE_TRACE_INSN ("sto.b");
1085 addr
+= cpu
.asregs
.regs
[a
];
1086 wbat (scpu
, opc
, addr
, cpu
.asregs
.regs
[b
]);
1090 case 0x38: /* ldo.s */
1092 unsigned int addr
= EXTRACT_OFFSET(pc
+2);
1093 int a
= (inst
>> 4) & 0xf;
1096 MOXIE_TRACE_INSN ("ldo.s");
1097 addr
+= cpu
.asregs
.regs
[b
];
1098 cpu
.asregs
.regs
[a
] = rsat (scpu
, opc
, addr
);
1102 case 0x39: /* sto.s */
1104 unsigned int addr
= EXTRACT_OFFSET(pc
+2);
1105 int a
= (inst
>> 4) & 0xf;
1108 MOXIE_TRACE_INSN ("sto.s");
1109 addr
+= cpu
.asregs
.regs
[a
];
1110 wsat (scpu
, opc
, addr
, cpu
.asregs
.regs
[b
]);
1116 MOXIE_TRACE_INSN ("SIGILL1");
1117 sim_engine_halt (sd
, scpu
, NULL
, pc
, sim_stopped
, SIM_SIGILL
);
1124 cpu
.asregs
.regs
[PC_REGNO
] = pc
;
1126 if (sim_events_tick (sd
))
1127 sim_events_process (sd
);
1133 moxie_reg_store (SIM_CPU
*scpu
, int rn
, unsigned char *memory
, int length
)
1135 if (rn
< NUM_MOXIE_REGS
&& rn
>= 0)
1141 /* misalignment safe */
1142 ival
= moxie_extract_unsigned_integer (memory
, 4);
1143 cpu
.asints
[rn
] = ival
;
1153 moxie_reg_fetch (SIM_CPU
*scpu
, int rn
, unsigned char *memory
, int length
)
1155 if (rn
< NUM_MOXIE_REGS
&& rn
>= 0)
1159 long ival
= cpu
.asints
[rn
];
1161 /* misalignment-safe */
1162 moxie_store_unsigned_integer (memory
, 4, ival
);
1172 moxie_pc_get (sim_cpu
*cpu
)
1174 return cpu
->registers
[PCIDX
];
1178 moxie_pc_set (sim_cpu
*cpu
, sim_cia pc
)
1180 cpu
->registers
[PCIDX
] = pc
;
1184 free_state (SIM_DESC sd
)
1186 if (STATE_MODULES (sd
) != NULL
)
1187 sim_module_uninstall (sd
);
1188 sim_cpu_free_all (sd
);
1189 sim_state_free (sd
);
1193 sim_open (SIM_OPEN_KIND kind
, host_callback
*cb
,
1194 struct bfd
*abfd
, char * const *argv
)
1197 SIM_DESC sd
= sim_state_alloc (kind
, cb
);
1198 SIM_ASSERT (STATE_MAGIC (sd
) == SIM_MAGIC_NUMBER
);
1200 /* The cpu data is kept in a separately allocated chunk of memory. */
1201 if (sim_cpu_alloc_all (sd
, 1) != SIM_RC_OK
)
1207 if (sim_pre_argv_init (sd
, argv
[0]) != SIM_RC_OK
)
1213 /* The parser will print an error message for us, so we silently return. */
1214 if (sim_parse_args (sd
, argv
) != SIM_RC_OK
)
1220 sim_do_command(sd
," memory region 0x00000000,0x4000000") ;
1221 sim_do_command(sd
," memory region 0xE0000000,0x10000") ;
1223 /* Check for/establish the a reference program image. */
1224 if (sim_analyze_program (sd
,
1225 (STATE_PROG_ARGV (sd
) != NULL
1226 ? *STATE_PROG_ARGV (sd
)
1227 : NULL
), abfd
) != SIM_RC_OK
)
1233 /* Configure/verify the target byte order and other runtime
1234 configuration options. */
1235 if (sim_config (sd
) != SIM_RC_OK
)
1237 sim_module_uninstall (sd
);
1241 if (sim_post_argv_init (sd
) != SIM_RC_OK
)
1243 /* Uninstall the modules to avoid memory leaks,
1244 file descriptor leaks, etc. */
1245 sim_module_uninstall (sd
);
1249 /* CPU specific initialization. */
1250 for (i
= 0; i
< MAX_NR_PROCESSORS
; ++i
)
1252 SIM_CPU
*cpu
= STATE_CPU (sd
, i
);
1254 CPU_REG_FETCH (cpu
) = moxie_reg_fetch
;
1255 CPU_REG_STORE (cpu
) = moxie_reg_store
;
1256 CPU_PC_FETCH (cpu
) = moxie_pc_get
;
1257 CPU_PC_STORE (cpu
) = moxie_pc_set
;
1259 set_initial_gprs (); /* Reset the GPR registers. */
1265 /* Load the device tree blob. */
1268 load_dtb (SIM_DESC sd
, const char *filename
)
1271 FILE *f
= fopen (filename
, "rb");
1273 sim_cpu
*scpu
= STATE_CPU (sd
, 0); /* FIXME */
1275 /* Don't warn as the sim works fine w/out a device tree. */
1278 fseek (f
, 0, SEEK_END
);
1280 fseek (f
, 0, SEEK_SET
);
1281 buf
= alloca (size
);
1282 if (size
!= fread (buf
, 1, size
, f
))
1284 sim_io_eprintf (sd
, "ERROR: error reading ``%s''.\n", filename
);
1288 sim_core_write_buffer (sd
, scpu
, write_map
, buf
, 0xE0000000, size
);
1289 cpu
.asregs
.sregs
[9] = 0xE0000000;
1294 sim_create_inferior (SIM_DESC sd
, struct bfd
*prog_bfd
,
1295 char * const *argv
, char * const *env
)
1299 sim_cpu
*scpu
= STATE_CPU (sd
, 0); /* FIXME */
1301 if (prog_bfd
!= NULL
)
1302 cpu
.asregs
.regs
[PC_REGNO
] = bfd_get_start_address (prog_bfd
);
1304 /* Copy args into target memory. */
1306 for (argc
= 0; avp
&& *avp
; avp
++)
1309 /* Target memory looks like this:
1310 0x00000000 zero word
1311 0x00000004 argc word
1312 0x00000008 start of argv
1314 0x0000???? end of argv
1315 0x0000???? zero word
1316 0x0000???? start of data pointed to by argv */
1318 wlat (scpu
, 0, 0, 0);
1319 wlat (scpu
, 0, 4, argc
);
1321 /* tp is the offset of our first argv data. */
1322 tp
= 4 + 4 + argc
* 4 + 4;
1324 for (i
= 0; i
< argc
; i
++)
1326 /* Set the argv value. */
1327 wlat (scpu
, 0, 4 + 4 + i
* 4, tp
);
1329 /* Store the string. */
1330 sim_core_write_buffer (sd
, scpu
, write_map
, argv
[i
],
1331 tp
, strlen(argv
[i
])+1);
1332 tp
+= strlen (argv
[i
]) + 1;
1335 wlat (scpu
, 0, 4 + 4 + i
* 4, 0);