static const char *ass_split_section(ASSSplitContext *ctx, const char *buf)

{

    const ASSSection *section = &ass_sections[ctx->current_section];

    int *number = &ctx->field_number[ctx->current_section];

    int *order = ctx->field_order[ctx->current_section];

    int *tmp, i, len;

    while (buf && *buf) {

        if (buf[0] == '[') {

            ctx->current_section = -1;

            break;

        }

        if (buf[0] == ';' || (buf[0] == '!' && buf[1] == ':')) {

            /* skip comments */

        } else if (section->format_header && !order) {

            len = strlen(section->format_header);

            if (strncmp(buf, section->format_header, len) || buf[len] != ':')

                return NULL;

            buf += len + 1;

            while (!is_eol(*buf)) {

                buf = skip_space(buf);

                len = strcspn(buf, ", \r\n");

                if (!(tmp = av_realloc(order, (*number + 1) * sizeof(*order))))

                    return NULL;

                order = tmp;

                order[*number] = -1;

                for (i=0; section->fields[i].name; i++)

                    if (!strncmp(buf, section->fields[i].name, len)) {

                        order[*number] = i;

                        break;

                    }

                (*number)++;

                buf = skip_space(buf + len + (buf[len] == ','));

            }

            ctx->field_order[ctx->current_section] = order;

        } else if (section->fields_header) {

            len = strlen(section->fields_header);

            if (!strncmp(buf, section->fields_header, len) && buf[len] == ':') {

                uint8_t *ptr, *struct_ptr = realloc_section_array(ctx);

                if (!struct_ptr)  return NULL;

                buf += len + 1;

                for (i=0; !is_eol(*buf) && i < *number; i++) {

                    int last = i == *number - 1;

                    buf = skip_space(buf);

                    len = strcspn(buf, last ? "\r\n" : ",\r\n");

                    if (order[i] >= 0) {

                        ASSFieldType type = section->fields[order[i]].type;

                        ptr = struct_ptr + section->fields[order[i]].offset;

                        convert_func[type](ptr, buf, len);

                    }

                    buf = skip_space(buf + len + !last);

                }

            }

        } else {

            len = strcspn(buf, ":\r\n");

            if (buf[len] == ':') {

                for (i=0; section->fields[i].name; i++)

                    if (!strncmp(buf, section->fields[i].name, len)) {

                        ASSFieldType type = section->fields[i].type;

                        uint8_t *ptr = (uint8_t *)&ctx->ass + section->offset;

                        ptr += section->fields[i].offset;

                        buf = skip_space(buf + len + 1);

                        convert_func[type](ptr, buf, strcspn(buf, "\r\n"));

                        break;

                    }

            }

        }

        buf += strcspn(buf, "\n") + 1;

    }

    return buf;

}


static inline void yuv2rgbXinC(int16_t *lumFilter, int16_t **lumSrc, int lumFilterSize,

				    int16_t *chrFilter, int16_t **chrSrc, int chrFilterSize,

				    uint8_t *dest, int dstW, int dstbpp)

{

	if(dstbpp==32)

	{

		int i;

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

			int j;

			int Y1=0;

			int Y2=0;

			int U=0;

			int V=0;

			int Cb, Cr, Cg;

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

			{

				Y1 += lumSrc[j][2*i] * lumFilter[j];

				Y2 += lumSrc[j][2*i+1] * lumFilter[j];

			}

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

			{

				U += chrSrc[j][i] * chrFilter[j];

				V += chrSrc[j][i+2048] * chrFilter[j];

			}

			Y1= clip_yuvtab_2568[ (Y1>>19) + 256 ];

			Y2= clip_yuvtab_2568[ (Y2>>19) + 256 ];

			U >>= 19;

			V >>= 19;

			Cb= clip_yuvtab_40cf[U+ 256];

			Cg= clip_yuvtab_1a1e[V+ 256] + yuvtab_0c92[U+ 256];

			Cr= clip_yuvtab_3343[V+ 256];

			dest[8*i+0]=clip_table[((Y1 + Cb) >>13)];

			dest[8*i+1]=clip_table[((Y1 + Cg) >>13)];

			dest[8*i+2]=clip_table[((Y1 + Cr) >>13)];

			dest[8*i+4]=clip_table[((Y2 + Cb) >>13)];

			dest[8*i+5]=clip_table[((Y2 + Cg) >>13)];

			dest[8*i+6]=clip_table[((Y2 + Cr) >>13)];

		}

	}

	else if(dstbpp==24)

	{

		int i;

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

			int j;

			int Y1=0;

			int Y2=0;

			int U=0;

			int V=0;

			int Cb, Cr, Cg;

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

			{

				Y1 += lumSrc[j][2*i] * lumFilter[j];

				Y2 += lumSrc[j][2*i+1] * lumFilter[j];

			}

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

			{

				U += chrSrc[j][i] * chrFilter[j];

				V += chrSrc[j][i+2048] * chrFilter[j];

			}

			Y1= clip_yuvtab_2568[ (Y1>>19) + 256 ];

			Y2= clip_yuvtab_2568[ (Y2>>19) + 256 ];

			U >>= 19;

			V >>= 19;

			Cb= clip_yuvtab_40cf[U+ 256];

			Cg= clip_yuvtab_1a1e[V+ 256] + yuvtab_0c92[U+ 256];

			Cr= clip_yuvtab_3343[V+ 256];

			dest[0]=clip_table[((Y1 + Cb) >>13)];

			dest[1]=clip_table[((Y1 + Cg) >>13)];

			dest[2]=clip_table[((Y1 + Cr) >>13)];

			dest[3]=clip_table[((Y2 + Cb) >>13)];

			dest[4]=clip_table[((Y2 + Cg) >>13)];

			dest[5]=clip_table[((Y2 + Cr) >>13)];

			dest+=6;

		}

	}

	else if(dstbpp==16)

	{

		int i;

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

			int j;

			int Y1=0;

			int Y2=0;

			int U=0;

			int V=0;

			int Cb, Cr, Cg;

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

			{

				Y1 += lumSrc[j][2*i] * lumFilter[j];

				Y2 += lumSrc[j][2*i+1] * lumFilter[j];

			}

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

			{

				U += chrSrc[j][i] * chrFilter[j];

				V += chrSrc[j][i+2048] * chrFilter[j];

			}

			Y1= clip_yuvtab_2568[ (Y1>>19) + 256 ];

			Y2= clip_yuvtab_2568[ (Y2>>19) + 256 ];

			U >>= 19;

			V >>= 19;

			Cb= clip_yuvtab_40cf[U+ 256];

			Cg= clip_yuvtab_1a1e[V+ 256] + yuvtab_0c92[U+ 256];

			Cr= clip_yuvtab_3343[V+ 256];

			((uint16_t*)dest)[2*i] =

				clip_table16b[(Y1 + Cb) >>13] |

				clip_table16g[(Y1 + Cg) >>13] |

				clip_table16r[(Y1 + Cr) >>13];

			((uint16_t*)dest)[2*i+1] =

				clip_table16b[(Y2 + Cb) >>13] |

				clip_table16g[(Y2 + Cg) >>13] |

				clip_table16r[(Y2 + Cr) >>13];

		}

	}

	else if(dstbpp==15)

	{

		int i;

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

			int j;

			int Y1=0;

			int Y2=0;

			int U=0;

			int V=0;

			int Cb, Cr, Cg;

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

			{

				Y1 += lumSrc[j][2*i] * lumFilter[j];

				Y2 += lumSrc[j][2*i+1] * lumFilter[j];

			}

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

			{

				U += chrSrc[j][i] * chrFilter[j];

				V += chrSrc[j][i+2048] * chrFilter[j];

			}

			Y1= clip_yuvtab_2568[ (Y1>>19) + 256 ];

			Y2= clip_yuvtab_2568[ (Y2>>19) + 256 ];

			U >>= 19;

			V >>= 19;

			Cb= clip_yuvtab_40cf[U+ 256];

			Cg= clip_yuvtab_1a1e[V+ 256] + yuvtab_0c92[U+ 256];

			Cr= clip_yuvtab_3343[V+ 256];

			((uint16_t*)dest)[2*i] =

				clip_table15b[(Y1 + Cb) >>13] |

				clip_table15g[(Y1 + Cg) >>13] |

				clip_table15r[(Y1 + Cr) >>13];

			((uint16_t*)dest)[2*i+1] =

				clip_table15b[(Y2 + Cb) >>13] |

				clip_table15g[(Y2 + Cg) >>13] |

				clip_table15r[(Y2 + Cr) >>13];

		}

	}

}


static int halfpel_interpol(SnowContext *s, uint8_t *halfpel[4][4], AVFrame *frame){

    int p,x,y;

    for(p=0; p < s->nb_planes; p++){

        int is_chroma= !!p;

        int w= is_chroma ? s->avctx->width >>s->chroma_h_shift : s->avctx->width;

        int h= is_chroma ? s->avctx->height>>s->chroma_v_shift : s->avctx->height;

        int ls= frame->linesize[p];

        uint8_t *src= frame->data[p];

        halfpel[1][p] = (uint8_t*) av_malloc_array(ls, (h + 2 * EDGE_WIDTH)) + EDGE_WIDTH * (1 + ls);

        halfpel[2][p] = (uint8_t*) av_malloc_array(ls, (h + 2 * EDGE_WIDTH)) + EDGE_WIDTH * (1 + ls);

        halfpel[3][p] = (uint8_t*) av_malloc_array(ls, (h + 2 * EDGE_WIDTH)) + EDGE_WIDTH * (1 + ls);

        if (!halfpel[1][p] || !halfpel[2][p] || !halfpel[3][p])

            return AVERROR(ENOMEM);

        halfpel[0][p]= src;

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

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

                int i= y*ls + x;

                halfpel[1][p][i]= (20*(src[i] + src[i+1]) - 5*(src[i-1] + src[i+2]) + (src[i-2] + src[i+3]) + 16 )>>5;

            }

        }

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

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

                int i= y*ls + x;

                halfpel[2][p][i]= (20*(src[i] + src[i+ls]) - 5*(src[i-ls] + src[i+2*ls]) + (src[i-2*ls] + src[i+3*ls]) + 16 )>>5;

            }

        }

        src= halfpel[1][p];

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

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

                int i= y*ls + x;

                halfpel[3][p][i]= (20*(src[i] + src[i+ls]) - 5*(src[i-ls] + src[i+2*ls]) + (src[i-2*ls] + src[i+3*ls]) + 16 )>>5;

            }

        }

//FIXME border!

    }

    return 0;

}


static void *qpa_thread_in (void *arg)

{

    PAVoiceIn *pa = arg;

    HWVoiceIn *hw = &pa->hw;

    if (audio_pt_lock (&pa->pt, AUDIO_FUNC)) {

        return NULL;

    }

    for (;;) {

        int incr, to_grab, wpos;

        for (;;) {

            if (pa->done) {

                goto exit;

            }

            if (pa->dead > 0) {

                break;

            }

            if (audio_pt_wait (&pa->pt, AUDIO_FUNC)) {

                goto exit;

            }

        }

        incr = to_grab = audio_MIN (pa->dead, conf.samples >> 2);

        wpos = pa->wpos;

        if (audio_pt_unlock (&pa->pt, AUDIO_FUNC)) {

            return NULL;

        }

        while (to_grab) {

            int error;

            int chunk = audio_MIN (to_grab, hw->samples - wpos);

            void *buf = advance (pa->pcm_buf, wpos);

            if (pa_simple_read (pa->s, buf,

                                chunk << hw->info.shift, &error) < 0) {

                qpa_logerr (error, "pa_simple_read failed\n");

                return NULL;

            }

            hw->conv (hw->conv_buf + wpos, buf, chunk);

            wpos = (wpos + chunk) % hw->samples;

            to_grab -= chunk;

        }

        if (audio_pt_lock (&pa->pt, AUDIO_FUNC)) {

            return NULL;

        }

        pa->wpos = wpos;

        pa->dead -= incr;

        pa->incr += incr;

    }

 exit:

    audio_pt_unlock (&pa->pt, AUDIO_FUNC);

    return NULL;

}


void ff_h261_encode_init(MpegEncContext *s){

    static int done = 0;

    if (!done) {

        done = 1;

        init_rl(&h261_rl_tcoeff);

    }

    s->min_qcoeff= -127;

    s->max_qcoeff=  127;

    s->y_dc_scale_table=

    s->c_dc_scale_table= ff_mpeg1_dc_scale_table;

}


static int mmu_translate_region(CPUS390XState *env, target_ulong vaddr,

                                uint64_t asc, uint64_t entry, int level,

                                target_ulong *raddr, int *flags, int rw,

                                bool exc)

{

    CPUState *cs = CPU(s390_env_get_cpu(env));

    uint64_t origin, offs, new_entry;

    const int pchks[4] = {

        PGM_SEGMENT_TRANS, PGM_REG_THIRD_TRANS,

        PGM_REG_SEC_TRANS, PGM_REG_FIRST_TRANS

    };

    PTE_DPRINTF("%s: 0x%" PRIx64 "\n", __func__, entry);

    origin = entry & _REGION_ENTRY_ORIGIN;

    offs = (vaddr >> (17 + 11 * level / 4)) & 0x3ff8;

    new_entry = ldq_phys(cs->as, origin + offs);

    PTE_DPRINTF("%s: 0x%" PRIx64 " + 0x%" PRIx64 " => 0x%016" PRIx64 "\n",

                __func__, origin, offs, new_entry);

    if ((new_entry & _REGION_ENTRY_INV) != 0) {

        /* XXX different regions have different faults */

        DPRINTF("%s: invalid region\n", __func__);

        trigger_page_fault(env, vaddr, PGM_SEGMENT_TRANS, asc, rw, exc);

        return -1;

    }

    if ((new_entry & _REGION_ENTRY_TYPE_MASK) != level) {

        trigger_page_fault(env, vaddr, PGM_TRANS_SPEC, asc, rw, exc);

        return -1;

    }

    /* XXX region protection flags */

    /* *flags &= ~PAGE_WRITE */

    if (level == _ASCE_TYPE_SEGMENT) {

        return mmu_translate_segment(env, vaddr, asc, new_entry, raddr, flags,

                                     rw, exc);

    }

    /* Check region table offset and length */

    offs = (vaddr >> (28 + 11 * (level - 4) / 4)) & 3;

    if (offs < ((new_entry & _REGION_ENTRY_TF) >> 6)

        || offs > (new_entry & _REGION_ENTRY_LENGTH)) {

        DPRINTF("%s: invalid offset or len (%lx)\n", __func__, new_entry);

        trigger_page_fault(env, vaddr, pchks[level / 4 - 1], asc, rw, exc);

        return -1;

    }

    /* yet another region */

    return mmu_translate_region(env, vaddr, asc, new_entry, level - 4,

                                raddr, flags, rw, exc);

}


static int pcx_encode_frame(AVCodecContext *avctx,

                            unsigned char *buf, int buf_size, void *data)

{

    PCXContext *s = avctx->priv_data;

    AVFrame *const pict = &s->picture;

    const uint8_t *buf_start = buf;

    const uint8_t *buf_end   = buf + buf_size;

    int bpp, nplanes, i, y, line_bytes, written;

    const uint32_t *pal = NULL;

    const uint8_t *src;

    *pict = *(AVFrame *)data;

    pict->pict_type = AV_PICTURE_TYPE_I;

    pict->key_frame = 1;

    if (avctx->width > 65535 || avctx->height > 65535) {

        av_log(avctx, AV_LOG_ERROR, "image dimensions do not fit in 16 bits\n");

        return -1;

    }

    switch (avctx->pix_fmt) {

    case PIX_FMT_RGB24:

        bpp = 8;

        nplanes = 3;

        break;

    case PIX_FMT_RGB8:

    case PIX_FMT_BGR8:

    case PIX_FMT_RGB4_BYTE:

    case PIX_FMT_BGR4_BYTE:

    case PIX_FMT_GRAY8:

        bpp = 8;

        nplanes = 1;

        ff_set_systematic_pal2(palette256, avctx->pix_fmt);

        pal = palette256;

        break;

    case PIX_FMT_PAL8:

        bpp = 8;

        nplanes = 1;

        pal = (uint32_t *)pict->data[1];

        break;

    case PIX_FMT_MONOBLACK:

        bpp = 1;

        nplanes = 1;

        pal = monoblack_pal;

        break;

    default:

        av_log(avctx, AV_LOG_ERROR, "unsupported pixfmt\n");

        return -1;

    }

    line_bytes = (avctx->width * bpp + 7) >> 3;

    line_bytes = (line_bytes + 1) & ~1;

    bytestream_put_byte(&buf, 10);                  // manufacturer

    bytestream_put_byte(&buf, 5);                   // version

    bytestream_put_byte(&buf, 1);                   // encoding

    bytestream_put_byte(&buf, bpp);                 // bits per pixel per plane

    bytestream_put_le16(&buf, 0);                   // x min

    bytestream_put_le16(&buf, 0);                   // y min

    bytestream_put_le16(&buf, avctx->width - 1);    // x max

    bytestream_put_le16(&buf, avctx->height - 1);   // y max

    bytestream_put_le16(&buf, 0);                   // horizontal DPI

    bytestream_put_le16(&buf, 0);                   // vertical DPI

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

        bytestream_put_be24(&buf, pal ? pal[i] : 0);// palette (<= 16 color only)

    bytestream_put_byte(&buf, 0);                   // reserved

    bytestream_put_byte(&buf, nplanes);             // number of planes

    bytestream_put_le16(&buf, line_bytes);          // scanline plane size in bytes

    while (buf - buf_start < 128)

        *buf++= 0;

    src = pict->data[0];

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

        if ((written = pcx_rle_encode(buf, buf_end - buf,

                                      src, line_bytes, nplanes)) < 0) {

            av_log(avctx, AV_LOG_ERROR, "buffer too small\n");

            return -1;

        }

        buf += written;

        src += pict->linesize[0];

    }

    if (nplanes == 1 && bpp == 8) {

        if (buf_end - buf < 257) {

            av_log(avctx, AV_LOG_ERROR, "buffer too small\n");

            return -1;

        }

        bytestream_put_byte(&buf, 12);

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

            bytestream_put_be24(&buf, pal[i]);

        }

    }

    return buf - buf_start;

}


static void GCC_FMT_ATTR(2, 3) qtest_send(CharDriverState *chr,

                                          const char *fmt, ...)

{

    va_list ap;

    char buffer[1024];

    size_t len;

    va_start(ap, fmt);

    len = vsnprintf(buffer, sizeof(buffer), fmt, ap);

    va_end(ap);

    qemu_chr_fe_write_all(chr, (uint8_t *)buffer, len);

    if (qtest_log_fp && qtest_opened) {

        fprintf(qtest_log_fp, "%s", buffer);

    }

}


static int dxtory_decode_v1_rgb(AVCodecContext *avctx, AVFrame *pic,

                                const uint8_t *src, int src_size,

                                int id, int bpp)

{

    int h;

    uint8_t *dst;

    int ret;

    if (src_size < avctx->width * avctx->height * bpp) {

        av_log(avctx, AV_LOG_ERROR, "packet too small\n");

        return AVERROR_INVALIDDATA;

    }

    avctx->pix_fmt = id;

    if ((ret = ff_get_buffer(avctx, pic, 0)) < 0)

        return ret;

    dst = pic->data[0];

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

        memcpy(dst, src, avctx->width * bpp);

        src += avctx->width * bpp;

        dst += pic->linesize[0];

    }

    return 0;

}


void vbe_ioport_write_data(void *opaque, uint32_t addr, uint32_t val)

{

    VGACommonState *s = opaque;

    if (s->vbe_index <= VBE_DISPI_INDEX_NB) {

#ifdef DEBUG_BOCHS_VBE

        printf("VBE: write index=0x%x val=0x%x\n", s->vbe_index, val);

#endif

        switch(s->vbe_index) {

        case VBE_DISPI_INDEX_ID:

            if (val == VBE_DISPI_ID0 ||

                val == VBE_DISPI_ID1 ||

                val == VBE_DISPI_ID2 ||

                val == VBE_DISPI_ID3 ||

                val == VBE_DISPI_ID4) {

                s->vbe_regs[s->vbe_index] = val;

            }

            break;

        case VBE_DISPI_INDEX_XRES:

        case VBE_DISPI_INDEX_YRES:

        case VBE_DISPI_INDEX_BPP:

        case VBE_DISPI_INDEX_VIRT_WIDTH:

        case VBE_DISPI_INDEX_X_OFFSET:

        case VBE_DISPI_INDEX_Y_OFFSET:

            s->vbe_regs[s->vbe_index] = val;

            vbe_fixup_regs(s);

            break;

        case VBE_DISPI_INDEX_BANK:

            if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4) {

              val &= (s->vbe_bank_mask >> 2);

            } else {

              val &= s->vbe_bank_mask;

            }

            s->vbe_regs[s->vbe_index] = val;

            s->bank_offset = (val << 16);

            vga_update_memory_access(s);

            break;

        case VBE_DISPI_INDEX_ENABLE:

            if ((val & VBE_DISPI_ENABLED) &&

                !(s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED)) {

                int h, shift_control;

                s->vbe_regs[VBE_DISPI_INDEX_VIRT_WIDTH] = 0;

                s->vbe_regs[VBE_DISPI_INDEX_X_OFFSET] = 0;

                s->vbe_regs[VBE_DISPI_INDEX_Y_OFFSET] = 0;

                s->vbe_regs[VBE_DISPI_INDEX_ENABLE] |= VBE_DISPI_ENABLED;

                vbe_fixup_regs(s);

                /* clear the screen */

                if (!(val & VBE_DISPI_NOCLEARMEM)) {

                    memset(s->vram_ptr, 0,

                           s->vbe_regs[VBE_DISPI_INDEX_YRES] * s->vbe_line_offset);

                }

                /* we initialize the VGA graphic mode */

                /* graphic mode + memory map 1 */

                s->gr[VGA_GFX_MISC] = (s->gr[VGA_GFX_MISC] & ~0x0c) | 0x04 |

                    VGA_GR06_GRAPHICS_MODE;

                s->cr[VGA_CRTC_MODE] |= 3; /* no CGA modes */

                s->cr[VGA_CRTC_OFFSET] = s->vbe_line_offset >> 3;

                /* width */

                s->cr[VGA_CRTC_H_DISP] =

                    (s->vbe_regs[VBE_DISPI_INDEX_XRES] >> 3) - 1;

                /* height (only meaningful if < 1024) */

                h = s->vbe_regs[VBE_DISPI_INDEX_YRES] - 1;

                s->cr[VGA_CRTC_V_DISP_END] = h;

                s->cr[VGA_CRTC_OVERFLOW] = (s->cr[VGA_CRTC_OVERFLOW] & ~0x42) |

                    ((h >> 7) & 0x02) | ((h >> 3) & 0x40);

                /* line compare to 1023 */

                s->cr[VGA_CRTC_LINE_COMPARE] = 0xff;

                s->cr[VGA_CRTC_OVERFLOW] |= 0x10;

                s->cr[VGA_CRTC_MAX_SCAN] |= 0x40;

                if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4) {

                    shift_control = 0;

                    s->sr[VGA_SEQ_CLOCK_MODE] &= ~8; /* no double line */

                } else {

                    shift_control = 2;

                    /* set chain 4 mode */

                    s->sr[VGA_SEQ_MEMORY_MODE] |= VGA_SR04_CHN_4M;

                    /* activate all planes */

                    s->sr[VGA_SEQ_PLANE_WRITE] |= VGA_SR02_ALL_PLANES;

                }

                s->gr[VGA_GFX_MODE] = (s->gr[VGA_GFX_MODE] & ~0x60) |

                    (shift_control << 5);

                s->cr[VGA_CRTC_MAX_SCAN] &= ~0x9f; /* no double scan */

            } else {

                s->bank_offset = 0;

            }

            s->dac_8bit = (val & VBE_DISPI_8BIT_DAC) > 0;

            s->vbe_regs[s->vbe_index] = val;

            vga_update_memory_access(s);

            break;

        default:

            break;

        }

    }

}


static void vexpress_common_init(MachineState *machine)

{

    VexpressMachineState *vms = VEXPRESS_MACHINE(machine);

    VexpressMachineClass *vmc = VEXPRESS_MACHINE_GET_CLASS(machine);

    VEDBoardInfo *daughterboard = vmc->daughterboard;

    DeviceState *dev, *sysctl, *pl041;

    qemu_irq pic[64];

    uint32_t sys_id;

    DriveInfo *dinfo;

    pflash_t *pflash0;

    ram_addr_t vram_size, sram_size;

    MemoryRegion *sysmem = get_system_memory();

    MemoryRegion *vram = g_new(MemoryRegion, 1);

    MemoryRegion *sram = g_new(MemoryRegion, 1);

    MemoryRegion *flashalias = g_new(MemoryRegion, 1);

    MemoryRegion *flash0mem;

    const hwaddr *map = daughterboard->motherboard_map;

    int i;

    daughterboard->init(vms, machine->ram_size, machine->cpu_model, pic);

    /*

     * If a bios file was provided, attempt to map it into memory

     */

    if (bios_name) {

        char *fn;

        int image_size;

        if (drive_get(IF_PFLASH, 0, 0)) {

            error_report("The contents of the first flash device may be "

                         "specified with -bios or with -drive if=pflash... "

                         "but you cannot use both options at once");

            exit(1);

        }

        fn = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);

        if (!fn) {

            error_report("Could not find ROM image '%s'", bios_name);

            exit(1);

        }

        image_size = load_image_targphys(fn, map[VE_NORFLASH0],

                                         VEXPRESS_FLASH_SIZE);

        g_free(fn);

        if (image_size < 0) {

            error_report("Could not load ROM image '%s'", bios_name);

            exit(1);

        }

    }

    /* Motherboard peripherals: the wiring is the same but the

     * addresses vary between the legacy and A-Series memory maps.

     */

    sys_id = 0x1190f500;

    sysctl = qdev_create(NULL, "realview_sysctl");

    qdev_prop_set_uint32(sysctl, "sys_id", sys_id);

    qdev_prop_set_uint32(sysctl, "proc_id", daughterboard->proc_id);

    qdev_prop_set_uint32(sysctl, "len-db-voltage",

                         daughterboard->num_voltage_sensors);

    for (i = 0; i < daughterboard->num_voltage_sensors; i++) {

        char *propname = g_strdup_printf("db-voltage[%d]", i);

        qdev_prop_set_uint32(sysctl, propname, daughterboard->voltages[i]);

        g_free(propname);

    }

    qdev_prop_set_uint32(sysctl, "len-db-clock",

                         daughterboard->num_clocks);

    for (i = 0; i < daughterboard->num_clocks; i++) {

        char *propname = g_strdup_printf("db-clock[%d]", i);

        qdev_prop_set_uint32(sysctl, propname, daughterboard->clocks[i]);

        g_free(propname);

    }

    qdev_init_nofail(sysctl);

    sysbus_mmio_map(SYS_BUS_DEVICE(sysctl), 0, map[VE_SYSREGS]);

    /* VE_SP810: not modelled */

    /* VE_SERIALPCI: not modelled */

    pl041 = qdev_create(NULL, "pl041");

    qdev_prop_set_uint32(pl041, "nc_fifo_depth", 512);

    qdev_init_nofail(pl041);

    sysbus_mmio_map(SYS_BUS_DEVICE(pl041), 0, map[VE_PL041]);

    sysbus_connect_irq(SYS_BUS_DEVICE(pl041), 0, pic[11]);

    dev = sysbus_create_varargs("pl181", map[VE_MMCI], pic[9], pic[10], NULL);

    /* Wire up MMC card detect and read-only signals */

    qdev_connect_gpio_out(dev, 0,

                          qdev_get_gpio_in(sysctl, ARM_SYSCTL_GPIO_MMC_WPROT));

    qdev_connect_gpio_out(dev, 1,

                          qdev_get_gpio_in(sysctl, ARM_SYSCTL_GPIO_MMC_CARDIN));

    sysbus_create_simple("pl050_keyboard", map[VE_KMI0], pic[12]);

    sysbus_create_simple("pl050_mouse", map[VE_KMI1], pic[13]);

    sysbus_create_simple("pl011", map[VE_UART0], pic[5]);

    sysbus_create_simple("pl011", map[VE_UART1], pic[6]);

    sysbus_create_simple("pl011", map[VE_UART2], pic[7]);

    sysbus_create_simple("pl011", map[VE_UART3], pic[8]);

    sysbus_create_simple("sp804", map[VE_TIMER01], pic[2]);

    sysbus_create_simple("sp804", map[VE_TIMER23], pic[3]);

    /* VE_SERIALDVI: not modelled */

    sysbus_create_simple("pl031", map[VE_RTC], pic[4]); /* RTC */

    /* VE_COMPACTFLASH: not modelled */

    sysbus_create_simple("pl111", map[VE_CLCD], pic[14]);

    dinfo = drive_get_next(IF_PFLASH);

    pflash0 = ve_pflash_cfi01_register(map[VE_NORFLASH0], "vexpress.flash0",

                                       dinfo);

    if (!pflash0) {

        fprintf(stderr, "vexpress: error registering flash 0.\n");

        exit(1);

    }

    if (map[VE_NORFLASHALIAS] != -1) {

        /* Map flash 0 as an alias into low memory */

        flash0mem = sysbus_mmio_get_region(SYS_BUS_DEVICE(pflash0), 0);

        memory_region_init_alias(flashalias, NULL, "vexpress.flashalias",

                                 flash0mem, 0, VEXPRESS_FLASH_SIZE);

        memory_region_add_subregion(sysmem, map[VE_NORFLASHALIAS], flashalias);

    }

    dinfo = drive_get_next(IF_PFLASH);

    if (!ve_pflash_cfi01_register(map[VE_NORFLASH1], "vexpress.flash1",

                                  dinfo)) {

        fprintf(stderr, "vexpress: error registering flash 1.\n");

        exit(1);

    }

    sram_size = 0x2000000;

    memory_region_init_ram(sram, NULL, "vexpress.sram", sram_size,

                           &error_abort);

    vmstate_register_ram_global(sram);

    memory_region_add_subregion(sysmem, map[VE_SRAM], sram);

    vram_size = 0x800000;

    memory_region_init_ram(vram, NULL, "vexpress.vram", vram_size,

                           &error_abort);

    vmstate_register_ram_global(vram);

    memory_region_add_subregion(sysmem, map[VE_VIDEORAM], vram);

    /* 0x4e000000 LAN9118 Ethernet */

    if (nd_table[0].used) {

        lan9118_init(&nd_table[0], map[VE_ETHERNET], pic[15]);

    }

    /* VE_USB: not modelled */

    /* VE_DAPROM: not modelled */

    /* Create mmio transports, so the user can create virtio backends

     * (which will be automatically plugged in to the transports). If

     * no backend is created the transport will just sit harmlessly idle.

     */

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

        sysbus_create_simple("virtio-mmio", map[VE_VIRTIO] + 0x200 * i,

                             pic[40 + i]);

    }

    daughterboard->bootinfo.ram_size = machine->ram_size;

    daughterboard->bootinfo.kernel_filename = machine->kernel_filename;

    daughterboard->bootinfo.kernel_cmdline = machine->kernel_cmdline;

    daughterboard->bootinfo.initrd_filename = machine->initrd_filename;

    daughterboard->bootinfo.nb_cpus = smp_cpus;

    daughterboard->bootinfo.board_id = VEXPRESS_BOARD_ID;

    daughterboard->bootinfo.loader_start = daughterboard->loader_start;

    daughterboard->bootinfo.smp_loader_start = map[VE_SRAM];

    daughterboard->bootinfo.smp_bootreg_addr = map[VE_SYSREGS] + 0x30;

    daughterboard->bootinfo.gic_cpu_if_addr = daughterboard->gic_cpu_if_addr;

    daughterboard->bootinfo.modify_dtb = vexpress_modify_dtb;

    /* Indicate that when booting Linux we should be in secure state */

    daughterboard->bootinfo.secure_boot = true;

    arm_load_kernel(ARM_CPU(first_cpu), &daughterboard->bootinfo);

}


static int vnc_set_gnutls_priority(gnutls_session_t s, int x509)

{

    const char *priority = x509 ? "NORMAL" : "NORMAL:+ANON-DH";

    int rc;

    rc = gnutls_priority_set_direct(s, priority, NULL);

    if (rc != GNUTLS_E_SUCCESS) {

        return -1;

    }

    return 0;

}


static void vfio_platform_eoi(VFIODevice *vbasedev)

{

    VFIOINTp *intp;

    VFIOPlatformDevice *vdev =

        container_of(vbasedev, VFIOPlatformDevice, vbasedev);

    qemu_mutex_lock(&vdev->intp_mutex);

    QLIST_FOREACH(intp, &vdev->intp_list, next) {

        if (intp->state == VFIO_IRQ_ACTIVE) {

            trace_vfio_platform_eoi(intp->pin,

                                event_notifier_get_fd(intp->interrupt));

            intp->state = VFIO_IRQ_INACTIVE;

            /* deassert the virtual IRQ */

            qemu_set_irq(intp->qemuirq, 0);

            if (intp->flags & VFIO_IRQ_INFO_AUTOMASKED) {

                /* unmasks the physical level-sensitive IRQ */

                vfio_unmask_single_irqindex(vbasedev, intp->pin);

            }

            /* a single IRQ can be active at a time */

            break;

        }

    }

    /* in case there are pending IRQs, handle the first one */

    if (!QSIMPLEQ_EMPTY(&vdev->pending_intp_queue)) {

        intp = QSIMPLEQ_FIRST(&vdev->pending_intp_queue);

        vfio_intp_inject_pending_lockheld(intp);

        QSIMPLEQ_REMOVE_HEAD(&vdev->pending_intp_queue, pqnext);

    }

    qemu_mutex_unlock(&vdev->intp_mutex);

}


static void qxl_enter_vga_mode(PCIQXLDevice *d)

{

    if (d->mode == QXL_MODE_VGA) {

        return;

    }

    trace_qxl_enter_vga_mode(d->id);

#if SPICE_SERVER_VERSION >= 0x000c03 /* release 0.12.3 */

    spice_qxl_driver_unload(&d->ssd.qxl);

#endif

    graphic_console_set_hwops(d->ssd.dcl.con, d->vga.hw_ops, &d->vga);

    update_displaychangelistener(&d->ssd.dcl, GUI_REFRESH_INTERVAL_DEFAULT);

    qemu_spice_create_host_primary(&d->ssd);

    d->mode = QXL_MODE_VGA;

    vga_dirty_log_start(&d->vga);

    graphic_hw_update(d->vga.con);

}


static int mov_read_smi(MOVContext *c, AVIOContext *pb, MOVAtom atom)

{

    AVStream *st;

    if (c->fc->nb_streams < 1)

        return 0;

    st = c->fc->streams[c->fc->nb_streams-1];

    if ((uint64_t)atom.size > (1<<30))

        return AVERROR_INVALIDDATA;

    // currently SVQ3 decoder expect full STSD header - so let's fake it

    // this should be fixed and just SMI header should be passed

    av_free(st->codec->extradata);

    st->codec->extradata = av_mallocz(atom.size + 0x5a + FF_INPUT_BUFFER_PADDING_SIZE);

    if (!st->codec->extradata)

        return AVERROR(ENOMEM);

    st->codec->extradata_size = 0x5a + atom.size;

    memcpy(st->codec->extradata, "SVQ3", 4); // fake

    avio_read(pb, st->codec->extradata + 0x5a, atom.size);

    av_log(c->fc, AV_LOG_TRACE, "Reading SMI %"PRId64"  %s\n", atom.size, st->codec->extradata + 0x5a);

    return 0;

}


AVFilterFormats *avfilter_merge_formats(AVFilterFormats *a, AVFilterFormats *b)

{

    AVFilterFormats *ret;

    unsigned i, j, k = 0;

    ret = av_mallocz(sizeof(AVFilterFormats));

    /* merge list of formats */

    ret->formats = av_malloc(sizeof(*ret->formats) * FFMIN(a->format_count,

                                                           b->format_count));

    for(i = 0; i < a->format_count; i ++)

        for(j = 0; j < b->format_count; j ++)

            if(a->formats[i] == b->formats[j])

                ret->formats[k++] = a->formats[i];

    /* check that there was at least one common format */

    if(!(ret->format_count = k)) {

        av_free(ret->formats);

        av_free(ret);

        return NULL;

    }

    /* merge and update all the references */

    ret->refs = av_malloc(sizeof(AVFilterFormats**)*(a->refcount+b->refcount));

    for(i = 0; i < a->refcount; i ++) {

        ret->refs[ret->refcount] = a->refs[i];

        *ret->refs[ret->refcount++] = ret;

    }

    for(i = 0; i < b->refcount; i ++) {

        ret->refs[ret->refcount] = b->refs[i];

        *ret->refs[ret->refcount++] = ret;

    }

    av_free(a->refs);

    av_free(a->formats);

    av_free(a);

    av_free(b->refs);

    av_free(b->formats);

    av_free(b);

    return ret;

}


static void rv40_v_loop_filter(uint8_t *src, int stride, int dmode,

                               int lim_q1, int lim_p1,

                               int alpha, int beta, int beta2, int chroma, int edge){

    rv40_adaptive_loop_filter(src, 1, stride, dmode, lim_q1, lim_p1,

                              alpha, beta, beta2, chroma, edge);

}


static void lfe_downsample(DCAEncContext *c, const int32_t *input)

{

    /* FIXME: make 128x LFE downsampling possible */

    const int lfech = lfe_index[c->channel_config];

    int i, j, lfes;

    int32_t hist[512];

    int32_t accum;

    int hist_start = 0;

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

        hist[i] = c->history[i][c->channels - 1];

    for (lfes = 0; lfes < DCA_LFE_SAMPLES; lfes++) {

        /* Calculate the convolution */

        accum = 0;

        for (i = hist_start, j = 0; i < 512; i++, j++)

            accum += mul32(hist[i], lfe_fir_64i[j]);

        for (i = 0; i < hist_start; i++, j++)

            accum += mul32(hist[i], lfe_fir_64i[j]);

        c->downsampled_lfe[lfes] = accum;

        /* Copy in 64 new samples from input */

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

            hist[i + hist_start] = input[(lfes * 64 + i) * c->channels + lfech];

        hist_start = (hist_start + 64) & 511;

    }

}


static int indeo3_decode_frame(AVCodecContext *avctx,

                               void *data, int *data_size,

                               const uint8_t *buf, int buf_size)

{

    Indeo3DecodeContext *s=avctx->priv_data;

    uint8_t *src, *dest;

    int y;

    iv_decode_frame(s, buf, buf_size);

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

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

    s->frame.reference = 0;

    if(avctx->get_buffer(avctx, &s->frame) < 0) {

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

        return -1;

    }

    src = s->cur_frame->Ybuf;

    dest = s->frame.data[0];

    for (y = 0; y < s->height; y++) {

        memcpy(dest, src, s->cur_frame->y_w);

        src += s->cur_frame->y_w;

        dest += s->frame.linesize[0];

    }

    if (!(s->avctx->flags & CODEC_FLAG_GRAY))

    {

        src = s->cur_frame->Ubuf;

        dest = s->frame.data[1];

        for (y = 0; y < s->height / 4; y++) {

            memcpy(dest, src, s->cur_frame->uv_w);

            src += s->cur_frame->uv_w;

            dest += s->frame.linesize[1];

        }

        src = s->cur_frame->Vbuf;

        dest = s->frame.data[2];

        for (y = 0; y < s->height / 4; y++) {

            memcpy(dest, src, s->cur_frame->uv_w);

            src += s->cur_frame->uv_w;

            dest += s->frame.linesize[2];

        }

    }

    *data_size=sizeof(AVFrame);

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

    return buf_size;

}


static void filter_mb_edgech( H264Context *h, uint8_t *pix, int stride, int bS[4], int qp ) {

    int i, d;

    const int index_a = clip( qp + h->slice_alpha_c0_offset, 0, 51 );

    const int alpha = alpha_table[index_a];

    const int beta  = beta_table[clip( qp + h->slice_beta_offset, 0, 51 )];

    const int pix_next  = stride;

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

    {

        if( bS[i] == 0 ) {

            pix += 2;

            continue;

        }

        /* 2px edge length (see deblocking_filter_edgecv) */

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

            const uint8_t p0 = pix[-1*pix_next];

            const uint8_t p1 = pix[-2*pix_next];

            const uint8_t q0 = pix[0];

            const uint8_t q1 = pix[1*pix_next];

            if( abs( p0 - q0 ) >= alpha ||

                abs( p1 - p0 ) >= beta ||

                abs( q1 - q0 ) >= beta ) {

                pix++;

                continue;

            }

            if( bS[i] < 4 ) {

                int tc = tc0_table[index_a][bS[i] - 1] + 1;

                int i_delta = clip( (((q0 - p0 ) << 2) + (p1 - q1) + 4) >> 3, -tc, tc );

                pix[-pix_next] = clip( p0 + i_delta, 0, 255 );    /* p0' */

                pix[0]         = clip( q0 - i_delta, 0, 255 );    /* q0' */

            }

            else

            {

                pix[-pix_next] = ( 2*p1 + p0 + q1 + 2 ) >> 2;   /* p0' */

                pix[0]         = ( 2*q1 + q0 + p1 + 2 ) >> 2;   /* q0' */

            }

            pix++;

        }

    }

}


void aio_context_unref(AioContext *ctx)

{

    g_source_unref(&ctx->source);

}


static void handle_hint(DisasContext *s, uint32_t insn,

                        unsigned int op1, unsigned int op2, unsigned int crm)

{

    unsigned int selector = crm << 3 | op2;

    if (op1 != 3) {

        unallocated_encoding(s);

        return;

    }

    switch (selector) {

    case 0: /* NOP */

        return;

    case 3: /* WFI */

        s->base.is_jmp = DISAS_WFI;

        return;

    case 1: /* YIELD */

        if (!parallel_cpus) {

            s->base.is_jmp = DISAS_YIELD;

        }

        return;

    case 2: /* WFE */

        if (!parallel_cpus) {

            s->base.is_jmp = DISAS_WFE;

        }

        return;

    case 4: /* SEV */

    case 5: /* SEVL */

        /* we treat all as NOP at least for now */

        return;

    default:

        /* default specified as NOP equivalent */

        return;

    }

}


static int msrle_decode_frame(AVCodecContext *avctx,

                              void *data, int *got_frame,

                              AVPacket *avpkt)

{

    const uint8_t *buf = avpkt->data;

    int buf_size = avpkt->size;

    MsrleContext *s = avctx->priv_data;

    int istride = FFALIGN(avctx->width*avctx->bits_per_coded_sample, 32) / 8;

    int ret;

    s->buf = buf;

    s->size = buf_size;

    if ((ret = ff_reget_buffer(avctx, s->frame)) < 0)

        return ret;

    if (avctx->bits_per_coded_sample > 1 && avctx->bits_per_coded_sample <= 8) {

        const uint8_t *pal = av_packet_get_side_data(avpkt, AV_PKT_DATA_PALETTE, NULL);

        if (pal) {

            s->frame->palette_has_changed = 1;

            memcpy(s->pal, pal, AVPALETTE_SIZE);

        }

        /* make the palette available */

        memcpy(s->frame->data[1], s->pal, AVPALETTE_SIZE);

    }

    /* FIXME how to correctly detect RLE ??? */

    if (avctx->height * istride == avpkt->size) { /* assume uncompressed */

        int linesize = (avctx->width * avctx->bits_per_coded_sample + 7) / 8;

        uint8_t *ptr = s->frame->data[0];

        uint8_t *buf = avpkt->data + (avctx->height-1)*istride;

        int i, j;

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

            if (avctx->bits_per_coded_sample == 4) {

                for (j = 0; j < avctx->width - 1; j += 2) {

                    ptr[j+0] = buf[j>>1] >> 4;

                    ptr[j+1] = buf[j>>1] & 0xF;

                }

                if (avctx->width & 1)

                    ptr[j+0] = buf[j>>1] >> 4;

            } else {

                memcpy(ptr, buf, linesize);

            }

            buf -= istride;

            ptr += s->frame->linesize[0];

        }

    } else {

        bytestream2_init(&s->gb, buf, buf_size);

        ff_msrle_decode(avctx, (AVPicture*)s->frame, avctx->bits_per_coded_sample, &s->gb);

    }

    if ((ret = av_frame_ref(data, s->frame)) < 0)

        return ret;

    *got_frame      = 1;

    /* report that the buffer was completely consumed */

    return buf_size;

}


static void tcx_update_display(void *opaque)

{

    TCXState *ts = opaque;

    ram_addr_t page, page_min, page_max;

    int y, y_start, dd, ds;

    uint8_t *d, *s;

    void (*f)(TCXState *s1, uint8_t *d, const uint8_t *s, int width);

    if (ts->ds->depth == 0)

	return;

    page = ts->vram_offset;

    y_start = -1;

    page_min = 0xffffffff;

    page_max = 0;

    d = ts->ds->data;

    s = ts->vram;

    dd = ts->ds->linesize;

    ds = 1024;

    switch (ts->ds->depth) {

    case 32:

	f = tcx_draw_line32;

	break;

    case 15:

    case 16:

	f = tcx_draw_line16;

	break;

    default:

    case 8:

	f = tcx_draw_line8;

	break;

    case 0:

	return;

    }

    for(y = 0; y < ts->height; y += 4, page += TARGET_PAGE_SIZE) {

	if (cpu_physical_memory_get_dirty(page, VGA_DIRTY_FLAG)) {

	    if (y_start < 0)

                y_start = y;

            if (page < page_min)

                page_min = page;

            if (page > page_max)

                page_max = page;

	    f(ts, d, s, ts->width);

	    d += dd;

	    s += ds;

	    f(ts, d, s, ts->width);

	    d += dd;

	    s += ds;

	    f(ts, d, s, ts->width);

	    d += dd;

	    s += ds;

	    f(ts, d, s, ts->width);

	    d += dd;

	    s += ds;

	} else {

            if (y_start >= 0) {

                /* flush to display */

                dpy_update(ts->ds, 0, y_start,

                           ts->width, y - y_start);

                y_start = -1;

            }

	    d += dd * 4;

	    s += ds * 4;

	}

    }

    if (y_start >= 0) {

	/* flush to display */

	dpy_update(ts->ds, 0, y_start,

		   ts->width, y - y_start);

    }

    /* reset modified pages */

    if (page_min <= page_max) {

        cpu_physical_memory_reset_dirty(page_min, page_max + TARGET_PAGE_SIZE,

                                        VGA_DIRTY_FLAG);

    }

}


int vnc_zlib_send_framebuffer_update(VncState *vs, int x, int y, int w, int h)

{

    int old_offset, new_offset, bytes_written;

    vnc_framebuffer_update(vs, x, y, w, h, VNC_ENCODING_ZLIB);

    // remember where we put in the follow-up size

    old_offset = vs->output.offset;

    vnc_write_s32(vs, 0);

    // compress the stream

    vnc_zlib_start(vs);

    vnc_raw_send_framebuffer_update(vs, x, y, w, h);

    bytes_written = vnc_zlib_stop(vs);

    if (bytes_written == -1)

        return 0;

    // hack in the size

    new_offset = vs->output.offset;

    vs->output.offset = old_offset;

    vnc_write_u32(vs, bytes_written);

    vs->output.offset = new_offset;

    return 1;

}


static TCGv_i64 read_fp_dreg(DisasContext *s, int reg)

{

    TCGv_i64 v = tcg_temp_new_i64();

    tcg_gen_ld_i64(v, cpu_env, fp_reg_offset(reg, MO_64));

    return v;

}


static int vfio_connect_container(VFIOGroup *group, AddressSpace *as)

{

    VFIOContainer *container;

    int ret, fd;

    VFIOAddressSpace *space;

    space = vfio_get_address_space(as);

    QLIST_FOREACH(container, &space->containers, next) {

        if (!ioctl(group->fd, VFIO_GROUP_SET_CONTAINER, &container->fd)) {

            group->container = container;

            QLIST_INSERT_HEAD(&container->group_list, group, container_next);

            return 0;

        }

    }

    fd = qemu_open("/dev/vfio/vfio", O_RDWR);

    if (fd < 0) {

        error_report("vfio: failed to open /dev/vfio/vfio: %m");

        ret = -errno;

        goto put_space_exit;

    }

    ret = ioctl(fd, VFIO_GET_API_VERSION);

    if (ret != VFIO_API_VERSION) {

        error_report("vfio: supported vfio version: %d, "

                     "reported version: %d", VFIO_API_VERSION, ret);

        ret = -EINVAL;

        goto close_fd_exit;

    }

    container = g_malloc0(sizeof(*container));

    container->space = space;

    container->fd = fd;

    if (ioctl(fd, VFIO_CHECK_EXTENSION, VFIO_TYPE1_IOMMU) ||

        ioctl(fd, VFIO_CHECK_EXTENSION, VFIO_TYPE1v2_IOMMU)) {

        bool v2 = !!ioctl(fd, VFIO_CHECK_EXTENSION, VFIO_TYPE1v2_IOMMU);

        struct vfio_iommu_type1_info info;

        ret = ioctl(group->fd, VFIO_GROUP_SET_CONTAINER, &fd);

        if (ret) {

            error_report("vfio: failed to set group container: %m");

            ret = -errno;

            goto free_container_exit;

        }

        container->iommu_type = v2 ? VFIO_TYPE1v2_IOMMU : VFIO_TYPE1_IOMMU;

        ret = ioctl(fd, VFIO_SET_IOMMU, container->iommu_type);

        if (ret) {

            error_report("vfio: failed to set iommu for container: %m");

            ret = -errno;

            goto free_container_exit;

        }

        /*

         * FIXME: This assumes that a Type1 IOMMU can map any 64-bit

         * IOVA whatsoever.  That's not actually true, but the current

         * kernel interface doesn't tell us what it can map, and the

         * existing Type1 IOMMUs generally support any IOVA we're

         * going to actually try in practice.

         */

        info.argsz = sizeof(info);

        ret = ioctl(fd, VFIO_IOMMU_GET_INFO, &info);

        /* Ignore errors */

        if (ret || !(info.flags & VFIO_IOMMU_INFO_PGSIZES)) {

            /* Assume 4k IOVA page size */

            info.iova_pgsizes = 4096;

        }

        vfio_host_win_add(container, 0, (hwaddr)-1, info.iova_pgsizes);

    } else if (ioctl(fd, VFIO_CHECK_EXTENSION, VFIO_SPAPR_TCE_IOMMU) ||

               ioctl(fd, VFIO_CHECK_EXTENSION, VFIO_SPAPR_TCE_v2_IOMMU)) {

        struct vfio_iommu_spapr_tce_info info;

        bool v2 = !!ioctl(fd, VFIO_CHECK_EXTENSION, VFIO_SPAPR_TCE_v2_IOMMU);

        ret = ioctl(group->fd, VFIO_GROUP_SET_CONTAINER, &fd);

        if (ret) {

            error_report("vfio: failed to set group container: %m");

            ret = -errno;

            goto free_container_exit;

        }

        container->iommu_type =

            v2 ? VFIO_SPAPR_TCE_v2_IOMMU : VFIO_SPAPR_TCE_IOMMU;

        ret = ioctl(fd, VFIO_SET_IOMMU, container->iommu_type);

        if (ret) {

            error_report("vfio: failed to set iommu for container: %m");

            ret = -errno;

            goto free_container_exit;

        }

        /*

         * The host kernel code implementing VFIO_IOMMU_DISABLE is called

         * when container fd is closed so we do not call it explicitly

         * in this file.

         */

        if (!v2) {

            ret = ioctl(fd, VFIO_IOMMU_ENABLE);

            if (ret) {

                error_report("vfio: failed to enable container: %m");

                ret = -errno;

                goto free_container_exit;

            }

        } else {

            container->prereg_listener = vfio_prereg_listener;

            memory_listener_register(&container->prereg_listener,

                                     &address_space_memory);

            if (container->error) {

                memory_listener_unregister(&container->prereg_listener);

                error_report("vfio: RAM memory listener initialization failed for container");

                goto free_container_exit;

            }

        }

        /*

         * This only considers the host IOMMU's 32-bit window.  At

         * some point we need to add support for the optional 64-bit

         * window and dynamic windows

         */

        info.argsz = sizeof(info);

        ret = ioctl(fd, VFIO_IOMMU_SPAPR_TCE_GET_INFO, &info);

        if (ret) {

            error_report("vfio: VFIO_IOMMU_SPAPR_TCE_GET_INFO failed: %m");

            ret = -errno;

            if (v2) {

                memory_listener_unregister(&container->prereg_listener);

            }

            goto free_container_exit;

        }

        /* The default table uses 4K pages */

        vfio_host_win_add(container, info.dma32_window_start,

                          info.dma32_window_start +

                          info.dma32_window_size - 1,

                          0x1000);

    } else {

        error_report("vfio: No available IOMMU models");

        ret = -EINVAL;

        goto free_container_exit;

    }

    container->listener = vfio_memory_listener;

    memory_listener_register(&container->listener, container->space->as);

    if (container->error) {

        ret = container->error;

        error_report("vfio: memory listener initialization failed for container");

        goto listener_release_exit;

    }

    container->initialized = true;

    QLIST_INIT(&container->group_list);

    QLIST_INSERT_HEAD(&space->containers, container, next);

    group->container = container;

    QLIST_INSERT_HEAD(&container->group_list, group, container_next);

    return 0;

listener_release_exit:

    vfio_listener_release(container);

free_container_exit:

    g_free(container);

close_fd_exit:

    close(fd);

put_space_exit:

    vfio_put_address_space(space);

    return ret;

}


static void pci_piix_init_ports(PCIIDEState *d) {

    int i;

    struct {

        int iobase;

        int iobase2;

        int isairq;

    } port_info[] = {

        {0x1f0, 0x3f6, 14},

        {0x170, 0x376, 15},

    };

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

        ide_bus_new(&d->bus[i], &d->dev.qdev, i);

        ide_init_ioport(&d->bus[i], port_info[i].iobase, port_info[i].iobase2);

        ide_init2(&d->bus[i], isa_reserve_irq(port_info[i].isairq));

        bmdma_init(&d->bus[i], &d->bmdma[i]);

        d->bmdma[i].bus = &d->bus[i];

        qemu_add_vm_change_state_handler(d->bus[i].dma->ops->restart_cb,

                                         &d->bmdma[i].dma);

    }

}


void load_seg(int seg_reg, int selector)

{

    SegmentCache *sc;

    SegmentDescriptorTable *dt;

    int index;

    uint32_t e1, e2;

    uint8_t *ptr;

    env->segs[seg_reg] = selector;

    sc = &env->seg_cache[seg_reg];

    if (env->eflags & VM_MASK) {

        sc->base = (void *)(selector << 4);

        sc->limit = 0xffff;

        sc->seg_32bit = 0;

    } else {

        if (selector & 0x4)

            dt = &env->ldt;

        else

            dt = &env->gdt;

        index = selector & ~7;

        if ((index + 7) > dt->limit)

            raise_exception_err(EXCP0D_GPF, selector);

        ptr = dt->base + index;

        e1 = ldl(ptr);

        e2 = ldl(ptr + 4);

        sc->base = (void *)((e1 >> 16) | ((e2 & 0xff) << 16) | (e2 & 0xff000000));

        sc->limit = (e1 & 0xffff) | (e2 & 0x000f0000);

        if (e2 & (1 << 23))

            sc->limit = (sc->limit << 12) | 0xfff;

        sc->seg_32bit = (e2 >> 22) & 1;

#if 0

        fprintf(logfile, "load_seg: sel=0x%04x base=0x%08lx limit=0x%08lx seg_32bit=%d\n",

                selector, (unsigned long)sc->base, sc->limit, sc->seg_32bit);

#endif

    }

}


static BlockBackend *blockdev_init(const char *file, QDict *bs_opts,

                                   Error **errp)

{

    const char *buf;

    int bdrv_flags = 0;

    int on_read_error, on_write_error;

    bool account_invalid, account_failed;

    const char *stats_intervals;

    BlockBackend *blk;

    BlockDriverState *bs;

    ThrottleConfig cfg;

    int snapshot = 0;

    Error *error = NULL;

    QemuOpts *opts;

    const char *id;

    bool has_driver_specific_opts;

    BlockdevDetectZeroesOptions detect_zeroes =

        BLOCKDEV_DETECT_ZEROES_OPTIONS_OFF;

    const char *throttling_group = NULL;

    /* Check common options by copying from bs_opts to opts, all other options

     * stay in bs_opts for processing by bdrv_open(). */

    id = qdict_get_try_str(bs_opts, "id");

    opts = qemu_opts_create(&qemu_common_drive_opts, id, 1, &error);

    if (error) {

        error_propagate(errp, error);

        goto err_no_opts;

    }

    qemu_opts_absorb_qdict(opts, bs_opts, &error);

    if (error) {

        error_propagate(errp, error);

        goto early_err;

    }

    if (id) {

        qdict_del(bs_opts, "id");

    }

    has_driver_specific_opts = !!qdict_size(bs_opts);

    /* extract parameters */

    snapshot = qemu_opt_get_bool(opts, "snapshot", 0);

    account_invalid = qemu_opt_get_bool(opts, "stats-account-invalid", true);

    account_failed = qemu_opt_get_bool(opts, "stats-account-failed", true);

    stats_intervals = qemu_opt_get(opts, "stats-intervals");

    extract_common_blockdev_options(opts, &bdrv_flags, &throttling_group, &cfg,

                                    &detect_zeroes, &error);

    if (error) {

        error_propagate(errp, error);

        goto early_err;

    }

    if ((buf = qemu_opt_get(opts, "format")) != NULL) {

        if (is_help_option(buf)) {

            error_printf("Supported formats:");

            bdrv_iterate_format(bdrv_format_print, NULL);

            error_printf("\n");

            goto early_err;

        }

        if (qdict_haskey(bs_opts, "driver")) {

            error_setg(errp, "Cannot specify both 'driver' and 'format'");

            goto early_err;

        }

        qdict_put(bs_opts, "driver", qstring_from_str(buf));

    }

    on_write_error = BLOCKDEV_ON_ERROR_ENOSPC;

    if ((buf = qemu_opt_get(opts, "werror")) != NULL) {

        on_write_error = parse_block_error_action(buf, 0, &error);

        if (error) {

            error_propagate(errp, error);

            goto early_err;

        }

    }

    on_read_error = BLOCKDEV_ON_ERROR_REPORT;

    if ((buf = qemu_opt_get(opts, "rerror")) != NULL) {

        on_read_error = parse_block_error_action(buf, 1, &error);

        if (error) {

            error_propagate(errp, error);

            goto early_err;

        }

    }

    if (snapshot) {

        /* always use cache=unsafe with snapshot */

        bdrv_flags &= ~BDRV_O_CACHE_MASK;

        bdrv_flags |= (BDRV_O_SNAPSHOT|BDRV_O_CACHE_WB|BDRV_O_NO_FLUSH);

    }

    /* init */

    if ((!file || !*file) && !has_driver_specific_opts) {

        BlockBackendRootState *blk_rs;

        blk = blk_new(qemu_opts_id(opts), errp);

        if (!blk) {

            goto early_err;

        }

        blk_rs = blk_get_root_state(blk);

        blk_rs->open_flags    = bdrv_flags;

        blk_rs->read_only     = !(bdrv_flags & BDRV_O_RDWR);

        blk_rs->detect_zeroes = detect_zeroes;

        if (throttle_enabled(&cfg)) {

            if (!throttling_group) {

                throttling_group = blk_name(blk);

            }

            blk_rs->throttle_group = g_strdup(throttling_group);

            blk_rs->throttle_state = throttle_group_incref(throttling_group);

            blk_rs->throttle_state->cfg = cfg;

        }

        QDECREF(bs_opts);

    } else {

        if (file && !*file) {

            file = NULL;

        }

        blk = blk_new_open(qemu_opts_id(opts), file, NULL, bs_opts, bdrv_flags,

                           errp);

        if (!blk) {

            goto err_no_bs_opts;

        }

        bs = blk_bs(blk);

        bs->detect_zeroes = detect_zeroes;

        /* disk I/O throttling */

        if (throttle_enabled(&cfg)) {

            if (!throttling_group) {

                throttling_group = blk_name(blk);

            }

            bdrv_io_limits_enable(bs, throttling_group);

            bdrv_set_io_limits(bs, &cfg);

        }

        if (bdrv_key_required(bs)) {

            autostart = 0;

        }

        block_acct_init(blk_get_stats(blk), account_invalid, account_failed);

        if (stats_intervals) {

            char **intervals = g_strsplit(stats_intervals, ":", 0);

            unsigned i;

            if (*stats_intervals == '\0') {

                error_setg(&error, "stats-intervals can't have an empty value");

            }

            for (i = 0; !error && intervals[i] != NULL; i++) {

                unsigned long long val;

                if (parse_uint_full(intervals[i], &val, 10) == 0 &&

                    val > 0 && val <= UINT_MAX) {

                    block_acct_add_interval(blk_get_stats(blk), val);

                } else {

                    error_setg(&error, "Invalid interval length: '%s'",

                               intervals[i]);

                }

            }

            g_strfreev(intervals);

            if (error) {

                error_propagate(errp, error);

                blk_unref(blk);

                blk = NULL;

                goto err_no_bs_opts;

            }

        }

    }

    blk_set_on_error(blk, on_read_error, on_write_error);

err_no_bs_opts:

    qemu_opts_del(opts);

    return blk;

early_err:

    qemu_opts_del(opts);

err_no_opts:

    QDECREF(bs_opts);

    return NULL;

}


av_cold void ff_dsputil_init_armv5te(DSPContext *c, AVCodecContext *avctx)

{

    if (avctx->bits_per_raw_sample <= 8 &&

        (avctx->idct_algo == FF_IDCT_AUTO ||

         avctx->idct_algo == FF_IDCT_SIMPLEARMV5TE)) {

        c->idct_put              = ff_simple_idct_put_armv5te;

        c->idct_add              = ff_simple_idct_add_armv5te;

        c->idct                  = ff_simple_idct_armv5te;

        c->idct_permutation_type = FF_NO_IDCT_PERM;

    }

    c->prefetch = ff_prefetch_arm;

}


static QObject *qmp_input_get_object(QmpInputVisitor *qiv,

                                     const char *name,

                                     bool consume, Error **errp)

{

    StackObject *tos;

    QObject *qobj;

    QObject *ret;

    if (QSLIST_EMPTY(&qiv->stack)) {

        /* Starting at root, name is ignored. */

        assert(qiv->root);

        return qiv->root;

    }

    /* We are in a container; find the next element. */

    tos = QSLIST_FIRST(&qiv->stack);

    qobj = tos->obj;

    assert(qobj);

    if (qobject_type(qobj) == QTYPE_QDICT) {

        assert(name);

        ret = qdict_get(qobject_to_qdict(qobj), name);

        if (tos->h && consume && ret) {

            bool removed = g_hash_table_remove(tos->h, name);

            assert(removed);

        }

        if (!ret) {

            error_setg(errp, QERR_MISSING_PARAMETER, name);

        }

    } else {

        assert(qobject_type(qobj) == QTYPE_QLIST);

        assert(!name);

        ret = qlist_entry_obj(tos->entry);

        assert(ret);

        if (consume) {

            tos->entry = qlist_next(tos->entry);

        }

    }

    return ret;

}


static void rtas_ibm_set_slot_reset(PowerPCCPU *cpu,

                                    sPAPREnvironment *spapr,

                                    uint32_t token, uint32_t nargs,

                                    target_ulong args, uint32_t nret,

                                    target_ulong rets)

{

    sPAPRPHBState *sphb;

    sPAPRPHBClass *spc;

    uint32_t option;

    uint64_t buid;

    int ret;

    if ((nargs != 4) || (nret != 1)) {

        goto param_error_exit;

    }

    buid = ((uint64_t)rtas_ld(args, 1) << 32) | rtas_ld(args, 2);

    option = rtas_ld(args, 3);

    sphb = find_phb(spapr, buid);

    if (!sphb) {

        goto param_error_exit;

    }

    spc = SPAPR_PCI_HOST_BRIDGE_GET_CLASS(sphb);

    if (!spc->eeh_reset) {

        goto param_error_exit;

    }

    ret = spc->eeh_reset(sphb, option);

    rtas_st(rets, 0, ret);

    return;

param_error_exit:

    rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);

}


int pp_check(int key, int pp, int nx)

{

    int access;

    /* Compute access rights */

    /* When pp is 3/7, the result is undefined. Set it to noaccess */

    access = 0;

    if (key == 0) {

        switch (pp) {

        case 0x0:

        case 0x1:

        case 0x2:

            access |= PAGE_WRITE;

            /* No break here */

        case 0x3:

        case 0x6:

            access |= PAGE_READ;

            break;

        }

    } else {

        switch (pp) {

        case 0x0:

        case 0x6:

            access = 0;

            break;

        case 0x1:

        case 0x3:

            access = PAGE_READ;

            break;

        case 0x2:

            access = PAGE_READ | PAGE_WRITE;

            break;

        }

    }

    if (nx == 0) {

        access |= PAGE_EXEC;

    }

    return access;

}


static bool check_section_footer(QEMUFile *f, SaveStateEntry *se)

{

    uint8_t read_mark;

    uint32_t read_section_id;

    if (skip_section_footers) {

        /* No footer to check */

        return true;

    }

    read_mark = qemu_get_byte(f);

    if (read_mark != QEMU_VM_SECTION_FOOTER) {

        error_report("Missing section footer for %s", se->idstr);

        return false;

    }

    read_section_id = qemu_get_be32(f);

    if (read_section_id != se->section_id) {

        error_report("Mismatched section id in footer for %s -"

                     " read 0x%x expected 0x%x",

                     se->idstr, read_section_id, se->section_id);

        return false;

    }

    /* All good */

    return true;

}