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