Commit a0333817 authored by Kwok Cheung Yeung's avatar Kwok Cheung Yeung Committed by Riku Voipio
Browse files

linux-user: Handle compressed ISA encodings when processing MIPS exceptions



Decode trap instructions during the handling of an EXCP_BREAK or EXCP_TRAP
according to the current ISA mode.

Signed-off-by: default avatarKwok Cheung Yeung <kcy@codesourcery.com>
Signed-off-by: default avatarRiku Voipio <riku.voipio@linaro.org>
parent d02532f0
Loading
Loading
Loading
Loading
+43 −3
Original line number Diff line number Diff line
@@ -2310,7 +2310,31 @@ done_syscall:
                abi_ulong trap_instr;
                unsigned int code;

                if (env->hflags & MIPS_HFLAG_M16) {
                    if (env->insn_flags & ASE_MICROMIPS) {
                        /* microMIPS mode */
                        abi_ulong instr[2];

                        ret = get_user_u16(instr[0], env->active_tc.PC) ||
                              get_user_u16(instr[1], env->active_tc.PC + 2);

                        trap_instr = (instr[0] << 16) | instr[1];
                    } else {
                        /* MIPS16e mode */
                        ret = get_user_u16(trap_instr, env->active_tc.PC);
                        if (ret != 0) {
                            goto error;
                        }
                        code = (trap_instr >> 6) & 0x3f;
                        if (do_break(env, &info, code) != 0) {
                            goto error;
                        }
                        break;
                    }
                } else {
                    ret = get_user_ual(trap_instr, env->active_tc.PC);
                }

                if (ret != 0) {
                    goto error;
                }
@@ -2334,15 +2358,31 @@ done_syscall:
                abi_ulong trap_instr;
                unsigned int code = 0;

                if (env->hflags & MIPS_HFLAG_M16) {
                    /* microMIPS mode */
                    abi_ulong instr[2];

                    ret = get_user_u16(instr[0], env->active_tc.PC) ||
                          get_user_u16(instr[1], env->active_tc.PC + 2);

                    trap_instr = (instr[0] << 16) | instr[1];
                } else {
                    ret = get_user_ual(trap_instr, env->active_tc.PC);
                }

                if (ret != 0) {
                    goto error;
                }

                /* The immediate versions don't provide a code.  */
                if (!(trap_instr & 0xFC000000)) {
                    if (env->hflags & MIPS_HFLAG_M16) {
                        /* microMIPS mode */
                        code = ((trap_instr >> 12) & ((1 << 4) - 1));
                    } else {
                        code = ((trap_instr >> 6) & ((1 << 10) - 1));
                    }
                }

                if (do_break(env, &info, code) != 0) {
                    goto error;