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