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