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