1 /* Simulator for the moxie processor
2 Copyright (C) 2008-2024 Free Software Foundation, Inc.
3 Contributed by Anthony Green
5 This file is part of GDB, the GNU debugger.
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>. */
20 /* This must come before any other includes. */
27 #include <sys/param.h>
30 #include "libiberty.h"
35 #include "sim-options.h"
37 #include "sim-signal.h"
38 #include "target-newlib-syscall.h"
40 #include "moxie-sim.h"
42 /* Extract the signed 10-bit offset from a 16-bit branch
44 #define INST2OFFSET(o) ((((signed short)((o & ((1<<10)-1))<<6))>>6)<<1)
46 #define EXTRACT_WORD(addr) \
47 ((sim_core_read_aligned_1 (scpu, cia, read_map, addr) << 24) \
48 + (sim_core_read_aligned_1 (scpu, cia, read_map, addr+1) << 16) \
49 + (sim_core_read_aligned_1 (scpu, cia, read_map, addr+2) << 8) \
50 + (sim_core_read_aligned_1 (scpu, cia, read_map, addr+3)))
52 #define EXTRACT_OFFSET(addr) \
55 ((sim_core_read_aligned_1 (scpu, cia, read_map, addr) << 8) \
56 + (sim_core_read_aligned_1 (scpu, cia, read_map, addr+1))) << 16) >> 16)
59 moxie_extract_unsigned_integer (const unsigned char *addr
, int len
)
63 unsigned char * startaddr
= (unsigned char *)addr
;
64 unsigned char * endaddr
= startaddr
+ len
;
66 if (len
> (int) sizeof (unsigned long))
67 printf ("That operation is not available on integers of more than %zu bytes.",
68 sizeof (unsigned long));
70 /* Start at the most significant end of the integer, and work towards
71 the least significant. */
74 for (p
= endaddr
; p
> startaddr
;)
75 retval
= (retval
<< 8) | * -- p
;
81 moxie_store_unsigned_integer (unsigned char *addr
, int len
, unsigned long val
)
84 unsigned char * startaddr
= (unsigned char *)addr
;
85 unsigned char * endaddr
= startaddr
+ len
;
87 for (p
= endaddr
; p
> startaddr
;)
96 This state is maintained in host byte order. The fetch/store
97 register functions must translate between host byte order and the
98 target processor byte order. Keeping this data in target byte
99 order simplifies the register read/write functions. Keeping this
100 data in native order improves the performance of the simulator.
101 Simulation speed is deemed more important. */
103 #define NUM_MOXIE_REGS 17 /* Including PC */
104 #define NUM_MOXIE_SREGS 256 /* The special registers */
107 /* The ordering of the moxie_regset structure is matched in the
108 gdb/config/moxie/tm-moxie.h file in the REGISTER_NAMES macro. */
109 /* TODO: This should be moved to sim-main.h:_sim_cpu. */
112 int32_t regs
[NUM_MOXIE_REGS
+ 1]; /* primary registers */
113 int32_t sregs
[256]; /* special registers */
114 int32_t cc
; /* the condition code reg */
115 unsigned long long insts
; /* instruction counter */
124 /* TODO: This should be moved to sim-main.h:moxie_sim_cpu. */
127 struct moxie_regset asregs
;
128 int32_t asints
[1]; /* but accessed larger... */
132 set_initial_gprs (void)
136 /* Set up machine just out of reset. */
137 cpu
.asregs
.regs
[PC_REGNO
] = 0;
139 /* Clean out the register contents. */
140 for (i
= 0; i
< NUM_MOXIE_REGS
; i
++)
141 cpu
.asregs
.regs
[i
] = 0;
142 for (i
= 0; i
< NUM_MOXIE_SREGS
; i
++)
143 cpu
.asregs
.sregs
[i
] = 0;
146 /* Write a 1 byte value to memory. */
149 wbat (sim_cpu
*scpu
, int32_t pc
, int32_t x
, int32_t v
)
151 address_word cia
= CPU_PC_GET (scpu
);
153 sim_core_write_aligned_1 (scpu
, cia
, write_map
, x
, v
);
156 /* Write a 2 byte value to memory. */
159 wsat (sim_cpu
*scpu
, int32_t pc
, int32_t x
, int32_t v
)
161 address_word cia
= CPU_PC_GET (scpu
);
163 sim_core_write_aligned_2 (scpu
, cia
, write_map
, x
, v
);
166 /* Write a 4 byte value to memory. */
169 wlat (sim_cpu
*scpu
, int32_t pc
, int32_t x
, int32_t v
)
171 address_word cia
= CPU_PC_GET (scpu
);
173 sim_core_write_aligned_4 (scpu
, cia
, write_map
, x
, v
);
176 /* Read 2 bytes from memory. */
179 rsat (sim_cpu
*scpu
, int32_t pc
, int32_t x
)
181 address_word cia
= CPU_PC_GET (scpu
);
183 return (sim_core_read_aligned_2 (scpu
, cia
, read_map
, x
));
186 /* Read 1 byte from memory. */
189 rbat (sim_cpu
*scpu
, int32_t pc
, int32_t x
)
191 address_word cia
= CPU_PC_GET (scpu
);
193 return (sim_core_read_aligned_1 (scpu
, cia
, read_map
, x
));
196 /* Read 4 bytes from memory. */
199 rlat (sim_cpu
*scpu
, int32_t pc
, int32_t x
)
201 address_word cia
= CPU_PC_GET (scpu
);
203 return (sim_core_read_aligned_4 (scpu
, cia
, read_map
, x
));
206 #define CHECK_FLAG(T,H) if (tflags & T) { hflags |= H; tflags ^= T; }
209 convert_target_flags (unsigned int tflags
)
211 unsigned int hflags
= 0x0;
213 CHECK_FLAG(0x0001, O_WRONLY
);
214 CHECK_FLAG(0x0002, O_RDWR
);
215 CHECK_FLAG(0x0008, O_APPEND
);
216 CHECK_FLAG(0x0200, O_CREAT
);
217 CHECK_FLAG(0x0400, O_TRUNC
);
218 CHECK_FLAG(0x0800, O_EXCL
);
219 CHECK_FLAG(0x2000, O_SYNC
);
223 "Simulator Error: problem converting target open flags for host. 0x%x\n",
229 /* TODO: Split this up into finger trace levels than just insn. */
230 #define MOXIE_TRACE_INSN(str) \
231 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", \
232 opc, str, cpu.asregs.regs[0], cpu.asregs.regs[1], \
233 cpu.asregs.regs[2], cpu.asregs.regs[3], cpu.asregs.regs[4], \
234 cpu.asregs.regs[5], cpu.asregs.regs[6], cpu.asregs.regs[7], \
235 cpu.asregs.regs[8], cpu.asregs.regs[9], cpu.asregs.regs[10], \
236 cpu.asregs.regs[11], cpu.asregs.regs[12], cpu.asregs.regs[13], \
237 cpu.asregs.regs[14], cpu.asregs.regs[15])
240 sim_engine_run (SIM_DESC sd
,
241 int next_cpu_nr
, /* ignore */
242 int nr_cpus
, /* ignore */
243 int siggnal
) /* ignore */
247 sim_cpu
*scpu
= STATE_CPU (sd
, 0); /* FIXME */
248 address_word cia
= CPU_PC_GET (scpu
);
250 pc
= cpu
.asregs
.regs
[PC_REGNO
];
252 /* Run instructions here. */
257 /* Fetch the instruction at pc. */
258 inst
= (sim_core_read_aligned_1 (scpu
, cia
, read_map
, pc
) << 8)
259 + sim_core_read_aligned_1 (scpu
, cia
, read_map
, pc
+1);
261 /* Decode instruction. */
262 if (inst
& (1 << 15))
264 if (inst
& (1 << 14))
266 /* This is a Form 3 instruction. */
267 int opcode
= (inst
>> 10 & 0xf);
273 MOXIE_TRACE_INSN ("beq");
274 if (cpu
.asregs
.cc
& CC_EQ
)
275 pc
+= INST2OFFSET(inst
);
280 MOXIE_TRACE_INSN ("bne");
281 if (! (cpu
.asregs
.cc
& CC_EQ
))
282 pc
+= INST2OFFSET(inst
);
287 MOXIE_TRACE_INSN ("blt");
288 if (cpu
.asregs
.cc
& CC_LT
)
289 pc
+= INST2OFFSET(inst
);
293 MOXIE_TRACE_INSN ("bgt");
294 if (cpu
.asregs
.cc
& CC_GT
)
295 pc
+= INST2OFFSET(inst
);
298 case 0x04: /* bltu */
300 MOXIE_TRACE_INSN ("bltu");
301 if (cpu
.asregs
.cc
& CC_LTU
)
302 pc
+= INST2OFFSET(inst
);
305 case 0x05: /* bgtu */
307 MOXIE_TRACE_INSN ("bgtu");
308 if (cpu
.asregs
.cc
& CC_GTU
)
309 pc
+= INST2OFFSET(inst
);
314 MOXIE_TRACE_INSN ("bge");
315 if (cpu
.asregs
.cc
& (CC_GT
| CC_EQ
))
316 pc
+= INST2OFFSET(inst
);
321 MOXIE_TRACE_INSN ("ble");
322 if (cpu
.asregs
.cc
& (CC_LT
| CC_EQ
))
323 pc
+= INST2OFFSET(inst
);
326 case 0x08: /* bgeu */
328 MOXIE_TRACE_INSN ("bgeu");
329 if (cpu
.asregs
.cc
& (CC_GTU
| CC_EQ
))
330 pc
+= INST2OFFSET(inst
);
333 case 0x09: /* bleu */
335 MOXIE_TRACE_INSN ("bleu");
336 if (cpu
.asregs
.cc
& (CC_LTU
| CC_EQ
))
337 pc
+= INST2OFFSET(inst
);
342 MOXIE_TRACE_INSN ("SIGILL3");
343 sim_engine_halt (sd
, scpu
, NULL
, pc
, sim_stopped
, SIM_SIGILL
);
350 /* This is a Form 2 instruction. */
351 int opcode
= (inst
>> 12 & 0x3);
356 int a
= (inst
>> 8) & 0xf;
357 unsigned av
= cpu
.asregs
.regs
[a
];
358 unsigned v
= (inst
& 0xff);
360 MOXIE_TRACE_INSN ("inc");
361 cpu
.asregs
.regs
[a
] = av
+ v
;
366 int a
= (inst
>> 8) & 0xf;
367 unsigned av
= cpu
.asregs
.regs
[a
];
368 unsigned v
= (inst
& 0xff);
370 MOXIE_TRACE_INSN ("dec");
371 cpu
.asregs
.regs
[a
] = av
- v
;
376 int a
= (inst
>> 8) & 0xf;
377 unsigned v
= (inst
& 0xff);
379 MOXIE_TRACE_INSN ("gsr");
380 cpu
.asregs
.regs
[a
] = cpu
.asregs
.sregs
[v
];
385 int a
= (inst
>> 8) & 0xf;
386 unsigned v
= (inst
& 0xff);
388 MOXIE_TRACE_INSN ("ssr");
389 cpu
.asregs
.sregs
[v
] = cpu
.asregs
.regs
[a
];
393 MOXIE_TRACE_INSN ("SIGILL2");
394 sim_engine_halt (sd
, scpu
, NULL
, pc
, sim_stopped
, SIM_SIGILL
);
401 /* This is a Form 1 instruction. */
402 int opcode
= inst
>> 8;
407 MOXIE_TRACE_INSN ("SIGILL0");
408 sim_engine_halt (sd
, scpu
, NULL
, pc
, sim_stopped
, SIM_SIGILL
);
410 case 0x01: /* ldi.l (immediate) */
412 int reg
= (inst
>> 4) & 0xf;
413 unsigned int val
= EXTRACT_WORD(pc
+2);
415 MOXIE_TRACE_INSN ("ldi.l");
416 cpu
.asregs
.regs
[reg
] = val
;
420 case 0x02: /* mov (register-to-register) */
422 int dest
= (inst
>> 4) & 0xf;
423 int src
= (inst
) & 0xf;
425 MOXIE_TRACE_INSN ("mov");
426 cpu
.asregs
.regs
[dest
] = cpu
.asregs
.regs
[src
];
429 case 0x03: /* jsra */
431 unsigned int fn
= EXTRACT_WORD(pc
+2);
432 unsigned int sp
= cpu
.asregs
.regs
[1];
434 MOXIE_TRACE_INSN ("jsra");
435 /* Save a slot for the static chain. */
438 /* Push the return address. */
440 wlat (scpu
, opc
, sp
, pc
+ 6);
442 /* Push the current frame pointer. */
444 wlat (scpu
, opc
, sp
, cpu
.asregs
.regs
[0]);
446 /* Uncache the stack pointer and set the pc and $fp. */
447 cpu
.asregs
.regs
[1] = sp
;
448 cpu
.asregs
.regs
[0] = sp
;
454 unsigned int sp
= cpu
.asregs
.regs
[0];
456 MOXIE_TRACE_INSN ("ret");
458 /* Pop the frame pointer. */
459 cpu
.asregs
.regs
[0] = rlat (scpu
, opc
, sp
);
462 /* Pop the return address. */
463 pc
= rlat (scpu
, opc
, sp
) - 2;
466 /* Skip over the static chain slot. */
469 /* Uncache the stack pointer. */
470 cpu
.asregs
.regs
[1] = sp
;
473 case 0x05: /* add.l */
475 int a
= (inst
>> 4) & 0xf;
477 unsigned av
= cpu
.asregs
.regs
[a
];
478 unsigned bv
= cpu
.asregs
.regs
[b
];
480 MOXIE_TRACE_INSN ("add.l");
481 cpu
.asregs
.regs
[a
] = av
+ bv
;
484 case 0x06: /* push */
486 int a
= (inst
>> 4) & 0xf;
488 int sp
= cpu
.asregs
.regs
[a
] - 4;
490 MOXIE_TRACE_INSN ("push");
491 wlat (scpu
, opc
, sp
, cpu
.asregs
.regs
[b
]);
492 cpu
.asregs
.regs
[a
] = sp
;
497 int a
= (inst
>> 4) & 0xf;
499 int sp
= cpu
.asregs
.regs
[a
];
501 MOXIE_TRACE_INSN ("pop");
502 cpu
.asregs
.regs
[b
] = rlat (scpu
, opc
, sp
);
503 cpu
.asregs
.regs
[a
] = sp
+ 4;
506 case 0x08: /* lda.l */
508 int reg
= (inst
>> 4) & 0xf;
509 unsigned int addr
= EXTRACT_WORD(pc
+2);
511 MOXIE_TRACE_INSN ("lda.l");
512 cpu
.asregs
.regs
[reg
] = rlat (scpu
, opc
, addr
);
516 case 0x09: /* sta.l */
518 int reg
= (inst
>> 4) & 0xf;
519 unsigned int addr
= EXTRACT_WORD(pc
+2);
521 MOXIE_TRACE_INSN ("sta.l");
522 wlat (scpu
, opc
, addr
, cpu
.asregs
.regs
[reg
]);
526 case 0x0a: /* ld.l (register indirect) */
528 int src
= inst
& 0xf;
529 int dest
= (inst
>> 4) & 0xf;
532 MOXIE_TRACE_INSN ("ld.l");
533 xv
= cpu
.asregs
.regs
[src
];
534 cpu
.asregs
.regs
[dest
] = rlat (scpu
, opc
, xv
);
537 case 0x0b: /* st.l */
539 int dest
= (inst
>> 4) & 0xf;
540 int val
= inst
& 0xf;
542 MOXIE_TRACE_INSN ("st.l");
543 wlat (scpu
, opc
, cpu
.asregs
.regs
[dest
], cpu
.asregs
.regs
[val
]);
546 case 0x0c: /* ldo.l */
548 unsigned int addr
= EXTRACT_OFFSET(pc
+2);
549 int a
= (inst
>> 4) & 0xf;
552 MOXIE_TRACE_INSN ("ldo.l");
553 addr
+= cpu
.asregs
.regs
[b
];
554 cpu
.asregs
.regs
[a
] = rlat (scpu
, opc
, addr
);
558 case 0x0d: /* sto.l */
560 unsigned int addr
= EXTRACT_OFFSET(pc
+2);
561 int a
= (inst
>> 4) & 0xf;
564 MOXIE_TRACE_INSN ("sto.l");
565 addr
+= cpu
.asregs
.regs
[a
];
566 wlat (scpu
, opc
, addr
, cpu
.asregs
.regs
[b
]);
572 int a
= (inst
>> 4) & 0xf;
575 int va
= cpu
.asregs
.regs
[a
];
576 int vb
= cpu
.asregs
.regs
[b
];
578 MOXIE_TRACE_INSN ("cmp");
583 cc
|= (va
< vb
? CC_LT
: 0);
584 cc
|= (va
> vb
? CC_GT
: 0);
585 cc
|= ((unsigned int) va
< (unsigned int) vb
? CC_LTU
: 0);
586 cc
|= ((unsigned int) va
> (unsigned int) vb
? CC_GTU
: 0);
594 case 0x10: /* sex.b */
596 int a
= (inst
>> 4) & 0xf;
598 signed char bv
= cpu
.asregs
.regs
[b
];
600 MOXIE_TRACE_INSN ("sex.b");
601 cpu
.asregs
.regs
[a
] = (int) bv
;
604 case 0x11: /* sex.s */
606 int a
= (inst
>> 4) & 0xf;
608 signed short bv
= cpu
.asregs
.regs
[b
];
610 MOXIE_TRACE_INSN ("sex.s");
611 cpu
.asregs
.regs
[a
] = (int) bv
;
614 case 0x12: /* zex.b */
616 int a
= (inst
>> 4) & 0xf;
618 signed char bv
= cpu
.asregs
.regs
[b
];
620 MOXIE_TRACE_INSN ("zex.b");
621 cpu
.asregs
.regs
[a
] = (int) bv
& 0xff;
624 case 0x13: /* zex.s */
626 int a
= (inst
>> 4) & 0xf;
628 signed short bv
= cpu
.asregs
.regs
[b
];
630 MOXIE_TRACE_INSN ("zex.s");
631 cpu
.asregs
.regs
[a
] = (int) bv
& 0xffff;
634 case 0x14: /* umul.x */
636 int a
= (inst
>> 4) & 0xf;
638 unsigned av
= cpu
.asregs
.regs
[a
];
639 unsigned bv
= cpu
.asregs
.regs
[b
];
640 unsigned long long r
=
641 (unsigned long long) av
* (unsigned long long) bv
;
643 MOXIE_TRACE_INSN ("umul.x");
644 cpu
.asregs
.regs
[a
] = r
>> 32;
647 case 0x15: /* mul.x */
649 int a
= (inst
>> 4) & 0xf;
651 unsigned av
= cpu
.asregs
.regs
[a
];
652 unsigned bv
= cpu
.asregs
.regs
[b
];
654 (signed long long) av
* (signed long long) bv
;
656 MOXIE_TRACE_INSN ("mul.x");
657 cpu
.asregs
.regs
[a
] = r
>> 32;
665 MOXIE_TRACE_INSN ("SIGILL0");
666 sim_engine_halt (sd
, scpu
, NULL
, pc
, sim_stopped
, SIM_SIGILL
);
671 unsigned int fn
= cpu
.asregs
.regs
[(inst
>> 4) & 0xf];
672 unsigned int sp
= cpu
.asregs
.regs
[1];
674 MOXIE_TRACE_INSN ("jsr");
676 /* Save a slot for the static chain. */
679 /* Push the return address. */
681 wlat (scpu
, opc
, sp
, pc
+ 2);
683 /* Push the current frame pointer. */
685 wlat (scpu
, opc
, sp
, cpu
.asregs
.regs
[0]);
687 /* Uncache the stack pointer and set the fp & pc. */
688 cpu
.asregs
.regs
[1] = sp
;
689 cpu
.asregs
.regs
[0] = sp
;
693 case 0x1a: /* jmpa */
695 unsigned int tgt
= EXTRACT_WORD(pc
+2);
697 MOXIE_TRACE_INSN ("jmpa");
701 case 0x1b: /* ldi.b (immediate) */
703 int reg
= (inst
>> 4) & 0xf;
704 unsigned int val
= EXTRACT_WORD(pc
+2);
706 MOXIE_TRACE_INSN ("ldi.b");
707 cpu
.asregs
.regs
[reg
] = val
;
711 case 0x1c: /* ld.b (register indirect) */
713 int src
= inst
& 0xf;
714 int dest
= (inst
>> 4) & 0xf;
717 MOXIE_TRACE_INSN ("ld.b");
718 xv
= cpu
.asregs
.regs
[src
];
719 cpu
.asregs
.regs
[dest
] = rbat (scpu
, opc
, xv
);
722 case 0x1d: /* lda.b */
724 int reg
= (inst
>> 4) & 0xf;
725 unsigned int addr
= EXTRACT_WORD(pc
+2);
727 MOXIE_TRACE_INSN ("lda.b");
728 cpu
.asregs
.regs
[reg
] = rbat (scpu
, opc
, addr
);
732 case 0x1e: /* st.b */
734 int dest
= (inst
>> 4) & 0xf;
735 int val
= inst
& 0xf;
737 MOXIE_TRACE_INSN ("st.b");
738 wbat (scpu
, opc
, cpu
.asregs
.regs
[dest
], cpu
.asregs
.regs
[val
]);
741 case 0x1f: /* sta.b */
743 int reg
= (inst
>> 4) & 0xf;
744 unsigned int addr
= EXTRACT_WORD(pc
+2);
746 MOXIE_TRACE_INSN ("sta.b");
747 wbat (scpu
, opc
, addr
, cpu
.asregs
.regs
[reg
]);
751 case 0x20: /* ldi.s (immediate) */
753 int reg
= (inst
>> 4) & 0xf;
755 unsigned int val
= EXTRACT_WORD(pc
+2);
757 MOXIE_TRACE_INSN ("ldi.s");
758 cpu
.asregs
.regs
[reg
] = val
;
762 case 0x21: /* ld.s (register indirect) */
764 int src
= inst
& 0xf;
765 int dest
= (inst
>> 4) & 0xf;
768 MOXIE_TRACE_INSN ("ld.s");
769 xv
= cpu
.asregs
.regs
[src
];
770 cpu
.asregs
.regs
[dest
] = rsat (scpu
, opc
, xv
);
773 case 0x22: /* lda.s */
775 int reg
= (inst
>> 4) & 0xf;
776 unsigned int addr
= EXTRACT_WORD(pc
+2);
778 MOXIE_TRACE_INSN ("lda.s");
779 cpu
.asregs
.regs
[reg
] = rsat (scpu
, opc
, addr
);
783 case 0x23: /* st.s */
785 int dest
= (inst
>> 4) & 0xf;
786 int val
= inst
& 0xf;
788 MOXIE_TRACE_INSN ("st.s");
789 wsat (scpu
, opc
, cpu
.asregs
.regs
[dest
], cpu
.asregs
.regs
[val
]);
792 case 0x24: /* sta.s */
794 int reg
= (inst
>> 4) & 0xf;
795 unsigned int addr
= EXTRACT_WORD(pc
+2);
797 MOXIE_TRACE_INSN ("sta.s");
798 wsat (scpu
, opc
, addr
, cpu
.asregs
.regs
[reg
]);
804 int reg
= (inst
>> 4) & 0xf;
806 MOXIE_TRACE_INSN ("jmp");
807 pc
= cpu
.asregs
.regs
[reg
] - 2;
812 int a
= (inst
>> 4) & 0xf;
816 MOXIE_TRACE_INSN ("and");
817 av
= cpu
.asregs
.regs
[a
];
818 bv
= cpu
.asregs
.regs
[b
];
819 cpu
.asregs
.regs
[a
] = av
& bv
;
822 case 0x27: /* lshr */
824 int a
= (inst
>> 4) & 0xf;
826 int av
= cpu
.asregs
.regs
[a
];
827 int bv
= cpu
.asregs
.regs
[b
];
829 MOXIE_TRACE_INSN ("lshr");
830 cpu
.asregs
.regs
[a
] = (unsigned) ((unsigned) av
>> bv
);
833 case 0x28: /* ashl */
835 int a
= (inst
>> 4) & 0xf;
837 int av
= cpu
.asregs
.regs
[a
];
838 int bv
= cpu
.asregs
.regs
[b
];
840 MOXIE_TRACE_INSN ("ashl");
841 cpu
.asregs
.regs
[a
] = av
<< bv
;
844 case 0x29: /* sub.l */
846 int a
= (inst
>> 4) & 0xf;
848 unsigned av
= cpu
.asregs
.regs
[a
];
849 unsigned bv
= cpu
.asregs
.regs
[b
];
851 MOXIE_TRACE_INSN ("sub.l");
852 cpu
.asregs
.regs
[a
] = av
- bv
;
857 int a
= (inst
>> 4) & 0xf;
859 int bv
= cpu
.asregs
.regs
[b
];
861 MOXIE_TRACE_INSN ("neg");
862 cpu
.asregs
.regs
[a
] = - bv
;
867 int a
= (inst
>> 4) & 0xf;
871 MOXIE_TRACE_INSN ("or");
872 av
= cpu
.asregs
.regs
[a
];
873 bv
= cpu
.asregs
.regs
[b
];
874 cpu
.asregs
.regs
[a
] = av
| bv
;
879 int a
= (inst
>> 4) & 0xf;
881 int bv
= cpu
.asregs
.regs
[b
];
883 MOXIE_TRACE_INSN ("not");
884 cpu
.asregs
.regs
[a
] = 0xffffffff ^ bv
;
887 case 0x2d: /* ashr */
889 int a
= (inst
>> 4) & 0xf;
891 int av
= cpu
.asregs
.regs
[a
];
892 int bv
= cpu
.asregs
.regs
[b
];
894 MOXIE_TRACE_INSN ("ashr");
895 cpu
.asregs
.regs
[a
] = av
>> bv
;
900 int a
= (inst
>> 4) & 0xf;
904 MOXIE_TRACE_INSN ("xor");
905 av
= cpu
.asregs
.regs
[a
];
906 bv
= cpu
.asregs
.regs
[b
];
907 cpu
.asregs
.regs
[a
] = av
^ bv
;
910 case 0x2f: /* mul.l */
912 int a
= (inst
>> 4) & 0xf;
914 unsigned av
= cpu
.asregs
.regs
[a
];
915 unsigned bv
= cpu
.asregs
.regs
[b
];
917 MOXIE_TRACE_INSN ("mul.l");
918 cpu
.asregs
.regs
[a
] = av
* bv
;
923 unsigned int inum
= EXTRACT_WORD(pc
+2);
925 MOXIE_TRACE_INSN ("swi");
926 /* Set the special registers appropriately. */
927 cpu
.asregs
.sregs
[2] = 3; /* MOXIE_EX_SWI */
928 cpu
.asregs
.sregs
[3] = inum
;
931 case TARGET_NEWLIB_SYS_exit
:
933 sim_engine_halt (sd
, scpu
, NULL
, pc
, sim_exited
,
937 case TARGET_NEWLIB_SYS_open
:
940 int mode
= (int) convert_target_flags ((unsigned) cpu
.asregs
.regs
[3]);
942 sim_core_read_buffer (sd
, scpu
, read_map
, fname
,
943 cpu
.asregs
.regs
[2], 1024);
944 fd
= sim_io_open (sd
, fname
, mode
);
945 /* FIXME - set errno */
946 cpu
.asregs
.regs
[2] = fd
;
949 case TARGET_NEWLIB_SYS_read
:
951 int fd
= cpu
.asregs
.regs
[2];
952 unsigned len
= (unsigned) cpu
.asregs
.regs
[4];
953 char *buf
= malloc (len
);
954 cpu
.asregs
.regs
[2] = sim_io_read (sd
, fd
, buf
, len
);
955 sim_core_write_buffer (sd
, scpu
, write_map
, buf
,
956 cpu
.asregs
.regs
[3], len
);
960 case TARGET_NEWLIB_SYS_write
:
963 /* String length is at 0x12($fp) */
964 unsigned count
, len
= (unsigned) cpu
.asregs
.regs
[4];
966 sim_core_read_buffer (sd
, scpu
, read_map
, str
,
967 cpu
.asregs
.regs
[3], len
);
968 count
= sim_io_write (sd
, cpu
.asregs
.regs
[2], str
, len
);
970 cpu
.asregs
.regs
[2] = count
;
973 case TARGET_NEWLIB_SYS_unlink
:
977 sim_core_read_buffer (sd
, scpu
, read_map
, fname
,
978 cpu
.asregs
.regs
[2], 1024);
979 fd
= sim_io_unlink (sd
, fname
);
980 /* FIXME - set errno */
981 cpu
.asregs
.regs
[2] = fd
;
984 case 0xffffffff: /* Linux System Call */
986 unsigned int handler
= cpu
.asregs
.sregs
[1];
987 unsigned int sp
= cpu
.asregs
.regs
[1];
989 /* Save a slot for the static chain. */
992 /* Push the return address. */
994 wlat (scpu
, opc
, sp
, pc
+ 6);
996 /* Push the current frame pointer. */
998 wlat (scpu
, opc
, sp
, cpu
.asregs
.regs
[0]);
1000 /* Uncache the stack pointer and set the fp & pc. */
1001 cpu
.asregs
.regs
[1] = sp
;
1002 cpu
.asregs
.regs
[0] = sp
;
1011 case 0x31: /* div.l */
1013 int a
= (inst
>> 4) & 0xf;
1015 int av
= cpu
.asregs
.regs
[a
];
1016 int bv
= cpu
.asregs
.regs
[b
];
1018 MOXIE_TRACE_INSN ("div.l");
1019 cpu
.asregs
.regs
[a
] = av
/ bv
;
1022 case 0x32: /* udiv.l */
1024 int a
= (inst
>> 4) & 0xf;
1026 unsigned int av
= cpu
.asregs
.regs
[a
];
1027 unsigned int bv
= cpu
.asregs
.regs
[b
];
1029 MOXIE_TRACE_INSN ("udiv.l");
1030 cpu
.asregs
.regs
[a
] = (av
/ bv
);
1033 case 0x33: /* mod.l */
1035 int a
= (inst
>> 4) & 0xf;
1037 int av
= cpu
.asregs
.regs
[a
];
1038 int bv
= cpu
.asregs
.regs
[b
];
1040 MOXIE_TRACE_INSN ("mod.l");
1041 cpu
.asregs
.regs
[a
] = av
% bv
;
1044 case 0x34: /* umod.l */
1046 int a
= (inst
>> 4) & 0xf;
1048 unsigned int av
= cpu
.asregs
.regs
[a
];
1049 unsigned int bv
= cpu
.asregs
.regs
[b
];
1051 MOXIE_TRACE_INSN ("umod.l");
1052 cpu
.asregs
.regs
[a
] = (av
% bv
);
1055 case 0x35: /* brk */
1056 MOXIE_TRACE_INSN ("brk");
1057 sim_engine_halt (sd
, scpu
, NULL
, pc
, sim_stopped
, SIM_SIGTRAP
);
1058 pc
-= 2; /* Adjust pc */
1060 case 0x36: /* ldo.b */
1062 unsigned int addr
= EXTRACT_OFFSET(pc
+2);
1063 int a
= (inst
>> 4) & 0xf;
1066 MOXIE_TRACE_INSN ("ldo.b");
1067 addr
+= cpu
.asregs
.regs
[b
];
1068 cpu
.asregs
.regs
[a
] = rbat (scpu
, opc
, addr
);
1072 case 0x37: /* sto.b */
1074 unsigned int addr
= EXTRACT_OFFSET(pc
+2);
1075 int a
= (inst
>> 4) & 0xf;
1078 MOXIE_TRACE_INSN ("sto.b");
1079 addr
+= cpu
.asregs
.regs
[a
];
1080 wbat (scpu
, opc
, addr
, cpu
.asregs
.regs
[b
]);
1084 case 0x38: /* ldo.s */
1086 unsigned int addr
= EXTRACT_OFFSET(pc
+2);
1087 int a
= (inst
>> 4) & 0xf;
1090 MOXIE_TRACE_INSN ("ldo.s");
1091 addr
+= cpu
.asregs
.regs
[b
];
1092 cpu
.asregs
.regs
[a
] = rsat (scpu
, opc
, addr
);
1096 case 0x39: /* sto.s */
1098 unsigned int addr
= EXTRACT_OFFSET(pc
+2);
1099 int a
= (inst
>> 4) & 0xf;
1102 MOXIE_TRACE_INSN ("sto.s");
1103 addr
+= cpu
.asregs
.regs
[a
];
1104 wsat (scpu
, opc
, addr
, cpu
.asregs
.regs
[b
]);
1110 MOXIE_TRACE_INSN ("SIGILL1");
1111 sim_engine_halt (sd
, scpu
, NULL
, pc
, sim_stopped
, SIM_SIGILL
);
1118 cpu
.asregs
.regs
[PC_REGNO
] = pc
;
1120 if (sim_events_tick (sd
))
1121 sim_events_process (sd
);
1127 moxie_reg_store (SIM_CPU
*scpu
, int rn
, const void *memory
, int length
)
1129 if (rn
< NUM_MOXIE_REGS
&& rn
>= 0)
1135 /* misalignment safe */
1136 ival
= moxie_extract_unsigned_integer (memory
, 4);
1137 cpu
.asints
[rn
] = ival
;
1147 moxie_reg_fetch (SIM_CPU
*scpu
, int rn
, void *memory
, int length
)
1149 if (rn
< NUM_MOXIE_REGS
&& rn
>= 0)
1153 long ival
= cpu
.asints
[rn
];
1155 /* misalignment-safe */
1156 moxie_store_unsigned_integer (memory
, 4, ival
);
1166 moxie_pc_get (sim_cpu
*cpu
)
1168 return MOXIE_SIM_CPU (cpu
)->registers
[PCIDX
];
1172 moxie_pc_set (sim_cpu
*cpu
, sim_cia pc
)
1174 MOXIE_SIM_CPU (cpu
)->registers
[PCIDX
] = pc
;
1178 free_state (SIM_DESC sd
)
1180 if (STATE_MODULES (sd
) != NULL
)
1181 sim_module_uninstall (sd
);
1182 sim_cpu_free_all (sd
);
1183 sim_state_free (sd
);
1187 sim_open (SIM_OPEN_KIND kind
, host_callback
*cb
,
1188 struct bfd
*abfd
, char * const *argv
)
1191 SIM_DESC sd
= sim_state_alloc (kind
, cb
);
1192 SIM_ASSERT (STATE_MAGIC (sd
) == SIM_MAGIC_NUMBER
);
1194 /* Set default options before parsing user options. */
1195 current_target_byte_order
= BFD_ENDIAN_BIG
;
1197 /* The cpu data is kept in a separately allocated chunk of memory. */
1198 if (sim_cpu_alloc_all_extra (sd
, 0, sizeof (struct moxie_sim_cpu
))
1205 if (sim_pre_argv_init (sd
, argv
[0]) != SIM_RC_OK
)
1211 /* The parser will print an error message for us, so we silently return. */
1212 if (sim_parse_args (sd
, argv
) != SIM_RC_OK
)
1218 sim_do_command(sd
," memory region 0x00000000,0x4000000") ;
1219 sim_do_command(sd
," memory region 0xE0000000,0x10000") ;
1221 /* Check for/establish the a reference program image. */
1222 if (sim_analyze_program (sd
, STATE_PROG_FILE (sd
), abfd
) != SIM_RC_OK
)
1228 /* Configure/verify the target byte order and other runtime
1229 configuration options. */
1230 if (sim_config (sd
) != SIM_RC_OK
)
1232 sim_module_uninstall (sd
);
1236 if (sim_post_argv_init (sd
) != SIM_RC_OK
)
1238 /* Uninstall the modules to avoid memory leaks,
1239 file descriptor leaks, etc. */
1240 sim_module_uninstall (sd
);
1244 /* CPU specific initialization. */
1245 for (i
= 0; i
< MAX_NR_PROCESSORS
; ++i
)
1247 SIM_CPU
*cpu
= STATE_CPU (sd
, i
);
1249 CPU_REG_FETCH (cpu
) = moxie_reg_fetch
;
1250 CPU_REG_STORE (cpu
) = moxie_reg_store
;
1251 CPU_PC_FETCH (cpu
) = moxie_pc_get
;
1252 CPU_PC_STORE (cpu
) = moxie_pc_set
;
1254 set_initial_gprs (); /* Reset the GPR registers. */
1260 /* Load the device tree blob. */
1263 load_dtb (SIM_DESC sd
, const char *filename
)
1266 FILE *f
= fopen (filename
, "rb");
1268 sim_cpu
*scpu
= STATE_CPU (sd
, 0); /* FIXME */
1270 /* Don't warn as the sim works fine w/out a device tree. */
1273 fseek (f
, 0, SEEK_END
);
1275 fseek (f
, 0, SEEK_SET
);
1276 buf
= alloca (size
);
1277 if (size
!= fread (buf
, 1, size
, f
))
1279 sim_io_eprintf (sd
, "ERROR: error reading ``%s''.\n", filename
);
1283 sim_core_write_buffer (sd
, scpu
, write_map
, buf
, 0xE0000000, size
);
1284 cpu
.asregs
.sregs
[9] = 0xE0000000;
1289 sim_create_inferior (SIM_DESC sd
, struct bfd
*prog_bfd
,
1290 char * const *argv
, char * const *env
)
1294 sim_cpu
*scpu
= STATE_CPU (sd
, 0); /* FIXME */
1296 if (prog_bfd
!= NULL
)
1297 cpu
.asregs
.regs
[PC_REGNO
] = bfd_get_start_address (prog_bfd
);
1299 /* Copy args into target memory. */
1301 for (argc
= 0; avp
&& *avp
; avp
++)
1304 /* Target memory looks like this:
1305 0x00000000 zero word
1306 0x00000004 argc word
1307 0x00000008 start of argv
1309 0x0000???? end of argv
1310 0x0000???? zero word
1311 0x0000???? start of data pointed to by argv */
1313 wlat (scpu
, 0, 0, 0);
1314 wlat (scpu
, 0, 4, argc
);
1316 /* tp is the offset of our first argv data. */
1317 tp
= 4 + 4 + argc
* 4 + 4;
1319 for (i
= 0; i
< argc
; i
++)
1321 /* Set the argv value. */
1322 wlat (scpu
, 0, 4 + 4 + i
* 4, tp
);
1324 /* Store the string. */
1325 sim_core_write_buffer (sd
, scpu
, write_map
, argv
[i
],
1326 tp
, strlen(argv
[i
])+1);
1327 tp
+= strlen (argv
[i
]) + 1;
1330 wlat (scpu
, 0, 4 + 4 + i
* 4, 0);