interp.c revision 1.1.1.7
1/* Simulator for the moxie processor
2   Copyright (C) 2008-2017 Free Software Foundation, Inc.
3   Contributed by Anthony Green
4
5This file is part of GDB, the GNU debugger.
6
7This program is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
9the Free Software Foundation; either version 3 of the License, or
10(at your option) any later version.
11
12This program is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
19
20#include "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
36typedef int word;
37typedef 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
55static unsigned long
56moxie_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
77static void
78moxie_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.  */
92static const char *reg_names[16] =
93  { "$fp", "$sp", "$r0", "$r1", "$r2", "$r3", "$r4", "$r5",
94    "$r6", "$r7", "$r8", "$r9", "$r10", "$r11", "$r12", "$r13" };
95
96/* The machine state.
97
98   This state is maintained in host byte order.  The fetch/store
99   register functions must translate between host byte order and the
100   target processor byte order.  Keeping this data in target byte
101   order simplifies the register read/write functions.  Keeping this
102   data in native order improves the performance of the simulator.
103   Simulation speed is deemed more important.  */
104
105#define NUM_MOXIE_REGS 17 /* Including PC */
106#define NUM_MOXIE_SREGS 256 /* The special registers */
107#define PC_REGNO     16
108
109/* The ordering of the moxie_regset structure is matched in the
110   gdb/config/moxie/tm-moxie.h file in the REGISTER_NAMES macro.  */
111/* TODO: This should be moved to sim-main.h:_sim_cpu.  */
112struct moxie_regset
113{
114  word		  regs[NUM_MOXIE_REGS + 1]; /* primary registers */
115  word		  sregs[256];             /* special registers */
116  word            cc;                   /* the condition code reg */
117  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.  */
127union
128{
129  struct moxie_regset asregs;
130  word asints [1];		/* but accessed larger... */
131} cpu;
132
133static void
134set_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
151static INLINE void
152wbat (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
161static INLINE void
162wsat (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
171static INLINE void
172wlat (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
181static INLINE int
182rsat (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
191static INLINE int
192rbat (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
201static INLINE int
202rlat (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
211static unsigned int
212convert_target_flags (unsigned int tflags)
213{
214  unsigned int hflags = 0x0;
215
216  CHECK_FLAG(0x0001, O_WRONLY);
217  CHECK_FLAG(0x0002, O_RDWR);
218  CHECK_FLAG(0x0008, O_APPEND);
219  CHECK_FLAG(0x0200, O_CREAT);
220  CHECK_FLAG(0x0400, O_TRUNC);
221  CHECK_FLAG(0x0800, O_EXCL);
222  CHECK_FLAG(0x2000, O_SYNC);
223
224  if (tflags != 0x0)
225    fprintf (stderr,
226	     "Simulator Error: problem converting target open flags for host.  0x%x\n",
227	     tflags);
228
229  return hflags;
230}
231
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
242void
243sim_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
1114static int
1115moxie_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
1134static int
1135moxie_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
1153static sim_cia
1154moxie_pc_get (sim_cpu *cpu)
1155{
1156  return cpu->registers[PCIDX];
1157}
1158
1159static void
1160moxie_pc_set (sim_cpu *cpu, sim_cia pc)
1161{
1162  cpu->registers[PCIDX] = pc;
1163}
1164
1165static void
1166free_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
1174SIM_DESC
1175sim_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
1252static void
1253load_dtb (SIM_DESC sd, const char *filename)
1254{
1255  int size = 0;
1256  FILE *f = fopen (filename, "rb");
1257  char *buf;
1258  sim_cpu *scpu = STATE_CPU (sd, 0); /* FIXME */
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
1278SIM_RC
1279sim_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