1/* Simulator for Motorola's MCore processor
2   Copyright (C) 1999-2023 Free Software Foundation, Inc.
3   Contributed by Cygnus Solutions.
4
5This file is part of GDB, the GNU debugger.
6
7This program is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
9the Free Software Foundation; either version 3 of the License, or
10(at your option) any later version.
11
12This program is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
19
20/* This must come before any other includes.  */
21#include "defs.h"
22
23#include <signal.h>
24#include <stdlib.h>
25#include <string.h>
26#include <sys/param.h>
27#include <unistd.h>
28#include "bfd.h"
29#include "sim/callback.h"
30#include "libiberty.h"
31#include "sim/sim.h"
32
33#include "sim-main.h"
34#include "sim-base.h"
35#include "sim-signal.h"
36#include "sim-syscall.h"
37#include "sim-options.h"
38
39#include "target-newlib-syscall.h"
40
41#define target_big_endian (CURRENT_TARGET_BYTE_ORDER == BIG_ENDIAN)
42
43
44static unsigned long
45mcore_extract_unsigned_integer (const unsigned char *addr, int len)
46{
47  unsigned long retval;
48  unsigned char * p;
49  unsigned char * startaddr = (unsigned char *)addr;
50  unsigned char * endaddr = startaddr + len;
51
52  if (len > (int) sizeof (unsigned long))
53    printf ("That operation is not available on integers of more than %zu bytes.",
54	    sizeof (unsigned long));
55
56  /* Start at the most significant end of the integer, and work towards
57     the least significant.  */
58  retval = 0;
59
60  if (! target_big_endian)
61    {
62      for (p = endaddr; p > startaddr;)
63	retval = (retval << 8) | * -- p;
64    }
65  else
66    {
67      for (p = startaddr; p < endaddr;)
68	retval = (retval << 8) | * p ++;
69    }
70
71  return retval;
72}
73
74static void
75mcore_store_unsigned_integer (unsigned char *addr, int len, unsigned long val)
76{
77  unsigned char * p;
78  unsigned char * startaddr = (unsigned char *)addr;
79  unsigned char * endaddr = startaddr + len;
80
81  if (! target_big_endian)
82    {
83      for (p = startaddr; p < endaddr;)
84	{
85	  * p ++ = val & 0xff;
86	  val >>= 8;
87	}
88    }
89  else
90    {
91      for (p = endaddr; p > startaddr;)
92	{
93	  * -- p = val & 0xff;
94	  val >>= 8;
95	}
96    }
97}
98
99static int memcycles = 1;
100
101#define gr	cpu->active_gregs
102#define cr	cpu->regs.cregs
103#define sr	cr[0]
104#define vbr	cr[1]
105#define esr	cr[2]
106#define fsr	cr[3]
107#define epc	cr[4]
108#define fpc	cr[5]
109#define ss0	cr[6]
110#define ss1	cr[7]
111#define ss2	cr[8]
112#define ss3	cr[9]
113#define ss4	cr[10]
114#define gcr	cr[11]
115#define gsr	cr[12]
116
117/* maniuplate the carry bit */
118#define C_ON()		(sr & 1)
119#define C_VALUE()	(sr & 1)
120#define C_OFF()		((sr & 1) == 0)
121#define SET_C()		{sr |= 1;}
122#define CLR_C()		{sr &= 0xfffffffe;}
123#define NEW_C(v)	{CLR_C(); sr |= ((v) & 1);}
124
125#define SR_AF()		((sr >> 1) & 1)
126static void set_active_regs (SIM_CPU *cpu)
127{
128  if (SR_AF())
129    cpu->active_gregs = cpu->regs.alt_gregs;
130  else
131    cpu->active_gregs = cpu->regs.gregs;
132}
133
134#define	TRAPCODE	1	/* r1 holds which function we want */
135#define	PARM1	2		/* first parameter  */
136#define	PARM2	3
137#define	PARM3	4
138#define	PARM4	5
139#define	RET1	2		/* register for return values. */
140
141/* Default to a 8 Mbyte (== 2^23) memory space.  */
142#define DEFAULT_MEMORY_SIZE 0x800000
143
144static void
145set_initial_gprs (SIM_CPU *cpu)
146{
147  /* Set up machine just out of reset.  */
148  CPU_PC_SET (cpu, 0);
149  sr = 0;
150
151  /* Clean out the GPRs and alternate GPRs.  */
152  memset (&cpu->regs.gregs, 0, sizeof(cpu->regs.gregs));
153  memset (&cpu->regs.alt_gregs, 0, sizeof(cpu->regs.alt_gregs));
154
155  /* Make our register set point to the right place.  */
156  set_active_regs (cpu);
157
158  /* ABI specifies initial values for these registers.  */
159  gr[0] = DEFAULT_MEMORY_SIZE - 4;
160
161  /* dac fix, the stack address must be 8-byte aligned! */
162  gr[0] = gr[0] - gr[0] % 8;
163  gr[PARM1] = 0;
164  gr[PARM2] = 0;
165  gr[PARM3] = 0;
166  gr[PARM4] = gr[0];
167}
168
169/* Simulate a monitor trap.  */
170
171static void
172handle_trap1 (SIM_DESC sd, SIM_CPU *cpu)
173{
174  /* XXX: We don't pass back the actual errno value.  */
175  gr[RET1] = sim_syscall (cpu, gr[TRAPCODE], gr[PARM1], gr[PARM2], gr[PARM3],
176			  gr[PARM4]);
177}
178
179static void
180process_stub (SIM_DESC sd, SIM_CPU *cpu, int what)
181{
182  /* These values should match those in libgloss/mcore/syscalls.s.  */
183  switch (what)
184    {
185    case 3:  /* _read */
186    case 4:  /* _write */
187    case 5:  /* _open */
188    case 6:  /* _close */
189    case 10: /* _unlink */
190    case 19: /* _lseek */
191    case 43: /* _times */
192      gr[TRAPCODE] = what;
193      handle_trap1 (sd, cpu);
194      break;
195
196    default:
197      if (STATE_VERBOSE_P (sd))
198	fprintf (stderr, "Unhandled stub opcode: %d\n", what);
199      break;
200    }
201}
202
203static void
204util (SIM_DESC sd, SIM_CPU *cpu, unsigned what)
205{
206  switch (what)
207    {
208    case 0:	/* exit */
209      sim_engine_halt (sd, cpu, NULL, cpu->regs.pc, sim_exited, gr[PARM1]);
210      break;
211
212    case 1:	/* printf */
213      if (STATE_VERBOSE_P (sd))
214	fprintf (stderr, "WARNING: printf unimplemented\n");
215      break;
216
217    case 2:	/* scanf */
218      if (STATE_VERBOSE_P (sd))
219	fprintf (stderr, "WARNING: scanf unimplemented\n");
220      break;
221
222    case 3:	/* utime */
223      gr[RET1] = cpu->insts;
224      break;
225
226    case 0xFF:
227      process_stub (sd, cpu, gr[1]);
228      break;
229
230    default:
231      if (STATE_VERBOSE_P (sd))
232	fprintf (stderr, "Unhandled util code: %x\n", what);
233      break;
234    }
235}
236
237/* For figuring out whether we carried; addc/subc use this. */
238static int
239iu_carry (unsigned long a, unsigned long b, int cin)
240{
241  unsigned long	x;
242
243  x = (a & 0xffff) + (b & 0xffff) + cin;
244  x = (x >> 16) + (a >> 16) + (b >> 16);
245  x >>= 16;
246
247  return (x != 0);
248}
249
250/* TODO: Convert to common watchpoints.  */
251#undef WATCHFUNCTIONS
252#ifdef WATCHFUNCTIONS
253
254#define MAXWL 80
255word WL[MAXWL];
256char * WLstr[MAXWL];
257
258int ENDWL=0;
259int WLincyc;
260int WLcyc[MAXWL];
261int WLcnts[MAXWL];
262int WLmax[MAXWL];
263int WLmin[MAXWL];
264word WLendpc;
265int WLbcyc;
266int WLW;
267#endif
268
269#define RD	(inst        & 0xF)
270#define RS	((inst >> 4) & 0xF)
271#define RX	((inst >> 8) & 0xF)
272#define IMM5	((inst >> 4) & 0x1F)
273#define IMM4	((inst) & 0xF)
274
275#define rbat(X)	sim_core_read_1 (cpu, 0, read_map, X)
276#define rhat(X)	sim_core_read_2 (cpu, 0, read_map, X)
277#define rlat(X)	sim_core_read_4 (cpu, 0, read_map, X)
278#define wbat(X, D) sim_core_write_1 (cpu, 0, write_map, X, D)
279#define what(X, D) sim_core_write_2 (cpu, 0, write_map, X, D)
280#define wlat(X, D) sim_core_write_4 (cpu, 0, write_map, X, D)
281
282static int tracing = 0;
283
284#define ILLEGAL() \
285  sim_engine_halt (sd, cpu, NULL, pc, sim_stopped, SIM_SIGILL)
286
287static void
288step_once (SIM_DESC sd, SIM_CPU *cpu)
289{
290  int needfetch;
291  word ibuf;
292  word pc;
293  unsigned short inst;
294  int memops;
295  int bonus_cycles;
296  int insts;
297  int w;
298  int cycs;
299#ifdef WATCHFUNCTIONS
300  word WLhash;
301#endif
302
303  pc = CPU_PC_GET (cpu);
304
305  /* Fetch the initial instructions that we'll decode. */
306  ibuf = rlat (pc & 0xFFFFFFFC);
307  needfetch = 0;
308
309  memops = 0;
310  bonus_cycles = 0;
311  insts = 0;
312
313  /* make our register set point to the right place */
314  set_active_regs (cpu);
315
316#ifdef WATCHFUNCTIONS
317  /* make a hash to speed exec loop, hope it's nonzero */
318  WLhash = 0xFFFFFFFF;
319
320  for (w = 1; w <= ENDWL; w++)
321    WLhash = WLhash & WL[w];
322#endif
323
324  /* TODO: Unindent this block.  */
325    {
326      word oldpc;
327
328      insts ++;
329
330      if (pc & 02)
331	{
332	  if (! target_big_endian)
333	    inst = ibuf >> 16;
334	  else
335	    inst = ibuf & 0xFFFF;
336	  needfetch = 1;
337	}
338      else
339	{
340	  if (! target_big_endian)
341	    inst = ibuf & 0xFFFF;
342	  else
343	    inst = ibuf >> 16;
344	}
345
346#ifdef WATCHFUNCTIONS
347      /* now scan list of watch addresses, if match, count it and
348	 note return address and count cycles until pc=return address */
349
350      if ((WLincyc == 1) && (pc == WLendpc))
351	{
352	  cycs = (cpu->cycles + (insts + bonus_cycles +
353				       (memops * memcycles)) - WLbcyc);
354
355	  if (WLcnts[WLW] == 1)
356	    {
357	      WLmax[WLW] = cycs;
358	      WLmin[WLW] = cycs;
359	      WLcyc[WLW] = 0;
360	    }
361
362	  if (cycs > WLmax[WLW])
363	    {
364	      WLmax[WLW] = cycs;
365	    }
366
367	  if (cycs < WLmin[WLW])
368	    {
369	      WLmin[WLW] = cycs;
370	    }
371
372	  WLcyc[WLW] += cycs;
373	  WLincyc = 0;
374	  WLendpc = 0;
375	}
376
377      /* Optimize with a hash to speed loop.  */
378      if (WLincyc == 0)
379	{
380          if ((WLhash == 0) || ((WLhash & pc) != 0))
381	    {
382	      for (w=1; w <= ENDWL; w++)
383		{
384		  if (pc == WL[w])
385		    {
386		      WLcnts[w]++;
387		      WLbcyc = cpu->cycles + insts
388			+ bonus_cycles + (memops * memcycles);
389		      WLendpc = gr[15];
390		      WLincyc = 1;
391		      WLW = w;
392		      break;
393		    }
394		}
395	    }
396	}
397#endif
398
399      if (tracing)
400	fprintf (stderr, "%.4lx: inst = %.4x ", pc, inst);
401
402      oldpc = pc;
403
404      pc += 2;
405
406      switch (inst >> 8)
407	{
408	case 0x00:
409	  switch RS
410	    {
411	    case 0x0:
412	      switch RD
413		{
414		case 0x0:				/* bkpt */
415		  pc -= 2;
416		  sim_engine_halt (sd, cpu, NULL, pc - 2,
417				   sim_stopped, SIM_SIGTRAP);
418		  break;
419
420		case 0x1:				/* sync */
421		  break;
422
423		case 0x2:				/* rte */
424		  pc = epc;
425		  sr = esr;
426		  needfetch = 1;
427
428		  set_active_regs (cpu);
429		  break;
430
431		case 0x3:				/* rfi */
432		  pc = fpc;
433		  sr = fsr;
434		  needfetch = 1;
435
436		  set_active_regs (cpu);
437		  break;
438
439		case 0x4:				/* stop */
440		  if (STATE_VERBOSE_P (sd))
441		    fprintf (stderr, "WARNING: stop unimplemented\n");
442		  break;
443
444		case 0x5:				/* wait */
445		  if (STATE_VERBOSE_P (sd))
446		    fprintf (stderr, "WARNING: wait unimplemented\n");
447		  break;
448
449		case 0x6:				/* doze */
450		  if (STATE_VERBOSE_P (sd))
451		    fprintf (stderr, "WARNING: doze unimplemented\n");
452		  break;
453
454		case 0x7:
455		  ILLEGAL ();				/* illegal */
456		  break;
457
458		case 0x8:				/* trap 0 */
459		case 0xA:				/* trap 2 */
460		case 0xB:				/* trap 3 */
461		  sim_engine_halt (sd, cpu, NULL, pc,
462				   sim_stopped, SIM_SIGTRAP);
463		  break;
464
465		case 0xC:				/* trap 4 */
466		case 0xD:				/* trap 5 */
467		case 0xE:				/* trap 6 */
468		  ILLEGAL ();				/* illegal */
469		  break;
470
471		case 0xF: 				/* trap 7 */
472		  sim_engine_halt (sd, cpu, NULL, pc,	/* integer div-by-0 */
473				   sim_stopped, SIM_SIGTRAP);
474		  break;
475
476		case 0x9:				/* trap 1 */
477		  handle_trap1 (sd, cpu);
478		  break;
479		}
480	      break;
481
482	    case 0x1:
483	      ILLEGAL ();				/* illegal */
484	      break;
485
486	    case 0x2:					/* mvc */
487	      gr[RD] = C_VALUE();
488	      break;
489	    case 0x3:					/* mvcv */
490	      gr[RD] = C_OFF();
491	      break;
492	    case 0x4:					/* ldq */
493	      {
494		word addr = gr[RD];
495		int regno = 4;			/* always r4-r7 */
496
497		bonus_cycles++;
498		memops += 4;
499		do
500		  {
501		    gr[regno] = rlat (addr);
502		    addr += 4;
503		    regno++;
504		  }
505		while ((regno&0x3) != 0);
506	      }
507	      break;
508	    case 0x5:					/* stq */
509	      {
510		word addr = gr[RD];
511		int regno = 4;			/* always r4-r7 */
512
513		memops += 4;
514		bonus_cycles++;
515		do
516		  {
517		    wlat (addr, gr[regno]);
518		    addr += 4;
519		    regno++;
520		  }
521		while ((regno & 0x3) != 0);
522	      }
523	      break;
524	    case 0x6:					/* ldm */
525	      {
526		word addr = gr[0];
527		int regno = RD;
528
529		/* bonus cycle is really only needed if
530		   the next insn shifts the last reg loaded.
531
532		   bonus_cycles++;
533		*/
534		memops += 16-regno;
535		while (regno <= 0xF)
536		  {
537		    gr[regno] = rlat (addr);
538		    addr += 4;
539		    regno++;
540		  }
541	      }
542	      break;
543	    case 0x7:					/* stm */
544	      {
545		word addr = gr[0];
546		int regno = RD;
547
548		/* this should be removed! */
549		/*  bonus_cycles ++; */
550
551		memops += 16 - regno;
552		while (regno <= 0xF)
553		  {
554		    wlat (addr, gr[regno]);
555		    addr += 4;
556		    regno++;
557		  }
558	      }
559	      break;
560
561	    case 0x8:					/* dect */
562	      gr[RD] -= C_VALUE();
563	      break;
564	    case 0x9:					/* decf */
565	      gr[RD] -= C_OFF();
566	      break;
567	    case 0xA:					/* inct */
568	      gr[RD] += C_VALUE();
569	      break;
570	    case 0xB:					/* incf */
571	      gr[RD] += C_OFF();
572	      break;
573	    case 0xC:					/* jmp */
574	      pc = gr[RD];
575	      if (tracing && RD == 15)
576		fprintf (stderr, "Func return, r2 = %lxx, r3 = %lx\n",
577			 gr[2], gr[3]);
578	      bonus_cycles++;
579	      needfetch = 1;
580	      break;
581	    case 0xD:					/* jsr */
582	      gr[15] = pc;
583	      pc = gr[RD];
584	      bonus_cycles++;
585	      needfetch = 1;
586	      break;
587	    case 0xE:					/* ff1 */
588	      {
589		word tmp, i;
590		tmp = gr[RD];
591		for (i = 0; !(tmp & 0x80000000) && i < 32; i++)
592		  tmp <<= 1;
593		gr[RD] = i;
594	      }
595	      break;
596	    case 0xF:					/* brev */
597	      {
598		word tmp;
599		tmp = gr[RD];
600		tmp = ((tmp & 0xaaaaaaaa) >>  1) | ((tmp & 0x55555555) <<  1);
601		tmp = ((tmp & 0xcccccccc) >>  2) | ((tmp & 0x33333333) <<  2);
602		tmp = ((tmp & 0xf0f0f0f0) >>  4) | ((tmp & 0x0f0f0f0f) <<  4);
603		tmp = ((tmp & 0xff00ff00) >>  8) | ((tmp & 0x00ff00ff) <<  8);
604		gr[RD] = ((tmp & 0xffff0000) >> 16) | ((tmp & 0x0000ffff) << 16);
605	      }
606	      break;
607	    }
608	  break;
609	case 0x01:
610	  switch RS
611	    {
612	    case 0x0:					/* xtrb3 */
613	      gr[1] = (gr[RD]) & 0xFF;
614	      NEW_C (gr[RD] != 0);
615	      break;
616	    case 0x1:					/* xtrb2 */
617	      gr[1] = (gr[RD]>>8) & 0xFF;
618	      NEW_C (gr[RD] != 0);
619	      break;
620	    case 0x2:					/* xtrb1 */
621	      gr[1] = (gr[RD]>>16) & 0xFF;
622	      NEW_C (gr[RD] != 0);
623	      break;
624	    case 0x3:					/* xtrb0 */
625	      gr[1] = (gr[RD]>>24) & 0xFF;
626	      NEW_C (gr[RD] != 0);
627	      break;
628	    case 0x4:					/* zextb */
629	      gr[RD] &= 0x000000FF;
630	      break;
631	    case 0x5:					/* sextb */
632	      {
633		long tmp;
634		tmp = gr[RD];
635		tmp <<= 24;
636		tmp >>= 24;
637		gr[RD] = tmp;
638	      }
639	      break;
640	    case 0x6:					/* zexth */
641	      gr[RD] &= 0x0000FFFF;
642	      break;
643	    case 0x7:					/* sexth */
644	      {
645		long tmp;
646		tmp = gr[RD];
647		tmp <<= 16;
648		tmp >>= 16;
649		gr[RD] = tmp;
650	      }
651	      break;
652	    case 0x8:					/* declt */
653	      --gr[RD];
654	      NEW_C ((long)gr[RD] < 0);
655	      break;
656	    case 0x9:					/* tstnbz */
657	      {
658		word tmp = gr[RD];
659		NEW_C ((tmp & 0xFF000000) != 0 &&
660		       (tmp & 0x00FF0000) != 0 && (tmp & 0x0000FF00) != 0 &&
661		       (tmp & 0x000000FF) != 0);
662	      }
663	      break;
664	    case 0xA:					/* decgt */
665	      --gr[RD];
666	      NEW_C ((long)gr[RD] > 0);
667	      break;
668	    case 0xB:					/* decne */
669	      --gr[RD];
670	      NEW_C ((long)gr[RD] != 0);
671	      break;
672	    case 0xC:					/* clrt */
673	      if (C_ON())
674		gr[RD] = 0;
675	      break;
676	    case 0xD:					/* clrf */
677	      if (C_OFF())
678		gr[RD] = 0;
679	      break;
680	    case 0xE:					/* abs */
681	      if (gr[RD] & 0x80000000)
682		gr[RD] = ~gr[RD] + 1;
683	      break;
684	    case 0xF:					/* not */
685	      gr[RD] = ~gr[RD];
686	      break;
687	    }
688	  break;
689	case 0x02:					/* movt */
690	  if (C_ON())
691	    gr[RD] = gr[RS];
692	  break;
693	case 0x03:					/* mult */
694	  /* consume 2 bits per cycle from rs, until rs is 0 */
695	  {
696	    unsigned int t = gr[RS];
697	    int ticks;
698	    for (ticks = 0; t != 0 ; t >>= 2)
699	      ticks++;
700	    bonus_cycles += ticks;
701	  }
702	  bonus_cycles += 2;  /* min. is 3, so add 2, plus ticks above */
703	  if (tracing)
704	    fprintf (stderr, "  mult %lx by %lx to give %lx",
705		     gr[RD], gr[RS], gr[RD] * gr[RS]);
706	  gr[RD] = gr[RD] * gr[RS];
707	  break;
708	case 0x04:					/* loopt */
709	  if (C_ON())
710	    {
711	      pc += (IMM4 << 1) - 32;
712	      bonus_cycles ++;
713	      needfetch = 1;
714	    }
715	  --gr[RS];				/* not RD! */
716	  NEW_C (((long)gr[RS]) > 0);
717	  break;
718	case 0x05:					/* subu */
719	  gr[RD] -= gr[RS];
720	  break;
721	case 0x06:					/* addc */
722	  {
723	    unsigned long tmp, a, b;
724	    a = gr[RD];
725	    b = gr[RS];
726	    gr[RD] = a + b + C_VALUE ();
727	    tmp = iu_carry (a, b, C_VALUE ());
728	    NEW_C (tmp);
729	  }
730	  break;
731	case 0x07:					/* subc */
732	  {
733	    unsigned long tmp, a, b;
734	    a = gr[RD];
735	    b = gr[RS];
736	    gr[RD] = a - b + C_VALUE () - 1;
737	    tmp = iu_carry (a,~b, C_VALUE ());
738	    NEW_C (tmp);
739	  }
740	  break;
741	case 0x08:					/* illegal */
742	case 0x09:					/* illegal*/
743	  ILLEGAL ();
744	  break;
745	case 0x0A:					/* movf */
746	  if (C_OFF())
747	    gr[RD] = gr[RS];
748	  break;
749	case 0x0B:					/* lsr */
750	  {
751	    unsigned long dst, src;
752	    dst = gr[RD];
753	    src = gr[RS];
754	    /* We must not rely solely upon the native shift operations, since they
755	       may not match the M*Core's behaviour on boundary conditions.  */
756	    dst = src > 31 ? 0 : dst >> src;
757	    gr[RD] = dst;
758	  }
759	  break;
760	case 0x0C:					/* cmphs */
761	  NEW_C ((unsigned long )gr[RD] >=
762		 (unsigned long)gr[RS]);
763	  break;
764	case 0x0D:					/* cmplt */
765	  NEW_C ((long)gr[RD] < (long)gr[RS]);
766	  break;
767	case 0x0E:					/* tst */
768	  NEW_C ((gr[RD] & gr[RS]) != 0);
769	  break;
770	case 0x0F:					/* cmpne */
771	  NEW_C (gr[RD] != gr[RS]);
772	  break;
773	case 0x10: case 0x11:				/* mfcr */
774	  {
775	    unsigned r;
776	    r = IMM5;
777	    if (r <= LAST_VALID_CREG)
778	      gr[RD] = cr[r];
779	    else
780	      ILLEGAL ();
781	  }
782	  break;
783
784	case 0x12:					/* mov */
785	  gr[RD] = gr[RS];
786	  if (tracing)
787	    fprintf (stderr, "MOV %lx into reg %d", gr[RD], RD);
788	  break;
789
790	case 0x13:					/* bgenr */
791	  if (gr[RS] & 0x20)
792	    gr[RD] = 0;
793	  else
794	    gr[RD] = 1 << (gr[RS] & 0x1F);
795	  break;
796
797	case 0x14:					/* rsub */
798	  gr[RD] = gr[RS] - gr[RD];
799	  break;
800
801	case 0x15:					/* ixw */
802	  gr[RD] += gr[RS]<<2;
803	  break;
804
805	case 0x16:					/* and */
806	  gr[RD] &= gr[RS];
807	  break;
808
809	case 0x17:					/* xor */
810	  gr[RD] ^= gr[RS];
811	  break;
812
813	case 0x18: case 0x19:				/* mtcr */
814	  {
815	    unsigned r;
816	    r = IMM5;
817	    if (r <= LAST_VALID_CREG)
818	      cr[r] = gr[RD];
819	    else
820	      ILLEGAL ();
821
822	    /* we might have changed register sets... */
823	    set_active_regs (cpu);
824	  }
825	  break;
826
827	case 0x1A:					/* asr */
828	  /* We must not rely solely upon the native shift operations, since they
829	     may not match the M*Core's behaviour on boundary conditions.  */
830	  if (gr[RS] > 30)
831	    gr[RD] = ((long) gr[RD]) < 0 ? -1 : 0;
832	  else
833	    gr[RD] = (long) gr[RD] >> gr[RS];
834	  break;
835
836	case 0x1B:					/* lsl */
837	  /* We must not rely solely upon the native shift operations, since they
838	     may not match the M*Core's behaviour on boundary conditions.  */
839	  gr[RD] = gr[RS] > 31 ? 0 : gr[RD] << gr[RS];
840	  break;
841
842	case 0x1C:					/* addu */
843	  gr[RD] += gr[RS];
844	  break;
845
846	case 0x1D:					/* ixh */
847	  gr[RD] += gr[RS] << 1;
848	  break;
849
850	case 0x1E:					/* or */
851	  gr[RD] |= gr[RS];
852	  break;
853
854	case 0x1F:					/* andn */
855	  gr[RD] &= ~gr[RS];
856	  break;
857	case 0x20: case 0x21:				/* addi */
858	  gr[RD] =
859	    gr[RD] + (IMM5 + 1);
860	  break;
861	case 0x22: case 0x23:				/* cmplti */
862	  {
863	    int tmp = (IMM5 + 1);
864	    if (gr[RD] < tmp)
865	      {
866	        SET_C();
867	      }
868	    else
869	      {
870	        CLR_C();
871	      }
872	  }
873	  break;
874	case 0x24: case 0x25:				/* subi */
875	  gr[RD] =
876	    gr[RD] - (IMM5 + 1);
877	  break;
878	case 0x26: case 0x27:				/* illegal */
879	  ILLEGAL ();
880	  break;
881	case 0x28: case 0x29:				/* rsubi */
882	  gr[RD] =
883	    IMM5 - gr[RD];
884	  break;
885	case 0x2A: case 0x2B:				/* cmpnei */
886	  if (gr[RD] != IMM5)
887	    {
888	      SET_C();
889	    }
890	  else
891	    {
892	      CLR_C();
893	    }
894	  break;
895
896	case 0x2C: case 0x2D:				/* bmaski, divu */
897	  {
898	    unsigned imm = IMM5;
899
900	    if (imm == 1)
901	      {
902		int exe;
903		int rxnlz, r1nlz;
904		unsigned int rx, r1;
905
906		rx = gr[RD];
907		r1 = gr[1];
908		exe = 0;
909
910		/* unsigned divide */
911		gr[RD] = (word) ((unsigned int) gr[RD] / (unsigned int)gr[1] );
912
913		/* compute bonus_cycles for divu */
914		for (r1nlz = 0; ((r1 & 0x80000000) == 0) && (r1nlz < 32); r1nlz ++)
915		  r1 = r1 << 1;
916
917		for (rxnlz = 0; ((rx & 0x80000000) == 0) && (rxnlz < 32); rxnlz ++)
918		  rx = rx << 1;
919
920		if (r1nlz < rxnlz)
921		  exe += 4;
922		else
923		  exe += 5 + r1nlz - rxnlz;
924
925		if (exe >= (2 * memcycles - 1))
926		  {
927		    bonus_cycles += exe - (2 * memcycles) + 1;
928		  }
929	      }
930	    else if (imm == 0 || imm >= 8)
931	      {
932		/* bmaski */
933		if (imm == 0)
934		  gr[RD] = -1;
935		else
936		  gr[RD] = (1 << imm) - 1;
937	      }
938	    else
939	      {
940		/* illegal */
941		ILLEGAL ();
942	      }
943	  }
944	  break;
945	case 0x2E: case 0x2F:				/* andi */
946	  gr[RD] = gr[RD] & IMM5;
947	  break;
948	case 0x30: case 0x31:				/* bclri */
949	  gr[RD] = gr[RD] & ~(1<<IMM5);
950	  break;
951	case 0x32: case 0x33:				/* bgeni, divs */
952	  {
953	    unsigned imm = IMM5;
954	    if (imm == 1)
955	      {
956		int exe,sc;
957		int rxnlz, r1nlz;
958		signed int rx, r1;
959
960		/* compute bonus_cycles for divu */
961		rx = gr[RD];
962		r1 = gr[1];
963		exe = 0;
964
965		if (((rx < 0) && (r1 > 0)) || ((rx >= 0) && (r1 < 0)))
966		  sc = 1;
967		else
968		  sc = 0;
969
970		rx = abs (rx);
971		r1 = abs (r1);
972
973		/* signed divide, general registers are of type int, so / op is OK */
974		gr[RD] = gr[RD] / gr[1];
975
976		for (r1nlz = 0; ((r1 & 0x80000000) == 0) && (r1nlz < 32) ; r1nlz ++ )
977		  r1 = r1 << 1;
978
979		for (rxnlz = 0; ((rx & 0x80000000) == 0) && (rxnlz < 32) ; rxnlz ++ )
980		  rx = rx << 1;
981
982		if (r1nlz < rxnlz)
983		  exe += 5;
984		else
985		  exe += 6 + r1nlz - rxnlz + sc;
986
987		if (exe >= (2 * memcycles - 1))
988		  {
989		    bonus_cycles += exe - (2 * memcycles) + 1;
990		  }
991	      }
992	    else if (imm >= 7)
993	      {
994		/* bgeni */
995		gr[RD] = (1 << IMM5);
996	      }
997	    else
998	      {
999		/* illegal */
1000		ILLEGAL ();
1001	      }
1002	    break;
1003	  }
1004	case 0x34: case 0x35:				/* bseti */
1005	  gr[RD] = gr[RD] | (1 << IMM5);
1006	  break;
1007	case 0x36: case 0x37:				/* btsti */
1008	  NEW_C (gr[RD] >> IMM5);
1009	  break;
1010	case 0x38: case 0x39:				/* xsr, rotli */
1011	  {
1012	    unsigned imm = IMM5;
1013	    unsigned long tmp = gr[RD];
1014	    if (imm == 0)
1015	      {
1016		word cbit;
1017		cbit = C_VALUE();
1018		NEW_C (tmp);
1019		gr[RD] = (cbit << 31) | (tmp >> 1);
1020	      }
1021	    else
1022	      gr[RD] = (tmp << imm) | (tmp >> (32 - imm));
1023	  }
1024	  break;
1025	case 0x3A: case 0x3B:				/* asrc, asri */
1026	  {
1027	    unsigned imm = IMM5;
1028	    long tmp = gr[RD];
1029	    if (imm == 0)
1030	      {
1031		NEW_C (tmp);
1032		gr[RD] = tmp >> 1;
1033	      }
1034	    else
1035	      gr[RD] = tmp >> imm;
1036	  }
1037	  break;
1038	case 0x3C: case 0x3D:				/* lslc, lsli */
1039	  {
1040	    unsigned imm = IMM5;
1041	    unsigned long tmp = gr[RD];
1042	    if (imm == 0)
1043	      {
1044		NEW_C (tmp >> 31);
1045		gr[RD] = tmp << 1;
1046	      }
1047	    else
1048	      gr[RD] = tmp << imm;
1049	  }
1050	  break;
1051	case 0x3E: case 0x3F:				/* lsrc, lsri */
1052	  {
1053	    unsigned imm = IMM5;
1054	    unsigned long tmp = gr[RD];
1055	    if (imm == 0)
1056	      {
1057		NEW_C (tmp);
1058		gr[RD] = tmp >> 1;
1059	      }
1060	    else
1061	      gr[RD] = tmp >> imm;
1062	  }
1063	  break;
1064	case 0x40: case 0x41: case 0x42: case 0x43:
1065	case 0x44: case 0x45: case 0x46: case 0x47:
1066	case 0x48: case 0x49: case 0x4A: case 0x4B:
1067	case 0x4C: case 0x4D: case 0x4E: case 0x4F:
1068	  ILLEGAL ();
1069	  break;
1070	case 0x50:
1071	  util (sd, cpu, inst & 0xFF);
1072	  break;
1073	case 0x51: case 0x52: case 0x53:
1074	case 0x54: case 0x55: case 0x56: case 0x57:
1075	case 0x58: case 0x59: case 0x5A: case 0x5B:
1076	case 0x5C: case 0x5D: case 0x5E: case 0x5F:
1077	  ILLEGAL ();
1078	  break;
1079	case 0x60: case 0x61: case 0x62: case 0x63:	/* movi  */
1080	case 0x64: case 0x65: case 0x66: case 0x67:
1081	  gr[RD] = (inst >> 4) & 0x7F;
1082	  break;
1083	case 0x68: case 0x69: case 0x6A: case 0x6B:
1084	case 0x6C: case 0x6D: case 0x6E: case 0x6F:	/* illegal */
1085	  ILLEGAL ();
1086	  break;
1087	case 0x71: case 0x72: case 0x73:
1088	case 0x74: case 0x75: case 0x76: case 0x77:
1089	case 0x78: case 0x79: case 0x7A: case 0x7B:
1090	case 0x7C: case 0x7D: case 0x7E:		/* lrw */
1091	  gr[RX] =  rlat ((pc + ((inst & 0xFF) << 2)) & 0xFFFFFFFC);
1092	  if (tracing)
1093	    fprintf (stderr, "LRW of 0x%x from 0x%lx to reg %d",
1094		     rlat ((pc + ((inst & 0xFF) << 2)) & 0xFFFFFFFC),
1095		     (pc + ((inst & 0xFF) << 2)) & 0xFFFFFFFC, RX);
1096	  memops++;
1097	  break;
1098	case 0x7F:					/* jsri */
1099	  gr[15] = pc;
1100	  if (tracing)
1101	    fprintf (stderr,
1102		     "func call: r2 = %lx r3 = %lx r4 = %lx r5 = %lx r6 = %lx r7 = %lx\n",
1103		     gr[2], gr[3], gr[4], gr[5], gr[6], gr[7]);
1104	case 0x70:					/* jmpi */
1105	  pc = rlat ((pc + ((inst & 0xFF) << 2)) & 0xFFFFFFFC);
1106	  memops++;
1107	  bonus_cycles++;
1108	  needfetch = 1;
1109	  break;
1110
1111	case 0x80: case 0x81: case 0x82: case 0x83:
1112	case 0x84: case 0x85: case 0x86: case 0x87:
1113	case 0x88: case 0x89: case 0x8A: case 0x8B:
1114	case 0x8C: case 0x8D: case 0x8E: case 0x8F:	/* ld */
1115	  gr[RX] = rlat (gr[RD] + ((inst >> 2) & 0x003C));
1116	  if (tracing)
1117	    fprintf (stderr, "load reg %d from 0x%lx with 0x%lx",
1118		     RX,
1119		     gr[RD] + ((inst >> 2) & 0x003C), gr[RX]);
1120	  memops++;
1121	  break;
1122	case 0x90: case 0x91: case 0x92: case 0x93:
1123	case 0x94: case 0x95: case 0x96: case 0x97:
1124	case 0x98: case 0x99: case 0x9A: case 0x9B:
1125	case 0x9C: case 0x9D: case 0x9E: case 0x9F:	/* st */
1126	  wlat (gr[RD] + ((inst >> 2) & 0x003C), gr[RX]);
1127	  if (tracing)
1128	    fprintf (stderr, "store reg %d (containing 0x%lx) to 0x%lx",
1129		     RX, gr[RX],
1130		     gr[RD] + ((inst >> 2) & 0x003C));
1131	  memops++;
1132	  break;
1133	case 0xA0: case 0xA1: case 0xA2: case 0xA3:
1134	case 0xA4: case 0xA5: case 0xA6: case 0xA7:
1135	case 0xA8: case 0xA9: case 0xAA: case 0xAB:
1136	case 0xAC: case 0xAD: case 0xAE: case 0xAF:	/* ld.b */
1137	  gr[RX] = rbat (gr[RD] + RS);
1138	  memops++;
1139	  break;
1140	case 0xB0: case 0xB1: case 0xB2: case 0xB3:
1141	case 0xB4: case 0xB5: case 0xB6: case 0xB7:
1142	case 0xB8: case 0xB9: case 0xBA: case 0xBB:
1143	case 0xBC: case 0xBD: case 0xBE: case 0xBF:	/* st.b */
1144	  wbat (gr[RD] + RS, gr[RX]);
1145	  memops++;
1146	  break;
1147	case 0xC0: case 0xC1: case 0xC2: case 0xC3:
1148	case 0xC4: case 0xC5: case 0xC6: case 0xC7:
1149	case 0xC8: case 0xC9: case 0xCA: case 0xCB:
1150	case 0xCC: case 0xCD: case 0xCE: case 0xCF:	/* ld.h */
1151	  gr[RX] = rhat (gr[RD] + ((inst >> 3) & 0x001E));
1152	  memops++;
1153	  break;
1154	case 0xD0: case 0xD1: case 0xD2: case 0xD3:
1155	case 0xD4: case 0xD5: case 0xD6: case 0xD7:
1156	case 0xD8: case 0xD9: case 0xDA: case 0xDB:
1157	case 0xDC: case 0xDD: case 0xDE: case 0xDF:	/* st.h */
1158	  what (gr[RD] + ((inst >> 3) & 0x001E), gr[RX]);
1159	  memops++;
1160	  break;
1161	case 0xE8: case 0xE9: case 0xEA: case 0xEB:
1162	case 0xEC: case 0xED: case 0xEE: case 0xEF:	/* bf */
1163	  if (C_OFF())
1164	    {
1165	      int disp;
1166	      disp = inst & 0x03FF;
1167	      if (inst & 0x0400)
1168		disp |= 0xFFFFFC00;
1169	      pc += disp<<1;
1170	      bonus_cycles++;
1171	      needfetch = 1;
1172	    }
1173	  break;
1174	case 0xE0: case 0xE1: case 0xE2: case 0xE3:
1175	case 0xE4: case 0xE5: case 0xE6: case 0xE7:	/* bt */
1176	  if (C_ON())
1177	    {
1178	      int disp;
1179	      disp = inst & 0x03FF;
1180	      if (inst & 0x0400)
1181		disp |= 0xFFFFFC00;
1182	      pc += disp<<1;
1183	      bonus_cycles++;
1184	      needfetch = 1;
1185	    }
1186	  break;
1187
1188	case 0xF8: case 0xF9: case 0xFA: case 0xFB:
1189	case 0xFC: case 0xFD: case 0xFE: case 0xFF:	/* bsr */
1190	  gr[15] = pc;
1191	case 0xF0: case 0xF1: case 0xF2: case 0xF3:
1192	case 0xF4: case 0xF5: case 0xF6: case 0xF7:	/* br */
1193	  {
1194	    int disp;
1195	    disp = inst & 0x03FF;
1196	    if (inst & 0x0400)
1197	      disp |= 0xFFFFFC00;
1198	    pc += disp<<1;
1199	    bonus_cycles++;
1200	    needfetch = 1;
1201	  }
1202	  break;
1203
1204	}
1205
1206      if (tracing)
1207	fprintf (stderr, "\n");
1208
1209      if (needfetch)
1210	{
1211	  ibuf = rlat (pc & 0xFFFFFFFC);
1212	  needfetch = 0;
1213	}
1214    }
1215
1216  /* Hide away the things we've cached while executing.  */
1217  CPU_PC_SET (cpu, pc);
1218  cpu->insts += insts;		/* instructions done ... */
1219  cpu->cycles += insts;		/* and each takes a cycle */
1220  cpu->cycles += bonus_cycles;	/* and extra cycles for branches */
1221  cpu->cycles += memops * memcycles;	/* and memop cycle delays */
1222}
1223
1224void
1225sim_engine_run (SIM_DESC sd,
1226		int next_cpu_nr,  /* ignore  */
1227		int nr_cpus,      /* ignore  */
1228		int siggnal)      /* ignore  */
1229{
1230  sim_cpu *cpu;
1231
1232  SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
1233
1234  cpu = STATE_CPU (sd, 0);
1235
1236  while (1)
1237    {
1238      step_once (sd, cpu);
1239      if (sim_events_tick (sd))
1240	sim_events_process (sd);
1241    }
1242}
1243
1244static int
1245mcore_reg_store (SIM_CPU *cpu, int rn, const void *memory, int length)
1246{
1247  if (rn < NUM_MCORE_REGS && rn >= 0)
1248    {
1249      if (length == 4)
1250	{
1251	  long ival;
1252
1253	  /* misalignment safe */
1254	  ival = mcore_extract_unsigned_integer (memory, 4);
1255	  cpu->asints[rn] = ival;
1256	}
1257
1258      return 4;
1259    }
1260  else
1261    return 0;
1262}
1263
1264static int
1265mcore_reg_fetch (SIM_CPU *cpu, int rn, void *memory, int length)
1266{
1267  if (rn < NUM_MCORE_REGS && rn >= 0)
1268    {
1269      if (length == 4)
1270	{
1271	  long ival = cpu->asints[rn];
1272
1273	  /* misalignment-safe */
1274	  mcore_store_unsigned_integer (memory, 4, ival);
1275	}
1276
1277      return 4;
1278    }
1279  else
1280    return 0;
1281}
1282
1283void
1284sim_info (SIM_DESC sd, int verbose)
1285{
1286  SIM_CPU *cpu = STATE_CPU (sd, 0);
1287#ifdef WATCHFUNCTIONS
1288  int w, wcyc;
1289#endif
1290  double virttime = cpu->cycles / 36.0e6;
1291  host_callback *callback = STATE_CALLBACK (sd);
1292
1293  callback->printf_filtered (callback, "\n\n# instructions executed  %10d\n",
1294			     cpu->insts);
1295  callback->printf_filtered (callback, "# cycles                 %10d\n",
1296			     cpu->cycles);
1297  callback->printf_filtered (callback, "# pipeline stalls        %10d\n",
1298			     cpu->stalls);
1299  callback->printf_filtered (callback, "# virtual time taken     %10.4f\n",
1300			     virttime);
1301
1302#ifdef WATCHFUNCTIONS
1303  callback->printf_filtered (callback, "\nNumber of watched functions: %d\n",
1304			     ENDWL);
1305
1306  wcyc = 0;
1307
1308  for (w = 1; w <= ENDWL; w++)
1309    {
1310      callback->printf_filtered (callback, "WL = %s %8x\n",WLstr[w],WL[w]);
1311      callback->printf_filtered (callback, "  calls = %d, cycles = %d\n",
1312				 WLcnts[w],WLcyc[w]);
1313
1314      if (WLcnts[w] != 0)
1315	callback->printf_filtered (callback,
1316				   "  maxcpc = %d, mincpc = %d, avecpc = %d\n",
1317				   WLmax[w],WLmin[w],WLcyc[w]/WLcnts[w]);
1318      wcyc += WLcyc[w];
1319    }
1320
1321  callback->printf_filtered (callback,
1322			     "Total cycles for watched functions: %d\n",wcyc);
1323#endif
1324}
1325
1326static sim_cia
1327mcore_pc_get (sim_cpu *cpu)
1328{
1329  return cpu->regs.pc;
1330}
1331
1332static void
1333mcore_pc_set (sim_cpu *cpu, sim_cia pc)
1334{
1335  cpu->regs.pc = pc;
1336}
1337
1338static void
1339free_state (SIM_DESC sd)
1340{
1341  if (STATE_MODULES (sd) != NULL)
1342    sim_module_uninstall (sd);
1343  sim_cpu_free_all (sd);
1344  sim_state_free (sd);
1345}
1346
1347SIM_DESC
1348sim_open (SIM_OPEN_KIND kind, host_callback *cb,
1349	  struct bfd *abfd, char * const *argv)
1350{
1351  int i;
1352  SIM_DESC sd = sim_state_alloc (kind, cb);
1353  SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
1354
1355  /* Set default options before parsing user options.  */
1356  cb->syscall_map = cb_mcore_syscall_map;
1357
1358  /* The cpu data is kept in a separately allocated chunk of memory.  */
1359  if (sim_cpu_alloc_all (sd, 1) != SIM_RC_OK)
1360    {
1361      free_state (sd);
1362      return 0;
1363    }
1364
1365  if (sim_pre_argv_init (sd, argv[0]) != SIM_RC_OK)
1366    {
1367      free_state (sd);
1368      return 0;
1369    }
1370
1371  /* The parser will print an error message for us, so we silently return.  */
1372  if (sim_parse_args (sd, argv) != SIM_RC_OK)
1373    {
1374      free_state (sd);
1375      return 0;
1376    }
1377
1378  /* Check for/establish the a reference program image.  */
1379  if (sim_analyze_program (sd, STATE_PROG_FILE (sd), abfd) != SIM_RC_OK)
1380    {
1381      free_state (sd);
1382      return 0;
1383    }
1384
1385  /* Configure/verify the target byte order and other runtime
1386     configuration options.  */
1387  if (sim_config (sd) != SIM_RC_OK)
1388    {
1389      sim_module_uninstall (sd);
1390      return 0;
1391    }
1392
1393  if (sim_post_argv_init (sd) != SIM_RC_OK)
1394    {
1395      /* Uninstall the modules to avoid memory leaks,
1396	 file descriptor leaks, etc.  */
1397      sim_module_uninstall (sd);
1398      return 0;
1399    }
1400
1401  /* CPU specific initialization.  */
1402  for (i = 0; i < MAX_NR_PROCESSORS; ++i)
1403    {
1404      SIM_CPU *cpu = STATE_CPU (sd, i);
1405
1406      CPU_REG_FETCH (cpu) = mcore_reg_fetch;
1407      CPU_REG_STORE (cpu) = mcore_reg_store;
1408      CPU_PC_FETCH (cpu) = mcore_pc_get;
1409      CPU_PC_STORE (cpu) = mcore_pc_set;
1410
1411      set_initial_gprs (cpu);	/* Reset the GPR registers.  */
1412    }
1413
1414  /* Default to a 8 Mbyte (== 2^23) memory space.  */
1415  sim_do_commandf (sd, "memory-size %#x", DEFAULT_MEMORY_SIZE);
1416
1417  return sd;
1418}
1419
1420SIM_RC
1421sim_create_inferior (SIM_DESC sd, struct bfd *prog_bfd,
1422		     char * const *argv, char * const *env)
1423{
1424  SIM_CPU *cpu = STATE_CPU (sd, 0);
1425  char * const *avp;
1426  int nargs = 0;
1427  int nenv = 0;
1428  int s_length;
1429  int l;
1430  unsigned long strings;
1431  unsigned long pointers;
1432  unsigned long hi_stack;
1433
1434
1435  /* Set the initial register set.  */
1436  set_initial_gprs (cpu);
1437
1438  hi_stack = DEFAULT_MEMORY_SIZE - 4;
1439  CPU_PC_SET (cpu, bfd_get_start_address (prog_bfd));
1440
1441  /* Calculate the argument and environment strings.  */
1442  s_length = 0;
1443  nargs = 0;
1444  avp = argv;
1445  while (avp && *avp)
1446    {
1447      l = strlen (*avp) + 1;	/* include the null */
1448      s_length += (l + 3) & ~3;	/* make it a 4 byte boundary */
1449      nargs++; avp++;
1450    }
1451
1452  nenv = 0;
1453  avp = env;
1454  while (avp && *avp)
1455    {
1456      l = strlen (*avp) + 1;	/* include the null */
1457      s_length += (l + 3) & ~ 3;/* make it a 4 byte boundary */
1458      nenv++; avp++;
1459    }
1460
1461  /* Claim some memory for the pointers and strings. */
1462  pointers = hi_stack - sizeof(word) * (nenv+1+nargs+1);
1463  pointers &= ~3;		/* must be 4-byte aligned */
1464  gr[0] = pointers;
1465
1466  strings = gr[0] - s_length;
1467  strings &= ~3;		/* want to make it 4-byte aligned */
1468  gr[0] = strings;
1469  /* dac fix, the stack address must be 8-byte aligned! */
1470  gr[0] = gr[0] - gr[0] % 8;
1471
1472  /* Loop through the arguments and fill them in.  */
1473  gr[PARM1] = nargs;
1474  if (nargs == 0)
1475    {
1476      /* No strings to fill in.  */
1477      gr[PARM2] = 0;
1478    }
1479  else
1480    {
1481      gr[PARM2] = pointers;
1482      avp = argv;
1483      while (avp && *avp)
1484	{
1485	  /* Save where we're putting it.  */
1486	  wlat (pointers, strings);
1487
1488	  /* Copy the string.  */
1489	  l = strlen (* avp) + 1;
1490	  sim_core_write_buffer (sd, cpu, write_map, *avp, strings, l);
1491
1492	  /* Bump the pointers.  */
1493	  avp++;
1494	  pointers += 4;
1495	  strings += l+1;
1496	}
1497
1498      /* A null to finish the list.  */
1499      wlat (pointers, 0);
1500      pointers += 4;
1501    }
1502
1503  /* Now do the environment pointers.  */
1504  if (nenv == 0)
1505    {
1506      /* No strings to fill in.  */
1507      gr[PARM3] = 0;
1508    }
1509  else
1510    {
1511      gr[PARM3] = pointers;
1512      avp = env;
1513
1514      while (avp && *avp)
1515	{
1516	  /* Save where we're putting it.  */
1517	  wlat (pointers, strings);
1518
1519	  /* Copy the string.  */
1520	  l = strlen (* avp) + 1;
1521	  sim_core_write_buffer (sd, cpu, write_map, *avp, strings, l);
1522
1523	  /* Bump the pointers.  */
1524	  avp++;
1525	  pointers += 4;
1526	  strings += l+1;
1527	}
1528
1529      /* A null to finish the list.  */
1530      wlat (pointers, 0);
1531      pointers += 4;
1532    }
1533
1534  return SIM_RC_OK;
1535}
1536