xref: /netbsd-src/external/gpl3/gdb.old/dist/sim/moxie/interp.c (revision 154bfe8e089c1a0a4e9ed8414f08d3da90949162)
1 /* Simulator for the moxie processor
2    Copyright (C) 2008-2017 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 #include "config.h"
21 #include <fcntl.h>
22 #include <signal.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <sys/times.h>
26 #include <sys/param.h>
27 #include <unistd.h>
28 #include "bfd.h"
29 #include "libiberty.h"
30 #include "gdb/remote-sim.h"
31 
32 #include "sim-main.h"
33 #include "sim-base.h"
34 #include "sim-options.h"
35 
36 typedef int word;
37 typedef unsigned int uword;
38 
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 
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)))
48 
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 
55 static unsigned long
56 moxie_extract_unsigned_integer (unsigned char *addr, int len)
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))
64     printf ("That operation is not available on integers of more than %zu bytes.",
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 
77 static void
78 moxie_store_unsigned_integer (unsigned char *addr, int len, unsigned long val)
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.  */
92 static 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.  */
111 /* TODO: This should be moved to sim-main.h:_sim_cpu.  */
112 struct moxie_regset
113 {
114   word		  regs[NUM_MOXIE_REGS + 1]; /* primary registers */
115   word		  sregs[256];             /* special registers */
116   word            cc;                   /* the condition code reg */
117   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 
126 /* TODO: This should be moved to sim-main.h:_sim_cpu.  */
127 union
128 {
129   struct moxie_regset asregs;
130   word asints [1];		/* but accessed larger... */
131 } cpu;
132 
133 static void
134 set_initial_gprs (void)
135 {
136   int i;
137   long space;
138 
139   /* Set up machine just out of reset.  */
140   cpu.asregs.regs[PC_REGNO] = 0;
141 
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 
149 /* Write a 1 byte value to memory.  */
150 
151 static INLINE void
152 wbat (sim_cpu *scpu, word pc, word x, word v)
153 {
154   address_word cia = CPU_PC_GET (scpu);
155 
156   sim_core_write_aligned_1 (scpu, cia, write_map, x, v);
157 }
158 
159 /* Write a 2 byte value to memory.  */
160 
161 static INLINE void
162 wsat (sim_cpu *scpu, word pc, word x, word v)
163 {
164   address_word cia = CPU_PC_GET (scpu);
165 
166   sim_core_write_aligned_2 (scpu, cia, write_map, x, v);
167 }
168 
169 /* Write a 4 byte value to memory.  */
170 
171 static INLINE void
172 wlat (sim_cpu *scpu, word pc, word x, word v)
173 {
174   address_word cia = CPU_PC_GET (scpu);
175 
176   sim_core_write_aligned_4 (scpu, cia, write_map, x, v);
177 }
178 
179 /* Read 2 bytes from memory.  */
180 
181 static INLINE int
182 rsat (sim_cpu *scpu, word pc, word x)
183 {
184   address_word cia = CPU_PC_GET (scpu);
185 
186   return (sim_core_read_aligned_2 (scpu, cia, read_map, x));
187 }
188 
189 /* Read 1 byte from memory.  */
190 
191 static INLINE int
192 rbat (sim_cpu *scpu, word pc, word x)
193 {
194   address_word cia = CPU_PC_GET (scpu);
195 
196   return (sim_core_read_aligned_1 (scpu, cia, read_map, x));
197 }
198 
199 /* Read 4 bytes from memory.  */
200 
201 static INLINE int
202 rlat (sim_cpu *scpu, word pc, word x)
203 {
204   address_word cia = CPU_PC_GET (scpu);
205 
206   return (sim_core_read_aligned_4 (scpu, cia, read_map, x));
207 }
208 
209 #define CHECK_FLAG(T,H) if (tflags & T) { hflags |= H; tflags ^= T; }
210 
211 static unsigned int
212 convert_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 
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])
241 
242 void
243 sim_engine_run (SIM_DESC sd,
244 		int next_cpu_nr, /* ignore  */
245 		int nr_cpus, /* ignore  */
246 		int siggnal) /* ignore  */
247 {
248   word pc, opc;
249   unsigned short inst;
250   sim_cpu *scpu = STATE_CPU (sd, 0); /* FIXME */
251   address_word cia = CPU_PC_GET (scpu);
252 
253   pc = cpu.asregs.regs[PC_REGNO];
254 
255   /* Run instructions here. */
256   do
257     {
258       opc = pc;
259 
260       /* Fetch the instruction at pc.  */
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);
263 
264       /* Decode instruction.  */
265       if (inst & (1 << 15))
266 	{
267 	  if (inst & (1 << 14))
268 	    {
269 	      /* This is a Form 3 instruction.  */
270 	      int opcode = (inst >> 10 & 0xf);
271 
272 	      switch (opcode)
273 		{
274 		case 0x00: /* beq */
275 		  {
276 		    MOXIE_TRACE_INSN ("beq");
277 		    if (cpu.asregs.cc & CC_EQ)
278 		      pc += INST2OFFSET(inst);
279 		  }
280 		  break;
281 		case 0x01: /* bne */
282 		  {
283 		    MOXIE_TRACE_INSN ("bne");
284 		    if (! (cpu.asregs.cc & CC_EQ))
285 		      pc += INST2OFFSET(inst);
286 		  }
287 		  break;
288 		case 0x02: /* blt */
289 		  {
290 		    MOXIE_TRACE_INSN ("blt");
291 		    if (cpu.asregs.cc & CC_LT)
292 		      pc += INST2OFFSET(inst);
293 		  }		  break;
294 		case 0x03: /* bgt */
295 		  {
296 		    MOXIE_TRACE_INSN ("bgt");
297 		    if (cpu.asregs.cc & CC_GT)
298 		      pc += INST2OFFSET(inst);
299 		  }
300 		  break;
301 		case 0x04: /* bltu */
302 		  {
303 		    MOXIE_TRACE_INSN ("bltu");
304 		    if (cpu.asregs.cc & CC_LTU)
305 		      pc += INST2OFFSET(inst);
306 		  }
307 		  break;
308 		case 0x05: /* bgtu */
309 		  {
310 		    MOXIE_TRACE_INSN ("bgtu");
311 		    if (cpu.asregs.cc & CC_GTU)
312 		      pc += INST2OFFSET(inst);
313 		  }
314 		  break;
315 		case 0x06: /* bge */
316 		  {
317 		    MOXIE_TRACE_INSN ("bge");
318 		    if (cpu.asregs.cc & (CC_GT | CC_EQ))
319 		      pc += INST2OFFSET(inst);
320 		  }
321 		  break;
322 		case 0x07: /* ble */
323 		  {
324 		    MOXIE_TRACE_INSN ("ble");
325 		    if (cpu.asregs.cc & (CC_LT | CC_EQ))
326 		      pc += INST2OFFSET(inst);
327 		  }
328 		  break;
329 		case 0x08: /* bgeu */
330 		  {
331 		    MOXIE_TRACE_INSN ("bgeu");
332 		    if (cpu.asregs.cc & (CC_GTU | CC_EQ))
333 		      pc += INST2OFFSET(inst);
334 		  }
335 		  break;
336 		case 0x09: /* bleu */
337 		  {
338 		    MOXIE_TRACE_INSN ("bleu");
339 		    if (cpu.asregs.cc & (CC_LTU | CC_EQ))
340 		      pc += INST2OFFSET(inst);
341 		  }
342 		  break;
343 		default:
344 		  {
345 		    MOXIE_TRACE_INSN ("SIGILL3");
346 		    sim_engine_halt (sd, NULL, NULL, pc, sim_stopped, SIM_SIGILL);
347 		    break;
348 		  }
349 		}
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);
362 
363 		    MOXIE_TRACE_INSN ("inc");
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);
372 
373 		    MOXIE_TRACE_INSN ("dec");
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);
381 
382 		    MOXIE_TRACE_INSN ("gsr");
383 		    cpu.asregs.regs[a] = cpu.asregs.sregs[v];
384 		  }
385 		  break;
386 		case 0x03: /* ssr */
387 		  {
388 		    int a = (inst >> 8) & 0xf;
389 		    unsigned v = (inst & 0xff);
390 
391 		    MOXIE_TRACE_INSN ("ssr");
392 		    cpu.asregs.sregs[v] = cpu.asregs.regs[a];
393 		  }
394 		  break;
395 		default:
396 		  MOXIE_TRACE_INSN ("SIGILL2");
397 		  sim_engine_halt (sd, NULL, NULL, pc, sim_stopped, SIM_SIGILL);
398 		  break;
399 		}
400 	    }
401 	}
402       else
403 	{
404 	  /* This is a Form 1 instruction.  */
405 	  int opcode = inst >> 8;
406 	  switch (opcode)
407 	    {
408 	    case 0x00: /* bad */
409 	      opc = opcode;
410 	      MOXIE_TRACE_INSN ("SIGILL0");
411 	      sim_engine_halt (sd, NULL, NULL, pc, sim_stopped, SIM_SIGILL);
412 	      break;
413 	    case 0x01: /* ldi.l (immediate) */
414 	      {
415 		int reg = (inst >> 4) & 0xf;
416 		unsigned int val = EXTRACT_WORD(pc+2);
417 
418 		MOXIE_TRACE_INSN ("ldi.l");
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;
427 
428 		MOXIE_TRACE_INSN ("mov");
429 		cpu.asregs.regs[dest] = cpu.asregs.regs[src];
430 	      }
431 	      break;
432  	    case 0x03: /* jsra */
433  	      {
434  		unsigned int fn = EXTRACT_WORD(pc+2);
435  		unsigned int sp = cpu.asregs.regs[1];
436 
437 		MOXIE_TRACE_INSN ("jsra");
438  		/* Save a slot for the static chain.  */
439 		sp -= 4;
440 
441  		/* Push the return address.  */
442 		sp -= 4;
443  		wlat (scpu, opc, sp, pc + 6);
444 
445  		/* Push the current frame pointer.  */
446  		sp -= 4;
447  		wlat (scpu, opc, sp, cpu.asregs.regs[0]);
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 
459 		MOXIE_TRACE_INSN ("ret");
460 
461  		/* Pop the frame pointer.  */
462  		cpu.asregs.regs[0] = rlat (scpu, opc, sp);
463  		sp += 4;
464 
465  		/* Pop the return address.  */
466  		pc = rlat (scpu, opc, sp) - 2;
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];
482 
483 		MOXIE_TRACE_INSN ("add.l");
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;
492 
493 		MOXIE_TRACE_INSN ("push");
494 		wlat (scpu, opc, sp, cpu.asregs.regs[b]);
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];
503 
504 		MOXIE_TRACE_INSN ("pop");
505 		cpu.asregs.regs[b] = rlat (scpu, opc, sp);
506 		cpu.asregs.regs[a] = sp + 4;
507 	      }
508 	      break;
509 	    case 0x08: /* lda.l */
510 	      {
511 		int reg = (inst >> 4) & 0xf;
512 		unsigned int addr = EXTRACT_WORD(pc+2);
513 
514 		MOXIE_TRACE_INSN ("lda.l");
515 		cpu.asregs.regs[reg] = rlat (scpu, opc, addr);
516 		pc += 4;
517 	      }
518 	      break;
519 	    case 0x09: /* sta.l */
520 	      {
521 		int reg = (inst >> 4) & 0xf;
522 		unsigned int addr = EXTRACT_WORD(pc+2);
523 
524 		MOXIE_TRACE_INSN ("sta.l");
525 		wlat (scpu, opc, addr, cpu.asregs.regs[reg]);
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;
534 
535 		MOXIE_TRACE_INSN ("ld.l");
536 		xv = cpu.asregs.regs[src];
537 		cpu.asregs.regs[dest] = rlat (scpu, opc, xv);
538 	      }
539 	      break;
540 	    case 0x0b: /* st.l */
541 	      {
542 		int dest = (inst >> 4) & 0xf;
543 		int val  = inst & 0xf;
544 
545 		MOXIE_TRACE_INSN ("st.l");
546 		wlat (scpu, opc, cpu.asregs.regs[dest], cpu.asregs.regs[val]);
547 	      }
548 	      break;
549 	    case 0x0c: /* ldo.l */
550 	      {
551 		unsigned int addr = EXTRACT_OFFSET(pc+2);
552 		int a = (inst >> 4) & 0xf;
553 		int b = inst & 0xf;
554 
555 		MOXIE_TRACE_INSN ("ldo.l");
556 		addr += cpu.asregs.regs[b];
557 		cpu.asregs.regs[a] = rlat (scpu, opc, addr);
558 		pc += 2;
559 	      }
560 	      break;
561 	    case 0x0d: /* sto.l */
562 	      {
563 		unsigned int addr = EXTRACT_OFFSET(pc+2);
564 		int a = (inst >> 4) & 0xf;
565 		int b = inst & 0xf;
566 
567 		MOXIE_TRACE_INSN ("sto.l");
568 		addr += cpu.asregs.regs[a];
569 		wlat (scpu, opc, addr, cpu.asregs.regs[b]);
570 		pc += 2;
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 
581 		MOXIE_TRACE_INSN ("cmp");
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;
595 	    case 0x0f: /* nop */
596 	      break;
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];
602 
603 		MOXIE_TRACE_INSN ("sex.b");
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];
612 
613 		MOXIE_TRACE_INSN ("sex.s");
614 		cpu.asregs.regs[a] = (int) bv;
615 	      }
616 	      break;
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];
622 
623 		MOXIE_TRACE_INSN ("zex.b");
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];
632 
633 		MOXIE_TRACE_INSN ("zex.s");
634 		cpu.asregs.regs[a] = (int) bv & 0xffff;
635 	      }
636 	      break;
637 	    case 0x14: /* umul.x */
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];
643 		unsigned long long r =
644 		  (unsigned long long) av * (unsigned long long) bv;
645 
646 		MOXIE_TRACE_INSN ("umul.x");
647 		cpu.asregs.regs[a] = r >> 32;
648 	      }
649 	      break;
650 	    case 0x15: /* mul.x */
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];
656 		signed long long r =
657 		  (signed long long) av * (signed long long) bv;
658 
659 		MOXIE_TRACE_INSN ("mul.x");
660 		cpu.asregs.regs[a] = r >> 32;
661 	      }
662 	      break;
663 	    case 0x16: /* bad */
664 	    case 0x17: /* bad */
665 	    case 0x18: /* bad */
666 	      {
667 		opc = opcode;
668 		MOXIE_TRACE_INSN ("SIGILL0");
669 		sim_engine_halt (sd, NULL, NULL, pc, sim_stopped, SIM_SIGILL);
670 		break;
671 	      }
672 	    case 0x19: /* jsr */
673 	      {
674 		unsigned int fn = cpu.asregs.regs[(inst >> 4) & 0xf];
675 		unsigned int sp = cpu.asregs.regs[1];
676 
677 		MOXIE_TRACE_INSN ("jsr");
678 
679  		/* Save a slot for the static chain.  */
680 		sp -= 4;
681 
682 		/* Push the return address.  */
683 		sp -= 4;
684 		wlat (scpu, opc, sp, pc + 2);
685 
686 		/* Push the current frame pointer.  */
687 		sp -= 4;
688 		wlat (scpu, opc, sp, cpu.asregs.regs[0]);
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 	      {
698 		unsigned int tgt = EXTRACT_WORD(pc+2);
699 
700 		MOXIE_TRACE_INSN ("jmpa");
701 		pc = tgt - 2;
702 	      }
703 	      break;
704 	    case 0x1b: /* ldi.b (immediate) */
705 	      {
706 		int reg = (inst >> 4) & 0xf;
707 		unsigned int val = EXTRACT_WORD(pc+2);
708 
709 		MOXIE_TRACE_INSN ("ldi.b");
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;
719 
720 		MOXIE_TRACE_INSN ("ld.b");
721 		xv = cpu.asregs.regs[src];
722 		cpu.asregs.regs[dest] = rbat (scpu, opc, xv);
723 	      }
724 	      break;
725 	    case 0x1d: /* lda.b */
726 	      {
727 		int reg = (inst >> 4) & 0xf;
728 		unsigned int addr = EXTRACT_WORD(pc+2);
729 
730 		MOXIE_TRACE_INSN ("lda.b");
731 		cpu.asregs.regs[reg] = rbat (scpu, opc, addr);
732 		pc += 4;
733 	      }
734 	      break;
735 	    case 0x1e: /* st.b */
736 	      {
737 		int dest = (inst >> 4) & 0xf;
738 		int val  = inst & 0xf;
739 
740 		MOXIE_TRACE_INSN ("st.b");
741 		wbat (scpu, opc, cpu.asregs.regs[dest], cpu.asregs.regs[val]);
742 	      }
743 	      break;
744 	    case 0x1f: /* sta.b */
745 	      {
746 		int reg = (inst >> 4) & 0xf;
747 		unsigned int addr = EXTRACT_WORD(pc+2);
748 
749 		MOXIE_TRACE_INSN ("sta.b");
750 		wbat (scpu, opc, addr, cpu.asregs.regs[reg]);
751 		pc += 4;
752 	      }
753 	      break;
754 	    case 0x20: /* ldi.s (immediate) */
755 	      {
756 		int reg = (inst >> 4) & 0xf;
757 
758 		unsigned int val = EXTRACT_WORD(pc+2);
759 
760 		MOXIE_TRACE_INSN ("ldi.s");
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;
770 
771 		MOXIE_TRACE_INSN ("ld.s");
772 		xv = cpu.asregs.regs[src];
773 		cpu.asregs.regs[dest] = rsat (scpu, opc, xv);
774 	      }
775 	      break;
776 	    case 0x22: /* lda.s */
777 	      {
778 		int reg = (inst >> 4) & 0xf;
779 		unsigned int addr = EXTRACT_WORD(pc+2);
780 
781 		MOXIE_TRACE_INSN ("lda.s");
782 		cpu.asregs.regs[reg] = rsat (scpu, opc, addr);
783 		pc += 4;
784 	      }
785 	      break;
786 	    case 0x23: /* st.s */
787 	      {
788 		int dest = (inst >> 4) & 0xf;
789 		int val  = inst & 0xf;
790 
791 		MOXIE_TRACE_INSN ("st.s");
792 		wsat (scpu, opc, cpu.asregs.regs[dest], cpu.asregs.regs[val]);
793 	      }
794 	      break;
795 	    case 0x24: /* sta.s */
796 	      {
797 		int reg = (inst >> 4) & 0xf;
798 		unsigned int addr = EXTRACT_WORD(pc+2);
799 
800 		MOXIE_TRACE_INSN ("sta.s");
801 		wsat (scpu, opc, addr, cpu.asregs.regs[reg]);
802 		pc += 4;
803 	      }
804 	      break;
805 	    case 0x25: /* jmp */
806 	      {
807 		int reg = (inst >> 4) & 0xf;
808 
809 		MOXIE_TRACE_INSN ("jmp");
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;
818 
819 		MOXIE_TRACE_INSN ("and");
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];
831 
832 		MOXIE_TRACE_INSN ("lshr");
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];
842 
843 		MOXIE_TRACE_INSN ("ashl");
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];
853 
854 		MOXIE_TRACE_INSN ("sub.l");
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];
863 
864 		MOXIE_TRACE_INSN ("neg");
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;
873 
874 		MOXIE_TRACE_INSN ("or");
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];
885 
886 		MOXIE_TRACE_INSN ("not");
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];
896 
897 		MOXIE_TRACE_INSN ("ashr");
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;
906 
907 		MOXIE_TRACE_INSN ("xor");
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];
919 
920 		MOXIE_TRACE_INSN ("mul.l");
921 		cpu.asregs.regs[a] = av * bv;
922 	      }
923 	      break;
924 	    case 0x30: /* swi */
925 	      {
926 		unsigned int inum = EXTRACT_WORD(pc+2);
927 
928 		MOXIE_TRACE_INSN ("swi");
929 		/* Set the special registers appropriately.  */
930 		cpu.asregs.sregs[2] = 3; /* MOXIE_EX_SWI */
931 	        cpu.asregs.sregs[3] = inum;
932 		switch (inum)
933 		  {
934 		  case 0x1: /* SYS_exit */
935 		    {
936 		      sim_engine_halt (sd, NULL, NULL, pc, sim_exited,
937 				       cpu.asregs.regs[2]);
938 		      break;
939 		    }
940 		  case 0x2: /* SYS_open */
941 		    {
942 		      char fname[1024];
943 		      int mode = (int) convert_target_flags ((unsigned) cpu.asregs.regs[3]);
944 		      int perm = (int) cpu.asregs.regs[4];
945 		      int fd = open (fname, mode, perm);
946 		      sim_core_read_buffer (sd, scpu, read_map, fname,
947 					    cpu.asregs.regs[2], 1024);
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];
955 		      unsigned len = (unsigned) cpu.asregs.regs[4];
956 		      char *buf = malloc (len);
957 		      cpu.asregs.regs[2] = read (fd, buf, len);
958 		      sim_core_write_buffer (sd, scpu, write_map, buf,
959 					     cpu.asregs.regs[3], len);
960 		      free (buf);
961 		      break;
962 		    }
963 		  case 0x5: /* SYS_write */
964 		    {
965 		      char *str;
966 		      /* String length is at 0x12($fp) */
967 		      unsigned count, len = (unsigned) cpu.asregs.regs[4];
968 		      str = malloc (len);
969 		      sim_core_read_buffer (sd, scpu, read_map, str,
970 					    cpu.asregs.regs[3], len);
971 		      count = write (cpu.asregs.regs[2], str, len);
972 		      free (str);
973 		      cpu.asregs.regs[2] = count;
974 		      break;
975 		    }
976 		  case 0xffffffff: /* Linux System Call */
977 		    {
978 		      unsigned int handler = cpu.asregs.sregs[1];
979 		      unsigned int sp = cpu.asregs.regs[1];
980 
981 		      /* Save a slot for the static chain.  */
982 		      sp -= 4;
983 
984 		      /* Push the return address.  */
985 		      sp -= 4;
986 		      wlat (scpu, opc, sp, pc + 6);
987 
988 		      /* Push the current frame pointer.  */
989 		      sp -= 4;
990 		      wlat (scpu, opc, sp, cpu.asregs.regs[0]);
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 		    }
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];
1009 
1010 		MOXIE_TRACE_INSN ("div.l");
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];
1020 
1021 		MOXIE_TRACE_INSN ("udiv.l");
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];
1031 
1032 		MOXIE_TRACE_INSN ("mod.l");
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];
1042 
1043 		MOXIE_TRACE_INSN ("umod.l");
1044 		cpu.asregs.regs[a] = (av % bv);
1045 	      }
1046 	      break;
1047 	    case 0x35: /* brk */
1048 	      MOXIE_TRACE_INSN ("brk");
1049 	      sim_engine_halt (sd, NULL, NULL, pc, sim_stopped, SIM_SIGTRAP);
1050 	      pc -= 2; /* Adjust pc */
1051 	      break;
1052 	    case 0x36: /* ldo.b */
1053 	      {
1054 		unsigned int addr = EXTRACT_OFFSET(pc+2);
1055 		int a = (inst >> 4) & 0xf;
1056 		int b = inst & 0xf;
1057 
1058 		MOXIE_TRACE_INSN ("ldo.b");
1059 		addr += cpu.asregs.regs[b];
1060 		cpu.asregs.regs[a] = rbat (scpu, opc, addr);
1061 		pc += 2;
1062 	      }
1063 	      break;
1064 	    case 0x37: /* sto.b */
1065 	      {
1066 		unsigned int addr = EXTRACT_OFFSET(pc+2);
1067 		int a = (inst >> 4) & 0xf;
1068 		int b = inst & 0xf;
1069 
1070 		MOXIE_TRACE_INSN ("sto.b");
1071 		addr += cpu.asregs.regs[a];
1072 		wbat (scpu, opc, addr, cpu.asregs.regs[b]);
1073 		pc += 2;
1074 	      }
1075 	      break;
1076 	    case 0x38: /* ldo.s */
1077 	      {
1078 		unsigned int addr = EXTRACT_OFFSET(pc+2);
1079 		int a = (inst >> 4) & 0xf;
1080 		int b = inst & 0xf;
1081 
1082 		MOXIE_TRACE_INSN ("ldo.s");
1083 		addr += cpu.asregs.regs[b];
1084 		cpu.asregs.regs[a] = rsat (scpu, opc, addr);
1085 		pc += 2;
1086 	      }
1087 	      break;
1088 	    case 0x39: /* sto.s */
1089 	      {
1090 		unsigned int addr = EXTRACT_OFFSET(pc+2);
1091 		int a = (inst >> 4) & 0xf;
1092 		int b = inst & 0xf;
1093 
1094 		MOXIE_TRACE_INSN ("sto.s");
1095 		addr += cpu.asregs.regs[a];
1096 		wsat (scpu, opc, addr, cpu.asregs.regs[b]);
1097 		pc += 2;
1098 	      }
1099 	      break;
1100 	    default:
1101 	      opc = opcode;
1102 	      MOXIE_TRACE_INSN ("SIGILL1");
1103 	      sim_engine_halt (sd, NULL, NULL, pc, sim_stopped, SIM_SIGILL);
1104 	      break;
1105 	    }
1106 	}
1107 
1108       cpu.asregs.insts++;
1109       pc += 2;
1110       cpu.asregs.regs[PC_REGNO] = pc;
1111     } while (1);
1112 }
1113 
1114 static int
1115 moxie_reg_store (SIM_CPU *scpu, int rn, unsigned char *memory, int length)
1116 {
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 
1134 static int
1135 moxie_reg_fetch (SIM_CPU *scpu, int rn, unsigned char *memory, int length)
1136 {
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 
1153 static sim_cia
1154 moxie_pc_get (sim_cpu *cpu)
1155 {
1156   return cpu->registers[PCIDX];
1157 }
1158 
1159 static void
1160 moxie_pc_set (sim_cpu *cpu, sim_cia pc)
1161 {
1162   cpu->registers[PCIDX] = pc;
1163 }
1164 
1165 static void
1166 free_state (SIM_DESC sd)
1167 {
1168   if (STATE_MODULES (sd) != NULL)
1169     sim_module_uninstall (sd);
1170   sim_cpu_free_all (sd);
1171   sim_state_free (sd);
1172 }
1173 
1174 SIM_DESC
1175 sim_open (SIM_OPEN_KIND kind, host_callback *cb,
1176 	  struct bfd *abfd, char * const *argv)
1177 {
1178   int i;
1179   SIM_DESC sd = sim_state_alloc (kind, cb);
1180   SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
1181 
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 
1192   if (sim_pre_argv_init (sd, argv[0]) != SIM_RC_OK)
1193     {
1194       free_state (sd);
1195       return 0;
1196     }
1197 
1198   /* The parser will print an error message for us, so we silently return.  */
1199   if (sim_parse_args (sd, argv) != SIM_RC_OK)
1200     {
1201       free_state (sd);
1202       return 0;
1203     }
1204 
1205   sim_do_command(sd," memory region 0x00000000,0x4000000") ;
1206   sim_do_command(sd," memory region 0xE0000000,0x10000") ;
1207 
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 
1218   /* Configure/verify the target byte order and other runtime
1219      configuration options.  */
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 
1234   /* CPU specific initialization.  */
1235   for (i = 0; i < MAX_NR_PROCESSORS; ++i)
1236     {
1237       SIM_CPU *cpu = STATE_CPU (sd, i);
1238 
1239       CPU_REG_FETCH (cpu) = moxie_reg_fetch;
1240       CPU_REG_STORE (cpu) = moxie_reg_store;
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     }
1246 
1247   return sd;
1248 }
1249 
1250 /* Load the device tree blob.  */
1251 
1252 static void
1253 load_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 */
1259 
1260   /* Don't warn as the sim works fine w/out a device tree.  */
1261   if (f == NULL)
1262     return;
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     {
1269       sim_io_eprintf (sd, "ERROR: error reading ``%s''.\n", filename);
1270       fclose (f);
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 
1278 SIM_RC
1279 sim_create_inferior (SIM_DESC sd, struct bfd *prog_bfd,
1280 		     char * const *argv, char * const *env)
1281 {
1282   char ** avp;
1283   int l, argc, i, tp;
1284   sim_cpu *scpu = STATE_CPU (sd, 0); /* FIXME */
1285 
1286   if (prog_bfd != NULL)
1287     cpu.asregs.regs[PC_REGNO] = bfd_get_start_address (prog_bfd);
1288 
1289   /* Copy args into target memory.  */
1290   avp = argv;
1291   for (argc = 0; avp && *avp; avp++)
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 
1303   wlat (scpu, 0, 0, 0);
1304   wlat (scpu, 0, 4, argc);
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.  */
1312       wlat (scpu, 0, 4 + 4 + i * 4, tp);
1313 
1314       /* Store the string.  */
1315       sim_core_write_buffer (sd, scpu, write_map, argv[i],
1316 			     tp, strlen(argv[i])+1);
1317       tp += strlen (argv[i]) + 1;
1318     }
1319 
1320   wlat (scpu, 0, 4 + 4 + i * 4, 0);
1321 
1322   load_dtb (sd, DTB);
1323 
1324   return SIM_RC_OK;
1325 }
1326