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