sim: split sim-signal.h include out
[deliverable/binutils-gdb.git] / sim / moxie / interp.c
1 /* Simulator for the moxie processor
2 Copyright (C) 2008-2021 Free Software Foundation, Inc.
3 Contributed by Anthony Green
4
5 This file is part of GDB, the GNU debugger.
6
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.
11
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.
16
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/>. */
19
20 /* This must come before any other includes. */
21 #include "defs.h"
22
23 #include <fcntl.h>
24 #include <signal.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <sys/param.h>
28 #include <unistd.h>
29 #include "bfd.h"
30 #include "libiberty.h"
31 #include "sim/sim.h"
32
33 #include "sim-main.h"
34 #include "sim-base.h"
35 #include "sim-options.h"
36 #include "sim-io.h"
37 #include "sim-signal.h"
38 #include "targ-vals.h"
39
40 typedef int word;
41 typedef unsigned int uword;
42
43 /* Extract the signed 10-bit offset from a 16-bit branch
44 instruction. */
45 #define INST2OFFSET(o) ((((signed short)((o & ((1<<10)-1))<<6))>>6)<<1)
46
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)))
52
53 #define EXTRACT_OFFSET(addr) \
54 (unsigned int) \
55 (((signed short) \
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)
58
59 static unsigned long
60 moxie_extract_unsigned_integer (unsigned char *addr, int len)
61 {
62 unsigned long retval;
63 unsigned char * p;
64 unsigned char * startaddr = (unsigned char *)addr;
65 unsigned char * endaddr = startaddr + len;
66
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));
70
71 /* Start at the most significant end of the integer, and work towards
72 the least significant. */
73 retval = 0;
74
75 for (p = endaddr; p > startaddr;)
76 retval = (retval << 8) | * -- p;
77
78 return retval;
79 }
80
81 static void
82 moxie_store_unsigned_integer (unsigned char *addr, int len, unsigned long val)
83 {
84 unsigned char * p;
85 unsigned char * startaddr = (unsigned char *)addr;
86 unsigned char * endaddr = startaddr + len;
87
88 for (p = endaddr; p > startaddr;)
89 {
90 * -- p = val & 0xff;
91 val >>= 8;
92 }
93 }
94
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" };
99
100 /* The machine state.
101
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. */
108
109 #define NUM_MOXIE_REGS 17 /* Including PC */
110 #define NUM_MOXIE_SREGS 256 /* The special registers */
111 #define PC_REGNO 16
112
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. */
116 struct moxie_regset
117 {
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 */
122 };
123
124 #define CC_GT 1<<0
125 #define CC_LT 1<<1
126 #define CC_EQ 1<<2
127 #define CC_GTU 1<<3
128 #define CC_LTU 1<<4
129
130 /* TODO: This should be moved to sim-main.h:_sim_cpu. */
131 union
132 {
133 struct moxie_regset asregs;
134 word asints [1]; /* but accessed larger... */
135 } cpu;
136
137 static void
138 set_initial_gprs (void)
139 {
140 int i;
141 long space;
142
143 /* Set up machine just out of reset. */
144 cpu.asregs.regs[PC_REGNO] = 0;
145
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;
151 }
152
153 /* Write a 1 byte value to memory. */
154
155 static INLINE void
156 wbat (sim_cpu *scpu, word pc, word x, word v)
157 {
158 address_word cia = CPU_PC_GET (scpu);
159
160 sim_core_write_aligned_1 (scpu, cia, write_map, x, v);
161 }
162
163 /* Write a 2 byte value to memory. */
164
165 static INLINE void
166 wsat (sim_cpu *scpu, word pc, word x, word v)
167 {
168 address_word cia = CPU_PC_GET (scpu);
169
170 sim_core_write_aligned_2 (scpu, cia, write_map, x, v);
171 }
172
173 /* Write a 4 byte value to memory. */
174
175 static INLINE void
176 wlat (sim_cpu *scpu, word pc, word x, word v)
177 {
178 address_word cia = CPU_PC_GET (scpu);
179
180 sim_core_write_aligned_4 (scpu, cia, write_map, x, v);
181 }
182
183 /* Read 2 bytes from memory. */
184
185 static INLINE int
186 rsat (sim_cpu *scpu, word pc, word x)
187 {
188 address_word cia = CPU_PC_GET (scpu);
189
190 return (sim_core_read_aligned_2 (scpu, cia, read_map, x));
191 }
192
193 /* Read 1 byte from memory. */
194
195 static INLINE int
196 rbat (sim_cpu *scpu, word pc, word x)
197 {
198 address_word cia = CPU_PC_GET (scpu);
199
200 return (sim_core_read_aligned_1 (scpu, cia, read_map, x));
201 }
202
203 /* Read 4 bytes from memory. */
204
205 static INLINE int
206 rlat (sim_cpu *scpu, word pc, word x)
207 {
208 address_word cia = CPU_PC_GET (scpu);
209
210 return (sim_core_read_aligned_4 (scpu, cia, read_map, x));
211 }
212
213 #define CHECK_FLAG(T,H) if (tflags & T) { hflags |= H; tflags ^= T; }
214
215 static unsigned int
216 convert_target_flags (unsigned int tflags)
217 {
218 unsigned int hflags = 0x0;
219
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);
227
228 if (tflags != 0x0)
229 fprintf (stderr,
230 "Simulator Error: problem converting target open flags for host. 0x%x\n",
231 tflags);
232
233 return hflags;
234 }
235
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])
245
246 void
247 sim_engine_run (SIM_DESC sd,
248 int next_cpu_nr, /* ignore */
249 int nr_cpus, /* ignore */
250 int siggnal) /* ignore */
251 {
252 word pc, opc;
253 unsigned short inst;
254 sim_cpu *scpu = STATE_CPU (sd, 0); /* FIXME */
255 address_word cia = CPU_PC_GET (scpu);
256
257 pc = cpu.asregs.regs[PC_REGNO];
258
259 /* Run instructions here. */
260 do
261 {
262 opc = pc;
263
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);
267
268 /* Decode instruction. */
269 if (inst & (1 << 15))
270 {
271 if (inst & (1 << 14))
272 {
273 /* This is a Form 3 instruction. */
274 int opcode = (inst >> 10 & 0xf);
275
276 switch (opcode)
277 {
278 case 0x00: /* beq */
279 {
280 MOXIE_TRACE_INSN ("beq");
281 if (cpu.asregs.cc & CC_EQ)
282 pc += INST2OFFSET(inst);
283 }
284 break;
285 case 0x01: /* bne */
286 {
287 MOXIE_TRACE_INSN ("bne");
288 if (! (cpu.asregs.cc & CC_EQ))
289 pc += INST2OFFSET(inst);
290 }
291 break;
292 case 0x02: /* blt */
293 {
294 MOXIE_TRACE_INSN ("blt");
295 if (cpu.asregs.cc & CC_LT)
296 pc += INST2OFFSET(inst);
297 } break;
298 case 0x03: /* bgt */
299 {
300 MOXIE_TRACE_INSN ("bgt");
301 if (cpu.asregs.cc & CC_GT)
302 pc += INST2OFFSET(inst);
303 }
304 break;
305 case 0x04: /* bltu */
306 {
307 MOXIE_TRACE_INSN ("bltu");
308 if (cpu.asregs.cc & CC_LTU)
309 pc += INST2OFFSET(inst);
310 }
311 break;
312 case 0x05: /* bgtu */
313 {
314 MOXIE_TRACE_INSN ("bgtu");
315 if (cpu.asregs.cc & CC_GTU)
316 pc += INST2OFFSET(inst);
317 }
318 break;
319 case 0x06: /* bge */
320 {
321 MOXIE_TRACE_INSN ("bge");
322 if (cpu.asregs.cc & (CC_GT | CC_EQ))
323 pc += INST2OFFSET(inst);
324 }
325 break;
326 case 0x07: /* ble */
327 {
328 MOXIE_TRACE_INSN ("ble");
329 if (cpu.asregs.cc & (CC_LT | CC_EQ))
330 pc += INST2OFFSET(inst);
331 }
332 break;
333 case 0x08: /* bgeu */
334 {
335 MOXIE_TRACE_INSN ("bgeu");
336 if (cpu.asregs.cc & (CC_GTU | CC_EQ))
337 pc += INST2OFFSET(inst);
338 }
339 break;
340 case 0x09: /* bleu */
341 {
342 MOXIE_TRACE_INSN ("bleu");
343 if (cpu.asregs.cc & (CC_LTU | CC_EQ))
344 pc += INST2OFFSET(inst);
345 }
346 break;
347 default:
348 {
349 MOXIE_TRACE_INSN ("SIGILL3");
350 sim_engine_halt (sd, scpu, NULL, pc, sim_stopped, SIM_SIGILL);
351 break;
352 }
353 }
354 }
355 else
356 {
357 /* This is a Form 2 instruction. */
358 int opcode = (inst >> 12 & 0x3);
359 switch (opcode)
360 {
361 case 0x00: /* inc */
362 {
363 int a = (inst >> 8) & 0xf;
364 unsigned av = cpu.asregs.regs[a];
365 unsigned v = (inst & 0xff);
366
367 MOXIE_TRACE_INSN ("inc");
368 cpu.asregs.regs[a] = av + v;
369 }
370 break;
371 case 0x01: /* dec */
372 {
373 int a = (inst >> 8) & 0xf;
374 unsigned av = cpu.asregs.regs[a];
375 unsigned v = (inst & 0xff);
376
377 MOXIE_TRACE_INSN ("dec");
378 cpu.asregs.regs[a] = av - v;
379 }
380 break;
381 case 0x02: /* gsr */
382 {
383 int a = (inst >> 8) & 0xf;
384 unsigned v = (inst & 0xff);
385
386 MOXIE_TRACE_INSN ("gsr");
387 cpu.asregs.regs[a] = cpu.asregs.sregs[v];
388 }
389 break;
390 case 0x03: /* ssr */
391 {
392 int a = (inst >> 8) & 0xf;
393 unsigned v = (inst & 0xff);
394
395 MOXIE_TRACE_INSN ("ssr");
396 cpu.asregs.sregs[v] = cpu.asregs.regs[a];
397 }
398 break;
399 default:
400 MOXIE_TRACE_INSN ("SIGILL2");
401 sim_engine_halt (sd, scpu, NULL, pc, sim_stopped, SIM_SIGILL);
402 break;
403 }
404 }
405 }
406 else
407 {
408 /* This is a Form 1 instruction. */
409 int opcode = inst >> 8;
410 switch (opcode)
411 {
412 case 0x00: /* bad */
413 opc = opcode;
414 MOXIE_TRACE_INSN ("SIGILL0");
415 sim_engine_halt (sd, scpu, NULL, pc, sim_stopped, SIM_SIGILL);
416 break;
417 case 0x01: /* ldi.l (immediate) */
418 {
419 int reg = (inst >> 4) & 0xf;
420 unsigned int val = EXTRACT_WORD(pc+2);
421
422 MOXIE_TRACE_INSN ("ldi.l");
423 cpu.asregs.regs[reg] = val;
424 pc += 4;
425 }
426 break;
427 case 0x02: /* mov (register-to-register) */
428 {
429 int dest = (inst >> 4) & 0xf;
430 int src = (inst ) & 0xf;
431
432 MOXIE_TRACE_INSN ("mov");
433 cpu.asregs.regs[dest] = cpu.asregs.regs[src];
434 }
435 break;
436 case 0x03: /* jsra */
437 {
438 unsigned int fn = EXTRACT_WORD(pc+2);
439 unsigned int sp = cpu.asregs.regs[1];
440
441 MOXIE_TRACE_INSN ("jsra");
442 /* Save a slot for the static chain. */
443 sp -= 4;
444
445 /* Push the return address. */
446 sp -= 4;
447 wlat (scpu, opc, sp, pc + 6);
448
449 /* Push the current frame pointer. */
450 sp -= 4;
451 wlat (scpu, opc, sp, cpu.asregs.regs[0]);
452
453 /* Uncache the stack pointer and set the pc and $fp. */
454 cpu.asregs.regs[1] = sp;
455 cpu.asregs.regs[0] = sp;
456 pc = fn - 2;
457 }
458 break;
459 case 0x04: /* ret */
460 {
461 unsigned int sp = cpu.asregs.regs[0];
462
463 MOXIE_TRACE_INSN ("ret");
464
465 /* Pop the frame pointer. */
466 cpu.asregs.regs[0] = rlat (scpu, opc, sp);
467 sp += 4;
468
469 /* Pop the return address. */
470 pc = rlat (scpu, opc, sp) - 2;
471 sp += 4;
472
473 /* Skip over the static chain slot. */
474 sp += 4;
475
476 /* Uncache the stack pointer. */
477 cpu.asregs.regs[1] = sp;
478 }
479 break;
480 case 0x05: /* add.l */
481 {
482 int a = (inst >> 4) & 0xf;
483 int b = inst & 0xf;
484 unsigned av = cpu.asregs.regs[a];
485 unsigned bv = cpu.asregs.regs[b];
486
487 MOXIE_TRACE_INSN ("add.l");
488 cpu.asregs.regs[a] = av + bv;
489 }
490 break;
491 case 0x06: /* push */
492 {
493 int a = (inst >> 4) & 0xf;
494 int b = inst & 0xf;
495 int sp = cpu.asregs.regs[a] - 4;
496
497 MOXIE_TRACE_INSN ("push");
498 wlat (scpu, opc, sp, cpu.asregs.regs[b]);
499 cpu.asregs.regs[a] = sp;
500 }
501 break;
502 case 0x07: /* pop */
503 {
504 int a = (inst >> 4) & 0xf;
505 int b = inst & 0xf;
506 int sp = cpu.asregs.regs[a];
507
508 MOXIE_TRACE_INSN ("pop");
509 cpu.asregs.regs[b] = rlat (scpu, opc, sp);
510 cpu.asregs.regs[a] = sp + 4;
511 }
512 break;
513 case 0x08: /* lda.l */
514 {
515 int reg = (inst >> 4) & 0xf;
516 unsigned int addr = EXTRACT_WORD(pc+2);
517
518 MOXIE_TRACE_INSN ("lda.l");
519 cpu.asregs.regs[reg] = rlat (scpu, opc, addr);
520 pc += 4;
521 }
522 break;
523 case 0x09: /* sta.l */
524 {
525 int reg = (inst >> 4) & 0xf;
526 unsigned int addr = EXTRACT_WORD(pc+2);
527
528 MOXIE_TRACE_INSN ("sta.l");
529 wlat (scpu, opc, addr, cpu.asregs.regs[reg]);
530 pc += 4;
531 }
532 break;
533 case 0x0a: /* ld.l (register indirect) */
534 {
535 int src = inst & 0xf;
536 int dest = (inst >> 4) & 0xf;
537 int xv;
538
539 MOXIE_TRACE_INSN ("ld.l");
540 xv = cpu.asregs.regs[src];
541 cpu.asregs.regs[dest] = rlat (scpu, opc, xv);
542 }
543 break;
544 case 0x0b: /* st.l */
545 {
546 int dest = (inst >> 4) & 0xf;
547 int val = inst & 0xf;
548
549 MOXIE_TRACE_INSN ("st.l");
550 wlat (scpu, opc, cpu.asregs.regs[dest], cpu.asregs.regs[val]);
551 }
552 break;
553 case 0x0c: /* ldo.l */
554 {
555 unsigned int addr = EXTRACT_OFFSET(pc+2);
556 int a = (inst >> 4) & 0xf;
557 int b = inst & 0xf;
558
559 MOXIE_TRACE_INSN ("ldo.l");
560 addr += cpu.asregs.regs[b];
561 cpu.asregs.regs[a] = rlat (scpu, opc, addr);
562 pc += 2;
563 }
564 break;
565 case 0x0d: /* sto.l */
566 {
567 unsigned int addr = EXTRACT_OFFSET(pc+2);
568 int a = (inst >> 4) & 0xf;
569 int b = inst & 0xf;
570
571 MOXIE_TRACE_INSN ("sto.l");
572 addr += cpu.asregs.regs[a];
573 wlat (scpu, opc, addr, cpu.asregs.regs[b]);
574 pc += 2;
575 }
576 break;
577 case 0x0e: /* cmp */
578 {
579 int a = (inst >> 4) & 0xf;
580 int b = inst & 0xf;
581 int cc = 0;
582 int va = cpu.asregs.regs[a];
583 int vb = cpu.asregs.regs[b];
584
585 MOXIE_TRACE_INSN ("cmp");
586 if (va == vb)
587 cc = CC_EQ;
588 else
589 {
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);
594 }
595
596 cpu.asregs.cc = cc;
597 }
598 break;
599 case 0x0f: /* nop */
600 break;
601 case 0x10: /* sex.b */
602 {
603 int a = (inst >> 4) & 0xf;
604 int b = inst & 0xf;
605 signed char bv = cpu.asregs.regs[b];
606
607 MOXIE_TRACE_INSN ("sex.b");
608 cpu.asregs.regs[a] = (int) bv;
609 }
610 break;
611 case 0x11: /* sex.s */
612 {
613 int a = (inst >> 4) & 0xf;
614 int b = inst & 0xf;
615 signed short bv = cpu.asregs.regs[b];
616
617 MOXIE_TRACE_INSN ("sex.s");
618 cpu.asregs.regs[a] = (int) bv;
619 }
620 break;
621 case 0x12: /* zex.b */
622 {
623 int a = (inst >> 4) & 0xf;
624 int b = inst & 0xf;
625 signed char bv = cpu.asregs.regs[b];
626
627 MOXIE_TRACE_INSN ("zex.b");
628 cpu.asregs.regs[a] = (int) bv & 0xff;
629 }
630 break;
631 case 0x13: /* zex.s */
632 {
633 int a = (inst >> 4) & 0xf;
634 int b = inst & 0xf;
635 signed short bv = cpu.asregs.regs[b];
636
637 MOXIE_TRACE_INSN ("zex.s");
638 cpu.asregs.regs[a] = (int) bv & 0xffff;
639 }
640 break;
641 case 0x14: /* umul.x */
642 {
643 int a = (inst >> 4) & 0xf;
644 int b = inst & 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;
649
650 MOXIE_TRACE_INSN ("umul.x");
651 cpu.asregs.regs[a] = r >> 32;
652 }
653 break;
654 case 0x15: /* mul.x */
655 {
656 int a = (inst >> 4) & 0xf;
657 int b = inst & 0xf;
658 unsigned av = cpu.asregs.regs[a];
659 unsigned bv = cpu.asregs.regs[b];
660 signed long long r =
661 (signed long long) av * (signed long long) bv;
662
663 MOXIE_TRACE_INSN ("mul.x");
664 cpu.asregs.regs[a] = r >> 32;
665 }
666 break;
667 case 0x16: /* bad */
668 case 0x17: /* bad */
669 case 0x18: /* bad */
670 {
671 opc = opcode;
672 MOXIE_TRACE_INSN ("SIGILL0");
673 sim_engine_halt (sd, scpu, NULL, pc, sim_stopped, SIM_SIGILL);
674 break;
675 }
676 case 0x19: /* jsr */
677 {
678 unsigned int fn = cpu.asregs.regs[(inst >> 4) & 0xf];
679 unsigned int sp = cpu.asregs.regs[1];
680
681 MOXIE_TRACE_INSN ("jsr");
682
683 /* Save a slot for the static chain. */
684 sp -= 4;
685
686 /* Push the return address. */
687 sp -= 4;
688 wlat (scpu, opc, sp, pc + 2);
689
690 /* Push the current frame pointer. */
691 sp -= 4;
692 wlat (scpu, opc, sp, cpu.asregs.regs[0]);
693
694 /* Uncache the stack pointer and set the fp & pc. */
695 cpu.asregs.regs[1] = sp;
696 cpu.asregs.regs[0] = sp;
697 pc = fn - 2;
698 }
699 break;
700 case 0x1a: /* jmpa */
701 {
702 unsigned int tgt = EXTRACT_WORD(pc+2);
703
704 MOXIE_TRACE_INSN ("jmpa");
705 pc = tgt - 2;
706 }
707 break;
708 case 0x1b: /* ldi.b (immediate) */
709 {
710 int reg = (inst >> 4) & 0xf;
711 unsigned int val = EXTRACT_WORD(pc+2);
712
713 MOXIE_TRACE_INSN ("ldi.b");
714 cpu.asregs.regs[reg] = val;
715 pc += 4;
716 }
717 break;
718 case 0x1c: /* ld.b (register indirect) */
719 {
720 int src = inst & 0xf;
721 int dest = (inst >> 4) & 0xf;
722 int xv;
723
724 MOXIE_TRACE_INSN ("ld.b");
725 xv = cpu.asregs.regs[src];
726 cpu.asregs.regs[dest] = rbat (scpu, opc, xv);
727 }
728 break;
729 case 0x1d: /* lda.b */
730 {
731 int reg = (inst >> 4) & 0xf;
732 unsigned int addr = EXTRACT_WORD(pc+2);
733
734 MOXIE_TRACE_INSN ("lda.b");
735 cpu.asregs.regs[reg] = rbat (scpu, opc, addr);
736 pc += 4;
737 }
738 break;
739 case 0x1e: /* st.b */
740 {
741 int dest = (inst >> 4) & 0xf;
742 int val = inst & 0xf;
743
744 MOXIE_TRACE_INSN ("st.b");
745 wbat (scpu, opc, cpu.asregs.regs[dest], cpu.asregs.regs[val]);
746 }
747 break;
748 case 0x1f: /* sta.b */
749 {
750 int reg = (inst >> 4) & 0xf;
751 unsigned int addr = EXTRACT_WORD(pc+2);
752
753 MOXIE_TRACE_INSN ("sta.b");
754 wbat (scpu, opc, addr, cpu.asregs.regs[reg]);
755 pc += 4;
756 }
757 break;
758 case 0x20: /* ldi.s (immediate) */
759 {
760 int reg = (inst >> 4) & 0xf;
761
762 unsigned int val = EXTRACT_WORD(pc+2);
763
764 MOXIE_TRACE_INSN ("ldi.s");
765 cpu.asregs.regs[reg] = val;
766 pc += 4;
767 }
768 break;
769 case 0x21: /* ld.s (register indirect) */
770 {
771 int src = inst & 0xf;
772 int dest = (inst >> 4) & 0xf;
773 int xv;
774
775 MOXIE_TRACE_INSN ("ld.s");
776 xv = cpu.asregs.regs[src];
777 cpu.asregs.regs[dest] = rsat (scpu, opc, xv);
778 }
779 break;
780 case 0x22: /* lda.s */
781 {
782 int reg = (inst >> 4) & 0xf;
783 unsigned int addr = EXTRACT_WORD(pc+2);
784
785 MOXIE_TRACE_INSN ("lda.s");
786 cpu.asregs.regs[reg] = rsat (scpu, opc, addr);
787 pc += 4;
788 }
789 break;
790 case 0x23: /* st.s */
791 {
792 int dest = (inst >> 4) & 0xf;
793 int val = inst & 0xf;
794
795 MOXIE_TRACE_INSN ("st.s");
796 wsat (scpu, opc, cpu.asregs.regs[dest], cpu.asregs.regs[val]);
797 }
798 break;
799 case 0x24: /* sta.s */
800 {
801 int reg = (inst >> 4) & 0xf;
802 unsigned int addr = EXTRACT_WORD(pc+2);
803
804 MOXIE_TRACE_INSN ("sta.s");
805 wsat (scpu, opc, addr, cpu.asregs.regs[reg]);
806 pc += 4;
807 }
808 break;
809 case 0x25: /* jmp */
810 {
811 int reg = (inst >> 4) & 0xf;
812
813 MOXIE_TRACE_INSN ("jmp");
814 pc = cpu.asregs.regs[reg] - 2;
815 }
816 break;
817 case 0x26: /* and */
818 {
819 int a = (inst >> 4) & 0xf;
820 int b = inst & 0xf;
821 int av, bv;
822
823 MOXIE_TRACE_INSN ("and");
824 av = cpu.asregs.regs[a];
825 bv = cpu.asregs.regs[b];
826 cpu.asregs.regs[a] = av & bv;
827 }
828 break;
829 case 0x27: /* lshr */
830 {
831 int a = (inst >> 4) & 0xf;
832 int b = inst & 0xf;
833 int av = cpu.asregs.regs[a];
834 int bv = cpu.asregs.regs[b];
835
836 MOXIE_TRACE_INSN ("lshr");
837 cpu.asregs.regs[a] = (unsigned) ((unsigned) av >> bv);
838 }
839 break;
840 case 0x28: /* ashl */
841 {
842 int a = (inst >> 4) & 0xf;
843 int b = inst & 0xf;
844 int av = cpu.asregs.regs[a];
845 int bv = cpu.asregs.regs[b];
846
847 MOXIE_TRACE_INSN ("ashl");
848 cpu.asregs.regs[a] = av << bv;
849 }
850 break;
851 case 0x29: /* sub.l */
852 {
853 int a = (inst >> 4) & 0xf;
854 int b = inst & 0xf;
855 unsigned av = cpu.asregs.regs[a];
856 unsigned bv = cpu.asregs.regs[b];
857
858 MOXIE_TRACE_INSN ("sub.l");
859 cpu.asregs.regs[a] = av - bv;
860 }
861 break;
862 case 0x2a: /* neg */
863 {
864 int a = (inst >> 4) & 0xf;
865 int b = inst & 0xf;
866 int bv = cpu.asregs.regs[b];
867
868 MOXIE_TRACE_INSN ("neg");
869 cpu.asregs.regs[a] = - bv;
870 }
871 break;
872 case 0x2b: /* or */
873 {
874 int a = (inst >> 4) & 0xf;
875 int b = inst & 0xf;
876 int av, bv;
877
878 MOXIE_TRACE_INSN ("or");
879 av = cpu.asregs.regs[a];
880 bv = cpu.asregs.regs[b];
881 cpu.asregs.regs[a] = av | bv;
882 }
883 break;
884 case 0x2c: /* not */
885 {
886 int a = (inst >> 4) & 0xf;
887 int b = inst & 0xf;
888 int bv = cpu.asregs.regs[b];
889
890 MOXIE_TRACE_INSN ("not");
891 cpu.asregs.regs[a] = 0xffffffff ^ bv;
892 }
893 break;
894 case 0x2d: /* ashr */
895 {
896 int a = (inst >> 4) & 0xf;
897 int b = inst & 0xf;
898 int av = cpu.asregs.regs[a];
899 int bv = cpu.asregs.regs[b];
900
901 MOXIE_TRACE_INSN ("ashr");
902 cpu.asregs.regs[a] = av >> bv;
903 }
904 break;
905 case 0x2e: /* xor */
906 {
907 int a = (inst >> 4) & 0xf;
908 int b = inst & 0xf;
909 int av, bv;
910
911 MOXIE_TRACE_INSN ("xor");
912 av = cpu.asregs.regs[a];
913 bv = cpu.asregs.regs[b];
914 cpu.asregs.regs[a] = av ^ bv;
915 }
916 break;
917 case 0x2f: /* mul.l */
918 {
919 int a = (inst >> 4) & 0xf;
920 int b = inst & 0xf;
921 unsigned av = cpu.asregs.regs[a];
922 unsigned bv = cpu.asregs.regs[b];
923
924 MOXIE_TRACE_INSN ("mul.l");
925 cpu.asregs.regs[a] = av * bv;
926 }
927 break;
928 case 0x30: /* swi */
929 {
930 unsigned int inum = EXTRACT_WORD(pc+2);
931
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;
936 switch (inum)
937 {
938 case TARGET_SYS_exit:
939 {
940 sim_engine_halt (sd, scpu, NULL, pc, sim_exited,
941 cpu.asregs.regs[2]);
942 break;
943 }
944 case TARGET_SYS_open:
945 {
946 char fname[1024];
947 int mode = (int) convert_target_flags ((unsigned) cpu.asregs.regs[3]);
948 int perm = (int) cpu.asregs.regs[4];
949 int fd;
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;
955 break;
956 }
957 case TARGET_SYS_read:
958 {
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);
965 free (buf);
966 break;
967 }
968 case TARGET_SYS_write:
969 {
970 char *str;
971 /* String length is at 0x12($fp) */
972 unsigned count, len = (unsigned) cpu.asregs.regs[4];
973 str = malloc (len);
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);
977 free (str);
978 cpu.asregs.regs[2] = count;
979 break;
980 }
981 case TARGET_SYS_unlink:
982 {
983 char fname[1024];
984 int fd;
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;
990 break;
991 }
992 case 0xffffffff: /* Linux System Call */
993 {
994 unsigned int handler = cpu.asregs.sregs[1];
995 unsigned int sp = cpu.asregs.regs[1];
996
997 /* Save a slot for the static chain. */
998 sp -= 4;
999
1000 /* Push the return address. */
1001 sp -= 4;
1002 wlat (scpu, opc, sp, pc + 6);
1003
1004 /* Push the current frame pointer. */
1005 sp -= 4;
1006 wlat (scpu, opc, sp, cpu.asregs.regs[0]);
1007
1008 /* Uncache the stack pointer and set the fp & pc. */
1009 cpu.asregs.regs[1] = sp;
1010 cpu.asregs.regs[0] = sp;
1011 pc = handler - 6;
1012 }
1013 default:
1014 break;
1015 }
1016 pc += 4;
1017 }
1018 break;
1019 case 0x31: /* div.l */
1020 {
1021 int a = (inst >> 4) & 0xf;
1022 int b = inst & 0xf;
1023 int av = cpu.asregs.regs[a];
1024 int bv = cpu.asregs.regs[b];
1025
1026 MOXIE_TRACE_INSN ("div.l");
1027 cpu.asregs.regs[a] = av / bv;
1028 }
1029 break;
1030 case 0x32: /* udiv.l */
1031 {
1032 int a = (inst >> 4) & 0xf;
1033 int b = inst & 0xf;
1034 unsigned int av = cpu.asregs.regs[a];
1035 unsigned int bv = cpu.asregs.regs[b];
1036
1037 MOXIE_TRACE_INSN ("udiv.l");
1038 cpu.asregs.regs[a] = (av / bv);
1039 }
1040 break;
1041 case 0x33: /* mod.l */
1042 {
1043 int a = (inst >> 4) & 0xf;
1044 int b = inst & 0xf;
1045 int av = cpu.asregs.regs[a];
1046 int bv = cpu.asregs.regs[b];
1047
1048 MOXIE_TRACE_INSN ("mod.l");
1049 cpu.asregs.regs[a] = av % bv;
1050 }
1051 break;
1052 case 0x34: /* umod.l */
1053 {
1054 int a = (inst >> 4) & 0xf;
1055 int b = inst & 0xf;
1056 unsigned int av = cpu.asregs.regs[a];
1057 unsigned int bv = cpu.asregs.regs[b];
1058
1059 MOXIE_TRACE_INSN ("umod.l");
1060 cpu.asregs.regs[a] = (av % bv);
1061 }
1062 break;
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 */
1067 break;
1068 case 0x36: /* ldo.b */
1069 {
1070 unsigned int addr = EXTRACT_OFFSET(pc+2);
1071 int a = (inst >> 4) & 0xf;
1072 int b = inst & 0xf;
1073
1074 MOXIE_TRACE_INSN ("ldo.b");
1075 addr += cpu.asregs.regs[b];
1076 cpu.asregs.regs[a] = rbat (scpu, opc, addr);
1077 pc += 2;
1078 }
1079 break;
1080 case 0x37: /* sto.b */
1081 {
1082 unsigned int addr = EXTRACT_OFFSET(pc+2);
1083 int a = (inst >> 4) & 0xf;
1084 int b = inst & 0xf;
1085
1086 MOXIE_TRACE_INSN ("sto.b");
1087 addr += cpu.asregs.regs[a];
1088 wbat (scpu, opc, addr, cpu.asregs.regs[b]);
1089 pc += 2;
1090 }
1091 break;
1092 case 0x38: /* ldo.s */
1093 {
1094 unsigned int addr = EXTRACT_OFFSET(pc+2);
1095 int a = (inst >> 4) & 0xf;
1096 int b = inst & 0xf;
1097
1098 MOXIE_TRACE_INSN ("ldo.s");
1099 addr += cpu.asregs.regs[b];
1100 cpu.asregs.regs[a] = rsat (scpu, opc, addr);
1101 pc += 2;
1102 }
1103 break;
1104 case 0x39: /* sto.s */
1105 {
1106 unsigned int addr = EXTRACT_OFFSET(pc+2);
1107 int a = (inst >> 4) & 0xf;
1108 int b = inst & 0xf;
1109
1110 MOXIE_TRACE_INSN ("sto.s");
1111 addr += cpu.asregs.regs[a];
1112 wsat (scpu, opc, addr, cpu.asregs.regs[b]);
1113 pc += 2;
1114 }
1115 break;
1116 default:
1117 opc = opcode;
1118 MOXIE_TRACE_INSN ("SIGILL1");
1119 sim_engine_halt (sd, scpu, NULL, pc, sim_stopped, SIM_SIGILL);
1120 break;
1121 }
1122 }
1123
1124 cpu.asregs.insts++;
1125 pc += 2;
1126 cpu.asregs.regs[PC_REGNO] = pc;
1127
1128 if (sim_events_tick (sd))
1129 sim_events_process (sd);
1130
1131 } while (1);
1132 }
1133
1134 static int
1135 moxie_reg_store (SIM_CPU *scpu, int rn, unsigned char *memory, int length)
1136 {
1137 if (rn < NUM_MOXIE_REGS && rn >= 0)
1138 {
1139 if (length == 4)
1140 {
1141 long ival;
1142
1143 /* misalignment safe */
1144 ival = moxie_extract_unsigned_integer (memory, 4);
1145 cpu.asints[rn] = ival;
1146 }
1147
1148 return 4;
1149 }
1150 else
1151 return 0;
1152 }
1153
1154 static int
1155 moxie_reg_fetch (SIM_CPU *scpu, int rn, unsigned char *memory, int length)
1156 {
1157 if (rn < NUM_MOXIE_REGS && rn >= 0)
1158 {
1159 if (length == 4)
1160 {
1161 long ival = cpu.asints[rn];
1162
1163 /* misalignment-safe */
1164 moxie_store_unsigned_integer (memory, 4, ival);
1165 }
1166
1167 return 4;
1168 }
1169 else
1170 return 0;
1171 }
1172
1173 static sim_cia
1174 moxie_pc_get (sim_cpu *cpu)
1175 {
1176 return cpu->registers[PCIDX];
1177 }
1178
1179 static void
1180 moxie_pc_set (sim_cpu *cpu, sim_cia pc)
1181 {
1182 cpu->registers[PCIDX] = pc;
1183 }
1184
1185 static void
1186 free_state (SIM_DESC sd)
1187 {
1188 if (STATE_MODULES (sd) != NULL)
1189 sim_module_uninstall (sd);
1190 sim_cpu_free_all (sd);
1191 sim_state_free (sd);
1192 }
1193
1194 SIM_DESC
1195 sim_open (SIM_OPEN_KIND kind, host_callback *cb,
1196 struct bfd *abfd, char * const *argv)
1197 {
1198 int i;
1199 SIM_DESC sd = sim_state_alloc (kind, cb);
1200 SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
1201
1202 /* Set default options before parsing user options. */
1203 current_target_byte_order = BFD_ENDIAN_BIG;
1204
1205 /* The cpu data is kept in a separately allocated chunk of memory. */
1206 if (sim_cpu_alloc_all (sd, 1) != SIM_RC_OK)
1207 {
1208 free_state (sd);
1209 return 0;
1210 }
1211
1212 if (sim_pre_argv_init (sd, argv[0]) != SIM_RC_OK)
1213 {
1214 free_state (sd);
1215 return 0;
1216 }
1217
1218 /* The parser will print an error message for us, so we silently return. */
1219 if (sim_parse_args (sd, argv) != SIM_RC_OK)
1220 {
1221 free_state (sd);
1222 return 0;
1223 }
1224
1225 sim_do_command(sd," memory region 0x00000000,0x4000000") ;
1226 sim_do_command(sd," memory region 0xE0000000,0x10000") ;
1227
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)
1233 {
1234 free_state (sd);
1235 return 0;
1236 }
1237
1238 /* Configure/verify the target byte order and other runtime
1239 configuration options. */
1240 if (sim_config (sd) != SIM_RC_OK)
1241 {
1242 sim_module_uninstall (sd);
1243 return 0;
1244 }
1245
1246 if (sim_post_argv_init (sd) != SIM_RC_OK)
1247 {
1248 /* Uninstall the modules to avoid memory leaks,
1249 file descriptor leaks, etc. */
1250 sim_module_uninstall (sd);
1251 return 0;
1252 }
1253
1254 /* CPU specific initialization. */
1255 for (i = 0; i < MAX_NR_PROCESSORS; ++i)
1256 {
1257 SIM_CPU *cpu = STATE_CPU (sd, i);
1258
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;
1263
1264 set_initial_gprs (); /* Reset the GPR registers. */
1265 }
1266
1267 return sd;
1268 }
1269
1270 /* Load the device tree blob. */
1271
1272 static void
1273 load_dtb (SIM_DESC sd, const char *filename)
1274 {
1275 int size = 0;
1276 FILE *f = fopen (filename, "rb");
1277 char *buf;
1278 sim_cpu *scpu = STATE_CPU (sd, 0); /* FIXME */
1279
1280 /* Don't warn as the sim works fine w/out a device tree. */
1281 if (f == NULL)
1282 return;
1283 fseek (f, 0, SEEK_END);
1284 size = ftell(f);
1285 fseek (f, 0, SEEK_SET);
1286 buf = alloca (size);
1287 if (size != fread (buf, 1, size, f))
1288 {
1289 sim_io_eprintf (sd, "ERROR: error reading ``%s''.\n", filename);
1290 fclose (f);
1291 return;
1292 }
1293 sim_core_write_buffer (sd, scpu, write_map, buf, 0xE0000000, size);
1294 cpu.asregs.sregs[9] = 0xE0000000;
1295 fclose (f);
1296 }
1297
1298 SIM_RC
1299 sim_create_inferior (SIM_DESC sd, struct bfd *prog_bfd,
1300 char * const *argv, char * const *env)
1301 {
1302 char * const *avp;
1303 int l, argc, i, tp;
1304 sim_cpu *scpu = STATE_CPU (sd, 0); /* FIXME */
1305
1306 if (prog_bfd != NULL)
1307 cpu.asregs.regs[PC_REGNO] = bfd_get_start_address (prog_bfd);
1308
1309 /* Copy args into target memory. */
1310 avp = argv;
1311 for (argc = 0; avp && *avp; avp++)
1312 argc++;
1313
1314 /* Target memory looks like this:
1315 0x00000000 zero word
1316 0x00000004 argc word
1317 0x00000008 start of argv
1318 .
1319 0x0000???? end of argv
1320 0x0000???? zero word
1321 0x0000???? start of data pointed to by argv */
1322
1323 wlat (scpu, 0, 0, 0);
1324 wlat (scpu, 0, 4, argc);
1325
1326 /* tp is the offset of our first argv data. */
1327 tp = 4 + 4 + argc * 4 + 4;
1328
1329 for (i = 0; i < argc; i++)
1330 {
1331 /* Set the argv value. */
1332 wlat (scpu, 0, 4 + 4 + i * 4, tp);
1333
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;
1338 }
1339
1340 wlat (scpu, 0, 4 + 4 + i * 4, 0);
1341
1342 load_dtb (sd, DTB);
1343
1344 return SIM_RC_OK;
1345 }
This page took 0.058269 seconds and 4 git commands to generate.