Add PC-relative branch support to moxie sim.
[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 8 Mbyte (== 2^23) memory space.  */
136 static int sim_memory_size = 23;
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                       /* Permission bits are at 0x12($fp) */
1001                       int perm = (int) EXTRACT_WORD(&memory[cpu.asregs.regs[0] + 20]);
1002                       int fd = open (fname, mode, perm);
1003 #if 0
1004                       fprintf(stderr, "open(\"%s\", 0x%x, 0x%x) = %d\n", fname, mode, perm, fd);
1005 #endif
1006                       /* FIXME - set errno */
1007                       cpu.asregs.regs[2] = fd;
1008                       break;
1009                     }
1010                   case 0x4: /* SYS_read */
1011                     {
1012                       int fd = cpu.asregs.regs[2];
1013                       char *buf = &memory[cpu.asregs.regs[3]];
1014                       /* String length is at 0x12($fp) */
1015                       unsigned len = EXTRACT_WORD(&memory[cpu.asregs.regs[0] + 20]);
1016                       cpu.asregs.regs[2] = read (fd, buf, len);
1017                       break;
1018                     }
1019                   case 0x5: /* SYS_write */
1020                     {
1021                       char *str = &memory[cpu.asregs.regs[3]];
1022                       /* String length is at 0x12($fp) */
1023                       unsigned count, len = EXTRACT_WORD(&memory[cpu.asregs.regs[0] + 20]);
1024                       count = write (cpu.asregs.regs[2], str, len);
1025                       cpu.asregs.regs[2] = count;
1026                       break;
1027                     }
1028                   default:
1029                     break;
1030                   }
1031                 pc += 4;
1032               }
1033               break;
1034             case 0x31: /* div.l */
1035               {
1036                 int a = (inst >> 4) & 0xf;
1037                 int b = inst & 0xf;
1038                 int av = cpu.asregs.regs[a];
1039                 int bv = cpu.asregs.regs[b];
1040                 TRACE("div.l");
1041                 cpu.asregs.regs[a] = av / bv;
1042               }
1043               break;
1044             case 0x32: /* udiv.l */
1045               {
1046                 int a = (inst >> 4) & 0xf;
1047                 int b = inst & 0xf;
1048                 unsigned int av = cpu.asregs.regs[a];
1049                 unsigned int bv = cpu.asregs.regs[b];
1050                 TRACE("udiv.l");
1051                 cpu.asregs.regs[a] = (av / bv);
1052               }
1053               break;
1054             case 0x33: /* mod.l */
1055               {
1056                 int a = (inst >> 4) & 0xf;
1057                 int b = inst & 0xf;
1058                 int av = cpu.asregs.regs[a];
1059                 int bv = cpu.asregs.regs[b];
1060                 TRACE("mod.l");
1061                 cpu.asregs.regs[a] = av % bv;
1062               }
1063               break;
1064             case 0x34: /* umod.l */
1065               {
1066                 int a = (inst >> 4) & 0xf;
1067                 int b = inst & 0xf;
1068                 unsigned int av = cpu.asregs.regs[a];
1069                 unsigned int bv = cpu.asregs.regs[b];
1070                 TRACE("umod.l");
1071                 cpu.asregs.regs[a] = (av % bv);
1072               }
1073               break;
1074             case 0x35: /* brk */
1075               TRACE("brk");
1076               cpu.asregs.exception = SIGTRAP;
1077               pc -= 2; /* Adjust pc */
1078               break;
1079             case 0x36: /* ldo.b */
1080               {
1081                 unsigned int addr = EXTRACT_WORD(&memory[pc+2]);
1082                 int a = (inst >> 4) & 0xf;
1083                 int b = inst & 0xf;
1084                 TRACE("ldo.b");
1085                 addr += cpu.asregs.regs[b];
1086                 cpu.asregs.regs[a] = rbat(opc, addr);
1087                 pc += 4;
1088               }
1089               break;
1090             case 0x37: /* sto.b */
1091               {
1092                 unsigned int addr = EXTRACT_WORD(&memory[pc+2]);
1093                 int a = (inst >> 4) & 0xf;
1094                 int b = inst & 0xf;
1095                 TRACE("sto.b");
1096                 addr += cpu.asregs.regs[a];
1097                 wbat(opc, addr, cpu.asregs.regs[b]);
1098                 pc += 4;
1099               }
1100               break;
1101             case 0x38: /* ldo.s */
1102               {
1103                 unsigned int addr = EXTRACT_WORD(&memory[pc+2]);
1104                 int a = (inst >> 4) & 0xf;
1105                 int b = inst & 0xf;
1106                 TRACE("ldo.s");
1107                 addr += cpu.asregs.regs[b];
1108                 cpu.asregs.regs[a] = rsat(opc, addr);
1109                 pc += 4;
1110               }
1111               break;
1112             case 0x39: /* sto.s */
1113               {
1114                 unsigned int addr = EXTRACT_WORD(&memory[pc+2]);
1115                 int a = (inst >> 4) & 0xf;
1116                 int b = inst & 0xf;
1117                 TRACE("sto.s");
1118                 addr += cpu.asregs.regs[a];
1119                 wsat(opc, addr, cpu.asregs.regs[b]);
1120                 pc += 4;
1121               }
1122               break;
1123             default:
1124               opc = opcode;
1125               TRACE("SIGILL1");
1126               cpu.asregs.exception = SIGILL;
1127               break;
1128             }
1129         }
1130
1131       insts++;
1132       pc += 2;
1133
1134     } while (!cpu.asregs.exception);
1135
1136   /* Hide away the things we've cached while executing.  */
1137   cpu.asregs.regs[PC_REGNO] = pc;
1138   cpu.asregs.insts += insts;            /* instructions done ... */
1139
1140   signal (SIGINT, sigsave);
1141 }
1142
1143 int
1144 sim_write (sd, addr, buffer, size)
1145      SIM_DESC sd;
1146      SIM_ADDR addr;
1147      unsigned char * buffer;
1148      int size;
1149 {
1150   int i;
1151   init_pointers ();
1152   
1153   memcpy (& cpu.asregs.memory[addr], buffer, size);
1154   
1155   return size;
1156 }
1157
1158 int
1159 sim_read (sd, addr, buffer, size)
1160      SIM_DESC sd;
1161      SIM_ADDR addr;
1162      unsigned char * buffer;
1163      int size;
1164 {
1165   int i;
1166   init_pointers ();
1167   
1168   memcpy (buffer, & cpu.asregs.memory[addr], size);
1169   
1170   return size;
1171 }
1172
1173
1174 int
1175 sim_store_register (sd, rn, memory, length)
1176      SIM_DESC sd;
1177      int rn;
1178      unsigned char * memory;
1179      int length;
1180 {
1181   init_pointers ();
1182
1183   if (rn < NUM_MOXIE_REGS && rn >= 0)
1184     {
1185       if (length == 4)
1186         {
1187           long ival;
1188           
1189           /* misalignment safe */
1190           ival = moxie_extract_unsigned_integer (memory, 4);
1191           cpu.asints[rn] = ival;
1192         }
1193
1194       return 4;
1195     }
1196   else
1197     return 0;
1198 }
1199
1200 int
1201 sim_fetch_register (sd, rn, memory, length)
1202      SIM_DESC sd;
1203      int rn;
1204      unsigned char * memory;
1205      int length;
1206 {
1207   init_pointers ();
1208   
1209   if (rn < NUM_MOXIE_REGS && rn >= 0)
1210     {
1211       if (length == 4)
1212         {
1213           long ival = cpu.asints[rn];
1214
1215           /* misalignment-safe */
1216           moxie_store_unsigned_integer (memory, 4, ival);
1217         }
1218       
1219       return 4;
1220     }
1221   else
1222     return 0;
1223 }
1224
1225
1226 int
1227 sim_trace (sd)
1228      SIM_DESC sd;
1229 {
1230   if (tracefile == 0)
1231     tracefile = fopen("trace.csv", "wb");
1232
1233   tracing = 1;
1234   
1235   sim_resume (sd, 0, 0);
1236
1237   tracing = 0;
1238   
1239   return 1;
1240 }
1241
1242 void
1243 sim_stop_reason (sd, reason, sigrc)
1244      SIM_DESC sd;
1245      enum sim_stop * reason;
1246      int * sigrc;
1247 {
1248   if (cpu.asregs.exception == SIGQUIT)
1249     {
1250       * reason = sim_exited;
1251       * sigrc = cpu.asregs.regs[2];
1252     }
1253   else
1254     {
1255       * reason = sim_stopped;
1256       * sigrc = cpu.asregs.exception;
1257     }
1258 }
1259
1260
1261 int
1262 sim_stop (sd)
1263      SIM_DESC sd;
1264 {
1265   cpu.asregs.exception = SIGINT;
1266   return 1;
1267 }
1268
1269
1270 void
1271 sim_info (sd, verbose)
1272      SIM_DESC sd;
1273      int verbose;
1274 {
1275   callback->printf_filtered (callback, "\n\n# instructions executed  %llu\n",
1276                              cpu.asregs.insts);
1277 }
1278
1279
1280 SIM_DESC
1281 sim_open (kind, cb, abfd, argv)
1282      SIM_OPEN_KIND kind;
1283      host_callback * cb;
1284      struct bfd * abfd;
1285      char ** argv;
1286 {
1287   int osize = sim_memory_size;
1288   myname = argv[0];
1289   callback = cb;
1290   
1291   if (kind == SIM_OPEN_STANDALONE)
1292     issue_messages = 1;
1293   
1294   /* Discard and reacquire memory -- start with a clean slate.  */
1295   sim_size (1);         /* small */
1296   sim_size (osize);     /* and back again */
1297
1298   set_initial_gprs ();  /* Reset the GPR registers.  */
1299   
1300   /* Fudge our descriptor for now.  */
1301   return (SIM_DESC) 1;
1302 }
1303
1304 void
1305 sim_close (sd, quitting)
1306      SIM_DESC sd;
1307      int quitting;
1308 {
1309   /* nothing to do */
1310 }
1311
1312 SIM_RC
1313 sim_load (sd, prog, abfd, from_tty)
1314      SIM_DESC sd;
1315      char * prog;
1316      bfd * abfd;
1317      int from_tty;
1318 {
1319
1320   /* Do the right thing for ELF executables; this turns out to be
1321      just about the right thing for any object format that:
1322        - we crack using BFD routines
1323        - follows the traditional UNIX text/data/bss layout
1324        - calls the bss section ".bss".   */
1325
1326   extern bfd * sim_load_file (); /* ??? Don't know where this should live.  */
1327   bfd * prog_bfd;
1328
1329   {
1330     bfd * handle;
1331     handle = bfd_openr (prog, 0);       /* could be "moxie" */
1332     
1333     if (!handle)
1334       {
1335         printf("``%s'' could not be opened.\n", prog);
1336         return SIM_RC_FAIL;
1337       }
1338     
1339     /* Makes sure that we have an object file, also cleans gets the 
1340        section headers in place.  */
1341     if (!bfd_check_format (handle, bfd_object))
1342       {
1343         /* wasn't an object file */
1344         bfd_close (handle);
1345         printf ("``%s'' is not appropriate object file.\n", prog);
1346         return SIM_RC_FAIL;
1347       }
1348
1349     /* Clean up after ourselves.  */
1350     bfd_close (handle);
1351   }
1352
1353   /* from sh -- dac */
1354   prog_bfd = sim_load_file (sd, myname, callback, prog, abfd,
1355                             sim_kind == SIM_OPEN_DEBUG,
1356                             0, sim_write);
1357   if (prog_bfd == NULL)
1358     return SIM_RC_FAIL;
1359   
1360   if (abfd == NULL)
1361     bfd_close (prog_bfd);
1362
1363   return SIM_RC_OK;
1364 }
1365
1366 SIM_RC
1367 sim_create_inferior (sd, prog_bfd, argv, env)
1368      SIM_DESC sd;
1369      struct bfd * prog_bfd;
1370      char ** argv;
1371      char ** env;
1372 {
1373   char ** avp;
1374   int l, argc, i, tp;
1375
1376   /* Set the initial register set.  */
1377   l = issue_messages;
1378   issue_messages = 0;
1379   set_initial_gprs ();
1380   issue_messages = l;
1381   
1382   cpu.asregs.regs[PC_REGNO] = bfd_get_start_address (prog_bfd);
1383
1384   /* Copy args into target memory.  */
1385   avp = argv;
1386   for (argc = 0; *avp; avp++)
1387     argc++;
1388
1389   /* Target memory looks like this:
1390      0x00000000 zero word
1391      0x00000004 argc word
1392      0x00000008 start of argv
1393      .
1394      0x0000???? end of argv
1395      0x0000???? zero word 
1396      0x0000???? start of data pointed to by argv  */
1397
1398   wlat (0, 0, 0);
1399   wlat (0, 4, argc);
1400
1401   /* tp is the offset of our first argv data.  */
1402   tp = 4 + 4 + argc * 4 + 4;
1403
1404   for (i = 0; i < argc; i++)
1405     {
1406       /* Set the argv value.  */
1407       wlat (0, 4 + 4 + i * 4, tp);
1408
1409       /* Store the string.  */
1410       strcpy (&cpu.asregs.memory[tp], argv[i]);
1411       tp += strlen (argv[i]) + 1;
1412     }
1413
1414   wlat (0, 4 + 4 + i * 4, 0);
1415
1416   return SIM_RC_OK;
1417 }
1418
1419 void
1420 sim_kill (sd)
1421      SIM_DESC sd;
1422 {
1423   if (tracefile)
1424     fclose(tracefile);
1425 }
1426
1427 void
1428 sim_do_command (sd, cmd)
1429      SIM_DESC sd;
1430      char * cmd;
1431 {
1432   /* Nothing there yet; it's all an error.  */
1433   
1434   if (cmd != NULL)
1435     {
1436       char ** simargv = buildargv (cmd);
1437       if (strcmp (simargv[0], "verbose") == 0)
1438         {
1439           issue_messages = 2;
1440         }
1441       else
1442         {
1443           fprintf (stderr,"Error: \"%s\" is not a valid moxie simulator command.\n",
1444                    cmd);
1445         }
1446     }
1447   else
1448     {
1449       fprintf (stderr, "moxie sim commands: \n");
1450       fprintf (stderr, "  verbose\n");
1451     }
1452 }
1453
1454 void
1455 sim_set_callbacks (ptr)
1456      host_callback * ptr;
1457 {
1458   callback = ptr; 
1459 }