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