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