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