static void gen_sse(DisasContext *s, int b, target_ulong pc_start, int rex_r)

{

    int b1, op1_offset, op2_offset, is_xmm, val, ot;

    int modrm, mod, rm, reg, reg_addr, offset_addr;

    void *sse_op2;

    b &= 0xff;

    if (s->prefix & PREFIX_DATA)

        b1 = 1;

    else if (s->prefix & PREFIX_REPZ)

        b1 = 2;

    else if (s->prefix & PREFIX_REPNZ)

        b1 = 3;

    else

        b1 = 0;

    sse_op2 = sse_op_table1[b][b1];

    if (!sse_op2)

        goto illegal_op;

    if ((b <= 0x5f && b >= 0x10) || b == 0xc6 || b == 0xc2) {

        is_xmm = 1;

    } else {

        if (b1 == 0) {

            /* MMX case */

            is_xmm = 0;

        } else {

            is_xmm = 1;

        }

    }

    /* simple MMX/SSE operation */

    if (s->flags & HF_TS_MASK) {

        gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);

        return;

    }

    if (s->flags & HF_EM_MASK) {

    illegal_op:

        gen_exception(s, EXCP06_ILLOP, pc_start - s->cs_base);

        return;

    }

    if (is_xmm && !(s->flags & HF_OSFXSR_MASK))

        if ((b != 0x38 && b != 0x3a) || (s->prefix & PREFIX_DATA))

            goto illegal_op;

    if (b == 0x0e) {

        if (!(s->cpuid_ext2_features & CPUID_EXT2_3DNOW))

            goto illegal_op;

        /* femms */

        tcg_gen_helper_0_0(helper_emms);

        return;

    }

    if (b == 0x77) {

        /* emms */

        tcg_gen_helper_0_0(helper_emms);

        return;

    }

    /* prepare MMX state (XXX: optimize by storing fptt and fptags in

       the static cpu state) */

    if (!is_xmm) {

        tcg_gen_helper_0_0(helper_enter_mmx);

    }

    modrm = ldub_code(s->pc++);

    reg = ((modrm >> 3) & 7);

    if (is_xmm)

        reg |= rex_r;

    mod = (modrm >> 6) & 3;

    if (sse_op2 == SSE_SPECIAL) {

        b |= (b1 << 8);

        switch(b) {

        case 0x0e7: /* movntq */

            if (mod == 3)

                goto illegal_op;

            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);

            gen_stq_env_A0(s->mem_index, offsetof(CPUX86State,fpregs[reg].mmx));

            break;

        case 0x1e7: /* movntdq */

        case 0x02b: /* movntps */

        case 0x12b: /* movntps */

        case 0x3f0: /* lddqu */

            if (mod == 3)

                goto illegal_op;

            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);

            gen_sto_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg]));

            break;

        case 0x6e: /* movd mm, ea */

#ifdef TARGET_X86_64

            if (s->dflag == 2) {

                gen_ldst_modrm(s, modrm, OT_QUAD, OR_TMP0, 0);

                tcg_gen_st_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,fpregs[reg].mmx));

            } else

#endif

            {

                gen_ldst_modrm(s, modrm, OT_LONG, OR_TMP0, 0);

                tcg_gen_addi_ptr(cpu_ptr0, cpu_env,

                                 offsetof(CPUX86State,fpregs[reg].mmx));

                tcg_gen_helper_0_2(helper_movl_mm_T0_mmx, cpu_ptr0, cpu_T[0]);

            }

            break;

        case 0x16e: /* movd xmm, ea */

#ifdef TARGET_X86_64

            if (s->dflag == 2) {

                gen_ldst_modrm(s, modrm, OT_QUAD, OR_TMP0, 0);

                tcg_gen_addi_ptr(cpu_ptr0, cpu_env,

                                 offsetof(CPUX86State,xmm_regs[reg]));

                tcg_gen_helper_0_2(helper_movq_mm_T0_xmm, cpu_ptr0, cpu_T[0]);

            } else

#endif

            {

                gen_ldst_modrm(s, modrm, OT_LONG, OR_TMP0, 0);

                tcg_gen_addi_ptr(cpu_ptr0, cpu_env,

                                 offsetof(CPUX86State,xmm_regs[reg]));

                tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);

                tcg_gen_helper_0_2(helper_movl_mm_T0_xmm, cpu_ptr0, cpu_tmp2_i32);

            }

            break;

        case 0x6f: /* movq mm, ea */

            if (mod != 3) {

                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);

                gen_ldq_env_A0(s->mem_index, offsetof(CPUX86State,fpregs[reg].mmx));

            } else {

                rm = (modrm & 7);

                tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env,

                               offsetof(CPUX86State,fpregs[rm].mmx));

                tcg_gen_st_i64(cpu_tmp1_i64, cpu_env,

                               offsetof(CPUX86State,fpregs[reg].mmx));

            }

            break;

        case 0x010: /* movups */

        case 0x110: /* movupd */

        case 0x028: /* movaps */

        case 0x128: /* movapd */

        case 0x16f: /* movdqa xmm, ea */

        case 0x26f: /* movdqu xmm, ea */

            if (mod != 3) {

                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);

                gen_ldo_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg]));

            } else {

                rm = (modrm & 7) | REX_B(s);

                gen_op_movo(offsetof(CPUX86State,xmm_regs[reg]),

                            offsetof(CPUX86State,xmm_regs[rm]));

            }

            break;

        case 0x210: /* movss xmm, ea */

            if (mod != 3) {

                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);

                gen_op_ld_T0_A0(OT_LONG + s->mem_index);

                tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)));

                gen_op_movl_T0_0();

                tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_regs[reg].XMM_L(1)));

                tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_regs[reg].XMM_L(2)));

                tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_regs[reg].XMM_L(3)));

            } else {

                rm = (modrm & 7) | REX_B(s);

                gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)),

                            offsetof(CPUX86State,xmm_regs[rm].XMM_L(0)));

            }

            break;

        case 0x310: /* movsd xmm, ea */

            if (mod != 3) {

                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);

                gen_ldq_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));

                gen_op_movl_T0_0();

                tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_regs[reg].XMM_L(2)));

                tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_regs[reg].XMM_L(3)));

            } else {

                rm = (modrm & 7) | REX_B(s);

                gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)),

                            offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0)));

            }

            break;

        case 0x012: /* movlps */

        case 0x112: /* movlpd */

            if (mod != 3) {

                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);

                gen_ldq_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));

            } else {

                /* movhlps */

                rm = (modrm & 7) | REX_B(s);

                gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)),

                            offsetof(CPUX86State,xmm_regs[rm].XMM_Q(1)));

            }

            break;

        case 0x212: /* movsldup */

            if (mod != 3) {

                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);

                gen_ldo_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg]));

            } else {

                rm = (modrm & 7) | REX_B(s);

                gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)),

                            offsetof(CPUX86State,xmm_regs[rm].XMM_L(0)));

                gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(2)),

                            offsetof(CPUX86State,xmm_regs[rm].XMM_L(2)));

            }

            gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(1)),

                        offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)));

            gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(3)),

                        offsetof(CPUX86State,xmm_regs[reg].XMM_L(2)));

            break;

        case 0x312: /* movddup */

            if (mod != 3) {

                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);

                gen_ldq_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));

            } else {

                rm = (modrm & 7) | REX_B(s);

                gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)),

                            offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0)));

            }

            gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(1)),

                        offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));

            break;

        case 0x016: /* movhps */

        case 0x116: /* movhpd */

            if (mod != 3) {

                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);

                gen_ldq_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg].XMM_Q(1)));

            } else {

                /* movlhps */

                rm = (modrm & 7) | REX_B(s);

                gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(1)),

                            offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0)));

            }

            break;

        case 0x216: /* movshdup */

            if (mod != 3) {

                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);

                gen_ldo_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg]));

            } else {

                rm = (modrm & 7) | REX_B(s);

                gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(1)),

                            offsetof(CPUX86State,xmm_regs[rm].XMM_L(1)));

                gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(3)),

                            offsetof(CPUX86State,xmm_regs[rm].XMM_L(3)));

            }

            gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)),

                        offsetof(CPUX86State,xmm_regs[reg].XMM_L(1)));

            gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(2)),

                        offsetof(CPUX86State,xmm_regs[reg].XMM_L(3)));

            break;

        case 0x7e: /* movd ea, mm */

#ifdef TARGET_X86_64

            if (s->dflag == 2) {

                tcg_gen_ld_i64(cpu_T[0], cpu_env,

                               offsetof(CPUX86State,fpregs[reg].mmx));

                gen_ldst_modrm(s, modrm, OT_QUAD, OR_TMP0, 1);

            } else

#endif

            {

                tcg_gen_ld32u_tl(cpu_T[0], cpu_env,

                                 offsetof(CPUX86State,fpregs[reg].mmx.MMX_L(0)));

                gen_ldst_modrm(s, modrm, OT_LONG, OR_TMP0, 1);

            }

            break;

        case 0x17e: /* movd ea, xmm */

#ifdef TARGET_X86_64

            if (s->dflag == 2) {

                tcg_gen_ld_i64(cpu_T[0], cpu_env,

                               offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));

                gen_ldst_modrm(s, modrm, OT_QUAD, OR_TMP0, 1);

            } else

#endif

            {

                tcg_gen_ld32u_tl(cpu_T[0], cpu_env,

                                 offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)));

                gen_ldst_modrm(s, modrm, OT_LONG, OR_TMP0, 1);

            }

            break;

        case 0x27e: /* movq xmm, ea */

            if (mod != 3) {

                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);

                gen_ldq_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));

            } else {

                rm = (modrm & 7) | REX_B(s);

                gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)),

                            offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0)));

            }

            gen_op_movq_env_0(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(1)));

            break;

        case 0x7f: /* movq ea, mm */

            if (mod != 3) {

                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);

                gen_stq_env_A0(s->mem_index, offsetof(CPUX86State,fpregs[reg].mmx));

            } else {

                rm = (modrm & 7);

                gen_op_movq(offsetof(CPUX86State,fpregs[rm].mmx),

                            offsetof(CPUX86State,fpregs[reg].mmx));

            }

            break;

        case 0x011: /* movups */

        case 0x111: /* movupd */

        case 0x029: /* movaps */

        case 0x129: /* movapd */

        case 0x17f: /* movdqa ea, xmm */

        case 0x27f: /* movdqu ea, xmm */

            if (mod != 3) {

                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);

                gen_sto_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg]));

            } else {

                rm = (modrm & 7) | REX_B(s);

                gen_op_movo(offsetof(CPUX86State,xmm_regs[rm]),

                            offsetof(CPUX86State,xmm_regs[reg]));

            }

            break;

        case 0x211: /* movss ea, xmm */

            if (mod != 3) {

                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);

                tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)));

                gen_op_st_T0_A0(OT_LONG + s->mem_index);

            } else {

                rm = (modrm & 7) | REX_B(s);

                gen_op_movl(offsetof(CPUX86State,xmm_regs[rm].XMM_L(0)),

                            offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)));

            }

            break;

        case 0x311: /* movsd ea, xmm */

            if (mod != 3) {

                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);

                gen_stq_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));

            } else {

                rm = (modrm & 7) | REX_B(s);

                gen_op_movq(offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0)),

                            offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));

            }

            break;

        case 0x013: /* movlps */

        case 0x113: /* movlpd */

            if (mod != 3) {

                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);

                gen_stq_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));

            } else {

                goto illegal_op;

            }

            break;

        case 0x017: /* movhps */

        case 0x117: /* movhpd */

            if (mod != 3) {

                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);

                gen_stq_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg].XMM_Q(1)));

            } else {

                goto illegal_op;

            }

            break;

        case 0x71: /* shift mm, im */

        case 0x72:

        case 0x73:

        case 0x171: /* shift xmm, im */

        case 0x172:

        case 0x173:

            val = ldub_code(s->pc++);

            if (is_xmm) {

                gen_op_movl_T0_im(val);

                tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_t0.XMM_L(0)));

                gen_op_movl_T0_0();

                tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_t0.XMM_L(1)));

                op1_offset = offsetof(CPUX86State,xmm_t0);

            } else {

                gen_op_movl_T0_im(val);

                tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,mmx_t0.MMX_L(0)));

                gen_op_movl_T0_0();

                tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,mmx_t0.MMX_L(1)));

                op1_offset = offsetof(CPUX86State,mmx_t0);

            }

            sse_op2 = sse_op_table2[((b - 1) & 3) * 8 + (((modrm >> 3)) & 7)][b1];

            if (!sse_op2)

                goto illegal_op;

            if (is_xmm) {

                rm = (modrm & 7) | REX_B(s);

                op2_offset = offsetof(CPUX86State,xmm_regs[rm]);

            } else {

                rm = (modrm & 7);

                op2_offset = offsetof(CPUX86State,fpregs[rm].mmx);

            }

            tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op2_offset);

            tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op1_offset);

            tcg_gen_helper_0_2(sse_op2, cpu_ptr0, cpu_ptr1);

            break;

        case 0x050: /* movmskps */

            rm = (modrm & 7) | REX_B(s);

            tcg_gen_addi_ptr(cpu_ptr0, cpu_env,

                             offsetof(CPUX86State,xmm_regs[rm]));

            tcg_gen_helper_1_1(helper_movmskps, cpu_tmp2_i32, cpu_ptr0);

            tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);

            gen_op_mov_reg_T0(OT_LONG, reg);

            break;

        case 0x150: /* movmskpd */

            rm = (modrm & 7) | REX_B(s);

            tcg_gen_addi_ptr(cpu_ptr0, cpu_env,

                             offsetof(CPUX86State,xmm_regs[rm]));

            tcg_gen_helper_1_1(helper_movmskpd, cpu_tmp2_i32, cpu_ptr0);

            tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);

            gen_op_mov_reg_T0(OT_LONG, reg);

            break;

        case 0x02a: /* cvtpi2ps */

        case 0x12a: /* cvtpi2pd */

            tcg_gen_helper_0_0(helper_enter_mmx);

            if (mod != 3) {

                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);

                op2_offset = offsetof(CPUX86State,mmx_t0);

                gen_ldq_env_A0(s->mem_index, op2_offset);

            } else {

                rm = (modrm & 7);

                op2_offset = offsetof(CPUX86State,fpregs[rm].mmx);

            }

            op1_offset = offsetof(CPUX86State,xmm_regs[reg]);

            tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);

            tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);

            switch(b >> 8) {

            case 0x0:

                tcg_gen_helper_0_2(helper_cvtpi2ps, cpu_ptr0, cpu_ptr1);

                break;

            default:

            case 0x1:

                tcg_gen_helper_0_2(helper_cvtpi2pd, cpu_ptr0, cpu_ptr1);

                break;

            }

            break;

        case 0x22a: /* cvtsi2ss */

        case 0x32a: /* cvtsi2sd */

            ot = (s->dflag == 2) ? OT_QUAD : OT_LONG;

            gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);

            op1_offset = offsetof(CPUX86State,xmm_regs[reg]);

            tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);

            sse_op2 = sse_op_table3[(s->dflag == 2) * 2 + ((b >> 8) - 2)];

            if (ot == OT_LONG) {

                tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);

                tcg_gen_helper_0_2(sse_op2, cpu_ptr0, cpu_tmp2_i32);

            } else {

                tcg_gen_helper_0_2(sse_op2, cpu_ptr0, cpu_T[0]);

            }

            break;

        case 0x02c: /* cvttps2pi */

        case 0x12c: /* cvttpd2pi */

        case 0x02d: /* cvtps2pi */

        case 0x12d: /* cvtpd2pi */

            tcg_gen_helper_0_0(helper_enter_mmx);

            if (mod != 3) {

                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);

                op2_offset = offsetof(CPUX86State,xmm_t0);

                gen_ldo_env_A0(s->mem_index, op2_offset);

            } else {

                rm = (modrm & 7) | REX_B(s);

                op2_offset = offsetof(CPUX86State,xmm_regs[rm]);

            }

            op1_offset = offsetof(CPUX86State,fpregs[reg & 7].mmx);

            tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);

            tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);

            switch(b) {

            case 0x02c:

                tcg_gen_helper_0_2(helper_cvttps2pi, cpu_ptr0, cpu_ptr1);

                break;

            case 0x12c:

                tcg_gen_helper_0_2(helper_cvttpd2pi, cpu_ptr0, cpu_ptr1);

                break;

            case 0x02d:

                tcg_gen_helper_0_2(helper_cvtps2pi, cpu_ptr0, cpu_ptr1);

                break;

            case 0x12d:

                tcg_gen_helper_0_2(helper_cvtpd2pi, cpu_ptr0, cpu_ptr1);

                break;

            }

            break;

        case 0x22c: /* cvttss2si */

        case 0x32c: /* cvttsd2si */

        case 0x22d: /* cvtss2si */

        case 0x32d: /* cvtsd2si */

            ot = (s->dflag == 2) ? OT_QUAD : OT_LONG;

            if (mod != 3) {

                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);

                if ((b >> 8) & 1) {

                    gen_ldq_env_A0(s->mem_index, offsetof(CPUX86State,xmm_t0.XMM_Q(0)));

                } else {

                    gen_op_ld_T0_A0(OT_LONG + s->mem_index);

                    tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_t0.XMM_L(0)));

                }

                op2_offset = offsetof(CPUX86State,xmm_t0);

            } else {

                rm = (modrm & 7) | REX_B(s);

                op2_offset = offsetof(CPUX86State,xmm_regs[rm]);

            }

            sse_op2 = sse_op_table3[(s->dflag == 2) * 2 + ((b >> 8) - 2) + 4 +

                                    (b & 1) * 4];

            tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op2_offset);

            if (ot == OT_LONG) {

                tcg_gen_helper_1_1(sse_op2, cpu_tmp2_i32, cpu_ptr0);

                tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);

            } else {

                tcg_gen_helper_1_1(sse_op2, cpu_T[0], cpu_ptr0);

            }

            gen_op_mov_reg_T0(ot, reg);

            break;

        case 0xc4: /* pinsrw */

        case 0x1c4:

            s->rip_offset = 1;

            gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0);

            val = ldub_code(s->pc++);

            if (b1) {

                val &= 7;

                tcg_gen_st16_tl(cpu_T[0], cpu_env,

                                offsetof(CPUX86State,xmm_regs[reg].XMM_W(val)));

            } else {

                val &= 3;

                tcg_gen_st16_tl(cpu_T[0], cpu_env,

                                offsetof(CPUX86State,fpregs[reg].mmx.MMX_W(val)));

            }

            break;

        case 0xc5: /* pextrw */

        case 0x1c5:

            if (mod != 3)

                goto illegal_op;

            ot = (s->dflag == 2) ? OT_QUAD : OT_LONG;

            val = ldub_code(s->pc++);

            if (b1) {

                val &= 7;

                rm = (modrm & 7) | REX_B(s);

                tcg_gen_ld16u_tl(cpu_T[0], cpu_env,

                                 offsetof(CPUX86State,xmm_regs[rm].XMM_W(val)));

            } else {

                val &= 3;

                rm = (modrm & 7);

                tcg_gen_ld16u_tl(cpu_T[0], cpu_env,

                                offsetof(CPUX86State,fpregs[rm].mmx.MMX_W(val)));

            }

            reg = ((modrm >> 3) & 7) | rex_r;

            gen_op_mov_reg_T0(ot, reg);

            break;

        case 0x1d6: /* movq ea, xmm */

            if (mod != 3) {

                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);

                gen_stq_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));

            } else {

                rm = (modrm & 7) | REX_B(s);

                gen_op_movq(offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0)),

                            offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));

                gen_op_movq_env_0(offsetof(CPUX86State,xmm_regs[rm].XMM_Q(1)));

            }

            break;

        case 0x2d6: /* movq2dq */

            tcg_gen_helper_0_0(helper_enter_mmx);

            rm = (modrm & 7);

            gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)),

                        offsetof(CPUX86State,fpregs[rm].mmx));

            gen_op_movq_env_0(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(1)));

            break;

        case 0x3d6: /* movdq2q */

            tcg_gen_helper_0_0(helper_enter_mmx);

            rm = (modrm & 7) | REX_B(s);

            gen_op_movq(offsetof(CPUX86State,fpregs[reg & 7].mmx),

                        offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0)));

            break;

        case 0xd7: /* pmovmskb */

        case 0x1d7:

            if (mod != 3)

                goto illegal_op;

            if (b1) {

                rm = (modrm & 7) | REX_B(s);

                tcg_gen_addi_ptr(cpu_ptr0, cpu_env, offsetof(CPUX86State,xmm_regs[rm]));

                tcg_gen_helper_1_1(helper_pmovmskb_xmm, cpu_tmp2_i32, cpu_ptr0);

            } else {

                rm = (modrm & 7);

                tcg_gen_addi_ptr(cpu_ptr0, cpu_env, offsetof(CPUX86State,fpregs[rm].mmx));

                tcg_gen_helper_1_1(helper_pmovmskb_mmx, cpu_tmp2_i32, cpu_ptr0);

            }

            tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);

            reg = ((modrm >> 3) & 7) | rex_r;

            gen_op_mov_reg_T0(OT_LONG, reg);

            break;

        case 0x038:

        case 0x138:

            b = modrm;

            modrm = ldub_code(s->pc++);

            rm = modrm & 7;

            reg = ((modrm >> 3) & 7) | rex_r;

            mod = (modrm >> 6) & 3;

            if (s->prefix & PREFIX_REPNZ)

                goto crc32;

            sse_op2 = sse_op_table6[b].op[b1];

            if (!sse_op2)

                goto illegal_op;

            if (!(s->cpuid_ext_features & sse_op_table6[b].ext_mask))

                goto illegal_op;

            if (b1) {

                op1_offset = offsetof(CPUX86State,xmm_regs[reg]);

                if (mod == 3) {

                    op2_offset = offsetof(CPUX86State,xmm_regs[rm | REX_B(s)]);

                } else {

                    op2_offset = offsetof(CPUX86State,xmm_t0);

                    gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);

                    switch (b) {

                    case 0x20: case 0x30: /* pmovsxbw, pmovzxbw */

                    case 0x23: case 0x33: /* pmovsxwd, pmovzxwd */

                    case 0x25: case 0x35: /* pmovsxdq, pmovzxdq */

                        gen_ldq_env_A0(s->mem_index, op2_offset +

                                        offsetof(XMMReg, XMM_Q(0)));

                        break;

                    case 0x21: case 0x31: /* pmovsxbd, pmovzxbd */

                    case 0x24: case 0x34: /* pmovsxwq, pmovzxwq */

                        tcg_gen_qemu_ld32u(cpu_tmp2_i32, cpu_A0,

                                          (s->mem_index >> 2) - 1);

                        tcg_gen_st_i32(cpu_tmp2_i32, cpu_env, op2_offset +

                                        offsetof(XMMReg, XMM_L(0)));

                        break;

                    case 0x22: case 0x32: /* pmovsxbq, pmovzxbq */

                        tcg_gen_qemu_ld16u(cpu_tmp0, cpu_A0,

                                          (s->mem_index >> 2) - 1);

                        tcg_gen_st16_tl(cpu_tmp0, cpu_env, op2_offset +

                                        offsetof(XMMReg, XMM_W(0)));

                        break;

                    case 0x2a:            /* movntqda */

                        gen_ldo_env_A0(s->mem_index, op1_offset);

                        return;

                    default:

                        gen_ldo_env_A0(s->mem_index, op2_offset);

                    }

                }

            } else {

                op1_offset = offsetof(CPUX86State,fpregs[reg].mmx);

                if (mod == 3) {

                    op2_offset = offsetof(CPUX86State,fpregs[rm].mmx);

                } else {

                    op2_offset = offsetof(CPUX86State,mmx_t0);

                    gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);

                    gen_ldq_env_A0(s->mem_index, op2_offset);

                }

            }

            if (sse_op2 == SSE_SPECIAL)

                goto illegal_op;

            tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);

            tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);

            tcg_gen_helper_0_2(sse_op2, cpu_ptr0, cpu_ptr1);

            if (b == 0x17)

                s->cc_op = CC_OP_EFLAGS;

            break;

        case 0x338: /* crc32 */

        crc32:

            b = modrm;

            modrm = ldub_code(s->pc++);

            reg = ((modrm >> 3) & 7) | rex_r;

            if (b != 0xf0 && b != 0xf1)

                goto illegal_op;

            if (!(s->cpuid_ext_features & CPUID_EXT_SSE42))

                goto illegal_op;

            if (b == 0xf0)

                ot = OT_BYTE;

            else if (b == 0xf1 && s->dflag != 2)

                if (s->prefix & PREFIX_DATA)

                    ot = OT_WORD;

                else

                    ot = OT_LONG;

            else

                ot = OT_QUAD;

            gen_op_mov_TN_reg(OT_LONG, 0, reg);

            tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);

            gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);

            tcg_gen_helper_1_3(helper_crc32, cpu_T[0], cpu_tmp2_i32,

                            cpu_T[0], tcg_const_i32(8 << ot));

            ot = (s->dflag == 2) ? OT_QUAD : OT_LONG;

            gen_op_mov_reg_T0(ot, reg);

            break;

        case 0x03a:

        case 0x13a:

            b = modrm;

            modrm = ldub_code(s->pc++);

            rm = modrm & 7;

            reg = ((modrm >> 3) & 7) | rex_r;

            mod = (modrm >> 6) & 3;

            sse_op2 = sse_op_table7[b].op[b1];

            if (!sse_op2)

                goto illegal_op;

            if (!(s->cpuid_ext_features & sse_op_table7[b].ext_mask))

                goto illegal_op;

            if (sse_op2 == SSE_SPECIAL) {

                ot = (s->dflag == 2) ? OT_QUAD : OT_LONG;

                rm = (modrm & 7) | REX_B(s);

                if (mod != 3)

                    gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);

                reg = ((modrm >> 3) & 7) | rex_r;

                val = ldub_code(s->pc++);

                switch (b) {

                case 0x14: /* pextrb */

                    tcg_gen_ld8u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,

                                            xmm_regs[reg].XMM_B(val & 15)));

                    if (mod == 3)

                        gen_op_mov_reg_T0(ot, rm);

                    else

                        tcg_gen_qemu_st8(cpu_T[0], cpu_A0,

                                        (s->mem_index >> 2) - 1);

                    break;

                case 0x15: /* pextrw */

                    tcg_gen_ld16u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,

                                            xmm_regs[reg].XMM_W(val & 7)));

                    if (mod == 3)

                        gen_op_mov_reg_T0(ot, rm);

                    else

                        tcg_gen_qemu_st16(cpu_T[0], cpu_A0,

                                        (s->mem_index >> 2) - 1);

                    break;

                case 0x16:

                    if (ot == OT_LONG) { /* pextrd */

                        tcg_gen_ld_i32(cpu_tmp2_i32, cpu_env,

                                        offsetof(CPUX86State,

                                                xmm_regs[reg].XMM_L(val & 3)));

                        if (mod == 3)

                            gen_op_mov_reg_v(ot, rm, cpu_tmp2_i32);

                        else

                            tcg_gen_qemu_st32(cpu_tmp2_i32, cpu_A0,

                                            (s->mem_index >> 2) - 1);

                    } else { /* pextrq */

                        tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env,

                                        offsetof(CPUX86State,

                                                xmm_regs[reg].XMM_Q(val & 1)));

                        if (mod == 3)

                            gen_op_mov_reg_v(ot, rm, cpu_tmp1_i64);

                        else

                            tcg_gen_qemu_st64(cpu_tmp1_i64, cpu_A0,

                                            (s->mem_index >> 2) - 1);

                    }

                    break;

                case 0x17: /* extractps */

                    tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,

                                            xmm_regs[reg].XMM_L(val & 3)));

                    if (mod == 3)

                        gen_op_mov_reg_T0(ot, rm);

                    else

                        tcg_gen_qemu_st32(cpu_T[0], cpu_A0,

                                        (s->mem_index >> 2) - 1);

                    break;

                case 0x20: /* pinsrb */

                    if (mod == 3)

                        gen_op_mov_TN_reg(OT_LONG, 0, rm);

                    else

                        tcg_gen_qemu_ld8u(cpu_T[0], cpu_A0,

                                        (s->mem_index >> 2) - 1);

                    tcg_gen_st8_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,

                                            xmm_regs[reg].XMM_B(val & 15)));

                    break;

                case 0x21: /* insertps */

                    if (mod == 3)

                        tcg_gen_ld_i32(cpu_tmp2_i32, cpu_env,

                                        offsetof(CPUX86State,xmm_regs[rm]

                                                .XMM_L((val >> 6) & 3)));

                    else

                        tcg_gen_qemu_ld32u(cpu_tmp2_i32, cpu_A0,

                                        (s->mem_index >> 2) - 1);

                    tcg_gen_st_i32(cpu_tmp2_i32, cpu_env,

                                    offsetof(CPUX86State,xmm_regs[reg]

                                            .XMM_L((val >> 4) & 3)));

                    if ((val >> 0) & 1)

                        tcg_gen_st_i32(tcg_const_i32(0 /*float32_zero*/),

                                        cpu_env, offsetof(CPUX86State,

                                                xmm_regs[reg].XMM_L(0)));

                    if ((val >> 1) & 1)

                        tcg_gen_st_i32(tcg_const_i32(0 /*float32_zero*/),

                                        cpu_env, offsetof(CPUX86State,

                                                xmm_regs[reg].XMM_L(1)));

                    if ((val >> 2) & 1)

                        tcg_gen_st_i32(tcg_const_i32(0 /*float32_zero*/),

                                        cpu_env, offsetof(CPUX86State,

                                                xmm_regs[reg].XMM_L(2)));

                    if ((val >> 3) & 1)

                        tcg_gen_st_i32(tcg_const_i32(0 /*float32_zero*/),

                                        cpu_env, offsetof(CPUX86State,

                                                xmm_regs[reg].XMM_L(3)));

                    break;

                case 0x22:

                    if (ot == OT_LONG) { /* pinsrd */

                        if (mod == 3)

                            gen_op_mov_v_reg(ot, cpu_tmp2_i32, rm);

                        else

                            tcg_gen_qemu_ld32u(cpu_tmp2_i32, cpu_A0,

                                            (s->mem_index >> 2) - 1);

                        tcg_gen_st_i32(cpu_tmp2_i32, cpu_env,

                                        offsetof(CPUX86State,

                                                xmm_regs[reg].XMM_L(val & 3)));

                    } else { /* pinsrq */

                        if (mod == 3)

                            gen_op_mov_v_reg(ot, cpu_tmp1_i64, rm);

                        else

                            tcg_gen_qemu_ld64(cpu_tmp1_i64, cpu_A0,

                                            (s->mem_index >> 2) - 1);

                        tcg_gen_st_i64(cpu_tmp1_i64, cpu_env,

                                        offsetof(CPUX86State,

                                                xmm_regs[reg].XMM_Q(val & 1)));

                    }

                    break;

                }

                return;

            }

            if (b1) {

                op1_offset = offsetof(CPUX86State,xmm_regs[reg]);

                if (mod == 3) {

                    op2_offset = offsetof(CPUX86State,xmm_regs[rm | REX_B(s)]);

                } else {

                    op2_offset = offsetof(CPUX86State,xmm_t0);

                    gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);

                    gen_ldo_env_A0(s->mem_index, op2_offset);

                }

            } else {

                op1_offset = offsetof(CPUX86State,fpregs[reg].mmx);

                if (mod == 3) {

                    op2_offset = offsetof(CPUX86State,fpregs[rm].mmx);

                } else {

                    op2_offset = offsetof(CPUX86State,mmx_t0);

                    gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);

                    gen_ldq_env_A0(s->mem_index, op2_offset);

                }

            }

            val = ldub_code(s->pc++);

            if ((b & 0xfc) == 0x60) { /* pcmpXstrX */

                s->cc_op = CC_OP_EFLAGS;

                if (s->dflag == 2)

                    /* The helper must use entire 64-bit gp registers */

                    val |= 1 << 8;

            }

            tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);

            tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);

            tcg_gen_helper_0_3(sse_op2, cpu_ptr0, cpu_ptr1, tcg_const_i32(val));

            break;

        default:

            goto illegal_op;

        }

    } else {

        /* generic MMX or SSE operation */

        switch(b) {

        case 0x70: /* pshufx insn */

        case 0xc6: /* pshufx insn */

        case 0xc2: /* compare insns */

            s->rip_offset = 1;

            break;

        default:

            break;

        }

        if (is_xmm) {

            op1_offset = offsetof(CPUX86State,xmm_regs[reg]);

            if (mod != 3) {

                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);

                op2_offset = offsetof(CPUX86State,xmm_t0);

                if (b1 >= 2 && ((b >= 0x50 && b <= 0x5f && b != 0x5b) ||

                                b == 0xc2)) {

                    /* specific case for SSE single instructions */

                    if (b1 == 2) {

                        /* 32 bit access */

                        gen_op_ld_T0_A0(OT_LONG + s->mem_index);

                        tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_t0.XMM_L(0)));

                    } else {

                        /* 64 bit access */

                        gen_ldq_env_A0(s->mem_index, offsetof(CPUX86State,xmm_t0.XMM_D(0)));

                    }

                } else {

                    gen_ldo_env_A0(s->mem_index, op2_offset);

                }

            } else {

                rm = (modrm & 7) | REX_B(s);

                op2_offset = offsetof(CPUX86State,xmm_regs[rm]);

            }

        } else {

            op1_offset = offsetof(CPUX86State,fpregs[reg].mmx);

            if (mod != 3) {

                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);

                op2_offset = offsetof(CPUX86State,mmx_t0);

                gen_ldq_env_A0(s->mem_index, op2_offset);

            } else {

                rm = (modrm & 7);

                op2_offset = offsetof(CPUX86State,fpregs[rm].mmx);

            }

        }

        switch(b) {

        case 0x0f: /* 3DNow! data insns */

            if (!(s->cpuid_ext2_features & CPUID_EXT2_3DNOW))

                goto illegal_op;

            val = ldub_code(s->pc++);

            sse_op2 = sse_op_table5[val];

            if (!sse_op2)

                goto illegal_op;

            tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);

            tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);

            tcg_gen_helper_0_2(sse_op2, cpu_ptr0, cpu_ptr1);

            break;

        case 0x70: /* pshufx insn */

        case 0xc6: /* pshufx insn */

            val = ldub_code(s->pc++);

            tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);

            tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);

            tcg_gen_helper_0_3(sse_op2, cpu_ptr0, cpu_ptr1, tcg_const_i32(val));

            break;

        case 0xc2:

            /* compare insns */

            val = ldub_code(s->pc++);

            if (val >= 8)

                goto illegal_op;

            sse_op2 = sse_op_table4[val][b1];

            tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);

            tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);

            tcg_gen_helper_0_2(sse_op2, cpu_ptr0, cpu_ptr1);

            break;

        case 0xf7:

            /* maskmov : we must prepare A0 */

            if (mod != 3)

                goto illegal_op;

#ifdef TARGET_X86_64

            if (s->aflag == 2) {

                gen_op_movq_A0_reg(R_EDI);

            } else

#endif

            {

                gen_op_movl_A0_reg(R_EDI);

                if (s->aflag == 0)

                    gen_op_andl_A0_ffff();

            }

            gen_add_A0_ds_seg(s);

            tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);

            tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);

            tcg_gen_helper_0_3(sse_op2, cpu_ptr0, cpu_ptr1, cpu_A0);

            break;

        default:

            tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);

            tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);

            tcg_gen_helper_0_2(sse_op2, cpu_ptr0, cpu_ptr1);

            break;

        }

        if (b == 0x2e || b == 0x2f) {

            s->cc_op = CC_OP_EFLAGS;

        }

    }

}


static void ff_jref_idct1_add(uint8_t *dest, int line_size, DCTELEM *block)

{

    uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;

    dest[0] = cm[dest[0] + ((block[0] + 4)>>3)];

}


static void hScale_altivec_real(SwsContext *c, int16_t *dst, int dstW,

                                const uint8_t *src, const int16_t *filter,

                                const int16_t *filterPos, int filterSize)

{

    register int i;

    DECLARE_ALIGNED(16, int, tempo)[4];

    if (filterSize % 4) {

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

            register int j;

            register int srcPos = filterPos[i];

            register int val    = 0;

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

                val += ((int)src[srcPos + j]) * filter[filterSize * i + j];

            dst[i] = FFMIN(val >> 7, (1 << 15) - 1);

        }

    } else

        switch (filterSize) {

        case 4:

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

                register int srcPos = filterPos[i];

                vector unsigned char src_v0 = vec_ld(srcPos, src);

                vector unsigned char src_v1, src_vF;

                vector signed short src_v, filter_v;

                vector signed int val_vEven, val_s;

                if ((((uintptr_t)src + srcPos) % 16) > 12) {

                    src_v1 = vec_ld(srcPos + 16, src);

                }

                src_vF = vec_perm(src_v0, src_v1, vec_lvsl(srcPos, src));

                src_v = // vec_unpackh sign-extends...

                        (vector signed short)(vec_mergeh((vector unsigned char)vzero, src_vF));

                // now put our elements in the even slots

                src_v = vec_mergeh(src_v, (vector signed short)vzero);

                filter_v = vec_ld(i << 3, filter);

                // The 3 above is 2 (filterSize == 4) + 1 (sizeof(short) == 2).

                // The neat trick: We only care for half the elements,

                // high or low depending on (i<<3)%16 (it's 0 or 8 here),

                // and we're going to use vec_mule, so we choose

                // carefully how to "unpack" the elements into the even slots.

                if ((i << 3) % 16)

                    filter_v = vec_mergel(filter_v, (vector signed short)vzero);

                else

                    filter_v = vec_mergeh(filter_v, (vector signed short)vzero);

                val_vEven = vec_mule(src_v, filter_v);

                val_s     = vec_sums(val_vEven, vzero);

                vec_st(val_s, 0, tempo);

                dst[i] = FFMIN(tempo[3] >> 7, (1 << 15) - 1);

            }

        break;

        case 8:

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

                register int srcPos = filterPos[i];

                vector unsigned char src_v0 = vec_ld(srcPos, src);

                vector unsigned char src_v1, src_vF;

                vector signed short src_v, filter_v;

                vector signed int val_v, val_s;

                if ((((uintptr_t)src + srcPos) % 16) > 8) {

                    src_v1 = vec_ld(srcPos + 16, src);

                }

                src_vF = vec_perm(src_v0, src_v1, vec_lvsl(srcPos, src));

                src_v = // vec_unpackh sign-extends...

                        (vector signed short)(vec_mergeh((vector unsigned char)vzero, src_vF));

                filter_v = vec_ld(i << 4, filter);

                // the 4 above is 3 (filterSize == 8) + 1 (sizeof(short) == 2)

                val_v = vec_msums(src_v, filter_v, (vector signed int)vzero);

                val_s = vec_sums(val_v, vzero);

                vec_st(val_s, 0, tempo);

                dst[i] = FFMIN(tempo[3] >> 7, (1 << 15) - 1);

            }

        break;

        case 16:

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

                register int srcPos = filterPos[i];

                vector unsigned char src_v0 = vec_ld(srcPos, src);

                vector unsigned char src_v1 = vec_ld(srcPos + 16, src);

                vector unsigned char src_vF = vec_perm(src_v0, src_v1, vec_lvsl(srcPos, src));

                vector signed short src_vA = // vec_unpackh sign-extends...

                                             (vector signed short)(vec_mergeh((vector unsigned char)vzero, src_vF));

                vector signed short src_vB = // vec_unpackh sign-extends...

                                             (vector signed short)(vec_mergel((vector unsigned char)vzero, src_vF));

                vector signed short filter_v0 = vec_ld(i << 5, filter);

                vector signed short filter_v1 = vec_ld((i << 5) + 16, filter);

                // the 5 above are 4 (filterSize == 16) + 1 (sizeof(short) == 2)

                vector signed int val_acc = vec_msums(src_vA, filter_v0, (vector signed int)vzero);

                vector signed int val_v   = vec_msums(src_vB, filter_v1, val_acc);

                vector signed int val_s = vec_sums(val_v, vzero);

                vec_st(val_s, 0, tempo);

                dst[i] = FFMIN(tempo[3] >> 7, (1 << 15) - 1);

            }

        break;

        default:

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

                register int j;

                register int srcPos = filterPos[i];

                vector signed int val_s, val_v = (vector signed int)vzero;

                vector signed short filter_v0R = vec_ld(i * 2 * filterSize, filter);

                vector unsigned char permF     = vec_lvsl((i * 2 * filterSize), filter);

                vector unsigned char src_v0 = vec_ld(srcPos, src);

                vector unsigned char permS  = vec_lvsl(srcPos, src);

                for (j = 0; j < filterSize - 15; j += 16) {

                    vector unsigned char src_v1 = vec_ld(srcPos + j + 16, src);

                    vector unsigned char src_vF = vec_perm(src_v0, src_v1, permS);

                    vector signed short src_vA = // vec_unpackh sign-extends...

                                                 (vector signed short)(vec_mergeh((vector unsigned char)vzero, src_vF));

                    vector signed short src_vB = // vec_unpackh sign-extends...

                                                 (vector signed short)(vec_mergel((vector unsigned char)vzero, src_vF));

                    vector signed short filter_v1R = vec_ld((i * 2 * filterSize) + (j * 2) + 16, filter);

                    vector signed short filter_v2R = vec_ld((i * 2 * filterSize) + (j * 2) + 32, filter);

                    vector signed short filter_v0  = vec_perm(filter_v0R, filter_v1R, permF);

                    vector signed short filter_v1  = vec_perm(filter_v1R, filter_v2R, permF);

                    vector signed int val_acc = vec_msums(src_vA, filter_v0, val_v);

                    val_v = vec_msums(src_vB, filter_v1, val_acc);

                    filter_v0R = filter_v2R;

                    src_v0     = src_v1;

                }

                if (j < filterSize - 7) {

                    // loading src_v0 is useless, it's already done above

                    // vector unsigned char src_v0 = vec_ld(srcPos + j, src);

                    vector unsigned char src_v1, src_vF;

                    vector signed short src_v, filter_v1R, filter_v;

                    if ((((uintptr_t)src + srcPos) % 16) > 8) {

                        src_v1 = vec_ld(srcPos + j + 16, src);

                    }

                    src_vF = vec_perm(src_v0, src_v1, permS);

                    src_v = // vec_unpackh sign-extends...

                            (vector signed short)(vec_mergeh((vector unsigned char)vzero, src_vF));

                    // loading filter_v0R is useless, it's already done above

                    // vector signed short filter_v0R = vec_ld((i * 2 * filterSize) + j, filter);

                    filter_v1R = vec_ld((i * 2 * filterSize) + (j * 2) + 16, filter);

                    filter_v   = vec_perm(filter_v0R, filter_v1R, permF);

                    val_v = vec_msums(src_v, filter_v, val_v);

                }

                val_s = vec_sums(val_v, vzero);

                vec_st(val_s, 0, tempo);

                dst[i] = FFMIN(tempo[3] >> 7, (1 << 15) - 1);

            }

        }

}


static int dfa_decode_frame(AVCodecContext *avctx,

                            void *data, int *data_size,

                            AVPacket *avpkt)

{

    DfaContext *s = avctx->priv_data;

    const uint8_t *buf = avpkt->data;

    const uint8_t *buf_end = avpkt->data + avpkt->size;

    const uint8_t *tmp_buf;

    uint32_t chunk_type, chunk_size;

    uint8_t *dst;

    int ret;

    int i, pal_elems;

    if (s->pic.data[0])

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

    if ((ret = avctx->get_buffer(avctx, &s->pic))) {

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

        return ret;

    }

    while (buf < buf_end) {

        chunk_size = AV_RL32(buf + 4);

        chunk_type = AV_RL32(buf + 8);

        buf += 12;

        if (buf_end - buf < chunk_size) {

            av_log(avctx, AV_LOG_ERROR, "Chunk size is too big (%d bytes)\n", chunk_size);

            return -1;

        }

        if (!chunk_type)

            break;

        if (chunk_type == 1) {

            pal_elems = FFMIN(chunk_size / 3, 256);

            tmp_buf = buf;

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

                s->pal[i] = bytestream_get_be24(&tmp_buf) << 2;

                s->pal[i] |= (s->pal[i] >> 6) & 0x333;

            }

            s->pic.palette_has_changed = 1;

        } else if (chunk_type <= 9) {

            if (decoder[chunk_type - 2](s->frame_buf, avctx->width, avctx->height,

                                        buf, buf + chunk_size)) {

                av_log(avctx, AV_LOG_ERROR, "Error decoding %s chunk\n",

                       chunk_name[chunk_type - 2]);

                return -1;

            }

        } else {

            av_log(avctx, AV_LOG_WARNING, "Ignoring unknown chunk type %d\n",

                   chunk_type);

        }

        buf += chunk_size;

    }

    buf = s->frame_buf;

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

    for (i = 0; i < avctx->height; i++) {

        memcpy(dst, buf, avctx->width);

        dst += s->pic.linesize[0];

        buf += avctx->width;

    }

    memcpy(s->pic.data[1], s->pal, sizeof(s->pal));

    *data_size = sizeof(AVFrame);

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

    return avpkt->size;

}


static int init_file(AVFormatContext *s, OutputStream *os, int64_t start_ts)

{

    int ret, i;

    ret = avio_open2(&os->out, os->temp_filename, AVIO_FLAG_WRITE,

                     &s->interrupt_callback, NULL);

    if (ret < 0)

        return ret;

    avio_wb32(os->out, 0);

    avio_wl32(os->out, MKTAG('m','d','a','t'));

    for (i = 0; i < os->nb_extra_packets; i++) {

        AV_WB24(os->extra_packets[i] + 4, start_ts);

        os->extra_packets[i][7] = (start_ts >> 24) & 0x7f;

        avio_write(os->out, os->extra_packets[i], os->extra_packet_sizes[i]);

    }

    return 0;

}


static inline void log_input_change(void *ctx, AVFilterLink *link, AVFilterBufferRef *ref)

{

    char old_layout_str[16], new_layout_str[16];

    av_get_channel_layout_string(old_layout_str, sizeof(old_layout_str),

                                 -1, link->channel_layout);

    av_get_channel_layout_string(new_layout_str, sizeof(new_layout_str),

                                 -1, ref->audio->channel_layout);

    av_log(ctx, AV_LOG_INFO,

           "Audio input format changed: "

           "%s:%s:%"PRId64" -> %s:%s:%u, normalizing\n",

           av_get_sample_fmt_name(link->format),

           old_layout_str, link->sample_rate,

           av_get_sample_fmt_name(ref->format),

           new_layout_str, ref->audio->sample_rate);

}


static int decode_mime_header(AMRWBContext *ctx, const uint8_t *buf)

{

    /* Decode frame header (1st octet) */

    ctx->fr_cur_mode  = buf[0] >> 3 & 0x0F;

    ctx->fr_quality   = (buf[0] & 0x4) != 0x4;

    return 1;

}


static void init_entropy_decoder(APEContext *ctx)

{

    /* Read the CRC */

    ctx->CRC = bytestream_get_be32(&ctx->ptr);

    /* Read the frame flags if they exist */

    ctx->frameflags = 0;

    if ((ctx->fileversion > 3820) && (ctx->CRC & 0x80000000)) {

        ctx->CRC &= ~0x80000000;

        ctx->frameflags = bytestream_get_be32(&ctx->ptr);

    }

    /* Keep a count of the blocks decoded in this frame */

    ctx->blocksdecoded = 0;

    /* Initialize the rice structs */

    ctx->riceX.k = 10;

    ctx->riceX.ksum = (1 << ctx->riceX.k) * 16;

    ctx->riceY.k = 10;

    ctx->riceY.ksum = (1 << ctx->riceY.k) * 16;

    /* The first 8 bits of input are ignored. */

    ctx->ptr++;

    range_start_decoding(ctx);

}


static gboolean qio_channel_yield_enter(QIOChannel *ioc,

                                        GIOCondition condition,

                                        gpointer opaque)

{

    QIOChannelYieldData *data = opaque;

    qemu_coroutine_enter(data->co, NULL);

    return FALSE;

}


void usb_ehci_realize(EHCIState *s, DeviceState *dev, Error **errp)

{

    int i;

    if (s->portnr > NB_PORTS) {

        error_setg(errp, "Too many ports! Max. port number is %d.",

                   NB_PORTS);

    usb_bus_new(&s->bus, sizeof(s->bus), s->companion_enable ?

                &ehci_bus_ops_companion : &ehci_bus_ops_standalone, dev);

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

        usb_register_port(&s->bus, &s->ports[i], s, i, &ehci_port_ops,

                          USB_SPEED_MASK_HIGH);

        s->ports[i].dev = 0;

    s->frame_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, ehci_work_timer, s);

    s->async_bh = qemu_bh_new(ehci_work_bh, s);

    s->device = dev;

    s->vmstate = qemu_add_vm_change_state_handler(usb_ehci_vm_state_change, s);


void qemu_system_guest_panicked(void)

{

    qapi_event_send_guest_panicked(GUEST_PANIC_ACTION_PAUSE, &error_abort);

    vm_stop(RUN_STATE_GUEST_PANICKED);


static void get_sub_picture(CinepakEncContext *s, int x, int y, AVPicture *in, AVPicture *out)

{

    out->data[0] = in->data[0] + x + y * in->linesize[0];

    out->linesize[0] = in->linesize[0];

    if(s->pix_fmt == AV_PIX_FMT_YUV420P) {

        out->data[1] = in->data[1] + (x >> 1) + (y >> 1) * in->linesize[1];

        out->linesize[1] = in->linesize[1];

        out->data[2] = in->data[2] + (x >> 1) + (y >> 1) * in->linesize[2];

        out->linesize[2] = in->linesize[2];

    }

}


int attribute_align_arg avcodec_open2(AVCodecContext *avctx, AVCodec *codec, AVDictionary **options)
{
    int ret = 0;
    AVDictionary *tmp = NULL;
    if (avctx->extradata_size < 0 || avctx->extradata_size >= FF_MAX_EXTRADATA_SIZE)
        return AVERROR(EINVAL);
    if (options)
        av_dict_copy(&tmp, *options, 0);
    /* If there is a user-supplied mutex locking routine, call it. */
    if (ff_lockmgr_cb) {
        if ((*ff_lockmgr_cb)(&codec_mutex, AV_LOCK_OBTAIN))
            return -1;
    entangled_thread_counter++;
    if(entangled_thread_counter != 1){
        av_log(avctx, AV_LOG_ERROR, "insufficient thread locking around avcodec_open/close()\n");
        goto end;
    if(avctx->codec || !codec) {
        ret = AVERROR(EINVAL);
        goto end;
    avctx->internal = av_mallocz(sizeof(AVCodecInternal));
    if (!avctx->internal) {
        ret = AVERROR(ENOMEM);
        goto end;
    if (codec->priv_data_size > 0) {
      if(!avctx->priv_data){
        avctx->priv_data = av_mallocz(codec->priv_data_size);
        if (!avctx->priv_data) {
            ret = AVERROR(ENOMEM);
            goto end;
        if (codec->priv_class) {
            *(AVClass**)avctx->priv_data= codec->priv_class;
            av_opt_set_defaults(avctx->priv_data);
      if (codec->priv_class && (ret = av_opt_set_dict(avctx->priv_data, &tmp)) < 0)
    } else {
        avctx->priv_data = NULL;
    if ((ret = av_opt_set_dict(avctx, &tmp)) < 0)
    //We only call avcodec_set_dimensions() for non h264 codecs so as not to overwrite previously setup dimensions
    if(!( avctx->coded_width && avctx->coded_height && avctx->width && avctx->height && avctx->codec_id == CODEC_ID_H264)){
    if(avctx->coded_width && avctx->coded_height)
        avcodec_set_dimensions(avctx, avctx->coded_width, avctx->coded_height);
    else if(avctx->width && avctx->height)
        avcodec_set_dimensions(avctx, avctx->width, avctx->height);
    if ((avctx->coded_width || avctx->coded_height || avctx->width || avctx->height)
        && (  av_image_check_size(avctx->coded_width, avctx->coded_height, 0, avctx) < 0
           || av_image_check_size(avctx->width,       avctx->height,       0, avctx) < 0)) {
        av_log(avctx, AV_LOG_WARNING, "ignoring invalid width/height values\n");
        avcodec_set_dimensions(avctx, 0, 0);
    /* if the decoder init function was already called previously,
       free the already allocated subtitle_header before overwriting it */
    if (codec->decode)
        av_freep(&avctx->subtitle_header);
#define SANE_NB_CHANNELS 128U
    if (avctx->channels > SANE_NB_CHANNELS) {
        ret = AVERROR(EINVAL);
    avctx->codec = codec;
    if ((avctx->codec_type == AVMEDIA_TYPE_UNKNOWN || avctx->codec_type == codec->type) &&
        avctx->codec_id == CODEC_ID_NONE) {
        avctx->codec_type = codec->type;
        avctx->codec_id   = codec->id;
    if (avctx->codec_id != codec->id || (avctx->codec_type != codec->type
                           && avctx->codec_type != AVMEDIA_TYPE_ATTACHMENT)) {
        av_log(avctx, AV_LOG_ERROR, "codec type or id mismatches\n");
        ret = AVERROR(EINVAL);
    avctx->frame_number = 0;
#if FF_API_ER
    av_log(avctx, AV_LOG_DEBUG, "err{or,}_recognition separate: %d; %X\n",
           avctx->error_recognition, avctx->err_recognition);
    switch(avctx->error_recognition){
        case FF_ER_EXPLODE        : avctx->err_recognition |= AV_EF_EXPLODE | AV_EF_COMPLIANT | AV_EF_CAREFUL;
            break;
        case FF_ER_VERY_AGGRESSIVE:
        case FF_ER_AGGRESSIVE     : avctx->err_recognition |= AV_EF_AGGRESSIVE;
        case FF_ER_COMPLIANT      : avctx->err_recognition |= AV_EF_COMPLIANT;
        case FF_ER_CAREFUL        : avctx->err_recognition |= AV_EF_CAREFUL;
    av_log(avctx, AV_LOG_DEBUG, "err{or,}_recognition combined: %d; %X\n",
           avctx->error_recognition, avctx->err_recognition);
#endif
    if (!HAVE_THREADS)
        av_log(avctx, AV_LOG_WARNING, "Warning: not compiled with thread support, using thread emulation\n");
    if (HAVE_THREADS && !avctx->thread_opaque) {
        ret = ff_thread_init(avctx);
        if (ret < 0) {
    if (!HAVE_THREADS && !(codec->capabilities & CODEC_CAP_AUTO_THREADS))
        avctx->thread_count = 1;
    if (avctx->codec->max_lowres < avctx->lowres || avctx->lowres < 0) {
        av_log(avctx, AV_LOG_ERROR, "The maximum value for lowres supported by the decoder is %d\n",
               avctx->codec->max_lowres);
        ret = AVERROR(EINVAL);
    if (avctx->codec->encode) {
        int i;
        if (avctx->codec->sample_fmts) {
            for (i = 0; avctx->codec->sample_fmts[i] != AV_SAMPLE_FMT_NONE; i++)
                if (avctx->sample_fmt == avctx->codec->sample_fmts[i])
                    break;
            if (avctx->codec->sample_fmts[i] == AV_SAMPLE_FMT_NONE) {
                av_log(avctx, AV_LOG_ERROR, "Specified sample_fmt is not supported.\n");
                ret = AVERROR(EINVAL);
        if (avctx->codec->supported_samplerates) {
            for (i = 0; avctx->codec->supported_samplerates[i] != 0; i++)
                if (avctx->sample_rate == avctx->codec->supported_samplerates[i])
                    break;
            if (avctx->codec->supported_samplerates[i] == 0) {
                av_log(avctx, AV_LOG_ERROR, "Specified sample_rate is not supported\n");
                ret = AVERROR(EINVAL);
        if (avctx->codec->channel_layouts) {
            if (!avctx->channel_layout) {
                av_log(avctx, AV_LOG_WARNING, "channel_layout not specified\n");
            } else {
                for (i = 0; avctx->codec->channel_layouts[i] != 0; i++)
                    if (avctx->channel_layout == avctx->codec->channel_layouts[i])
                        break;
                if (avctx->codec->channel_layouts[i] == 0) {
                    av_log(avctx, AV_LOG_ERROR, "Specified channel_layout is not supported\n");
                    ret = AVERROR(EINVAL);
        if (avctx->channel_layout && avctx->channels) {
            if (av_get_channel_layout_nb_channels(avctx->channel_layout) != avctx->channels) {
                av_log(avctx, AV_LOG_ERROR, "channel layout does not match number of channels\n");
                ret = AVERROR(EINVAL);
        } else if (avctx->channel_layout) {
            avctx->channels = av_get_channel_layout_nb_channels(avctx->channel_layout);
    avctx->pts_correction_num_faulty_pts =
    avctx->pts_correction_num_faulty_dts = 0;
    avctx->pts_correction_last_pts =
    avctx->pts_correction_last_dts = INT64_MIN;
    if(avctx->codec->init && !(avctx->active_thread_type&FF_THREAD_FRAME)){
        ret = avctx->codec->init(avctx);
        if (ret < 0) {
    ret=0;
end:
    entangled_thread_counter--;
    /* Release any user-supplied mutex. */
    if (ff_lockmgr_cb) {
        (*ff_lockmgr_cb)(&codec_mutex, AV_LOCK_RELEASE);
    if (options) {
        av_dict_free(options);
        *options = tmp;
    return ret;
free_and_end:
    av_dict_free(&tmp);
    av_freep(&avctx->priv_data);
    av_freep(&avctx->internal);
    avctx->codec= NULL;
    goto end;


static void cpu_class_init(ObjectClass *klass, void *data)

{

    DeviceClass *dc = DEVICE_CLASS(klass);

    CPUClass *k = CPU_CLASS(klass);

    k->class_by_name = cpu_common_class_by_name;

    k->reset = cpu_common_reset;

    k->get_arch_id = cpu_common_get_arch_id;

    k->get_paging_enabled = cpu_common_get_paging_enabled;

    k->get_memory_mapping = cpu_common_get_memory_mapping;

    k->write_elf32_qemunote = cpu_common_write_elf32_qemunote;

    k->write_elf32_note = cpu_common_write_elf32_note;

    k->write_elf64_qemunote = cpu_common_write_elf64_qemunote;

    k->write_elf64_note = cpu_common_write_elf64_note;

    k->gdb_read_register = cpu_common_gdb_read_register;

    k->gdb_write_register = cpu_common_gdb_write_register;

    dc->realize = cpu_common_realizefn;

    dc->no_user = 1;

}


static int fill_note_info(struct elf_note_info *info,

                          long signr, const CPUArchState *env)

{

#define NUMNOTES 3

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

    TaskState *ts = (TaskState *)cpu->opaque;

    int i;

    info->notes = g_malloc0(NUMNOTES * sizeof (struct memelfnote));

    if (info->notes == NULL)

        return (-ENOMEM);

    info->prstatus = g_malloc0(sizeof (*info->prstatus));

    if (info->prstatus == NULL)

        return (-ENOMEM);

    info->psinfo = g_malloc0(sizeof (*info->psinfo));

    if (info->prstatus == NULL)

        return (-ENOMEM);

    /*

     * First fill in status (and registers) of current thread

     * including process info & aux vector.

     */

    fill_prstatus(info->prstatus, ts, signr);

    elf_core_copy_regs(&info->prstatus->pr_reg, env);

    fill_note(&info->notes[0], "CORE", NT_PRSTATUS,

              sizeof (*info->prstatus), info->prstatus);

    fill_psinfo(info->psinfo, ts);

    fill_note(&info->notes[1], "CORE", NT_PRPSINFO,

              sizeof (*info->psinfo), info->psinfo);

    fill_auxv_note(&info->notes[2], ts);

    info->numnote = 3;

    info->notes_size = 0;

    for (i = 0; i < info->numnote; i++)

        info->notes_size += note_size(&info->notes[i]);

    /* read and fill status of all threads */

    cpu_list_lock();

    CPU_FOREACH(cpu) {

        if (cpu == thread_cpu) {

            continue;

        }

        fill_thread_info(info, (CPUArchState *)cpu->env_ptr);

    }

    cpu_list_unlock();

    return (0);

}


static uint16List **host_memory_append_node(uint16List **node,

                                            unsigned long value)

{

     *node = g_malloc0(sizeof(**node));

     (*node)->value = value;

     return &(*node)->next;

}


static int e1000_post_load(void *opaque, int version_id)

{

    E1000State *s = opaque;

    NetClientState *nc = qemu_get_queue(s->nic);

    /* nc.link_down can't be migrated, so infer link_down according

     * to link status bit in mac_reg[STATUS] */

    nc->link_down = (s->mac_reg[STATUS] & E1000_STATUS_LU) == 0;

    return 0;

}


bdrv_acct_start(BlockDriverState *bs, BlockAcctCookie *cookie, int64_t bytes,

        enum BlockAcctType type)

{

    assert(type < BDRV_MAX_IOTYPE);

    cookie->bytes = bytes;

    cookie->start_time_ns = get_clock();

    cookie->type = type;

}


static int tcp_open(URLContext *h, const char *uri, int flags)

{

    struct sockaddr_in dest_addr;

    int port, fd = -1;

    TCPContext *s = NULL;

    fd_set wfds;

    int fd_max, ret;

    struct timeval tv;

    socklen_t optlen;

    char hostname[1024],proto[1024],path[1024],tmp[1024],*q;

    if(!ff_network_init())

        return AVERROR(EIO);

    url_split(proto, sizeof(proto), NULL, 0, hostname, sizeof(hostname),

        &port, path, sizeof(path), uri);

    if (strcmp(proto,"tcp") || port <= 0 || port >= 65536)

        return AVERROR(EINVAL);

    if ((q = strchr(hostname,'@'))) { strcpy(tmp,q+1); strcpy(hostname,tmp); }

    dest_addr.sin_family = AF_INET;

    dest_addr.sin_port = htons(port);

    if (resolve_host(&dest_addr.sin_addr, hostname) < 0)

        return AVERROR(EIO);

    fd = socket(AF_INET, SOCK_STREAM, 0);

    if (fd < 0)

        return AVERROR(EIO);

    ff_socket_nonblock(fd, 1);

 redo:

    ret = connect(fd, (struct sockaddr *)&dest_addr,

                  sizeof(dest_addr));

    if (ret < 0) {

        if (ff_neterrno() == FF_NETERROR(EINTR))

            goto redo;

        if (ff_neterrno() != FF_NETERROR(EINPROGRESS) &&

            ff_neterrno() != FF_NETERROR(EAGAIN))

            goto fail;

        /* wait until we are connected or until abort */

        for(;;) {

            if (url_interrupt_cb()) {

                ret = AVERROR(EINTR);

                goto fail1;

            }

            fd_max = fd;

            FD_ZERO(&wfds);

            FD_SET(fd, &wfds);

            tv.tv_sec = 0;

            tv.tv_usec = 100 * 1000;

            ret = select(fd_max + 1, NULL, &wfds, NULL, &tv);

            if (ret > 0 && FD_ISSET(fd, &wfds))

                break;

        }

        /* test error */

        optlen = sizeof(ret);

        getsockopt (fd, SOL_SOCKET, SO_ERROR, &ret, &optlen);

        if (ret != 0)

            goto fail;

    }

    s = av_malloc(sizeof(TCPContext));

    if (!s)

        return AVERROR(ENOMEM);

    h->priv_data = s;

    h->is_streamed = 1;

    s->fd = fd;

    return 0;

 fail:

    ret = AVERROR(EIO);

 fail1:

    if (fd >= 0)

        closesocket(fd);

    return ret;

}


static av_always_inline int even(uint64_t layout)

{

    return (!layout || (layout & (layout - 1)));

}


static int xen_host_pci_get_value(XenHostPCIDevice *d, const char *name,

                                  unsigned int *pvalue, int base)

{

    char path[PATH_MAX];

    char buf[XEN_HOST_PCI_GET_VALUE_BUFFER_SIZE];

    int fd, rc;

    unsigned long value;

    char *endptr;

    rc = xen_host_pci_sysfs_path(d, name, path, sizeof (path));

    if (rc) {

        return rc;

    }

    fd = open(path, O_RDONLY);

    if (fd == -1) {

        XEN_HOST_PCI_LOG("Error: Can't open %s: %s\n", path, strerror(errno));

        return -errno;

    }

    do {

        rc = read(fd, &buf, sizeof (buf) - 1);

        if (rc < 0 && errno != EINTR) {

            rc = -errno;

            goto out;

        }

    } while (rc < 0);

    buf[rc] = 0;

    value = strtol(buf, &endptr, base);

    if (endptr == buf || *endptr != '\n') {

        rc = -1;

    } else if ((value == LONG_MIN || value == LONG_MAX) && errno == ERANGE) {

        rc = -errno;

    } else {

        rc = 0;

        *pvalue = value;

    }

out:

    close(fd);

    return rc;

}


static int64_t mkv_write_seekhead(AVIOContext *pb, mkv_seekhead *seekhead)

{

    ebml_master metaseek, seekentry;

    int64_t currentpos;

    int i;

    currentpos = avio_tell(pb);

    if (seekhead->reserved_size > 0)

        if (avio_seek(pb, seekhead->filepos, SEEK_SET) < 0)

            return -1;

    metaseek = start_ebml_master(pb, MATROSKA_ID_SEEKHEAD, seekhead->reserved_size);

    for (i = 0; i < seekhead->num_entries; i++) {

        mkv_seekhead_entry *entry = &seekhead->entries[i];

        seekentry = start_ebml_master(pb, MATROSKA_ID_SEEKENTRY, MAX_SEEKENTRY_SIZE);

        put_ebml_id(pb, MATROSKA_ID_SEEKID);

        put_ebml_num(pb, ebml_id_size(entry->elementid), 0);

        put_ebml_id(pb, entry->elementid);

        put_ebml_uint(pb, MATROSKA_ID_SEEKPOSITION, entry->segmentpos);

        end_ebml_master(pb, seekentry);

    }

    end_ebml_master(pb, metaseek);

    if (seekhead->reserved_size > 0) {

        uint64_t remaining = seekhead->filepos + seekhead->reserved_size - avio_tell(pb);

        put_ebml_void(pb, remaining);

        avio_seek(pb, currentpos, SEEK_SET);

        currentpos = seekhead->filepos;

    }

    av_free(seekhead->entries);

    av_free(seekhead);

    return currentpos;

}


static int wavpack_decode_frame(AVCodecContext *avctx,

                            void *data, int *data_size,

                            AVPacket *avpkt)

{

    WavpackContext *s = avctx->priv_data;

    const uint8_t *buf = avpkt->data;

    int buf_size = avpkt->size;

    int frame_size;

    int samplecount = 0;

    s->block = 0;

    s->samples_left = 0;

    s->ch_offset = 0;

    if(s->mkv_mode){

        s->samples = AV_RL32(buf); buf += 4;

    }

    while(buf_size > 0){

        if(!s->multichannel){

            frame_size = buf_size;

        }else{

            if(!s->mkv_mode){

                frame_size = AV_RL32(buf) - 12; buf += 4; buf_size -= 4;

            }else{

                if(buf_size < 12) //MKV files can have zero flags after last block

                    break;

                frame_size = AV_RL32(buf + 8) + 12;

            }

        }

        if(frame_size < 0 || frame_size > buf_size){

            av_log(avctx, AV_LOG_ERROR, "Block %d has invalid size (size %d vs. %d bytes left)\n",

                   s->block, frame_size, buf_size);

            return -1;

        }

        if((samplecount = wavpack_decode_block(avctx, s->block, data,

                                               data_size, buf, frame_size)) < 0)

            return -1;

        s->block++;

        buf += frame_size; buf_size -= frame_size;

    }

    *data_size = samplecount * avctx->channels;

    return s->samples_left > 0 ? 0 : avpkt->size;

}


static int get_bits(J2kDecoderContext *s, int n)

{

    int res = 0;

    if (s->buf_end - s->buf < ((n - s->bit_index) >> 8))

        return AVERROR(EINVAL);

    while (--n >= 0){

        res <<= 1;

        if (s->bit_index == 0){

            s->bit_index = 7 + (*s->buf != 0xff);

            s->buf++;

        }

        s->bit_index--;

        res |= (*s->buf >> s->bit_index) & 1;

    }

    return res;

}


static uint32_t drc_set_usable(sPAPRDRConnector *drc)

{

    /* if there's no resource/device associated with the DRC, there's

     * no way for us to put it in an allocation state consistent with

     * being 'USABLE'. PAPR 2.7, 13.5.3.4 documents that this should

     * result in an RTAS return code of -3 / "no such indicator"

     */

    if (!drc->dev) {

        return RTAS_OUT_NO_SUCH_INDICATOR;

    }

    if (drc->awaiting_release && drc->awaiting_allocation) {

        /* kernel is acknowledging a previous hotplug event

         * while we are already removing it.

         * it's safe to ignore awaiting_allocation here since we know the

         * situation is predicated on the guest either already having done

         * so (boot-time hotplug), or never being able to acquire in the

         * first place (hotplug followed by immediate unplug).

         */

        return RTAS_OUT_NO_SUCH_INDICATOR;

    }

    drc->allocation_state = SPAPR_DR_ALLOCATION_STATE_USABLE;

    drc->awaiting_allocation = false;

    return RTAS_OUT_SUCCESS;

}


static ssize_t qcow2_crypto_hdr_init_func(QCryptoBlock *block, size_t headerlen,

                                          void *opaque, Error **errp)

{

    BlockDriverState *bs = opaque;

    BDRVQcow2State *s = bs->opaque;

    int64_t ret;

    int64_t clusterlen;

    ret = qcow2_alloc_clusters(bs, headerlen);

    if (ret < 0) {

        error_setg_errno(errp, -ret,

                         "Cannot allocate cluster for LUKS header size %zu",

                         headerlen);

        return -1;

    }

    s->crypto_header.length = headerlen;

    s->crypto_header.offset = ret;

    /* Zero fill remaining space in cluster so it has predictable

     * content in case of future spec changes */

    clusterlen = size_to_clusters(s, headerlen) * s->cluster_size;

    ret = bdrv_pwrite_zeroes(bs->file,

                             ret + headerlen,

                             clusterlen - headerlen, 0);

    if (ret < 0) {

        error_setg_errno(errp, -ret, "Could not zero fill encryption header");

        return -1;

    }

    return ret;

}


static int get_cookies(HTTPContext *s, char **cookies, const char *path,

                       const char *domain)

{

    // cookie strings will look like Set-Cookie header field values.  Multiple

    // Set-Cookie fields will result in multiple values delimited by a newline

    int ret = 0;

    char *next, *cookie, *set_cookies = av_strdup(s->cookies), *cset_cookies = set_cookies;

    if (!set_cookies) return AVERROR(EINVAL);

    *cookies = NULL;

    while ((cookie = av_strtok(set_cookies, "\n", &next))) {

        int domain_offset = 0;

        char *param, *next_param, *cdomain = NULL, *cpath = NULL, *cvalue = NULL;

        set_cookies = NULL;

        while ((param = av_strtok(cookie, "; ", &next_param))) {

            cookie = NULL;

            if        (!av_strncasecmp("path=",   param, 5)) {

                cpath = av_strdup(&param[5]);

            } else if (!av_strncasecmp("domain=", param, 7)) {

                cdomain = av_strdup(&param[7]);

            } else if (!av_strncasecmp("secure",  param, 6) ||

                       !av_strncasecmp("comment", param, 7) ||

                       !av_strncasecmp("max-age", param, 7) ||

                       !av_strncasecmp("version", param, 7)) {

                // ignore Comment, Max-Age, Secure and Version

            } else {

                av_free(cvalue);

                cvalue = av_strdup(param);

            }

        }

        // ensure all of the necessary values are valid

        if (!cdomain || !cpath || !cvalue) {

            av_log(s, AV_LOG_WARNING,

                   "Invalid cookie found, no value, path or domain specified\n");

            goto done_cookie;

        }

        // check if the request path matches the cookie path

        if (av_strncasecmp(path, cpath, strlen(cpath)))

            goto done_cookie;

        // the domain should be at least the size of our cookie domain

        domain_offset = strlen(domain) - strlen(cdomain);

        if (domain_offset < 0)

            goto done_cookie;

        // match the cookie domain

        if (av_strcasecmp(&domain[domain_offset], cdomain))

            goto done_cookie;

        // cookie parameters match, so copy the value

        if (!*cookies) {

            if (!(*cookies = av_strdup(cvalue))) {

                ret = AVERROR(ENOMEM);

                goto done_cookie;

            }

        } else {

            char *tmp = *cookies;

            size_t str_size = strlen(cvalue) + strlen(*cookies) + 3;

            if (!(*cookies = av_malloc(str_size))) {

                ret = AVERROR(ENOMEM);

                goto done_cookie;

            }

            snprintf(*cookies, str_size, "%s; %s", tmp, cvalue);

            av_free(tmp);

        }

        done_cookie:

        av_free(cvalue);

        if (ret < 0) {

            if (*cookies) av_freep(cookies);

            av_free(cset_cookies);

            return ret;

        }

    }

    av_free(cset_cookies);

    return 0;

}


static inline void xan_wc3_copy_pixel_run(XanContext *s,

    int x, int y, int pixel_count, int motion_x, int motion_y)

{

    int stride;

    int line_inc;

    int curframe_index, prevframe_index;

    int curframe_x, prevframe_x;

    int width = s->avctx->width;

    unsigned char *palette_plane, *prev_palette_plane;

    palette_plane = s->current_frame.data[0];

    prev_palette_plane = s->last_frame.data[0];

    stride = s->current_frame.linesize[0];

    line_inc = stride - width;

    curframe_index = y * stride + x;

    curframe_x = x;

    prevframe_index = (y + motion_y) * stride + x + motion_x;

    prevframe_x = x + motion_x;

    while(pixel_count && (curframe_index < s->frame_size)) {

        int count = FFMIN3(pixel_count, width - curframe_x, width - prevframe_x);

        memcpy(palette_plane + curframe_index, prev_palette_plane + prevframe_index, count);

        pixel_count     -= count;

        curframe_index  += count;

        prevframe_index += count;

        curframe_x      += count;

        prevframe_x     += count;

        if (curframe_x >= width) {

            curframe_index += line_inc;

            curframe_x = 0;

        }

        if (prevframe_x >= width) {

            prevframe_index += line_inc;

            prevframe_x = 0;

        }

    }

}


pixman_format_code_t qemu_default_pixman_format(int bpp, bool native_endian)

{

    if (native_endian) {

        switch (bpp) {

        case 15:

            return PIXMAN_x1r5g5b5;

        case 16:

            return PIXMAN_r5g6b5;

        case 24:

            return PIXMAN_r8g8b8;

        case 32:

            return PIXMAN_x8r8g8b8;

        }

    } else {

        switch (bpp) {

        case 24:

            return PIXMAN_b8g8r8;

        case 32:

            return PIXMAN_b8g8r8x8;

        break;

        }

    }

    g_assert_not_reached();

}


static ssize_t handle_aiocb_rw_linear(RawPosixAIOData *aiocb, char *buf)

{

    ssize_t offset = 0;

    ssize_t len;

    while (offset < aiocb->aio_nbytes) {

        if (aiocb->aio_type & QEMU_AIO_WRITE) {

            len = pwrite(aiocb->aio_fildes,

                         (const char *)buf + offset,

                         aiocb->aio_nbytes - offset,

                         aiocb->aio_offset + offset);

        } else {

            len = pread(aiocb->aio_fildes,

                        buf + offset,

                        aiocb->aio_nbytes - offset,

                        aiocb->aio_offset + offset);

        }

        if (len == -1 && errno == EINTR) {

            continue;

        } else if (len == -1) {

            offset = -errno;

        } else if (len == 0) {

        }

        offset += len;

    }

    return offset;

}


static inline int get_block(GetBitContext *gb, DCTELEM *block, const uint8_t *scan,
                            const uint32_t *quant) {
    int coeff, i, n;
    int8_t ac;
    uint8_t dc = get_bits(gb, 8);
    // block not coded
    if (dc == 255)
    // number of non-zero coefficients
    coeff = get_bits(gb, 6);
    // normally we would only need to clear the (63 - coeff) last values,
    // but since we do not know where they are we just clear the whole block
    memset(block, 0, 64 * sizeof(DCTELEM));
    // 2 bits per coefficient
    while (coeff) {
        ac = get_sbits(gb, 2);
        if (ac == -2)
            break; // continue with more bits
        PUT_COEFF(ac);
    }
    // 4 bits per coefficient
    ALIGN(4);
    if (get_bits_count(gb) + (coeff << 2) >= gb->size_in_bits)
    while (coeff) {
        ac = get_sbits(gb, 4);
        if (ac == -8)
            break; // continue with more bits
        PUT_COEFF(ac);
    }
    // 8 bits per coefficient
    ALIGN(8);
    if (get_bits_count(gb) + (coeff << 3) >= gb->size_in_bits)
    while (coeff) {
        ac = get_sbits(gb, 8);
        PUT_COEFF(ac);
    }
    PUT_COEFF(dc);
    return 1;
}


vcard_emul_find_vreader_from_slot(PK11SlotInfo *slot)

{

    VReaderList *reader_list = vreader_get_reader_list();

    VReaderListEntry *current_entry = NULL;

    if (reader_list == NULL) {

        return NULL;

    }

    for (current_entry = vreader_list_get_first(reader_list); current_entry;

                        current_entry = vreader_list_get_next(current_entry)) {

        VReader *reader = vreader_list_get_reader(current_entry);

        VReaderEmul *reader_emul = vreader_get_private(reader);

        if (reader_emul->slot == slot) {

            return reader;

        }

        vreader_free(reader);

    }

    return NULL;

}


static int can_merge_formats(AVFilterFormats *a_arg,

                             AVFilterFormats *b_arg,

                             enum AVMediaType type,

                             int is_sample_rate)

{

    AVFilterFormats *a, *b, *ret;

    if (a == b)

        return 1;

    a = clone_filter_formats(a_arg);

    b = clone_filter_formats(b_arg);

    if (is_sample_rate) {

        ret = ff_merge_samplerates(a, b);

    } else {

        ret = ff_merge_formats(a, b, type);

    }

    if (ret) {

        av_freep(&ret->formats);

        av_freep(&ret);

        return 1;

    } else {

        av_freep(&a->formats);

        av_freep(&b->formats);

        av_freep(&a);

        av_freep(&b);

        return 0;

    }

}


static int mxf_write_partition(AVFormatContext *s, int bodysid,

                                int indexsid,

                                const uint8_t *key, int write_metadata)

{

    MXFContext *mxf = s->priv_data;

    AVIOContext *pb = s->pb;

    int64_t header_byte_count_offset;

    unsigned index_byte_count = 0;

    uint64_t partition_offset = avio_tell(pb);

    int err;

    if (!mxf->edit_unit_byte_count && mxf->edit_units_count)

        index_byte_count = 85 + 12+(s->nb_streams+1)*6 +

            12+mxf->edit_units_count*(11+mxf->slice_count*4);

    else if (mxf->edit_unit_byte_count && indexsid)

        index_byte_count = 80;

    if (index_byte_count) {

        // add encoded ber length

        index_byte_count += 16 + klv_ber_length(index_byte_count);

        index_byte_count += klv_fill_size(index_byte_count);

    }

    if (!memcmp(key, body_partition_key, 16)) {

        if ((err = av_reallocp_array(&mxf->body_partition_offset, mxf->body_partitions_count + 1,

                                     sizeof(*mxf->body_partition_offset))) < 0) {

            mxf->body_partitions_count = 0;

            return err;

        }

        mxf->body_partition_offset[mxf->body_partitions_count++] = partition_offset;

    }

    // write klv

    avio_write(pb, key, 16);

    klv_encode_ber_length(pb, 88 + 16 * mxf->essence_container_count);

    // write partition value

    avio_wb16(pb, 1); // majorVersion

    avio_wb16(pb, 2); // minorVersion

    avio_wb32(pb, KAG_SIZE); // KAGSize

    avio_wb64(pb, partition_offset); // ThisPartition

    if (!memcmp(key, body_partition_key, 16) && mxf->body_partitions_count > 1)

        avio_wb64(pb, mxf->body_partition_offset[mxf->body_partitions_count-2]); // PreviousPartition

    else if (!memcmp(key, footer_partition_key, 16) && mxf->body_partitions_count)

        avio_wb64(pb, mxf->body_partition_offset[mxf->body_partitions_count-1]); // PreviousPartition

    else

        avio_wb64(pb, 0);

    avio_wb64(pb, mxf->footer_partition_offset); // footerPartition

    // set offset

    header_byte_count_offset = avio_tell(pb);

    avio_wb64(pb, 0); // headerByteCount, update later

    // indexTable

    avio_wb64(pb, index_byte_count); // indexByteCount

    avio_wb32(pb, index_byte_count ? indexsid : 0); // indexSID

    // BodyOffset

    if (bodysid && mxf->edit_units_count && mxf->body_partitions_count) {

        avio_wb64(pb, mxf->body_offset);

    } else

        avio_wb64(pb, 0);

    avio_wb32(pb, bodysid); // bodySID

    // operational pattern

    avio_write(pb, op1a_ul, 16);

    // essence container

    mxf_write_essence_container_refs(s);

    if (write_metadata) {

        // mark the start of the headermetadata and calculate metadata size

        int64_t pos, start;

        unsigned header_byte_count;

        mxf_write_klv_fill(s);

        start = avio_tell(s->pb);

        mxf_write_primer_pack(s);

        mxf_write_header_metadata_sets(s);

        pos = avio_tell(s->pb);

        header_byte_count = pos - start + klv_fill_size(pos);

        // update header_byte_count

        avio_seek(pb, header_byte_count_offset, SEEK_SET);

        avio_wb64(pb, header_byte_count);

        avio_seek(pb, pos, SEEK_SET);

    }

    avio_flush(pb);

    return 0;

}


void virtio_config_writew(VirtIODevice *vdev, uint32_t addr, uint32_t data)

{

    VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev);

    uint16_t val = data;

    if (addr > (vdev->config_len - sizeof(val)))

        return;

    stw_p(vdev->config + addr, val);

    if (k->set_config) {

        k->set_config(vdev, vdev->config);

    }

}


static uint8_t get_sot(J2kDecoderContext *s)

{

    if (s->buf_end - s->buf < 4)

        return AVERROR(EINVAL);

    s->curtileno = bytestream_get_be16(&s->buf); ///< Isot

    if((unsigned)s->curtileno >= s->numXtiles * s->numYtiles){

        s->curtileno=0;

        return AVERROR(EINVAL);

    }

    s->buf += 4; ///< Psot (ignored)

    if (!bytestream_get_byte(&s->buf)){ ///< TPsot

        J2kTile *tile = s->tile + s->curtileno;

        /* copy defaults */

        memcpy(tile->codsty, s->codsty, s->ncomponents * sizeof(J2kCodingStyle));

        memcpy(tile->qntsty, s->qntsty, s->ncomponents * sizeof(J2kQuantStyle));

    }

    bytestream_get_byte(&s->buf); ///< TNsot

    return 0;

}


static void i6300esb_pc_init(PCIBus *pci_bus)

{

    I6300State *d;

    uint8_t *pci_conf;

    if (!pci_bus) {

        fprintf(stderr, "wdt_i6300esb: no PCI bus in this machine\n");

        return;

    }

    d = (I6300State *)

        pci_register_device (pci_bus, "i6300esb_wdt", sizeof (I6300State),

                             -1,

                             i6300esb_config_read, i6300esb_config_write);

    d->reboot_enabled = 1;

    d->clock_scale = CLOCK_SCALE_1KHZ;

    d->int_type = INT_TYPE_IRQ;

    d->free_run = 0;

    d->locked = 0;

    d->enabled = 0;

    d->timer = qemu_new_timer(vm_clock, i6300esb_timer_expired, d);

    d->timer1_preload = 0xfffff;

    d->timer2_preload = 0xfffff;

    d->stage = 1;

    d->unlock_state = 0;

    d->previous_reboot_flag = 0;

    pci_conf = d->dev.config;

    pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_INTEL);

    pci_config_set_device_id(pci_conf, PCI_DEVICE_ID_INTEL_ESB_9);

    pci_config_set_class(pci_conf, PCI_CLASS_SYSTEM_OTHER);

    pci_conf[0x0e] = 0x00;

    pci_register_bar(&d->dev, 0, 0x10,

                            PCI_ADDRESS_SPACE_MEM, i6300esb_map);

    register_savevm("i6300esb_wdt", -1, sizeof(I6300State),

                     i6300esb_save, i6300esb_load, d);

}


static inline void cpu_loop_exec_tb(CPUState *cpu, TranslationBlock *tb,

                                    TranslationBlock **last_tb, int *tb_exit,

                                    SyncClocks *sc)

{

    uintptr_t ret;

    if (unlikely(atomic_read(&cpu->exit_request))) {

        return;

    }

    trace_exec_tb(tb, tb->pc);

    ret = cpu_tb_exec(cpu, tb);

    *last_tb = (TranslationBlock *)(ret & ~TB_EXIT_MASK);

    *tb_exit = ret & TB_EXIT_MASK;

    switch (*tb_exit) {

    case TB_EXIT_REQUESTED:

        /* Something asked us to stop executing

         * chained TBs; just continue round the main

         * loop. Whatever requested the exit will also

         * have set something else (eg exit_request or

         * interrupt_request) which we will handle

         * next time around the loop.  But we need to

         * ensure the tcg_exit_req read in generated code

         * comes before the next read of cpu->exit_request

         * or cpu->interrupt_request.

         */

        smp_rmb();

        *last_tb = NULL;

        break;

    case TB_EXIT_ICOUNT_EXPIRED:

    {

        /* Instruction counter expired.  */

#ifdef CONFIG_USER_ONLY

        abort();

#else

        int insns_left = cpu->icount_decr.u32;

        if (cpu->icount_extra && insns_left >= 0) {

            /* Refill decrementer and continue execution.  */

            cpu->icount_extra += insns_left;

            insns_left = MIN(0xffff, cpu->icount_extra);

            cpu->icount_extra -= insns_left;

            cpu->icount_decr.u16.low = insns_left;

        } else {

            if (insns_left > 0) {

                /* Execute remaining instructions.  */

                cpu_exec_nocache(cpu, insns_left, *last_tb, false);

                align_clocks(sc, cpu);

            }

            cpu->exception_index = EXCP_INTERRUPT;

            *last_tb = NULL;

            cpu_loop_exit(cpu);

        }

        break;

#endif

    }

    default:

        break;

    }

}


static void vnc_dpy_update(DisplayState *ds, int x, int y, int w, int h)

{

    VncState *vs = ds->opaque;

    int i;

    h += y;

    /* round x down to ensure the loop only spans one 16-pixel block per,

       iteration.  otherwise, if (x % 16) != 0, the last iteration may span

       two 16-pixel blocks but we only mark the first as dirty

    */

    w += (x % 16);

    x -= (x % 16);

    x = MIN(x, vs->width);

    y = MIN(y, vs->height);

    w = MIN(x + w, vs->width) - x;

    h = MIN(h, vs->height);

    for (; y < h; y++)

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

	    vnc_set_bit(vs->dirty_row[y], (x + i) / 16);

}


static void musb_async_cancel_device(MUSBState *s, USBDevice *dev)

{

    int ep, dir;

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

        for (dir = 0; dir < 2; dir++) {

            if (s->ep[ep].packey[dir].p.owner == NULL ||

                s->ep[ep].packey[dir].p.owner->dev != dev) {

                continue;

            }

            usb_cancel_packet(&s->ep[ep].packey[dir].p);

            /* status updates needed here? */

        }

    }

}


int qemu_reset_requested_get(void)

{

    return reset_requested;

}


static void select_input_picture(MpegEncContext *s){

    int i;

    for(i=1; i<MAX_PICTURE_COUNT; i++)

        s->reordered_input_picture[i-1]= s->reordered_input_picture[i];

    s->reordered_input_picture[MAX_PICTURE_COUNT-1]= NULL;

    /* set next picture type & ordering */

    if(s->reordered_input_picture[0]==NULL && s->input_picture[0]){

        if(/*s->picture_in_gop_number >= s->gop_size ||*/ s->next_picture_ptr==NULL || s->intra_only){

            s->reordered_input_picture[0]= s->input_picture[0];

            s->reordered_input_picture[0]->pict_type= I_TYPE;

            s->reordered_input_picture[0]->coded_picture_number= s->coded_picture_number++;

        }else{

            int b_frames;

            if(s->avctx->frame_skip_threshold || s->avctx->frame_skip_factor){

                if(s->picture_in_gop_number < s->gop_size && skip_check(s, s->input_picture[0], s->next_picture_ptr)){

                //FIXME check that te gop check above is +-1 correct

//av_log(NULL, AV_LOG_DEBUG, "skip %p %Ld\n", s->input_picture[0]->data[0], s->input_picture[0]->pts);

                    if(s->input_picture[0]->type == FF_BUFFER_TYPE_SHARED){

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

                            s->input_picture[0]->data[i]= NULL;

                        s->input_picture[0]->type= 0;

                    }else{

                        assert(   s->input_picture[0]->type==FF_BUFFER_TYPE_USER

                               || s->input_picture[0]->type==FF_BUFFER_TYPE_INTERNAL);

                        s->avctx->release_buffer(s->avctx, (AVFrame*)s->input_picture[0]);

                    }

                    emms_c();

                    ff_vbv_update(s, 0);

                    goto no_output_pic;

                }

            }

            if(s->flags&CODEC_FLAG_PASS2){

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

                    int pict_num= s->input_picture[0]->display_picture_number + i;

                    if(pict_num >= s->rc_context.num_entries)

                        break;

                    if(!s->input_picture[i]){

                        s->rc_context.entry[pict_num-1].new_pict_type = P_TYPE;

                        break;

                    }

                    s->input_picture[i]->pict_type=

                        s->rc_context.entry[pict_num].new_pict_type;

                }

            }

            if(s->avctx->b_frame_strategy==0){

                b_frames= s->max_b_frames;

                while(b_frames && !s->input_picture[b_frames]) b_frames--;

            }else if(s->avctx->b_frame_strategy==1){

                for(i=1; i<s->max_b_frames+1; i++){

                    if(s->input_picture[i] && s->input_picture[i]->b_frame_score==0){

                        s->input_picture[i]->b_frame_score=

                            get_intra_count(s, s->input_picture[i  ]->data[0],

                                               s->input_picture[i-1]->data[0], s->linesize) + 1;

                    }

                }

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

                    if(s->input_picture[i]==NULL || s->input_picture[i]->b_frame_score - 1 > s->mb_num/s->avctx->b_sensitivity) break;

                }

                b_frames= FFMAX(0, i-1);

                /* reset scores */

                for(i=0; i<b_frames+1; i++){

                    s->input_picture[i]->b_frame_score=0;

                }

            }else if(s->avctx->b_frame_strategy==2){

                b_frames= estimate_best_b_count(s);

            }else{

                av_log(s->avctx, AV_LOG_ERROR, "illegal b frame strategy\n");

                b_frames=0;

            }

            emms_c();

//static int b_count=0;

//b_count+= b_frames;

//av_log(s->avctx, AV_LOG_DEBUG, "b_frames: %d\n", b_count);

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

                int type= s->input_picture[i]->pict_type;

                if(type && type != B_TYPE)

                    b_frames= i;

            }

            if(s->input_picture[b_frames]->pict_type == B_TYPE && b_frames == s->max_b_frames){

                av_log(s->avctx, AV_LOG_ERROR, "warning, too many b frames in a row\n");

            }

            if(s->picture_in_gop_number + b_frames >= s->gop_size){

              if((s->flags2 & CODEC_FLAG2_STRICT_GOP) && s->gop_size > s->picture_in_gop_number){

                    b_frames= s->gop_size - s->picture_in_gop_number - 1;

              }else{

                if(s->flags & CODEC_FLAG_CLOSED_GOP)

                    b_frames=0;

                s->input_picture[b_frames]->pict_type= I_TYPE;

              }

            }

            if(   (s->flags & CODEC_FLAG_CLOSED_GOP)

               && b_frames

               && s->input_picture[b_frames]->pict_type== I_TYPE)

                b_frames--;

            s->reordered_input_picture[0]= s->input_picture[b_frames];

            if(s->reordered_input_picture[0]->pict_type != I_TYPE)

                s->reordered_input_picture[0]->pict_type= P_TYPE;

            s->reordered_input_picture[0]->coded_picture_number= s->coded_picture_number++;

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

                s->reordered_input_picture[i+1]= s->input_picture[i];

                s->reordered_input_picture[i+1]->pict_type= B_TYPE;

                s->reordered_input_picture[i+1]->coded_picture_number= s->coded_picture_number++;

            }

        }

    }

no_output_pic:

    if(s->reordered_input_picture[0]){

        s->reordered_input_picture[0]->reference= s->reordered_input_picture[0]->pict_type!=B_TYPE ? 3 : 0;

        copy_picture(&s->new_picture, s->reordered_input_picture[0]);

        if(s->reordered_input_picture[0]->type == FF_BUFFER_TYPE_SHARED){

            // input is a shared pix, so we can't modifiy it -> alloc a new one & ensure that the shared one is reuseable

            int i= ff_find_unused_picture(s, 0);

            Picture *pic= &s->picture[i];

            /* mark us unused / free shared pic */

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

                s->reordered_input_picture[0]->data[i]= NULL;

            s->reordered_input_picture[0]->type= 0;

            pic->reference              = s->reordered_input_picture[0]->reference;

            alloc_picture(s, pic, 0);

            copy_picture_attributes(s, (AVFrame*)pic, (AVFrame*)s->reordered_input_picture[0]);

            s->current_picture_ptr= pic;

        }else{

            // input is not a shared pix -> reuse buffer for current_pix

            assert(   s->reordered_input_picture[0]->type==FF_BUFFER_TYPE_USER

                   || s->reordered_input_picture[0]->type==FF_BUFFER_TYPE_INTERNAL);

            s->current_picture_ptr= s->reordered_input_picture[0];

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

                s->new_picture.data[i]+= INPLACE_OFFSET;

            }

        }

        copy_picture(&s->current_picture, s->current_picture_ptr);

        s->picture_number= s->new_picture.display_picture_number;

//printf("dpn:%d\n", s->picture_number);

    }else{

       memset(&s->new_picture, 0, sizeof(Picture));

    }

}


static int local_chown(FsContext *fs_ctx, const char *path, FsCred *credp)

{

    if ((credp->fc_uid == -1 && credp->fc_gid == -1) ||

            (fs_ctx->fs_sm == SM_PASSTHROUGH)) {

        return lchown(rpath(fs_ctx, path), credp->fc_uid, credp->fc_gid);

    } else if (fs_ctx->fs_sm == SM_MAPPED) {

        return local_set_xattr(rpath(fs_ctx, path), credp);

    } else if (fs_ctx->fs_sm == SM_PASSTHROUGH) {

        return lchown(rpath(fs_ctx, path), credp->fc_uid, credp->fc_gid);

    }

    return -1;

}