* config/tc-arm.c (s_arm_tls_desceq): Move code into ELF-only
[deliverable/binutils-gdb.git] / sim / moxie / interp.c
CommitLineData
fdd6fa61 1/* Simulator for the moxie processor
7b6bb8da 2 Copyright (C) 2008, 2009, 2010, 2011 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 {
32d49b7b
AG
417 case 0x00: /* bad */
418 opc = opcode;
419 TRACE("SIGILL0");
420 cpu.asregs.exception = SIGILL;
fdd6fa61
AG
421 break;
422 case 0x01: /* ldi.l (immediate) */
423 {
424 int reg = (inst >> 4) & 0xf;
425 TRACE("ldi.l");
5c27d164 426 unsigned int val = EXTRACT_WORD(pc+2);
fdd6fa61
AG
427 cpu.asregs.regs[reg] = val;
428 pc += 4;
429 }
430 break;
431 case 0x02: /* mov (register-to-register) */
432 {
433 int dest = (inst >> 4) & 0xf;
434 int src = (inst ) & 0xf;
435 TRACE("mov");
436 cpu.asregs.regs[dest] = cpu.asregs.regs[src];
437 }
438 break;
439 case 0x03: /* jsra */
440 {
5c27d164 441 unsigned int fn = EXTRACT_WORD(pc+2);
fdd6fa61
AG
442 unsigned int sp = cpu.asregs.regs[1];
443 TRACE("jsra");
444 /* Save a slot for the static chain. */
445 sp -= 4;
446
447 /* Push the return address. */
448 sp -= 4;
5c27d164 449 wlat (scpu, opc, sp, pc + 6);
fdd6fa61
AG
450
451 /* Push the current frame pointer. */
452 sp -= 4;
5c27d164 453 wlat (scpu, opc, sp, cpu.asregs.regs[0]);
fdd6fa61
AG
454
455 /* Uncache the stack pointer and set the pc and $fp. */
456 cpu.asregs.regs[1] = sp;
457 cpu.asregs.regs[0] = sp;
458 pc = fn - 2;
459 }
460 break;
461 case 0x04: /* ret */
462 {
463 unsigned int sp = cpu.asregs.regs[0];
464
465 TRACE("ret");
466
467 /* Pop the frame pointer. */
5c27d164 468 cpu.asregs.regs[0] = rlat (scpu, opc, sp);
fdd6fa61
AG
469 sp += 4;
470
471 /* Pop the return address. */
5c27d164 472 pc = rlat (scpu, opc, sp) - 2;
fdd6fa61
AG
473 sp += 4;
474
475 /* Skip over the static chain slot. */
476 sp += 4;
477
478 /* Uncache the stack pointer. */
479 cpu.asregs.regs[1] = sp;
480 }
481 break;
482 case 0x05: /* add.l */
483 {
484 int a = (inst >> 4) & 0xf;
485 int b = inst & 0xf;
486 unsigned av = cpu.asregs.regs[a];
487 unsigned bv = cpu.asregs.regs[b];
488 TRACE("add.l");
489 cpu.asregs.regs[a] = av + bv;
490 }
491 break;
492 case 0x06: /* push */
493 {
494 int a = (inst >> 4) & 0xf;
495 int b = inst & 0xf;
496 int sp = cpu.asregs.regs[a] - 4;
497 TRACE("push");
5c27d164 498 wlat (scpu, opc, sp, cpu.asregs.regs[b]);
fdd6fa61
AG
499 cpu.asregs.regs[a] = sp;
500 }
501 break;
502 case 0x07: /* pop */
503 {
504 int a = (inst >> 4) & 0xf;
505 int b = inst & 0xf;
506 int sp = cpu.asregs.regs[a];
507 TRACE("pop");
5c27d164 508 cpu.asregs.regs[b] = rlat (scpu, opc, sp);
fdd6fa61
AG
509 cpu.asregs.regs[a] = sp + 4;
510 }
511 break;
512 case 0x08: /* lda.l */
513 {
514 int reg = (inst >> 4) & 0xf;
5c27d164 515 unsigned int addr = EXTRACT_WORD(pc+2);
fdd6fa61 516 TRACE("lda.l");
5c27d164 517 cpu.asregs.regs[reg] = rlat (scpu, opc, addr);
fdd6fa61
AG
518 pc += 4;
519 }
520 break;
521 case 0x09: /* sta.l */
522 {
523 int reg = (inst >> 4) & 0xf;
5c27d164 524 unsigned int addr = EXTRACT_WORD(pc+2);
fdd6fa61 525 TRACE("sta.l");
5c27d164 526 wlat (scpu, opc, addr, cpu.asregs.regs[reg]);
fdd6fa61
AG
527 pc += 4;
528 }
529 break;
530 case 0x0a: /* ld.l (register indirect) */
531 {
532 int src = inst & 0xf;
533 int dest = (inst >> 4) & 0xf;
534 int xv;
535 TRACE("ld.l");
536 xv = cpu.asregs.regs[src];
5c27d164 537 cpu.asregs.regs[dest] = rlat (scpu, opc, xv);
fdd6fa61
AG
538 }
539 break;
540 case 0x0b: /* st.l */
541 {
542 int dest = (inst >> 4) & 0xf;
543 int val = inst & 0xf;
544 TRACE("st.l");
5c27d164 545 wlat (scpu, opc, cpu.asregs.regs[dest], cpu.asregs.regs[val]);
fdd6fa61
AG
546 }
547 break;
548 case 0x0c: /* ldo.l */
549 {
5c27d164 550 unsigned int addr = EXTRACT_WORD(pc+2);
fdd6fa61
AG
551 int a = (inst >> 4) & 0xf;
552 int b = inst & 0xf;
553 TRACE("ldo.l");
554 addr += cpu.asregs.regs[b];
5c27d164 555 cpu.asregs.regs[a] = rlat (scpu, opc, addr);
fdd6fa61
AG
556 pc += 4;
557 }
558 break;
559 case 0x0d: /* sto.l */
560 {
5c27d164 561 unsigned int addr = EXTRACT_WORD(pc+2);
fdd6fa61
AG
562 int a = (inst >> 4) & 0xf;
563 int b = inst & 0xf;
564 TRACE("sto.l");
565 addr += cpu.asregs.regs[a];
5c27d164 566 wlat (scpu, opc, addr, cpu.asregs.regs[b]);
fdd6fa61
AG
567 pc += 4;
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 TRACE("cmp");
579
580 if (va == vb)
581 cc = CC_EQ;
582 else
583 {
584 cc |= (va < vb ? CC_LT : 0);
585 cc |= (va > vb ? CC_GT : 0);
586 cc |= ((unsigned int) va < (unsigned int) vb ? CC_LTU : 0);
587 cc |= ((unsigned int) va > (unsigned int) vb ? CC_GTU : 0);
588 }
589
590 cpu.asregs.cc = cc;
591 }
592 break;
32d49b7b
AG
593 case 0x0f: /* nop */
594 break;
595 case 0x10: /* bad */
596 case 0x11: /* bad */
597 case 0x12: /* bad */
598 case 0x13: /* bad */
599 case 0x14: /* bad */
600 case 0x15: /* bad */
601 case 0x16: /* bad */
602 case 0x17: /* bad */
603 case 0x18: /* bad */
fdd6fa61 604 {
86566200
AG
605 opc = opcode;
606 TRACE("SIGILL0");
607 cpu.asregs.exception = SIGILL;
608 break;
fdd6fa61 609 }
fdd6fa61
AG
610 case 0x19: /* jsr */
611 {
612 unsigned int fn = cpu.asregs.regs[(inst >> 4) & 0xf];
613 unsigned int sp = cpu.asregs.regs[1];
614
615 TRACE("jsr");
616
617 /* Save a slot for the static chain. */
618 sp -= 4;
619
620 /* Push the return address. */
621 sp -= 4;
5c27d164 622 wlat (scpu, opc, sp, pc + 2);
fdd6fa61
AG
623
624 /* Push the current frame pointer. */
625 sp -= 4;
5c27d164 626 wlat (scpu, opc, sp, cpu.asregs.regs[0]);
fdd6fa61
AG
627
628 /* Uncache the stack pointer and set the fp & pc. */
629 cpu.asregs.regs[1] = sp;
630 cpu.asregs.regs[0] = sp;
631 pc = fn - 2;
632 }
633 break;
634 case 0x1a: /* jmpa */
635 {
5c27d164 636 unsigned int tgt = EXTRACT_WORD(pc+2);
fdd6fa61
AG
637 TRACE("jmpa");
638 pc = tgt - 2;
639 }
640 break;
641 case 0x1b: /* ldi.b (immediate) */
642 {
643 int reg = (inst >> 4) & 0xf;
644
5c27d164 645 unsigned int val = EXTRACT_WORD(pc+2);
fdd6fa61
AG
646 TRACE("ldi.b");
647 cpu.asregs.regs[reg] = val;
648 pc += 4;
649 }
650 break;
651 case 0x1c: /* ld.b (register indirect) */
652 {
653 int src = inst & 0xf;
654 int dest = (inst >> 4) & 0xf;
655 int xv;
656 TRACE("ld.b");
657 xv = cpu.asregs.regs[src];
5c27d164 658 cpu.asregs.regs[dest] = rbat (scpu, opc, xv);
fdd6fa61
AG
659 }
660 break;
661 case 0x1d: /* lda.b */
662 {
663 int reg = (inst >> 4) & 0xf;
5c27d164 664 unsigned int addr = EXTRACT_WORD(pc+2);
fdd6fa61 665 TRACE("lda.b");
5c27d164 666 cpu.asregs.regs[reg] = rbat (scpu, opc, addr);
fdd6fa61
AG
667 pc += 4;
668 }
669 break;
670 case 0x1e: /* st.b */
671 {
672 int dest = (inst >> 4) & 0xf;
673 int val = inst & 0xf;
674 TRACE("st.b");
5c27d164 675 wbat (scpu, opc, cpu.asregs.regs[dest], cpu.asregs.regs[val]);
fdd6fa61
AG
676 }
677 break;
678 case 0x1f: /* sta.b */
679 {
680 int reg = (inst >> 4) & 0xf;
5c27d164 681 unsigned int addr = EXTRACT_WORD(pc+2);
fdd6fa61 682 TRACE("sta.b");
5c27d164 683 wbat (scpu, opc, addr, cpu.asregs.regs[reg]);
fdd6fa61
AG
684 pc += 4;
685 }
686 break;
687 case 0x20: /* ldi.s (immediate) */
688 {
689 int reg = (inst >> 4) & 0xf;
690
5c27d164 691 unsigned int val = EXTRACT_WORD(pc+2);
fdd6fa61
AG
692 TRACE("ldi.s");
693 cpu.asregs.regs[reg] = val;
694 pc += 4;
695 }
696 break;
697 case 0x21: /* ld.s (register indirect) */
698 {
699 int src = inst & 0xf;
700 int dest = (inst >> 4) & 0xf;
701 int xv;
702 TRACE("ld.s");
703 xv = cpu.asregs.regs[src];
5c27d164 704 cpu.asregs.regs[dest] = rsat (scpu, opc, xv);
fdd6fa61
AG
705 }
706 break;
707 case 0x22: /* lda.s */
708 {
709 int reg = (inst >> 4) & 0xf;
5c27d164 710 unsigned int addr = EXTRACT_WORD(pc+2);
fdd6fa61 711 TRACE("lda.s");
5c27d164 712 cpu.asregs.regs[reg] = rsat (scpu, opc, addr);
fdd6fa61
AG
713 pc += 4;
714 }
715 break;
716 case 0x23: /* st.s */
717 {
718 int dest = (inst >> 4) & 0xf;
719 int val = inst & 0xf;
720 TRACE("st.s");
5c27d164 721 wsat (scpu, opc, cpu.asregs.regs[dest], cpu.asregs.regs[val]);
fdd6fa61
AG
722 }
723 break;
724 case 0x24: /* sta.s */
725 {
726 int reg = (inst >> 4) & 0xf;
5c27d164 727 unsigned int addr = EXTRACT_WORD(pc+2);
fdd6fa61 728 TRACE("sta.s");
5c27d164 729 wsat (scpu, opc, addr, cpu.asregs.regs[reg]);
fdd6fa61
AG
730 pc += 4;
731 }
732 break;
733 case 0x25: /* jmp */
734 {
735 int reg = (inst >> 4) & 0xf;
736 TRACE("jmp");
737 pc = cpu.asregs.regs[reg] - 2;
738 }
739 break;
740 case 0x26: /* and */
741 {
742 int a = (inst >> 4) & 0xf;
743 int b = inst & 0xf;
744 int av, bv;
745 TRACE("and");
746 av = cpu.asregs.regs[a];
747 bv = cpu.asregs.regs[b];
748 cpu.asregs.regs[a] = av & bv;
749 }
750 break;
751 case 0x27: /* lshr */
752 {
753 int a = (inst >> 4) & 0xf;
754 int b = inst & 0xf;
755 int av = cpu.asregs.regs[a];
756 int bv = cpu.asregs.regs[b];
757 TRACE("lshr");
758 cpu.asregs.regs[a] = (unsigned) ((unsigned) av >> bv);
759 }
760 break;
761 case 0x28: /* ashl */
762 {
763 int a = (inst >> 4) & 0xf;
764 int b = inst & 0xf;
765 int av = cpu.asregs.regs[a];
766 int bv = cpu.asregs.regs[b];
767 TRACE("ashl");
768 cpu.asregs.regs[a] = av << bv;
769 }
770 break;
771 case 0x29: /* sub.l */
772 {
773 int a = (inst >> 4) & 0xf;
774 int b = inst & 0xf;
775 unsigned av = cpu.asregs.regs[a];
776 unsigned bv = cpu.asregs.regs[b];
777 TRACE("sub.l");
778 cpu.asregs.regs[a] = av - bv;
779 }
780 break;
781 case 0x2a: /* neg */
782 {
783 int a = (inst >> 4) & 0xf;
784 int b = inst & 0xf;
785 int bv = cpu.asregs.regs[b];
786 TRACE("neg");
787 cpu.asregs.regs[a] = - bv;
788 }
789 break;
790 case 0x2b: /* or */
791 {
792 int a = (inst >> 4) & 0xf;
793 int b = inst & 0xf;
794 int av, bv;
795 TRACE("or");
796 av = cpu.asregs.regs[a];
797 bv = cpu.asregs.regs[b];
798 cpu.asregs.regs[a] = av | bv;
799 }
800 break;
801 case 0x2c: /* not */
802 {
803 int a = (inst >> 4) & 0xf;
804 int b = inst & 0xf;
805 int bv = cpu.asregs.regs[b];
806 TRACE("not");
807 cpu.asregs.regs[a] = 0xffffffff ^ bv;
808 }
809 break;
810 case 0x2d: /* ashr */
811 {
812 int a = (inst >> 4) & 0xf;
813 int b = inst & 0xf;
814 int av = cpu.asregs.regs[a];
815 int bv = cpu.asregs.regs[b];
816 TRACE("ashr");
817 cpu.asregs.regs[a] = av >> bv;
818 }
819 break;
820 case 0x2e: /* xor */
821 {
822 int a = (inst >> 4) & 0xf;
823 int b = inst & 0xf;
824 int av, bv;
825 TRACE("xor");
826 av = cpu.asregs.regs[a];
827 bv = cpu.asregs.regs[b];
828 cpu.asregs.regs[a] = av ^ bv;
829 }
830 break;
831 case 0x2f: /* mul.l */
832 {
833 int a = (inst >> 4) & 0xf;
834 int b = inst & 0xf;
835 unsigned av = cpu.asregs.regs[a];
836 unsigned bv = cpu.asregs.regs[b];
837 TRACE("mul.l");
838 cpu.asregs.regs[a] = av * bv;
839 }
840 break;
841 case 0x30: /* swi */
842 {
5c27d164 843 unsigned int inum = EXTRACT_WORD(pc+2);
fdd6fa61 844 TRACE("swi");
5c27d164
AG
845 /* Set the special registers appropriately. */
846 cpu.asregs.sregs[2] = 3; /* MOXIE_EX_SWI */
847 cpu.asregs.sregs[3] = inum;
fdd6fa61
AG
848 switch (inum)
849 {
850 case 0x1: /* SYS_exit */
851 {
852 cpu.asregs.exception = SIGQUIT;
853 break;
854 }
855 case 0x2: /* SYS_open */
856 {
5c27d164 857 char fname[1024];
fdd6fa61 858 int mode = (int) convert_target_flags ((unsigned) cpu.asregs.regs[3]);
7a321525 859 int perm = (int) cpu.asregs.regs[4];
fdd6fa61 860 int fd = open (fname, mode, perm);
5c27d164
AG
861 sim_core_read_buffer (sd, scpu, read_map, fname,
862 cpu.asregs.regs[2], 1024);
fdd6fa61
AG
863 /* FIXME - set errno */
864 cpu.asregs.regs[2] = fd;
865 break;
866 }
867 case 0x4: /* SYS_read */
868 {
869 int fd = cpu.asregs.regs[2];
7a321525 870 unsigned len = (unsigned) cpu.asregs.regs[4];
5c27d164 871 char *buf = malloc (len);
fdd6fa61 872 cpu.asregs.regs[2] = read (fd, buf, len);
5c27d164
AG
873 sim_core_write_buffer (sd, scpu, write_map, buf,
874 cpu.asregs.regs[3], len);
875 free (buf);
fdd6fa61
AG
876 break;
877 }
878 case 0x5: /* SYS_write */
879 {
5c27d164 880 char *str;
fdd6fa61 881 /* String length is at 0x12($fp) */
7a321525 882 unsigned count, len = (unsigned) cpu.asregs.regs[4];
5c27d164
AG
883 str = malloc (len);
884 sim_core_read_buffer (sd, scpu, read_map, str,
885 cpu.asregs.regs[3], len);
fdd6fa61 886 count = write (cpu.asregs.regs[2], str, len);
5c27d164 887 free (str);
fdd6fa61
AG
888 cpu.asregs.regs[2] = count;
889 break;
890 }
7a321525
AG
891 case 0xffffffff: /* Linux System Call */
892 {
893 unsigned int handler = cpu.asregs.sregs[1];
894 unsigned int sp = cpu.asregs.regs[1];
7a321525
AG
895
896 /* Save a slot for the static chain. */
897 sp -= 4;
898
899 /* Push the return address. */
900 sp -= 4;
5c27d164 901 wlat (scpu, opc, sp, pc + 6);
7a321525
AG
902
903 /* Push the current frame pointer. */
904 sp -= 4;
5c27d164 905 wlat (scpu, opc, sp, cpu.asregs.regs[0]);
7a321525
AG
906
907 /* Uncache the stack pointer and set the fp & pc. */
908 cpu.asregs.regs[1] = sp;
909 cpu.asregs.regs[0] = sp;
910 pc = handler - 6;
911 }
fdd6fa61
AG
912 default:
913 break;
914 }
915 pc += 4;
916 }
917 break;
918 case 0x31: /* div.l */
919 {
920 int a = (inst >> 4) & 0xf;
921 int b = inst & 0xf;
922 int av = cpu.asregs.regs[a];
923 int bv = cpu.asregs.regs[b];
924 TRACE("div.l");
925 cpu.asregs.regs[a] = av / bv;
926 }
927 break;
928 case 0x32: /* udiv.l */
929 {
930 int a = (inst >> 4) & 0xf;
931 int b = inst & 0xf;
932 unsigned int av = cpu.asregs.regs[a];
933 unsigned int bv = cpu.asregs.regs[b];
934 TRACE("udiv.l");
935 cpu.asregs.regs[a] = (av / bv);
936 }
937 break;
938 case 0x33: /* mod.l */
939 {
940 int a = (inst >> 4) & 0xf;
941 int b = inst & 0xf;
942 int av = cpu.asregs.regs[a];
943 int bv = cpu.asregs.regs[b];
944 TRACE("mod.l");
945 cpu.asregs.regs[a] = av % bv;
946 }
947 break;
948 case 0x34: /* umod.l */
949 {
950 int a = (inst >> 4) & 0xf;
951 int b = inst & 0xf;
952 unsigned int av = cpu.asregs.regs[a];
953 unsigned int bv = cpu.asregs.regs[b];
954 TRACE("umod.l");
955 cpu.asregs.regs[a] = (av % bv);
956 }
957 break;
958 case 0x35: /* brk */
959 TRACE("brk");
960 cpu.asregs.exception = SIGTRAP;
961 pc -= 2; /* Adjust pc */
962 break;
963 case 0x36: /* ldo.b */
964 {
5c27d164 965 unsigned int addr = EXTRACT_WORD(pc+2);
fdd6fa61
AG
966 int a = (inst >> 4) & 0xf;
967 int b = inst & 0xf;
968 TRACE("ldo.b");
969 addr += cpu.asregs.regs[b];
5c27d164 970 cpu.asregs.regs[a] = rbat (scpu, opc, addr);
fdd6fa61
AG
971 pc += 4;
972 }
973 break;
974 case 0x37: /* sto.b */
975 {
5c27d164 976 unsigned int addr = EXTRACT_WORD(pc+2);
fdd6fa61
AG
977 int a = (inst >> 4) & 0xf;
978 int b = inst & 0xf;
979 TRACE("sto.b");
980 addr += cpu.asregs.regs[a];
5c27d164 981 wbat (scpu, opc, addr, cpu.asregs.regs[b]);
fdd6fa61
AG
982 pc += 4;
983 }
984 break;
985 case 0x38: /* ldo.s */
986 {
5c27d164 987 unsigned int addr = EXTRACT_WORD(pc+2);
fdd6fa61
AG
988 int a = (inst >> 4) & 0xf;
989 int b = inst & 0xf;
990 TRACE("ldo.s");
991 addr += cpu.asregs.regs[b];
5c27d164 992 cpu.asregs.regs[a] = rsat (scpu, opc, addr);
fdd6fa61
AG
993 pc += 4;
994 }
995 break;
996 case 0x39: /* sto.s */
997 {
5c27d164 998 unsigned int addr = EXTRACT_WORD(pc+2);
fdd6fa61
AG
999 int a = (inst >> 4) & 0xf;
1000 int b = inst & 0xf;
1001 TRACE("sto.s");
1002 addr += cpu.asregs.regs[a];
5c27d164 1003 wsat (scpu, opc, addr, cpu.asregs.regs[b]);
fdd6fa61
AG
1004 pc += 4;
1005 }
1006 break;
1007 default:
1008 opc = opcode;
1009 TRACE("SIGILL1");
1010 cpu.asregs.exception = SIGILL;
1011 break;
1012 }
1013 }
1014
1015 insts++;
1016 pc += 2;
1017
1018 } while (!cpu.asregs.exception);
1019
1020 /* Hide away the things we've cached while executing. */
1021 cpu.asregs.regs[PC_REGNO] = pc;
1022 cpu.asregs.insts += insts; /* instructions done ... */
1023
1024 signal (SIGINT, sigsave);
1025}
1026
1027int
1028sim_write (sd, addr, buffer, size)
1029 SIM_DESC sd;
1030 SIM_ADDR addr;
5558e7e6 1031 const unsigned char * buffer;
fdd6fa61
AG
1032 int size;
1033{
5c27d164
AG
1034 sim_cpu *scpu = STATE_CPU (sd, 0); /* FIXME */
1035
1036 sim_core_write_buffer (sd, scpu, write_map, buffer, addr, size);
1037
fdd6fa61
AG
1038 return size;
1039}
1040
1041int
1042sim_read (sd, addr, buffer, size)
1043 SIM_DESC sd;
1044 SIM_ADDR addr;
1045 unsigned char * buffer;
1046 int size;
1047{
5c27d164
AG
1048 sim_cpu *scpu = STATE_CPU (sd, 0); /* FIXME */
1049
1050 sim_core_read_buffer (sd, scpu, read_map, buffer, addr, size);
fdd6fa61
AG
1051
1052 return size;
1053}
1054
1055
1056int
1057sim_store_register (sd, rn, memory, length)
1058 SIM_DESC sd;
1059 int rn;
1060 unsigned char * memory;
1061 int length;
1062{
fdd6fa61
AG
1063 if (rn < NUM_MOXIE_REGS && rn >= 0)
1064 {
1065 if (length == 4)
1066 {
1067 long ival;
1068
1069 /* misalignment safe */
1070 ival = moxie_extract_unsigned_integer (memory, 4);
1071 cpu.asints[rn] = ival;
1072 }
1073
1074 return 4;
1075 }
1076 else
1077 return 0;
1078}
1079
1080int
1081sim_fetch_register (sd, rn, memory, length)
1082 SIM_DESC sd;
1083 int rn;
1084 unsigned char * memory;
1085 int length;
1086{
fdd6fa61
AG
1087 if (rn < NUM_MOXIE_REGS && rn >= 0)
1088 {
1089 if (length == 4)
1090 {
1091 long ival = cpu.asints[rn];
1092
1093 /* misalignment-safe */
1094 moxie_store_unsigned_integer (memory, 4, ival);
1095 }
1096
1097 return 4;
1098 }
1099 else
1100 return 0;
1101}
1102
1103
1104int
1105sim_trace (sd)
1106 SIM_DESC sd;
1107{
1108 if (tracefile == 0)
1109 tracefile = fopen("trace.csv", "wb");
1110
1111 tracing = 1;
1112
1113 sim_resume (sd, 0, 0);
1114
1115 tracing = 0;
1116
1117 return 1;
1118}
1119
1120void
1121sim_stop_reason (sd, reason, sigrc)
1122 SIM_DESC sd;
1123 enum sim_stop * reason;
1124 int * sigrc;
1125{
1126 if (cpu.asregs.exception == SIGQUIT)
1127 {
1128 * reason = sim_exited;
1129 * sigrc = cpu.asregs.regs[2];
1130 }
1131 else
1132 {
1133 * reason = sim_stopped;
1134 * sigrc = cpu.asregs.exception;
1135 }
1136}
1137
1138
1139int
1140sim_stop (sd)
1141 SIM_DESC sd;
1142{
1143 cpu.asregs.exception = SIGINT;
1144 return 1;
1145}
1146
1147
1148void
1149sim_info (sd, verbose)
1150 SIM_DESC sd;
1151 int verbose;
1152{
1153 callback->printf_filtered (callback, "\n\n# instructions executed %llu\n",
1154 cpu.asregs.insts);
1155}
1156
1157
1158SIM_DESC
1159sim_open (kind, cb, abfd, argv)
1160 SIM_OPEN_KIND kind;
1161 host_callback * cb;
1162 struct bfd * abfd;
1163 char ** argv;
1164{
5c27d164
AG
1165 SIM_DESC sd = sim_state_alloc (kind, cb);
1166 printf ("0x%x 0x%x\n", sd, STATE_MAGIC(sd));
1167 SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
1168
1169 if (sim_pre_argv_init (sd, argv[0]) != SIM_RC_OK)
1170 return 0;
1171
1172 sim_do_command(sd," memory region 0x00000000,0x4000000") ;
1173 sim_do_command(sd," memory region 0xE0000000,0x10000") ;
1174
fdd6fa61
AG
1175 myname = argv[0];
1176 callback = cb;
1177
1178 if (kind == SIM_OPEN_STANDALONE)
1179 issue_messages = 1;
1180
fdd6fa61
AG
1181 set_initial_gprs (); /* Reset the GPR registers. */
1182
b8dcd182 1183 /* Configure/verify the target byte order and other runtime
11db68fd 1184 configuration options. */
b8dcd182
AG
1185 if (sim_config (sd) != SIM_RC_OK)
1186 {
1187 sim_module_uninstall (sd);
1188 return 0;
1189 }
1190
1191 if (sim_post_argv_init (sd) != SIM_RC_OK)
1192 {
1193 /* Uninstall the modules to avoid memory leaks,
1194 file descriptor leaks, etc. */
1195 sim_module_uninstall (sd);
1196 return 0;
1197 }
1198
5c27d164 1199 return sd;
fdd6fa61
AG
1200}
1201
1202void
1203sim_close (sd, quitting)
1204 SIM_DESC sd;
1205 int quitting;
1206{
1207 /* nothing to do */
1208}
1209
5c27d164
AG
1210
1211/* Load the device tree blob. */
1212
1213static void
1214load_dtb (SIM_DESC sd, const char *filename)
1215{
1216 int size = 0;
1217 FILE *f = fopen (filename, "rb");
1218 char *buf;
1219 sim_cpu *scpu = STATE_CPU (sd, 0); /* FIXME */
1220 if (f == NULL)
1221 {
1222 printf ("WARNING: ``%s'' could not be opened.\n", filename);
1223 return;
1224 }
1225 fseek (f, 0, SEEK_END);
1226 size = ftell(f);
1227 fseek (f, 0, SEEK_SET);
1228 buf = alloca (size);
1229 if (size != fread (buf, 1, size, f))
1230 {
1231 printf ("ERROR: error reading ``%s''.\n", filename);
1232 return;
1233 }
1234 sim_core_write_buffer (sd, scpu, write_map, buf, 0xE0000000, size);
1235 cpu.asregs.sregs[9] = 0xE0000000;
1236 fclose (f);
1237}
1238
fdd6fa61
AG
1239SIM_RC
1240sim_load (sd, prog, abfd, from_tty)
1241 SIM_DESC sd;
1242 char * prog;
1243 bfd * abfd;
1244 int from_tty;
1245{
1246
1247 /* Do the right thing for ELF executables; this turns out to be
1248 just about the right thing for any object format that:
1249 - we crack using BFD routines
1250 - follows the traditional UNIX text/data/bss layout
1251 - calls the bss section ".bss". */
1252
1253 extern bfd * sim_load_file (); /* ??? Don't know where this should live. */
1254 bfd * prog_bfd;
1255
1256 {
1257 bfd * handle;
1258 handle = bfd_openr (prog, 0); /* could be "moxie" */
1259
1260 if (!handle)
1261 {
1262 printf("``%s'' could not be opened.\n", prog);
1263 return SIM_RC_FAIL;
1264 }
1265
1266 /* Makes sure that we have an object file, also cleans gets the
1267 section headers in place. */
1268 if (!bfd_check_format (handle, bfd_object))
1269 {
1270 /* wasn't an object file */
1271 bfd_close (handle);
1272 printf ("``%s'' is not appropriate object file.\n", prog);
1273 return SIM_RC_FAIL;
1274 }
1275
1276 /* Clean up after ourselves. */
1277 bfd_close (handle);
1278 }
1279
1280 /* from sh -- dac */
1281 prog_bfd = sim_load_file (sd, myname, callback, prog, abfd,
1282 sim_kind == SIM_OPEN_DEBUG,
1283 0, sim_write);
1284 if (prog_bfd == NULL)
1285 return SIM_RC_FAIL;
1286
1287 if (abfd == NULL)
1288 bfd_close (prog_bfd);
1289
1290 return SIM_RC_OK;
1291}
1292
1293SIM_RC
1294sim_create_inferior (sd, prog_bfd, argv, env)
1295 SIM_DESC sd;
1296 struct bfd * prog_bfd;
1297 char ** argv;
1298 char ** env;
1299{
1300 char ** avp;
1301 int l, argc, i, tp;
5c27d164 1302 sim_cpu *scpu = STATE_CPU (sd, 0); /* FIXME */
fdd6fa61
AG
1303
1304 /* Set the initial register set. */
1305 l = issue_messages;
1306 issue_messages = 0;
1307 set_initial_gprs ();
1308 issue_messages = l;
1309
bc56c8fa
JK
1310 if (prog_bfd != NULL)
1311 cpu.asregs.regs[PC_REGNO] = bfd_get_start_address (prog_bfd);
fdd6fa61
AG
1312
1313 /* Copy args into target memory. */
1314 avp = argv;
bc56c8fa 1315 for (argc = 0; avp && *avp; avp++)
fdd6fa61
AG
1316 argc++;
1317
1318 /* Target memory looks like this:
1319 0x00000000 zero word
1320 0x00000004 argc word
1321 0x00000008 start of argv
1322 .
1323 0x0000???? end of argv
1324 0x0000???? zero word
1325 0x0000???? start of data pointed to by argv */
1326
5c27d164
AG
1327 wlat (scpu, 0, 0, 0);
1328 wlat (scpu, 0, 4, argc);
fdd6fa61
AG
1329
1330 /* tp is the offset of our first argv data. */
1331 tp = 4 + 4 + argc * 4 + 4;
1332
1333 for (i = 0; i < argc; i++)
1334 {
1335 /* Set the argv value. */
5c27d164 1336 wlat (scpu, 0, 4 + 4 + i * 4, tp);
fdd6fa61
AG
1337
1338 /* Store the string. */
5c27d164
AG
1339 sim_core_write_buffer (sd, scpu, write_map, argv[i],
1340 tp, strlen(argv[i])+1);
fdd6fa61
AG
1341 tp += strlen (argv[i]) + 1;
1342 }
1343
5c27d164
AG
1344 wlat (scpu, 0, 4 + 4 + i * 4, 0);
1345
1346 load_dtb (sd, DTB);
fdd6fa61
AG
1347
1348 return SIM_RC_OK;
1349}
1350
1351void
1352sim_kill (sd)
1353 SIM_DESC sd;
1354{
1355 if (tracefile)
1356 fclose(tracefile);
1357}
1358
1359void
1360sim_do_command (sd, cmd)
1361 SIM_DESC sd;
1362 char * cmd;
1363{
5c27d164
AG
1364 if (sim_args_command (sd, cmd) != SIM_RC_OK)
1365 sim_io_printf (sd,
1366 "Error: \"%s\" is not a valid moxie simulator command.\n",
fdd6fa61 1367 cmd);
fdd6fa61
AG
1368}
1369
1370void
1371sim_set_callbacks (ptr)
1372 host_callback * ptr;
1373{
1374 callback = ptr;
1375}
This page took 0.144432 seconds and 4 git commands to generate.