+ c = rd & 1;
+ rd = ((unsigned char) rd) >> 1;
+ if (c)
+ rd |= 0x80;
+ }
+
+ v = 0;
+ goto shift8;
+
+ case O (O_ROTL, SW):
+ case O (O_ROTR, SW):
+ if (fetch2 (sd, &code->dst, &rd))
+ goto end;
+
+ if (code->src.type == X (OP_IMM, SW))
+ fetch (sd, &code->src, &ea);
+ else
+ ea = 1;
+
+ while (ea--)
+ if (code->opcode == O (O_ROTL, SW))
+ {
+ c = rd & 0x8000;
+ rd <<= 1;
+ if (c)
+ rd |= 1;
+ }
+ else
+ {
+ c = rd & 1;
+ rd = ((unsigned short) rd) >> 1;
+ if (c)
+ rd |= 0x8000;
+ }
+
+ v = 0;
+ goto shift16;
+
+ case O (O_ROTL, SL):
+ case O (O_ROTR, SL):
+ if (fetch2 (sd, &code->dst, &rd))
+ goto end;
+
+ if (code->src.type == X (OP_IMM, SL))
+ fetch (sd, &code->src, &ea);
+ else
+ ea = 1;
+
+ while (ea--)
+ if (code->opcode == O (O_ROTL, SL))
+ {
+ c = rd & 0x80000000;
+ rd <<= 1;
+ if (c)
+ rd |= 1;
+ }
+ else
+ {
+ c = rd & 1;
+ rd = ((unsigned int) rd) >> 1;
+ if (c)
+ rd |= 0x80000000;
+ }
+
+ v = 0;
+ goto shift32;
+
+ case O (O_ROTXL, SB):
+ case O (O_ROTXR, SB):
+ if (fetch2 (sd, &code->dst, &rd))
+ goto end;
+
+ if (code->src.type == X (OP_IMM, SB))
+ fetch (sd, &code->src, &ea);
+ else
+ ea = 1;
+
+ while (ea--)
+ if (code->opcode == O (O_ROTXL, SB))
+ {
+ res = rd & 0x80;
+ rd <<= 1;
+ if (C)
+ rd |= 1;
+ c = res;
+ }
+ else
+ {
+ res = rd & 1;
+ rd = ((unsigned char) rd) >> 1;
+ if (C)
+ rd |= 0x80;
+ c = res;
+ }
+
+ v = 0;
+ goto shift8;
+
+ case O (O_ROTXL, SW):
+ case O (O_ROTXR, SW):
+ if (fetch2 (sd, &code->dst, &rd))
+ goto end;
+
+ if (code->src.type == X (OP_IMM, SW))
+ fetch (sd, &code->src, &ea);
+ else
+ ea = 1;
+
+ while (ea--)
+ if (code->opcode == O (O_ROTXL, SW))
+ {
+ res = rd & 0x8000;
+ rd <<= 1;
+ if (C)
+ rd |= 1;
+ c = res;
+ }
+ else
+ {
+ res = rd & 1;
+ rd = ((unsigned short) rd) >> 1;
+ if (C)
+ rd |= 0x8000;
+ c = res;
+ }
+
+ v = 0;
+ goto shift16;
+
+ case O (O_ROTXL, SL):
+ case O (O_ROTXR, SL):
+ if (fetch2 (sd, &code->dst, &rd))
+ goto end;
+
+ if (code->src.type == X (OP_IMM, SL))
+ fetch (sd, &code->src, &ea);
+ else
+ ea = 1;
+
+ while (ea--)
+ if (code->opcode == O (O_ROTXL, SL))
+ {
+ res = rd & 0x80000000;
+ rd <<= 1;
+ if (C)
+ rd |= 1;
+ c = res;
+ }
+ else
+ {
+ res = rd & 1;
+ rd = ((unsigned int) rd) >> 1;
+ if (C)
+ rd |= 0x80000000;
+ c = res;
+ }
+
+ v = 0;
+ goto shift32;
+
+ case O (O_JMP, SN):
+ case O (O_JMP, SL):
+ case O (O_JMP, SB): /* jmp */
+ case O (O_JMP, SW):
+ fetch (sd, &code->src, &pc);
+ goto end;
+
+ case O (O_JSR, SN):
+ case O (O_JSR, SL):
+ case O (O_JSR, SB): /* jsr, jump to subroutine */
+ case O (O_JSR, SW):
+ if (fetch (sd, &code->src, &pc))
+ goto end;
+ call:
+ tmp = h8_get_reg (sd, SP_REGNUM);
+
+ if (h8300hmode && !h8300_normal_mode)
+ {
+ tmp -= 4;
+ SET_MEMORY_L (tmp, code->next_pc);
+ }
+ else
+ {
+ tmp -= 2;
+ SET_MEMORY_W (tmp, code->next_pc);
+ }
+ h8_set_reg (sd, SP_REGNUM, tmp);
+
+ goto end;
+
+ case O (O_BSR, SW):
+ case O (O_BSR, SL):
+ case O (O_BSR, SB): /* bsr, branch to subroutine */
+ if (fetch (sd, &code->src, &res))
+ goto end;
+ pc = code->next_pc + res;
+ goto call;
+
+ case O (O_RTE, SN): /* rte, return from exception */
+ rte:
+ /* Pops exr and ccr before pc -- otherwise identical to rts. */
+ tmp = h8_get_reg (sd, SP_REGNUM);
+
+ if (h8300smode) /* pop exr */
+ {
+ h8_set_exr (sd, GET_MEMORY_L (tmp));
+ tmp += 4;
+ }
+ if (h8300hmode && !h8300_normal_mode)
+ {
+ h8_set_ccr (sd, GET_MEMORY_L (tmp));
+ tmp += 4;
+ pc = GET_MEMORY_L (tmp);
+ tmp += 4;
+ }
+ else
+ {
+ h8_set_ccr (sd, GET_MEMORY_W (tmp));
+ tmp += 2;
+ pc = GET_MEMORY_W (tmp);
+ tmp += 2;
+ }
+
+ GETSR (sd);
+ h8_set_reg (sd, SP_REGNUM, tmp);
+ goto end;
+
+ case O (O_RTS, SN): /* rts, return from subroutine */
+ rts:
+ tmp = h8_get_reg (sd, SP_REGNUM);
+
+ if (h8300hmode && !h8300_normal_mode)
+ {
+ pc = GET_MEMORY_L (tmp);
+ tmp += 4;
+ }
+ else
+ {
+ pc = GET_MEMORY_W (tmp);
+ tmp += 2;
+ }
+
+ h8_set_reg (sd, SP_REGNUM, tmp);
+ goto end;
+
+ case O (O_ILL, SB): /* illegal */
+ sim_engine_halt (sd, cpu, NULL, pc, sim_stopped, SIM_SIGILL);
+ goto end;
+
+ case O (O_SLEEP, SN): /* sleep */
+ /* Check for magic numbers in r1 and r2. */
+ if ((h8_get_reg (sd, R1_REGNUM) & 0xffff) == LIBC_EXIT_MAGIC1 &&
+ (h8_get_reg (sd, R2_REGNUM) & 0xffff) == LIBC_EXIT_MAGIC2 &&
+ SIM_WIFEXITED (h8_get_reg (sd, 0)))
+ {
+ /* This trap comes from _exit, not from gdb. */
+ sim_engine_halt (sd, cpu, NULL, pc, sim_exited,
+ SIM_WEXITSTATUS (h8_get_reg (sd, 0)));
+ }
+#if 0
+ /* Unfortunately this won't really work, because
+ when we take a breakpoint trap, R0 has a "random",
+ user-defined value. Don't see any immediate solution. */
+ else if (SIM_WIFSTOPPED (h8_get_reg (sd, 0)))
+ {
+ /* Pass the stop signal up to gdb. */
+ sim_engine_halt (sd, cpu, NULL, pc, sim_stopped,
+ SIM_WSTOPSIG (h8_get_reg (sd, 0)));
+ }
+#endif
+ else
+ {
+ /* Treat it as a sigtrap. */
+ sim_engine_halt (sd, cpu, NULL, pc, sim_stopped, SIM_SIGTRAP);
+ }
+ goto end;
+
+ case O (O_TRAPA, SB): /* trapa */
+ if (fetch (sd, &code->src, &res))
+ goto end; /* res is vector number. */
+
+ tmp = h8_get_reg (sd, SP_REGNUM);
+ if(h8300_normal_mode)
+ {
+ tmp -= 2;
+ SET_MEMORY_W (tmp, code->next_pc);
+ tmp -= 2;
+ SET_MEMORY_W (tmp, h8_get_ccr (sd));
+ }
+ else
+ {
+ tmp -= 4;
+ SET_MEMORY_L (tmp, code->next_pc);
+ tmp -= 4;
+ SET_MEMORY_L (tmp, h8_get_ccr (sd));
+ }
+ intMaskBit = 1;
+ BUILDSR (sd);
+
+ if (h8300smode)
+ {
+ tmp -= 4;
+ SET_MEMORY_L (tmp, h8_get_exr (sd));
+ }
+
+ h8_set_reg (sd, SP_REGNUM, tmp);
+
+ if(h8300_normal_mode)
+ pc = GET_MEMORY_L (0x10 + res * 2); /* Vector addresses are 0x10,0x12,0x14 and 0x16 */
+ else
+ pc = GET_MEMORY_L (0x20 + res * 4);
+ goto end;
+
+ case O (O_BPT, SN):
+ sim_engine_halt (sd, cpu, NULL, pc, sim_stopped, SIM_SIGTRAP);
+ goto end;
+
+ case O (O_BSETEQ, SB):
+ if (Z)
+ goto bset;
+ goto next;
+
+ case O (O_BSETNE, SB):
+ if (!Z)
+ goto bset;
+ goto next;
+
+ case O (O_BCLREQ, SB):
+ if (Z)
+ goto bclr;
+ goto next;
+
+ case O (O_BCLRNE, SB):
+ if (!Z)
+ goto bclr;
+ goto next;
+
+ OBITOP (O_BNOT, 1, 1, ea ^= m); /* bnot */
+ OBITOP (O_BTST, 1, 0, nz = ea & m); /* btst */
+ bset:
+ OBITOP (O_BSET, 1, 1, ea |= m); /* bset */
+ bclr:
+ OBITOP (O_BCLR, 1, 1, ea &= ~m); /* bclr */
+ OBITOP (O_BLD, 1, 0, c = ea & m); /* bld */
+ OBITOP (O_BILD, 1, 0, c = !(ea & m)); /* bild */
+ OBITOP (O_BST, 1, 1, ea &= ~m;
+ if (C) ea |= m); /* bst */
+ OBITOP (O_BIST, 1, 1, ea &= ~m;
+ if (!C) ea |= m); /* bist */
+ OBITOP (O_BSTZ, 1, 1, ea &= ~m;
+ if (Z) ea |= m); /* bstz */
+ OBITOP (O_BISTZ, 1, 1, ea &= ~m;
+ if (!Z) ea |= m); /* bistz */
+ OBITOP (O_BAND, 1, 0, c = (ea & m) && C); /* band */
+ OBITOP (O_BIAND, 1, 0, c = !(ea & m) && C); /* biand */
+ OBITOP (O_BOR, 1, 0, c = (ea & m) || C); /* bor */
+ OBITOP (O_BIOR, 1, 0, c = !(ea & m) || C); /* bior */
+ OBITOP (O_BXOR, 1, 0, c = ((ea & m) != 0)!= C); /* bxor */
+ OBITOP (O_BIXOR, 1, 0, c = !(ea & m) != C); /* bixor */
+
+ case O (O_BFLD, SB): /* bfld */
+ /* bitfield load */
+ ea = 0;
+ if (fetch (sd, &code->src, &bit))
+ goto end;
+
+ if (bit != 0)
+ {
+ if (fetch (sd, &code->dst, &ea))
+ goto end;
+
+ ea &= bit;
+ while (!(bit & 1))
+ {
+ ea >>= 1;
+ bit >>= 1;
+ }
+ }
+ if (store (sd, &code->op3, ea))
+ goto end;
+
+ goto next;
+
+ case O(O_BFST, SB): /* bfst */
+ /* bitfield store */
+ /* NOTE: the imm8 value is in dst, and the ea value
+ (which is actually the destination) is in op3.
+ It has to be that way, to avoid breaking the assembler. */
+
+ if (fetch (sd, &code->dst, &bit)) /* imm8 */
+ goto end;
+ if (bit == 0) /* noop -- nothing to do. */
+ goto next;
+
+ if (fetch (sd, &code->src, &rd)) /* reg8 src */
+ goto end;
+
+ if (fetch2 (sd, &code->op3, &ea)) /* ea dst */
+ goto end;
+
+ /* Left-shift the register data into position. */
+ for (tmp = bit; !(tmp & 1); tmp >>= 1)
+ rd <<= 1;
+
+ /* Combine it with the neighboring bits. */
+ ea = (ea & ~bit) | (rd & bit);
+
+ /* Put it back. */
+ if (store2 (sd, &code->op3, ea))
+ goto end;
+ goto next;
+
+ case O (O_CLRMAC, SN): /* clrmac */
+ h8_set_mach (sd, 0);
+ h8_set_macl (sd, 0);
+ h8_set_macZ (sd, 1);
+ h8_set_macV (sd, 0);
+ h8_set_macN (sd, 0);
+ goto next;
+
+ case O (O_STMAC, SL): /* stmac, 260 */
+ switch (code->src.type) {
+ case X (OP_MACH, SL):
+ res = h8_get_mach (sd);
+ if (res & 0x200) /* sign extend */
+ res |= 0xfffffc00;
+ break;
+ case X (OP_MACL, SL):
+ res = h8_get_macl (sd);
+ break;
+ default: goto illegal;
+ }
+ nz = !h8_get_macZ (sd);
+ n = h8_get_macN (sd);
+ v = h8_get_macV (sd);
+
+ if (store (sd, &code->dst, res))
+ goto end;
+
+ goto next;
+
+ case O (O_LDMAC, SL): /* ldmac, 179 */
+ if (fetch (sd, &code->src, &rd))
+ goto end;
+
+ switch (code->dst.type) {
+ case X (OP_MACH, SL):
+ rd &= 0x3ff; /* Truncate to 10 bits */
+ h8_set_mach (sd, rd);
+ break;
+ case X (OP_MACL, SL):
+ h8_set_macl (sd, rd);
+ break;
+ default: goto illegal;
+ }
+ h8_set_macV (sd, 0);
+ goto next;
+
+ case O (O_MAC, SW):
+ if (fetch (sd, &code->src, &rd) ||
+ fetch (sd, &code->dst, &res))
+ goto end;
+
+ /* Ye gods, this is non-portable!
+ However, the existing mul/div code is similar. */
+ res = SEXTSHORT (res) * SEXTSHORT (rd);
+
+ if (h8_get_macS (sd)) /* Saturating mode */
+ {
+ long long mac = h8_get_macl (sd);
+
+ if (mac & 0x80000000) /* sign extend */
+ mac |= 0xffffffff00000000LL;
+
+ mac += res;
+ if (mac > 0x7fffffff || mac < 0xffffffff80000000LL)
+ h8_set_macV (sd, 1);
+ h8_set_macZ (sd, (mac == 0));
+ h8_set_macN (sd, (mac < 0));
+ h8_set_macl (sd, (int) mac);
+ }
+ else /* "Less Saturating" mode */
+ {
+ long long mac = h8_get_mach (sd);
+ mac <<= 32;
+ mac += h8_get_macl (sd);
+
+ if (mac & 0x20000000000LL) /* sign extend */
+ mac |= 0xfffffc0000000000LL;
+
+ mac += res;
+ if (mac > 0x1ffffffffffLL ||
+ mac < (long long) 0xfffffe0000000000LL)
+ h8_set_macV (sd, 1);
+ h8_set_macZ (sd, (mac == 0));
+ h8_set_macN (sd, (mac < 0));
+ h8_set_macl (sd, (int) mac);
+ mac >>= 32;
+ h8_set_mach (sd, (int) (mac & 0x3ff));
+ }
+ goto next;
+
+ case O (O_MULS, SW): /* muls.w */
+ if (fetch (sd, &code->src, &ea) ||
+ fetch (sd, &code->dst, &rd))
+ goto end;
+
+ ea = SEXTSHORT (ea);
+ res = SEXTSHORT (ea * SEXTSHORT (rd));
+
+ n = res & 0x8000;
+ nz = res & 0xffff;
+ if (store (sd, &code->dst, res))
+ goto end;
+
+ goto next;
+
+ case O (O_MULS, SL): /* muls.l */
+ if (fetch (sd, &code->src, &ea) ||
+ fetch (sd, &code->dst, &rd))
+ goto end;
+
+ res = ea * rd;
+
+ n = res & 0x80000000;
+ nz = res & 0xffffffff;
+ if (store (sd, &code->dst, res))
+ goto end;
+ goto next;
+
+ case O (O_MULSU, SL): /* muls/u.l */
+ if (fetch (sd, &code->src, &ea) ||
+ fetch (sd, &code->dst, &rd))
+ goto end;
+
+ /* Compute upper 32 bits of the 64-bit result. */
+ res = (((long long) ea) * ((long long) rd)) >> 32;
+
+ n = res & 0x80000000;
+ nz = res & 0xffffffff;
+ if (store (sd, &code->dst, res))
+ goto end;
+ goto next;
+
+ case O (O_MULU, SW): /* mulu.w */
+ if (fetch (sd, &code->src, &ea) ||
+ fetch (sd, &code->dst, &rd))
+ goto end;
+
+ res = UEXTSHORT ((UEXTSHORT (ea) * UEXTSHORT (rd)));
+
+ /* Don't set Z or N. */
+ if (store (sd, &code->dst, res))
+ goto end;
+
+ goto next;
+
+ case O (O_MULU, SL): /* mulu.l */
+ if (fetch (sd, &code->src, &ea) ||
+ fetch (sd, &code->dst, &rd))
+ goto end;
+
+ res = ea * rd;
+
+ /* Don't set Z or N. */
+ if (store (sd, &code->dst, res))
+ goto end;
+
+ goto next;
+
+ case O (O_MULUU, SL): /* mulu/u.l */
+ if (fetch (sd, &code->src, &ea) ||
+ fetch (sd, &code->dst, &rd))
+ goto end;
+
+ /* Compute upper 32 bits of the 64-bit result. */
+ res = (((unsigned long long) (unsigned) ea) *
+ ((unsigned long long) (unsigned) rd)) >> 32;
+
+ /* Don't set Z or N. */
+ if (store (sd, &code->dst, res))
+ goto end;
+
+ goto next;
+
+ case O (O_MULXS, SB): /* mulxs.b */
+ if (fetch (sd, &code->src, &ea) ||
+ fetch (sd, &code->dst, &rd))
+ goto end;
+
+ ea = SEXTCHAR (ea);
+ res = ea * SEXTCHAR (rd);
+
+ n = res & 0x8000;
+ nz = res & 0xffff;
+ if (store (sd, &code->dst, res))
+ goto end;
+
+ goto next;
+
+ case O (O_MULXS, SW): /* mulxs.w */
+ if (fetch (sd, &code->src, &ea) ||
+ fetch (sd, &code->dst, &rd))
+ goto end;
+
+ ea = SEXTSHORT (ea);
+ res = ea * SEXTSHORT (rd & 0xffff);
+
+ n = res & 0x80000000;
+ nz = res & 0xffffffff;
+ if (store (sd, &code->dst, res))
+ goto end;
+
+ goto next;
+
+ case O (O_MULXU, SB): /* mulxu.b */
+ if (fetch (sd, &code->src, &ea) ||
+ fetch (sd, &code->dst, &rd))
+ goto end;
+
+ res = UEXTCHAR (ea) * UEXTCHAR (rd);
+
+ if (store (sd, &code->dst, res))
+ goto end;
+
+ goto next;
+
+ case O (O_MULXU, SW): /* mulxu.w */
+ if (fetch (sd, &code->src, &ea) ||
+ fetch (sd, &code->dst, &rd))
+ goto end;
+
+ res = UEXTSHORT (ea) * UEXTSHORT (rd);
+
+ if (store (sd, &code->dst, res))
+ goto end;
+
+ goto next;
+
+ case O (O_TAS, SB): /* tas (test and set) */
+ if (!h8300sxmode) /* h8sx can use any register. */
+ switch (code->src.reg)
+ {
+ case R0_REGNUM:
+ case R1_REGNUM:
+ case R4_REGNUM:
+ case R5_REGNUM:
+ break;
+ default:
+ goto illegal;