diff options
-rw-r--r-- | sim/sh/ChangeLog | 38 | ||||
-rw-r--r-- | sim/sh/gencode.c | 436 | ||||
-rw-r--r-- | sim/sh/interp.c | 348 |
3 files changed, 785 insertions, 37 deletions
diff --git a/sim/sh/ChangeLog b/sim/sh/ChangeLog index 10b4ae21710..381e1de4ec8 100644 --- a/sim/sh/ChangeLog +++ b/sim/sh/ChangeLog @@ -1,3 +1,41 @@ +2004-09-08 DJ Delorie <dj@redhat.com> + + Commited by Corinna Vinschen <vinschen@redhat.com> + * gencode.c (movua.l): Compensate for endianness. + +2004-09-08 Corinna Vinschen <vinschen@redhat.com> + + * interp.c (RAISE_EXCEPTION_IF_IN_DELAY_SLOT): New macro. + (in_delay_slot): New flag variable. + (Delay_Slot): Set in_delay_slot. + (sim_resume): Reset in_delay_slot after leaving code switch. + * gencode.c (op tab): Call RAISE_EXCEPTION_IF_IN_DELAY_SLOT for all + instructions not allowed in delay slots. + +2004-09-08 Michael Snyder <msnyder@redhat.com> + + Commited by Corinna Vinschen <vinschen@redhat.com> + Introduce SH2a support. + * interp.c: Change type of jump table to short. Add various macros. + (sim_load): Save the bfd machine code. + (sim_create_inferior): Ditto. + (union saved_state_type): Add tbr, ibnr and ibcr registers. + Move bfd_mach to end of struct. Add regstack pointer. + (init_dsp): Don't swap contents of sh_dsp_table any more. Instead + use it directly in its own switch statement. Allocate space for 512 + register banks. + (do_long_move_insn): New function. + (do_blog_insn): Ditto. + (trap): Use trap #13 and trap #14 to set ibnr and ibcr. + * gencode.c: Move movx/movy insns into separate switch statement. + (op tab): Add sh2a insns. Reject instructions that are disabled + on that chip. + (gensim_caselist): Generate default case here instead of in caller. + (gensim): Generate two separate switch statements. Call + gensim_caselist once for each (for movsxy_tab and for tab). + Add tokens for r15 and multiple regs. + (conflict_warn, warn_conflicts): Add for debugging. + 2004-08-18 J"orn Rennecke <joern.rennecke@superh.com> * gencode.c (tab): For shad snd shld, fix result for diff --git a/sim/sh/gencode.c b/sim/sh/gencode.c index 155138a2daf..f03ba4e341e 100644 --- a/sim/sh/gencode.c +++ b/sim/sh/gencode.c @@ -84,6 +84,7 @@ op tab[] = }, { "", "", "bf <bdisp8>", "10001011i8p1....", + "RAISE_EXCEPTION_IF_IN_DELAY_SLOT ();", "if (!T) {", " SET_NIP (PC + 4 + (SEXT (i) * 2));", " cycles += 2;", @@ -91,6 +92,7 @@ op tab[] = }, { "", "", "bf.s <bdisp8>", "10001111i8p1....", + "RAISE_EXCEPTION_IF_IN_DELAY_SLOT ();", "if (!T) {", " SET_NIP (PC + 4 + (SEXT (i) * 2));", " cycles += 2;", @@ -98,19 +100,35 @@ op tab[] = "}", }, + { "", "n", "bit32 #imm3,@(disp12,<REG_N>)", "0011nnnni8*11001", + "/* 32-bit logical bit-manipulation instructions. */", + "RAISE_EXCEPTION_IF_IN_DELAY_SLOT ();", + "int word2 = RIAT (nip);", + "i >>= 4; /* BOGUS: Using only three bits of 'i'. */", + "/* MSB of 'i' must be zero. */", + "if (i > 7)", + " RAISE_EXCEPTION (SIGILL);", + "MA (1);", + "do_blog_insn (1 << i, (word2 & 0xfff) + R[n], ", + " (word2 >> 12) & 0xf, memory, maskb);", + "SET_NIP (nip + 2); /* Consume 2 more bytes. */", + }, { "", "", "bra <bdisp12>", "1010i12.........", + "RAISE_EXCEPTION_IF_IN_DELAY_SLOT ();", "SET_NIP (PC + 4 + (SEXT12 (i) * 2));", "cycles += 2;", "Delay_Slot (PC + 2);", }, { "", "n", "braf <REG_N>", "0000nnnn00100011", + "RAISE_EXCEPTION_IF_IN_DELAY_SLOT ();", "SET_NIP (PC + 4 + R[n]);", "cycles += 2;", "Delay_Slot (PC + 2);", }, { "", "", "bsr <bdisp12>", "1011i12.........", + "RAISE_EXCEPTION_IF_IN_DELAY_SLOT ();", "PR = PH2T (PC + 4);", "SET_NIP (PC + 4 + (SEXT12 (i) * 2));", "cycles += 2;", @@ -118,6 +136,7 @@ op tab[] = }, { "", "n", "bsrf <REG_N>", "0000nnnn00000011", + "RAISE_EXCEPTION_IF_IN_DELAY_SLOT ();", "PR = PH2T (PC) + 4;", "SET_NIP (PC + 4 + R[n]);", "cycles += 2;", @@ -125,13 +144,187 @@ op tab[] = }, { "", "", "bt <bdisp8>", "10001001i8p1....", + "RAISE_EXCEPTION_IF_IN_DELAY_SLOT ();", "if (T) {", " SET_NIP (PC + 4 + (SEXT (i) * 2));", " cycles += 2;", "}", }, + + { "", "m", "bld/st #<imm>, <REG_M>", "10000111mmmmi4*1", + "/* MSB of 'i' is true for load, false for store. */", + "if (i <= 7)", + " if (T)", + " R[m] |= (1 << i);", + " else", + " R[m] &= ~(1 << i);", + "else", + " SET_SR_T ((R[m] & (1 << (i - 8))) != 0);", + }, + { "m", "m", "bset/clr #<imm>, <REG_M>", "10000110mmmmi4*1", + "/* MSB of 'i' is true for set, false for clear. */", + "if (i <= 7)", + " R[m] &= ~(1 << i);", + "else", + " R[m] |= (1 << (i - 8));", + }, + { "n", "n", "clips.b <REG_N>", "0100nnnn10010001", + "if (R[n] < -128 || R[n] > 127) {", + " L (n);", + " SET_SR_CS (1);", + " if (R[n] > 127)", + " R[n] = 127;", + " else if (R[n] < -128)", + " R[n] = -128;", + "}", + }, + { "n", "n", "clips.w <REG_N>", "0100nnnn10010101", + "if (R[n] < -32768 || R[n] > 32767) {", + " L (n);", + " SET_SR_CS (1);", + " if (R[n] > 32767)", + " R[n] = 32767;", + " else if (R[n] < -32768)", + " R[n] = -32768;", + "}", + }, + { "n", "n", "clipu.b <REG_N>", "0100nnnn10000001", + "if (R[n] < -256 || R[n] > 255) {", + " L (n);", + " SET_SR_CS (1);", + " R[n] = 255;", + "}", + }, + { "n", "n", "clipu.w <REG_N>", "0100nnnn10000101", + "if (R[n] < -65536 || R[n] > 65535) {", + " L (n);", + " SET_SR_CS (1);", + " R[n] = 65535;", + "}", + }, + { "n", "0n", "divs R0,<REG_N>", "0100nnnn10010100", + "RAISE_EXCEPTION_IF_IN_DELAY_SLOT ();", + "if (R0 == 0)", + " R[n] = 0x7fffffff;", + "else if (R0 == -1 && R[n] == 0x80000000)", + " R[n] = 0x7fffffff;", + "else R[n] /= R0;", + "L (n);", + }, + { "n", "0n", "divu R0,<REG_N>", "0100nnnn10000100", + "RAISE_EXCEPTION_IF_IN_DELAY_SLOT ();", + "if (R0 == 0)", + " R[n] = 0xffffffff;", + "else (unsigned int) R[n] = (unsigned int) R[n] / (unsigned int) R0;", + "L (n);", + }, + { "n", "0n", "mulr R0,<REG_N>", "0100nnnn10000000", + "R[n] = (R[n] * R0) & 0xffffffff;", + "L (n);", + }, + { "0", "n", "ldbank @<REG_N>,R0", "0100nnnn11100101", + "int regn = (R[n] >> 2) & 0x1f;", + "int bankn = (R[n] >> 7) & 0x1ff;", + "if (regn > 19)", + " regn = 19; /* FIXME what should happen? */", + "R0 = saved_state.asregs.regstack[bankn].regs[regn];", + "L (0);", + }, + { "", "0n", "stbank R0,@<REG_N>", "0100nnnn11100001", + "int regn = (R[n] >> 2) & 0x1f;", + "int bankn = (R[n] >> 7) & 0x1ff;", + "if (regn > 19)", + " regn = 19; /* FIXME what should happen? */", + "saved_state.asregs.regstack[bankn].regs[regn] = R0;", + }, + { "", "", "resbank", "0000000001011011", + "RAISE_EXCEPTION_IF_IN_DELAY_SLOT ();", + /* FIXME: cdef all */ + "int i;", + "if (BO) { /* Bank Overflow */", + /* FIXME: how do we know when to reset BO? */ + " for (i = 0; i <= 14; i++) {", + " R[i] = RLAT (R[15]);", + " MA (1);", + " R[15] += 4;", + " }", + " PR = RLAT (R[15]);", + " R[15] += 4;", + " MA (1);", + " GBR = RLAT (R[15]);", + " R[15] += 4;", + " MA (1);", + " MACH = RLAT (R[15]);", + " R[15] += 4;", + " MA (1);", + " MACL = RLAT (R[15]);", + " R[15] += 4;", + " MA (1);", + "}", + "else if (BANKN == 0) /* Bank Underflow */", + " RAISE_EXCEPTION (SIGILL);", /* FIXME: what exception? */ + "else {", + " SET_BANKN (BANKN - 1);", + " for (i = 0; i <= 14; i++)", + " R[i] = saved_state.asregs.regstack[BANKN].regs[i];", + " MACH = saved_state.asregs.regstack[BANKN].regs[15];", + " PR = saved_state.asregs.regstack[BANKN].regs[17];", + " GBR = saved_state.asregs.regstack[BANKN].regs[18];", + " MACL = saved_state.asregs.regstack[BANKN].regs[19];", + "}", + }, + { "f", "f-", "movml.l <REG_N>,@-R15", "0100nnnn11110001", + "/* Push Rn...R0 (if n==15, push pr and R14...R0). */", + "do {", + " MA (1);", + " R[15] -= 4;", + " if (n == 15)", + " WLAT (R[15], PR);", + " else", + " WLAT (R[15], R[n]);", + "} while (n-- > 0);", + }, + { "f", "f+", "movml.l @R15+,<REG_N>", "0100nnnn11110101", + "/* Pop R0...Rn (if n==15, pop R0...R14 and pr). */", + "int i = 0;\n", + "do {", + " MA (1);", + " if (i == 15)", + " PR = RLAT (R[15]);", + " else", + " R[i] = RLAT (R[15]);", + " R[15] += 4;", + "} while (i++ < n);", + }, + { "f", "f-", "movmu.l <REG_N>,@-R15", "0100nnnn11110000", + "/* Push pr, R14...Rn (if n==15, push pr). */", /* FIXME */ + "int i = 15;\n", + "do {", + " MA (1);", + " R[15] -= 4;", + " if (i == 15)", + " WLAT (R[15], PR);", + " else", + " WLAT (R[15], R[i]);", + "} while (i-- > n);", + }, + { "f", "f+", "movmu.l @R15+,<REG_N>", "0100nnnn11110100", + "/* Pop Rn...R14, pr (if n==15, pop pr). */", /* FIXME */ + "do {", + " MA (1);", + " if (n == 15)", + " PR = RLAT (R[15]);", + " else", + " R[n] = RLAT (R[15]);", + " R[15] += 4;", + "} while (n++ < 15);", + }, + { "", "", "nott", "0000000001101000", + "SET_SR_T (T == 0);", + }, { "", "", "bt.s <bdisp8>", "10001101i8p1....", + "RAISE_EXCEPTION_IF_IN_DELAY_SLOT ();", "if (T) {", " SET_NIP (PC + 4 + (SEXT (i) * 2));", " cycles += 2;", @@ -297,6 +490,8 @@ op tab[] = "else", "{", " double fsum = 0;", + " if (saved_state.asregs.bfd_mach == bfd_mach_sh2a)", + " RAISE_EXCEPTION (SIGILL);", " /* FIXME: check for nans and infinities. */", " fsum += FR (v1+0) * FR (v2+0);", " fsum += FR (v1+1) * FR (v2+1);", @@ -386,6 +581,18 @@ op tab[] = " SET_FI (n, RLAT (R[m]));", "}", }, + /* sh2a */ + { "", "n", "fmov.s @(disp12,<REG_N>), <FREG_M>", "0011nnnnmmmm0001", + "/* and fmov.s <FREG_N>, @(disp12,<FREG_M>)", + " and mov.bwl <REG_N>, @(disp12,<REG_M>)", + " and mov.bwl @(disp12,<REG_N>),<REG_M>", + " and movu.bw @(disp12,<REG_N>),<REG_M>. */", + "RAISE_EXCEPTION_IF_IN_DELAY_SLOT ();", + "int word2 = RIAT (nip);", + "SET_NIP (nip + 2); /* Consume 2 more bytes. */", + "MA (1);", + "do_long_move_insn (word2 & 0xf000, word2 & 0x0fff, m, n, &thislock);", + }, /* sh2e */ { "m", "m", "fmov.s @<REG_M>+,<FREG_N>", "1111nnnnmmmm1001", /* sh4 */ @@ -465,6 +672,8 @@ op tab[] = { "", "", "frchg", "1111101111111101", "if (FPSCR_PR)", " RAISE_EXCEPTION (SIGILL);", + "else if (saved_state.asregs.bfd_mach == bfd_mach_sh2a)", + " RAISE_EXCEPTION (SIGILL);", "else", " SET_FPSCR (GET_FPSCR () ^ FPSCR_MASK_FR);", }, @@ -473,6 +682,8 @@ op tab[] = { "", "", "fsca", "1111eeee11111101", "if (FPSCR_PR)", " RAISE_EXCEPTION (SIGILL);", + "else if (saved_state.asregs.bfd_mach == bfd_mach_sh2a)", + " RAISE_EXCEPTION (SIGILL);", "else", " {", " SET_FR (n, fsca_s (FPUL, &sin));", @@ -494,6 +705,8 @@ op tab[] = { "", "", "fsrra <FREG_N>", "1111nnnn01111101", "if (FPSCR_PR)", " RAISE_EXCEPTION (SIGILL);", + "else if (saved_state.asregs.bfd_mach == bfd_mach_sh2a)", + " RAISE_EXCEPTION (SIGILL);", "else", " SET_FR (n, fsrra_s (FR (n)));", }, @@ -525,6 +738,8 @@ op tab[] = " RAISE_EXCEPTION (SIGILL);", "else", "{", + " if (saved_state.asregs.bfd_mach == bfd_mach_sh2a)", + " RAISE_EXCEPTION (SIGILL);", " /* FIXME not implemented. */", " printf (\"ftrv xmtrx, FV%d\\n\", v1);", "}", @@ -542,12 +757,14 @@ op tab[] = }, { "", "n", "jmp @<REG_N>", "0100nnnn00101011", + "RAISE_EXCEPTION_IF_IN_DELAY_SLOT ();", "SET_NIP (PT2H (R[n]));", "cycles += 2;", "Delay_Slot (PC + 2);", }, { "", "n", "jsr @<REG_N>", "0100nnnn00001011", + "RAISE_EXCEPTION_IF_IN_DELAY_SLOT ();", "PR = PH2T (PC + 4);", "if (~doprofile)", " gotcall (PR, R[n]);", @@ -555,6 +772,20 @@ op tab[] = "cycles += 2;", "Delay_Slot (PC + 2);", }, + { "", "n", "jsr/n @<REG_N>", "0100nnnn01001011", + "RAISE_EXCEPTION_IF_IN_DELAY_SLOT ();", + "PR = PH2T (PC + 2);", + "if (~doprofile)", + " gotcall (PR, R[n]);", + "SET_NIP (PT2H (R[n]));", + }, + { "", "", "jsr/n @@(<disp>,TBR)", "10000011i8p4....", + "RAISE_EXCEPTION_IF_IN_DELAY_SLOT ();", + "PR = PH2T (PC + 2);", + "if (~doprofile)", + " gotcall (PR, i + TBR);", + "SET_NIP (PT2H (i + TBR));", + }, { "", "n", "ldc <REG_N>,<CREG_M>", "0100nnnnmmmm1110", "CREG (m) = R[n];", @@ -579,6 +810,12 @@ op tab[] = "else", " RAISE_EXCEPTION (SIGILL); /* user mode */", }, + { "", "n", "ldc <REG_N>,TBR", "0100nnnn01001010", + "if (SR_MD)", /* FIXME? */ + " TBR = R[n]; /* priv mode */", + "else", + " RAISE_EXCEPTION (SIGILL); /* user mode */", + }, { "n", "n", "ldc.l @<REG_N>+,<CREG_M>", "0100nnnnmmmm0111", "MA (1);", "CREG (m) = RLAT (R[n]);", @@ -673,6 +910,16 @@ op tab[] = { "n", "", "mov #<imm>,<REG_N>", "1110nnnni8*1....", "R[n] = SEXT (i);", }, + { "n", "", "movi20 #<imm20>,<REG_N>", "0000nnnni8*10000", + "RAISE_EXCEPTION_IF_IN_DELAY_SLOT ();", + "R[n] = ((i << 24) >> 12) | RIAT (nip);", + "SET_NIP (nip + 2); /* Consume 2 more bytes. */", + }, + { "n", "", "movi20s #<imm20>,<REG_N>", "0000nnnni8*10001", + "RAISE_EXCEPTION_IF_IN_DELAY_SLOT ();", + "R[n] = ((((i & 0xf0) << 24) >> 12) | RIAT (nip)) << 8;", + "SET_NIP (nip + 2); /* Consume 2 more bytes. */", + }, { "n", "m", "mov <REG_M>,<REG_N>", "0110nnnnmmmm0011", "R[n] = R[m];", }, @@ -698,6 +945,12 @@ op tab[] = "R[m] += 1;", "L (n);", }, + { "0n", "n", "mov.b @-<REG_N>,R0", "0100nnnn11001011", + "MA (1);", + "R[n] -= 1;", + "R0 = RSBAT (R[n]);", + "L (0);", + }, { "", "mn", "mov.b <REG_M>,@<REG_N>", "0010nnnnmmmm0000", "MA (1);", "WBAT (R[n], R[m]);", @@ -719,6 +972,11 @@ op tab[] = "R[n] -= 1;", "WBAT (R[n], R[m]);", }, + { "n", "n0", "mov.b R0,@<REG_N>+", "0100nnnn10001011", + "MA (1);", + "WBAT (R[n], R0);", + "R[n] += 1;", + }, { "n", "m", "mov.b @<REG_M>,<REG_N>", "0110nnnnmmmm0000", "MA (1);", "R[n] = RSBAT (R[m]);", @@ -751,6 +1009,12 @@ op tab[] = "R[m] += 4;", "L (n);", }, + { "0n", "n", "mov.l @-<REG_N>,R0", "0100nnnn11101011", + "MA (1);", + "R[n] -= 4;", + "R0 = RLAT (R[n]);", + "L (0);", + }, { "n", "m", "mov.l @<REG_M>,<REG_N>", "0110nnnnmmmm0010", "MA (1);", "R[n] = RLAT (R[m]);", @@ -773,6 +1037,11 @@ op tab[] = "R[n] -= 4;", "WLAT (R[n], R[m]);", }, + { "n", "n0", "mov.l R0,@<REG_N>+", "0100nnnn10101011", + "MA (1) ;", + "WLAT (R[n], R0);", + "R[n] += 4;", + }, { "", "nm", "mov.l <REG_M>,@<REG_N>", "0010nnnnmmmm0010", "MA (1);", "WLAT (R[n], R[m]);", @@ -804,6 +1073,12 @@ op tab[] = "R[m] += 2;", "L (n);", }, + { "0n", "n", "mov.w @-<REG_N>,R0", "0100nnnn11011011", + "MA (1);", + "R[n] -= 2;", + "R0 = RSWAT (R[n]);", + "L (0);", + }, { "n", "m", "mov.w @<REG_M>,<REG_N>", "0110nnnnmmmm0001", "MA (1);", "R[n] = RSWAT (R[m]);", @@ -826,6 +1101,11 @@ op tab[] = "R[n] -= 2;", "WWAT (R[n], R[m]);", }, + { "n", "0n", "mov.w R0,@<REG_N>+", "0100nnnn10011011", + "MA (1);", + "WWAT (R[n], R0);", + "R[n] += 2;", + }, { "", "nm", "mov.w <REG_M>,@<REG_N>", "0010nnnnmmmm0001", "MA (1);", "WWAT (R[n], R[m]);", @@ -863,19 +1143,23 @@ op tab[] = { "n", "", "movt <REG_N>", "0000nnnn00101001", "R[n] = T;", }, - + { "", "", "movrt <REG_N>", "0000nnnn00111001", + "R[n] = (T == 0);", + }, { "0", "n", "movua.l @<REG_N>,R0", "0100nnnn10101001", "int regn = R[n];", + "int e = target_little_endian ? 3 : 0;", "MA (1);", - "R[0] = (RBAT (regn) << 24) + (RBAT (regn + 1) << 16) + ", - " (RBAT (regn + 2) << 8) + RBAT (regn + 3);", + "R[0] = (RBAT (regn + (0^e)) << 24) + (RBAT (regn + (1^e)) << 16) + ", + " (RBAT (regn + (2^e)) << 8) + RBAT (regn + (3^e));", "L (0);", }, { "0n", "n", "movua.l @<REG_N>+,R0", "0100nnnn11101001", "int regn = R[n];", + "int e = target_little_endian ? 3 : 0;", "MA (1);", - "R[0] = (RBAT (regn) << 24) + (RBAT (regn + 1) << 16) + ", - " (RBAT (regn + 2) << 8) + RBAT (regn + 3);", + "R[0] = (RBAT (regn + (0^e)) << 24) + (RBAT (regn + (1^e)) << 16) + ", + " (RBAT (regn + (2^e)) << 8) + RBAT (regn + (3^e));", "R[n] += 4;", "L (0);", }, @@ -1002,6 +1286,7 @@ op tab[] = "R[15] += 4;", "Delay_Slot (PC + 2);", #else + "RAISE_EXCEPTION_IF_IN_DELAY_SLOT ();", "SET_SR (SSR);", "SET_NIP (PT2H (SPC));", "cycles += 2;", @@ -1010,10 +1295,21 @@ op tab[] = }, { "", "", "rts", "0000000000001011", + "RAISE_EXCEPTION_IF_IN_DELAY_SLOT ();", "SET_NIP (PT2H (PR));", "cycles += 2;", "Delay_Slot (PC + 2);", }, + { "", "", "rts/n", "0000000001101011", + "RAISE_EXCEPTION_IF_IN_DELAY_SLOT ();", + "SET_NIP (PT2H (PR));", + }, + { "0", "n", "rtv/n <REG_N>", "0000nnnn01111011", + "RAISE_EXCEPTION_IF_IN_DELAY_SLOT ();", + "R0 = R[n];", + "L (0);", + "SET_NIP (PT2H (PR));", + }, /* sh4a */ { "", "", "setdmx", "0000000010011000", @@ -1121,6 +1417,12 @@ op tab[] = "else", " RAISE_EXCEPTION (SIGILL); /* user mode */", }, + { "n", "", "stc TBR,<REG_N>", "0000nnnn01001010", + "if (SR_MD)", /* FIXME? */ + " R[n] = TBR; /* priv mode */", + "else", + " RAISE_EXCEPTION (SIGILL); /* user mode */", + }, { "n", "n", "stc.l <CREG_M>,@-<REG_N>", "0100nnnnmmmm0011", "MA (1);", "R[n] -= 4;", @@ -1191,6 +1493,7 @@ op tab[] = }, { "0", "", "trapa #<imm>", "11000011i8*1....", + "RAISE_EXCEPTION_IF_IN_DELAY_SLOT ();", "long imm = 0xff & i;", "if (i < 20 || i == 33 || i == 34 || i == 0xc3)", " nip += trap (i, &R0, PC, memory, maskl, maskw, endianw);", @@ -1515,8 +1818,9 @@ op movsxy_tab[] = "/* nop */", }, { "", "", "ppi", "1111100000000000", + "RAISE_EXCEPTION_IF_IN_DELAY_SLOT ();", "ppi_insn (RIAT (nip));", - "nip += 2;", + "SET_NIP (nip + 2);", "iword &= 0xf7ff; goto top;", }, #endif @@ -2267,6 +2571,58 @@ gengastab () static unsigned short table[1 << 16]; +static int warn_conflicts = 0; + +static void +conflict_warn (val, i) + int val; + int i; +{ + int ix, key; + int j = table[val]; + + fprintf (stderr, "Warning: opcode table conflict: 0x%04x (idx %d && %d)\n", + val, i, table[val]); + + for (ix = sizeof (tab) / sizeof (tab[0]); ix >= 0; ix--) + if (tab[ix].index == i || tab[ix].index == j) + { + key = ((tab[ix].code[0] - '0') << 3) + + ((tab[ix].code[1] - '0') << 2) + + ((tab[ix].code[2] - '0') << 1) + + ((tab[ix].code[3] - '0')); + + if (val >> 12 == key) + fprintf (stderr, " %s -- %s\n", tab[ix].code, tab[ix].name); + } + + for (ix = sizeof (movsxy_tab) / sizeof (movsxy_tab[0]); ix >= 0; ix--) + if (movsxy_tab[ix].index == i || movsxy_tab[ix].index == j) + { + key = ((movsxy_tab[ix].code[0] - '0') << 3) + + ((movsxy_tab[ix].code[1] - '0') << 2) + + ((movsxy_tab[ix].code[2] - '0') << 1) + + ((movsxy_tab[ix].code[3] - '0')); + + if (val >> 12 == key) + fprintf (stderr, " %s -- %s\n", + movsxy_tab[ix].code, movsxy_tab[ix].name); + } + + for (ix = sizeof (ppi_tab) / sizeof (ppi_tab[0]); ix >= 0; ix--) + if (ppi_tab[ix].index == i || ppi_tab[ix].index == j) + { + key = ((ppi_tab[ix].code[0] - '0') << 3) + + ((ppi_tab[ix].code[1] - '0') << 2) + + ((ppi_tab[ix].code[2] - '0') << 1) + + ((ppi_tab[ix].code[3] - '0')); + + if (val >> 12 == key) + fprintf (stderr, " %s -- %s\n", + ppi_tab[ix].code, ppi_tab[ix].name); + } +} + /* Take an opcode, expand all varying fields in it out and fill all the right entries in 'table' with the opcode index. */ @@ -2278,6 +2634,8 @@ expand_opcode (val, i, s) { if (*s == 0) { + if (warn_conflicts && table[val] != 0) + conflict_warn (val, i); table[val] = i; } else @@ -2599,6 +2957,12 @@ gensim_caselist (p) switch (s[1]) { + default: + fprintf (stderr, + "gensim_caselist: Unknown char '%c' in %s\n", + s[1], s); + exit (1); + break; case '4': printf ("f"); break; @@ -2607,7 +2971,6 @@ gensim_caselist (p) break; case '1': sextbit = 12; - printf ("fff"); break; } @@ -2615,6 +2978,14 @@ gensim_caselist (p) switch (s[3]) { + default: + fprintf (stderr, + "gensim_caselist: Unknown char '%c' in %s\n", + s[3], s); + exit (1); + break; + case '.': /* eg. "i12." */ + break; case '1': break; case '2': @@ -2646,6 +3017,25 @@ gensim_caselist (p) char *r; for (r = p->refs; *r; r++) { + if (*r == 'f') printf (" CREF (15);\n"); + if (*r == '-') + { + printf (" {\n"); + printf (" int i = n;\n"); + printf (" do {\n"); + printf (" CREF (i);\n"); + printf (" } while (i-- > 0);\n"); + printf (" }\n"); + } + if (*r == '+') + { + printf (" {\n"); + printf (" int i = n;\n"); + printf (" do {\n"); + printf (" CREF (i);\n"); + printf (" } while (i++ < 14);\n"); + printf (" }\n"); + } if (*r == '0') printf (" CREF (0);\n"); if (*r == '8') printf (" CREF (8);\n"); if (*r == '9') printf (" CREF (9);\n"); @@ -2669,9 +3059,28 @@ gensim_caselist (p) char *r; for (r = p->defs; *r; r++) { - if (*r == '0') printf(" CDEF (0);\n"); - if (*r == 'n') printf(" CDEF (n);\n"); - if (*r == 'm') printf(" CDEF (m);\n"); + if (*r == 'f') printf (" CDEF (15);\n"); + if (*r == '-') + { + printf (" {\n"); + printf (" int i = n;\n"); + printf (" do {\n"); + printf (" CDEF (i);\n"); + printf (" } while (i-- > 0);\n"); + printf (" }\n"); + } + if (*r == '+') + { + printf (" {\n"); + printf (" int i = n;\n"); + printf (" do {\n"); + printf (" CDEF (i);\n"); + printf (" } while (i++ < 14);\n"); + printf (" }\n"); + } + if (*r == '0') printf (" CDEF (0);\n"); + if (*r == 'n') printf (" CDEF (n);\n"); + if (*r == 'm') printf (" CDEF (m);\n"); } } @@ -2757,6 +3166,9 @@ expand_ppi_code (val, i, s) break; case 'g': case 'z': + if (warn_conflicts && table[val] != 0) + conflict_warn (val, i); + /* The last four bits are disregarded for the switch table. */ table[val] = i; return; @@ -2992,6 +3404,10 @@ main (ac, av) /* Now generate the requested data. */ if (ac > 1) { + if (ac > 2 && strcmp (av[2], "-w") == 0) + { + warn_conflicts = 1; + } if (strcmp (av[1], "-t") == 0) { gengastab (); diff --git a/sim/sh/interp.c b/sim/sh/interp.c index b7c77799447..5d4a4f558ae 100644 --- a/sim/sh/interp.c +++ b/sim/sh/interp.c @@ -65,6 +65,11 @@ int sim_write (SIM_DESC sd, SIM_ADDR addr, unsigned char *buffer, int size); for a quit. */ #define POLL_QUIT_INTERVAL 0x60000 +typedef struct +{ + int regs[20]; +} regstacktype; + typedef union { @@ -123,6 +128,9 @@ typedef union int dbr; /* debug base register */ int sgr; /* saved gr15 */ int ldst; /* load/store flag (boolean) */ + int tbr; + int ibcr; /* sh2a bank control register */ + int ibnr; /* sh2a bank number register */ } named; int i[16]; } cregs; @@ -152,6 +160,8 @@ typedef union unsigned char *ymem; unsigned char *xmem_offset; unsigned char *ymem_offset; + unsigned long bfd_mach; + regstacktype *regstack; } asregs; int asints[40]; @@ -175,6 +185,7 @@ static int maskl = 0; static SIM_OPEN_KIND sim_kind; static char *myname; +static int tracing = 0; /* Short hand definitions of the registers */ @@ -191,6 +202,11 @@ static char *myname; #define GBR saved_state.asregs.cregs.named.gbr #define VBR saved_state.asregs.cregs.named.vbr #define DBR saved_state.asregs.cregs.named.dbr +#define TBR saved_state.asregs.cregs.named.tbr +#define IBCR saved_state.asregs.cregs.named.ibcr +#define IBNR saved_state.asregs.cregs.named.ibnr +#define BANKN (saved_state.asregs.cregs.named.ibnr & 0x1ff) +#define ME ((saved_state.asregs.cregs.named.ibnr >> 14) & 0x3) #define SSR saved_state.asregs.cregs.named.ssr #define SPC saved_state.asregs.cregs.named.spc #define SGR saved_state.asregs.cregs.named.sgr @@ -213,6 +229,8 @@ static char *myname; /* Manipulate SR */ +#define SR_MASK_BO (1 << 14) +#define SR_MASK_CS (1 << 13) #define SR_MASK_DMY (1 << 11) #define SR_MASK_DMX (1 << 10) #define SR_MASK_M (1 << 9) @@ -227,6 +245,8 @@ static char *myname; #define SR_MASK_RC 0x0fff0000 #define SR_RC_INCREMENT -0x00010000 +#define BO ((saved_state.asregs.cregs.named.sr & SR_MASK_BO) != 0) +#define CS ((saved_state.asregs.cregs.named.sr & SR_MASK_CS) != 0) #define M ((saved_state.asregs.cregs.named.sr & SR_MASK_M) != 0) #define Q ((saved_state.asregs.cregs.named.sr & SR_MASK_Q) != 0) #define S ((saved_state.asregs.cregs.named.sr & SR_MASK_S) != 0) @@ -249,6 +269,16 @@ do { \ saved_state.asregs.cregs.named.sr &= ~(BIT); \ } while (0) +#define SET_SR_BO(EXP) SET_SR_BIT ((EXP), SR_MASK_BO) +#define SET_SR_CS(EXP) SET_SR_BIT ((EXP), SR_MASK_CS) +#define SET_BANKN(EXP) \ +do { \ + IBNR = (IBNR & 0xfe00) | (EXP & 0x1f); \ +} while (0) +#define SET_ME(EXP) \ +do { \ + IBNR = (IBNR & 0x3fff) | ((EXP & 0x3) << 14); \ +} while (0) #define SET_SR_M(EXP) SET_SR_BIT ((EXP), SR_MASK_M) #define SET_SR_Q(EXP) SET_SR_BIT ((EXP), SR_MASK_Q) #define SET_SR_S(EXP) SET_SR_BIT ((EXP), SR_MASK_S) @@ -323,6 +353,9 @@ fail () #define RAISE_EXCEPTION(x) \ (saved_state.asregs.exception = x, saved_state.asregs.insn_end = 0) +#define RAISE_EXCEPTION_IF_IN_DELAY_SLOT() \ + if (in_delay_slot) RAISE_EXCEPTION (SIGILL) + /* This function exists mainly for the purpose of setting a breakpoint to catch simulated bus errors when running the simulator under GDB. */ @@ -780,7 +813,8 @@ process_rbat_addr (addr) #define SET_NIP(x) nip = (x); CHECK_INSN_PTR (nip); -#define Delay_Slot(TEMPPC) iword = RIAT (TEMPPC); goto top; +static int in_delay_slot = 0; +#define Delay_Slot(TEMPPC) iword = RIAT (TEMPPC); in_delay_slot = 1; goto top; #define CHECK_INSN_PTR(p) \ do { \ @@ -1181,6 +1215,12 @@ trap (i, regs, insn_ptr, memory, maskl, maskw, endianw) } break; + case 13: /* Set IBNR */ + IBNR = regs[0] & 0xffff; + break; + case 14: /* Set IBCR */ + IBCR = regs[0] & 0xffff; + break; case 0xc3: case 255: raise_exception (SIGTRAP); @@ -1419,32 +1459,140 @@ macl (regs, memory, n, m) MACH = mach; } - -/* GET_LOOP_BOUNDS {EXTENDED} - These two functions compute the actual starting and ending point - of the repeat loop, based on the RS and RE registers (repeat start, - repeat stop). The extended version is called for LDRC, and the - regular version is called for SETRC. The difference is that for - LDRC, the loop start and end instructions are literally the ones - pointed to by RS and RE -- for SETRC, they're not (see docs). */ - -static struct loop_bounds -get_loop_bounds_ext (rs, re, memory, mem_end, maskw, endianw) - int rs, re; - unsigned char *memory, *mem_end; - int maskw, endianw; +enum { + B_BCLR = 0, + B_BSET = 1, + B_BST = 2, + B_BLD = 3, + B_BAND = 4, + B_BOR = 5, + B_BXOR = 6, + B_BLDNOT = 11, + B_BANDNOT = 12, + B_BORNOT = 13, + + MOVB_RM = 0x0000, + MOVW_RM = 0x1000, + MOVL_RM = 0x2000, + FMOV_RM = 0x3000, + MOVB_MR = 0x4000, + MOVW_MR = 0x5000, + MOVL_MR = 0x6000, + FMOV_MR = 0x7000, + MOVU_BMR = 0x8000, + MOVU_WMR = 0x9000, +}; + +/* Do extended displacement move instructions. */ +void +do_long_move_insn (int op, int disp12, int m, int n, int *thatlock) { - struct loop_bounds loop; - - /* FIXME: should I verify RS < RE? */ - loop.start = PT2H (RS); /* FIXME not using the params? */ - loop.end = PT2H (RE & ~1); /* Ignore bit 0 of RE. */ - SKIP_INSN (loop.end); - if (loop.end >= mem_end) - loop.end = PT2H (0); - return loop; + int memstalls = 0; + int thislock = *thatlock; + int endianw = global_endianw; + int *R = &(saved_state.asregs.regs[0]); + unsigned char *memory = saved_state.asregs.memory; + int maskb = ~((saved_state.asregs.msize - 1) & ~0); + unsigned char *insn_ptr = PT2H (saved_state.asregs.pc); + + switch (op) { + case MOVB_RM: /* signed */ + WBAT (disp12 * 1 + R[n], R[m]); + break; + case MOVW_RM: + WWAT (disp12 * 2 + R[n], R[m]); + break; + case MOVL_RM: + WLAT (disp12 * 4 + R[n], R[m]); + break; + case FMOV_RM: /* floating point */ + if (FPSCR_SZ) + { + MA (1); + WDAT (R[n] + 8 * disp12, m); + } + else + WLAT (R[n] + 4 * disp12, FI (m)); + break; + case MOVB_MR: + R[n] = RSBAT (disp12 * 1 + R[m]); + L (n); + break; + case MOVW_MR: + R[n] = RSWAT (disp12 * 2 + R[m]); + L (n); + break; + case MOVL_MR: + R[n] = RLAT (disp12 * 4 + R[m]); + L (n); + break; + case FMOV_MR: + if (FPSCR_SZ) { + MA (1); + RDAT (R[m] + 8 * disp12, n); + } + else + SET_FI (n, RLAT (R[m] + 4 * disp12)); + break; + case MOVU_BMR: /* unsigned */ + R[n] = RBAT (disp12 * 1 + R[m]); + L (n); + break; + case MOVU_WMR: + R[n] = RWAT (disp12 * 2 + R[m]); + L (n); + break; + default: + RAISE_EXCEPTION (SIGINT); + exit (1); + } + saved_state.asregs.memstalls += memstalls; + *thatlock = thislock; } +/* Do binary logical bit-manipulation insns. */ +void +do_blog_insn (int imm, int addr, int binop, + unsigned char *memory, int maskb) +{ + int oldval = RBAT (addr); + + switch (binop) { + case B_BCLR: /* bclr.b */ + WBAT (addr, oldval & ~imm); + break; + case B_BSET: /* bset.b */ + WBAT (addr, oldval | imm); + break; + case B_BST: /* bst.b */ + if (T) + WBAT (addr, oldval | imm); + else + WBAT (addr, oldval & ~imm); + break; + case B_BLD: /* bld.b */ + SET_SR_T ((oldval & imm) != 0); + break; + case B_BAND: /* band.b */ + SET_SR_T (T && ((oldval & imm) != 0)); + break; + case B_BOR: /* bor.b */ + SET_SR_T (T || ((oldval & imm) != 0)); + break; + case B_BXOR: /* bxor.b */ + SET_SR_T (T ^ ((oldval & imm) != 0)); + break; + case B_BLDNOT: /* bldnot.b */ + SET_SR_T ((oldval & imm) == 0); + break; + case B_BANDNOT: /* bandnot.b */ + SET_SR_T (T && ((oldval & imm) == 0)); + break; + case B_BORNOT: /* bornot.b */ + SET_SR_T (T || ((oldval & imm) == 0)); + break; + } +} float fsca_s (int in, double (*f) (double)) { @@ -1494,6 +1642,32 @@ fsrra_s (float in) return upper - result >= result - lower ? upper : lower; } + +/* GET_LOOP_BOUNDS {EXTENDED} + These two functions compute the actual starting and ending point + of the repeat loop, based on the RS and RE registers (repeat start, + repeat stop). The extended version is called for LDRC, and the + regular version is called for SETRC. The difference is that for + LDRC, the loop start and end instructions are literally the ones + pointed to by RS and RE -- for SETRC, they're not (see docs). */ + +static struct loop_bounds +get_loop_bounds_ext (rs, re, memory, mem_end, maskw, endianw) + int rs, re; + unsigned char *memory, *mem_end; + int maskw, endianw; +{ + struct loop_bounds loop; + + /* FIXME: should I verify RS < RE? */ + loop.start = PT2H (RS); /* FIXME not using the params? */ + loop.end = PT2H (RE & ~1); /* Ignore bit 0 of RE. */ + SKIP_INSN (loop.end); + if (loop.end >= mem_end) + loop.end = PT2H (0); + return loop; +} + static struct loop_bounds get_loop_bounds (rs, re, memory, mem_end, maskw, endianw) int rs, re; @@ -1607,8 +1781,10 @@ init_dsp (abfd) saved_state.asregs.xyram_select = new_select; free (saved_state.asregs.xmem); free (saved_state.asregs.ymem); - saved_state.asregs.xmem = (unsigned char *) calloc (1, ram_area_size); - saved_state.asregs.ymem = (unsigned char *) calloc (1, ram_area_size); + saved_state.asregs.xmem = + (unsigned char *) calloc (1, ram_area_size); + saved_state.asregs.ymem = + (unsigned char *) calloc (1, ram_area_size); /* Disable use of X / Y mmeory if not allocated. */ if (! saved_state.asregs.xmem || ! saved_state.asregs.ymem) @@ -1642,6 +1818,10 @@ init_dsp (abfd) saved_state.asregs.yram_start = 1; } + if (saved_state.asregs.regstack == NULL) + saved_state.asregs.regstack = + calloc (512, sizeof *saved_state.asregs.regstack); + if (target_dsp != was_dsp) { int i, tmp; @@ -1741,7 +1921,11 @@ sim_resume (sd, step, siggnal) register int memstalls = 0; register int insts = 0; register int prevlock; +#if 1 + int thislock; +#else register int thislock; +#endif register unsigned int doprofile; register int pollcount = 0; /* endianw is used for every insn fetch, hence it makes sense to cache it. @@ -1820,10 +2004,13 @@ sim_resume (sd, step, siggnal) insts++; #endif top: + if (tracing) + fprintf (stderr, "PC: %08x, insn: %04x\n", PH2T (insn_ptr), iword); #include "code.c" + in_delay_slot = 0; insn_ptr = nip; if (--pollcount < 0) @@ -1940,6 +2127,15 @@ sim_read (sd, addr, buffer, size) return size; } +static int gdb_bank_number; +enum { + REGBANK_MACH = 15, + REGBANK_IVN = 16, + REGBANK_PR = 17, + REGBANK_GBR = 18, + REGBANK_MACL = 19 +}; + int sim_store_register (sd, rn, memory, length) SIM_DESC sd; @@ -2050,6 +2246,12 @@ sim_store_register (sd, rn, memory, length) case SIM_SH_R2_BANK0_REGNUM: case SIM_SH_R3_BANK0_REGNUM: case SIM_SH_R4_BANK0_REGNUM: case SIM_SH_R5_BANK0_REGNUM: case SIM_SH_R6_BANK0_REGNUM: case SIM_SH_R7_BANK0_REGNUM: + if (saved_state.asregs.bfd_mach == bfd_mach_sh2a) + { + rn -= SIM_SH_R0_BANK0_REGNUM; + saved_state.asregs.regstack[gdb_bank_number].regs[rn] = val; + } + else if (SR_MD && SR_RB) Rn_BANK (rn - SIM_SH_R0_BANK0_REGNUM) = val; else @@ -2059,6 +2261,12 @@ sim_store_register (sd, rn, memory, length) case SIM_SH_R2_BANK1_REGNUM: case SIM_SH_R3_BANK1_REGNUM: case SIM_SH_R4_BANK1_REGNUM: case SIM_SH_R5_BANK1_REGNUM: case SIM_SH_R6_BANK1_REGNUM: case SIM_SH_R7_BANK1_REGNUM: + if (saved_state.asregs.bfd_mach == bfd_mach_sh2a) + { + rn -= SIM_SH_R0_BANK1_REGNUM; + saved_state.asregs.regstack[gdb_bank_number].regs[rn + 8] = val; + } + else if (SR_MD && SR_RB) saved_state.asregs.regs[rn - SIM_SH_R0_BANK1_REGNUM] = val; else @@ -2070,6 +2278,35 @@ sim_store_register (sd, rn, memory, length) case SIM_SH_R6_BANK_REGNUM: case SIM_SH_R7_BANK_REGNUM: SET_Rn_BANK (rn - SIM_SH_R0_BANK_REGNUM, val); break; + case SIM_SH_TBR_REGNUM: + TBR = val; + break; + case SIM_SH_IBNR_REGNUM: + IBNR = val; + break; + case SIM_SH_IBCR_REGNUM: + IBCR = val; + break; + case SIM_SH_BANK_REGNUM: + /* This is a pseudo-register maintained just for gdb. + It tells us what register bank gdb would like to read/write. */ + gdb_bank_number = val; + break; + case SIM_SH_BANK_MACL_REGNUM: + saved_state.asregs.regstack[gdb_bank_number].regs[REGBANK_MACL] = val; + break; + case SIM_SH_BANK_GBR_REGNUM: + saved_state.asregs.regstack[gdb_bank_number].regs[REGBANK_GBR] = val; + break; + case SIM_SH_BANK_PR_REGNUM: + saved_state.asregs.regstack[gdb_bank_number].regs[REGBANK_PR] = val; + break; + case SIM_SH_BANK_IVN_REGNUM: + saved_state.asregs.regstack[gdb_bank_number].regs[REGBANK_IVN] = val; + break; + case SIM_SH_BANK_MACH_REGNUM: + saved_state.asregs.regstack[gdb_bank_number].regs[REGBANK_MACH] = val; + break; default: return 0; } @@ -2185,6 +2422,12 @@ sim_fetch_register (sd, rn, memory, length) case SIM_SH_R2_BANK0_REGNUM: case SIM_SH_R3_BANK0_REGNUM: case SIM_SH_R4_BANK0_REGNUM: case SIM_SH_R5_BANK0_REGNUM: case SIM_SH_R6_BANK0_REGNUM: case SIM_SH_R7_BANK0_REGNUM: + if (saved_state.asregs.bfd_mach == bfd_mach_sh2a) + { + rn -= SIM_SH_R0_BANK0_REGNUM; + val = saved_state.asregs.regstack[gdb_bank_number].regs[rn]; + } + else val = (SR_MD && SR_RB ? Rn_BANK (rn - SIM_SH_R0_BANK0_REGNUM) : saved_state.asregs.regs[rn - SIM_SH_R0_BANK0_REGNUM]); @@ -2193,6 +2436,12 @@ sim_fetch_register (sd, rn, memory, length) case SIM_SH_R2_BANK1_REGNUM: case SIM_SH_R3_BANK1_REGNUM: case SIM_SH_R4_BANK1_REGNUM: case SIM_SH_R5_BANK1_REGNUM: case SIM_SH_R6_BANK1_REGNUM: case SIM_SH_R7_BANK1_REGNUM: + if (saved_state.asregs.bfd_mach == bfd_mach_sh2a) + { + rn -= SIM_SH_R0_BANK1_REGNUM; + val = saved_state.asregs.regstack[gdb_bank_number].regs[rn + 8]; + } + else val = (! SR_MD || ! SR_RB ? Rn_BANK (rn - SIM_SH_R0_BANK1_REGNUM) : saved_state.asregs.regs[rn - SIM_SH_R0_BANK1_REGNUM]); @@ -2203,6 +2452,35 @@ sim_fetch_register (sd, rn, memory, length) case SIM_SH_R6_BANK_REGNUM: case SIM_SH_R7_BANK_REGNUM: val = Rn_BANK (rn - SIM_SH_R0_BANK_REGNUM); break; + case SIM_SH_TBR_REGNUM: + val = TBR; + break; + case SIM_SH_IBNR_REGNUM: + val = IBNR; + break; + case SIM_SH_IBCR_REGNUM: + val = IBCR; + break; + case SIM_SH_BANK_REGNUM: + /* This is a pseudo-register maintained just for gdb. + It tells us what register bank gdb would like to read/write. */ + val = gdb_bank_number; + break; + case SIM_SH_BANK_MACL_REGNUM: + val = saved_state.asregs.regstack[gdb_bank_number].regs[REGBANK_MACL]; + break; + case SIM_SH_BANK_GBR_REGNUM: + val = saved_state.asregs.regstack[gdb_bank_number].regs[REGBANK_GBR]; + break; + case SIM_SH_BANK_PR_REGNUM: + val = saved_state.asregs.regstack[gdb_bank_number].regs[REGBANK_PR]; + break; + case SIM_SH_BANK_IVN_REGNUM: + val = saved_state.asregs.regstack[gdb_bank_number].regs[REGBANK_IVN]; + break; + case SIM_SH_BANK_MACH_REGNUM: + val = saved_state.asregs.regstack[gdb_bank_number].regs[REGBANK_MACH]; + break; default: return 0; } @@ -2214,7 +2492,10 @@ int sim_trace (sd) SIM_DESC sd; { - return 0; + tracing = 1; + sim_resume (sd, 0, 0); + tracing = 0; + return 1; } void @@ -2381,6 +2662,15 @@ sim_load (sd, prog, abfd, from_tty) prog_bfd = sim_load_file (sd, myname, callback, prog, abfd, sim_kind == SIM_OPEN_DEBUG, 0, sim_write); + + /* Set the bfd machine type. */ + if (prog_bfd) + saved_state.asregs.bfd_mach = bfd_get_mach (prog_bfd); + else if (abfd) + saved_state.asregs.bfd_mach = bfd_get_mach (abfd); + else + saved_state.asregs.bfd_mach = 0; + if (prog_bfd == NULL) return SIM_RC_FAIL; if (abfd == NULL) @@ -2403,6 +2693,10 @@ sim_create_inferior (sd, prog_bfd, argv, env) if (prog_bfd != NULL) saved_state.asregs.pc = bfd_get_start_address (prog_bfd); + /* Set the bfd machine type. */ + if (prog_bfd != NULL) + saved_state.asregs.bfd_mach = bfd_get_mach (prog_bfd); + /* Record the program's arguments. */ prog_argv = argv; |