static int alac_decode_frame(AVCodecContext *avctx,

                             void *outbuffer, int *outputsize,

                             uint8_t *inbuffer, int input_buffer_size)

{

    ALACContext *alac = avctx->priv_data;

    int channels;

    int32_t outputsamples;

    /* short-circuit null buffers */

    if (!inbuffer || !input_buffer_size)

        return input_buffer_size;

    /* initialize from the extradata */

    if (!alac->context_initialized) {

        if (alac->avctx->extradata_size != ALAC_EXTRADATA_SIZE) {

            av_log(avctx, AV_LOG_ERROR, "alac: expected %d extradata bytes\n",

                ALAC_EXTRADATA_SIZE);

            return input_buffer_size;

        }

        alac_set_info(alac);

        alac->context_initialized = 1;

    }

    outputsamples = alac->setinfo_max_samples_per_frame;

    init_get_bits(&alac->gb, inbuffer, input_buffer_size * 8);

    channels = get_bits(&alac->gb, 3);

    *outputsize = outputsamples * alac->bytespersample;

    switch(channels) {

    case 0: { /* 1 channel */

        int hassize;

        int isnotcompressed;

        int readsamplesize;

        int wasted_bytes;

        int ricemodifier;

        /* 2^result = something to do with output waiting.

         * perhaps matters if we read > 1 frame in a pass?

         */

        get_bits(&alac->gb, 4);

        get_bits(&alac->gb, 12); /* unknown, skip 12 bits */

        hassize = get_bits(&alac->gb, 1); /* the output sample size is stored soon */

        wasted_bytes = get_bits(&alac->gb, 2); /* unknown ? */

        isnotcompressed = get_bits(&alac->gb, 1); /* whether the frame is compressed */

        if (hassize) {

            /* now read the number of samples,

             * as a 32bit integer */

            outputsamples = get_bits(&alac->gb, 32);

            *outputsize = outputsamples * alac->bytespersample;

        }

        readsamplesize = alac->setinfo_sample_size - (wasted_bytes * 8);

        if (!isnotcompressed) {

         /* so it is compressed */

            int16_t predictor_coef_table[32];

            int predictor_coef_num;

            int prediction_type;

            int prediction_quantitization;

            int i;

            /* FIXME: skip 16 bits, not sure what they are. seem to be used in

             * two channel case */

            get_bits(&alac->gb, 8);

            get_bits(&alac->gb, 8);

            prediction_type = get_bits(&alac->gb, 4);

            prediction_quantitization = get_bits(&alac->gb, 4);

            ricemodifier = get_bits(&alac->gb, 3);

            predictor_coef_num = get_bits(&alac->gb, 5);

            /* read the predictor table */

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

                predictor_coef_table[i] = (int16_t)get_bits(&alac->gb, 16);

            }

            if (wasted_bytes) {

                /* these bytes seem to have something to do with

                 * > 2 channel files.

                 */

                av_log(avctx, AV_LOG_ERROR, "FIXME: unimplemented, unhandling of wasted_bytes\n");

            }

            bastardized_rice_decompress(alac,

                                        alac->predicterror_buffer_a,

                                        outputsamples,

                                        readsamplesize,

                                        alac->setinfo_rice_initialhistory,

                                        alac->setinfo_rice_kmodifier,

                                        ricemodifier * alac->setinfo_rice_historymult / 4,

                                        (1 << alac->setinfo_rice_kmodifier) - 1);

            if (prediction_type == 0) {

              /* adaptive fir */

                predictor_decompress_fir_adapt(alac->predicterror_buffer_a,

                                               alac->outputsamples_buffer_a,

                                               outputsamples,

                                               readsamplesize,

                                               predictor_coef_table,

                                               predictor_coef_num,

                                               prediction_quantitization);

            } else {

                av_log(avctx, AV_LOG_ERROR, "FIXME: unhandled prediction type: %i\n", prediction_type);

                /* i think the only other prediction type (or perhaps this is just a

                 * boolean?) runs adaptive fir twice.. like:

                 * predictor_decompress_fir_adapt(predictor_error, tempout, ...)

                 * predictor_decompress_fir_adapt(predictor_error, outputsamples ...)

                 * little strange..

                 */

            }

        } else {

          /* not compressed, easy case */

            if (readsamplesize <= 16) {

                int i;

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

                    int32_t audiobits = get_bits(&alac->gb, readsamplesize);

                    audiobits = SIGN_EXTENDED32(audiobits, readsamplesize);

                    alac->outputsamples_buffer_a[i] = audiobits;

                }

            } else {

                int i;

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

                    int32_t audiobits;

                    audiobits = get_bits(&alac->gb, 16);

                    /* special case of sign extension..

                     * as we'll be ORing the low 16bits into this */

                    audiobits = audiobits << 16;

                    audiobits = audiobits >> (32 - readsamplesize);

                    audiobits |= get_bits(&alac->gb, readsamplesize - 16);

                    alac->outputsamples_buffer_a[i] = audiobits;

                }

            }

            /* wasted_bytes = 0; // unused */

        }

        switch(alac->setinfo_sample_size) {

        case 16: {

            int i;

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

                int16_t sample = alac->outputsamples_buffer_a[i];

                ((int16_t*)outbuffer)[i * alac->numchannels] = sample;

            }

            break;

        }

        case 20:

        case 24:

        case 32:

            av_log(avctx, AV_LOG_ERROR, "FIXME: unimplemented sample size %i\n", alac->setinfo_sample_size);

            break;

        default:

            break;

        }

        break;

    }

    case 1: { /* 2 channels */

        int hassize;

        int isnotcompressed;

        int readsamplesize;

        int wasted_bytes;

        uint8_t interlacing_shift;

        uint8_t interlacing_leftweight;

        /* 2^result = something to do with output waiting.

         * perhaps matters if we read > 1 frame in a pass?

         */

        get_bits(&alac->gb, 4);

        get_bits(&alac->gb, 12); /* unknown, skip 12 bits */

        hassize = get_bits(&alac->gb, 1); /* the output sample size is stored soon */

        wasted_bytes = get_bits(&alac->gb, 2); /* unknown ? */

        isnotcompressed = get_bits(&alac->gb, 1); /* whether the frame is compressed */

        if (hassize) {

            /* now read the number of samples,

             * as a 32bit integer */

            outputsamples = get_bits(&alac->gb, 32);

            *outputsize = outputsamples * alac->bytespersample;

        }

        readsamplesize = alac->setinfo_sample_size - (wasted_bytes * 8) + 1;

        if (!isnotcompressed) {

         /* compressed */

            int16_t predictor_coef_table_a[32];

            int predictor_coef_num_a;

            int prediction_type_a;

            int prediction_quantitization_a;

            int ricemodifier_a;

            int16_t predictor_coef_table_b[32];

            int predictor_coef_num_b;

            int prediction_type_b;

            int prediction_quantitization_b;

            int ricemodifier_b;

            int i;

            interlacing_shift = get_bits(&alac->gb, 8);

            interlacing_leftweight = get_bits(&alac->gb, 8);

            /******** channel 1 ***********/

            prediction_type_a = get_bits(&alac->gb, 4);

            prediction_quantitization_a = get_bits(&alac->gb, 4);

            ricemodifier_a = get_bits(&alac->gb, 3);

            predictor_coef_num_a = get_bits(&alac->gb, 5);

            /* read the predictor table */

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

                predictor_coef_table_a[i] = (int16_t)get_bits(&alac->gb, 16);

            }

            /******** channel 2 *********/

            prediction_type_b = get_bits(&alac->gb, 4);

            prediction_quantitization_b = get_bits(&alac->gb, 4);

            ricemodifier_b = get_bits(&alac->gb, 3);

            predictor_coef_num_b = get_bits(&alac->gb, 5);

            /* read the predictor table */

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

                predictor_coef_table_b[i] = (int16_t)get_bits(&alac->gb, 16);

            }

            /*********************/

            if (wasted_bytes) {

              /* see mono case */

                av_log(avctx, AV_LOG_ERROR, "FIXME: unimplemented, unhandling of wasted_bytes\n");

            }

            /* channel 1 */

            bastardized_rice_decompress(alac,

                                        alac->predicterror_buffer_a,

                                        outputsamples,

                                        readsamplesize,

                                        alac->setinfo_rice_initialhistory,

                                        alac->setinfo_rice_kmodifier,

                                        ricemodifier_a * alac->setinfo_rice_historymult / 4,

                                        (1 << alac->setinfo_rice_kmodifier) - 1);

            if (prediction_type_a == 0) {

              /* adaptive fir */

                predictor_decompress_fir_adapt(alac->predicterror_buffer_a,

                                               alac->outputsamples_buffer_a,

                                               outputsamples,

                                               readsamplesize,

                                               predictor_coef_table_a,

                                               predictor_coef_num_a,

                                               prediction_quantitization_a);

            } else {

              /* see mono case */

                av_log(avctx, AV_LOG_ERROR, "FIXME: unhandled prediction type: %i\n", prediction_type_a);

            }

            /* channel 2 */

            bastardized_rice_decompress(alac,

                                        alac->predicterror_buffer_b,

                                        outputsamples,

                                        readsamplesize,

                                        alac->setinfo_rice_initialhistory,

                                        alac->setinfo_rice_kmodifier,

                                        ricemodifier_b * alac->setinfo_rice_historymult / 4,

                                        (1 << alac->setinfo_rice_kmodifier) - 1);

            if (prediction_type_b == 0) {

              /* adaptive fir */

                predictor_decompress_fir_adapt(alac->predicterror_buffer_b,

                                               alac->outputsamples_buffer_b,

                                               outputsamples,

                                               readsamplesize,

                                               predictor_coef_table_b,

                                               predictor_coef_num_b,

                                               prediction_quantitization_b);

            } else {

                av_log(avctx, AV_LOG_ERROR, "FIXME: unhandled prediction type: %i\n", prediction_type_b);

            }

        } else {

         /* not compressed, easy case */

            if (alac->setinfo_sample_size <= 16) {

                int i;

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

                    int32_t audiobits_a, audiobits_b;

                    audiobits_a = get_bits(&alac->gb, alac->setinfo_sample_size);

                    audiobits_b = get_bits(&alac->gb, alac->setinfo_sample_size);

                    audiobits_a = SIGN_EXTENDED32(audiobits_a, alac->setinfo_sample_size);

                    audiobits_b = SIGN_EXTENDED32(audiobits_b, alac->setinfo_sample_size);

                    alac->outputsamples_buffer_a[i] = audiobits_a;

                    alac->outputsamples_buffer_b[i] = audiobits_b;

                }

            } else {

                int i;

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

                    int32_t audiobits_a, audiobits_b;

                    audiobits_a = get_bits(&alac->gb, 16);

                    audiobits_a = audiobits_a << 16;

                    audiobits_a = audiobits_a >> (32 - alac->setinfo_sample_size);

                    audiobits_a |= get_bits(&alac->gb, alac->setinfo_sample_size - 16);

                    audiobits_b = get_bits(&alac->gb, 16);

                    audiobits_b = audiobits_b << 16;

                    audiobits_b = audiobits_b >> (32 - alac->setinfo_sample_size);

                    audiobits_b |= get_bits(&alac->gb, alac->setinfo_sample_size - 16);

                    alac->outputsamples_buffer_a[i] = audiobits_a;

                    alac->outputsamples_buffer_b[i] = audiobits_b;

                }

            }

            /* wasted_bytes = 0; */

            interlacing_shift = 0;

            interlacing_leftweight = 0;

        }

        switch(alac->setinfo_sample_size) {

        case 16: {

            deinterlace_16(alac->outputsamples_buffer_a,

                           alac->outputsamples_buffer_b,

                           (int16_t*)outbuffer,

                           alac->numchannels,

                           outputsamples,

                           interlacing_shift,

                           interlacing_leftweight);

            break;

        }

        case 20:

        case 24:

        case 32:

            av_log(avctx, AV_LOG_ERROR, "FIXME: unimplemented sample size %i\n", alac->setinfo_sample_size);

            break;

        default:

            break;

        }

        break;

    }

    }

    return input_buffer_size;

}


static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1)

{

    uint32_t insn, imm, shift, offset;

    uint32_t rd, rn, rm, rs;

    TCGv tmp;

    TCGv tmp2;

    TCGv tmp3;

    TCGv addr;

    TCGv_i64 tmp64;

    int op;

    int shiftop;

    int conds;

    int logic_cc;

    if (!(arm_feature(env, ARM_FEATURE_THUMB2)

          || arm_feature (env, ARM_FEATURE_M))) {

        /* Thumb-1 cores may need to treat bl and blx as a pair of

           16-bit instructions to get correct prefetch abort behavior.  */

        insn = insn_hw1;

        if ((insn & (1 << 12)) == 0) {

            /* Second half of blx.  */

            offset = ((insn & 0x7ff) << 1);

            tmp = load_reg(s, 14);

            tcg_gen_addi_i32(tmp, tmp, offset);

            tcg_gen_andi_i32(tmp, tmp, 0xfffffffc);

            tmp2 = new_tmp();

            tcg_gen_movi_i32(tmp2, s->pc | 1);

            store_reg(s, 14, tmp2);

            gen_bx(s, tmp);

            return 0;

        }

        if (insn & (1 << 11)) {

            /* Second half of bl.  */

            offset = ((insn & 0x7ff) << 1) | 1;

            tmp = load_reg(s, 14);

            tcg_gen_addi_i32(tmp, tmp, offset);

            tmp2 = new_tmp();

            tcg_gen_movi_i32(tmp2, s->pc | 1);

            store_reg(s, 14, tmp2);

            gen_bx(s, tmp);

            return 0;

        }

        if ((s->pc & ~TARGET_PAGE_MASK) == 0) {

            /* Instruction spans a page boundary.  Implement it as two

               16-bit instructions in case the second half causes an

               prefetch abort.  */

            offset = ((int32_t)insn << 21) >> 9;

            tcg_gen_movi_i32(cpu_R[14], s->pc + 2 + offset);

            return 0;

        }

        /* Fall through to 32-bit decode.  */

    }

    insn = lduw_code(s->pc);

    s->pc += 2;

    insn |= (uint32_t)insn_hw1 << 16;

    if ((insn & 0xf800e800) != 0xf000e800) {

        ARCH(6T2);

    }

    rn = (insn >> 16) & 0xf;

    rs = (insn >> 12) & 0xf;

    rd = (insn >> 8) & 0xf;

    rm = insn & 0xf;

    switch ((insn >> 25) & 0xf) {

    case 0: case 1: case 2: case 3:

        /* 16-bit instructions.  Should never happen.  */

        abort();

    case 4:

        if (insn & (1 << 22)) {

            /* Other load/store, table branch.  */

            if (insn & 0x01200000) {

                /* Load/store doubleword.  */

                if (rn == 15) {

                    addr = new_tmp();

                    tcg_gen_movi_i32(addr, s->pc & ~3);

                } else {

                    addr = load_reg(s, rn);

                }

                offset = (insn & 0xff) * 4;

                if ((insn & (1 << 23)) == 0)

                    offset = -offset;

                if (insn & (1 << 24)) {

                    tcg_gen_addi_i32(addr, addr, offset);

                    offset = 0;

                }

                if (insn & (1 << 20)) {

                    /* ldrd */

                    tmp = gen_ld32(addr, IS_USER(s));

                    store_reg(s, rs, tmp);

                    tcg_gen_addi_i32(addr, addr, 4);

                    tmp = gen_ld32(addr, IS_USER(s));

                    store_reg(s, rd, tmp);

                } else {

                    /* strd */

                    tmp = load_reg(s, rs);

                    gen_st32(tmp, addr, IS_USER(s));

                    tcg_gen_addi_i32(addr, addr, 4);

                    tmp = load_reg(s, rd);

                    gen_st32(tmp, addr, IS_USER(s));

                }

                if (insn & (1 << 21)) {

                    /* Base writeback.  */

                    if (rn == 15)

                        goto illegal_op;

                    tcg_gen_addi_i32(addr, addr, offset - 4);

                    store_reg(s, rn, addr);

                } else {

                    dead_tmp(addr);

                }

            } else if ((insn & (1 << 23)) == 0) {

                /* Load/store exclusive word.  */

                addr = tcg_temp_local_new();

                load_reg_var(s, addr, rn);

                tcg_gen_addi_i32(addr, addr, (insn & 0xff) << 2);

                if (insn & (1 << 20)) {

                    gen_load_exclusive(s, rs, 15, addr, 2);

                } else {

                    gen_store_exclusive(s, rd, rs, 15, addr, 2);

                }

                tcg_temp_free(addr);

            } else if ((insn & (1 << 6)) == 0) {

                /* Table Branch.  */

                if (rn == 15) {

                    addr = new_tmp();

                    tcg_gen_movi_i32(addr, s->pc);

                } else {

                    addr = load_reg(s, rn);

                }

                tmp = load_reg(s, rm);

                tcg_gen_add_i32(addr, addr, tmp);

                if (insn & (1 << 4)) {

                    /* tbh */

                    tcg_gen_add_i32(addr, addr, tmp);

                    dead_tmp(tmp);

                    tmp = gen_ld16u(addr, IS_USER(s));

                } else { /* tbb */

                    dead_tmp(tmp);

                    tmp = gen_ld8u(addr, IS_USER(s));

                }

                dead_tmp(addr);

                tcg_gen_shli_i32(tmp, tmp, 1);

                tcg_gen_addi_i32(tmp, tmp, s->pc);

                store_reg(s, 15, tmp);

            } else {

                /* Load/store exclusive byte/halfword/doubleword.  */

                ARCH(7);

                op = (insn >> 4) & 0x3;

                if (op == 2) {

                    goto illegal_op;

                }

                addr = tcg_temp_local_new();

                load_reg_var(s, addr, rn);

                if (insn & (1 << 20)) {

                    gen_load_exclusive(s, rs, rd, addr, op);

                } else {

                    gen_store_exclusive(s, rm, rs, rd, addr, op);

                }

                tcg_temp_free(addr);

            }

        } else {

            /* Load/store multiple, RFE, SRS.  */

            if (((insn >> 23) & 1) == ((insn >> 24) & 1)) {

                /* Not available in user mode.  */

                if (IS_USER(s))

                    goto illegal_op;

                if (insn & (1 << 20)) {

                    /* rfe */

                    addr = load_reg(s, rn);

                    if ((insn & (1 << 24)) == 0)

                        tcg_gen_addi_i32(addr, addr, -8);

                    /* Load PC into tmp and CPSR into tmp2.  */

                    tmp = gen_ld32(addr, 0);

                    tcg_gen_addi_i32(addr, addr, 4);

                    tmp2 = gen_ld32(addr, 0);

                    if (insn & (1 << 21)) {

                        /* Base writeback.  */

                        if (insn & (1 << 24)) {

                            tcg_gen_addi_i32(addr, addr, 4);

                        } else {

                            tcg_gen_addi_i32(addr, addr, -4);

                        }

                        store_reg(s, rn, addr);

                    } else {

                        dead_tmp(addr);

                    }

                    gen_rfe(s, tmp, tmp2);

                } else {

                    /* srs */

                    op = (insn & 0x1f);

                    if (op == (env->uncached_cpsr & CPSR_M)) {

                        addr = load_reg(s, 13);

                    } else {

                        addr = new_tmp();

                        tmp = tcg_const_i32(op);

                        gen_helper_get_r13_banked(addr, cpu_env, tmp);

                        tcg_temp_free_i32(tmp);

                    }

                    if ((insn & (1 << 24)) == 0) {

                        tcg_gen_addi_i32(addr, addr, -8);

                    }

                    tmp = load_reg(s, 14);

                    gen_st32(tmp, addr, 0);

                    tcg_gen_addi_i32(addr, addr, 4);

                    tmp = new_tmp();

                    gen_helper_cpsr_read(tmp);

                    gen_st32(tmp, addr, 0);

                    if (insn & (1 << 21)) {

                        if ((insn & (1 << 24)) == 0) {

                            tcg_gen_addi_i32(addr, addr, -4);

                        } else {

                            tcg_gen_addi_i32(addr, addr, 4);

                        }

                        if (op == (env->uncached_cpsr & CPSR_M)) {

                            store_reg(s, 13, addr);

                        } else {

                            tmp = tcg_const_i32(op);

                            gen_helper_set_r13_banked(cpu_env, tmp, addr);

                            tcg_temp_free_i32(tmp);

                        }

                    } else {

                        dead_tmp(addr);

                    }

                }

            } else {

                int i;

                /* Load/store multiple.  */

                addr = load_reg(s, rn);

                offset = 0;

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

                    if (insn & (1 << i))

                        offset += 4;

                }

                if (insn & (1 << 24)) {

                    tcg_gen_addi_i32(addr, addr, -offset);

                }

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

                    if ((insn & (1 << i)) == 0)

                        continue;

                    if (insn & (1 << 20)) {

                        /* Load.  */

                        tmp = gen_ld32(addr, IS_USER(s));

                        if (i == 15) {

                            gen_bx(s, tmp);

                        } else {

                            store_reg(s, i, tmp);

                        }

                    } else {

                        /* Store.  */

                        tmp = load_reg(s, i);

                        gen_st32(tmp, addr, IS_USER(s));

                    }

                    tcg_gen_addi_i32(addr, addr, 4);

                }

                if (insn & (1 << 21)) {

                    /* Base register writeback.  */

                    if (insn & (1 << 24)) {

                        tcg_gen_addi_i32(addr, addr, -offset);

                    }

                    /* Fault if writeback register is in register list.  */

                    if (insn & (1 << rn))

                        goto illegal_op;

                    store_reg(s, rn, addr);

                } else {

                    dead_tmp(addr);

                }

            }

        }

        break;

    case 5:

        op = (insn >> 21) & 0xf;

        if (op == 6) {

            /* Halfword pack.  */

            tmp = load_reg(s, rn);

            tmp2 = load_reg(s, rm);

            shift = ((insn >> 10) & 0x1c) | ((insn >> 6) & 0x3);

            if (insn & (1 << 5)) {

                /* pkhtb */

                if (shift == 0)

                    shift = 31;

                tcg_gen_sari_i32(tmp2, tmp2, shift);

                tcg_gen_andi_i32(tmp, tmp, 0xffff0000);

                tcg_gen_ext16u_i32(tmp2, tmp2);

            } else {

                /* pkhbt */

                if (shift)

                    tcg_gen_shli_i32(tmp2, tmp2, shift);

                tcg_gen_ext16u_i32(tmp, tmp);

                tcg_gen_andi_i32(tmp2, tmp2, 0xffff0000);

            }

            tcg_gen_or_i32(tmp, tmp, tmp2);

            dead_tmp(tmp2);

            store_reg(s, rd, tmp);

        } else {

            /* Data processing register constant shift.  */

            if (rn == 15) {

                tmp = new_tmp();

                tcg_gen_movi_i32(tmp, 0);

            } else {

                tmp = load_reg(s, rn);

            }

            tmp2 = load_reg(s, rm);

            shiftop = (insn >> 4) & 3;

            shift = ((insn >> 6) & 3) | ((insn >> 10) & 0x1c);

            conds = (insn & (1 << 20)) != 0;

            logic_cc = (conds && thumb2_logic_op(op));

            gen_arm_shift_im(tmp2, shiftop, shift, logic_cc);

            if (gen_thumb2_data_op(s, op, conds, 0, tmp, tmp2))

                goto illegal_op;

            dead_tmp(tmp2);

            if (rd != 15) {

                store_reg(s, rd, tmp);

            } else {

                dead_tmp(tmp);

            }

        }

        break;

    case 13: /* Misc data processing.  */

        op = ((insn >> 22) & 6) | ((insn >> 7) & 1);

        if (op < 4 && (insn & 0xf000) != 0xf000)

            goto illegal_op;

        switch (op) {

        case 0: /* Register controlled shift.  */

            tmp = load_reg(s, rn);

            tmp2 = load_reg(s, rm);

            if ((insn & 0x70) != 0)

                goto illegal_op;

            op = (insn >> 21) & 3;

            logic_cc = (insn & (1 << 20)) != 0;

            gen_arm_shift_reg(tmp, op, tmp2, logic_cc);

            if (logic_cc)

                gen_logic_CC(tmp);

            store_reg_bx(env, s, rd, tmp);

            break;

        case 1: /* Sign/zero extend.  */

            tmp = load_reg(s, rm);

            shift = (insn >> 4) & 3;

            /* ??? In many cases it's not neccessary to do a

               rotate, a shift is sufficient.  */

            if (shift != 0)

                tcg_gen_rotri_i32(tmp, tmp, shift * 8);

            op = (insn >> 20) & 7;

            switch (op) {

            case 0: gen_sxth(tmp);   break;

            case 1: gen_uxth(tmp);   break;

            case 2: gen_sxtb16(tmp); break;

            case 3: gen_uxtb16(tmp); break;

            case 4: gen_sxtb(tmp);   break;

            case 5: gen_uxtb(tmp);   break;

            default: goto illegal_op;

            }

            if (rn != 15) {

                tmp2 = load_reg(s, rn);

                if ((op >> 1) == 1) {

                    gen_add16(tmp, tmp2);

                } else {

                    tcg_gen_add_i32(tmp, tmp, tmp2);

                    dead_tmp(tmp2);

                }

            }

            store_reg(s, rd, tmp);

            break;

        case 2: /* SIMD add/subtract.  */

            op = (insn >> 20) & 7;

            shift = (insn >> 4) & 7;

            if ((op & 3) == 3 || (shift & 3) == 3)

                goto illegal_op;

            tmp = load_reg(s, rn);

            tmp2 = load_reg(s, rm);

            gen_thumb2_parallel_addsub(op, shift, tmp, tmp2);

            dead_tmp(tmp2);

            store_reg(s, rd, tmp);

            break;

        case 3: /* Other data processing.  */

            op = ((insn >> 17) & 0x38) | ((insn >> 4) & 7);

            if (op < 4) {

                /* Saturating add/subtract.  */

                tmp = load_reg(s, rn);

                tmp2 = load_reg(s, rm);

                if (op & 1)

                    gen_helper_double_saturate(tmp, tmp);

                if (op & 2)

                    gen_helper_sub_saturate(tmp, tmp2, tmp);

                else

                    gen_helper_add_saturate(tmp, tmp, tmp2);

                dead_tmp(tmp2);

            } else {

                tmp = load_reg(s, rn);

                switch (op) {

                case 0x0a: /* rbit */

                    gen_helper_rbit(tmp, tmp);

                    break;

                case 0x08: /* rev */

                    tcg_gen_bswap32_i32(tmp, tmp);

                    break;

                case 0x09: /* rev16 */

                    gen_rev16(tmp);

                    break;

                case 0x0b: /* revsh */

                    gen_revsh(tmp);

                    break;

                case 0x10: /* sel */

                    tmp2 = load_reg(s, rm);

                    tmp3 = new_tmp();

                    tcg_gen_ld_i32(tmp3, cpu_env, offsetof(CPUState, GE));

                    gen_helper_sel_flags(tmp, tmp3, tmp, tmp2);

                    dead_tmp(tmp3);

                    dead_tmp(tmp2);

                    break;

                case 0x18: /* clz */

                    gen_helper_clz(tmp, tmp);

                    break;

                default:

                    goto illegal_op;

                }

            }

            store_reg(s, rd, tmp);

            break;

        case 4: case 5: /* 32-bit multiply.  Sum of absolute differences.  */

            op = (insn >> 4) & 0xf;

            tmp = load_reg(s, rn);

            tmp2 = load_reg(s, rm);

            switch ((insn >> 20) & 7) {

            case 0: /* 32 x 32 -> 32 */

                tcg_gen_mul_i32(tmp, tmp, tmp2);

                dead_tmp(tmp2);

                if (rs != 15) {

                    tmp2 = load_reg(s, rs);

                    if (op)

                        tcg_gen_sub_i32(tmp, tmp2, tmp);

                    else

                        tcg_gen_add_i32(tmp, tmp, tmp2);

                    dead_tmp(tmp2);

                }

                break;

            case 1: /* 16 x 16 -> 32 */

                gen_mulxy(tmp, tmp2, op & 2, op & 1);

                dead_tmp(tmp2);

                if (rs != 15) {

                    tmp2 = load_reg(s, rs);

                    gen_helper_add_setq(tmp, tmp, tmp2);

                    dead_tmp(tmp2);

                }

                break;

            case 2: /* Dual multiply add.  */

            case 4: /* Dual multiply subtract.  */

                if (op)

                    gen_swap_half(tmp2);

                gen_smul_dual(tmp, tmp2);

                /* This addition cannot overflow.  */

                if (insn & (1 << 22)) {

                    tcg_gen_sub_i32(tmp, tmp, tmp2);

                } else {

                    tcg_gen_add_i32(tmp, tmp, tmp2);

                }

                dead_tmp(tmp2);

                if (rs != 15)

                  {

                    tmp2 = load_reg(s, rs);

                    gen_helper_add_setq(tmp, tmp, tmp2);

                    dead_tmp(tmp2);

                  }

                break;

            case 3: /* 32 * 16 -> 32msb */

                if (op)

                    tcg_gen_sari_i32(tmp2, tmp2, 16);

                else

                    gen_sxth(tmp2);

                tmp64 = gen_muls_i64_i32(tmp, tmp2);

                tcg_gen_shri_i64(tmp64, tmp64, 16);

                tmp = new_tmp();

                tcg_gen_trunc_i64_i32(tmp, tmp64);

                tcg_temp_free_i64(tmp64);

                if (rs != 15)

                  {

                    tmp2 = load_reg(s, rs);

                    gen_helper_add_setq(tmp, tmp, tmp2);

                    dead_tmp(tmp2);

                  }

                break;

            case 5: case 6: /* 32 * 32 -> 32msb (SMMUL, SMMLA, SMMLS) */

                tmp64 = gen_muls_i64_i32(tmp, tmp2);

                if (rs != 15) {

                    tmp = load_reg(s, rs);

                    if (insn & (1 << 20)) {

                        tmp64 = gen_addq_msw(tmp64, tmp);

                    } else {

                        tmp64 = gen_subq_msw(tmp64, tmp);

                    }

                }

                if (insn & (1 << 4)) {

                    tcg_gen_addi_i64(tmp64, tmp64, 0x80000000u);

                }

                tcg_gen_shri_i64(tmp64, tmp64, 32);

                tmp = new_tmp();

                tcg_gen_trunc_i64_i32(tmp, tmp64);

                tcg_temp_free_i64(tmp64);

                break;

            case 7: /* Unsigned sum of absolute differences.  */

                gen_helper_usad8(tmp, tmp, tmp2);

                dead_tmp(tmp2);

                if (rs != 15) {

                    tmp2 = load_reg(s, rs);

                    tcg_gen_add_i32(tmp, tmp, tmp2);

                    dead_tmp(tmp2);

                }

                break;

            }

            store_reg(s, rd, tmp);

            break;

        case 6: case 7: /* 64-bit multiply, Divide.  */

            op = ((insn >> 4) & 0xf) | ((insn >> 16) & 0x70);

            tmp = load_reg(s, rn);

            tmp2 = load_reg(s, rm);

            if ((op & 0x50) == 0x10) {

                /* sdiv, udiv */

                if (!arm_feature(env, ARM_FEATURE_DIV))

                    goto illegal_op;

                if (op & 0x20)

                    gen_helper_udiv(tmp, tmp, tmp2);

                else

                    gen_helper_sdiv(tmp, tmp, tmp2);

                dead_tmp(tmp2);

                store_reg(s, rd, tmp);

            } else if ((op & 0xe) == 0xc) {

                /* Dual multiply accumulate long.  */

                if (op & 1)

                    gen_swap_half(tmp2);

                gen_smul_dual(tmp, tmp2);

                if (op & 0x10) {

                    tcg_gen_sub_i32(tmp, tmp, tmp2);

                } else {

                    tcg_gen_add_i32(tmp, tmp, tmp2);

                }

                dead_tmp(tmp2);

                /* BUGFIX */

                tmp64 = tcg_temp_new_i64();

                tcg_gen_ext_i32_i64(tmp64, tmp);

                dead_tmp(tmp);

                gen_addq(s, tmp64, rs, rd);

                gen_storeq_reg(s, rs, rd, tmp64);

                tcg_temp_free_i64(tmp64);

            } else {

                if (op & 0x20) {

                    /* Unsigned 64-bit multiply  */

                    tmp64 = gen_mulu_i64_i32(tmp, tmp2);

                } else {

                    if (op & 8) {

                        /* smlalxy */

                        gen_mulxy(tmp, tmp2, op & 2, op & 1);

                        dead_tmp(tmp2);

                        tmp64 = tcg_temp_new_i64();

                        tcg_gen_ext_i32_i64(tmp64, tmp);

                        dead_tmp(tmp);

                    } else {

                        /* Signed 64-bit multiply  */

                        tmp64 = gen_muls_i64_i32(tmp, tmp2);

                    }

                }

                if (op & 4) {

                    /* umaal */

                    gen_addq_lo(s, tmp64, rs);

                    gen_addq_lo(s, tmp64, rd);

                } else if (op & 0x40) {

                    /* 64-bit accumulate.  */

                    gen_addq(s, tmp64, rs, rd);

                }

                gen_storeq_reg(s, rs, rd, tmp64);

                tcg_temp_free_i64(tmp64);

            }

            break;

        }

        break;

    case 6: case 7: case 14: case 15:

        /* Coprocessor.  */

        if (((insn >> 24) & 3) == 3) {

            /* Translate into the equivalent ARM encoding.  */

            insn = (insn & 0xe2ffffff) | ((insn & (1 << 28)) >> 4);

            if (disas_neon_data_insn(env, s, insn))

                goto illegal_op;

        } else {

            if (insn & (1 << 28))

                goto illegal_op;

            if (disas_coproc_insn (env, s, insn))

                goto illegal_op;

        }

        break;

    case 8: case 9: case 10: case 11:

        if (insn & (1 << 15)) {

            /* Branches, misc control.  */

            if (insn & 0x5000) {

                /* Unconditional branch.  */

                /* signextend(hw1[10:0]) -> offset[:12].  */

                offset = ((int32_t)insn << 5) >> 9 & ~(int32_t)0xfff;

                /* hw1[10:0] -> offset[11:1].  */

                offset |= (insn & 0x7ff) << 1;

                /* (~hw2[13, 11] ^ offset[24]) -> offset[23,22]

                   offset[24:22] already have the same value because of the

                   sign extension above.  */

                offset ^= ((~insn) & (1 << 13)) << 10;

                offset ^= ((~insn) & (1 << 11)) << 11;

                if (insn & (1 << 14)) {

                    /* Branch and link.  */

                    tcg_gen_movi_i32(cpu_R[14], s->pc | 1);

                }

                offset += s->pc;

                if (insn & (1 << 12)) {

                    /* b/bl */

                    gen_jmp(s, offset);

                } else {

                    /* blx */

                    offset &= ~(uint32_t)2;

                    gen_bx_im(s, offset);

                }

            } else if (((insn >> 23) & 7) == 7) {

                /* Misc control */

                if (insn & (1 << 13))

                    goto illegal_op;

                if (insn & (1 << 26)) {

                    /* Secure monitor call (v6Z) */

                    goto illegal_op; /* not implemented.  */

                } else {

                    op = (insn >> 20) & 7;

                    switch (op) {

                    case 0: /* msr cpsr.  */

                        if (IS_M(env)) {

                            tmp = load_reg(s, rn);

                            addr = tcg_const_i32(insn & 0xff);

                            gen_helper_v7m_msr(cpu_env, addr, tmp);

                            tcg_temp_free_i32(addr);

                            dead_tmp(tmp);

                            gen_lookup_tb(s);

                            break;

                        }

                        /* fall through */

                    case 1: /* msr spsr.  */

                        if (IS_M(env))

                            goto illegal_op;

                        tmp = load_reg(s, rn);

                        if (gen_set_psr(s,

                              msr_mask(env, s, (insn >> 8) & 0xf, op == 1),

                              op == 1, tmp))

                            goto illegal_op;

                        break;

                    case 2: /* cps, nop-hint.  */

                        if (((insn >> 8) & 7) == 0) {

                            gen_nop_hint(s, insn & 0xff);

                        }

                        /* Implemented as NOP in user mode.  */

                        if (IS_USER(s))

                            break;

                        offset = 0;

                        imm = 0;

                        if (insn & (1 << 10)) {

                            if (insn & (1 << 7))

                                offset |= CPSR_A;

                            if (insn & (1 << 6))

                                offset |= CPSR_I;

                            if (insn & (1 << 5))

                                offset |= CPSR_F;

                            if (insn & (1 << 9))

                                imm = CPSR_A | CPSR_I | CPSR_F;

                        }

                        if (insn & (1 << 8)) {

                            offset |= 0x1f;

                            imm |= (insn & 0x1f);

                        }

                        if (offset) {

                            gen_set_psr_im(s, offset, 0, imm);

                        }

                        break;

                    case 3: /* Special control operations.  */

                        ARCH(7);

                        op = (insn >> 4) & 0xf;

                        switch (op) {

                        case 2: /* clrex */

                            gen_clrex(s);

                            break;

                        case 4: /* dsb */

                        case 5: /* dmb */

                        case 6: /* isb */

                            /* These execute as NOPs.  */

                            break;

                        default:

                            goto illegal_op;

                        }

                        break;

                    case 4: /* bxj */

                        /* Trivial implementation equivalent to bx.  */

                        tmp = load_reg(s, rn);

                        gen_bx(s, tmp);

                        break;

                    case 5: /* Exception return.  */

                        if (IS_USER(s)) {

                            goto illegal_op;

                        }

                        if (rn != 14 || rd != 15) {

                            goto illegal_op;

                        }

                        tmp = load_reg(s, rn);

                        tcg_gen_subi_i32(tmp, tmp, insn & 0xff);

                        gen_exception_return(s, tmp);

                        break;

                    case 6: /* mrs cpsr.  */

                        tmp = new_tmp();

                        if (IS_M(env)) {

                            addr = tcg_const_i32(insn & 0xff);

                            gen_helper_v7m_mrs(tmp, cpu_env, addr);

                            tcg_temp_free_i32(addr);

                        } else {

                            gen_helper_cpsr_read(tmp);

                        }

                        store_reg(s, rd, tmp);

                        break;

                    case 7: /* mrs spsr.  */

                        /* Not accessible in user mode.  */

                        if (IS_USER(s) || IS_M(env))

                            goto illegal_op;

                        tmp = load_cpu_field(spsr);

                        store_reg(s, rd, tmp);

                        break;

                    }

                }

            } else {

                /* Conditional branch.  */

                op = (insn >> 22) & 0xf;

                /* Generate a conditional jump to next instruction.  */

                s->condlabel = gen_new_label();

                gen_test_cc(op ^ 1, s->condlabel);

                s->condjmp = 1;

                /* offset[11:1] = insn[10:0] */

                offset = (insn & 0x7ff) << 1;

                /* offset[17:12] = insn[21:16].  */

                offset |= (insn & 0x003f0000) >> 4;

                /* offset[31:20] = insn[26].  */

                offset |= ((int32_t)((insn << 5) & 0x80000000)) >> 11;

                /* offset[18] = insn[13].  */

                offset |= (insn & (1 << 13)) << 5;

                /* offset[19] = insn[11].  */

                offset |= (insn & (1 << 11)) << 8;

                /* jump to the offset */

                gen_jmp(s, s->pc + offset);

            }

        } else {

            /* Data processing immediate.  */

            if (insn & (1 << 25)) {

                if (insn & (1 << 24)) {

                    if (insn & (1 << 20))

                        goto illegal_op;

                    /* Bitfield/Saturate.  */

                    op = (insn >> 21) & 7;

                    imm = insn & 0x1f;

                    shift = ((insn >> 6) & 3) | ((insn >> 10) & 0x1c);

                    if (rn == 15) {

                        tmp = new_tmp();

                        tcg_gen_movi_i32(tmp, 0);

                    } else {

                        tmp = load_reg(s, rn);

                    }

                    switch (op) {

                    case 2: /* Signed bitfield extract.  */

                        imm++;

                        if (shift + imm > 32)

                            goto illegal_op;

                        if (imm < 32)

                            gen_sbfx(tmp, shift, imm);

                        break;

                    case 6: /* Unsigned bitfield extract.  */

                        imm++;

                        if (shift + imm > 32)

                            goto illegal_op;

                        if (imm < 32)

                            gen_ubfx(tmp, shift, (1u << imm) - 1);

                        break;

                    case 3: /* Bitfield insert/clear.  */

                        if (imm < shift)

                            goto illegal_op;

                        imm = imm + 1 - shift;

                        if (imm != 32) {

                            tmp2 = load_reg(s, rd);

                            gen_bfi(tmp, tmp2, tmp, shift, (1u << imm) - 1);

                            dead_tmp(tmp2);

                        }

                        break;

                    case 7:

                        goto illegal_op;

                    default: /* Saturate.  */

                        if (shift) {

                            if (op & 1)

                                tcg_gen_sari_i32(tmp, tmp, shift);

                            else

                                tcg_gen_shli_i32(tmp, tmp, shift);

                        }

                        tmp2 = tcg_const_i32(imm);

                        if (op & 4) {

                            /* Unsigned.  */

                            if ((op & 1) && shift == 0)

                                gen_helper_usat16(tmp, tmp, tmp2);

                            else

                                gen_helper_usat(tmp, tmp, tmp2);

                        } else {

                            /* Signed.  */

                            if ((op & 1) && shift == 0)

                                gen_helper_ssat16(tmp, tmp, tmp2);

                            else

                                gen_helper_ssat(tmp, tmp, tmp2);

                        }

                        tcg_temp_free_i32(tmp2);

                        break;

                    }

                    store_reg(s, rd, tmp);

                } else {

                    imm = ((insn & 0x04000000) >> 15)

                          | ((insn & 0x7000) >> 4) | (insn & 0xff);

                    if (insn & (1 << 22)) {

                        /* 16-bit immediate.  */

                        imm |= (insn >> 4) & 0xf000;

                        if (insn & (1 << 23)) {

                            /* movt */

                            tmp = load_reg(s, rd);

                            tcg_gen_ext16u_i32(tmp, tmp);

                            tcg_gen_ori_i32(tmp, tmp, imm << 16);

                        } else {

                            /* movw */

                            tmp = new_tmp();

                            tcg_gen_movi_i32(tmp, imm);

                        }

                    } else {

                        /* Add/sub 12-bit immediate.  */

                        if (rn == 15) {

                            offset = s->pc & ~(uint32_t)3;

                            if (insn & (1 << 23))

                                offset -= imm;

                            else

                                offset += imm;

                            tmp = new_tmp();

                            tcg_gen_movi_i32(tmp, offset);

                        } else {

                            tmp = load_reg(s, rn);

                            if (insn & (1 << 23))

                                tcg_gen_subi_i32(tmp, tmp, imm);

                            else

                                tcg_gen_addi_i32(tmp, tmp, imm);

                        }

                    }

                    store_reg(s, rd, tmp);

                }

            } else {

                int shifter_out = 0;

                /* modified 12-bit immediate.  */

                shift = ((insn & 0x04000000) >> 23) | ((insn & 0x7000) >> 12);

                imm = (insn & 0xff);

                switch (shift) {

                case 0: /* XY */

                    /* Nothing to do.  */

                    break;

                case 1: /* 00XY00XY */

                    imm |= imm << 16;

                    break;

                case 2: /* XY00XY00 */

                    imm |= imm << 16;

                    imm <<= 8;

                    break;

                case 3: /* XYXYXYXY */

                    imm |= imm << 16;

                    imm |= imm << 8;

                    break;

                default: /* Rotated constant.  */

                    shift = (shift << 1) | (imm >> 7);

                    imm |= 0x80;

                    imm = imm << (32 - shift);

                    shifter_out = 1;

                    break;

                }

                tmp2 = new_tmp();

                tcg_gen_movi_i32(tmp2, imm);

                rn = (insn >> 16) & 0xf;

                if (rn == 15) {

                    tmp = new_tmp();

                    tcg_gen_movi_i32(tmp, 0);

                } else {

                    tmp = load_reg(s, rn);

                }

                op = (insn >> 21) & 0xf;

                if (gen_thumb2_data_op(s, op, (insn & (1 << 20)) != 0,

                                       shifter_out, tmp, tmp2))

                    goto illegal_op;

                dead_tmp(tmp2);

                rd = (insn >> 8) & 0xf;

                if (rd != 15) {

                    store_reg(s, rd, tmp);

                } else {

                    dead_tmp(tmp);

                }

            }

        }

        break;

    case 12: /* Load/store single data item.  */

        {

        int postinc = 0;

        int writeback = 0;

        int user;

        if ((insn & 0x01100000) == 0x01000000) {

            if (disas_neon_ls_insn(env, s, insn))

                goto illegal_op;

            break;

        }

        user = IS_USER(s);

        if (rn == 15) {

            addr = new_tmp();

            /* PC relative.  */

            /* s->pc has already been incremented by 4.  */

            imm = s->pc & 0xfffffffc;

            if (insn & (1 << 23))

                imm += insn & 0xfff;

            else

                imm -= insn & 0xfff;

            tcg_gen_movi_i32(addr, imm);

        } else {

            addr = load_reg(s, rn);

            if (insn & (1 << 23)) {

                /* Positive offset.  */

                imm = insn & 0xfff;

                tcg_gen_addi_i32(addr, addr, imm);

            } else {

                op = (insn >> 8) & 7;

                imm = insn & 0xff;

                switch (op) {

                case 0: case 8: /* Shifted Register.  */

                    shift = (insn >> 4) & 0xf;

                    if (shift > 3)

                        goto illegal_op;

                    tmp = load_reg(s, rm);

                    if (shift)

                        tcg_gen_shli_i32(tmp, tmp, shift);

                    tcg_gen_add_i32(addr, addr, tmp);

                    dead_tmp(tmp);

                    break;

                case 4: /* Negative offset.  */

                    tcg_gen_addi_i32(addr, addr, -imm);

                    break;

                case 6: /* User privilege.  */

                    tcg_gen_addi_i32(addr, addr, imm);

                    user = 1;

                    break;

                case 1: /* Post-decrement.  */

                    imm = -imm;

                    /* Fall through.  */

                case 3: /* Post-increment.  */

                    postinc = 1;

                    writeback = 1;

                    break;

                case 5: /* Pre-decrement.  */

                    imm = -imm;

                    /* Fall through.  */

                case 7: /* Pre-increment.  */

                    tcg_gen_addi_i32(addr, addr, imm);

                    writeback = 1;

                    break;

                default:

                    goto illegal_op;

                }

            }

        }

        op = ((insn >> 21) & 3) | ((insn >> 22) & 4);

        if (insn & (1 << 20)) {

            /* Load.  */

            if (rs == 15 && op != 2) {

                if (op & 2)

                    goto illegal_op;

                /* Memory hint.  Implemented as NOP.  */

            } else {

                switch (op) {

                case 0: tmp = gen_ld8u(addr, user); break;

                case 4: tmp = gen_ld8s(addr, user); break;

                case 1: tmp = gen_ld16u(addr, user); break;

                case 5: tmp = gen_ld16s(addr, user); break;

                case 2: tmp = gen_ld32(addr, user); break;

                default: goto illegal_op;

                }

                if (rs == 15) {

                    gen_bx(s, tmp);

                } else {

                    store_reg(s, rs, tmp);

                }

            }

        } else {

            /* Store.  */

            if (rs == 15)

                goto illegal_op;

            tmp = load_reg(s, rs);

            switch (op) {

            case 0: gen_st8(tmp, addr, user); break;

            case 1: gen_st16(tmp, addr, user); break;

            case 2: gen_st32(tmp, addr, user); break;

            default: goto illegal_op;

            }

        }

        if (postinc)

            tcg_gen_addi_i32(addr, addr, imm);

        if (writeback) {

            store_reg(s, rn, addr);

        } else {

            dead_tmp(addr);

        }

        }

        break;

    default:

        goto illegal_op;

    }

    return 0;

illegal_op:

    return 1;

}


size_t iov_to_buf(const struct iovec *iov, const unsigned int iov_cnt, size_t iov_off,

                  void *buf, size_t size)

{

    uint8_t *ptr;

    size_t iovec_off, buf_off;

    unsigned int i;

    ptr = buf;

    iovec_off = 0;

    buf_off = 0;

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

        if (iov_off < (iovec_off + iov[i].iov_len)) {

            size_t len = MIN((iovec_off + iov[i].iov_len) - iov_off , size);

            memcpy(ptr + buf_off, iov[i].iov_base + (iov_off - iovec_off), len);

            buf_off += len;

            iov_off += len;

            size -= len;

        }

        iovec_off += iov[i].iov_len;

    }

    return buf_off;

}


void hmp_savevm(Monitor *mon, const QDict *qdict)

{

    BlockDriverState *bs, *bs1;

    QEMUSnapshotInfo sn1, *sn = &sn1, old_sn1, *old_sn = &old_sn1;

    int ret;

    QEMUFile *f;

    int saved_vm_running;

    uint64_t vm_state_size;

    qemu_timeval tv;

    struct tm tm;

    const char *name = qdict_get_try_str(qdict, "name");

    Error *local_err = NULL;

    AioContext *aio_context;

    if (!bdrv_all_can_snapshot(&bs)) {

        monitor_printf(mon, "Device '%s' is writable but does not "

                       "support snapshots.\n", bdrv_get_device_name(bs));

        return;

    }

    /* Delete old snapshots of the same name */

    if (name && bdrv_all_delete_snapshot(name, &bs1, &local_err) < 0) {

        error_reportf_err(local_err,

                          "Error while deleting snapshot on device '%s': ",

                          bdrv_get_device_name(bs1));

        return;

    }

    bs = bdrv_all_find_vmstate_bs();

    if (bs == NULL) {

        monitor_printf(mon, "No block device can accept snapshots\n");

        return;

    }

    aio_context = bdrv_get_aio_context(bs);

    saved_vm_running = runstate_is_running();

    ret = global_state_store();

    if (ret) {

        monitor_printf(mon, "Error saving global state\n");

        return;

    }

    vm_stop(RUN_STATE_SAVE_VM);

    aio_context_acquire(aio_context);

    memset(sn, 0, sizeof(*sn));

    /* fill auxiliary fields */

    qemu_gettimeofday(&tv);

    sn->date_sec = tv.tv_sec;

    sn->date_nsec = tv.tv_usec * 1000;

    sn->vm_clock_nsec = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);

    if (name) {

        ret = bdrv_snapshot_find(bs, old_sn, name);

        if (ret >= 0) {

            pstrcpy(sn->name, sizeof(sn->name), old_sn->name);

            pstrcpy(sn->id_str, sizeof(sn->id_str), old_sn->id_str);

        } else {

            pstrcpy(sn->name, sizeof(sn->name), name);

        }

    } else {

        /* cast below needed for OpenBSD where tv_sec is still 'long' */

        localtime_r((const time_t *)&tv.tv_sec, &tm);

        strftime(sn->name, sizeof(sn->name), "vm-%Y%m%d%H%M%S", &tm);

    }

    /* save the VM state */

    f = qemu_fopen_bdrv(bs, 1);

    if (!f) {

        monitor_printf(mon, "Could not open VM state file\n");

        goto the_end;

    }

    ret = qemu_savevm_state(f, &local_err);

    vm_state_size = qemu_ftell(f);

    qemu_fclose(f);

    if (ret < 0) {

        error_report_err(local_err);

        goto the_end;

    }

    ret = bdrv_all_create_snapshot(sn, bs, vm_state_size, &bs);

    if (ret < 0) {

        monitor_printf(mon, "Error while creating snapshot on '%s'\n",

                       bdrv_get_device_name(bs));

    }

 the_end:

    aio_context_release(aio_context);

    if (saved_vm_running) {

        vm_start();

    }

}


static coroutine_fn int qcow2_co_pwritev(BlockDriverState *bs, uint64_t offset,

                                         uint64_t bytes, QEMUIOVector *qiov,

                                         int flags)

{

    BDRVQcow2State *s = bs->opaque;

    int offset_in_cluster;

    int ret;

    unsigned int cur_bytes; /* number of sectors in current iteration */

    uint64_t cluster_offset;

    QEMUIOVector hd_qiov;

    uint64_t bytes_done = 0;

    uint8_t *cluster_data = NULL;

    QCowL2Meta *l2meta = NULL;

    trace_qcow2_writev_start_req(qemu_coroutine_self(), offset, bytes);

    qemu_iovec_init(&hd_qiov, qiov->niov);

    s->cluster_cache_offset = -1; /* disable compressed cache */

    qemu_co_mutex_lock(&s->lock);

    while (bytes != 0) {

        l2meta = NULL;

        trace_qcow2_writev_start_part(qemu_coroutine_self());

        offset_in_cluster = offset_into_cluster(s, offset);

        cur_bytes = MIN(bytes, INT_MAX);

        if (bs->encrypted) {

            cur_bytes = MIN(cur_bytes,

                            QCOW_MAX_CRYPT_CLUSTERS * s->cluster_size

                            - offset_in_cluster);

        }

        ret = qcow2_alloc_cluster_offset(bs, offset, &cur_bytes,

                                         &cluster_offset, &l2meta);

        if (ret < 0) {

            goto fail;

        }

        assert((cluster_offset & 511) == 0);

        qemu_iovec_reset(&hd_qiov);

        qemu_iovec_concat(&hd_qiov, qiov, bytes_done, cur_bytes);

        if (bs->encrypted) {

            Error *err = NULL;

            assert(s->cipher);

            if (!cluster_data) {

                cluster_data = qemu_try_blockalign(bs->file->bs,

                                                   QCOW_MAX_CRYPT_CLUSTERS

                                                   * s->cluster_size);

                if (cluster_data == NULL) {

                    ret = -ENOMEM;

                    goto fail;

                }

            }

            assert(hd_qiov.size <=

                   QCOW_MAX_CRYPT_CLUSTERS * s->cluster_size);

            qemu_iovec_to_buf(&hd_qiov, 0, cluster_data, hd_qiov.size);

            if (qcow2_encrypt_sectors(s, offset >> BDRV_SECTOR_BITS,

                                      cluster_data,

                                      cur_bytes >>BDRV_SECTOR_BITS,

                                      true, &err) < 0) {

                error_free(err);

                ret = -EIO;

                goto fail;

            }

            qemu_iovec_reset(&hd_qiov);

            qemu_iovec_add(&hd_qiov, cluster_data, cur_bytes);

        }

        ret = qcow2_pre_write_overlap_check(bs, 0,

                cluster_offset + offset_in_cluster, cur_bytes);

        if (ret < 0) {

            goto fail;

        }

        /* If we need to do COW, check if it's possible to merge the

         * writing of the guest data together with that of the COW regions.

         * If it's not possible (or not necessary) then write the

         * guest data now. */

        if (!merge_cow(offset, cur_bytes, &hd_qiov, l2meta)) {

            qemu_co_mutex_unlock(&s->lock);

            BLKDBG_EVENT(bs->file, BLKDBG_WRITE_AIO);

            trace_qcow2_writev_data(qemu_coroutine_self(),

                                    cluster_offset + offset_in_cluster);

            ret = bdrv_co_pwritev(bs->file,

                                  cluster_offset + offset_in_cluster,

                                  cur_bytes, &hd_qiov, 0);

            qemu_co_mutex_lock(&s->lock);

            if (ret < 0) {

                goto fail;

            }

        }

        while (l2meta != NULL) {

            QCowL2Meta *next;

            ret = qcow2_alloc_cluster_link_l2(bs, l2meta);

            if (ret < 0) {

                goto fail;

            }

            /* Take the request off the list of running requests */

            if (l2meta->nb_clusters != 0) {

                QLIST_REMOVE(l2meta, next_in_flight);

            }

            qemu_co_queue_restart_all(&l2meta->dependent_requests);

            next = l2meta->next;

            g_free(l2meta);

            l2meta = next;

        }

        bytes -= cur_bytes;

        offset += cur_bytes;

        bytes_done += cur_bytes;

        trace_qcow2_writev_done_part(qemu_coroutine_self(), cur_bytes);

    }

    ret = 0;

fail:

    qemu_co_mutex_unlock(&s->lock);

    while (l2meta != NULL) {

        QCowL2Meta *next;

        if (l2meta->nb_clusters != 0) {

            QLIST_REMOVE(l2meta, next_in_flight);

        }

        qemu_co_queue_restart_all(&l2meta->dependent_requests);

        next = l2meta->next;

        g_free(l2meta);

        l2meta = next;

    }

    qemu_iovec_destroy(&hd_qiov);

    qemu_vfree(cluster_data);

    trace_qcow2_writev_done_req(qemu_coroutine_self(), ret);

    return ret;

}


static int open_self_maps(void *cpu_env, int fd)

{

#if defined(TARGET_ARM) || defined(TARGET_M68K) || defined(TARGET_UNICORE32)

    CPUState *cpu = ENV_GET_CPU((CPUArchState *)cpu_env);

    TaskState *ts = cpu->opaque;

#endif

    FILE *fp;

    char *line = NULL;

    size_t len = 0;

    ssize_t read;

    fp = fopen("/proc/self/maps", "r");

    if (fp == NULL) {

        return -EACCES;

    }

    while ((read = getline(&line, &len, fp)) != -1) {

        int fields, dev_maj, dev_min, inode;

        uint64_t min, max, offset;

        char flag_r, flag_w, flag_x, flag_p;

        char path[512] = "";

        fields = sscanf(line, "%"PRIx64"-%"PRIx64" %c%c%c%c %"PRIx64" %x:%x %d"

                        " %512s", &min, &max, &flag_r, &flag_w, &flag_x,

                        &flag_p, &offset, &dev_maj, &dev_min, &inode, path);

        if ((fields < 10) || (fields > 11)) {

            continue;

        }

        if (!strncmp(path, "[stack]", 7)) {

            continue;

        }

        if (h2g_valid(min) && h2g_valid(max)) {

            dprintf(fd, TARGET_ABI_FMT_lx "-" TARGET_ABI_FMT_lx

                    " %c%c%c%c %08" PRIx64 " %02x:%02x %d %s%s\n",

                    h2g(min), h2g(max), flag_r, flag_w,

                    flag_x, flag_p, offset, dev_maj, dev_min, inode,

                    path[0] ? "         " : "", path);

        }

    }

    free(line);

    fclose(fp);

#if defined(TARGET_ARM) || defined(TARGET_M68K) || defined(TARGET_UNICORE32)

    dprintf(fd, "%08llx-%08llx rw-p %08llx 00:00 0          [stack]\n",

                (unsigned long long)ts->info->stack_limit,

                (unsigned long long)(ts->info->start_stack +

                                     (TARGET_PAGE_SIZE - 1)) & TARGET_PAGE_MASK,

                (unsigned long long)0);

#endif

    return 0;

}


static void qxl_log_cmd_draw(PCIQXLDevice *qxl, QXLDrawable *draw, int group_id)

{

    fprintf(stderr, ": surface_id %d type %s effect %s",

            draw->surface_id,

            qxl_name(qxl_draw_type, draw->type),

            qxl_name(qxl_draw_effect, draw->effect));

    switch (draw->type) {

    case QXL_DRAW_COPY:

        qxl_log_cmd_draw_copy(qxl, &draw->u.copy, group_id);

        break;

    }

}


int bdrv_enable_write_cache(BlockDriverState *bs)

{

    return bs->enable_write_cache;

}


static int add_doubles_metadata(int count,

                                const char *name, const char *sep,

                                TiffContext *s)

{

    char *ap;

    int i;

    double *dp;

    if (bytestream2_get_bytes_left(&s->gb) < count * sizeof(int64_t))

        return -1;

    dp = av_malloc(count * sizeof(double));

    if (!dp)

        return AVERROR(ENOMEM);

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

        dp[i] = tget_double(&s->gb, s->le);

    ap = doubles2str(dp, count, sep);

    av_freep(&dp);

    if (!ap)

        return AVERROR(ENOMEM);

    av_dict_set(&s->picture.metadata, name, ap, AV_DICT_DONT_STRDUP_VAL);

    return 0;

}


static void device_set_realized(Object *obj, bool value, Error **errp)

{

    DeviceState *dev = DEVICE(obj);

    DeviceClass *dc = DEVICE_GET_CLASS(dev);

    HotplugHandler *hotplug_ctrl;

    BusState *bus;

    Error *local_err = NULL;

    bool unattached_parent = false;

    static int unattached_count;

    if (dev->hotplugged && !dc->hotpluggable) {

        error_setg(errp, QERR_DEVICE_NO_HOTPLUG, object_get_typename(obj));

        return;

    }

    if (value && !dev->realized) {

        if (!obj->parent) {

            gchar *name = g_strdup_printf("device[%d]", unattached_count++);

            object_property_add_child(container_get(qdev_get_machine(),

                                                    "/unattached"),

                                      name, obj, &error_abort);

            unattached_parent = true;

            g_free(name);

        }

        hotplug_ctrl = qdev_get_hotplug_handler(dev);

        if (hotplug_ctrl) {

            hotplug_handler_pre_plug(hotplug_ctrl, dev, &local_err);

            if (local_err != NULL) {

                goto fail;

            }

        }

        if (dc->realize) {

            dc->realize(dev, &local_err);

        }

        if (local_err != NULL) {

            goto fail;

        }

        DEVICE_LISTENER_CALL(realize, Forward, dev);

        if (hotplug_ctrl) {

            hotplug_handler_plug(hotplug_ctrl, dev, &local_err);

        }

        if (local_err != NULL) {

            goto post_realize_fail;

        }

        if (qdev_get_vmsd(dev)) {

            vmstate_register_with_alias_id(dev, -1, qdev_get_vmsd(dev), dev,

                                           dev->instance_id_alias,

                                           dev->alias_required_for_version,

                                           NULL);

        }

        QLIST_FOREACH(bus, &dev->child_bus, sibling) {

            object_property_set_bool(OBJECT(bus), true, "realized",

                                         &local_err);

            if (local_err != NULL) {

                goto child_realize_fail;

            }

        }

        if (dev->hotplugged) {

            device_reset(dev);

        }

        dev->pending_deleted_event = false;

    } else if (!value && dev->realized) {

        Error **local_errp = NULL;

        QLIST_FOREACH(bus, &dev->child_bus, sibling) {

            local_errp = local_err ? NULL : &local_err;

            object_property_set_bool(OBJECT(bus), false, "realized",

                                     local_errp);

        }

        if (qdev_get_vmsd(dev)) {

            vmstate_unregister(dev, qdev_get_vmsd(dev), dev);

        }

        if (dc->unrealize) {

            local_errp = local_err ? NULL : &local_err;

            dc->unrealize(dev, local_errp);

        }

        dev->pending_deleted_event = true;

        DEVICE_LISTENER_CALL(unrealize, Reverse, dev);

    }

    if (local_err != NULL) {

        goto fail;

    }

    dev->realized = value;

    return;

child_realize_fail:

    QLIST_FOREACH(bus, &dev->child_bus, sibling) {

        object_property_set_bool(OBJECT(bus), false, "realized",

                                 NULL);

    }

    if (qdev_get_vmsd(dev)) {

        vmstate_unregister(dev, qdev_get_vmsd(dev), dev);

    }

post_realize_fail:

    if (dc->unrealize) {

        dc->unrealize(dev, NULL);

    }

fail:

    error_propagate(errp, local_err);

    if (unattached_parent) {

        object_unparent(OBJECT(dev));

        unattached_count--;

    }

}


static void serial_update_irq(SerialState *s)

{

    uint8_t tmp_iir = UART_IIR_NO_INT;

    if ((s->ier & UART_IER_RLSI) && (s->lsr & UART_LSR_INT_ANY)) {

        tmp_iir = UART_IIR_RLSI;

    } else if ((s->ier & UART_IER_RDI) && s->timeout_ipending) {

        /* Note that(s->ier & UART_IER_RDI) can mask this interrupt,

         * this is not in the specification but is observed on existing

         * hardware.  */

        tmp_iir = UART_IIR_CTI;

    } else if ((s->ier & UART_IER_RDI) && (s->lsr & UART_LSR_DR)) {

        if (!(s->fcr & UART_FCR_FE)) {

           tmp_iir = UART_IIR_RDI;

        } else if (s->recv_fifo.count >= s->recv_fifo.itl) {

           tmp_iir = UART_IIR_RDI;

        }

    } else if ((s->ier & UART_IER_THRI) && s->thr_ipending) {

        tmp_iir = UART_IIR_THRI;

    } else if ((s->ier & UART_IER_MSI) && (s->msr & UART_MSR_ANY_DELTA)) {

        tmp_iir = UART_IIR_MSI;

    }

    s->iir = tmp_iir | (s->iir & 0xF0);

    if (tmp_iir != UART_IIR_NO_INT) {

        qemu_irq_raise(s->irq);

    } else {

        qemu_irq_lower(s->irq);

    }

}


static void spapr_add_lmbs(DeviceState *dev, uint64_t addr_start, uint64_t size,

                           uint32_t node, bool dedicated_hp_event_source,

                           Error **errp)

{

    sPAPRDRConnector *drc;

    uint32_t nr_lmbs = size/SPAPR_MEMORY_BLOCK_SIZE;

    int i, fdt_offset, fdt_size;

    void *fdt;

    uint64_t addr = addr_start;

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

        drc = spapr_drc_by_id(TYPE_SPAPR_DRC_LMB,

                              addr / SPAPR_MEMORY_BLOCK_SIZE);

        g_assert(drc);

        fdt = create_device_tree(&fdt_size);

        fdt_offset = spapr_populate_memory_node(fdt, node, addr,

                                                SPAPR_MEMORY_BLOCK_SIZE);

        spapr_drc_attach(drc, dev, fdt, fdt_offset, !dev->hotplugged, errp);

        addr += SPAPR_MEMORY_BLOCK_SIZE;

        if (!dev->hotplugged) {

            sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);

            /* guests expect coldplugged LMBs to be pre-allocated */

            drck->set_allocation_state(drc, SPAPR_DR_ALLOCATION_STATE_USABLE);

            drck->set_isolation_state(drc, SPAPR_DR_ISOLATION_STATE_UNISOLATED);

        }

    }

    /* send hotplug notification to the

     * guest only in case of hotplugged memory

     */

    if (dev->hotplugged) {

        if (dedicated_hp_event_source) {

            drc = spapr_drc_by_id(TYPE_SPAPR_DRC_LMB,

                                  addr_start / SPAPR_MEMORY_BLOCK_SIZE);

            spapr_hotplug_req_add_by_count_indexed(SPAPR_DR_CONNECTOR_TYPE_LMB,

                                                   nr_lmbs,

                                                   spapr_drc_index(drc));

        } else {

            spapr_hotplug_req_add_by_count(SPAPR_DR_CONNECTOR_TYPE_LMB,

                                           nr_lmbs);

        }

    }

}


static int vdi_open(BlockDriverState *bs, int flags)

{

    BDRVVdiState *s = bs->opaque;

    VdiHeader header;

    size_t bmap_size;

    int ret;

    logout("\n");

    ret = bdrv_read(bs->file, 0, (uint8_t *)&header, 1);

    if (ret < 0) {

        goto fail;

    }

    vdi_header_to_cpu(&header);

#if defined(CONFIG_VDI_DEBUG)

    vdi_header_print(&header);

#endif

    if (header.disk_size % SECTOR_SIZE != 0) {

        /* 'VBoxManage convertfromraw' can create images with odd disk sizes.

           We accept them but round the disk size to the next multiple of

           SECTOR_SIZE. */

        logout("odd disk size %" PRIu64 " B, round up\n", header.disk_size);

        header.disk_size += SECTOR_SIZE - 1;

        header.disk_size &= ~(SECTOR_SIZE - 1);

    }

    if (header.version != VDI_VERSION_1_1) {

        logout("unsupported version %u.%u\n",

               header.version >> 16, header.version & 0xffff);

        ret = -ENOTSUP;

        goto fail;

    } else if (header.offset_bmap % SECTOR_SIZE != 0) {

        /* We only support block maps which start on a sector boundary. */

        logout("unsupported block map offset 0x%x B\n", header.offset_bmap);

        ret = -ENOTSUP;

        goto fail;

    } else if (header.offset_data % SECTOR_SIZE != 0) {

        /* We only support data blocks which start on a sector boundary. */

        logout("unsupported data offset 0x%x B\n", header.offset_data);

        ret = -ENOTSUP;

        goto fail;

    } else if (header.sector_size != SECTOR_SIZE) {

        logout("unsupported sector size %u B\n", header.sector_size);

        ret = -ENOTSUP;

        goto fail;

    } else if (header.block_size != 1 * MiB) {

        logout("unsupported block size %u B\n", header.block_size);

        ret = -ENOTSUP;

        goto fail;

    } else if (header.disk_size >

               (uint64_t)header.blocks_in_image * header.block_size) {

        logout("unsupported disk size %" PRIu64 " B\n", header.disk_size);

        ret = -ENOTSUP;

        goto fail;

    } else if (!uuid_is_null(header.uuid_link)) {

        logout("link uuid != 0, unsupported\n");

        ret = -ENOTSUP;

        goto fail;

    } else if (!uuid_is_null(header.uuid_parent)) {

        logout("parent uuid != 0, unsupported\n");

        ret = -ENOTSUP;

        goto fail;

    }

    bs->total_sectors = header.disk_size / SECTOR_SIZE;

    s->block_size = header.block_size;

    s->block_sectors = header.block_size / SECTOR_SIZE;

    s->bmap_sector = header.offset_bmap / SECTOR_SIZE;

    s->header = header;

    bmap_size = header.blocks_in_image * sizeof(uint32_t);

    bmap_size = (bmap_size + SECTOR_SIZE - 1) / SECTOR_SIZE;

    if (bmap_size > 0) {

        s->bmap = g_malloc(bmap_size * SECTOR_SIZE);

    }

    ret = bdrv_read(bs->file, s->bmap_sector, (uint8_t *)s->bmap, bmap_size);

    if (ret < 0) {

        goto fail_free_bmap;

    }

    /* Disable migration when vdi images are used */

    error_set(&s->migration_blocker,

              QERR_BLOCK_FORMAT_FEATURE_NOT_SUPPORTED,

              "vdi", bs->device_name, "live migration");

    migrate_add_blocker(s->migration_blocker);

    return 0;

 fail_free_bmap:

    g_free(s->bmap);

 fail:

    return ret;

}


qemu_irq isa_reserve_irq(int isairq)

{

    if (isairq < 0 || isairq > 15) {

        hw_error("isa irq %d invalid", isairq);

    }

    if (isabus->assigned & (1 << isairq)) {

        hw_error("isa irq %d already assigned", isairq);

    }

    isabus->assigned |= (1 << isairq);

    return isabus->irqs[isairq];

}


S390CPU *cpu_s390x_create(const char *cpu_model, Error **errp)

{

    static bool features_parsed;

    char *name, *features;

    const char *typename;

    ObjectClass *oc;

    CPUClass *cc;

    name = g_strdup(cpu_model);

    features = strchr(name, ',');

    if (features) {

        features[0] = 0;

        features++;

    }

    oc = cpu_class_by_name(TYPE_S390_CPU, name);

    if (!oc) {

        error_setg(errp, "Unknown CPU definition \'%s\'", name);

        g_free(name);

        return NULL;

    }

    typename = object_class_get_name(oc);

    if (!features_parsed) {

        features_parsed = true;

        cc = CPU_CLASS(oc);

        cc->parse_features(typename, features, errp);

    }

    g_free(name);

    if (*errp) {

        return NULL;

    }

    return S390_CPU(CPU(object_new(typename)));

}


static inline void pit_load_count(PITChannelState *s, int val)

{

    if (val == 0)

        val = 0x10000;

    s->count_load_time = cpu_get_ticks();

    s->count_last_edge_check_time = s->count_load_time;

    s->count = val;

    if (s == &pit_channels[0] && val <= pit_min_timer_count) {

        fprintf(stderr,

                "\nWARNING: qemu: on your system, accurate timer emulation is impossible if its frequency is more than %d Hz. If using a 2.5.xx Linux kernel, you must patch asm/param.h to change HZ from 1000 to 100.\n\n",

                PIT_FREQ / pit_min_timer_count);

    }

}


static int usbredir_handle_bulk_data(USBRedirDevice *dev, USBPacket *p,

                                      uint8_t ep)

{

    AsyncURB *aurb = async_alloc(dev, p);

    struct usb_redir_bulk_packet_header bulk_packet;

    DPRINTF("bulk-out ep %02X len %zd id %u\n", ep,

            p->iov.size, aurb->packet_id);

    bulk_packet.endpoint  = ep;

    bulk_packet.length    = p->iov.size;

    bulk_packet.stream_id = 0;

    aurb->bulk_packet = bulk_packet;

    if (ep & USB_DIR_IN) {

        usbredirparser_send_bulk_packet(dev->parser, aurb->packet_id,

                                        &bulk_packet, NULL, 0);

    } else {

        uint8_t buf[p->iov.size];

        usb_packet_copy(p, buf, p->iov.size);

        usbredir_log_data(dev, "bulk data out:", buf, p->iov.size);

        usbredirparser_send_bulk_packet(dev->parser, aurb->packet_id,

                                        &bulk_packet, buf, p->iov.size);

    }

    usbredirparser_do_write(dev->parser);

    return USB_RET_ASYNC;

}


static int decode_frame(AVCodecContext *avctx, void *data,

                            int *data_size, AVPacket *avpkt)

{

    const uint8_t *buf = avpkt->data;

    int buf_size = avpkt->size;

    C93DecoderContext * const c93 = avctx->priv_data;

    AVFrame * const newpic = &c93->pictures[c93->currentpic];

    AVFrame * const oldpic = &c93->pictures[c93->currentpic^1];

    AVFrame *picture = data;

    uint8_t *out;

    int stride, i, x, y, bt = 0;

    c93->currentpic ^= 1;

    newpic->reference = 1;

    newpic->buffer_hints = FF_BUFFER_HINTS_VALID | FF_BUFFER_HINTS_PRESERVE |

                         FF_BUFFER_HINTS_REUSABLE | FF_BUFFER_HINTS_READABLE;

    if (avctx->reget_buffer(avctx, newpic)) {

        av_log(avctx, AV_LOG_ERROR, "reget_buffer() failed\n");

        return -1;

    }

    stride = newpic->linesize[0];

    if (buf[0] & C93_FIRST_FRAME) {

        newpic->pict_type = AV_PICTURE_TYPE_I;

        newpic->key_frame = 1;

    } else {

        newpic->pict_type = AV_PICTURE_TYPE_P;

        newpic->key_frame = 0;

    }

    if (*buf++ & C93_HAS_PALETTE) {

        uint32_t *palette = (uint32_t *) newpic->data[1];

        const uint8_t *palbuf = buf + buf_size - 768 - 1;

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

            palette[i] = bytestream_get_be24(&palbuf);

        }

    } else {

        if (oldpic->data[1])

            memcpy(newpic->data[1], oldpic->data[1], 256 * 4);

    }

    for (y = 0; y < HEIGHT; y += 8) {

        out = newpic->data[0] + y * stride;

        for (x = 0; x < WIDTH; x += 8) {

            uint8_t *copy_from = oldpic->data[0];

            unsigned int offset, j;

            uint8_t cols[4], grps[4];

            C93BlockType block_type;

            if (!bt)

                bt = *buf++;

            block_type= bt & 0x0F;

            switch (block_type) {

            case C93_8X8_FROM_PREV:

                offset = bytestream_get_le16(&buf);

                if (copy_block(avctx, out, copy_from, offset, 8, stride))

                    return -1;

                break;

            case C93_4X4_FROM_CURR:

                copy_from = newpic->data[0];

            case C93_4X4_FROM_PREV:

                for (j = 0; j < 8; j += 4) {

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

                        offset = bytestream_get_le16(&buf);

                        if (copy_block(avctx, &out[j*stride+i],

                                           copy_from, offset, 4, stride))

                            return -1;

                    }

                }

                break;

            case C93_8X8_2COLOR:

                bytestream_get_buffer(&buf, cols, 2);

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

                    draw_n_color(out + i*stride, stride, 8, 1, 1, cols,

                                     NULL, *buf++);

                }

                break;

            case C93_4X4_2COLOR:

            case C93_4X4_4COLOR:

            case C93_4X4_4COLOR_GRP:

                for (j = 0; j < 8; j += 4) {

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

                        if (block_type == C93_4X4_2COLOR) {

                            bytestream_get_buffer(&buf, cols, 2);

                            draw_n_color(out + i + j*stride, stride, 4, 4,

                                    1, cols, NULL, bytestream_get_le16(&buf));

                        } else if (block_type == C93_4X4_4COLOR) {

                            bytestream_get_buffer(&buf, cols, 4);

                            draw_n_color(out + i + j*stride, stride, 4, 4,

                                    2, cols, NULL, bytestream_get_le32(&buf));

                        } else {

                            bytestream_get_buffer(&buf, grps, 4);

                            draw_n_color(out + i + j*stride, stride, 4, 4,

                                    1, cols, grps, bytestream_get_le16(&buf));

                        }

                    }

                }

                break;

            case C93_NOOP:

                break;

            case C93_8X8_INTRA:

                for (j = 0; j < 8; j++)

                    bytestream_get_buffer(&buf, out + j*stride, 8);

                break;

            default:

                av_log(avctx, AV_LOG_ERROR, "unexpected type %x at %dx%d\n",

                       block_type, x, y);

                return -1;

            }

            bt >>= 4;

            out += 8;

        }

    }

    *picture = *newpic;

    *data_size = sizeof(AVFrame);

    return buf_size;

}


static int filter_frame(AVFilterLink *inlink, AVFilterBufferRef *in)

{

    HQDN3DContext *hqdn3d = inlink->dst->priv;

    AVFilterLink *outlink = inlink->dst->outputs[0];

    AVFilterBufferRef *out;

    int direct, c;

    if (in->perms & AV_PERM_WRITE) {

        direct = 1;

        out = in;

    } else {

        out = ff_get_video_buffer(outlink, AV_PERM_WRITE, outlink->w, outlink->h);

        if (!out) {

            avfilter_unref_bufferp(&in);

            return AVERROR(ENOMEM);

        }

        avfilter_copy_buffer_ref_props(out, in);

        out->video->w = outlink->w;

        out->video->h = outlink->h;

    }

    for (c = 0; c < 3; c++) {

        denoise(hqdn3d, in->data[c], out->data[c],

                hqdn3d->line, &hqdn3d->frame_prev[c],

                in->video->w >> (!!c * hqdn3d->hsub),

                in->video->h >> (!!c * hqdn3d->vsub),

                in->linesize[c], out->linesize[c],

                hqdn3d->coefs[c?2:0], hqdn3d->coefs[c?3:1]);

    }

    if (!direct)

        avfilter_unref_bufferp(&in);

    return ff_filter_frame(outlink, out);

}


void *qemu_blockalign(BlockDriverState *bs, size_t size)

{

    return qemu_memalign((bs && bs->buffer_alignment) ? bs->buffer_alignment : 512, size);

}


static int ehci_fill_queue(EHCIPacket *p)

{

    USBEndpoint *ep = p->packet.ep;

    EHCIQueue *q = p->queue;

    EHCIqtd qtd = p->qtd;

    uint32_t qtdaddr;

    for (;;) {

        if (NLPTR_TBIT(qtd.next) != 0) {

        qtdaddr = qtd.next;

        /*

         * Detect circular td lists, Windows creates these, counting on the

         * active bit going low after execution to make the queue stop.

         */

        QTAILQ_FOREACH(p, &q->packets, next) {

            if (p->qtdaddr == qtdaddr) {

                goto leave;

        if (get_dwords(q->ehci, NLPTR_GET(qtdaddr),

                       (uint32_t *) &qtd, sizeof(EHCIqtd) >> 2) < 0) {

            return -1;

        ehci_trace_qtd(q, NLPTR_GET(qtdaddr), &qtd);

        if (!(qtd.token & QTD_TOKEN_ACTIVE)) {

        p = ehci_alloc_packet(q);

        p->qtdaddr = qtdaddr;

        p->qtd = qtd;

        if (ehci_execute(p, "queue") == -1) {

            return -1;

        assert(p->packet.status == USB_RET_ASYNC);

        p->async = EHCI_ASYNC_INFLIGHT;

leave:

    usb_device_flush_ep_queue(ep->dev, ep);

    return 1;


void bdrv_close(BlockDriverState *bs)

{

    if (bs->drv) {

        if (bs->backing_hd)

            bdrv_delete(bs->backing_hd);

        bs->drv->bdrv_close(bs);

        qemu_free(bs->opaque);

#ifdef _WIN32

        if (bs->is_temporary) {

            unlink(bs->filename);

        }

#endif

        bs->opaque = NULL;

        bs->drv = NULL;

        /* call the change callback */

        bs->total_sectors = 0;

        bs->media_changed = 1;

        if (bs->change_cb)

            bs->change_cb(bs->change_opaque);

    }

}


static int encode_block(SVQ1EncContext *s, uint8_t *src, uint8_t *ref,

                        uint8_t *decoded, int stride, int level,

                        int threshold, int lambda, int intra)

{

    int count, y, x, i, j, split, best_mean, best_score, best_count;

    int best_vector[6];

    int block_sum[7] = { 0, 0, 0, 0, 0, 0 };

    int w            = 2 << (level + 2 >> 1);

    int h            = 2 << (level + 1 >> 1);

    int size         = w * h;

    int16_t (*block)[256] = s->encoded_block_levels[level];

    const int8_t *codebook_sum, *codebook;

    const uint16_t(*mean_vlc)[2];

    const uint8_t(*multistage_vlc)[2];

    best_score = 0;

    // FIXME: Optimize, this does not need to be done multiple times.

    if (intra) {

        codebook_sum   = svq1_intra_codebook_sum[level];

        codebook       = ff_svq1_intra_codebooks[level];

        mean_vlc       = ff_svq1_intra_mean_vlc;

        multistage_vlc = ff_svq1_intra_multistage_vlc[level];

        for (y = 0; y < h; y++) {

            for (x = 0; x < w; x++) {

                int v = src[x + y * stride];

                block[0][x + w * y] = v;

                best_score         += v * v;

                block_sum[0]       += v;

            }

        }

    } else {

        codebook_sum   = svq1_inter_codebook_sum[level];

        codebook       = ff_svq1_inter_codebooks[level];

        mean_vlc       = ff_svq1_inter_mean_vlc + 256;

        multistage_vlc = ff_svq1_inter_multistage_vlc[level];

        for (y = 0; y < h; y++) {

            for (x = 0; x < w; x++) {

                int v = src[x + y * stride] - ref[x + y * stride];

                block[0][x + w * y] = v;

                best_score         += v * v;

                block_sum[0]       += v;

            }

        }

    }

    best_count  = 0;

    best_score -= (int)((unsigned)block_sum[0] * block_sum[0] >> (level + 3));

    best_mean   = block_sum[0] + (size >> 1) >> (level + 3);

    if (level < 4) {

        for (count = 1; count < 7; count++) {

            int best_vector_score = INT_MAX;

            int best_vector_sum   = -999, best_vector_mean = -999;

            const int stage       = count - 1;

            const int8_t *vector;

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

                int sum = codebook_sum[stage * 16 + i];

                int sqr, diff, score;

                vector = codebook + stage * size * 16 + i * size;

                sqr    = s->ssd_int8_vs_int16(vector, block[stage], size);

                diff   = block_sum[stage] - sum;

                score  = sqr - (diff * (int64_t)diff >> (level + 3)); // FIXME: 64bit slooow

                if (score < best_vector_score) {

                    int mean = diff + (size >> 1) >> (level + 3);

                    av_assert2(mean > -300 && mean < 300);

                    mean               = av_clip(mean, intra ? 0 : -256, 255);

                    best_vector_score  = score;

                    best_vector[stage] = i;

                    best_vector_sum    = sum;

                    best_vector_mean   = mean;

                }

            }

            av_assert0(best_vector_mean != -999);

            vector = codebook + stage * size * 16 + best_vector[stage] * size;

            for (j = 0; j < size; j++)

                block[stage + 1][j] = block[stage][j] - vector[j];

            block_sum[stage + 1] = block_sum[stage] - best_vector_sum;

            best_vector_score   += lambda *

                                   (+1 + 4 * count +

                                    multistage_vlc[1 + count][1]

                                    + mean_vlc[best_vector_mean][1]);

            if (best_vector_score < best_score) {

                best_score = best_vector_score;

                best_count = count;

                best_mean  = best_vector_mean;

            }

        }

    }

    split = 0;

    if (best_score > threshold && level) {

        int score  = 0;

        int offset = level & 1 ? stride * h / 2 : w / 2;

        PutBitContext backup[6];

        for (i = level - 1; i >= 0; i--)

            backup[i] = s->reorder_pb[i];

        score += encode_block(s, src, ref, decoded, stride, level - 1,

                              threshold >> 1, lambda, intra);

        score += encode_block(s, src + offset, ref + offset, decoded + offset,

                              stride, level - 1, threshold >> 1, lambda, intra);

        score += lambda;

        if (score < best_score) {

            best_score = score;

            split      = 1;

        } else {

            for (i = level - 1; i >= 0; i--)

                s->reorder_pb[i] = backup[i];

        }

    }

    if (level > 0)

        put_bits(&s->reorder_pb[level], 1, split);

    if (!split) {

        av_assert1(best_mean >= 0 && best_mean < 256 || !intra);

        av_assert1(best_mean >= -256 && best_mean < 256);

        av_assert1(best_count >= 0 && best_count < 7);

        av_assert1(level < 4 || best_count == 0);

        /* output the encoding */

        put_bits(&s->reorder_pb[level],

                 multistage_vlc[1 + best_count][1],

                 multistage_vlc[1 + best_count][0]);

        put_bits(&s->reorder_pb[level], mean_vlc[best_mean][1],

                 mean_vlc[best_mean][0]);

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

            av_assert2(best_vector[i] >= 0 && best_vector[i] < 16);

            put_bits(&s->reorder_pb[level], 4, best_vector[i]);

        }

        for (y = 0; y < h; y++)

            for (x = 0; x < w; x++)

                decoded[x + y * stride] = src[x + y * stride] -

                                          block[best_count][x + w * y] +

                                          best_mean;

    }

    return best_score;

}


void bdrv_attach_aio_context(BlockDriverState *bs,

                             AioContext *new_context)

{

    BdrvAioNotifier *ban;

    BdrvChild *child;

    if (!bs->drv) {

        return;

    }

    bs->aio_context = new_context;

    QLIST_FOREACH(child, &bs->children, next) {

        bdrv_attach_aio_context(child->bs, new_context);

    }

    if (bs->drv->bdrv_attach_aio_context) {

        bs->drv->bdrv_attach_aio_context(bs, new_context);

    }

    QLIST_FOREACH(ban, &bs->aio_notifiers, list) {

        ban->attached_aio_context(new_context, ban->opaque);

    }

}


static inline CopyRet copy_frame(AVCodecContext *avctx,

                                 BC_DTS_PROC_OUT *output,

                                 void *data, int *data_size)

{

    BC_STATUS ret;

    BC_DTS_STATUS decoder_status = { 0, };

    uint8_t trust_interlaced;

    uint8_t interlaced;

    CHDContext *priv = avctx->priv_data;

    int64_t pkt_pts  = AV_NOPTS_VALUE;

    uint8_t pic_type = 0;

    uint8_t bottom_field = (output->PicInfo.flags & VDEC_FLAG_BOTTOMFIELD) ==

                           VDEC_FLAG_BOTTOMFIELD;

    uint8_t bottom_first = !!(output->PicInfo.flags & VDEC_FLAG_BOTTOM_FIRST);

    int width    = output->PicInfo.width;

    int height   = output->PicInfo.height;

    int bwidth;

    uint8_t *src = output->Ybuff;

    int sStride;

    uint8_t *dst;

    int dStride;

    if (output->PicInfo.timeStamp != 0) {

        OpaqueList *node = opaque_list_pop(priv, output->PicInfo.timeStamp);

        if (node) {

            pkt_pts = node->reordered_opaque;

            pic_type = node->pic_type;

            av_free(node);

        } else {

            /*

             * We will encounter a situation where a timestamp cannot be

             * popped if a second field is being returned. In this case,

             * each field has the same timestamp and the first one will

             * cause it to be popped. To keep subsequent calculations

             * simple, pic_type should be set a FIELD value - doesn't

             * matter which, but I chose BOTTOM.

             */

            pic_type = PICT_BOTTOM_FIELD;

        }

        av_log(avctx, AV_LOG_VERBOSE, "output \"pts\": %"PRIu64"\n",

               output->PicInfo.timeStamp);

        av_log(avctx, AV_LOG_VERBOSE, "output picture type %d\n",

               pic_type);

    }

    ret = DtsGetDriverStatus(priv->dev, &decoder_status);

    if (ret != BC_STS_SUCCESS) {

        av_log(avctx, AV_LOG_ERROR,

               "CrystalHD: GetDriverStatus failed: %u\n", ret);

       return RET_ERROR;

    }

    /*

     * For most content, we can trust the interlaced flag returned

     * by the hardware, but sometimes we can't. These are the

     * conditions under which we can trust the flag:

     *

     * 1) It's not h.264 content

     * 2) The UNKNOWN_SRC flag is not set

     * 3) We know we're expecting a second field

     * 4) The hardware reports this picture and the next picture

     *    have the same picture number.

     *

     * Note that there can still be interlaced content that will

     * fail this check, if the hardware hasn't decoded the next

     * picture or if there is a corruption in the stream. (In either

     * case a 0 will be returned for the next picture number)

     */

    trust_interlaced = avctx->codec->id != CODEC_ID_H264 ||

                       !(output->PicInfo.flags & VDEC_FLAG_UNKNOWN_SRC) ||

                       priv->need_second_field ||

                       (decoder_status.picNumFlags & ~0x40000000) ==

                       output->PicInfo.picture_number;

    /*

     * If we got a false negative for trust_interlaced on the first field,

     * we will realise our mistake here when we see that the picture number is that

     * of the previous picture. We cannot recover the frame and should discard the

     * second field to keep the correct number of output frames.

     */

    if (output->PicInfo.picture_number == priv->last_picture && !priv->need_second_field) {

        av_log(avctx, AV_LOG_WARNING,

               "Incorrectly guessed progressive frame. Discarding second field\n");

        /* Returning without providing a picture. */

        return RET_OK;

    }

    interlaced = (output->PicInfo.flags & VDEC_FLAG_INTERLACED_SRC) &&

                 trust_interlaced;

    if (!trust_interlaced && (decoder_status.picNumFlags & ~0x40000000) == 0) {

        av_log(avctx, AV_LOG_VERBOSE,

               "Next picture number unknown. Assuming progressive frame.\n");

    }

    av_log(avctx, AV_LOG_VERBOSE, "Interlaced state: %d | trust_interlaced %d\n",

           interlaced, trust_interlaced);

    if (priv->pic.data[0] && !priv->need_second_field)

        avctx->release_buffer(avctx, &priv->pic);

    priv->need_second_field = interlaced && !priv->need_second_field;

    priv->pic.buffer_hints = FF_BUFFER_HINTS_VALID | FF_BUFFER_HINTS_PRESERVE |

                             FF_BUFFER_HINTS_REUSABLE;

    if (!priv->pic.data[0]) {

        if (avctx->get_buffer(avctx, &priv->pic) < 0) {

            av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");

            return RET_ERROR;

        }

    }

    bwidth = av_image_get_linesize(avctx->pix_fmt, width, 0);

    if (priv->is_70012) {

        int pStride;

        if (width <= 720)

            pStride = 720;

        else if (width <= 1280)

            pStride = 1280;

        else pStride = 1920;

        sStride = av_image_get_linesize(avctx->pix_fmt, pStride, 0);

    } else {

        sStride = bwidth;

    }

    dStride = priv->pic.linesize[0];

    dst     = priv->pic.data[0];

    av_log(priv->avctx, AV_LOG_VERBOSE, "CrystalHD: Copying out frame\n");

    if (interlaced) {

        int dY = 0;

        int sY = 0;

        height /= 2;

        if (bottom_field) {

            av_log(priv->avctx, AV_LOG_VERBOSE, "Interlaced: bottom field\n");

            dY = 1;

        } else {

            av_log(priv->avctx, AV_LOG_VERBOSE, "Interlaced: top field\n");

            dY = 0;

        }

        for (sY = 0; sY < height; dY++, sY++) {

            memcpy(&(dst[dY * dStride]), &(src[sY * sStride]), bwidth);

            dY++;

        }

    } else {

        av_image_copy_plane(dst, dStride, src, sStride, bwidth, height);

    }

    priv->pic.interlaced_frame = interlaced;

    if (interlaced)

        priv->pic.top_field_first = !bottom_first;

    priv->pic.pkt_pts = pkt_pts;

    if (!priv->need_second_field) {

        *data_size       = sizeof(AVFrame);

        *(AVFrame *)data = priv->pic;

    }

    /*

     * Two types of PAFF content have been observed. One form causes the

     * hardware to return a field pair and the other individual fields,

     * even though the input is always individual fields. We must skip

     * copying on the next decode() call to maintain pipeline length in

     * the first case.

     */

    if (!interlaced && (output->PicInfo.flags & VDEC_FLAG_UNKNOWN_SRC) &&

        (pic_type == PICT_TOP_FIELD || pic_type == PICT_BOTTOM_FIELD)) {

        av_log(priv->avctx, AV_LOG_VERBOSE, "Fieldpair from two packets.\n");

        return RET_SKIP_NEXT_COPY;

    }

    /*

     * Testing has shown that in all cases where we don't want to return the

     * full frame immediately, VDEC_FLAG_UNKNOWN_SRC is set.

     */

    return priv->need_second_field &&

           !(output->PicInfo.flags & VDEC_FLAG_UNKNOWN_SRC) ?

           RET_COPY_NEXT_FIELD : RET_OK;

}