static void gen_mfc0 (CPUState *env, DisasContext *ctx, int reg, int sel)

{

    const char *rn = "invalid";

    if (sel != 0)

        check_insn(env, ctx, ISA_MIPS32);

    switch (reg) {

    case 0:

        switch (sel) {

        case 0:

            gen_op_mfc0_index();

            rn = "Index";

            break;

        case 1:

            check_mips_mt(env, ctx);

            gen_op_mfc0_mvpcontrol();

            rn = "MVPControl";

            break;

        case 2:

            check_mips_mt(env, ctx);

            gen_op_mfc0_mvpconf0();

            rn = "MVPConf0";

            break;

        case 3:

            check_mips_mt(env, ctx);

            gen_op_mfc0_mvpconf1();

            rn = "MVPConf1";

            break;

        default:

            goto die;

        }

        break;

    case 1:

        switch (sel) {

        case 0:

            gen_op_mfc0_random();

            rn = "Random";

            break;

        case 1:

            check_mips_mt(env, ctx);

            gen_op_mfc0_vpecontrol();

            rn = "VPEControl";

            break;

        case 2:

            check_mips_mt(env, ctx);

            gen_op_mfc0_vpeconf0();

            rn = "VPEConf0";

            break;

        case 3:

            check_mips_mt(env, ctx);

            gen_op_mfc0_vpeconf1();

            rn = "VPEConf1";

            break;

        case 4:

            check_mips_mt(env, ctx);

            gen_op_mfc0_yqmask();

            rn = "YQMask";

            break;

        case 5:

            check_mips_mt(env, ctx);

            gen_op_mfc0_vpeschedule();

            rn = "VPESchedule";

            break;

        case 6:

            check_mips_mt(env, ctx);

            gen_op_mfc0_vpeschefback();

            rn = "VPEScheFBack";

            break;

        case 7:

            check_mips_mt(env, ctx);

            gen_op_mfc0_vpeopt();

            rn = "VPEOpt";

            break;

        default:

            goto die;

        }

        break;

    case 2:

        switch (sel) {

        case 0:

            gen_op_mfc0_entrylo0();

            rn = "EntryLo0";

            break;

        case 1:

            check_mips_mt(env, ctx);

            gen_op_mfc0_tcstatus();

            rn = "TCStatus";

            break;

        case 2:

            check_mips_mt(env, ctx);

            gen_op_mfc0_tcbind();

            rn = "TCBind";

            break;

        case 3:

            check_mips_mt(env, ctx);

            gen_op_mfc0_tcrestart();

            rn = "TCRestart";

            break;

        case 4:

            check_mips_mt(env, ctx);

            gen_op_mfc0_tchalt();

            rn = "TCHalt";

            break;

        case 5:

            check_mips_mt(env, ctx);

            gen_op_mfc0_tccontext();

            rn = "TCContext";

            break;

        case 6:

            check_mips_mt(env, ctx);

            gen_op_mfc0_tcschedule();

            rn = "TCSchedule";

            break;

        case 7:

            check_mips_mt(env, ctx);

            gen_op_mfc0_tcschefback();

            rn = "TCScheFBack";

            break;

        default:

            goto die;

        }

        break;

    case 3:

        switch (sel) {

        case 0:

            gen_op_mfc0_entrylo1();

            rn = "EntryLo1";

            break;

        default:

            goto die;

        }

        break;

    case 4:

        switch (sel) {

        case 0:

            gen_op_mfc0_context();

            rn = "Context";

            break;

        case 1:

//            gen_op_mfc0_contextconfig(); /* SmartMIPS ASE */

            rn = "ContextConfig";

//            break;

        default:

            goto die;

        }

        break;

    case 5:

        switch (sel) {

        case 0:

            gen_op_mfc0_pagemask();

            rn = "PageMask";

            break;

        case 1:

            check_insn(env, ctx, ISA_MIPS32R2);

            gen_op_mfc0_pagegrain();

            rn = "PageGrain";

            break;

        default:

            goto die;

        }

        break;

    case 6:

        switch (sel) {

        case 0:

            gen_op_mfc0_wired();

            rn = "Wired";

            break;

        case 1:

            check_insn(env, ctx, ISA_MIPS32R2);

            gen_op_mfc0_srsconf0();

            rn = "SRSConf0";

            break;

        case 2:

            check_insn(env, ctx, ISA_MIPS32R2);

            gen_op_mfc0_srsconf1();

            rn = "SRSConf1";

            break;

        case 3:

            check_insn(env, ctx, ISA_MIPS32R2);

            gen_op_mfc0_srsconf2();

            rn = "SRSConf2";

            break;

        case 4:

            check_insn(env, ctx, ISA_MIPS32R2);

            gen_op_mfc0_srsconf3();

            rn = "SRSConf3";

            break;

        case 5:

            check_insn(env, ctx, ISA_MIPS32R2);

            gen_op_mfc0_srsconf4();

            rn = "SRSConf4";

            break;

        default:

            goto die;

        }

        break;

    case 7:

        switch (sel) {

        case 0:

            check_insn(env, ctx, ISA_MIPS32R2);

            gen_op_mfc0_hwrena();

            rn = "HWREna";

            break;

        default:

            goto die;

        }

        break;

    case 8:

        switch (sel) {

        case 0:

            gen_op_mfc0_badvaddr();

            rn = "BadVaddr";

            break;

        default:

            goto die;

       }

        break;

    case 9:

        switch (sel) {

        case 0:

            gen_op_mfc0_count();

            rn = "Count";

            break;

        /* 6,7 are implementation dependent */

        default:

            goto die;

        }

        break;

    case 10:

        switch (sel) {

        case 0:

            gen_op_mfc0_entryhi();

            rn = "EntryHi";

            break;

        default:

            goto die;

        }

        break;

    case 11:

        switch (sel) {

        case 0:

            gen_op_mfc0_compare();

            rn = "Compare";

            break;

        /* 6,7 are implementation dependent */

        default:

            goto die;

        }

        break;

    case 12:

        switch (sel) {

        case 0:

            gen_op_mfc0_status();

            rn = "Status";

            break;

        case 1:

            check_insn(env, ctx, ISA_MIPS32R2);

            gen_op_mfc0_intctl();

            rn = "IntCtl";

            break;

        case 2:

            check_insn(env, ctx, ISA_MIPS32R2);

            gen_op_mfc0_srsctl();

            rn = "SRSCtl";

            break;

        case 3:

            check_insn(env, ctx, ISA_MIPS32R2);

            gen_op_mfc0_srsmap();

            rn = "SRSMap";

            break;

        default:

            goto die;

       }

        break;

    case 13:

        switch (sel) {

        case 0:

            gen_op_mfc0_cause();

            rn = "Cause";

            break;

        default:

            goto die;

       }

        break;

    case 14:

        switch (sel) {

        case 0:

            gen_op_mfc0_epc();

            rn = "EPC";

            break;

        default:

            goto die;

        }

        break;

    case 15:

        switch (sel) {

        case 0:

            gen_op_mfc0_prid();

            rn = "PRid";

            break;

        case 1:

            check_insn(env, ctx, ISA_MIPS32R2);

            gen_op_mfc0_ebase();

            rn = "EBase";

            break;

        default:

            goto die;

       }

        break;

    case 16:

        switch (sel) {

        case 0:

            gen_op_mfc0_config0();

            rn = "Config";

            break;

        case 1:

            gen_op_mfc0_config1();

            rn = "Config1";

            break;

        case 2:

            gen_op_mfc0_config2();

            rn = "Config2";

            break;

        case 3:

            gen_op_mfc0_config3();

            rn = "Config3";

            break;

        /* 4,5 are reserved */

        /* 6,7 are implementation dependent */

        case 6:

            gen_op_mfc0_config6();

            rn = "Config6";

            break;

        case 7:

            gen_op_mfc0_config7();

            rn = "Config7";

            break;

        default:

            goto die;

        }

        break;

    case 17:

        switch (sel) {

        case 0:

            gen_op_mfc0_lladdr();

            rn = "LLAddr";

            break;

        default:

            goto die;

        }

        break;

    case 18:

        switch (sel) {

        case 0 ... 7:

            gen_op_mfc0_watchlo(sel);

            rn = "WatchLo";

            break;

        default:

            goto die;

        }

        break;

    case 19:

        switch (sel) {

        case 0 ...7:

            gen_op_mfc0_watchhi(sel);

            rn = "WatchHi";

            break;

        default:

            goto die;

        }

        break;

    case 20:

        switch (sel) {

        case 0:

#if defined(TARGET_MIPSN32) || defined(TARGET_MIPS64)

            check_insn(env, ctx, ISA_MIPS3);

            gen_op_mfc0_xcontext();

            rn = "XContext";

            break;

#endif

        default:

            goto die;

        }

        break;

    case 21:

       /* Officially reserved, but sel 0 is used for R1x000 framemask */

        switch (sel) {

        case 0:

            gen_op_mfc0_framemask();

            rn = "Framemask";

            break;

        default:

            goto die;

        }

        break;

    case 22:

        /* ignored */

        rn = "'Diagnostic"; /* implementation dependent */

        break;

    case 23:

        switch (sel) {

        case 0:

            gen_op_mfc0_debug(); /* EJTAG support */

            rn = "Debug";

            break;

        case 1:

//            gen_op_mfc0_tracecontrol(); /* PDtrace support */

            rn = "TraceControl";

//            break;

        case 2:

//            gen_op_mfc0_tracecontrol2(); /* PDtrace support */

            rn = "TraceControl2";

//            break;

        case 3:

//            gen_op_mfc0_usertracedata(); /* PDtrace support */

            rn = "UserTraceData";

//            break;

        case 4:

//            gen_op_mfc0_debug(); /* PDtrace support */

            rn = "TraceBPC";

//            break;

        default:

            goto die;

        }

        break;

    case 24:

        switch (sel) {

        case 0:

            gen_op_mfc0_depc(); /* EJTAG support */

            rn = "DEPC";

            break;

        default:

            goto die;

        }

        break;

    case 25:

        switch (sel) {

        case 0:

            gen_op_mfc0_performance0();

            rn = "Performance0";

            break;

        case 1:

//            gen_op_mfc0_performance1();

            rn = "Performance1";

//            break;

        case 2:

//            gen_op_mfc0_performance2();

            rn = "Performance2";

//            break;

        case 3:

//            gen_op_mfc0_performance3();

            rn = "Performance3";

//            break;

        case 4:

//            gen_op_mfc0_performance4();

            rn = "Performance4";

//            break;

        case 5:

//            gen_op_mfc0_performance5();

            rn = "Performance5";

//            break;

        case 6:

//            gen_op_mfc0_performance6();

            rn = "Performance6";

//            break;

        case 7:

//            gen_op_mfc0_performance7();

            rn = "Performance7";

//            break;

        default:

            goto die;

        }

        break;

    case 26:

       rn = "ECC";

       break;

    case 27:

        switch (sel) {

        /* ignored */

        case 0 ... 3:

            rn = "CacheErr";

            break;

        default:

            goto die;

        }

        break;

    case 28:

        switch (sel) {

        case 0:

        case 2:

        case 4:

        case 6:

            gen_op_mfc0_taglo();

            rn = "TagLo";

            break;

        case 1:

        case 3:

        case 5:

        case 7:

            gen_op_mfc0_datalo();

            rn = "DataLo";

            break;

        default:

            goto die;

        }

        break;

    case 29:

        switch (sel) {

        case 0:

        case 2:

        case 4:

        case 6:

            gen_op_mfc0_taghi();

            rn = "TagHi";

            break;

        case 1:

        case 3:

        case 5:

        case 7:

            gen_op_mfc0_datahi();

            rn = "DataHi";

            break;

        default:

            goto die;

        }

        break;

    case 30:

        switch (sel) {

        case 0:

            gen_op_mfc0_errorepc();

            rn = "ErrorEPC";

            break;

        default:

            goto die;

        }

        break;

    case 31:

        switch (sel) {

        case 0:

            gen_op_mfc0_desave(); /* EJTAG support */

            rn = "DESAVE";

            break;

        default:

            goto die;

        }

        break;

    default:

       goto die;

    }

#if defined MIPS_DEBUG_DISAS

    if (loglevel & CPU_LOG_TB_IN_ASM) {

        fprintf(logfile, "mfc0 %s (reg %d sel %d)\n",

                rn, reg, sel);

    }

#endif

    return;

die:

#if defined MIPS_DEBUG_DISAS

    if (loglevel & CPU_LOG_TB_IN_ASM) {

        fprintf(logfile, "mfc0 %s (reg %d sel %d)\n",

                rn, reg, sel);

    }

#endif

    generate_exception(ctx, EXCP_RI);

}


intptr_t (*checkasm_check_func(intptr_t (*func)(), const char *name, ...))()

{

    char name_buf[256];

    intptr_t (*ref)() = func;

    CheckasmFuncVersion *v;

    int name_length;

    va_list arg;

    va_start(arg, name);

    name_length = vsnprintf(name_buf, sizeof(name_buf), name, arg);

    va_end(arg);

    if (!func || name_length <= 0 || name_length >= sizeof(name_buf))

        return NULL;

    state.current_func = get_func(name_buf, name_length);

    v = &state.current_func->versions;

    if (v->func) {

        CheckasmFuncVersion *prev;

        do {

            /* Only test functions that haven't already been tested */

            if (v->func == func)

                return NULL;

            if (v->ok)

                ref = v->func;

            prev = v;

        } while ((v = v->next));

        v = prev->next = checkasm_malloc(sizeof(CheckasmFuncVersion));

    }

    v->func = func;

    v->ok = 1;

    v->cpu = state.cpu_flag;

    state.current_func_ver = v;

    if (state.cpu_flag)

        state.num_checked++;

    return ref;

}


static hwaddr vfio_container_granularity(VFIOContainer *container)

{

    return (hwaddr)1 << ctz64(container->iova_pgsizes);

}


void apic_init_reset(DeviceState *dev)

{

    APICCommonState *s = APIC_COMMON(dev);

    APICCommonClass *info = APIC_COMMON_GET_CLASS(s);

    int i;

    if (!s) {

        return;

    }

    s->tpr = 0;

    s->spurious_vec = 0xff;

    s->log_dest = 0;

    s->dest_mode = 0xf;

    memset(s->isr, 0, sizeof(s->isr));

    memset(s->tmr, 0, sizeof(s->tmr));

    memset(s->irr, 0, sizeof(s->irr));

    for (i = 0; i < APIC_LVT_NB; i++) {

        s->lvt[i] = APIC_LVT_MASKED;

    }

    s->esr = 0;

    memset(s->icr, 0, sizeof(s->icr));

    s->divide_conf = 0;

    s->count_shift = 0;

    s->initial_count = 0;

    s->initial_count_load_time = 0;

    s->next_time = 0;

    s->wait_for_sipi = !cpu_is_bsp(s->cpu);

    if (s->timer) {

        timer_del(s->timer);

    }

    s->timer_expiry = -1;

    if (info->reset) {

        info->reset(s);

    }

}


static void gen_msa(CPUMIPSState *env, DisasContext *ctx)

{

    uint32_t opcode = ctx->opcode;

    check_insn(ctx, ASE_MSA);

    check_msa_access(ctx);

    switch (MASK_MSA_MINOR(opcode)) {

    case OPC_MSA_I8_00:

    case OPC_MSA_I8_01:

    case OPC_MSA_I8_02:

        gen_msa_i8(env, ctx);

        break;

    case OPC_MSA_I5_06:

    case OPC_MSA_I5_07:

        gen_msa_i5(env, ctx);

        break;

    case OPC_MSA_BIT_09:

    case OPC_MSA_BIT_0A:

        gen_msa_bit(env, ctx);

        break;

    case OPC_MSA_3R_0D:

    case OPC_MSA_3R_0E:

    case OPC_MSA_3R_0F:

    case OPC_MSA_3R_10:

    case OPC_MSA_3R_11:

    case OPC_MSA_3R_12:

    case OPC_MSA_3R_13:

    case OPC_MSA_3R_14:

    case OPC_MSA_3R_15:

        gen_msa_3r(env, ctx);

        break;

    case OPC_MSA_ELM:

        gen_msa_elm(env, ctx);

        break;

    case OPC_MSA_3RF_1A:

    case OPC_MSA_3RF_1B:

    case OPC_MSA_3RF_1C:

        gen_msa_3rf(env, ctx);

        break;

    case OPC_MSA_VEC:

        gen_msa_vec(env, ctx);

        break;

    case OPC_LD_B:

    case OPC_LD_H:

    case OPC_LD_W:

    case OPC_LD_D:

    case OPC_ST_B:

    case OPC_ST_H:

    case OPC_ST_W:

    case OPC_ST_D:

        {

            int32_t s10 = sextract32(ctx->opcode, 16, 10);

            uint8_t rs = (ctx->opcode >> 11) & 0x1f;

            uint8_t wd = (ctx->opcode >> 6) & 0x1f;

            uint8_t df = (ctx->opcode >> 0) & 0x3;

            TCGv_i32 tdf = tcg_const_i32(df);

            TCGv_i32 twd = tcg_const_i32(wd);

            TCGv_i32 trs = tcg_const_i32(rs);

            TCGv_i32 ts10 = tcg_const_i32(s10);

            switch (MASK_MSA_MINOR(opcode)) {

            case OPC_LD_B:

            case OPC_LD_H:

            case OPC_LD_W:

            case OPC_LD_D:

                save_cpu_state(ctx, 1);

                gen_helper_msa_ld_df(cpu_env, tdf, twd, trs, ts10);

                break;

            case OPC_ST_B:

            case OPC_ST_H:

            case OPC_ST_W:

            case OPC_ST_D:

                save_cpu_state(ctx, 1);

                gen_helper_msa_st_df(cpu_env, tdf, twd, trs, ts10);

                break;

            }

            tcg_temp_free_i32(twd);

            tcg_temp_free_i32(tdf);

            tcg_temp_free_i32(trs);

            tcg_temp_free_i32(ts10);

        }

        break;

    default:

        MIPS_INVAL("MSA instruction");

        generate_exception(ctx, EXCP_RI);

        break;

    }

}


int bdrv_snapshot_load_tmp(BlockDriverState *bs,

        const char *snapshot_name)

{

    BlockDriver *drv = bs->drv;

    if (!drv) {

        return -ENOMEDIUM;

    }

    if (!bs->read_only) {

        return -EINVAL;

    }

    if (drv->bdrv_snapshot_load_tmp) {

        return drv->bdrv_snapshot_load_tmp(bs, snapshot_name);

    }

    return -ENOTSUP;

}


static void io_watch_poll_finalize(GSource *source)

{

    IOWatchPoll *iwp = io_watch_poll_from_source(source);

    g_source_destroy(iwp->src);

    g_source_unref(iwp->src);

    iwp->src = NULL;

}


static void omap_pin_cfg_init(MemoryRegion *system_memory,

                target_phys_addr_t base,

                struct omap_mpu_state_s *mpu)

{

    memory_region_init_io(&mpu->pin_cfg_iomem, &omap_pin_cfg_ops, mpu,

                          "omap-pin-cfg", 0x800);

    memory_region_add_subregion(system_memory, base, &mpu->pin_cfg_iomem);

    omap_pin_cfg_reset(mpu);

}


void cpu_x86_inject_mce(CPUState *cenv, int bank, uint64_t status,

                        uint64_t mcg_status, uint64_t addr, uint64_t misc,

                        int broadcast)

{

    unsigned bank_num = cenv->mcg_cap & 0xff;

    CPUState *env;

    int flag = 0;

    if (bank >= bank_num || !(status & MCI_STATUS_VAL)) {

        return;

    }

    if (broadcast) {

        if (!cpu_x86_support_mca_broadcast(cenv)) {

            fprintf(stderr, "Current CPU does not support broadcast\n");

            return;

        }

    }

    if (kvm_enabled()) {

        if (broadcast) {

            flag |= MCE_BROADCAST;

        }

        kvm_inject_x86_mce(cenv, bank, status, mcg_status, addr, misc, flag);

    } else {

        qemu_inject_x86_mce(cenv, bank, status, mcg_status, addr, misc);

        if (broadcast) {

            for (env = first_cpu; env != NULL; env = env->next_cpu) {

                if (cenv == env) {

                    continue;

                }

                qemu_inject_x86_mce(env, 1, MCI_STATUS_VAL | MCI_STATUS_UC,

                                    MCG_STATUS_MCIP | MCG_STATUS_RIPV, 0, 0);

            }

        }

    }

}


static void psy_3gpp_analyze(FFPsyContext *ctx, int channel,

                             const float *coefs, const FFPsyWindowInfo *wi)

{

    AacPsyContext *pctx = (AacPsyContext*) ctx->model_priv_data;

    AacPsyChannel *pch  = &pctx->ch[channel];

    int start = 0;

    int i, w, g;

    const int num_bands       = ctx->num_bands[wi->num_windows == 8];

    const uint8_t* band_sizes = ctx->bands[wi->num_windows == 8];

    AacPsyCoeffs *coeffs     = &pctx->psy_coef[wi->num_windows == 8];

    //calculate energies, initial thresholds and related values - 5.4.2 "Threshold Calculation"

    for (w = 0; w < wi->num_windows*16; w += 16) {

        for (g = 0; g < num_bands; g++) {

            AacPsyBand *band = &pch->band[w+g];

            band->energy = 0.0f;

            for (i = 0; i < band_sizes[g]; i++)

                band->energy += coefs[start+i] * coefs[start+i];

            band->thr     = band->energy * 0.001258925f;

            start        += band_sizes[g];

            ctx->psy_bands[channel*PSY_MAX_BANDS+w+g].energy = band->energy;

        }

    }

    //modify thresholds - spread, threshold in quiet - 5.4.3 "Spreaded Energy Calculation"

    for (w = 0; w < wi->num_windows*16; w += 16) {

        AacPsyBand *band = &pch->band[w];

        for (g = 1; g < num_bands; g++)

            band[g].thr = FFMAX(band[g].thr, band[g-1].thr * coeffs->spread_hi [g]);

        for (g = num_bands - 2; g >= 0; g--)

            band[g].thr = FFMAX(band[g].thr, band[g+1].thr * coeffs->spread_low[g]);

        for (g = 0; g < num_bands; g++) {

            band[g].thr_quiet = band[g].thr = FFMAX(band[g].thr, coeffs->ath[g]);

            if (!(wi->window_type[0] == LONG_STOP_SEQUENCE || (wi->window_type[1] == LONG_START_SEQUENCE && !w)))

                band[g].thr = FFMAX(PSY_3GPP_RPEMIN*band[g].thr, FFMIN(band[g].thr,

                                    PSY_3GPP_RPELEV*pch->prev_band[w+g].thr_quiet));

            ctx->psy_bands[channel*PSY_MAX_BANDS+w+g].threshold = band[g].thr;

        }

    }

    memcpy(pch->prev_band, pch->band, sizeof(pch->band));

}


static void dbdma_writel (void *opaque,

                          target_phys_addr_t addr, uint32_t value)

{

    int channel = addr >> DBDMA_CHANNEL_SHIFT;

    DBDMA_channel *ch = (DBDMA_channel *)opaque + channel;

    int reg = (addr - (channel << DBDMA_CHANNEL_SHIFT)) >> 2;

    DBDMA_DPRINTF("writel 0x" TARGET_FMT_plx " <= 0x%08x\n", addr, value);

    DBDMA_DPRINTF("channel 0x%x reg 0x%x\n",

                  (uint32_t)addr >> DBDMA_CHANNEL_SHIFT, reg);

    /* cmdptr cannot be modified if channel is RUN or ACTIVE */

    if (reg == DBDMA_CMDPTR_LO &&

        (ch->regs[DBDMA_STATUS] & cpu_to_be32(RUN | ACTIVE)))

	return;

    ch->regs[reg] = value;

    switch(reg) {

    case DBDMA_CONTROL:

        dbdma_control_write(ch);

        break;

    case DBDMA_CMDPTR_LO:

        /* 16-byte aligned */

        ch->regs[DBDMA_CMDPTR_LO] &= cpu_to_be32(~0xf);

        dbdma_cmdptr_load(ch);

        break;

    case DBDMA_STATUS:

    case DBDMA_INTR_SEL:

    case DBDMA_BRANCH_SEL:

    case DBDMA_WAIT_SEL:

        /* nothing to do */

        break;

    case DBDMA_XFER_MODE:

    case DBDMA_CMDPTR_HI:

    case DBDMA_DATA2PTR_HI:

    case DBDMA_DATA2PTR_LO:

    case DBDMA_ADDRESS_HI:

    case DBDMA_BRANCH_ADDR_HI:

    case DBDMA_RES1:

    case DBDMA_RES2:

    case DBDMA_RES3:

    case DBDMA_RES4:

        /* unused */

        break;

    }

}


static uint64_t omap_os_timer_read(void *opaque, target_phys_addr_t addr,

                                   unsigned size)

{

    struct omap_32khz_timer_s *s = (struct omap_32khz_timer_s *) opaque;

    int offset = addr & OMAP_MPUI_REG_MASK;

    if (size != 4) {

        return omap_badwidth_read32(opaque, addr);

    }

    switch (offset) {

    case 0x00:	/* TVR */

        return s->timer.reset_val;

    case 0x04:	/* TCR */

        return omap_timer_read(&s->timer);

    case 0x08:	/* CR */

        return (s->timer.ar << 3) | (s->timer.it_ena << 2) | s->timer.st;

    default:

        break;

    }

    OMAP_BAD_REG(addr);

    return 0;

}


static uint64_t ahci_mem_read(void *opaque, target_phys_addr_t addr,

                              unsigned size)

{

    AHCIState *s = opaque;

    uint32_t val = 0;

    if (addr < AHCI_GENERIC_HOST_CONTROL_REGS_MAX_ADDR) {

        switch (addr) {

        case HOST_CAP:

            val = s->control_regs.cap;

            break;

        case HOST_CTL:

            val = s->control_regs.ghc;

            break;

        case HOST_IRQ_STAT:

            val = s->control_regs.irqstatus;

            break;

        case HOST_PORTS_IMPL:

            val = s->control_regs.impl;

            break;

        case HOST_VERSION:

            val = s->control_regs.version;

            break;

        }

        DPRINTF(-1, "(addr 0x%08X), val 0x%08X\n", (unsigned) addr, val);

    } else if ((addr >= AHCI_PORT_REGS_START_ADDR) &&

               (addr < (AHCI_PORT_REGS_START_ADDR +

                (s->ports * AHCI_PORT_ADDR_OFFSET_LEN)))) {

        val = ahci_port_read(s, (addr - AHCI_PORT_REGS_START_ADDR) >> 7,

                             addr & AHCI_PORT_ADDR_OFFSET_MASK);

    }

    return val;

}


static inline uint16_t get_hwc_color(SM501State *state, int crt, int index)

{

    uint32_t color_reg = 0;

    uint16_t color_565 = 0;

    if (index == 0) {

        return 0;

    }

    switch (index) {

    case 1:

    case 2:

        color_reg = crt ? state->dc_crt_hwc_color_1_2

                        : state->dc_panel_hwc_color_1_2;

        break;

    case 3:

        color_reg = crt ? state->dc_crt_hwc_color_3

                        : state->dc_panel_hwc_color_3;

        break;

    default:

        printf("invalid hw cursor color.\n");

        abort();

    }

    switch (index) {

    case 1:

    case 3:

        color_565 = (uint16_t)(color_reg & 0xFFFF);

        break;

    case 2:

        color_565 = (uint16_t)((color_reg >> 16) & 0xFFFF);

        break;

    }

    return color_565;

}


mlt_compensate_output(COOKContext *q, float *decode_buffer,

                      cook_gains *gains, float *previous_buffer,

                      int16_t *out, int chan)

{

    int j;

    cook_imlt(q, decode_buffer, q->mono_mdct_output);

    gain_compensate(q, gains, previous_buffer);

    /* Clip and convert floats to 16 bits.

     */

    for (j = 0; j < q->samples_per_channel; j++) {

        out[chan + q->nb_channels * j] =

          av_clip(lrintf(q->mono_mdct_output[j]), -32768, 32767);

    }

}


int main(int argc, char **argv){

    int in_sample_rate, out_sample_rate, ch ,i, flush_count;

    uint64_t in_ch_layout, out_ch_layout;

    enum AVSampleFormat in_sample_fmt, out_sample_fmt;

    uint8_t array_in[SAMPLES*8*8];

    uint8_t array_mid[SAMPLES*8*8*3];

    uint8_t array_out[SAMPLES*8*8+100];

    uint8_t *ain[SWR_CH_MAX];

    uint8_t *aout[SWR_CH_MAX];

    uint8_t *amid[SWR_CH_MAX];

    int flush_i=0;

    int mode;

    int num_tests = 10000;

    uint32_t seed = 0;

    uint32_t rand_seed = 0;

    int remaining_tests[FF_ARRAY_ELEMS(rates) * FF_ARRAY_ELEMS(layouts) * FF_ARRAY_ELEMS(formats) * FF_ARRAY_ELEMS(layouts) * FF_ARRAY_ELEMS(formats)];

    int max_tests = FF_ARRAY_ELEMS(remaining_tests);

    int test;

    int specific_test= -1;

    struct SwrContext * forw_ctx= NULL;

    struct SwrContext *backw_ctx= NULL;

    if (argc > 1) {

        if (!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")) {

            av_log(NULL, AV_LOG_INFO, "Usage: swresample-test [<num_tests>[ <test>]]  \n"

                   "num_tests           Default is %d\n", num_tests);

            return 0;

        }

        num_tests = strtol(argv[1], NULL, 0);

        if(num_tests < 0) {

            num_tests = -num_tests;

            rand_seed = time(0);

        }

        if(num_tests<= 0 || num_tests>max_tests)

            num_tests = max_tests;

        if(argc > 2) {

            specific_test = strtol(argv[1], NULL, 0);

        }

    }

    for(i=0; i<max_tests; i++)

        remaining_tests[i] = i;

    for(test=0; test<num_tests; test++){

        unsigned r;

        uint_rand(seed);

        r = (seed * (uint64_t)(max_tests - test)) >>32;

        FFSWAP(int, remaining_tests[r], remaining_tests[max_tests - test - 1]);

    }

    qsort(remaining_tests + max_tests - num_tests, num_tests, sizeof(remaining_tests[0]), (void*)cmp);

    in_sample_rate=16000;

    for(test=0; test<num_tests; test++){

        char  in_layout_string[256];

        char out_layout_string[256];

        unsigned vector= remaining_tests[max_tests - test - 1];

        int in_ch_count;

        int out_count, mid_count, out_ch_count;

        in_ch_layout    = layouts[vector % FF_ARRAY_ELEMS(layouts)]; vector /= FF_ARRAY_ELEMS(layouts);

        out_ch_layout   = layouts[vector % FF_ARRAY_ELEMS(layouts)]; vector /= FF_ARRAY_ELEMS(layouts);

        in_sample_fmt   = formats[vector % FF_ARRAY_ELEMS(formats)]; vector /= FF_ARRAY_ELEMS(formats);

        out_sample_fmt  = formats[vector % FF_ARRAY_ELEMS(formats)]; vector /= FF_ARRAY_ELEMS(formats);

        out_sample_rate = rates  [vector % FF_ARRAY_ELEMS(rates  )]; vector /= FF_ARRAY_ELEMS(rates);

        av_assert0(!vector);

        if(specific_test == 0){

            if(out_sample_rate != in_sample_rate || in_ch_layout != out_ch_layout)

                continue;

        }

        in_ch_count= av_get_channel_layout_nb_channels(in_ch_layout);

        out_ch_count= av_get_channel_layout_nb_channels(out_ch_layout);

        av_get_channel_layout_string( in_layout_string, sizeof( in_layout_string),  in_ch_count,  in_ch_layout);

        av_get_channel_layout_string(out_layout_string, sizeof(out_layout_string), out_ch_count, out_ch_layout);

        fprintf(stderr, "TEST: %s->%s, rate:%5d->%5d, fmt:%s->%s\n",

                in_layout_string, out_layout_string,

                in_sample_rate, out_sample_rate,

                av_get_sample_fmt_name(in_sample_fmt), av_get_sample_fmt_name(out_sample_fmt));

        forw_ctx  = swr_alloc_set_opts(forw_ctx, out_ch_layout, out_sample_fmt,  out_sample_rate,

                                                    in_ch_layout,  in_sample_fmt,  in_sample_rate,

                                        0, 0);

        backw_ctx = swr_alloc_set_opts(backw_ctx, in_ch_layout,  in_sample_fmt,             in_sample_rate,

                                                    out_ch_layout, out_sample_fmt, out_sample_rate,

                                        0, 0);

        if(swr_init( forw_ctx) < 0)

            fprintf(stderr, "swr_init(->) failed\n");

        if(swr_init(backw_ctx) < 0)

            fprintf(stderr, "swr_init(<-) failed\n");

        if(!forw_ctx)

            fprintf(stderr, "Failed to init forw_cts\n");

        if(!backw_ctx)

            fprintf(stderr, "Failed to init backw_ctx\n");

                //FIXME test planar

        setup_array(ain , array_in ,  in_sample_fmt,   SAMPLES);

        setup_array(amid, array_mid, out_sample_fmt, 3*SAMPLES);

        setup_array(aout, array_out,  in_sample_fmt           ,   SAMPLES);

#if 0

        for(ch=0; ch<in_ch_count; ch++){

            for(i=0; i<SAMPLES; i++)

                set(ain, ch, i, in_ch_count, in_sample_fmt, sin(i*i*3/SAMPLES));

        }

#else

        audiogen(ain, in_sample_fmt, in_ch_count, SAMPLES/6+1, SAMPLES);

#endif

        mode = uint_rand(rand_seed) % 3;

        if(mode==0 /*|| out_sample_rate == in_sample_rate*/) {

            mid_count= swr_convert(forw_ctx, amid, 3*SAMPLES, (const uint8_t **)ain, SAMPLES);

        } else if(mode==1){

            mid_count= swr_convert(forw_ctx, amid,         0, (const uint8_t **)ain, SAMPLES);

            mid_count+=swr_convert(forw_ctx, amid, 3*SAMPLES, (const uint8_t **)ain,       0);

        } else {

            int tmp_count;

            mid_count= swr_convert(forw_ctx, amid,         0, (const uint8_t **)ain,       1);

            av_assert0(mid_count==0);

            shift(ain,  1, in_ch_count, in_sample_fmt);

            mid_count+=swr_convert(forw_ctx, amid, 3*SAMPLES, (const uint8_t **)ain,       0);

            shift(amid,  mid_count, out_ch_count, out_sample_fmt); tmp_count = mid_count;

            mid_count+=swr_convert(forw_ctx, amid,         2, (const uint8_t **)ain,       2);

            shift(amid,  mid_count-tmp_count, out_ch_count, out_sample_fmt); tmp_count = mid_count;

            shift(ain,  2, in_ch_count, in_sample_fmt);

            mid_count+=swr_convert(forw_ctx, amid,         1, (const uint8_t **)ain, SAMPLES-3);

            shift(amid,  mid_count-tmp_count, out_ch_count, out_sample_fmt); tmp_count = mid_count;

            shift(ain, -3, in_ch_count, in_sample_fmt);

            mid_count+=swr_convert(forw_ctx, amid, 3*SAMPLES, (const uint8_t **)ain,       0);

            shift(amid,  -tmp_count, out_ch_count, out_sample_fmt);

        }

        out_count= swr_convert(backw_ctx,aout, SAMPLES, (const uint8_t **)amid, mid_count);

        for(ch=0; ch<in_ch_count; ch++){

            double sse, maxdiff=0;

            double sum_a= 0;

            double sum_b= 0;

            double sum_aa= 0;

            double sum_bb= 0;

            double sum_ab= 0;

            for(i=0; i<out_count; i++){

                double a= get(ain , ch, i, in_ch_count, in_sample_fmt);

                double b= get(aout, ch, i, in_ch_count, in_sample_fmt);

                sum_a += a;

                sum_b += b;

                sum_aa+= a*a;

                sum_bb+= b*b;

                sum_ab+= a*b;

                maxdiff= FFMAX(maxdiff, FFABS(a-b));

            }

            sse= sum_aa + sum_bb - 2*sum_ab;

            if(sse < 0 && sse > -0.00001) sse=0; //fix rounding error

            fprintf(stderr, "[e:%f c:%f max:%f] len:%5d\n", sqrt(sse/out_count), sum_ab/(sqrt(sum_aa*sum_bb)), maxdiff, out_count);

        }

        flush_i++;

        flush_i%=21;

        flush_count = swr_convert(backw_ctx,aout, flush_i, 0, 0);

        shift(aout,  flush_i, in_ch_count, in_sample_fmt);

        flush_count+= swr_convert(backw_ctx,aout, SAMPLES-flush_i, 0, 0);

        shift(aout, -flush_i, in_ch_count, in_sample_fmt);

        if(flush_count){

            for(ch=0; ch<in_ch_count; ch++){

                double sse, maxdiff=0;

                double sum_a= 0;

                double sum_b= 0;

                double sum_aa= 0;

                double sum_bb= 0;

                double sum_ab= 0;

                for(i=0; i<flush_count; i++){

                    double a= get(ain , ch, i+out_count, in_ch_count, in_sample_fmt);

                    double b= get(aout, ch, i, in_ch_count, in_sample_fmt);

                    sum_a += a;

                    sum_b += b;

                    sum_aa+= a*a;

                    sum_bb+= b*b;

                    sum_ab+= a*b;

                    maxdiff= FFMAX(maxdiff, FFABS(a-b));

                }

                sse= sum_aa + sum_bb - 2*sum_ab;

                if(sse < 0 && sse > -0.00001) sse=0; //fix rounding error

                fprintf(stderr, "[e:%f c:%f max:%f] len:%5d F:%3d\n", sqrt(sse/flush_count), sum_ab/(sqrt(sum_aa*sum_bb)), maxdiff, flush_count, flush_i);

            }

        }

        fprintf(stderr, "\n");

    }

    return 0;

}


void MPV_decode_mb_internal(MpegEncContext *s, DCTELEM block[12][64],

                            int is_mpeg12)

{

    const int mb_xy = s->mb_y * s->mb_stride + s->mb_x;

    if(CONFIG_MPEG_XVMC_DECODER && s->avctx->xvmc_acceleration){

        ff_xvmc_decode_mb(s);//xvmc uses pblocks

        return;

    }

    if(s->avctx->debug&FF_DEBUG_DCT_COEFF) {

       /* save DCT coefficients */

       int i,j;

       DCTELEM *dct = &s->current_picture.f.dct_coeff[mb_xy * 64 * 6];

       av_log(s->avctx, AV_LOG_DEBUG, "DCT coeffs of MB at %dx%d:\n", s->mb_x, s->mb_y);

       for(i=0; i<6; i++){

           for(j=0; j<64; j++){

               *dct++ = block[i][s->dsp.idct_permutation[j]];

               av_log(s->avctx, AV_LOG_DEBUG, "%5d", dct[-1]);

           }

           av_log(s->avctx, AV_LOG_DEBUG, "\n");

       }

    }

    s->current_picture.f.qscale_table[mb_xy] = s->qscale;

    /* update DC predictors for P macroblocks */

    if (!s->mb_intra) {

        if (!is_mpeg12 && (s->h263_pred || s->h263_aic)) {

            if(s->mbintra_table[mb_xy])

                ff_clean_intra_table_entries(s);

        } else {

            s->last_dc[0] =

            s->last_dc[1] =

            s->last_dc[2] = 128 << s->intra_dc_precision;

        }

    }

    else if (!is_mpeg12 && (s->h263_pred || s->h263_aic))

        s->mbintra_table[mb_xy]=1;

    if ((s->flags&CODEC_FLAG_PSNR) || !(s->encoding && (s->intra_only || s->pict_type==AV_PICTURE_TYPE_B) && s->avctx->mb_decision != FF_MB_DECISION_RD)) { //FIXME precalc

        uint8_t *dest_y, *dest_cb, *dest_cr;

        int dct_linesize, dct_offset;

        op_pixels_func (*op_pix)[4];

        qpel_mc_func (*op_qpix)[16];

        const int linesize   = s->current_picture.f.linesize[0]; //not s->linesize as this would be wrong for field pics

        const int uvlinesize = s->current_picture.f.linesize[1];

        const int readable= s->pict_type != AV_PICTURE_TYPE_B || s->encoding || s->avctx->draw_horiz_band;

        const int block_size = 8;

        /* avoid copy if macroblock skipped in last frame too */

        /* skip only during decoding as we might trash the buffers during encoding a bit */

        if(!s->encoding){

            uint8_t *mbskip_ptr = &s->mbskip_table[mb_xy];

            if (s->mb_skipped) {

                s->mb_skipped= 0;

                assert(s->pict_type!=AV_PICTURE_TYPE_I);

                *mbskip_ptr = 1;

            } else if(!s->current_picture.f.reference) {

                *mbskip_ptr = 1;

            } else{

                *mbskip_ptr = 0; /* not skipped */

            }

        }

        dct_linesize = linesize << s->interlaced_dct;

        dct_offset   = s->interlaced_dct ? linesize : linesize * block_size;

        if(readable){

            dest_y=  s->dest[0];

            dest_cb= s->dest[1];

            dest_cr= s->dest[2];

        }else{

            dest_y = s->b_scratchpad;

            dest_cb= s->b_scratchpad+16*linesize;

            dest_cr= s->b_scratchpad+32*linesize;

        }

        if (!s->mb_intra) {

            /* motion handling */

            /* decoding or more than one mb_type (MC was already done otherwise) */

            if(!s->encoding){

                if(HAVE_THREADS && s->avctx->active_thread_type&FF_THREAD_FRAME) {

                    if (s->mv_dir & MV_DIR_FORWARD) {

                        ff_thread_await_progress(&s->last_picture_ptr->f,

                                                 ff_MPV_lowest_referenced_row(s, 0),

                                                 0);

                    }

                    if (s->mv_dir & MV_DIR_BACKWARD) {

                        ff_thread_await_progress(&s->next_picture_ptr->f,

                                                 ff_MPV_lowest_referenced_row(s, 1),

                                                 0);

                    }

                }

                op_qpix= s->me.qpel_put;

                if ((!s->no_rounding) || s->pict_type==AV_PICTURE_TYPE_B){

                    op_pix = s->dsp.put_pixels_tab;

                }else{

                    op_pix = s->dsp.put_no_rnd_pixels_tab;

                }

                if (s->mv_dir & MV_DIR_FORWARD) {

                    MPV_motion(s, dest_y, dest_cb, dest_cr, 0, s->last_picture.f.data, op_pix, op_qpix);

                    op_pix = s->dsp.avg_pixels_tab;

                    op_qpix= s->me.qpel_avg;

                }

                if (s->mv_dir & MV_DIR_BACKWARD) {

                    MPV_motion(s, dest_y, dest_cb, dest_cr, 1, s->next_picture.f.data, op_pix, op_qpix);

                }

            }

            /* skip dequant / idct if we are really late ;) */

            if(s->avctx->skip_idct){

                if(  (s->avctx->skip_idct >= AVDISCARD_NONREF && s->pict_type == AV_PICTURE_TYPE_B)

                   ||(s->avctx->skip_idct >= AVDISCARD_NONKEY && s->pict_type != AV_PICTURE_TYPE_I)

                   || s->avctx->skip_idct >= AVDISCARD_ALL)

                    goto skip_idct;

            }

            /* add dct residue */

            if(s->encoding || !(   s->msmpeg4_version || s->codec_id==CODEC_ID_MPEG1VIDEO || s->codec_id==CODEC_ID_MPEG2VIDEO

                                || (s->codec_id==CODEC_ID_MPEG4 && !s->mpeg_quant))){

                add_dequant_dct(s, block[0], 0, dest_y                          , dct_linesize, s->qscale);

                add_dequant_dct(s, block[1], 1, dest_y              + block_size, dct_linesize, s->qscale);

                add_dequant_dct(s, block[2], 2, dest_y + dct_offset             , dct_linesize, s->qscale);

                add_dequant_dct(s, block[3], 3, dest_y + dct_offset + block_size, dct_linesize, s->qscale);

                if(!CONFIG_GRAY || !(s->flags&CODEC_FLAG_GRAY)){

                    if (s->chroma_y_shift){

                        add_dequant_dct(s, block[4], 4, dest_cb, uvlinesize, s->chroma_qscale);

                        add_dequant_dct(s, block[5], 5, dest_cr, uvlinesize, s->chroma_qscale);

                    }else{

                        dct_linesize >>= 1;

                        dct_offset >>=1;

                        add_dequant_dct(s, block[4], 4, dest_cb,              dct_linesize, s->chroma_qscale);

                        add_dequant_dct(s, block[5], 5, dest_cr,              dct_linesize, s->chroma_qscale);

                        add_dequant_dct(s, block[6], 6, dest_cb + dct_offset, dct_linesize, s->chroma_qscale);

                        add_dequant_dct(s, block[7], 7, dest_cr + dct_offset, dct_linesize, s->chroma_qscale);

                    }

                }

            } else if(is_mpeg12 || (s->codec_id != CODEC_ID_WMV2)){

                add_dct(s, block[0], 0, dest_y                          , dct_linesize);

                add_dct(s, block[1], 1, dest_y              + block_size, dct_linesize);

                add_dct(s, block[2], 2, dest_y + dct_offset             , dct_linesize);

                add_dct(s, block[3], 3, dest_y + dct_offset + block_size, dct_linesize);

                if(!CONFIG_GRAY || !(s->flags&CODEC_FLAG_GRAY)){

                    if(s->chroma_y_shift){//Chroma420

                        add_dct(s, block[4], 4, dest_cb, uvlinesize);

                        add_dct(s, block[5], 5, dest_cr, uvlinesize);

                    }else{

                        //chroma422

                        dct_linesize = uvlinesize << s->interlaced_dct;

                        dct_offset   = s->interlaced_dct ? uvlinesize : uvlinesize*block_size;

                        add_dct(s, block[4], 4, dest_cb, dct_linesize);

                        add_dct(s, block[5], 5, dest_cr, dct_linesize);

                        add_dct(s, block[6], 6, dest_cb+dct_offset, dct_linesize);

                        add_dct(s, block[7], 7, dest_cr+dct_offset, dct_linesize);

                        if(!s->chroma_x_shift){//Chroma444

                            add_dct(s, block[8], 8, dest_cb+block_size, dct_linesize);

                            add_dct(s, block[9], 9, dest_cr+block_size, dct_linesize);

                            add_dct(s, block[10], 10, dest_cb+block_size+dct_offset, dct_linesize);

                            add_dct(s, block[11], 11, dest_cr+block_size+dct_offset, dct_linesize);

                        }

                    }

                }//fi gray

            }

            else if (CONFIG_WMV2_DECODER || CONFIG_WMV2_ENCODER) {

                ff_wmv2_add_mb(s, block, dest_y, dest_cb, dest_cr);

            }

        } else {

            /* dct only in intra block */

            if(s->encoding || !(s->codec_id==CODEC_ID_MPEG1VIDEO || s->codec_id==CODEC_ID_MPEG2VIDEO)){

                put_dct(s, block[0], 0, dest_y                          , dct_linesize, s->qscale);

                put_dct(s, block[1], 1, dest_y              + block_size, dct_linesize, s->qscale);

                put_dct(s, block[2], 2, dest_y + dct_offset             , dct_linesize, s->qscale);

                put_dct(s, block[3], 3, dest_y + dct_offset + block_size, dct_linesize, s->qscale);

                if(!CONFIG_GRAY || !(s->flags&CODEC_FLAG_GRAY)){

                    if(s->chroma_y_shift){

                        put_dct(s, block[4], 4, dest_cb, uvlinesize, s->chroma_qscale);

                        put_dct(s, block[5], 5, dest_cr, uvlinesize, s->chroma_qscale);

                    }else{

                        dct_offset >>=1;

                        dct_linesize >>=1;

                        put_dct(s, block[4], 4, dest_cb,              dct_linesize, s->chroma_qscale);

                        put_dct(s, block[5], 5, dest_cr,              dct_linesize, s->chroma_qscale);

                        put_dct(s, block[6], 6, dest_cb + dct_offset, dct_linesize, s->chroma_qscale);

                        put_dct(s, block[7], 7, dest_cr + dct_offset, dct_linesize, s->chroma_qscale);

                    }

                }

            }else{

                s->dsp.idct_put(dest_y                          , dct_linesize, block[0]);

                s->dsp.idct_put(dest_y              + block_size, dct_linesize, block[1]);

                s->dsp.idct_put(dest_y + dct_offset             , dct_linesize, block[2]);

                s->dsp.idct_put(dest_y + dct_offset + block_size, dct_linesize, block[3]);

                if(!CONFIG_GRAY || !(s->flags&CODEC_FLAG_GRAY)){

                    if(s->chroma_y_shift){

                        s->dsp.idct_put(dest_cb, uvlinesize, block[4]);

                        s->dsp.idct_put(dest_cr, uvlinesize, block[5]);

                    }else{

                        dct_linesize = uvlinesize << s->interlaced_dct;

                        dct_offset   = s->interlaced_dct? uvlinesize : uvlinesize*block_size;

                        s->dsp.idct_put(dest_cb,              dct_linesize, block[4]);

                        s->dsp.idct_put(dest_cr,              dct_linesize, block[5]);

                        s->dsp.idct_put(dest_cb + dct_offset, dct_linesize, block[6]);

                        s->dsp.idct_put(dest_cr + dct_offset, dct_linesize, block[7]);

                        if(!s->chroma_x_shift){//Chroma444

                            s->dsp.idct_put(dest_cb + block_size,              dct_linesize, block[8]);

                            s->dsp.idct_put(dest_cr + block_size,              dct_linesize, block[9]);

                            s->dsp.idct_put(dest_cb + block_size + dct_offset, dct_linesize, block[10]);

                            s->dsp.idct_put(dest_cr + block_size + dct_offset, dct_linesize, block[11]);

                        }

                    }

                }//gray

            }

        }

skip_idct:

        if(!readable){

            s->dsp.put_pixels_tab[0][0](s->dest[0], dest_y ,   linesize,16);

            s->dsp.put_pixels_tab[s->chroma_x_shift][0](s->dest[1], dest_cb, uvlinesize,16 >> s->chroma_y_shift);

            s->dsp.put_pixels_tab[s->chroma_x_shift][0](s->dest[2], dest_cr, uvlinesize,16 >> s->chroma_y_shift);

        }

    }

}


int ff_h264_decode_ref_pic_marking(H264Context *h, GetBitContext *gb,

                                   int first_slice)

{

    int i, ret;

    MMCO mmco_temp[MAX_MMCO_COUNT], *mmco = mmco_temp;

    int mmco_index = 0;

    if (h->nal_unit_type == NAL_IDR_SLICE) { // FIXME fields

        skip_bits1(gb); // broken_link

        if (get_bits1(gb)) {

            mmco[0].opcode   = MMCO_LONG;

            mmco[0].long_arg = 0;

            mmco_index       = 1;

        }

    } else {

        if (get_bits1(gb)) { // adaptive_ref_pic_marking_mode_flag

            for (i = 0; i < MAX_MMCO_COUNT; i++) {

                MMCOOpcode opcode = get_ue_golomb_31(gb);

                mmco[i].opcode = opcode;

                if (opcode == MMCO_SHORT2UNUSED || opcode == MMCO_SHORT2LONG) {

                    mmco[i].short_pic_num =

                        (h->curr_pic_num - get_ue_golomb(gb) - 1) &

                            (h->max_pic_num - 1);

#if 0

                    if (mmco[i].short_pic_num >= h->short_ref_count ||

                        !h->short_ref[mmco[i].short_pic_num]) {

                        av_log(s->avctx, AV_LOG_ERROR,

                               "illegal short ref in memory management control "

                               "operation %d\n", mmco);

                        return -1;

                    }

#endif

                }

                if (opcode == MMCO_SHORT2LONG || opcode == MMCO_LONG2UNUSED ||

                    opcode == MMCO_LONG || opcode == MMCO_SET_MAX_LONG) {

                    unsigned int long_arg = get_ue_golomb_31(gb);

                    if (long_arg >= 32 ||

                        (long_arg >= 16 && !(opcode == MMCO_SET_MAX_LONG &&

                                             long_arg == 16) &&

                         !(opcode == MMCO_LONG2UNUSED && FIELD_PICTURE(h)))) {

                        av_log(h->avctx, AV_LOG_ERROR,

                               "illegal long ref in memory management control "

                               "operation %d\n", opcode);

                        return -1;

                    }

                    mmco[i].long_arg = long_arg;

                }

                if (opcode > (unsigned) MMCO_LONG) {

                    av_log(h->avctx, AV_LOG_ERROR,

                           "illegal memory management control operation %d\n",

                           opcode);

                    return -1;

                }

                if (opcode == MMCO_END)

                    break;

            }

            mmco_index = i;

        } else {

            if (first_slice) {

                ret = ff_generate_sliding_window_mmcos(h, first_slice);

                if (ret < 0 && h->avctx->err_recognition & AV_EF_EXPLODE)

                    return ret;

            }

            mmco_index = -1;

        }

    }

    if (first_slice && mmco_index != -1) {

        memcpy(h->mmco, mmco_temp, sizeof(h->mmco));

        h->mmco_index = mmco_index;

    } else if (!first_slice && mmco_index >= 0 &&

               (mmco_index != h->mmco_index ||

                check_opcodes(h->mmco, mmco_temp, mmco_index))) {

        av_log(h->avctx, AV_LOG_ERROR,

               "Inconsistent MMCO state between slices [%d, %d]\n",

               mmco_index, h->mmco_index);

        return AVERROR_INVALIDDATA;

    }

    return 0;

}


static int init_input_stream(int ist_index, char *error, int error_len)

{

    int i;

    InputStream *ist = input_streams[ist_index];

    if (ist->decoding_needed) {

        AVCodec *codec = ist->dec;

        if (!codec) {

            snprintf(error, error_len, "Decoder (codec id %d) not found for input stream #%d:%d",

                    ist->st->codec->codec_id, ist->file_index, ist->st->index);

            return AVERROR(EINVAL);

        }

        /* update requested sample format for the decoder based on the

           corresponding encoder sample format */

        for (i = 0; i < nb_output_streams; i++) {

            OutputStream *ost = output_streams[i];

            if (ost->source_index == ist_index) {

                update_sample_fmt(ist->st->codec, codec, ost->st->codec);

                break;

            }

        }

        if (codec->type == AVMEDIA_TYPE_VIDEO && codec->capabilities & CODEC_CAP_DR1) {

            ist->st->codec->get_buffer     = codec_get_buffer;

            ist->st->codec->release_buffer = codec_release_buffer;

            ist->st->codec->opaque         = &ist->buffer_pool;

        }

        if (!av_dict_get(ist->opts, "threads", NULL, 0))

            av_dict_set(&ist->opts, "threads", "auto", 0);

        if (avcodec_open2(ist->st->codec, codec, &ist->opts) < 0) {

            snprintf(error, error_len, "Error while opening decoder for input stream #%d:%d",

                    ist->file_index, ist->st->index);

            return AVERROR(EINVAL);

        }

        assert_codec_experimental(ist->st->codec, 0);

        assert_avoptions(ist->opts);

    }

    ist->last_dts = ist->st->avg_frame_rate.num ? - ist->st->codec->has_b_frames * AV_TIME_BASE / av_q2d(ist->st->avg_frame_rate) : 0;

    ist->next_dts = AV_NOPTS_VALUE;

    init_pts_correction(&ist->pts_ctx);

    ist->is_start = 1;

    return 0;

}


build_tpm_tcpa(GArray *table_data, BIOSLinker *linker, GArray *tcpalog)

{

    Acpi20Tcpa *tcpa = acpi_data_push(table_data, sizeof *tcpa);

    tcpa->platform_class = cpu_to_le16(TPM_TCPA_ACPI_CLASS_CLIENT);

    tcpa->log_area_minimum_length = cpu_to_le32(TPM_LOG_AREA_MINIMUM_SIZE);

    acpi_data_push(tcpalog, le32_to_cpu(tcpa->log_area_minimum_length));

    bios_linker_loader_alloc(linker, ACPI_BUILD_TPMLOG_FILE, tcpalog, 1,

                             false /* high memory */);

    /* log area start address to be filled by Guest linker */

    bios_linker_loader_add_pointer(linker, ACPI_BUILD_TABLE_FILE,

                                   ACPI_BUILD_TPMLOG_FILE,

                                   &tcpa->log_area_start_address,

                                   sizeof(tcpa->log_area_start_address));

    build_header(linker, table_data,

                 (void *)tcpa, "TCPA", sizeof(*tcpa), 2, NULL, NULL);

}


static CharDriverState *qemu_chr_open_udp_fd(int fd)

{

    CharDriverState *chr = NULL;

    NetCharDriver *s = NULL;

    chr = g_malloc0(sizeof(CharDriverState));

    s = g_malloc0(sizeof(NetCharDriver));

    s->fd = fd;

    s->chan = io_channel_from_socket(s->fd);

    s->bufcnt = 0;

    s->bufptr = 0;

    chr->opaque = s;

    chr->chr_write = udp_chr_write;

    chr->chr_update_read_handler = udp_chr_update_read_handler;

    chr->chr_close = udp_chr_close;

    /* be isn't opened until we get a connection */

    chr->explicit_be_open = true;

    return chr;

}


static int get_pix_fmt_score(enum AVPixelFormat dst_pix_fmt,

                              enum AVPixelFormat src_pix_fmt,

                              unsigned *lossp, unsigned consider)

{

    const AVPixFmtDescriptor *src_desc = av_pix_fmt_desc_get(src_pix_fmt);

    const AVPixFmtDescriptor *dst_desc = av_pix_fmt_desc_get(dst_pix_fmt);

    int src_color, dst_color;

    int src_min_depth, src_max_depth, dst_min_depth, dst_max_depth;

    int ret, loss, i, nb_components;

    int score = INT_MAX - 1;

    if (dst_pix_fmt >= AV_PIX_FMT_NB || dst_pix_fmt <= AV_PIX_FMT_NONE)

        return ~0;

    /* compute loss */

    *lossp = loss = 0;

    if (dst_pix_fmt == src_pix_fmt)

        return INT_MAX;

    if ((ret = get_pix_fmt_depth(&src_min_depth, &src_max_depth, src_pix_fmt)) < 0)

        return ret;

    if ((ret = get_pix_fmt_depth(&dst_min_depth, &dst_max_depth, dst_pix_fmt)) < 0)

        return ret;

    src_color = get_color_type(src_desc);

    dst_color = get_color_type(dst_desc);

    if (dst_pix_fmt == AV_PIX_FMT_PAL8)

        nb_components = FFMIN(src_desc->nb_components, 4);

    else

        nb_components = FFMIN(src_desc->nb_components, dst_desc->nb_components);

    for (i = 0; i < nb_components; i++) {

        int depth_minus1 = (dst_pix_fmt == AV_PIX_FMT_PAL8) ? 7/nb_components : (dst_desc->comp[i].depth - 1);

        if (src_desc->comp[i].depth - 1 > depth_minus1 && (consider & FF_LOSS_DEPTH)) {

            loss |= FF_LOSS_DEPTH;

            score -= 65536 >> depth_minus1;

        }

    }

    if (consider & FF_LOSS_RESOLUTION) {

        if (dst_desc->log2_chroma_w > src_desc->log2_chroma_w) {

            loss |= FF_LOSS_RESOLUTION;

            score -= 256 << dst_desc->log2_chroma_w;

        }

        if (dst_desc->log2_chroma_h > src_desc->log2_chroma_h) {

            loss |= FF_LOSS_RESOLUTION;

            score -= 256 << dst_desc->log2_chroma_h;

        }

        // don't favor 422 over 420 if downsampling is needed, because 420 has much better support on the decoder side

        if (dst_desc->log2_chroma_w == 1 && src_desc->log2_chroma_w == 0 &&

            dst_desc->log2_chroma_h == 1 && src_desc->log2_chroma_h == 0 ) {

            score += 512;

        }

    }

    if(consider & FF_LOSS_COLORSPACE)

    switch(dst_color) {

    case FF_COLOR_RGB:

        if (src_color != FF_COLOR_RGB &&

            src_color != FF_COLOR_GRAY)

            loss |= FF_LOSS_COLORSPACE;

        break;

    case FF_COLOR_GRAY:

        if (src_color != FF_COLOR_GRAY)

            loss |= FF_LOSS_COLORSPACE;

        break;

    case FF_COLOR_YUV:

        if (src_color != FF_COLOR_YUV)

            loss |= FF_LOSS_COLORSPACE;

        break;

    case FF_COLOR_YUV_JPEG:

        if (src_color != FF_COLOR_YUV_JPEG &&

            src_color != FF_COLOR_YUV &&

            src_color != FF_COLOR_GRAY)

            loss |= FF_LOSS_COLORSPACE;

        break;

    default:

        /* fail safe test */

        if (src_color != dst_color)

            loss |= FF_LOSS_COLORSPACE;

        break;

    }

    if(loss & FF_LOSS_COLORSPACE)

        score -= (nb_components * 65536) >> FFMIN(dst_desc->comp[0].depth - 1, src_desc->comp[0].depth - 1);

    if (dst_color == FF_COLOR_GRAY &&

        src_color != FF_COLOR_GRAY && (consider & FF_LOSS_CHROMA)) {

        loss |= FF_LOSS_CHROMA;

        score -= 2 * 65536;

    }

    if (!pixdesc_has_alpha(dst_desc) && (pixdesc_has_alpha(src_desc) && (consider & FF_LOSS_ALPHA))) {

        loss |= FF_LOSS_ALPHA;

        score -= 65536;

    }

    if (dst_pix_fmt == AV_PIX_FMT_PAL8 && (consider & FF_LOSS_COLORQUANT) &&

        (src_pix_fmt != AV_PIX_FMT_PAL8 && (src_color != FF_COLOR_GRAY || (pixdesc_has_alpha(src_desc) && (consider & FF_LOSS_ALPHA))))) {

        loss |= FF_LOSS_COLORQUANT;

        score -= 65536;

    }

    *lossp = loss;

    return score;

}


static void pc_init1(ram_addr_t ram_size,

                     const char *boot_device,

                     const char *kernel_filename, const char *kernel_cmdline,

                     const char *initrd_filename,

                     int pci_enabled, const char *cpu_model)

{

    char *filename;

    int ret, linux_boot, i;

    ram_addr_t ram_addr, bios_offset, option_rom_offset;

    ram_addr_t below_4g_mem_size, above_4g_mem_size = 0;

    int bios_size, isa_bios_size, oprom_area_size;

    PCIBus *pci_bus;

    int piix3_devfn = -1;

    CPUState *env;

    qemu_irq *cpu_irq;

    qemu_irq *i8259;

    int index;

    BlockDriverState *hd[MAX_IDE_BUS * MAX_IDE_DEVS];

    BlockDriverState *fd[MAX_FD];

    int using_vga = cirrus_vga_enabled || std_vga_enabled || vmsvga_enabled;

    if (ram_size >= 0xe0000000 ) {

        above_4g_mem_size = ram_size - 0xe0000000;

        below_4g_mem_size = 0xe0000000;

    } else {

        below_4g_mem_size = ram_size;

    }

    linux_boot = (kernel_filename != NULL);

    /* init CPUs */

    if (cpu_model == NULL) {

#ifdef TARGET_X86_64

        cpu_model = "qemu64";

#else

        cpu_model = "qemu32";

#endif

    }

    for(i = 0; i < smp_cpus; i++) {

        env = cpu_init(cpu_model);

        if (!env) {

            fprintf(stderr, "Unable to find x86 CPU definition\n");

            exit(1);

        }

        if ((env->cpuid_features & CPUID_APIC) || smp_cpus > 1) {

            env->cpuid_apic_id = env->cpu_index;

            apic_init(env);

        }

        qemu_register_reset(main_cpu_reset, 0, env);

    }

    vmport_init();

    /* allocate RAM */

    ram_addr = qemu_ram_alloc(0xa0000);

    cpu_register_physical_memory(0, 0xa0000, ram_addr);

    /* Allocate, even though we won't register, so we don't break the

     * phys_ram_base + PA assumption. This range includes vga (0xa0000 - 0xc0000),

     * and some bios areas, which will be registered later

     */

    ram_addr = qemu_ram_alloc(0x100000 - 0xa0000);

    ram_addr = qemu_ram_alloc(below_4g_mem_size - 0x100000);

    cpu_register_physical_memory(0x100000,

                 below_4g_mem_size - 0x100000,

                 ram_addr);

    /* above 4giga memory allocation */

    if (above_4g_mem_size > 0) {

#if TARGET_PHYS_ADDR_BITS == 32

        hw_error("To much RAM for 32-bit physical address");

#else

        ram_addr = qemu_ram_alloc(above_4g_mem_size);

        cpu_register_physical_memory(0x100000000ULL,

                                     above_4g_mem_size,

                                     ram_addr);

#endif

    }

    /* BIOS load */

    if (bios_name == NULL)

        bios_name = BIOS_FILENAME;

    filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);

    if (filename) {

        bios_size = get_image_size(filename);

    } else {

        bios_size = -1;

    }

    if (bios_size <= 0 ||

        (bios_size % 65536) != 0) {

        goto bios_error;

    }

    bios_offset = qemu_ram_alloc(bios_size);

    ret = load_image(filename, qemu_get_ram_ptr(bios_offset));

    if (ret != bios_size) {

    bios_error:

        fprintf(stderr, "qemu: could not load PC BIOS '%s'\n", bios_name);

        exit(1);

    }

    if (filename) {

        qemu_free(filename);

    }

    /* map the last 128KB of the BIOS in ISA space */

    isa_bios_size = bios_size;

    if (isa_bios_size > (128 * 1024))

        isa_bios_size = 128 * 1024;

    cpu_register_physical_memory(0x100000 - isa_bios_size,

                                 isa_bios_size,

                                 (bios_offset + bios_size - isa_bios_size) | IO_MEM_ROM);

    option_rom_offset = qemu_ram_alloc(0x20000);

    oprom_area_size = 0;

    cpu_register_physical_memory(0xc0000, 0x20000, option_rom_offset);

    if (using_vga) {

        const char *vgabios_filename;

        /* VGA BIOS load */

        if (cirrus_vga_enabled) {

            vgabios_filename = VGABIOS_CIRRUS_FILENAME;

        } else {

            vgabios_filename = VGABIOS_FILENAME;

        }

        oprom_area_size = load_option_rom(vgabios_filename, 0xc0000, 0xe0000);

    }

    /* Although video roms can grow larger than 0x8000, the area between

     * 0xc0000 - 0xc8000 is reserved for them. It means we won't be looking

     * for any other kind of option rom inside this area */

    if (oprom_area_size < 0x8000)

        oprom_area_size = 0x8000;

    if (linux_boot) {

        load_linux(0xc0000 + oprom_area_size,

                   kernel_filename, initrd_filename, kernel_cmdline, below_4g_mem_size);

        oprom_area_size += 2048;

    }

    for (i = 0; i < nb_option_roms; i++) {

        oprom_area_size += load_option_rom(option_rom[i],

                                           0xc0000 + oprom_area_size, 0xe0000);

    }

    /* map all the bios at the top of memory */

    cpu_register_physical_memory((uint32_t)(-bios_size),

                                 bios_size, bios_offset | IO_MEM_ROM);

    bochs_bios_init();

    cpu_irq = qemu_allocate_irqs(pic_irq_request, NULL, 1);

    i8259 = i8259_init(cpu_irq[0]);

    ferr_irq = i8259[13];

    if (pci_enabled) {

        pci_bus = i440fx_init(&i440fx_state, i8259);

        piix3_devfn = piix3_init(pci_bus, -1);

    } else {

        pci_bus = NULL;

    }

    /* init basic PC hardware */

    register_ioport_write(0x80, 1, 1, ioport80_write, NULL);

    register_ioport_write(0xf0, 1, 1, ioportF0_write, NULL);

    if (cirrus_vga_enabled) {

        if (pci_enabled) {

            pci_cirrus_vga_init(pci_bus);

        } else {

            isa_cirrus_vga_init();

        }

    } else if (vmsvga_enabled) {

        if (pci_enabled)

            pci_vmsvga_init(pci_bus);

        else

            fprintf(stderr, "%s: vmware_vga: no PCI bus\n", __FUNCTION__);

    } else if (std_vga_enabled) {

        if (pci_enabled) {

            pci_vga_init(pci_bus, 0, 0);

        } else {

            isa_vga_init();

        }

    }

    rtc_state = rtc_init(0x70, i8259[8], 2000);

    qemu_register_boot_set(pc_boot_set, rtc_state);

    register_ioport_read(0x92, 1, 1, ioport92_read, NULL);

    register_ioport_write(0x92, 1, 1, ioport92_write, NULL);

    if (pci_enabled) {

        ioapic = ioapic_init();

    }

    pit = pit_init(0x40, i8259[0]);

    pcspk_init(pit);

    if (!no_hpet) {

        hpet_init(i8259);

    }

    if (pci_enabled) {

        pic_set_alt_irq_func(isa_pic, ioapic_set_irq, ioapic);

    }

    for(i = 0; i < MAX_SERIAL_PORTS; i++) {

        if (serial_hds[i]) {

            serial_init(serial_io[i], i8259[serial_irq[i]], 115200,

                        serial_hds[i]);

        }

    }

    for(i = 0; i < MAX_PARALLEL_PORTS; i++) {

        if (parallel_hds[i]) {

            parallel_init(parallel_io[i], i8259[parallel_irq[i]],

                          parallel_hds[i]);

        }

    }

    watchdog_pc_init(pci_bus);

    for(i = 0; i < nb_nics; i++) {

        NICInfo *nd = &nd_table[i];

        if (!pci_enabled || (nd->model && strcmp(nd->model, "ne2k_isa") == 0))

            pc_init_ne2k_isa(nd, i8259);

        else

            pci_nic_init(pci_bus, nd, -1, "ne2k_pci");

    }

    qemu_system_hot_add_init();

    if (drive_get_max_bus(IF_IDE) >= MAX_IDE_BUS) {

        fprintf(stderr, "qemu: too many IDE bus\n");

        exit(1);

    }

    for(i = 0; i < MAX_IDE_BUS * MAX_IDE_DEVS; i++) {

        index = drive_get_index(IF_IDE, i / MAX_IDE_DEVS, i % MAX_IDE_DEVS);

	if (index != -1)

	    hd[i] = drives_table[index].bdrv;

	else

	    hd[i] = NULL;

    }

    if (pci_enabled) {

        pci_piix3_ide_init(pci_bus, hd, piix3_devfn + 1, i8259);

    } else {

        for(i = 0; i < MAX_IDE_BUS; i++) {

            isa_ide_init(ide_iobase[i], ide_iobase2[i], i8259[ide_irq[i]],

	                 hd[MAX_IDE_DEVS * i], hd[MAX_IDE_DEVS * i + 1]);

        }

    }

    i8042_init(i8259[1], i8259[12], 0x60);

    DMA_init(0);

#ifdef HAS_AUDIO

    audio_init(pci_enabled ? pci_bus : NULL, i8259);

#endif

    for(i = 0; i < MAX_FD; i++) {

        index = drive_get_index(IF_FLOPPY, 0, i);

	if (index != -1)

	    fd[i] = drives_table[index].bdrv;

	else

	    fd[i] = NULL;

    }

    floppy_controller = fdctrl_init(i8259[6], 2, 0, 0x3f0, fd);

    cmos_init(below_4g_mem_size, above_4g_mem_size, boot_device, hd);

    if (pci_enabled && usb_enabled) {

        usb_uhci_piix3_init(pci_bus, piix3_devfn + 2);

    }

    if (pci_enabled && acpi_enabled) {

        uint8_t *eeprom_buf = qemu_mallocz(8 * 256); /* XXX: make this persistent */

        i2c_bus *smbus;

        /* TODO: Populate SPD eeprom data.  */

        smbus = piix4_pm_init(pci_bus, piix3_devfn + 3, 0xb100, i8259[9]);

        for (i = 0; i < 8; i++) {

            DeviceState *eeprom;

            eeprom = qdev_create((BusState *)smbus, "smbus-eeprom");

            qdev_set_prop_int(eeprom, "address", 0x50 + i);

            qdev_set_prop_ptr(eeprom, "data", eeprom_buf + (i * 256));

            qdev_init(eeprom);

        }

    }

    if (i440fx_state) {

        i440fx_init_memory_mappings(i440fx_state);

    }

    if (pci_enabled) {

	int max_bus;

        int bus;

        max_bus = drive_get_max_bus(IF_SCSI);

	for (bus = 0; bus <= max_bus; bus++) {

            pci_create_simple(pci_bus, -1, "lsi53c895a");

        }

    }

    /* Add virtio block devices */

    if (pci_enabled) {

        int index;

        int unit_id = 0;

        while ((index = drive_get_index(IF_VIRTIO, 0, unit_id)) != -1) {

            pci_create_simple(pci_bus, -1, "virtio-blk-pci");

            unit_id++;

        }

    }

    /* Add virtio balloon device */

    if (pci_enabled && !no_virtio_balloon) {

        pci_create_simple(pci_bus, -1, "virtio-balloon-pci");

    }

    /* Add virtio console devices */

    if (pci_enabled) {

        for(i = 0; i < MAX_VIRTIO_CONSOLES; i++) {

            if (virtcon_hds[i]) {

                pci_create_simple(pci_bus, -1, "virtio-console-pci");

            }

        }

    }

}


static ssize_t v9fs_synth_lgetxattr(FsContext *ctx, V9fsPath *path,

                                    const char *name, void *value, size_t size)

{

    errno = ENOTSUP;

    return -1;

}


static void aw_emac_cleanup(NetClientState *nc)

{

    AwEmacState *s = qemu_get_nic_opaque(nc);

    s->nic = NULL;

}


static void virtio_net_set_features(VirtIODevice *vdev, uint32_t features)

{

    VirtIONet *n = VIRTIO_NET(vdev);

    int i;

    virtio_net_set_multiqueue(n, !!(features & (1 << VIRTIO_NET_F_MQ)),

                              !!(features & (1 << VIRTIO_NET_F_CTRL_VQ)));

    virtio_net_set_mrg_rx_bufs(n, !!(features & (1 << VIRTIO_NET_F_MRG_RXBUF)));

    if (n->has_vnet_hdr) {

        tap_set_offload(qemu_get_subqueue(n->nic, 0)->peer,

                        (features >> VIRTIO_NET_F_GUEST_CSUM) & 1,

                        (features >> VIRTIO_NET_F_GUEST_TSO4) & 1,

                        (features >> VIRTIO_NET_F_GUEST_TSO6) & 1,

                        (features >> VIRTIO_NET_F_GUEST_ECN)  & 1,

                        (features >> VIRTIO_NET_F_GUEST_UFO)  & 1);

    }

    for (i = 0;  i < n->max_queues; i++) {

        NetClientState *nc = qemu_get_subqueue(n->nic, i);

        if (!nc->peer || nc->peer->info->type != NET_CLIENT_OPTIONS_KIND_TAP) {

            continue;

        }

        if (!tap_get_vhost_net(nc->peer)) {

            continue;

        }

        vhost_net_ack_features(tap_get_vhost_net(nc->peer), features);

    }

}


void qemu_del_nic(NICState *nic)

{

    int i, queues = nic->conf->queues;

    /* If this is a peer NIC and peer has already been deleted, free it now. */

    if (nic->peer_deleted) {

        for (i = 0; i < queues; i++) {

            qemu_free_net_client(qemu_get_subqueue(nic, i)->peer);

        }

    }

    for (i = queues - 1; i >= 0; i--) {

        NetClientState *nc = qemu_get_subqueue(nic, i);

        qemu_cleanup_net_client(nc);

        qemu_free_net_client(nc);

    }

}


static int vfio_initfn(PCIDevice *pdev)

{

    VFIOPCIDevice *vdev = DO_UPCAST(VFIOPCIDevice, pdev, pdev);

    VFIODevice *vbasedev_iter;

    VFIOGroup *group;

    char path[PATH_MAX], iommu_group_path[PATH_MAX], *group_name;

    ssize_t len;

    struct stat st;

    int groupid;

    int ret;

    /* Check that the host device exists */

    snprintf(path, sizeof(path),

             "/sys/bus/pci/devices/%04x:%02x:%02x.%01x/",

             vdev->host.domain, vdev->host.bus, vdev->host.slot,

             vdev->host.function);

    if (stat(path, &st) < 0) {

        error_report("vfio: error: no such host device: %s", path);

        return -errno;

    }

    vdev->vbasedev.ops = &vfio_pci_ops;

    vdev->vbasedev.type = VFIO_DEVICE_TYPE_PCI;

    vdev->vbasedev.name = g_strdup_printf("%04x:%02x:%02x.%01x",

                                          vdev->host.domain, vdev->host.bus,

                                          vdev->host.slot, vdev->host.function);

    strncat(path, "iommu_group", sizeof(path) - strlen(path) - 1);

    len = readlink(path, iommu_group_path, sizeof(path));

    if (len <= 0 || len >= sizeof(path)) {

        error_report("vfio: error no iommu_group for device");

        return len < 0 ? -errno : -ENAMETOOLONG;

    }

    iommu_group_path[len] = 0;

    group_name = basename(iommu_group_path);

    if (sscanf(group_name, "%d", &groupid) != 1) {

        error_report("vfio: error reading %s: %m", path);

        return -errno;

    }

    trace_vfio_initfn(vdev->vbasedev.name, groupid);

    group = vfio_get_group(groupid, pci_device_iommu_address_space(pdev));

    if (!group) {

        error_report("vfio: failed to get group %d", groupid);

        return -ENOENT;

    }

    snprintf(path, sizeof(path), "%04x:%02x:%02x.%01x",

            vdev->host.domain, vdev->host.bus, vdev->host.slot,

            vdev->host.function);

    QLIST_FOREACH(vbasedev_iter, &group->device_list, next) {

        if (strcmp(vbasedev_iter->name, vdev->vbasedev.name) == 0) {

            error_report("vfio: error: device %s is already attached", path);

            vfio_put_group(group);

            return -EBUSY;

        }

    }

    ret = vfio_get_device(group, path, &vdev->vbasedev);

    if (ret) {

        error_report("vfio: failed to get device %s", path);

        vfio_put_group(group);

        return ret;

    }

    ret = vfio_populate_device(vdev);

    if (ret) {

        return ret;

    }

    /* Get a copy of config space */

    ret = pread(vdev->vbasedev.fd, vdev->pdev.config,

                MIN(pci_config_size(&vdev->pdev), vdev->config_size),

                vdev->config_offset);

    if (ret < (int)MIN(pci_config_size(&vdev->pdev), vdev->config_size)) {

        ret = ret < 0 ? -errno : -EFAULT;

        error_report("vfio: Failed to read device config space");

        return ret;

    }

    /* vfio emulates a lot for us, but some bits need extra love */

    vdev->emulated_config_bits = g_malloc0(vdev->config_size);

    /* QEMU can choose to expose the ROM or not */

    memset(vdev->emulated_config_bits + PCI_ROM_ADDRESS, 0xff, 4);

    /*

     * The PCI spec reserves vendor ID 0xffff as an invalid value.  The

     * device ID is managed by the vendor and need only be a 16-bit value.

     * Allow any 16-bit value for subsystem so they can be hidden or changed.

     */

    if (vdev->vendor_id != PCI_ANY_ID) {

        if (vdev->vendor_id >= 0xffff) {

            error_report("vfio: Invalid PCI vendor ID provided");

            return -EINVAL;

        }

        vfio_add_emulated_word(vdev, PCI_VENDOR_ID, vdev->vendor_id, ~0);

        trace_vfio_pci_emulated_vendor_id(vdev->vbasedev.name, vdev->vendor_id);

    } else {

        vdev->vendor_id = pci_get_word(pdev->config + PCI_VENDOR_ID);

    }

    if (vdev->device_id != PCI_ANY_ID) {

        if (vdev->device_id > 0xffff) {

            error_report("vfio: Invalid PCI device ID provided");

            return -EINVAL;

        }

        vfio_add_emulated_word(vdev, PCI_DEVICE_ID, vdev->device_id, ~0);

        trace_vfio_pci_emulated_device_id(vdev->vbasedev.name, vdev->device_id);

    } else {

        vdev->device_id = pci_get_word(pdev->config + PCI_DEVICE_ID);

    }

    if (vdev->sub_vendor_id != PCI_ANY_ID) {

        if (vdev->sub_vendor_id > 0xffff) {

            error_report("vfio: Invalid PCI subsystem vendor ID provided");

            return -EINVAL;

        }

        vfio_add_emulated_word(vdev, PCI_SUBSYSTEM_VENDOR_ID,

                               vdev->sub_vendor_id, ~0);

        trace_vfio_pci_emulated_sub_vendor_id(vdev->vbasedev.name,

                                              vdev->sub_vendor_id);

    }

    if (vdev->sub_device_id != PCI_ANY_ID) {

        if (vdev->sub_device_id > 0xffff) {

            error_report("vfio: Invalid PCI subsystem device ID provided");

            return -EINVAL;

        }

        vfio_add_emulated_word(vdev, PCI_SUBSYSTEM_ID, vdev->sub_device_id, ~0);

        trace_vfio_pci_emulated_sub_device_id(vdev->vbasedev.name,

                                              vdev->sub_device_id);

    }

    /* QEMU can change multi-function devices to single function, or reverse */

    vdev->emulated_config_bits[PCI_HEADER_TYPE] =

                                              PCI_HEADER_TYPE_MULTI_FUNCTION;

    /* Restore or clear multifunction, this is always controlled by QEMU */

    if (vdev->pdev.cap_present & QEMU_PCI_CAP_MULTIFUNCTION) {

        vdev->pdev.config[PCI_HEADER_TYPE] |= PCI_HEADER_TYPE_MULTI_FUNCTION;

    } else {

        vdev->pdev.config[PCI_HEADER_TYPE] &= ~PCI_HEADER_TYPE_MULTI_FUNCTION;

    }

    /*

     * Clear host resource mapping info.  If we choose not to register a

     * BAR, such as might be the case with the option ROM, we can get

     * confusing, unwritable, residual addresses from the host here.

     */

    memset(&vdev->pdev.config[PCI_BASE_ADDRESS_0], 0, 24);

    memset(&vdev->pdev.config[PCI_ROM_ADDRESS], 0, 4);

    vfio_pci_size_rom(vdev);

    ret = vfio_msix_early_setup(vdev);

    if (ret) {

        return ret;

    }

    vfio_map_bars(vdev);

    ret = vfio_add_capabilities(vdev);

    if (ret) {

        goto out_teardown;

    }

    /* QEMU emulates all of MSI & MSIX */

    if (pdev->cap_present & QEMU_PCI_CAP_MSIX) {

        memset(vdev->emulated_config_bits + pdev->msix_cap, 0xff,

               MSIX_CAP_LENGTH);

    }

    if (pdev->cap_present & QEMU_PCI_CAP_MSI) {

        memset(vdev->emulated_config_bits + pdev->msi_cap, 0xff,

               vdev->msi_cap_size);

    }

    if (vfio_pci_read_config(&vdev->pdev, PCI_INTERRUPT_PIN, 1)) {

        vdev->intx.mmap_timer = timer_new_ms(QEMU_CLOCK_VIRTUAL,

                                                  vfio_intx_mmap_enable, vdev);

        pci_device_set_intx_routing_notifier(&vdev->pdev, vfio_intx_update);

        ret = vfio_intx_enable(vdev);

        if (ret) {

            goto out_teardown;

        }

    }

    vfio_register_err_notifier(vdev);

    vfio_register_req_notifier(vdev);

    vfio_setup_resetfn_quirk(vdev);

    return 0;

out_teardown:

    pci_device_set_intx_routing_notifier(&vdev->pdev, NULL);

    vfio_teardown_msi(vdev);

    vfio_unregister_bars(vdev);

    return ret;

}


static void absolute_mouse_grab(void)

{

    int mouse_x, mouse_y;

    if (SDL_GetAppState() & SDL_APPINPUTFOCUS) {

        SDL_GetMouseState(&mouse_x, &mouse_y);

        if (mouse_x > 0 && mouse_x < real_screen->w - 1 &&

            mouse_y > 0 && mouse_y < real_screen->h - 1) {

            sdl_grab_start();

        }

    }

}


int socket_dgram(SocketAddress *remote, SocketAddress *local, Error **errp)

{

    int fd;

    switch (remote->type) {

    case SOCKET_ADDRESS_KIND_INET:

        fd = inet_dgram_saddr(remote->u.inet, local ? local->u.inet : NULL, errp);

        break;

    default:

        error_setg(errp, "socket type unsupported for datagram");

        fd = -1;

    }

    return fd;

}


static int update_wrap_reference(AVFormatContext *s, AVStream *st, int stream_index)

{

    if (s->correct_ts_overflow && st->pts_wrap_bits < 63 &&

        st->pts_wrap_reference == AV_NOPTS_VALUE && st->first_dts != AV_NOPTS_VALUE) {

        int i;

        // reference time stamp should be 60 s before first time stamp

        int64_t pts_wrap_reference = st->first_dts - av_rescale(60, st->time_base.den, st->time_base.num);

        // if first time stamp is not more than 1/8 and 60s before the wrap point, subtract rather than add wrap offset

        int pts_wrap_behavior = (st->first_dts < (1LL<<st->pts_wrap_bits) - (1LL<<st->pts_wrap_bits-3)) ||

            (st->first_dts < (1LL<<st->pts_wrap_bits) - av_rescale(60, st->time_base.den, st->time_base.num)) ?

            AV_PTS_WRAP_ADD_OFFSET : AV_PTS_WRAP_SUB_OFFSET;

        AVProgram *first_program = av_find_program_from_stream(s, NULL, stream_index);

        if (!first_program) {

            int default_stream_index = av_find_default_stream_index(s);

            if (s->streams[default_stream_index]->pts_wrap_reference == AV_NOPTS_VALUE) {

                for (i=0; i<s->nb_streams; i++) {

                    s->streams[i]->pts_wrap_reference = pts_wrap_reference;

                    s->streams[i]->pts_wrap_behavior = pts_wrap_behavior;

                }

            }

            else {

                st->pts_wrap_reference = s->streams[default_stream_index]->pts_wrap_reference;

                st->pts_wrap_behavior = s->streams[default_stream_index]->pts_wrap_behavior;

            }

        }

        else {

            AVProgram *program = first_program;

            while (program) {

                if (program->pts_wrap_reference != AV_NOPTS_VALUE) {

                    pts_wrap_reference = program->pts_wrap_reference;

                    pts_wrap_behavior = program->pts_wrap_behavior;

                    break;

                }

                program = av_find_program_from_stream(s, program, stream_index);

            }

            // update every program with differing pts_wrap_reference

            program = first_program;

            while(program) {

                if (program->pts_wrap_reference != pts_wrap_reference) {

                    for (i=0; i<program->nb_stream_indexes; i++) {

                        s->streams[program->stream_index[i]]->pts_wrap_reference = pts_wrap_reference;

                        s->streams[program->stream_index[i]]->pts_wrap_behavior = pts_wrap_behavior;

                    }

                    program->pts_wrap_reference = pts_wrap_reference;

                    program->pts_wrap_behavior = pts_wrap_behavior;

                }

                program = av_find_program_from_stream(s, program, stream_index);

            }

        }

        return 1;

    }

    return 0;

}


uint64_t HELPER(diag)(CPUS390XState *env, uint32_t num, uint64_t mem,

                      uint64_t code)

{

    uint64_t r;

    switch (num) {

    case 0x500:

        /* KVM hypercall */

        r = s390_virtio_hypercall(env);

        break;

    case 0x44:

        /* yield */

        r = 0;

        break;

    case 0x308:

        /* ipl */

        r = 0;

        break;

    default:

        r = -1;

        break;

    }

    if (r) {

        program_interrupt(env, PGM_OPERATION, ILEN_LATER_INC);

    }

    return r;

}


static uint64_t get_cluster_offset(BlockDriverState *bs,

                                    VmdkExtent *extent,

                                    VmdkMetaData *m_data,

                                    uint64_t offset, int allocate)

{

    unsigned int l1_index, l2_offset, l2_index;

    int min_index, i, j;

    uint32_t min_count, *l2_table, tmp = 0;

    uint64_t cluster_offset;

    if (m_data)

        m_data->valid = 0;

    l1_index = (offset >> 9) / extent->l1_entry_sectors;

    if (l1_index >= extent->l1_size) {

        return 0;

    }

    l2_offset = extent->l1_table[l1_index];

    if (!l2_offset) {

        return 0;

    }

    for (i = 0; i < L2_CACHE_SIZE; i++) {

        if (l2_offset == extent->l2_cache_offsets[i]) {

            /* increment the hit count */

            if (++extent->l2_cache_counts[i] == 0xffffffff) {

                for (j = 0; j < L2_CACHE_SIZE; j++) {

                    extent->l2_cache_counts[j] >>= 1;

                }

            }

            l2_table = extent->l2_cache + (i * extent->l2_size);

            goto found;

        }

    }

    /* not found: load a new entry in the least used one */

    min_index = 0;

    min_count = 0xffffffff;

    for (i = 0; i < L2_CACHE_SIZE; i++) {

        if (extent->l2_cache_counts[i] < min_count) {

            min_count = extent->l2_cache_counts[i];

            min_index = i;

        }

    }

    l2_table = extent->l2_cache + (min_index * extent->l2_size);

    if (bdrv_pread(

                extent->file,

                (int64_t)l2_offset * 512,

                l2_table,

                extent->l2_size * sizeof(uint32_t)

            ) != extent->l2_size * sizeof(uint32_t)) {

        return 0;

    }

    extent->l2_cache_offsets[min_index] = l2_offset;

    extent->l2_cache_counts[min_index] = 1;

 found:

    l2_index = ((offset >> 9) / extent->cluster_sectors) % extent->l2_size;

    cluster_offset = le32_to_cpu(l2_table[l2_index]);

    if (!cluster_offset) {

        if (!allocate)

            return 0;

        // Avoid the L2 tables update for the images that have snapshots.

        cluster_offset = bdrv_getlength(extent->file);

        bdrv_truncate(

            extent->file,

            cluster_offset + (extent->cluster_sectors << 9)

        );

        cluster_offset >>= 9;

        tmp = cpu_to_le32(cluster_offset);

        l2_table[l2_index] = tmp;

        /* First of all we write grain itself, to avoid race condition

         * that may to corrupt the image.

         * This problem may occur because of insufficient space on host disk

         * or inappropriate VM shutdown.

         */

        if (get_whole_cluster(

                bs, extent, cluster_offset, offset, allocate) == -1)

            return 0;

        if (m_data) {

            m_data->offset = tmp;

            m_data->l1_index = l1_index;

            m_data->l2_index = l2_index;

            m_data->l2_offset = l2_offset;

            m_data->valid = 1;

        }

    }

    cluster_offset <<= 9;

    return cluster_offset;

}


void qemu_set_fd_handler(int fd,

                         IOHandler *fd_read,

                         IOHandler *fd_write,

                         void *opaque)

{

    iohandler_init();

    aio_set_fd_handler(iohandler_ctx, fd, false,

                       fd_read, fd_write, NULL, opaque);

}


static MemTxResult nvic_sysreg_write(void *opaque, hwaddr addr,

                                     uint64_t value, unsigned size,

                                     MemTxAttrs attrs)

{

    NVICState *s = (NVICState *)opaque;

    uint32_t offset = addr;

    unsigned i, startvec, end;

    unsigned setval = 0;

    trace_nvic_sysreg_write(addr, value, size);

    if (attrs.user && !nvic_user_access_ok(s, addr)) {

        /* Generate BusFault for unprivileged accesses */

        return MEMTX_ERROR;

    }

    switch (offset) {

    case 0x100 ... 0x13f: /* NVIC Set enable */

        offset += 0x80;

        setval = 1;

        /* fall through */

    case 0x180 ... 0x1bf: /* NVIC Clear enable */

        startvec = 8 * (offset - 0x180) + NVIC_FIRST_IRQ;

        for (i = 0, end = size * 8; i < end && startvec + i < s->num_irq; i++) {

            if (value & (1 << i)) {

                s->vectors[startvec + i].enabled = setval;

            }

        }

        nvic_irq_update(s);

        return MEMTX_OK;

    case 0x200 ... 0x23f: /* NVIC Set pend */

        /* the special logic in armv7m_nvic_set_pending()

         * is not needed since IRQs are never escalated

         */

        offset += 0x80;

        setval = 1;

        /* fall through */

    case 0x280 ... 0x2bf: /* NVIC Clear pend */

        startvec = 8 * (offset - 0x280) + NVIC_FIRST_IRQ; /* vector # */

        for (i = 0, end = size * 8; i < end && startvec + i < s->num_irq; i++) {

            if (value & (1 << i)) {

                s->vectors[startvec + i].pending = setval;

            }

        }

        nvic_irq_update(s);

        return MEMTX_OK;

    case 0x300 ... 0x33f: /* NVIC Active */

        return MEMTX_OK; /* R/O */

    case 0x400 ... 0x5ef: /* NVIC Priority */

        startvec = 8 * (offset - 0x400) + NVIC_FIRST_IRQ; /* vector # */

        for (i = 0; i < size && startvec + i < s->num_irq; i++) {

            set_prio(s, startvec + i, (value >> (i * 8)) & 0xff);

        }

        nvic_irq_update(s);

        return MEMTX_OK;

    case 0xd18 ... 0xd23: /* System Handler Priority.  */

        for (i = 0; i < size; i++) {

            unsigned hdlidx = (offset - 0xd14) + i;

            set_prio(s, hdlidx, (value >> (i * 8)) & 0xff);

        }

        nvic_irq_update(s);

        return MEMTX_OK;

    }

    if (size == 4) {

        nvic_writel(s, offset, value);

        return MEMTX_OK;

    }

    qemu_log_mask(LOG_GUEST_ERROR,

                  "NVIC: Bad write of size %d at offset 0x%x\n", size, offset);

    /* This is UNPREDICTABLE; treat as RAZ/WI */

    return MEMTX_OK;

}


static void phys_page_set_level(PhysPageEntry *lp, hwaddr *index,

                                hwaddr *nb, uint16_t leaf,

                                int level)

{

    PhysPageEntry *p;

    int i;

    hwaddr step = (hwaddr)1 << (level * P_L2_BITS);

    if (lp->skip && lp->ptr == PHYS_MAP_NODE_NIL) {

        lp->ptr = phys_map_node_alloc();

        p = next_map.nodes[lp->ptr];

        if (level == 0) {

            for (i = 0; i < P_L2_SIZE; i++) {

                p[i].skip = 0;

                p[i].ptr = PHYS_SECTION_UNASSIGNED;

            }

        }

    } else {

        p = next_map.nodes[lp->ptr];

    }

    lp = &p[(*index >> (level * P_L2_BITS)) & (P_L2_SIZE - 1)];

    while (*nb && lp < &p[P_L2_SIZE]) {

        if ((*index & (step - 1)) == 0 && *nb >= step) {

            lp->skip = 0;

            lp->ptr = leaf;

            *index += step;

            *nb -= step;

        } else {

            phys_page_set_level(lp, index, nb, leaf, level - 1);

        }

        ++lp;

    }

}


static void map_page(uint8_t **ptr, uint64_t addr, uint32_t wanted)

{

    target_phys_addr_t len = wanted;

    if (*ptr) {

        cpu_physical_memory_unmap(*ptr, len, 1, len);

    }

    *ptr = cpu_physical_memory_map(addr, &len, 1);

    if (len < wanted) {

        cpu_physical_memory_unmap(*ptr, len, 1, len);

        *ptr = NULL;

    }

}


static VmdkExtent *vmdk_add_extent(BlockDriverState *bs,

                           BlockDriverState *file, bool flat, int64_t sectors,

                           int64_t l1_offset, int64_t l1_backup_offset,

                           uint32_t l1_size,

                           int l2_size, unsigned int cluster_sectors)

{

    VmdkExtent *extent;

    BDRVVmdkState *s = bs->opaque;

    s->extents = g_realloc(s->extents,

                              (s->num_extents + 1) * sizeof(VmdkExtent));

    extent = &s->extents[s->num_extents];

    s->num_extents++;

    memset(extent, 0, sizeof(VmdkExtent));

    extent->file = file;

    extent->flat = flat;

    extent->sectors = sectors;

    extent->l1_table_offset = l1_offset;

    extent->l1_backup_table_offset = l1_backup_offset;

    extent->l1_size = l1_size;

    extent->l1_entry_sectors = l2_size * cluster_sectors;

    extent->l2_size = l2_size;

    extent->cluster_sectors = cluster_sectors;

    if (s->num_extents > 1) {

        extent->end_sector = (*(extent - 1)).end_sector + extent->sectors;

    } else {

        extent->end_sector = extent->sectors;

    }

    bs->total_sectors = extent->end_sector;

    return extent;

}


static void ppc_heathrow_init (int ram_size, int vga_ram_size,

                               const char *boot_device, DisplayState *ds,

                               const char **fd_filename, int snapshot,

                               const char *kernel_filename,

                               const char *kernel_cmdline,

                               const char *initrd_filename,

                               const char *cpu_model)

{

    CPUState *env = NULL, *envs[MAX_CPUS];

    char buf[1024];

    qemu_irq *pic, **heathrow_irqs;

    nvram_t nvram;

    m48t59_t *m48t59;

    int linux_boot, i;

    unsigned long bios_offset, vga_bios_offset;

    uint32_t kernel_base, kernel_size, initrd_base, initrd_size;

    PCIBus *pci_bus;

    MacIONVRAMState *nvr;

    int vga_bios_size, bios_size;

    qemu_irq *dummy_irq;

    int pic_mem_index, nvram_mem_index, dbdma_mem_index, cuda_mem_index;

    int ppc_boot_device = boot_device[0];

    linux_boot = (kernel_filename != NULL);

    /* init CPUs */

    if (cpu_model == NULL)

        cpu_model = "default";

    for (i = 0; i < smp_cpus; i++) {

        env = cpu_init(cpu_model);

        if (!env) {

            fprintf(stderr, "Unable to find PowerPC CPU definition\n");

            exit(1);

        }

        /* Set time-base frequency to 100 Mhz */

        cpu_ppc_tb_init(env, 100UL * 1000UL * 1000UL);

        env->osi_call = vga_osi_call;

        qemu_register_reset(&cpu_ppc_reset, env);

        register_savevm("cpu", 0, 3, cpu_save, cpu_load, env);

        envs[i] = env;

    }

    if (env->nip < 0xFFF80000) {

        /* Special test for PowerPC 601:

         * the boot vector is at 0xFFF00100, then we need a 1MB BIOS.

         * But the NVRAM is located at 0xFFF04000...

         */

        cpu_abort(env, "G3BW Mac hardware can not handle 1 MB BIOS\n");

    }

    /* allocate RAM */

    cpu_register_physical_memory(0, ram_size, IO_MEM_RAM);

    /* allocate and load BIOS */

    bios_offset = ram_size + vga_ram_size;

    if (bios_name == NULL)

        bios_name = BIOS_FILENAME;

    snprintf(buf, sizeof(buf), "%s/%s", bios_dir, bios_name);

    bios_size = load_image(buf, phys_ram_base + bios_offset);

    if (bios_size < 0 || bios_size > BIOS_SIZE) {

        cpu_abort(env, "qemu: could not load PowerPC bios '%s'\n", buf);

        exit(1);

    }

    bios_size = (bios_size + 0xfff) & ~0xfff;

    if (bios_size > 0x00080000) {

        /* As the NVRAM is located at 0xFFF04000, we cannot use 1 MB BIOSes */

        cpu_abort(env, "G3BW Mac hardware can not handle 1 MB BIOS\n");

    }

    cpu_register_physical_memory((uint32_t)(-bios_size),

                                 bios_size, bios_offset | IO_MEM_ROM);

    /* allocate and load VGA BIOS */

    vga_bios_offset = bios_offset + bios_size;

    snprintf(buf, sizeof(buf), "%s/%s", bios_dir, VGABIOS_FILENAME);

    vga_bios_size = load_image(buf, phys_ram_base + vga_bios_offset + 8);

    if (vga_bios_size < 0) {

        /* if no bios is present, we can still work */

        fprintf(stderr, "qemu: warning: could not load VGA bios '%s'\n", buf);

        vga_bios_size = 0;

    } else {

        /* set a specific header (XXX: find real Apple format for NDRV

           drivers) */

        phys_ram_base[vga_bios_offset] = 'N';

        phys_ram_base[vga_bios_offset + 1] = 'D';

        phys_ram_base[vga_bios_offset + 2] = 'R';

        phys_ram_base[vga_bios_offset + 3] = 'V';

        cpu_to_be32w((uint32_t *)(phys_ram_base + vga_bios_offset + 4),

                     vga_bios_size);

        vga_bios_size += 8;

    }

    vga_bios_size = (vga_bios_size + 0xfff) & ~0xfff;

    if (linux_boot) {

        kernel_base = KERNEL_LOAD_ADDR;

        /* now we can load the kernel */

        kernel_size = load_image(kernel_filename, phys_ram_base + kernel_base);

        if (kernel_size < 0) {

            cpu_abort(env, "qemu: could not load kernel '%s'\n",

                      kernel_filename);

            exit(1);

        }

        /* load initrd */

        if (initrd_filename) {

            initrd_base = INITRD_LOAD_ADDR;

            initrd_size = load_image(initrd_filename,

                                     phys_ram_base + initrd_base);

            if (initrd_size < 0) {

                cpu_abort(env, "qemu: could not load initial ram disk '%s'\n",

                          initrd_filename);

                exit(1);

            }

        } else {

            initrd_base = 0;

            initrd_size = 0;

        }

        ppc_boot_device = 'm';

    } else {

        kernel_base = 0;

        kernel_size = 0;

        initrd_base = 0;

        initrd_size = 0;

    }

    isa_mem_base = 0x80000000;

    /* Register 2 MB of ISA IO space */

    isa_mmio_init(0xfe000000, 0x00200000);

    /* XXX: we register only 1 output pin for heathrow PIC */

    heathrow_irqs = qemu_mallocz(smp_cpus * sizeof(qemu_irq *));

    heathrow_irqs[0] =

        qemu_mallocz(smp_cpus * sizeof(qemu_irq) * 1);

    /* Connect the heathrow PIC outputs to the 6xx bus */

    for (i = 0; i < smp_cpus; i++) {

        switch (PPC_INPUT(env)) {

        case PPC_FLAGS_INPUT_6xx:

            heathrow_irqs[i] = heathrow_irqs[0] + (i * 1);

            heathrow_irqs[i][0] =

                ((qemu_irq *)env->irq_inputs)[PPC6xx_INPUT_INT];

            break;

        default:

            cpu_abort(env, "Bus model not supported on OldWorld Mac machine\n");

            exit(1);

        }

    }

    /* init basic PC hardware */

    if (PPC_INPUT(env) != PPC_FLAGS_INPUT_6xx) {

        cpu_abort(env, "Only 6xx bus is supported on heathrow machine\n");

        exit(1);

    }

    pic = heathrow_pic_init(&pic_mem_index, 1, heathrow_irqs);

    pci_bus = pci_grackle_init(0xfec00000, pic);

    pci_vga_init(pci_bus, ds, phys_ram_base + ram_size,

                 ram_size, vga_ram_size,

                 vga_bios_offset, vga_bios_size);

    /* XXX: suppress that */

    dummy_irq = i8259_init(NULL);

    /* XXX: use Mac Serial port */

    serial_init(0x3f8, dummy_irq[4], serial_hds[0]);

    for(i = 0; i < nb_nics; i++) {

        if (!nd_table[i].model)

            nd_table[i].model = "ne2k_pci";

        pci_nic_init(pci_bus, &nd_table[i], -1);

    }

    pci_cmd646_ide_init(pci_bus, &bs_table[0], 0);

    /* cuda also initialize ADB */

    cuda_init(&cuda_mem_index, pic[0x12]);

    adb_kbd_init(&adb_bus);

    adb_mouse_init(&adb_bus);

    nvr = macio_nvram_init(&nvram_mem_index, 0x2000);

    pmac_format_nvram_partition(nvr, 0x2000);

    dbdma_init(&dbdma_mem_index);

    macio_init(pci_bus, 0x0017, 1, pic_mem_index, dbdma_mem_index,

               cuda_mem_index, nvr, 0, NULL);

    if (usb_enabled) {

        usb_ohci_init_pci(pci_bus, 3, -1);

    }

    if (graphic_depth != 15 && graphic_depth != 32 && graphic_depth != 8)

        graphic_depth = 15;

    m48t59 = m48t59_init(dummy_irq[8], 0xFFF04000, 0x0074, NVRAM_SIZE, 59);

    nvram.opaque = m48t59;

    nvram.read_fn = &m48t59_read;

    nvram.write_fn = &m48t59_write;

    PPC_NVRAM_set_params(&nvram, NVRAM_SIZE, "HEATHROW", ram_size,

                         ppc_boot_device, kernel_base, kernel_size,

                         kernel_cmdline,

                         initrd_base, initrd_size,

                         /* XXX: need an option to load a NVRAM image */

                         0,

                         graphic_width, graphic_height, graphic_depth);

    /* No PCI init: the BIOS will do it */

    /* Special port to get debug messages from Open-Firmware */

    register_ioport_write(0x0F00, 4, 1, &PPC_debug_write, NULL);

}