Example #1
0
static void sparc_cpu_set_pc(CPUState *cs, vaddr value)
{
    SPARCCPU *cpu = SPARC_CPU(cs);

    cpu->env.pc = value;
    cpu->env.npc = value + 4;
}
Example #2
0
static void sparc_cpu_synchronize_from_tb(CPUState *cs, TranslationBlock *tb)
{
    SPARCCPU *cpu = SPARC_CPU(cs);

    cpu->env.pc = tb->pc;
    cpu->env.npc = tb->cs_base;
}
Example #3
0
SPARCCPU *sparc64_cpu_devinit(const char *cpu_type, uint64_t prom_addr)
{
    SPARCCPU *cpu;
    CPUSPARCState *env;
    ResetData *reset_info;

    uint32_t   tick_frequency = 100 * 1000000;
    uint32_t  stick_frequency = 100 * 1000000;
    uint32_t hstick_frequency = 100 * 1000000;

    cpu = SPARC_CPU(cpu_create(cpu_type));
    qdev_init_gpio_in_named(DEVICE(cpu), sparc64_cpu_set_ivec_irq,
                            "ivec-irq", IVEC_MAX);
    env = &cpu->env;

    env->tick = cpu_timer_create("tick", cpu, tick_irq,
                                  tick_frequency, TICK_INT_DIS,
                                  TICK_NPT_MASK);

    env->stick = cpu_timer_create("stick", cpu, stick_irq,
                                   stick_frequency, TICK_INT_DIS,
                                   TICK_NPT_MASK);

    env->hstick = cpu_timer_create("hstick", cpu, hstick_irq,
                                    hstick_frequency, TICK_INT_DIS,
                                    TICK_NPT_MASK);

    reset_info = g_malloc0(sizeof(ResetData));
    reset_info->cpu = cpu;
    reset_info->prom_addr = prom_addr;
    qemu_register_reset(main_cpu_reset, reset_info);

    return cpu;
}
Example #4
0
static void sparc_cpu_uninitfn(Object *obj)
{
    SPARCCPU *cpu = SPARC_CPU(obj);
    CPUSPARCState *env = &cpu->env;

    g_free(env->def);
}
Example #5
0
static bool sparc_cpu_has_work(CPUState *cs)
{
    SPARCCPU *cpu = SPARC_CPU(cs);
    CPUSPARCState *env = &cpu->env;

    return (cs->interrupt_request & CPU_INTERRUPT_HARD) &&
           cpu_interrupts_enabled(env);
}
Example #6
0
static void sparc_cpu_realizefn(DeviceState *dev, Error **errp)
{
    SPARCCPU *cpu = SPARC_CPU(dev);
    SPARCCPUClass *scc = SPARC_CPU_GET_CLASS(dev);

    qemu_init_vcpu(&cpu->env);

    scc->parent_realize(dev, errp);
}
Example #7
0
CpuInfoList *qmp_query_cpus(Error **errp)
{
    CpuInfoList *head = NULL, *cur_item = NULL;
    CPUState *cpu;

    for (cpu = first_cpu; cpu != NULL; cpu = cpu->next_cpu) {
        CpuInfoList *info;
#if defined(TARGET_I386)
        X86CPU *x86_cpu = X86_CPU(cpu);
        CPUX86State *env = &x86_cpu->env;
#elif defined(TARGET_PPC)
        PowerPCCPU *ppc_cpu = POWERPC_CPU(cpu);
        CPUPPCState *env = &ppc_cpu->env;
#elif defined(TARGET_SPARC)
        SPARCCPU *sparc_cpu = SPARC_CPU(cpu);
        CPUSPARCState *env = &sparc_cpu->env;
#elif defined(TARGET_MIPS)
        MIPSCPU *mips_cpu = MIPS_CPU(cpu);
        CPUMIPSState *env = &mips_cpu->env;
#endif

        cpu_synchronize_state(cpu);

        info = g_malloc0(sizeof(*info));
        info->value = g_malloc0(sizeof(*info->value));
        info->value->CPU = cpu->cpu_index;
        info->value->current = (cpu == first_cpu);
        info->value->halted = cpu->halted;
        info->value->thread_id = cpu->thread_id;
#if defined(TARGET_I386)
        info->value->has_pc = true;
        info->value->pc = env->eip + env->segs[R_CS].base;
#elif defined(TARGET_PPC)
        info->value->has_nip = true;
        info->value->nip = env->nip;
#elif defined(TARGET_SPARC)
        info->value->has_pc = true;
        info->value->pc = env->pc;
        info->value->has_npc = true;
        info->value->npc = env->npc;
#elif defined(TARGET_MIPS)
        info->value->has_PC = true;
        info->value->PC = env->active_tc.PC;
#endif

        /* XXX: waiting for the qapi to support GSList */
        if (!cur_item) {
            head = cur_item = info;
        } else {
            cur_item->next = info;
            cur_item = info;
        }
    }

    return head;
}
Example #8
0
int sparc_reg_write(struct uc_struct *uc, unsigned int regid, const void *value)
{
    CPUState *mycpu = first_cpu;

    if (regid >= UC_SPARC_REG_G0 && regid <= UC_SPARC_REG_G7)
        SPARC_CPU(uc, mycpu)->env.gregs[regid - UC_SPARC_REG_G0] = *(uint64_t *)value;
    else if (regid >= UC_SPARC_REG_O0 && regid <= UC_SPARC_REG_O7)
        SPARC_CPU(uc, mycpu)->env.regwptr[regid - UC_SPARC_REG_O0] = *(uint64_t *)value;
    else if (regid >= UC_SPARC_REG_L0 && regid <= UC_SPARC_REG_L7)
        SPARC_CPU(uc, mycpu)->env.regwptr[8 + regid - UC_SPARC_REG_L0] = *(uint64_t *)value;
    else if (regid >= UC_SPARC_REG_I0 && regid <= UC_SPARC_REG_I7)
        SPARC_CPU(uc, mycpu)->env.regwptr[16 + regid - UC_SPARC_REG_I0] = *(uint64_t *)value;
    else {
        switch(regid) {
            default: break;
            case UC_SPARC_REG_PC:
                 SPARC_CPU(uc, mycpu)->env.pc = *(uint64_t *)value;
                 SPARC_CPU(uc, mycpu)->env.npc = *(uint64_t *)value + 4;
                 break;
        }
    }


    return 0;
}
Example #9
0
int sparc_reg_write(struct uc_struct *uc, unsigned int regid, const void *value)
{
    CPUState *mycpu = first_cpu;

    if (regid >= UC_SPARC_REG_G0 && regid <= UC_SPARC_REG_G7)
        SPARC_CPU(uc, mycpu)->env.gregs[regid - UC_SPARC_REG_G0] = *(uint32_t *)value;
    else if (regid >= UC_SPARC_REG_O0 && regid <= UC_SPARC_REG_O7)
        SPARC_CPU(uc, mycpu)->env.regwptr[regid - UC_SPARC_REG_O0] = *(uint32_t *)value;
    else if (regid >= UC_SPARC_REG_L0 && regid <= UC_SPARC_REG_L7)
        SPARC_CPU(uc, mycpu)->env.regwptr[8 + regid - UC_SPARC_REG_L0] = *(uint32_t *)value;
    else if (regid >= UC_SPARC_REG_I0 && regid <= UC_SPARC_REG_I7)
            SPARC_CPU(uc, mycpu)->env.regwptr[16 + regid - UC_SPARC_REG_I0] = *(uint32_t *)value;
    else {
        switch(regid) {
            default: break;
            case UC_SPARC_REG_PC:
                SPARC_CPU(uc, mycpu)->env.pc = *(uint32_t *)value;
                SPARC_CPU(uc, mycpu)->env.npc = *(uint32_t *)value + 4;
                // force to quit execution and flush TB
                uc->quit_request = true;
                uc_emu_stop(uc);
                break;
        }
    }

    return 0;
}
Example #10
0
static void sparc_cpu_initfn(Object *obj)
{
    CPUState *cs = CPU(obj);
    SPARCCPU *cpu = SPARC_CPU(obj);
    CPUSPARCState *env = &cpu->env;

    cs->env_ptr = env;
    cpu_exec_init(env);

    if (tcg_enabled()) {
        gen_intermediate_code_init(env);
    }
}
Example #11
0
int sparc_reg_read(struct uc_struct *uc, unsigned int regid, void *value)
{
    CPUState *mycpu = first_cpu;

    if (regid >= UC_SPARC_REG_G0 && regid <= UC_SPARC_REG_G7)
        *(int32_t *)value = SPARC_CPU(uc, mycpu)->env.gregs[regid - UC_SPARC_REG_G0];
    else if (regid >= UC_SPARC_REG_O0 && regid <= UC_SPARC_REG_O7)
        *(int32_t *)value = SPARC_CPU(uc, mycpu)->env.regwptr[regid - UC_SPARC_REG_O0];
    else if (regid >= UC_SPARC_REG_L0 && regid <= UC_SPARC_REG_L7)
            *(int32_t *)value = SPARC_CPU(uc, mycpu)->env.regwptr[8 + regid - UC_SPARC_REG_L0];
    else if (regid >= UC_SPARC_REG_I0 && regid <= UC_SPARC_REG_I7)
            *(int32_t *)value = SPARC_CPU(uc, mycpu)->env.regwptr[16 + regid - UC_SPARC_REG_I0];
    else {
        switch(regid) {
            default: break;
            case UC_SPARC_REG_PC:
                *(int32_t *)value = SPARC_CPU(uc, mycpu)->env.pc;
                break;
        }
    }

    return 0;
}
Example #12
0
/* CPUClass::reset() */
static void sparc_cpu_reset(CPUState *s)
{
    SPARCCPU *cpu = SPARC_CPU(s);
    SPARCCPUClass *scc = SPARC_CPU_GET_CLASS(cpu);
    CPUSPARCState *env = &cpu->env;

    if (qemu_loglevel_mask(CPU_LOG_RESET)) {
        qemu_log("CPU Reset (CPU %d)\n", s->cpu_index);
        log_cpu_state(env, 0);
    }

    scc->parent_reset(s);

    memset(env, 0, offsetof(CPUSPARCState, breakpoints));
    tlb_flush(env, 1);
    env->cwp = 0;
#ifndef TARGET_SPARC64
    env->wim = 1;
#endif
    env->regwptr = env->regbase + (env->cwp * 16);
    CC_OP = CC_OP_FLAGS;
#if defined(CONFIG_USER_ONLY)
#ifdef TARGET_SPARC64
    env->cleanwin = env->nwindows - 2;
    env->cansave = env->nwindows - 2;
    env->pstate = PS_RMO | PS_PEF | PS_IE;
    env->asi = 0x82; /* Primary no-fault */
#endif
#else
#if !defined(TARGET_SPARC64)
    env->psret = 0;
    env->psrs = 1;
    env->psrps = 1;
#endif
#ifdef TARGET_SPARC64
    env->pstate = PS_PRIV|PS_RED|PS_PEF|PS_AG;
    env->hpstate = cpu_has_hypervisor(env) ? HS_PRIV : 0;
    env->tl = env->maxtl;
    cpu_tsptr(env)->tt = TT_POWER_ON_RESET;
    env->lsu = 0;
#else
    env->mmuregs[0] &= ~(MMU_E | MMU_NF);
    env->mmuregs[0] |= env->def->mmu_bm;
#endif
    env->pc = 0;
    env->npc = env->pc + 4;
#endif
    env->cache_control = 0;
}
Example #13
0
SPARCCPU *cpu_sparc_init(const char *cpu_model)
{
    SPARCCPU *cpu;

    cpu = SPARC_CPU(object_new(TYPE_SPARC_CPU));

    if (cpu_sparc_register(cpu, cpu_model) < 0) {
        object_unref(OBJECT(cpu));
        return NULL;
    }

    object_property_set_bool(OBJECT(cpu), true, "realized", NULL);

    return cpu;
}
Example #14
0
static void sparc_cpu_realizefn(DeviceState *dev, Error **errp)
{
    SPARCCPUClass *scc = SPARC_CPU_GET_CLASS(dev);
#if defined(CONFIG_USER_ONLY)
    SPARCCPU *cpu = SPARC_CPU(dev);
    CPUSPARCState *env = &cpu->env;

    if ((env->def->features & CPU_FEATURE_FLOAT)) {
        env->def->features |= CPU_FEATURE_FLOAT128;
    }
#endif

    qemu_init_vcpu(CPU(dev));

    scc->parent_realize(dev, errp);
}
Example #15
0
static bool sparc_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
{
    if (interrupt_request & CPU_INTERRUPT_HARD) {
        SPARCCPU *cpu = SPARC_CPU(cs);
        CPUSPARCState *env = &cpu->env;

        if (cpu_interrupts_enabled(env) && env->interrupt_index > 0) {
            int pil = env->interrupt_index & 0xf;
            int type = env->interrupt_index & 0xf0;

            if (type != TT_EXTINT || cpu_pil_allowed(env, pil)) {
                cs->exception_index = env->interrupt_index;
                sparc_cpu_do_interrupt(cs);
                return true;
            }
        }
    }
    return false;
}
Example #16
0
File: sparc64.c Project: 8tab/qemu
SPARCCPU *sparc64_cpu_devinit(const char *cpu_model,
                              const char *default_cpu_model, uint64_t prom_addr)
{
    SPARCCPU *cpu;
    CPUSPARCState *env;
    ResetData *reset_info;

    uint32_t   tick_frequency = 100 * 1000000;
    uint32_t  stick_frequency = 100 * 1000000;
    uint32_t hstick_frequency = 100 * 1000000;

    if (cpu_model == NULL) {
        cpu_model = default_cpu_model;
    }
    cpu = SPARC_CPU(cpu_generic_init(TYPE_SPARC_CPU, cpu_model));
    if (cpu == NULL) {
        fprintf(stderr, "Unable to find Sparc CPU definition\n");
        exit(1);
    }
    env = &cpu->env;

    env->tick = cpu_timer_create("tick", cpu, tick_irq,
                                  tick_frequency, TICK_INT_DIS,
                                  TICK_NPT_MASK);

    env->stick = cpu_timer_create("stick", cpu, stick_irq,
                                   stick_frequency, TICK_INT_DIS,
                                   TICK_NPT_MASK);

    env->hstick = cpu_timer_create("hstick", cpu, hstick_irq,
                                    hstick_frequency, TICK_INT_DIS,
                                    TICK_NPT_MASK);

    reset_info = g_malloc0(sizeof(ResetData));
    reset_info->cpu = cpu;
    reset_info->prom_addr = prom_addr;
    qemu_register_reset(main_cpu_reset, reset_info);

    return cpu;
}
Example #17
0
void sparc_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
                          int flags)
{
    SPARCCPU *cpu = SPARC_CPU(cs);
    CPUSPARCState *env = &cpu->env;
    int i, x;

    cpu_fprintf(f, "pc: " TARGET_FMT_lx "  npc: " TARGET_FMT_lx "\n", env->pc,
                env->npc);

    for (i = 0; i < 8; i++) {
        if (i % REGS_PER_LINE == 0) {
            cpu_fprintf(f, "%%g%d-%d:", i, i + REGS_PER_LINE - 1);
        }
        cpu_fprintf(f, " " TARGET_FMT_lx, env->gregs[i]);
        if (i % REGS_PER_LINE == REGS_PER_LINE - 1) {
            cpu_fprintf(f, "\n");
        }
    }
    for (x = 0; x < 3; x++) {
        for (i = 0; i < 8; i++) {
            if (i % REGS_PER_LINE == 0) {
                cpu_fprintf(f, "%%%c%d-%d: ",
                            x == 0 ? 'o' : (x == 1 ? 'l' : 'i'),
                            i, i + REGS_PER_LINE - 1);
            }
            cpu_fprintf(f, TARGET_FMT_lx " ", env->regwptr[i + x * 8]);
            if (i % REGS_PER_LINE == REGS_PER_LINE - 1) {
                cpu_fprintf(f, "\n");
            }
        }
    }

    for (i = 0; i < TARGET_DPREGS; i++) {
        if ((i & 3) == 0) {
            cpu_fprintf(f, "%%f%02d: ", i * 2);
        }
        cpu_fprintf(f, " %016" PRIx64, env->fpr[i].ll);
        if ((i & 3) == 3) {
            cpu_fprintf(f, "\n");
        }
    }
#ifdef TARGET_SPARC64
    cpu_fprintf(f, "pstate: %08x ccr: %02x (icc: ", env->pstate,
                (unsigned)cpu_get_ccr(env));
    cpu_print_cc(f, cpu_fprintf, cpu_get_ccr(env) << PSR_CARRY_SHIFT);
    cpu_fprintf(f, " xcc: ");
    cpu_print_cc(f, cpu_fprintf, cpu_get_ccr(env) << (PSR_CARRY_SHIFT - 4));
    cpu_fprintf(f, ") asi: %02x tl: %d pil: %x\n", env->asi, env->tl,
                env->psrpil);
    cpu_fprintf(f, "cansave: %d canrestore: %d otherwin: %d wstate: %d "
                "cleanwin: %d cwp: %d\n",
                env->cansave, env->canrestore, env->otherwin, env->wstate,
                env->cleanwin, env->nwindows - 1 - env->cwp);
    cpu_fprintf(f, "fsr: " TARGET_FMT_lx " y: " TARGET_FMT_lx " fprs: "
                TARGET_FMT_lx "\n", env->fsr, env->y, env->fprs);
#else
    cpu_fprintf(f, "psr: %08x (icc: ", cpu_get_psr(env));
    cpu_print_cc(f, cpu_fprintf, cpu_get_psr(env));
    cpu_fprintf(f, " SPE: %c%c%c) wim: %08x\n", env->psrs ? 'S' : '-',
                env->psrps ? 'P' : '-', env->psret ? 'E' : '-',
                env->wim);
    cpu_fprintf(f, "fsr: " TARGET_FMT_lx " y: " TARGET_FMT_lx "\n",
                env->fsr, env->y);
#endif
    cpu_fprintf(f, "\n");
}
Example #18
0
void sparc_cpu_do_interrupt(CPUState *cs)
{
    SPARCCPU *cpu = SPARC_CPU(cs);
    CPUSPARCState *env = &cpu->env;
    int cwp, intno = cs->exception_index;

    /* Compute PSR before exposing state.  */
    if (env->cc_op != CC_OP_FLAGS) {
        cpu_get_psr(env);
    }

#ifdef DEBUG_PCALL
    if (qemu_loglevel_mask(CPU_LOG_INT)) {
        static int count;
        const char *name;

        if (intno < 0 || intno >= 0x100) {
            name = "Unknown";
        } else if (intno >= 0x80) {
            name = "Trap Instruction";
        } else {
            name = excp_names[intno];
            if (!name) {
                name = "Unknown";
            }
        }

        qemu_log("%6d: %s (v=%02x)\n", count, name, intno);
        log_cpu_state(cs, 0);
#if 0
        {
            int i;
            uint8_t *ptr;

            qemu_log("       code=");
            ptr = (uint8_t *)env->pc;
            for (i = 0; i < 16; i++) {
                qemu_log(" %02x", ldub(ptr + i));
            }
            qemu_log("\n");
        }
#endif
        count++;
    }
#endif
#if !defined(CONFIG_USER_ONLY)
    if (env->psret == 0) {
        if (cs->exception_index == 0x80 &&
            env->def->features & CPU_FEATURE_TA0_SHUTDOWN) {
            qemu_system_shutdown_request();
        } else {
            cpu_abort(cs, "Trap 0x%02x while interrupts disabled, Error state",
                      cs->exception_index);
        }
        return;
    }
#endif
    env->psret = 0;
    cwp = cpu_cwp_dec(env, env->cwp - 1);
    cpu_set_cwp(env, cwp);
    env->regwptr[9] = env->pc;
    env->regwptr[10] = env->npc;
    env->psrps = env->psrs;
    env->psrs = 1;
    env->tbr = (env->tbr & TBR_BASE_MASK) | (intno << 4);
    env->pc = env->tbr;
    env->npc = env->pc + 4;
    cs->exception_index = -1;

#if !defined(CONFIG_USER_ONLY)
    /* IRQ acknowledgment */
    if ((intno & ~15) == TT_EXTINT && env->qemu_irq_ack != NULL) {
        env->qemu_irq_ack(env, env->irq_manager, intno);
    }
#endif
}
Example #19
0
static void sparc_cpu_parse_features(CPUState *cs, char *features,
                                     Error **errp)
{
    SPARCCPU *cpu = SPARC_CPU(cs);
    sparc_def_t *cpu_def = cpu->env.def;
    char *featurestr;
    uint32_t plus_features = 0;
    uint32_t minus_features = 0;
    uint64_t iu_version;
    uint32_t fpu_version, mmu_version, nwindows;

    featurestr = features ? strtok(features, ",") : NULL;
    while (featurestr) {
        char *val;

        if (featurestr[0] == '+') {
            add_flagname_to_bitmaps(featurestr + 1, &plus_features);
        } else if (featurestr[0] == '-') {
            add_flagname_to_bitmaps(featurestr + 1, &minus_features);
        } else if ((val = strchr(featurestr, '='))) {
            *val = 0; val++;
            if (!strcmp(featurestr, "iu_version")) {
                char *err;

                iu_version = strtoll(val, &err, 0);
                if (!*val || *err) {
                    error_setg(errp, "bad numerical value %s", val);
                    return;
                }
                cpu_def->iu_version = iu_version;
#ifdef DEBUG_FEATURES
                fprintf(stderr, "iu_version %" PRIx64 "\n", iu_version);
#endif
            } else if (!strcmp(featurestr, "fpu_version")) {
                char *err;

                fpu_version = strtol(val, &err, 0);
                if (!*val || *err) {
                    error_setg(errp, "bad numerical value %s", val);
                    return;
                }
                cpu_def->fpu_version = fpu_version;
#ifdef DEBUG_FEATURES
                fprintf(stderr, "fpu_version %x\n", fpu_version);
#endif
            } else if (!strcmp(featurestr, "mmu_version")) {
                char *err;

                mmu_version = strtol(val, &err, 0);
                if (!*val || *err) {
                    error_setg(errp, "bad numerical value %s", val);
                    return;
                }
                cpu_def->mmu_version = mmu_version;
#ifdef DEBUG_FEATURES
                fprintf(stderr, "mmu_version %x\n", mmu_version);
#endif
            } else if (!strcmp(featurestr, "nwindows")) {
                char *err;

                nwindows = strtol(val, &err, 0);
                if (!*val || *err || nwindows > MAX_NWINDOWS ||
                    nwindows < MIN_NWINDOWS) {
                    error_setg(errp, "bad numerical value %s", val);
                    return;
                }
                cpu_def->nwindows = nwindows;
#ifdef DEBUG_FEATURES
                fprintf(stderr, "nwindows %d\n", nwindows);
#endif
            } else {
                error_setg(errp, "unrecognized feature %s", featurestr);
                return;
            }
        } else {
            error_setg(errp, "feature string `%s' not in format "
                             "(+feature|-feature|feature=xyz)", featurestr);
            return;
        }
        featurestr = strtok(NULL, ",");
    }
    cpu_def->features |= plus_features;
    cpu_def->features &= ~minus_features;
#ifdef DEBUG_FEATURES
    print_features(stderr, fprintf, cpu_def->features, NULL);
#endif
}
Example #20
0
void sparc_cpu_do_interrupt(CPUState *cs)
{
    SPARCCPU *cpu = SPARC_CPU(cs);
    CPUSPARCState *env = &cpu->env;
    int intno = cs->exception_index;
    trap_state *tsptr;

    /* Compute PSR before exposing state.  */
    if (env->cc_op != CC_OP_FLAGS) {
        cpu_get_psr(env);
    }

#ifdef DEBUG_PCALL
    if (qemu_loglevel_mask(CPU_LOG_INT)) {
        static int count;
        const char *name;

        if (intno < 0 || intno >= 0x180) {
            name = "Unknown";
        } else if (intno >= 0x100) {
            name = "Trap Instruction";
        } else if (intno >= 0xc0) {
            name = "Window Fill";
        } else if (intno >= 0x80) {
            name = "Window Spill";
        } else {
            name = excp_names[intno];
            if (!name) {
                name = "Unknown";
            }
        }

        qemu_log("%6d: %s (v=%04x)\n", count, name, intno);
        log_cpu_state(cs, 0);
#if 0
        {
            int i;
            uint8_t *ptr;

            qemu_log("       code=");
            ptr = (uint8_t *)env->pc;
            for (i = 0; i < 16; i++) {
                qemu_log(" %02x", ldub(ptr + i));
            }
            qemu_log("\n");
        }
#endif
        count++;
    }
#endif
#if !defined(CONFIG_USER_ONLY)
    if (env->tl >= env->maxtl) {
        cpu_abort(cs, "Trap 0x%04x while trap level (%d) >= MAXTL (%d),"
                  " Error state", cs->exception_index, env->tl, env->maxtl);
        return;
    }
#endif
    if (env->tl < env->maxtl - 1) {
        env->tl++;
    } else {
        env->pstate |= PS_RED;
        if (env->tl < env->maxtl) {
            env->tl++;
        }
    }
    tsptr = cpu_tsptr(env);

    tsptr->tstate = (cpu_get_ccr(env) << 32) |
        ((env->asi & 0xff) << 24) | ((env->pstate & 0xf3f) << 8) |
        cpu_get_cwp64(env);
    tsptr->tpc = env->pc;
    tsptr->tnpc = env->npc;
    tsptr->tt = intno;

    switch (intno) {
    case TT_IVEC:
        cpu_change_pstate(env, PS_PEF | PS_PRIV | PS_IG);
        break;
    case TT_TFAULT:
    case TT_DFAULT:
    case TT_TMISS ... TT_TMISS + 3:
    case TT_DMISS ... TT_DMISS + 3:
    case TT_DPROT ... TT_DPROT + 3:
        cpu_change_pstate(env, PS_PEF | PS_PRIV | PS_MG);
        break;
    default:
        cpu_change_pstate(env, PS_PEF | PS_PRIV | PS_AG);
        break;
    }

    if (intno == TT_CLRWIN) {
        cpu_set_cwp(env, cpu_cwp_dec(env, env->cwp - 1));
    } else if ((intno & 0x1c0) == TT_SPILL) {
        cpu_set_cwp(env, cpu_cwp_dec(env, env->cwp - env->cansave - 2));
    } else if ((intno & 0x1c0) == TT_FILL) {
        cpu_set_cwp(env, cpu_cwp_inc(env, env->cwp + 1));
    }
    env->tbr &= ~0x7fffULL;
    env->tbr |= ((env->tl > 1) ? 1 << 14 : 0) | (intno << 5);
    env->pc = env->tbr;
    env->npc = env->pc + 4;
    cs->exception_index = -1;
}