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