Increase simulated memory size. Support new system call ABI. Support exception...
[external/binutils.git] / sim / moxie / interp.c
1 /* Simulator for the moxie processor
2    Copyright (C) 2008, 2009 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 <signal.h>
21 #include <stdlib.h>
22 #include "sysdep.h"
23 #include <sys/times.h>
24 #include <sys/param.h>
25 #include <netinet/in.h> /* for byte ordering macros */
26 #include "bfd.h"
27 #include "gdb/callback.h"
28 #include "libiberty.h"
29 #include "gdb/remote-sim.h"
30
31 typedef int word;
32 typedef unsigned int uword;
33
34 host_callback *       callback;
35
36 FILE *tracefile;
37
38 /* Extract the signed 10-bit offset from a 16-bit branch
39    instruction.  */
40 #define INST2OFFSET(o) ((((signed short)((o & ((1<<10)-1))<<6))>>6)<<1)
41
42 #define EXTRACT_WORD(addr) (((addr)[0] << 24) \
43                             + ((addr)[1] << 16) \
44                             + ((addr)[2] << 8) \
45                             + ((addr)[3]))
46
47 unsigned long
48 moxie_extract_unsigned_integer (addr, len)
49      unsigned char * addr;
50      int len;
51 {
52   unsigned long retval;
53   unsigned char * p;
54   unsigned char * startaddr = (unsigned char *)addr;
55   unsigned char * endaddr = startaddr + len;
56  
57   if (len > (int) sizeof (unsigned long))
58     printf ("That operation is not available on integers of more than %d bytes.",
59             sizeof (unsigned long));
60  
61   /* Start at the most significant end of the integer, and work towards
62      the least significant.  */
63   retval = 0;
64
65   for (p = endaddr; p > startaddr;)
66     retval = (retval << 8) | * -- p;
67   
68   return retval;
69 }
70
71 void
72 moxie_store_unsigned_integer (addr, len, val)
73      unsigned char * addr;
74      int len;
75      unsigned long val;
76 {
77   unsigned char * p;
78   unsigned char * startaddr = (unsigned char *)addr;
79   unsigned char * endaddr = startaddr + len;
80
81   for (p = endaddr; p > startaddr;)
82     {
83       * -- p = val & 0xff;
84       val >>= 8;
85     }
86 }
87
88 /* moxie register names.  */
89 static const char *reg_names[16] = 
90   { "$fp", "$sp", "$r0", "$r1", "$r2", "$r3", "$r4", "$r5", 
91     "$r6", "$r7", "$r8", "$r9", "$r10", "$r11", "$r12", "$r13" };
92
93 /* The machine state.
94
95    This state is maintained in host byte order.  The fetch/store
96    register functions must translate between host byte order and the
97    target processor byte order.  Keeping this data in target byte
98    order simplifies the register read/write functions.  Keeping this
99    data in native order improves the performance of the simulator.
100    Simulation speed is deemed more important.  */
101
102 #define NUM_MOXIE_REGS 17 /* Including PC */
103 #define NUM_MOXIE_SREGS 256 /* The special registers */
104 #define PC_REGNO     16
105
106 /* The ordering of the moxie_regset structure is matched in the
107    gdb/config/moxie/tm-moxie.h file in the REGISTER_NAMES macro.  */
108 struct moxie_regset
109 {
110   word            regs[NUM_MOXIE_REGS + 1]; /* primary registers */
111   word            sregs[256];             /* special registers */
112   word            cc;                   /* the condition code reg */
113   int             exception;
114   unsigned long   msize;
115   unsigned char * memory;
116   unsigned long long insts;                /* instruction counter */
117 };
118
119 #define CC_GT  1<<0
120 #define CC_LT  1<<1
121 #define CC_EQ  1<<2
122 #define CC_GTU 1<<3
123 #define CC_LTU 1<<4
124
125 union
126 {
127   struct moxie_regset asregs;
128   word asints [1];              /* but accessed larger... */
129 } cpu;
130
131 static char *myname;
132 static SIM_OPEN_KIND sim_kind;
133 static int issue_messages = 0;
134
135 /* Default to a 16 Mbyte (== 2^23) memory space.  */
136 static int sim_memory_size = 24;
137
138 #define MEM_SIZE_FLOOR  64
139 void
140 sim_size (power)
141      int power;
142 {
143   sim_memory_size = power;
144   cpu.asregs.msize = 1 << sim_memory_size;
145
146   if (cpu.asregs.memory)
147     free (cpu.asregs.memory);
148
149   /* Watch out for the '0 count' problem. There's probably a better
150      way.. e.g., why do we use 64 here?  */
151   if (cpu.asregs.msize < 64)    /* Ensure a boundary.  */
152     cpu.asregs.memory = (unsigned char *) calloc (64, (64 + cpu.asregs.msize) / 64);
153   else
154     cpu.asregs.memory = (unsigned char *) calloc (64, cpu.asregs.msize / 64);
155
156   if (!cpu.asregs.memory)
157     {
158       if (issue_messages)
159         fprintf (stderr,
160                  "Not enough VM for simulation of %d bytes of RAM\n",
161                  cpu.asregs.msize);
162
163       cpu.asregs.msize = 1;
164       cpu.asregs.memory = (unsigned char *) calloc (1, 1);
165     }
166 }
167
168 static void
169 init_pointers ()
170 {
171   if (cpu.asregs.msize != (1 << sim_memory_size))
172     sim_size (sim_memory_size);
173 }
174
175
176 static void
177 set_initial_gprs ()
178 {
179   int i;
180   long space;
181   unsigned long memsize;
182   
183   init_pointers ();
184
185   /* Set up machine just out of reset.  */
186   cpu.asregs.regs[PC_REGNO] = 0;
187   
188   memsize = cpu.asregs.msize / (1024 * 1024);
189
190   if (issue_messages > 1)
191     fprintf (stderr, "Simulated memory of %d Mbytes (0x0 .. 0x%08x)\n",
192              memsize, cpu.asregs.msize - 1);
193
194   /* Clean out the register contents.  */
195   for (i = 0; i < NUM_MOXIE_REGS; i++)
196     cpu.asregs.regs[i] = 0;
197   for (i = 0; i < NUM_MOXIE_SREGS; i++)
198     cpu.asregs.sregs[i] = 0;
199 }
200
201 static void
202 interrupt ()
203 {
204   cpu.asregs.exception = SIGINT;
205 }
206
207 /* Write a 1 byte value to memory.  */
208
209 static void INLINE 
210 wbat (pc, x, v)
211      word pc, x, v;
212 {
213   if (((uword)x) >= cpu.asregs.msize)
214     {
215       if (issue_messages)
216         fprintf (stderr, "byte write to 0x%x outside memory range\n", x);
217       
218       cpu.asregs.exception = SIGSEGV;
219     }
220   else
221     {
222       {
223         unsigned char * p = cpu.asregs.memory + x;
224         *p = v;
225       }
226     }
227 }
228
229 /* Write a 2 byte value to memory.  */
230
231 static void INLINE 
232 wsat (pc, x, v)
233      word pc, x, v;
234 {
235   if (((uword)x) >= cpu.asregs.msize)
236     {
237       if (issue_messages)
238         fprintf (stderr, "short word write to 0x%x outside memory range\n", x);
239       
240       cpu.asregs.exception = SIGSEGV;
241     }
242   else
243     {
244       if ((x & 1) != 0)
245         {
246           if (issue_messages)
247             fprintf (stderr, "short word write to unaligned memory address: 0x%x\n", x);
248       
249           cpu.asregs.exception = SIGBUS;
250         }
251       {
252         unsigned char * p = cpu.asregs.memory + x;
253         p[0] = v >> 8;
254         p[1] = v;
255       }
256     }
257 }
258
259 /* Write a 4 byte value to memory.  */
260
261 static void INLINE 
262 wlat (pc, x, v)
263      word pc, x, v;
264 {
265   if (((uword)x) >= cpu.asregs.msize)
266     {
267       if (issue_messages)
268         fprintf (stderr, "word write to 0x%x outside memory range\n", x);
269       
270       cpu.asregs.exception = SIGSEGV;
271     }
272   else
273     {
274       if ((x & 1) != 0)
275         {
276           if (issue_messages)
277             fprintf (stderr, "word write to unaligned memory address: 0x%x\n", x);
278       
279           cpu.asregs.exception = SIGBUS;
280         }
281       {
282         unsigned char * p = cpu.asregs.memory + x;
283         p[0] = v >> 24;
284         p[1] = v >> 16;
285         p[2] = v >> 8;
286         p[3] = v;
287       }
288     }
289 }
290
291 /* Read 2 bytes from memory.  */
292
293 static int INLINE 
294 rsat (pc, x)
295      word pc, x;
296 {
297   if (((uword) x) >= cpu.asregs.msize)
298     {
299       if (issue_messages)
300         fprintf (stderr, "short word read from 0x%x outside memory range\n", x);
301       
302       cpu.asregs.exception = SIGSEGV;
303       return 0;
304     }
305   else
306     {
307       if ((x & 1) != 0)
308         {
309           if (issue_messages)
310             fprintf (stderr, "short word read from unaligned address: 0x%x\n", x);
311       
312           cpu.asregs.exception = SIGBUS;
313           return 0;
314         }
315       {
316         unsigned char * p = cpu.asregs.memory + x;
317         return (p[0] << 8) | p[1];
318       }
319     }
320 }
321
322 /* Read 1 byte from memory.  */
323
324 static int INLINE 
325 rbat (pc, x)
326      word pc, x;
327 {
328   if (((uword) x) >= cpu.asregs.msize)
329     {
330       if (issue_messages)
331         fprintf (stderr, "byte read from 0x%x outside memory range\n", x);
332       
333       cpu.asregs.exception = SIGSEGV;
334       return 0;
335     }
336   else
337     {
338       unsigned char * p = cpu.asregs.memory + x;
339       return *p;
340     }
341 }
342
343 /* Read 4 bytes from memory.  */
344
345 static int INLINE 
346 rlat (pc, x)
347      word pc, x;
348 {
349   if (((uword) x) >= cpu.asregs.msize)
350     {
351       if (issue_messages)
352         fprintf (stderr, "word read from 0x%x outside memory range\n", x);
353       
354       cpu.asregs.exception = SIGSEGV;
355       return 0;
356     }
357   else
358     {
359       if ((x & 3) != 0)
360         {
361           if (issue_messages)
362             fprintf (stderr, "word read from unaligned address: 0x%x\n", x);
363       
364           cpu.asregs.exception = SIGBUS;
365           return 0;
366         }
367       {
368         unsigned char * p = cpu.asregs.memory + x;
369         return (EXTRACT_WORD(p));
370       }
371     }
372 }
373
374 #define CHECK_FLAG(T,H) if (tflags & T) { hflags |= H; tflags ^= T; }
375
376 unsigned int 
377 convert_target_flags (unsigned int tflags)
378 {
379   unsigned int hflags = 0x0;
380
381   CHECK_FLAG(0x0001, O_WRONLY);
382   CHECK_FLAG(0x0002, O_RDWR);
383   CHECK_FLAG(0x0008, O_APPEND);
384   CHECK_FLAG(0x0200, O_CREAT);
385   CHECK_FLAG(0x0400, O_TRUNC);
386   CHECK_FLAG(0x0800, O_EXCL);
387   CHECK_FLAG(0x2000, O_SYNC);
388
389   if (tflags != 0x0)
390     fprintf (stderr, 
391              "Simulator Error: problem converting target open flags for host.  0x%x\n", 
392              tflags);
393
394   return hflags;
395 }
396
397 #define TRACE(str) if (tracing) fprintf(tracefile,"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\n", opc, str, cpu.asregs.regs[0], cpu.asregs.regs[1], cpu.asregs.regs[2], cpu.asregs.regs[3], cpu.asregs.regs[4], cpu.asregs.regs[5], cpu.asregs.regs[6], cpu.asregs.regs[7], cpu.asregs.regs[8], cpu.asregs.regs[9], cpu.asregs.regs[10], cpu.asregs.regs[11], cpu.asregs.regs[12], cpu.asregs.regs[13], cpu.asregs.regs[14], cpu.asregs.regs[15]);
398
399 static int tracing = 0;
400
401 void
402 sim_resume (sd, step, siggnal)
403      SIM_DESC sd;
404      int step, siggnal;
405 {
406   word pc, opc;
407   unsigned long long insts;
408   unsigned short inst;
409   void (* sigsave)();
410
411   sigsave = signal (SIGINT, interrupt);
412   cpu.asregs.exception = step ? SIGTRAP: 0;
413   pc = cpu.asregs.regs[PC_REGNO];
414   insts = cpu.asregs.insts;
415   unsigned char *memory = cpu.asregs.memory;
416
417   /* Run instructions here. */
418   do 
419     {
420       opc = pc;
421
422       /* Fetch the instruction at pc.  */
423       inst = (memory[pc] << 8) + memory[pc + 1];
424
425       /* Decode instruction.  */
426       if (inst & (1 << 15))
427         {
428           if (inst & (1 << 14))
429             {
430               /* This is a Form 3 instruction.  */
431               int opcode = (inst >> 10 & 0xf);
432
433               switch (opcode)
434                 {
435                 case 0x00: /* beq */
436                   {
437                     TRACE("beq");
438                     if (cpu.asregs.cc & CC_EQ)
439                       pc += INST2OFFSET(inst) - 2;
440                   }
441                   break;
442                 case 0x01: /* bne */
443                   {
444                     TRACE("bne");
445                     if (! (cpu.asregs.cc & CC_EQ))
446                       pc += INST2OFFSET(inst) - 2;
447                   }
448                   break;
449                 case 0x02: /* blt */
450                   {
451                     TRACE("blt");
452                     if (cpu.asregs.cc & CC_LT)
453                       pc += INST2OFFSET(inst) - 2;
454                   }               break;
455                 case 0x03: /* bgt */
456                   {
457                     TRACE("bgt");
458                     if (cpu.asregs.cc & CC_GT)
459                       pc += INST2OFFSET(inst) - 2;
460                   }
461                   break;
462                 case 0x04: /* bltu */
463                   {
464                     TRACE("bltu");
465                     if (cpu.asregs.cc & CC_LTU)
466                       pc += INST2OFFSET(inst) - 2;
467                   }
468                   break;
469                 case 0x05: /* bgtu */
470                   {
471                     TRACE("bgtu");
472                     if (cpu.asregs.cc & CC_GTU)
473                       pc += INST2OFFSET(inst) - 2;
474                   }
475                   break;
476                 case 0x06: /* bge */
477                   {
478                     TRACE("bge");
479                     if (cpu.asregs.cc & (CC_GT | CC_EQ))
480                       pc += INST2OFFSET(inst) - 2;
481                   }
482                   break;
483                 case 0x07: /* ble */
484                   {
485                     TRACE("ble");
486                     if (cpu.asregs.cc & (CC_LT | CC_EQ))
487                       pc += INST2OFFSET(inst) - 2;
488                   }
489                   break;
490                 case 0x08: /* bgeu */
491                   {
492                     TRACE("bgeu");
493                     if (cpu.asregs.cc & (CC_GTU | CC_EQ))
494                       pc += INST2OFFSET(inst) - 2;
495                   }
496                   break;
497                 case 0x09: /* bleu */
498                   {
499                     TRACE("bleu");
500                     if (cpu.asregs.cc & (CC_LTU | CC_EQ))
501                       pc += INST2OFFSET(inst) - 2;
502                   }
503                   break;
504                 default:
505                   {
506                     TRACE("SIGILL3");
507                     cpu.asregs.exception = SIGILL;
508                     break;
509                   }
510                 }
511             }
512           else
513             {
514               /* This is a Form 2 instruction.  */
515               int opcode = (inst >> 12 & 0x3);
516               switch (opcode)
517                 {
518                 case 0x00: /* inc */
519                   {
520                     int a = (inst >> 8) & 0xf;
521                     unsigned av = cpu.asregs.regs[a];
522                     unsigned v = (inst & 0xff);
523                     TRACE("inc");
524                     cpu.asregs.regs[a] = av + v;
525                   }
526                   break;
527                 case 0x01: /* dec */
528                   {
529                     int a = (inst >> 8) & 0xf;
530                     unsigned av = cpu.asregs.regs[a];
531                     unsigned v = (inst & 0xff);
532                     TRACE("dec");
533                     cpu.asregs.regs[a] = av - v;
534                   }
535                   break;
536                 case 0x02: /* gsr */
537                   {
538                     int a = (inst >> 8) & 0xf;
539                     unsigned v = (inst & 0xff);
540                     TRACE("gsr");
541                     cpu.asregs.regs[a] = cpu.asregs.sregs[v];
542                   }
543                   break;
544                 case 0x03: /* ssr */
545                   {
546                     int a = (inst >> 8) & 0xf;
547                     unsigned v = (inst & 0xff);
548                     TRACE("ssr");
549                     cpu.asregs.sregs[v] = cpu.asregs.regs[a];
550                   }
551                   break;
552                 default:
553                   TRACE("SIGILL2");
554                   cpu.asregs.exception = SIGILL;
555                   break;
556                 }
557             }
558         }
559       else
560         {
561           /* This is a Form 1 instruction.  */
562           int opcode = inst >> 8;
563           switch (opcode)
564             {
565             case 0x00: /* nop */
566               break;
567             case 0x01: /* ldi.l (immediate) */
568               {
569                 int reg = (inst >> 4) & 0xf;
570                 TRACE("ldi.l");
571                 unsigned int val = EXTRACT_WORD(&(memory[pc + 2]));
572                 cpu.asregs.regs[reg] = val;
573                 pc += 4;
574               }
575               break;
576             case 0x02: /* mov (register-to-register) */
577               {
578                 int dest  = (inst >> 4) & 0xf;
579                 int src = (inst ) & 0xf;
580                 TRACE("mov");
581                 cpu.asregs.regs[dest] = cpu.asregs.regs[src];
582               }
583               break;
584             case 0x03: /* jsra */
585               {
586                 unsigned int fn = EXTRACT_WORD(&(memory[pc + 2]));
587                 unsigned int sp = cpu.asregs.regs[1];
588                 TRACE("jsra");
589                 /* Save a slot for the static chain.  */
590                 sp -= 4;
591
592                 /* Push the return address.  */
593                 sp -= 4;
594                 wlat (opc, sp, pc + 6);
595                 
596                 /* Push the current frame pointer.  */
597                 sp -= 4;
598                 wlat (opc, sp, cpu.asregs.regs[0]);
599  
600                 /* Uncache the stack pointer and set the pc and $fp.  */
601                 cpu.asregs.regs[1] = sp;
602                 cpu.asregs.regs[0] = sp;
603                 pc = fn - 2;
604               }
605               break;
606             case 0x04: /* ret */
607               {
608                 unsigned int sp = cpu.asregs.regs[0];
609
610                 TRACE("ret");
611  
612                 /* Pop the frame pointer.  */
613                 cpu.asregs.regs[0] = rlat (opc, sp);
614                 sp += 4;
615                 
616                 /* Pop the return address.  */
617                 pc = rlat (opc, sp) - 2;
618                 sp += 4;
619
620                 /* Skip over the static chain slot.  */
621                 sp += 4;
622  
623                 /* Uncache the stack pointer.  */
624                 cpu.asregs.regs[1] = sp;
625               }
626               break;
627             case 0x05: /* add.l */
628               {
629                 int a = (inst >> 4) & 0xf;
630                 int b = inst & 0xf;
631                 unsigned av = cpu.asregs.regs[a];
632                 unsigned bv = cpu.asregs.regs[b];
633                 TRACE("add.l");
634                 cpu.asregs.regs[a] = av + bv;
635               }
636               break;
637             case 0x06: /* push */
638               {
639                 int a = (inst >> 4) & 0xf;
640                 int b = inst & 0xf;
641                 int sp = cpu.asregs.regs[a] - 4;
642                 TRACE("push");
643                 wlat (opc, sp, cpu.asregs.regs[b]);
644                 cpu.asregs.regs[a] = sp;
645               }
646               break;
647             case 0x07: /* pop */
648               {
649                 int a = (inst >> 4) & 0xf;
650                 int b = inst & 0xf;
651                 int sp = cpu.asregs.regs[a];
652                 TRACE("pop");
653                 cpu.asregs.regs[b] = rlat (opc, sp);
654                 cpu.asregs.regs[a] = sp + 4;
655               }
656               break;
657             case 0x08: /* lda.l */
658               {
659                 int reg = (inst >> 4) & 0xf;
660                 unsigned int addr = EXTRACT_WORD(&memory[pc+2]);
661                 TRACE("lda.l");
662                 cpu.asregs.regs[reg] = rlat (opc, addr);
663                 pc += 4;
664               }
665               break;
666             case 0x09: /* sta.l */
667               {
668                 int reg = (inst >> 4) & 0xf;
669                 unsigned int addr = EXTRACT_WORD(&memory[pc+2]);
670                 TRACE("sta.l");
671                 wlat (opc, addr, cpu.asregs.regs[reg]);
672                 pc += 4;
673               }
674               break;
675             case 0x0a: /* ld.l (register indirect) */
676               {
677                 int src  = inst & 0xf;
678                 int dest = (inst >> 4) & 0xf;
679                 int xv;
680                 TRACE("ld.l");
681                 xv = cpu.asregs.regs[src];
682                 cpu.asregs.regs[dest] = rlat (opc, xv);
683               }
684               break;
685             case 0x0b: /* st.l */
686               {
687                 int dest = (inst >> 4) & 0xf;
688                 int val  = inst & 0xf;
689                 TRACE("st.l");
690                 wlat (opc, cpu.asregs.regs[dest], cpu.asregs.regs[val]);
691               }
692               break;
693             case 0x0c: /* ldo.l */
694               {
695                 unsigned int addr = EXTRACT_WORD(&memory[pc+2]);
696                 int a = (inst >> 4) & 0xf;
697                 int b = inst & 0xf;
698                 TRACE("ldo.l");
699                 addr += cpu.asregs.regs[b];
700                 cpu.asregs.regs[a] = rlat(opc, addr);
701                 pc += 4;
702               }
703               break;
704             case 0x0d: /* sto.l */
705               {
706                 unsigned int addr = EXTRACT_WORD(&memory[pc+2]);
707                 int a = (inst >> 4) & 0xf;
708                 int b = inst & 0xf;
709                 TRACE("sto.l");
710                 addr += cpu.asregs.regs[a];
711                 wlat(opc, addr, cpu.asregs.regs[b]);
712                 pc += 4;
713               }
714               break;
715             case 0x0e: /* cmp */
716               {
717                 int a  = (inst >> 4) & 0xf;
718                 int b  = inst & 0xf;
719                 int cc = 0;
720                 int va = cpu.asregs.regs[a];
721                 int vb = cpu.asregs.regs[b]; 
722
723                 TRACE("cmp");
724
725                 if (va == vb)
726                   cc = CC_EQ;
727                 else
728                   {
729                     cc |= (va < vb ? CC_LT : 0);
730                     cc |= (va > vb ? CC_GT : 0);
731                     cc |= ((unsigned int) va < (unsigned int) vb ? CC_LTU : 0);
732                     cc |= ((unsigned int) va > (unsigned int) vb ? CC_GTU : 0);
733                   }
734
735                 cpu.asregs.cc = cc;
736               }
737               break;
738             case 0x0f:
739             case 0x10:
740             case 0x11:
741             case 0x12:
742             case 0x13:
743             case 0x14:
744             case 0x15:
745             case 0x16:
746             case 0x17:
747             case 0x18:
748               {
749                 opc = opcode;
750                 TRACE("SIGILL0");
751                 cpu.asregs.exception = SIGILL;
752                 break;
753               }
754             case 0x19: /* jsr */
755               {
756                 unsigned int fn = cpu.asregs.regs[(inst >> 4) & 0xf];
757                 unsigned int sp = cpu.asregs.regs[1];
758
759                 TRACE("jsr");
760
761                 /* Save a slot for the static chain.  */
762                 sp -= 4;
763
764                 /* Push the return address.  */
765                 sp -= 4;
766                 wlat (opc, sp, pc + 2);
767                 
768                 /* Push the current frame pointer.  */
769                 sp -= 4;
770                 wlat (opc, sp, cpu.asregs.regs[0]);
771
772                 /* Uncache the stack pointer and set the fp & pc.  */
773                 cpu.asregs.regs[1] = sp;
774                 cpu.asregs.regs[0] = sp;
775                 pc = fn - 2;
776               }
777               break;
778             case 0x1a: /* jmpa */
779               {
780                 unsigned int tgt = EXTRACT_WORD(&memory[pc+2]);
781                 TRACE("jmpa");
782                 pc = tgt - 2;
783               }
784               break;
785             case 0x1b: /* ldi.b (immediate) */
786               {
787                 int reg = (inst >> 4) & 0xf;
788
789                 unsigned int val = EXTRACT_WORD(&(memory[pc + 2]));
790                 TRACE("ldi.b");
791                 cpu.asregs.regs[reg] = val;
792                 pc += 4;
793               }
794               break;
795             case 0x1c: /* ld.b (register indirect) */
796               {
797                 int src  = inst & 0xf;
798                 int dest = (inst >> 4) & 0xf;
799                 int xv;
800                 TRACE("ld.b");
801                 xv = cpu.asregs.regs[src];
802                 cpu.asregs.regs[dest] = rbat (opc, xv);
803               }
804               break;
805             case 0x1d: /* lda.b */
806               {
807                 int reg = (inst >> 4) & 0xf;
808                 unsigned int addr = EXTRACT_WORD(&memory[pc+2]);
809                 TRACE("lda.b");
810                 cpu.asregs.regs[reg] = rbat (opc, addr);
811                 pc += 4;
812               }
813               break;
814             case 0x1e: /* st.b */
815               {
816                 int dest = (inst >> 4) & 0xf;
817                 int val  = inst & 0xf;
818                 TRACE("st.b");
819                 wbat (opc, cpu.asregs.regs[dest], cpu.asregs.regs[val]);
820               }
821               break;
822             case 0x1f: /* sta.b */
823               {
824                 int reg = (inst >> 4) & 0xf;
825                 unsigned int addr = EXTRACT_WORD(&memory[pc+2]);
826                 TRACE("sta.b");
827                 wbat (opc, addr, cpu.asregs.regs[reg]);
828                 pc += 4;
829               }
830               break;
831             case 0x20: /* ldi.s (immediate) */
832               {
833                 int reg = (inst >> 4) & 0xf;
834
835                 unsigned int val = EXTRACT_WORD(&(memory[pc + 2]));
836                 TRACE("ldi.s");
837                 cpu.asregs.regs[reg] = val;
838                 pc += 4;
839               }
840               break;
841             case 0x21: /* ld.s (register indirect) */
842               {
843                 int src  = inst & 0xf;
844                 int dest = (inst >> 4) & 0xf;
845                 int xv;
846                 TRACE("ld.s");
847                 xv = cpu.asregs.regs[src];
848                 cpu.asregs.regs[dest] = rsat (opc, xv);
849               }
850               break;
851             case 0x22: /* lda.s */
852               {
853                 int reg = (inst >> 4) & 0xf;
854                 unsigned int addr = EXTRACT_WORD(&memory[pc+2]);
855                 TRACE("lda.s");
856                 cpu.asregs.regs[reg] = rsat (opc, addr);
857                 pc += 4;
858               }
859               break;
860             case 0x23: /* st.s */
861               {
862                 int dest = (inst >> 4) & 0xf;
863                 int val  = inst & 0xf;
864                 TRACE("st.s");
865                 wsat (opc, cpu.asregs.regs[dest], cpu.asregs.regs[val]);
866               }
867               break;
868             case 0x24: /* sta.s */
869               {
870                 int reg = (inst >> 4) & 0xf;
871                 unsigned int addr = EXTRACT_WORD(&memory[pc+2]);
872                 TRACE("sta.s");
873                 wsat (opc, addr, cpu.asregs.regs[reg]);
874                 pc += 4;
875               }
876               break;
877             case 0x25: /* jmp */
878               {
879                 int reg = (inst >> 4) & 0xf;
880                 TRACE("jmp");
881                 pc = cpu.asregs.regs[reg] - 2;
882               }
883               break;
884             case 0x26: /* and */
885               {
886                 int a = (inst >> 4) & 0xf;
887                 int b = inst & 0xf;
888                 int av, bv;
889                 TRACE("and");
890                 av = cpu.asregs.regs[a];
891                 bv = cpu.asregs.regs[b];
892                 cpu.asregs.regs[a] = av & bv;
893               }
894               break;
895             case 0x27: /* lshr */
896               {
897                 int a = (inst >> 4) & 0xf;
898                 int b = inst & 0xf;
899                 int av = cpu.asregs.regs[a];
900                 int bv = cpu.asregs.regs[b];
901                 TRACE("lshr");
902                 cpu.asregs.regs[a] = (unsigned) ((unsigned) av >> bv);
903               }
904               break;
905             case 0x28: /* ashl */
906               {
907                 int a = (inst >> 4) & 0xf;
908                 int b = inst & 0xf;
909                 int av = cpu.asregs.regs[a];
910                 int bv = cpu.asregs.regs[b];
911                 TRACE("ashl");
912                 cpu.asregs.regs[a] = av << bv;
913               }
914               break;
915             case 0x29: /* sub.l */
916               {
917                 int a = (inst >> 4) & 0xf;
918                 int b = inst & 0xf;
919                 unsigned av = cpu.asregs.regs[a];
920                 unsigned bv = cpu.asregs.regs[b];
921                 TRACE("sub.l");
922                 cpu.asregs.regs[a] = av - bv;
923               }
924               break;
925             case 0x2a: /* neg */
926               {
927                 int a  = (inst >> 4) & 0xf;
928                 int b  = inst & 0xf;
929                 int bv = cpu.asregs.regs[b];
930                 TRACE("neg");
931                 cpu.asregs.regs[a] = - bv;
932               }
933               break;
934             case 0x2b: /* or */
935               {
936                 int a = (inst >> 4) & 0xf;
937                 int b = inst & 0xf;
938                 int av, bv;
939                 TRACE("or");
940                 av = cpu.asregs.regs[a];
941                 bv = cpu.asregs.regs[b];
942                 cpu.asregs.regs[a] = av | bv;
943               }
944               break;
945             case 0x2c: /* not */
946               {
947                 int a = (inst >> 4) & 0xf;
948                 int b = inst & 0xf;
949                 int bv = cpu.asregs.regs[b];
950                 TRACE("not");
951                 cpu.asregs.regs[a] = 0xffffffff ^ bv;
952               }
953               break;
954             case 0x2d: /* ashr */
955               {
956                 int a  = (inst >> 4) & 0xf;
957                 int b  = inst & 0xf;
958                 int av = cpu.asregs.regs[a];
959                 int bv = cpu.asregs.regs[b];
960                 TRACE("ashr");
961                 cpu.asregs.regs[a] = av >> bv;
962               }
963               break;
964             case 0x2e: /* xor */
965               {
966                 int a = (inst >> 4) & 0xf;
967                 int b = inst & 0xf;
968                 int av, bv;
969                 TRACE("xor");
970                 av = cpu.asregs.regs[a];
971                 bv = cpu.asregs.regs[b];
972                 cpu.asregs.regs[a] = av ^ bv;
973               }
974               break;
975             case 0x2f: /* mul.l */
976               {
977                 int a = (inst >> 4) & 0xf;
978                 int b = inst & 0xf;
979                 unsigned av = cpu.asregs.regs[a];
980                 unsigned bv = cpu.asregs.regs[b];
981                 TRACE("mul.l");
982                 cpu.asregs.regs[a] = av * bv;
983               }
984               break;
985             case 0x30: /* swi */
986               {
987                 unsigned int inum = EXTRACT_WORD(&memory[pc+2]);
988                 TRACE("swi");
989                 switch (inum)
990                   {
991                   case 0x1: /* SYS_exit */
992                     {
993                       cpu.asregs.exception = SIGQUIT;
994                       break;
995                     }
996                   case 0x2: /* SYS_open */
997                     {
998                       char *fname = &memory[cpu.asregs.regs[2]];
999                       int mode = (int) convert_target_flags ((unsigned) cpu.asregs.regs[3]);
1000                       int perm = (int) cpu.asregs.regs[4];
1001                       int fd = open (fname, mode, perm);
1002                       /* FIXME - set errno */
1003                       cpu.asregs.regs[2] = fd;
1004                       break;
1005                     }
1006                   case 0x4: /* SYS_read */
1007                     {
1008                       int fd = cpu.asregs.regs[2];
1009                       char *buf = &memory[cpu.asregs.regs[3]];
1010                       unsigned len = (unsigned) cpu.asregs.regs[4];
1011                       cpu.asregs.regs[2] = read (fd, buf, len);
1012                       break;
1013                     }
1014                   case 0x5: /* SYS_write */
1015                     {
1016                       char *str = &memory[cpu.asregs.regs[3]];
1017                       /* String length is at 0x12($fp) */
1018                       unsigned count, len = (unsigned) cpu.asregs.regs[4];
1019                       count = write (cpu.asregs.regs[2], str, len);
1020                       cpu.asregs.regs[2] = count;
1021                       break;
1022                     }
1023                   case 0xffffffff: /* Linux System Call */
1024                     {
1025                       unsigned int handler = cpu.asregs.sregs[1];
1026                       unsigned int sp = cpu.asregs.regs[1];
1027                       cpu.asregs.sregs[2] = 3; /* MOXIE_EX_SWI */
1028
1029                       /* Save a slot for the static chain.  */
1030                       sp -= 4;
1031
1032                       /* Push the return address.  */
1033                       sp -= 4;
1034                       wlat (opc, sp, pc + 6);
1035                 
1036                       /* Push the current frame pointer.  */
1037                       sp -= 4;
1038                       wlat (opc, sp, cpu.asregs.regs[0]);
1039
1040                       /* Uncache the stack pointer and set the fp & pc.  */
1041                       cpu.asregs.regs[1] = sp;
1042                       cpu.asregs.regs[0] = sp;
1043                       pc = handler - 6;
1044                     }
1045                   default:
1046                     break;
1047                   }
1048                 pc += 4;
1049               }
1050               break;
1051             case 0x31: /* div.l */
1052               {
1053                 int a = (inst >> 4) & 0xf;
1054                 int b = inst & 0xf;
1055                 int av = cpu.asregs.regs[a];
1056                 int bv = cpu.asregs.regs[b];
1057                 TRACE("div.l");
1058                 cpu.asregs.regs[a] = av / bv;
1059               }
1060               break;
1061             case 0x32: /* udiv.l */
1062               {
1063                 int a = (inst >> 4) & 0xf;
1064                 int b = inst & 0xf;
1065                 unsigned int av = cpu.asregs.regs[a];
1066                 unsigned int bv = cpu.asregs.regs[b];
1067                 TRACE("udiv.l");
1068                 cpu.asregs.regs[a] = (av / bv);
1069               }
1070               break;
1071             case 0x33: /* mod.l */
1072               {
1073                 int a = (inst >> 4) & 0xf;
1074                 int b = inst & 0xf;
1075                 int av = cpu.asregs.regs[a];
1076                 int bv = cpu.asregs.regs[b];
1077                 TRACE("mod.l");
1078                 cpu.asregs.regs[a] = av % bv;
1079               }
1080               break;
1081             case 0x34: /* umod.l */
1082               {
1083                 int a = (inst >> 4) & 0xf;
1084                 int b = inst & 0xf;
1085                 unsigned int av = cpu.asregs.regs[a];
1086                 unsigned int bv = cpu.asregs.regs[b];
1087                 TRACE("umod.l");
1088                 cpu.asregs.regs[a] = (av % bv);
1089               }
1090               break;
1091             case 0x35: /* brk */
1092               TRACE("brk");
1093               cpu.asregs.exception = SIGTRAP;
1094               pc -= 2; /* Adjust pc */
1095               break;
1096             case 0x36: /* ldo.b */
1097               {
1098                 unsigned int addr = EXTRACT_WORD(&memory[pc+2]);
1099                 int a = (inst >> 4) & 0xf;
1100                 int b = inst & 0xf;
1101                 TRACE("ldo.b");
1102                 addr += cpu.asregs.regs[b];
1103                 cpu.asregs.regs[a] = rbat(opc, addr);
1104                 pc += 4;
1105               }
1106               break;
1107             case 0x37: /* sto.b */
1108               {
1109                 unsigned int addr = EXTRACT_WORD(&memory[pc+2]);
1110                 int a = (inst >> 4) & 0xf;
1111                 int b = inst & 0xf;
1112                 TRACE("sto.b");
1113                 addr += cpu.asregs.regs[a];
1114                 wbat(opc, addr, cpu.asregs.regs[b]);
1115                 pc += 4;
1116               }
1117               break;
1118             case 0x38: /* ldo.s */
1119               {
1120                 unsigned int addr = EXTRACT_WORD(&memory[pc+2]);
1121                 int a = (inst >> 4) & 0xf;
1122                 int b = inst & 0xf;
1123                 TRACE("ldo.s");
1124                 addr += cpu.asregs.regs[b];
1125                 cpu.asregs.regs[a] = rsat(opc, addr);
1126                 pc += 4;
1127               }
1128               break;
1129             case 0x39: /* sto.s */
1130               {
1131                 unsigned int addr = EXTRACT_WORD(&memory[pc+2]);
1132                 int a = (inst >> 4) & 0xf;
1133                 int b = inst & 0xf;
1134                 TRACE("sto.s");
1135                 addr += cpu.asregs.regs[a];
1136                 wsat(opc, addr, cpu.asregs.regs[b]);
1137                 pc += 4;
1138               }
1139               break;
1140             default:
1141               opc = opcode;
1142               TRACE("SIGILL1");
1143               cpu.asregs.exception = SIGILL;
1144               break;
1145             }
1146         }
1147
1148       insts++;
1149       pc += 2;
1150
1151     } while (!cpu.asregs.exception);
1152
1153   /* Hide away the things we've cached while executing.  */
1154   cpu.asregs.regs[PC_REGNO] = pc;
1155   cpu.asregs.insts += insts;            /* instructions done ... */
1156
1157   signal (SIGINT, sigsave);
1158 }
1159
1160 int
1161 sim_write (sd, addr, buffer, size)
1162      SIM_DESC sd;
1163      SIM_ADDR addr;
1164      unsigned char * buffer;
1165      int size;
1166 {
1167   int i;
1168   init_pointers ();
1169   
1170   memcpy (& cpu.asregs.memory[addr], buffer, size);
1171   
1172   return size;
1173 }
1174
1175 int
1176 sim_read (sd, addr, buffer, size)
1177      SIM_DESC sd;
1178      SIM_ADDR addr;
1179      unsigned char * buffer;
1180      int size;
1181 {
1182   int i;
1183   init_pointers ();
1184   
1185   memcpy (buffer, & cpu.asregs.memory[addr], size);
1186   
1187   return size;
1188 }
1189
1190
1191 int
1192 sim_store_register (sd, rn, memory, length)
1193      SIM_DESC sd;
1194      int rn;
1195      unsigned char * memory;
1196      int length;
1197 {
1198   init_pointers ();
1199
1200   if (rn < NUM_MOXIE_REGS && rn >= 0)
1201     {
1202       if (length == 4)
1203         {
1204           long ival;
1205           
1206           /* misalignment safe */
1207           ival = moxie_extract_unsigned_integer (memory, 4);
1208           cpu.asints[rn] = ival;
1209         }
1210
1211       return 4;
1212     }
1213   else
1214     return 0;
1215 }
1216
1217 int
1218 sim_fetch_register (sd, rn, memory, length)
1219      SIM_DESC sd;
1220      int rn;
1221      unsigned char * memory;
1222      int length;
1223 {
1224   init_pointers ();
1225   
1226   if (rn < NUM_MOXIE_REGS && rn >= 0)
1227     {
1228       if (length == 4)
1229         {
1230           long ival = cpu.asints[rn];
1231
1232           /* misalignment-safe */
1233           moxie_store_unsigned_integer (memory, 4, ival);
1234         }
1235       
1236       return 4;
1237     }
1238   else
1239     return 0;
1240 }
1241
1242
1243 int
1244 sim_trace (sd)
1245      SIM_DESC sd;
1246 {
1247   if (tracefile == 0)
1248     tracefile = fopen("trace.csv", "wb");
1249
1250   tracing = 1;
1251   
1252   sim_resume (sd, 0, 0);
1253
1254   tracing = 0;
1255   
1256   return 1;
1257 }
1258
1259 void
1260 sim_stop_reason (sd, reason, sigrc)
1261      SIM_DESC sd;
1262      enum sim_stop * reason;
1263      int * sigrc;
1264 {
1265   if (cpu.asregs.exception == SIGQUIT)
1266     {
1267       * reason = sim_exited;
1268       * sigrc = cpu.asregs.regs[2];
1269     }
1270   else
1271     {
1272       * reason = sim_stopped;
1273       * sigrc = cpu.asregs.exception;
1274     }
1275 }
1276
1277
1278 int
1279 sim_stop (sd)
1280      SIM_DESC sd;
1281 {
1282   cpu.asregs.exception = SIGINT;
1283   return 1;
1284 }
1285
1286
1287 void
1288 sim_info (sd, verbose)
1289      SIM_DESC sd;
1290      int verbose;
1291 {
1292   callback->printf_filtered (callback, "\n\n# instructions executed  %llu\n",
1293                              cpu.asregs.insts);
1294 }
1295
1296
1297 SIM_DESC
1298 sim_open (kind, cb, abfd, argv)
1299      SIM_OPEN_KIND kind;
1300      host_callback * cb;
1301      struct bfd * abfd;
1302      char ** argv;
1303 {
1304   int osize = sim_memory_size;
1305   myname = argv[0];
1306   callback = cb;
1307   
1308   if (kind == SIM_OPEN_STANDALONE)
1309     issue_messages = 1;
1310   
1311   /* Discard and reacquire memory -- start with a clean slate.  */
1312   sim_size (1);         /* small */
1313   sim_size (osize);     /* and back again */
1314
1315   set_initial_gprs ();  /* Reset the GPR registers.  */
1316   
1317   /* Fudge our descriptor for now.  */
1318   return (SIM_DESC) 1;
1319 }
1320
1321 void
1322 sim_close (sd, quitting)
1323      SIM_DESC sd;
1324      int quitting;
1325 {
1326   /* nothing to do */
1327 }
1328
1329 SIM_RC
1330 sim_load (sd, prog, abfd, from_tty)
1331      SIM_DESC sd;
1332      char * prog;
1333      bfd * abfd;
1334      int from_tty;
1335 {
1336
1337   /* Do the right thing for ELF executables; this turns out to be
1338      just about the right thing for any object format that:
1339        - we crack using BFD routines
1340        - follows the traditional UNIX text/data/bss layout
1341        - calls the bss section ".bss".   */
1342
1343   extern bfd * sim_load_file (); /* ??? Don't know where this should live.  */
1344   bfd * prog_bfd;
1345
1346   {
1347     bfd * handle;
1348     handle = bfd_openr (prog, 0);       /* could be "moxie" */
1349     
1350     if (!handle)
1351       {
1352         printf("``%s'' could not be opened.\n", prog);
1353         return SIM_RC_FAIL;
1354       }
1355     
1356     /* Makes sure that we have an object file, also cleans gets the 
1357        section headers in place.  */
1358     if (!bfd_check_format (handle, bfd_object))
1359       {
1360         /* wasn't an object file */
1361         bfd_close (handle);
1362         printf ("``%s'' is not appropriate object file.\n", prog);
1363         return SIM_RC_FAIL;
1364       }
1365
1366     /* Clean up after ourselves.  */
1367     bfd_close (handle);
1368   }
1369
1370   /* from sh -- dac */
1371   prog_bfd = sim_load_file (sd, myname, callback, prog, abfd,
1372                             sim_kind == SIM_OPEN_DEBUG,
1373                             0, sim_write);
1374   if (prog_bfd == NULL)
1375     return SIM_RC_FAIL;
1376   
1377   if (abfd == NULL)
1378     bfd_close (prog_bfd);
1379
1380   return SIM_RC_OK;
1381 }
1382
1383 SIM_RC
1384 sim_create_inferior (sd, prog_bfd, argv, env)
1385      SIM_DESC sd;
1386      struct bfd * prog_bfd;
1387      char ** argv;
1388      char ** env;
1389 {
1390   char ** avp;
1391   int l, argc, i, tp;
1392
1393   /* Set the initial register set.  */
1394   l = issue_messages;
1395   issue_messages = 0;
1396   set_initial_gprs ();
1397   issue_messages = l;
1398   
1399   cpu.asregs.regs[PC_REGNO] = bfd_get_start_address (prog_bfd);
1400
1401   /* Copy args into target memory.  */
1402   avp = argv;
1403   for (argc = 0; *avp; avp++)
1404     argc++;
1405
1406   /* Target memory looks like this:
1407      0x00000000 zero word
1408      0x00000004 argc word
1409      0x00000008 start of argv
1410      .
1411      0x0000???? end of argv
1412      0x0000???? zero word 
1413      0x0000???? start of data pointed to by argv  */
1414
1415   wlat (0, 0, 0);
1416   wlat (0, 4, argc);
1417
1418   /* tp is the offset of our first argv data.  */
1419   tp = 4 + 4 + argc * 4 + 4;
1420
1421   for (i = 0; i < argc; i++)
1422     {
1423       /* Set the argv value.  */
1424       wlat (0, 4 + 4 + i * 4, tp);
1425
1426       /* Store the string.  */
1427       strcpy (&cpu.asregs.memory[tp], argv[i]);
1428       tp += strlen (argv[i]) + 1;
1429     }
1430
1431   wlat (0, 4 + 4 + i * 4, 0);
1432
1433   return SIM_RC_OK;
1434 }
1435
1436 void
1437 sim_kill (sd)
1438      SIM_DESC sd;
1439 {
1440   if (tracefile)
1441     fclose(tracefile);
1442 }
1443
1444 void
1445 sim_do_command (sd, cmd)
1446      SIM_DESC sd;
1447      char * cmd;
1448 {
1449   /* Nothing there yet; it's all an error.  */
1450   
1451   if (cmd != NULL)
1452     {
1453       char ** simargv = buildargv (cmd);
1454       if (strcmp (simargv[0], "verbose") == 0)
1455         {
1456           issue_messages = 2;
1457         }
1458       else
1459         {
1460           fprintf (stderr,"Error: \"%s\" is not a valid moxie simulator command.\n",
1461                    cmd);
1462         }
1463     }
1464   else
1465     {
1466       fprintf (stderr, "moxie sim commands: \n");
1467       fprintf (stderr, "  verbose\n");
1468     }
1469 }
1470
1471 void
1472 sim_set_callbacks (ptr)
1473      host_callback * ptr;
1474 {
1475   callback = ptr; 
1476 }