matroska_add_stream (MatroskaDemuxContext *matroska)

{

    int res = 0;

    uint32_t id;

    MatroskaTrack *track;

    av_log(matroska->ctx, AV_LOG_DEBUG, "parsing track, adding stream..,\n");

    /* Allocate a generic track. As soon as we know its type we'll realloc. */

    track = av_mallocz(MAX_TRACK_SIZE);

    matroska->num_tracks++;

    strcpy(track->language, "eng");

    /* start with the master */

    if ((res = ebml_read_master(matroska, &id)) < 0)

        return res;

    /* try reading the trackentry headers */

    while (res == 0) {

        if (!(id = ebml_peek_id(matroska, &matroska->level_up))) {

            res = AVERROR(EIO);

            break;

        } else if (matroska->level_up > 0) {

            matroska->level_up--;

            break;

        }

        switch (id) {

            /* track number (unique stream ID) */

            case MATROSKA_ID_TRACKNUMBER: {

                uint64_t num;

                if ((res = ebml_read_uint(matroska, &id, &num)) < 0)

                    break;

                track->num = num;

                break;

            }

            /* track UID (unique identifier) */

            case MATROSKA_ID_TRACKUID: {

                uint64_t num;

                if ((res = ebml_read_uint(matroska, &id, &num)) < 0)

                    break;

                track->uid = num;

                break;

            }

            /* track type (video, audio, combined, subtitle, etc.) */

            case MATROSKA_ID_TRACKTYPE: {

                uint64_t num;

                if ((res = ebml_read_uint(matroska, &id, &num)) < 0)

                    break;

                if (track->type && track->type != num) {

                    av_log(matroska->ctx, AV_LOG_INFO,

                           "More than one tracktype in an entry - skip\n");

                    break;

                }

                track->type = num;

                switch (track->type) {

                    case MATROSKA_TRACK_TYPE_VIDEO:

                    case MATROSKA_TRACK_TYPE_AUDIO:

                    case MATROSKA_TRACK_TYPE_SUBTITLE:

                        break;

                    case MATROSKA_TRACK_TYPE_COMPLEX:

                    case MATROSKA_TRACK_TYPE_LOGO:

                    case MATROSKA_TRACK_TYPE_CONTROL:

                    default:

                        av_log(matroska->ctx, AV_LOG_INFO,

                               "Unknown or unsupported track type 0x%x\n",

                               track->type);

                        track->type = MATROSKA_TRACK_TYPE_NONE;

                        break;

                }

                matroska->tracks[matroska->num_tracks - 1] = track;

                break;

            }

            /* tracktype specific stuff for video */

            case MATROSKA_ID_TRACKVIDEO: {

                MatroskaVideoTrack *videotrack;

                if (!track->type)

                    track->type = MATROSKA_TRACK_TYPE_VIDEO;

                if (track->type != MATROSKA_TRACK_TYPE_VIDEO) {

                    av_log(matroska->ctx, AV_LOG_INFO,

                           "video data in non-video track - ignoring\n");

                    res = AVERROR_INVALIDDATA;

                    break;

                } else if ((res = ebml_read_master(matroska, &id)) < 0)

                    break;

                videotrack = (MatroskaVideoTrack *)track;

                while (res == 0) {

                    if (!(id = ebml_peek_id(matroska, &matroska->level_up))) {

                        res = AVERROR(EIO);

                        break;

                    } else if (matroska->level_up > 0) {

                        matroska->level_up--;

                        break;

                    }

                    switch (id) {

                        /* fixme, this should be one-up, but I get it here */

                        case MATROSKA_ID_TRACKDEFAULTDURATION: {

                            uint64_t num;

                            if ((res = ebml_read_uint (matroska, &id,

                                                       &num)) < 0)

                                break;

                            track->default_duration = num;

                            break;

                        }

                        /* video framerate */

                        case MATROSKA_ID_VIDEOFRAMERATE: {

                            double num;

                            if ((res = ebml_read_float(matroska, &id,

                                                       &num)) < 0)

                                break;

                            if (!track->default_duration)

                                track->default_duration = 1000000000/num;

                            break;

                        }

                        /* width of the size to display the video at */

                        case MATROSKA_ID_VIDEODISPLAYWIDTH: {

                            uint64_t num;

                            if ((res = ebml_read_uint(matroska, &id,

                                                      &num)) < 0)

                                break;

                            videotrack->display_width = num;

                            break;

                        }

                        /* height of the size to display the video at */

                        case MATROSKA_ID_VIDEODISPLAYHEIGHT: {

                            uint64_t num;

                            if ((res = ebml_read_uint(matroska, &id,

                                                      &num)) < 0)

                                break;

                            videotrack->display_height = num;

                            break;

                        }

                        /* width of the video in the file */

                        case MATROSKA_ID_VIDEOPIXELWIDTH: {

                            uint64_t num;

                            if ((res = ebml_read_uint(matroska, &id,

                                                      &num)) < 0)

                                break;

                            videotrack->pixel_width = num;

                            break;

                        }

                        /* height of the video in the file */

                        case MATROSKA_ID_VIDEOPIXELHEIGHT: {

                            uint64_t num;

                            if ((res = ebml_read_uint(matroska, &id,

                                                      &num)) < 0)

                                break;

                            videotrack->pixel_height = num;

                            break;

                        }

                        /* whether the video is interlaced */

                        case MATROSKA_ID_VIDEOFLAGINTERLACED: {

                            uint64_t num;

                            if ((res = ebml_read_uint(matroska, &id,

                                                      &num)) < 0)

                                break;

                            if (num)

                                track->flags |=

                                    MATROSKA_VIDEOTRACK_INTERLACED;

                            else

                                track->flags &=

                                    ~MATROSKA_VIDEOTRACK_INTERLACED;

                            break;

                        }

                        /* stereo mode (whether the video has two streams,

                         * where one is for the left eye and the other for

                         * the right eye, which creates a 3D-like

                         * effect) */

                        case MATROSKA_ID_VIDEOSTEREOMODE: {

                            uint64_t num;

                            if ((res = ebml_read_uint(matroska, &id,

                                                      &num)) < 0)

                                break;

                            if (num != MATROSKA_EYE_MODE_MONO &&

                                num != MATROSKA_EYE_MODE_LEFT &&

                                num != MATROSKA_EYE_MODE_RIGHT &&

                                num != MATROSKA_EYE_MODE_BOTH) {

                                av_log(matroska->ctx, AV_LOG_INFO,

                                       "Ignoring unknown eye mode 0x%x\n",

                                       (uint32_t) num);

                                break;

                            }

                            videotrack->eye_mode = num;

                            break;

                        }

                        /* aspect ratio behaviour */

                        case MATROSKA_ID_VIDEOASPECTRATIO: {

                            uint64_t num;

                            if ((res = ebml_read_uint(matroska, &id,

                                                      &num)) < 0)

                                break;

                            if (num != MATROSKA_ASPECT_RATIO_MODE_FREE &&

                                num != MATROSKA_ASPECT_RATIO_MODE_KEEP &&

                                num != MATROSKA_ASPECT_RATIO_MODE_FIXED) {

                                av_log(matroska->ctx, AV_LOG_INFO,

                                       "Ignoring unknown aspect ratio 0x%x\n",

                                       (uint32_t) num);

                                break;

                            }

                            videotrack->ar_mode = num;

                            break;

                        }

                        /* colorspace (only matters for raw video)

                         * fourcc */

                        case MATROSKA_ID_VIDEOCOLORSPACE: {

                            uint64_t num;

                            if ((res = ebml_read_uint(matroska, &id,

                                                      &num)) < 0)

                                break;

                            videotrack->fourcc = num;

                            break;

                        }

                        default:

                            av_log(matroska->ctx, AV_LOG_INFO,

                                   "Unknown video track header entry "

                                   "0x%x - ignoring\n", id);

                            /* pass-through */

                        case EBML_ID_VOID:

                            res = ebml_read_skip(matroska);

                            break;

                    }

                    if (matroska->level_up) {

                        matroska->level_up--;

                        break;

                    }

                }

                break;

            }

            /* tracktype specific stuff for audio */

            case MATROSKA_ID_TRACKAUDIO: {

                MatroskaAudioTrack *audiotrack;

                if (!track->type)

                    track->type = MATROSKA_TRACK_TYPE_AUDIO;

                if (track->type != MATROSKA_TRACK_TYPE_AUDIO) {

                    av_log(matroska->ctx, AV_LOG_INFO,

                           "audio data in non-audio track - ignoring\n");

                    res = AVERROR_INVALIDDATA;

                    break;

                } else if ((res = ebml_read_master(matroska, &id)) < 0)

                    break;

                audiotrack = (MatroskaAudioTrack *)track;

                audiotrack->channels = 1;

                audiotrack->samplerate = 8000;

                while (res == 0) {

                    if (!(id = ebml_peek_id(matroska, &matroska->level_up))) {

                        res = AVERROR(EIO);

                        break;

                    } else if (matroska->level_up > 0) {

                        matroska->level_up--;

                        break;

                    }

                    switch (id) {

                        /* samplerate */

                        case MATROSKA_ID_AUDIOSAMPLINGFREQ: {

                            double num;

                            if ((res = ebml_read_float(matroska, &id,

                                                       &num)) < 0)

                                break;

                            audiotrack->internal_samplerate =

                            audiotrack->samplerate = num;

                            break;

                        }

                        case MATROSKA_ID_AUDIOOUTSAMPLINGFREQ: {

                            double num;

                            if ((res = ebml_read_float(matroska, &id,

                                                       &num)) < 0)

                                break;

                            audiotrack->samplerate = num;

                            break;

                        }

                            /* bitdepth */

                        case MATROSKA_ID_AUDIOBITDEPTH: {

                            uint64_t num;

                            if ((res = ebml_read_uint(matroska, &id,

                                                      &num)) < 0)

                                break;

                            audiotrack->bitdepth = num;

                            break;

                        }

                            /* channels */

                        case MATROSKA_ID_AUDIOCHANNELS: {

                            uint64_t num;

                            if ((res = ebml_read_uint(matroska, &id,

                                                      &num)) < 0)

                                break;

                            audiotrack->channels = num;

                            break;

                        }

                        default:

                            av_log(matroska->ctx, AV_LOG_INFO,

                                   "Unknown audio track header entry "

                                   "0x%x - ignoring\n", id);

                            /* pass-through */

                        case EBML_ID_VOID:

                            res = ebml_read_skip(matroska);

                            break;

                    }

                    if (matroska->level_up) {

                        matroska->level_up--;

                        break;

                    }

                }

                break;

            }

                /* codec identifier */

            case MATROSKA_ID_CODECID: {

                char *text;

                if ((res = ebml_read_ascii(matroska, &id, &text)) < 0)

                    break;

                track->codec_id = text;

                break;

            }

                /* codec private data */

            case MATROSKA_ID_CODECPRIVATE: {

                uint8_t *data;

                int size;

                if ((res = ebml_read_binary(matroska, &id, &data, &size) < 0))

                    break;

                track->codec_priv = data;

                track->codec_priv_size = size;

                break;

            }

                /* name of the codec */

            case MATROSKA_ID_CODECNAME: {

                char *text;

                if ((res = ebml_read_utf8(matroska, &id, &text)) < 0)

                    break;

                track->codec_name = text;

                break;

            }

                /* name of this track */

            case MATROSKA_ID_TRACKNAME: {

                char *text;

                if ((res = ebml_read_utf8(matroska, &id, &text)) < 0)

                    break;

                track->name = text;

                break;

            }

                /* language (matters for audio/subtitles, mostly) */

            case MATROSKA_ID_TRACKLANGUAGE: {

                char *text, *end;

                if ((res = ebml_read_utf8(matroska, &id, &text)) < 0)

                    break;

                if ((end = strchr(text, '-')))

                    *end = '\0';

                if (strlen(text) == 3)

                    strcpy(track->language, text);

                av_free(text);

                break;

            }

                /* whether this is actually used */

            case MATROSKA_ID_TRACKFLAGENABLED: {

                uint64_t num;

                if ((res = ebml_read_uint(matroska, &id, &num)) < 0)

                    break;

                if (num)

                    track->flags |= MATROSKA_TRACK_ENABLED;

                else

                    track->flags &= ~MATROSKA_TRACK_ENABLED;

                break;

            }

                /* whether it's the default for this track type */

            case MATROSKA_ID_TRACKFLAGDEFAULT: {

                uint64_t num;

                if ((res = ebml_read_uint(matroska, &id, &num)) < 0)

                    break;

                if (num)

                    track->flags |= MATROSKA_TRACK_DEFAULT;

                else

                    track->flags &= ~MATROSKA_TRACK_DEFAULT;

                break;

            }

                /* lacing (like MPEG, where blocks don't end/start on frame

                 * boundaries) */

            case MATROSKA_ID_TRACKFLAGLACING: {

                uint64_t num;

                if ((res = ebml_read_uint(matroska, &id, &num)) < 0)

                    break;

                if (num)

                    track->flags |= MATROSKA_TRACK_LACING;

                else

                    track->flags &= ~MATROSKA_TRACK_LACING;

                break;

            }

                /* default length (in time) of one data block in this track */

            case MATROSKA_ID_TRACKDEFAULTDURATION: {

                uint64_t num;

                if ((res = ebml_read_uint(matroska, &id, &num)) < 0)

                    break;

                track->default_duration = num;

                break;

            }

            case MATROSKA_ID_TRACKCONTENTENCODINGS: {

                if ((res = ebml_read_master(matroska, &id)) < 0)

                    break;

                while (res == 0) {

                    if (!(id = ebml_peek_id(matroska, &matroska->level_up))) {

                        res = AVERROR(EIO);

                        break;

                    } else if (matroska->level_up > 0) {

                        matroska->level_up--;

                        break;

                    }

                    switch (id) {

                        case MATROSKA_ID_TRACKCONTENTENCODING: {

                            int encoding_scope = 1;

                            if ((res = ebml_read_master(matroska, &id)) < 0)

                                break;

                            while (res == 0) {

                                if (!(id = ebml_peek_id(matroska, &matroska->level_up))) {

                                    res = AVERROR(EIO);

                                    break;

                                } else if (matroska->level_up > 0) {

                                    matroska->level_up--;

                                    break;

                                }

                                switch (id) {

                                    case MATROSKA_ID_ENCODINGSCOPE: {

                                        uint64_t num;

                                        if ((res = ebml_read_uint(matroska, &id, &num)) < 0)

                                            break;

                                        encoding_scope = num;

                                        break;

                                    }

                                    case MATROSKA_ID_ENCODINGTYPE: {

                                        uint64_t num;

                                        if ((res = ebml_read_uint(matroska, &id, &num)) < 0)

                                            break;

                                        if (num)

                                            av_log(matroska->ctx, AV_LOG_ERROR,

                                                   "Unsupported encoding type");

                                        break;

                                    }

                                    case MATROSKA_ID_ENCODINGCOMPRESSION: {

                                        if ((res = ebml_read_master(matroska, &id)) < 0)

                                            break;

                                        while (res == 0) {

                                            if (!(id = ebml_peek_id(matroska, &matroska->level_up))) {

                                                res = AVERROR(EIO);

                                                break;

                                            } else if (matroska->level_up > 0) {

                                                matroska->level_up--;

                                                break;

                                            }

                                            switch (id) {

                                                case MATROSKA_ID_ENCODINGCOMPALGO: {

                                                    uint64_t num;

                                                    if ((res = ebml_read_uint(matroska, &id, &num)) < 0)

                                                        break;

                                                    if (num != MATROSKA_TRACK_ENCODING_COMP_HEADERSTRIP &&

#ifdef CONFIG_ZLIB

                                                        num != MATROSKA_TRACK_ENCODING_COMP_ZLIB &&

#endif

#ifdef CONFIG_BZLIB

                                                        num != MATROSKA_TRACK_ENCODING_COMP_BZLIB &&

#endif

                                                        num != MATROSKA_TRACK_ENCODING_COMP_LZO)

                                                        av_log(matroska->ctx, AV_LOG_ERROR,

                                                               "Unsupported compression algo\n");

                                                    track->encoding_algo = num;

                                                    break;

                                                }

                                                case MATROSKA_ID_ENCODINGCOMPSETTINGS: {

                                                    uint8_t *data;

                                                    int size;

                                                    if ((res = ebml_read_binary(matroska, &id, &data, &size) < 0))

                                                        break;

                                                    track->encoding_settings = data;

                                                    track->encoding_settings_len = size;

                                                    break;

                                                }

                                                default:

                                                    av_log(matroska->ctx, AV_LOG_INFO,

                                                           "Unknown compression header entry "

                                                           "0x%x - ignoring\n", id);

                                                    /* pass-through */

                                                case EBML_ID_VOID:

                                                    res = ebml_read_skip(matroska);

                                                    break;

                                            }

                                            if (matroska->level_up) {

                                                matroska->level_up--;

                                                break;

                                            }

                                        }

                                        break;

                                    }

                                    default:

                                        av_log(matroska->ctx, AV_LOG_INFO,

                                               "Unknown content encoding header entry "

                                               "0x%x - ignoring\n", id);

                                        /* pass-through */

                                    case EBML_ID_VOID:

                                        res = ebml_read_skip(matroska);

                                        break;

                                }

                                if (matroska->level_up) {

                                    matroska->level_up--;

                                    break;

                                }

                            }

                            track->encoding_scope = encoding_scope;

                            break;

                        }

                        default:

                            av_log(matroska->ctx, AV_LOG_INFO,

                                   "Unknown content encodings header entry "

                                   "0x%x - ignoring\n", id);

                            /* pass-through */

                        case EBML_ID_VOID:

                            res = ebml_read_skip(matroska);

                            break;

                    }

                    if (matroska->level_up) {

                        matroska->level_up--;

                        break;

                    }

                }

                break;

            }

            case MATROSKA_ID_TRACKTIMECODESCALE: {

                double num;

                if ((res = ebml_read_float(matroska, &id, &num)) < 0)

                    break;

                track->time_scale = num;

                break;

            }

            default:

                av_log(matroska->ctx, AV_LOG_INFO,

                       "Unknown track header entry 0x%x - ignoring\n", id);

                /* pass-through */

            case EBML_ID_VOID:

            /* we ignore these because they're nothing useful. */

            case MATROSKA_ID_TRACKFLAGFORCED:

            case MATROSKA_ID_CODECDECODEALL:

            case MATROSKA_ID_CODECINFOURL:

            case MATROSKA_ID_CODECDOWNLOADURL:

            case MATROSKA_ID_TRACKMINCACHE:

            case MATROSKA_ID_TRACKMAXCACHE:

                res = ebml_read_skip(matroska);

                break;

        }

        if (matroska->level_up) {

            matroska->level_up--;

            break;

        }

    }

    return res;

}


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

{

    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 chmod(rpath(fs_ctx, path), credp->fc_mode);

    }

    return -1;

}


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

{

    DeviceClass *dc = DEVICE_CLASS(klass);

    USBDeviceClass *uc = USB_DEVICE_CLASS(klass);

    uc->realize = usb_msd_realize_storage;

    dc->props = msd_properties;

}


void coroutine_fn qemu_co_mutex_unlock(CoMutex *mutex)

{

    Coroutine *self = qemu_coroutine_self();

    trace_qemu_co_mutex_unlock_entry(mutex, self);

    assert(mutex->locked);

    assert(mutex->holder == self);

    assert(qemu_in_coroutine());

    mutex->holder = NULL;

    self->locks_held--;

    if (atomic_fetch_dec(&mutex->locked) == 1) {

        /* No waiting qemu_co_mutex_lock().  Pfew, that was easy!  */

        return;

    }

    for (;;) {

        CoWaitRecord *to_wake = pop_waiter(mutex);

        unsigned our_handoff;

        if (to_wake) {

            Coroutine *co = to_wake->co;

            aio_co_wake(co);

            break;

        }

        /* Some concurrent lock() is in progress (we know this because

         * mutex->locked was >1) but it hasn't yet put itself on the wait

         * queue.  Pick a sequence number for the handoff protocol (not 0).

         */

        if (++mutex->sequence == 0) {

            mutex->sequence = 1;

        }

        our_handoff = mutex->sequence;

        atomic_mb_set(&mutex->handoff, our_handoff);

        if (!has_waiters(mutex)) {

            /* The concurrent lock has not added itself yet, so it

             * will be able to pick our handoff.

             */

            break;

        }

        /* Try to do the handoff protocol ourselves; if somebody else has

         * already taken it, however, we're done and they're responsible.

         */

        if (atomic_cmpxchg(&mutex->handoff, our_handoff, 0) != our_handoff) {

            break;

        }

    }

    trace_qemu_co_mutex_unlock_return(mutex, self);

}


inline static void RENAME(hcscale)(uint16_t *dst, int dstWidth,

				uint8_t *src1, uint8_t *src2, int srcW, int xInc)

{

#ifdef HAVE_MMX

	// use the new MMX scaler if th mmx2 cant be used (its faster than the x86asm one)

    if(sws_flags != SWS_FAST_BILINEAR || (!canMMX2BeUsed))

#else

    if(sws_flags != SWS_FAST_BILINEAR)

#endif

    {

    	RENAME(hScale)(dst     , dstWidth, src1, srcW, xInc, hChrFilter, hChrFilterPos, hChrFilterSize);

    	RENAME(hScale)(dst+2048, dstWidth, src2, srcW, xInc, hChrFilter, hChrFilterPos, hChrFilterSize);

    }

    else // Fast Bilinear upscale / crap downscale

    {

#ifdef ARCH_X86

#ifdef HAVE_MMX2

	int i;

	if(canMMX2BeUsed)

	{

		asm volatile(

		"pxor %%mm7, %%mm7		\n\t"

		"pxor %%mm2, %%mm2		\n\t" // 2*xalpha

		"movd %5, %%mm6			\n\t" // xInc&0xFFFF

		"punpcklwd %%mm6, %%mm6		\n\t"

		"punpcklwd %%mm6, %%mm6		\n\t"

		"movq %%mm6, %%mm2		\n\t"

		"psllq $16, %%mm2		\n\t"

		"paddw %%mm6, %%mm2		\n\t"

		"psllq $16, %%mm2		\n\t"

		"paddw %%mm6, %%mm2		\n\t"

		"psllq $16, %%mm2		\n\t" //0,t,2t,3t		t=xInc&0xFFFF

		"movq %%mm2, "MANGLE(temp0)"	\n\t"

		"movd %4, %%mm6			\n\t" //(xInc*4)&0xFFFF

		"punpcklwd %%mm6, %%mm6		\n\t"

		"punpcklwd %%mm6, %%mm6		\n\t"

		"xorl %%eax, %%eax		\n\t" // i

		"movl %0, %%esi			\n\t" // src

		"movl %1, %%edi			\n\t" // buf1

		"movl %3, %%edx			\n\t" // (xInc*4)>>16

		"xorl %%ecx, %%ecx		\n\t"

		"xorl %%ebx, %%ebx		\n\t"

		"movw %4, %%bx			\n\t" // (xInc*4)&0xFFFF

#define FUNNYUVCODE \

			PREFETCH" 1024(%%esi)		\n\t"\

			PREFETCH" 1056(%%esi)		\n\t"\

			PREFETCH" 1088(%%esi)		\n\t"\

			"call "MANGLE(funnyUVCode)"	\n\t"\

			"movq "MANGLE(temp0)", %%mm2	\n\t"\

			"xorl %%ecx, %%ecx		\n\t"

FUNNYUVCODE

FUNNYUVCODE

FUNNYUVCODE

FUNNYUVCODE

FUNNYUVCODE

FUNNYUVCODE

FUNNYUVCODE

FUNNYUVCODE

		"xorl %%eax, %%eax		\n\t" // i

		"movl %6, %%esi			\n\t" // src

		"movl %1, %%edi			\n\t" // buf1

		"addl $4096, %%edi		\n\t"

FUNNYUVCODE

FUNNYUVCODE

FUNNYUVCODE

FUNNYUVCODE

FUNNYUVCODE

FUNNYUVCODE

FUNNYUVCODE

FUNNYUVCODE

		:: "m" (src1), "m" (dst), "m" (dstWidth), "m" ((xInc*4)>>16),

		  "m" ((xInc*4)&0xFFFF), "m" (xInc&0xFFFF), "m" (src2)

		: "%eax", "%ebx", "%ecx", "%edx", "%esi", "%edi"

	);

		for(i=dstWidth-1; (i*xInc)>>16 >=srcW-1; i--)

		{

//			printf("%d %d %d\n", dstWidth, i, srcW);

			dst[i] = src1[srcW-1]*128;

			dst[i+2048] = src2[srcW-1]*128;

		}

	}

	else

	{

#endif

	asm volatile(

		"xorl %%eax, %%eax		\n\t" // i

		"xorl %%ebx, %%ebx		\n\t" // xx

		"xorl %%ecx, %%ecx		\n\t" // 2*xalpha

		".balign 16			\n\t"

		"1:				\n\t"

		"movl %0, %%esi			\n\t"

		"movzbl  (%%esi, %%ebx), %%edi	\n\t" //src[xx]

		"movzbl 1(%%esi, %%ebx), %%esi	\n\t" //src[xx+1]

		"subl %%edi, %%esi		\n\t" //src[xx+1] - src[xx]

		"imull %%ecx, %%esi		\n\t" //(src[xx+1] - src[xx])*2*xalpha

		"shll $16, %%edi		\n\t"

		"addl %%edi, %%esi		\n\t" //src[xx+1]*2*xalpha + src[xx]*(1-2*xalpha)

		"movl %1, %%edi			\n\t"

		"shrl $9, %%esi			\n\t"

		"movw %%si, (%%edi, %%eax, 2)	\n\t"

		"movzbl  (%5, %%ebx), %%edi	\n\t" //src[xx]

		"movzbl 1(%5, %%ebx), %%esi	\n\t" //src[xx+1]

		"subl %%edi, %%esi		\n\t" //src[xx+1] - src[xx]

		"imull %%ecx, %%esi		\n\t" //(src[xx+1] - src[xx])*2*xalpha

		"shll $16, %%edi		\n\t"

		"addl %%edi, %%esi		\n\t" //src[xx+1]*2*xalpha + src[xx]*(1-2*xalpha)

		"movl %1, %%edi			\n\t"

		"shrl $9, %%esi			\n\t"

		"movw %%si, 4096(%%edi, %%eax, 2)\n\t"

		"addw %4, %%cx			\n\t" //2*xalpha += xInc&0xFF

		"adcl %3, %%ebx			\n\t" //xx+= xInc>>8 + carry

		"addl $1, %%eax			\n\t"

		"cmpl %2, %%eax			\n\t"

		" jb 1b				\n\t"

		:: "m" (src1), "m" (dst), "m" (dstWidth), "m" (xInc>>16), "m" (xInc&0xFFFF),

		"r" (src2)

		: "%eax", "%ebx", "%ecx", "%edi", "%esi"

		);

#ifdef HAVE_MMX2

	} //if MMX2 cant be used

#endif

#else

	int i;

	unsigned int xpos=0;

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

	{

		register unsigned int xx=xpos>>16;

		register unsigned int xalpha=(xpos&0xFFFF)>>9;

		dst[i]=(src1[xx]*(xalpha^127)+src1[xx+1]*xalpha);

		dst[i+2048]=(src2[xx]*(xalpha^127)+src2[xx+1]*xalpha);

/* slower

	  dst[i]= (src1[xx]<<7) + (src1[xx+1] - src1[xx])*xalpha;

	  dst[i+2048]=(src2[xx]<<7) + (src2[xx+1] - src2[xx])*xalpha;

*/

		xpos+=xInc;

	}

#endif

   }

}


static uint32_t nvram_readb (void *opaque, target_phys_addr_t addr)

{

    ds1225y_t *NVRAM = opaque;

    int64_t pos;

    pos = addr - NVRAM->mem_base;

    if (addr >= NVRAM->capacity)

        addr -= NVRAM->capacity;

    if (!ds1225y_set_to_mode(NVRAM, readmode, "rb"))

        return 0;

    qemu_fseek(NVRAM->file, pos, SEEK_SET);

    return (uint32_t)qemu_get_byte(NVRAM->file);

}


static int decode_plane10(UtvideoContext *c, int plane_no,

                          uint16_t *dst, int step, ptrdiff_t stride,

                          int width, int height,

                          const uint8_t *src, const uint8_t *huff,

                          int use_pred)

{

    int i, j, slice, pix, ret;

    int sstart, send;

    VLC vlc;

    GetBitContext gb;

    int prev, fsym;

    if ((ret = build_huff10(huff, &vlc, &fsym)) < 0) {

        av_log(c->avctx, AV_LOG_ERROR, "Cannot build Huffman codes\n");

        return ret;

    }

    if (fsym >= 0) { // build_huff reported a symbol to fill slices with

        send = 0;

        for (slice = 0; slice < c->slices; slice++) {

            uint16_t *dest;

            sstart = send;

            send   = (height * (slice + 1) / c->slices);

            dest   = dst + sstart * stride;

            prev = 0x200;

            for (j = sstart; j < send; j++) {

                for (i = 0; i < width * step; i += step) {

                    pix = fsym;

                    if (use_pred) {

                        prev += pix;

                        prev &= 0x3FF;

                        pix   = prev;

                    }

                    dest[i] = pix;

                }

                dest += stride;

            }

        }

        return 0;

    }

    send = 0;

    for (slice = 0; slice < c->slices; slice++) {

        uint16_t *dest;

        int slice_data_start, slice_data_end, slice_size;

        sstart = send;

        send   = (height * (slice + 1) / c->slices);

        dest   = dst + sstart * stride;

        // slice offset and size validation was done earlier

        slice_data_start = slice ? AV_RL32(src + slice * 4 - 4) : 0;

        slice_data_end   = AV_RL32(src + slice * 4);

        slice_size       = slice_data_end - slice_data_start;

        if (!slice_size) {

            av_log(c->avctx, AV_LOG_ERROR, "Plane has more than one symbol "

                   "yet a slice has a length of zero.\n");

            goto fail;

        }

        memset(c->slice_bits + slice_size, 0, AV_INPUT_BUFFER_PADDING_SIZE);

        c->bdsp.bswap_buf((uint32_t *) c->slice_bits,

                          (uint32_t *)(src + slice_data_start + c->slices * 4),

                          (slice_data_end - slice_data_start + 3) >> 2);

        init_get_bits(&gb, c->slice_bits, slice_size * 8);

        prev = 0x200;

        for (j = sstart; j < send; j++) {

            for (i = 0; i < width * step; i += step) {

                pix = get_vlc2(&gb, vlc.table, VLC_BITS, 3);

                if (pix < 0) {

                    av_log(c->avctx, AV_LOG_ERROR, "Decoding error\n");

                    goto fail;

                }

                if (use_pred) {

                    prev += pix;

                    prev &= 0x3FF;

                    pix   = prev;

                }

                dest[i] = pix;

            }

            dest += stride;

            if (get_bits_left(&gb) < 0) {

                av_log(c->avctx, AV_LOG_ERROR,

                        "Slice decoding ran out of bits\n");

                goto fail;

            }

        }

        if (get_bits_left(&gb) > 32)

            av_log(c->avctx, AV_LOG_WARNING,

                   "%d bits left after decoding slice\n", get_bits_left(&gb));

    }

    ff_free_vlc(&vlc);

    return 0;

fail:

    ff_free_vlc(&vlc);

    return AVERROR_INVALIDDATA;

}


static int encode_slice(AVCodecContext *avctx, const AVFrame *pic,

                        PutBitContext *pb,

                        int sizes[4], int x, int y, int quant,

                        int mbs_per_slice)

{

    ProresContext *ctx = avctx->priv_data;

    int i, xp, yp;

    int total_size = 0;

    const uint16_t *src;

    int slice_width_factor = av_log2(mbs_per_slice);

    int num_cblocks, pwidth;

    int plane_factor, is_chroma;

    for (i = 0; i < ctx->num_planes; i++) {

        is_chroma    = (i == 1 || i == 2);

        plane_factor = slice_width_factor + 2;

        if (is_chroma)

            plane_factor += ctx->chroma_factor - 3;

        if (!is_chroma || ctx->chroma_factor == CFACTOR_Y444) {

            xp          = x << 4;

            yp          = y << 4;

            num_cblocks = 4;

            pwidth      = avctx->width;

        } else {

            xp          = x << 3;

            yp          = y << 4;

            num_cblocks = 2;

            pwidth      = avctx->width >> 1;

        }

        src = (const uint16_t*)(pic->data[i] + yp * pic->linesize[i]) + xp;

        get_slice_data(ctx, src, pic->linesize[i], xp, yp,

                       pwidth, avctx->height, ctx->blocks[0],

                       mbs_per_slice, num_cblocks);

        sizes[i] = encode_slice_plane(ctx, pb, src, pic->linesize[i],

                                      mbs_per_slice, ctx->blocks[0],

                                      num_cblocks, plane_factor,

                                      ctx->quants[quant]);

        total_size += sizes[i];

    }

    return total_size;

}


static int ogg_write_header(AVFormatContext *s)

{

    OGGStreamContext *oggstream;

    int i, j;

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

        AVStream *st = s->streams[i];

        unsigned serial_num = i;

        if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO) {

            if (st->codec->codec_id == AV_CODEC_ID_OPUS)

                /* Opus requires a fixed 48kHz clock */

                avpriv_set_pts_info(st, 64, 1, 48000);

            else

                avpriv_set_pts_info(st, 64, 1, st->codec->sample_rate);

        } else if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO)

            avpriv_set_pts_info(st, 64, st->codec->time_base.num, st->codec->time_base.den);

        if (st->codec->codec_id != AV_CODEC_ID_VORBIS &&

            st->codec->codec_id != AV_CODEC_ID_THEORA &&

            st->codec->codec_id != AV_CODEC_ID_SPEEX  &&

            st->codec->codec_id != AV_CODEC_ID_FLAC   &&

            st->codec->codec_id != AV_CODEC_ID_OPUS) {

            av_log(s, AV_LOG_ERROR, "Unsupported codec id in stream %d\n", i);

            return -1;

        }

        if (!st->codec->extradata || !st->codec->extradata_size) {

            av_log(s, AV_LOG_ERROR, "No extradata present\n");

            return -1;

        }

        oggstream = av_mallocz(sizeof(*oggstream));

        oggstream->page.stream_index = i;

        if (!(st->codec->flags & CODEC_FLAG_BITEXACT))

            do {

                serial_num = av_get_random_seed();

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

                    OGGStreamContext *sc = s->streams[j]->priv_data;

                    if (serial_num == sc->serial_num)

                        break;

                }

            } while (j < i);

        oggstream->serial_num = serial_num;

        st->priv_data = oggstream;

        if (st->codec->codec_id == AV_CODEC_ID_FLAC) {

            int err = ogg_build_flac_headers(st->codec, oggstream,

                                             st->codec->flags & CODEC_FLAG_BITEXACT,

                                             &s->metadata);

            if (err) {

                av_log(s, AV_LOG_ERROR, "Error writing FLAC headers\n");

                av_freep(&st->priv_data);

                return err;

            }

        } else if (st->codec->codec_id == AV_CODEC_ID_SPEEX) {

            int err = ogg_build_speex_headers(st->codec, oggstream,

                                              st->codec->flags & CODEC_FLAG_BITEXACT,

                                              &s->metadata);

            if (err) {

                av_log(s, AV_LOG_ERROR, "Error writing Speex headers\n");

                av_freep(&st->priv_data);

                return err;

            }

        } else if (st->codec->codec_id == AV_CODEC_ID_OPUS) {

            int err = ogg_build_opus_headers(st->codec, oggstream,

                                             st->codec->flags & CODEC_FLAG_BITEXACT,

                                             &s->metadata);

            if (err) {

                av_log(s, AV_LOG_ERROR, "Error writing Opus headers\n");

                av_freep(&st->priv_data);

                return err;

            }

        } else {

            uint8_t *p;

            const char *cstr = st->codec->codec_id == AV_CODEC_ID_VORBIS ? "vorbis" : "theora";

            int header_type = st->codec->codec_id == AV_CODEC_ID_VORBIS ? 3 : 0x81;

            int framing_bit = st->codec->codec_id == AV_CODEC_ID_VORBIS ? 1 : 0;

            if (avpriv_split_xiph_headers(st->codec->extradata, st->codec->extradata_size,

                                      st->codec->codec_id == AV_CODEC_ID_VORBIS ? 30 : 42,

                                      oggstream->header, oggstream->header_len) < 0) {

                av_log(s, AV_LOG_ERROR, "Extradata corrupted\n");

                av_freep(&st->priv_data);

                return -1;

            }

            p = ogg_write_vorbiscomment(7, st->codec->flags & CODEC_FLAG_BITEXACT,

                                        &oggstream->header_len[1], &s->metadata,

                                        framing_bit);

            oggstream->header[1] = p;

            if (!p)

                return AVERROR(ENOMEM);

            bytestream_put_byte(&p, header_type);

            bytestream_put_buffer(&p, cstr, 6);

            if (st->codec->codec_id == AV_CODEC_ID_THEORA) {

                /** KFGSHIFT is the width of the less significant section of the granule position

                    The less significant section is the frame count since the last keyframe */

                oggstream->kfgshift = ((oggstream->header[0][40]&3)<<3)|(oggstream->header[0][41]>>5);

                oggstream->vrev = oggstream->header[0][9];

                av_log(s, AV_LOG_DEBUG, "theora kfgshift %d, vrev %d\n",

                       oggstream->kfgshift, oggstream->vrev);

            }

        }

    }

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

        OGGStreamContext *oggstream = s->streams[j]->priv_data;

        ogg_buffer_data(s, s->streams[j], oggstream->header[0],

                        oggstream->header_len[0], 0, 1);

        oggstream->page.flags |= 2; // bos

        ogg_buffer_page(s, oggstream);

    }

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

        AVStream *st = s->streams[j];

        OGGStreamContext *oggstream = st->priv_data;

        for (i = 1; i < 3; i++) {

            if (oggstream && oggstream->header_len[i])

                ogg_buffer_data(s, st, oggstream->header[i],

                                oggstream->header_len[i], 0, 1);

        }

        ogg_buffer_page(s, oggstream);

    }

    return 0;

}


static void test_dma_fragmented(void)

{

    AHCIQState *ahci;

    AHCICommand *cmd;

    uint8_t px;

    size_t bufsize = 4096;

    unsigned char *tx = g_malloc(bufsize);

    unsigned char *rx = g_malloc0(bufsize);

    uint64_t ptr;

    ahci = ahci_boot_and_enable();

    px = ahci_port_select(ahci);

    ahci_port_clear(ahci, px);

    /* create pattern */

    generate_pattern(tx, bufsize, AHCI_SECTOR_SIZE);

    /* Create a DMA buffer in guest memory, and write our pattern to it. */

    ptr = guest_alloc(ahci->parent->alloc, bufsize);

    g_assert(ptr);

    memwrite(ptr, tx, bufsize);

    cmd = ahci_command_create(CMD_WRITE_DMA);

    ahci_command_adjust(cmd, 0, ptr, bufsize, 32);

    ahci_command_commit(ahci, cmd, px);

    ahci_command_issue(ahci, cmd);

    ahci_command_verify(ahci, cmd);

    g_free(cmd);

    cmd = ahci_command_create(CMD_READ_DMA);

    ahci_command_adjust(cmd, 0, ptr, bufsize, 32);

    ahci_command_commit(ahci, cmd, px);

    ahci_command_issue(ahci, cmd);

    ahci_command_verify(ahci, cmd);

    g_free(cmd);

    /* Read back the guest's receive buffer into local memory */

    memread(ptr, rx, bufsize);

    guest_free(ahci->parent->alloc, ptr);

    g_assert_cmphex(memcmp(tx, rx, bufsize), ==, 0);

    ahci_shutdown(ahci);

    g_free(rx);

    g_free(tx);

}


static long do_rt_sigreturn_v1(CPUARMState *env)

{

        abi_ulong frame_addr;

        struct rt_sigframe_v1 *frame = NULL;

        sigset_t host_set;

	/*

	 * Since we stacked the signal on a 64-bit boundary,

	 * then 'sp' should be word aligned here.  If it's

	 * not, then the user is trying to mess with us.

	 */

        frame_addr = env->regs[13];

        if (frame_addr & 7) {

            goto badframe;

        }

	if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))

                goto badframe;

        target_to_host_sigset(&host_set, &frame->uc.tuc_sigmask);

        sigprocmask(SIG_SETMASK, &host_set, NULL);

	if (restore_sigcontext(env, &frame->uc.tuc_mcontext))

		goto badframe;

	if (do_sigaltstack(frame_addr + offsetof(struct rt_sigframe_v1, uc.tuc_stack), 0, get_sp_from_cpustate(env)) == -EFAULT)

		goto badframe;

#if 0

	/* Send SIGTRAP if we're single-stepping */

	if (ptrace_cancel_bpt(current))

		send_sig(SIGTRAP, current, 1);

#endif

	unlock_user_struct(frame, frame_addr, 0);

	return env->regs[0];

badframe:

	unlock_user_struct(frame, frame_addr, 0);

        force_sig(TARGET_SIGSEGV /* , current */);

	return 0;

}


int qcow2_cache_flush(BlockDriverState *bs, Qcow2Cache *c)

{

    BDRVQcow2State *s = bs->opaque;

    int result = 0;

    int ret;

    int i;

    trace_qcow2_cache_flush(qemu_coroutine_self(), c == s->l2_table_cache);

    for (i = 0; i < c->size; i++) {

        ret = qcow2_cache_entry_flush(bs, c, i);

        if (ret < 0 && result != -ENOSPC) {

            result = ret;

        }

    }

    if (result == 0) {

        ret = bdrv_flush(bs->file->bs);

        if (ret < 0) {

            result = ret;

        }

    }

    return result;

}


MemoryRegion *pci_address_space_io(PCIDevice *dev)

{

    return dev->bus->address_space_io;

}


static void lm32_uclinux_init(QEMUMachineInitArgs *args)

{

    const char *cpu_model = args->cpu_model;

    const char *kernel_filename = args->kernel_filename;

    const char *kernel_cmdline = args->kernel_cmdline;

    const char *initrd_filename = args->initrd_filename;

    LM32CPU *cpu;

    CPULM32State *env;

    DriveInfo *dinfo;

    MemoryRegion *address_space_mem =  get_system_memory();

    MemoryRegion *phys_ram = g_new(MemoryRegion, 1);

    qemu_irq *cpu_irq, irq[32];

    HWSetup *hw;

    ResetInfo *reset_info;

    int i;

    /* memory map */

    target_phys_addr_t flash_base   = 0x04000000;

    size_t flash_sector_size        = 256 * 1024;

    size_t flash_size               = 32 * 1024 * 1024;

    target_phys_addr_t ram_base     = 0x08000000;

    size_t ram_size                 = 64 * 1024 * 1024;

    target_phys_addr_t uart0_base   = 0x80000000;

    target_phys_addr_t timer0_base  = 0x80002000;

    target_phys_addr_t timer1_base  = 0x80010000;

    target_phys_addr_t timer2_base  = 0x80012000;

    int uart0_irq                   = 0;

    int timer0_irq                  = 1;

    int timer1_irq                  = 20;

    int timer2_irq                  = 21;

    target_phys_addr_t hwsetup_base = 0x0bffe000;

    target_phys_addr_t cmdline_base = 0x0bfff000;

    target_phys_addr_t initrd_base  = 0x08400000;

    size_t initrd_max               = 0x01000000;

    reset_info = g_malloc0(sizeof(ResetInfo));

    if (cpu_model == NULL) {

        cpu_model = "lm32-full";

    }

    cpu = cpu_lm32_init(cpu_model);

    env = &cpu->env;

    reset_info->cpu = cpu;

    reset_info->flash_base = flash_base;

    memory_region_init_ram(phys_ram, "lm32_uclinux.sdram", ram_size);

    vmstate_register_ram_global(phys_ram);

    memory_region_add_subregion(address_space_mem, ram_base, phys_ram);

    dinfo = drive_get(IF_PFLASH, 0, 0);

    /* Spansion S29NS128P */

    pflash_cfi02_register(flash_base, NULL, "lm32_uclinux.flash", flash_size,

                          dinfo ? dinfo->bdrv : NULL, flash_sector_size,

                          flash_size / flash_sector_size, 1, 2,

                          0x01, 0x7e, 0x43, 0x00, 0x555, 0x2aa, 1);

    /* create irq lines */

    cpu_irq = qemu_allocate_irqs(cpu_irq_handler, env, 1);

    env->pic_state = lm32_pic_init(*cpu_irq);

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

        irq[i] = qdev_get_gpio_in(env->pic_state, i);

    }

    sysbus_create_simple("lm32-uart", uart0_base, irq[uart0_irq]);

    sysbus_create_simple("lm32-timer", timer0_base, irq[timer0_irq]);

    sysbus_create_simple("lm32-timer", timer1_base, irq[timer1_irq]);

    sysbus_create_simple("lm32-timer", timer2_base, irq[timer2_irq]);

    /* make sure juart isn't the first chardev */

    env->juart_state = lm32_juart_init();

    reset_info->bootstrap_pc = flash_base;

    if (kernel_filename) {

        uint64_t entry;

        int kernel_size;

        kernel_size = load_elf(kernel_filename, NULL, NULL, &entry, NULL, NULL,

                               1, ELF_MACHINE, 0);

        reset_info->bootstrap_pc = entry;

        if (kernel_size < 0) {

            kernel_size = load_image_targphys(kernel_filename, ram_base,

                                              ram_size);

            reset_info->bootstrap_pc = ram_base;

        }

        if (kernel_size < 0) {

            fprintf(stderr, "qemu: could not load kernel '%s'\n",

                    kernel_filename);

            exit(1);

        }

    }

    /* generate a rom with the hardware description */

    hw = hwsetup_init();

    hwsetup_add_cpu(hw, "LM32", 75000000);

    hwsetup_add_flash(hw, "flash", flash_base, flash_size);

    hwsetup_add_ddr_sdram(hw, "ddr_sdram", ram_base, ram_size);

    hwsetup_add_timer(hw, "timer0", timer0_base, timer0_irq);

    hwsetup_add_timer(hw, "timer1_dev_only", timer1_base, timer1_irq);

    hwsetup_add_timer(hw, "timer2_dev_only", timer2_base, timer2_irq);

    hwsetup_add_uart(hw, "uart", uart0_base, uart0_irq);

    hwsetup_add_trailer(hw);

    hwsetup_create_rom(hw, hwsetup_base);

    hwsetup_free(hw);

    reset_info->hwsetup_base = hwsetup_base;

    if (kernel_cmdline && strlen(kernel_cmdline)) {

        pstrcpy_targphys("cmdline", cmdline_base, TARGET_PAGE_SIZE,

                kernel_cmdline);

        reset_info->cmdline_base = cmdline_base;

    }

    if (initrd_filename) {

        size_t initrd_size;

        initrd_size = load_image_targphys(initrd_filename, initrd_base,

                initrd_max);

        reset_info->initrd_base = initrd_base;

        reset_info->initrd_size = initrd_size;

    }

    qemu_register_reset(main_cpu_reset, reset_info);

}


static void timestamp_put(QDict *qdict)

{

    int err;

    QObject *obj;

    qemu_timeval tv;

    err = qemu_gettimeofday(&tv);

    if (err < 0)

        return;

    obj = qobject_from_jsonf("{ 'seconds': %" PRId64 ", "

                                "'microseconds': %" PRId64 " }",

                                (int64_t) tv.tv_sec, (int64_t) tv.tv_usec);

    assert(obj != NULL);

    qdict_put_obj(qdict, "timestamp", obj);

}


int av_get_cpu_flags(void)

{

    if (checked)

        return flags;

    if (ARCH_AARCH64)

        flags = ff_get_cpu_flags_aarch64();

    if (ARCH_ARM)

        flags = ff_get_cpu_flags_arm();

    if (ARCH_PPC)

        flags = ff_get_cpu_flags_ppc();

    if (ARCH_X86)

        flags = ff_get_cpu_flags_x86();

    checked = 1;

    return flags;

}


static int target_restore_sigframe(CPUARMState *env,

                                   struct target_rt_sigframe *sf)

{

    sigset_t set;

    int i;

    struct target_aux_context *aux =

        (struct target_aux_context *)sf->uc.tuc_mcontext.__reserved;

    uint32_t magic, size, fpsr, fpcr;

    uint64_t pstate;

    target_to_host_sigset(&set, &sf->uc.tuc_sigmask);

    sigprocmask(SIG_SETMASK, &set, NULL);

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

        __get_user(env->xregs[i], &sf->uc.tuc_mcontext.regs[i]);

    }

    __get_user(env->xregs[31], &sf->uc.tuc_mcontext.sp);

    __get_user(env->pc, &sf->uc.tuc_mcontext.pc);

    __get_user(pstate, &sf->uc.tuc_mcontext.pstate);

    pstate_write(env, pstate);

    __get_user(magic, &aux->fpsimd.head.magic);

    __get_user(size, &aux->fpsimd.head.size);

    if (magic != TARGET_FPSIMD_MAGIC

        || size != sizeof(struct target_fpsimd_context)) {

        return 1;

    }

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

#ifdef TARGET_WORDS_BIGENDIAN

        __get_user(env->vfp.regs[i * 2], &aux->fpsimd.vregs[i * 2 + 1]);

        __get_user(env->vfp.regs[i * 2 + 1], &aux->fpsimd.vregs[i * 2]);

#else

        __get_user(env->vfp.regs[i * 2], &aux->fpsimd.vregs[i * 2]);

        __get_user(env->vfp.regs[i * 2 + 1], &aux->fpsimd.vregs[i * 2 + 1]);

#endif

    }

    __get_user(fpsr, &aux->fpsimd.fpsr);

    vfp_set_fpsr(env, fpsr);

    __get_user(fpcr, &aux->fpsimd.fpcr);

    vfp_set_fpcr(env, fpcr);

    return 0;

}


static void reclaim_list_el(struct rcu_head *prcu)

{

    struct list_element *el = container_of(prcu, struct list_element, rcu);

    g_free(el);

    atomic_add(&n_reclaims, 1);

}


uint64_t helper_ld_virt_to_phys (uint64_t virtaddr)

{

    uint64_t tlb_addr, physaddr;

    int index, mmu_idx;

    void *retaddr;

    mmu_idx = cpu_mmu_index(env);

    index = (virtaddr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);

 redo:

    tlb_addr = env->tlb_table[mmu_idx][index].addr_read;

    if ((virtaddr & TARGET_PAGE_MASK) ==

        (tlb_addr & (TARGET_PAGE_MASK | TLB_INVALID_MASK))) {

        physaddr = virtaddr + env->tlb_table[mmu_idx][index].addend;

    } else {

        /* the page is not in the TLB : fill it */

        retaddr = GETPC();

        tlb_fill(virtaddr, 0, mmu_idx, retaddr);

        goto redo;

    }

    return physaddr;

}


static bool less_than_7(void *opaque, int version_id)

{

    return version_id < 7;

}


static void ppc_hash64_set_isi(CPUState *cs, CPUPPCState *env,

                               uint64_t error_code)

{

    bool vpm;

    if (msr_ir) {

        vpm = !!(env->spr[SPR_LPCR] & LPCR_VPM1);

    } else {

        vpm = !!(env->spr[SPR_LPCR] & LPCR_VPM0);

    }

    if (vpm && !msr_hv) {

        cs->exception_index = POWERPC_EXCP_HISI;

    } else {

        cs->exception_index = POWERPC_EXCP_ISI;

    }

    env->error_code = error_code;

}


static int vnc_tls_initialize(void)

{

    static int tlsinitialized = 0;

    if (tlsinitialized)

	return 1;

    if (gnutls_global_init () < 0)

	return 0;

    /* XXX ought to re-generate diffie-hellmen params periodically */

    if (gnutls_dh_params_init (&dh_params) < 0)

	return 0;

    if (gnutls_dh_params_generate2 (dh_params, DH_BITS) < 0)

	return 0;

#if defined(_VNC_DEBUG) && _VNC_DEBUG >= 2

    gnutls_global_set_log_level(10);

    gnutls_global_set_log_function(vnc_debug_gnutls_log);

#endif

    tlsinitialized = 1;

    return 1;

}


void slirp_init(int restricted, struct in_addr vnetwork,

                struct in_addr vnetmask, struct in_addr vhost,

                const char *vhostname, const char *tftp_path,

                const char *bootfile, struct in_addr vdhcp_start,

                struct in_addr vnameserver)

{

    slirp_init_once();

    link_up = 1;

    slirp_restrict = restricted;

    if_init();

    ip_init();

    /* Initialise mbufs *after* setting the MTU */

    m_init();

    vnetwork_addr = vnetwork;

    vnetwork_mask = vnetmask;

    vhost_addr = vhost;

    if (vhostname) {

        pstrcpy(slirp_hostname, sizeof(slirp_hostname), vhostname);

    }

    qemu_free(tftp_prefix);

    tftp_prefix = NULL;

    if (tftp_path) {

        tftp_prefix = qemu_strdup(tftp_path);

    }

    qemu_free(bootp_filename);

    bootp_filename = NULL;

    if (bootfile) {

        bootp_filename = qemu_strdup(bootfile);

    }

    vdhcp_startaddr = vdhcp_start;

    vnameserver_addr = vnameserver;

    register_savevm("slirp", 0, 1, slirp_state_save, slirp_state_load, NULL);

}


static void bswap_phdr(struct elf_phdr *phdr)

{

    bswap32s(&phdr->p_type);            /* Segment type */

    bswaptls(&phdr->p_offset);          /* Segment file offset */

    bswaptls(&phdr->p_vaddr);           /* Segment virtual address */

    bswaptls(&phdr->p_paddr);           /* Segment physical address */

    bswaptls(&phdr->p_filesz);          /* Segment size in file */

    bswaptls(&phdr->p_memsz);           /* Segment size in memory */

    bswap32s(&phdr->p_flags);           /* Segment flags */

    bswaptls(&phdr->p_align);           /* Segment alignment */

}


static uint64_t ahci_idp_read(void *opaque, target_phys_addr_t addr,

                              unsigned size)

{

    AHCIState *s = opaque;

    if (addr == s->idp_offset) {

        /* index register */

        return s->idp_index;

    } else if (addr == s->idp_offset + 4) {

        /* data register - do memory read at location selected by index */

        return ahci_mem_read(opaque, s->idp_index, size);

    } else {

        return 0;

    }

}


int qemu_chr_fe_write(CharDriverState *s, const uint8_t *buf, int len)

{

    return s->chr_write(s, buf, len);

}


static inline void gen_efdabs(DisasContext *ctx)

{

    if (unlikely(!ctx->spe_enabled)) {

        gen_exception(ctx, POWERPC_EXCP_APU);

        return;

    }

#if defined(TARGET_PPC64)

    tcg_gen_andi_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], ~0x8000000000000000LL);

#else

    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);

    tcg_gen_andi_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], ~0x80000000);

#endif

}


static inline void gen_op_mfspr (DisasContext *ctx)

{

    void (*read_cb)(void *opaque, int sprn);

    uint32_t sprn = SPR(ctx->opcode);

#if !defined(CONFIG_USER_ONLY)

    if (ctx->supervisor)

        read_cb = ctx->spr_cb[sprn].oea_read;

    else

#endif

        read_cb = ctx->spr_cb[sprn].uea_read;

    if (likely(read_cb != NULL)) {

        if (likely(read_cb != SPR_NOACCESS)) {

            (*read_cb)(ctx, sprn);

            gen_op_store_T0_gpr(rD(ctx->opcode));

        } else {

            /* Privilege exception */

            if (loglevel != 0) {

                fprintf(logfile, "Trying to read privileged spr %d %03x\n",

                        sprn, sprn);

            }

            printf("Trying to read privileged spr %d %03x\n", sprn, sprn);

            RET_PRIVREG(ctx);

        }

    } else {

        /* Not defined */

        if (loglevel != 0) {

            fprintf(logfile, "Trying to read invalid spr %d %03x\n",

                    sprn, sprn);

        }

        printf("Trying to read invalid spr %d %03x\n", sprn, sprn);

        RET_EXCP(ctx, EXCP_PROGRAM, EXCP_INVAL | EXCP_INVAL_SPR);

    }

}


static void bdrv_do_release_matching_dirty_bitmap(BlockDriverState *bs,

                                                  BdrvDirtyBitmap *bitmap,

                                                  bool only_named)

{

    BdrvDirtyBitmap *bm, *next;

    QLIST_FOREACH_SAFE(bm, &bs->dirty_bitmaps, list, next) {

        if ((!bitmap || bm == bitmap) && (!only_named || bm->name)) {

            assert(!bm->active_iterators);

            assert(!bdrv_dirty_bitmap_frozen(bm));

            assert(!bm->meta);

            QLIST_REMOVE(bm, list);

            hbitmap_free(bm->bitmap);

            g_free(bm->name);

            g_free(bm);

            if (bitmap) {

                return;

            }

        }

    }

    if (bitmap) {

        abort();

    }

}


static uint64_t arm_thistimer_read(void *opaque, target_phys_addr_t addr,

                                   unsigned size)

{

    arm_mptimer_state *s = (arm_mptimer_state *)opaque;

    int id = get_current_cpu(s);

    return timerblock_read(&s->timerblock[id * 2], addr, size);

}


void ff_snow_pred_block(SnowContext *s, uint8_t *dst, uint8_t *tmp, int stride, int sx, int sy, int b_w, int b_h, BlockNode *block, int plane_index, int w, int h){

    if(block->type & BLOCK_INTRA){

        int x, y;

        const unsigned color  = block->color[plane_index];

        const unsigned color4 = color*0x01010101;

        if(b_w==32){

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

                *(uint32_t*)&dst[0 + y*stride]= color4;

                *(uint32_t*)&dst[4 + y*stride]= color4;

                *(uint32_t*)&dst[8 + y*stride]= color4;

                *(uint32_t*)&dst[12+ y*stride]= color4;

                *(uint32_t*)&dst[16+ y*stride]= color4;

                *(uint32_t*)&dst[20+ y*stride]= color4;

                *(uint32_t*)&dst[24+ y*stride]= color4;

                *(uint32_t*)&dst[28+ y*stride]= color4;

            }

        }else if(b_w==16){

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

                *(uint32_t*)&dst[0 + y*stride]= color4;

                *(uint32_t*)&dst[4 + y*stride]= color4;

                *(uint32_t*)&dst[8 + y*stride]= color4;

                *(uint32_t*)&dst[12+ y*stride]= color4;

            }

        }else if(b_w==8){

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

                *(uint32_t*)&dst[0 + y*stride]= color4;

                *(uint32_t*)&dst[4 + y*stride]= color4;

            }

        }else if(b_w==4){

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

                *(uint32_t*)&dst[0 + y*stride]= color4;

            }

        }else{

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

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

                    dst[x + y*stride]= color;

                }

            }

        }

    }else{

        uint8_t *src= s->last_picture[block->ref]->data[plane_index];

        const int scale= plane_index ?  (2*s->mv_scale)>>s->chroma_h_shift : 2*s->mv_scale;

        int mx= block->mx*scale;

        int my= block->my*scale;

        const int dx= mx&15;

        const int dy= my&15;

        const int tab_index= 3 - (b_w>>2) + (b_w>>4);

        sx += (mx>>4) - (HTAPS_MAX/2-1);

        sy += (my>>4) - (HTAPS_MAX/2-1);

        src += sx + sy*stride;

        if(   (unsigned)sx >= FFMAX(w - b_w - (HTAPS_MAX-2), 0)

           || (unsigned)sy >= FFMAX(h - b_h - (HTAPS_MAX-2), 0)){

            s->vdsp.emulated_edge_mc(tmp + MB_SIZE, src, stride, b_w+HTAPS_MAX-1, b_h+HTAPS_MAX-1, sx, sy, w, h);

            src= tmp + MB_SIZE;

        }

        av_assert2(s->chroma_h_shift == s->chroma_v_shift); // only one mv_scale

        av_assert2(b_w>1 && b_h>1);

        av_assert2((tab_index>=0 && tab_index<4) || b_w==32);

        if((dx&3) || (dy&3) || !(b_w == b_h || 2*b_w == b_h || b_w == 2*b_h) || (b_w&(b_w-1)) || !s->plane[plane_index].fast_mc )

            mc_block(&s->plane[plane_index], dst, src, stride, b_w, b_h, dx, dy);

        else if(b_w==32){

            int y;

            for(y=0; y<b_h; y+=16){

                s->h264qpel.put_h264_qpel_pixels_tab[0][dy+(dx>>2)](dst + y*stride, src + 3 + (y+3)*stride,stride);

                s->h264qpel.put_h264_qpel_pixels_tab[0][dy+(dx>>2)](dst + 16 + y*stride, src + 19 + (y+3)*stride,stride);

            }

        }else if(b_w==b_h)

            s->h264qpel.put_h264_qpel_pixels_tab[tab_index  ][dy+(dx>>2)](dst,src + 3 + 3*stride,stride);

        else if(b_w==2*b_h){

            s->h264qpel.put_h264_qpel_pixels_tab[tab_index+1][dy+(dx>>2)](dst    ,src + 3       + 3*stride,stride);

            s->h264qpel.put_h264_qpel_pixels_tab[tab_index+1][dy+(dx>>2)](dst+b_h,src + 3 + b_h + 3*stride,stride);

        }else{

            av_assert2(2*b_w==b_h);

            s->h264qpel.put_h264_qpel_pixels_tab[tab_index  ][dy+(dx>>2)](dst           ,src + 3 + 3*stride           ,stride);

            s->h264qpel.put_h264_qpel_pixels_tab[tab_index  ][dy+(dx>>2)](dst+b_w*stride,src + 3 + 3*stride+b_w*stride,stride);

        }

    }

}


void backup_start(BlockDriverState *bs, BlockDriverState *target,
                  int64_t speed, MirrorSyncMode sync_mode,
                  BlockdevOnError on_source_error,
                  BlockdevOnError on_target_error,
                  BlockCompletionFunc *cb, void *opaque,
                  Error **errp)
{
    int64_t len;
    assert(bs);
    assert(target);
    assert(cb);
    if (bs == target) {
        error_setg(errp, "Source and target cannot be the same");
    if ((on_source_error == BLOCKDEV_ON_ERROR_STOP ||
         on_source_error == BLOCKDEV_ON_ERROR_ENOSPC) &&
        !bdrv_iostatus_is_enabled(bs)) {
        error_set(errp, QERR_INVALID_PARAMETER, "on-source-error");
    len = bdrv_getlength(bs);
    if (len < 0) {
        error_setg_errno(errp, -len, "unable to get length for '%s'",
    BackupBlockJob *job = block_job_create(&backup_job_driver, bs, speed,
                                           cb, opaque, errp);
    if (!job) {
    bdrv_op_block_all(target, job->common.blocker);
    job->on_source_error = on_source_error;
    job->on_target_error = on_target_error;
    job->target = target;
    job->sync_mode = sync_mode;
    job->common.len = len;
    job->common.co = qemu_coroutine_create(backup_run);
    qemu_coroutine_enter(job->common.co, job);


static int decode_pic_timing(HEVCSEIContext *s, GetBitContext *gb, const HEVCParamSets *ps,

                             void *logctx)

{

    HEVCSEIPictureTiming *h = &s->picture_timing;

    HEVCSPS *sps;

    if (!ps->sps_list[s->active_seq_parameter_set_id])

        return(AVERROR(ENOMEM));

    sps = (HEVCSPS*)ps->sps_list[s->active_seq_parameter_set_id]->data;

    if (sps->vui.frame_field_info_present_flag) {

        int pic_struct = get_bits(gb, 4);

        h->picture_struct = AV_PICTURE_STRUCTURE_UNKNOWN;

        if (pic_struct == 2) {

            av_log(logctx, AV_LOG_DEBUG, "BOTTOM Field\n");

            h->picture_struct = AV_PICTURE_STRUCTURE_BOTTOM_FIELD;

        } else if (pic_struct == 1) {

            av_log(logctx, AV_LOG_DEBUG, "TOP Field\n");

            h->picture_struct = AV_PICTURE_STRUCTURE_TOP_FIELD;

        }

        get_bits(gb, 2);                   // source_scan_type

        get_bits(gb, 1);                   // duplicate_flag

    }

    return 1;

}


static int film_read_header(AVFormatContext *s)

{

    FilmDemuxContext *film = s->priv_data;

    AVIOContext *pb = s->pb;

    AVStream *st;

    unsigned char scratch[256];

    int i;

    unsigned int data_offset;

    unsigned int audio_frame_counter;

    film->sample_table = NULL;

    film->stereo_buffer = NULL;

    film->stereo_buffer_size = 0;

    /* load the main FILM header */

    if (avio_read(pb, scratch, 16) != 16)

        return AVERROR(EIO);

    data_offset = AV_RB32(&scratch[4]);

    film->version = AV_RB32(&scratch[8]);

    /* load the FDSC chunk */

    if (film->version == 0) {

        /* special case for Lemmings .film files; 20-byte header */

        if (avio_read(pb, scratch, 20) != 20)

            return AVERROR(EIO);

        /* make some assumptions about the audio parameters */

        film->audio_type = AV_CODEC_ID_PCM_S8;

        film->audio_samplerate = 22050;

        film->audio_channels = 1;

        film->audio_bits = 8;

    } else {

        /* normal Saturn .cpk files; 32-byte header */

        if (avio_read(pb, scratch, 32) != 32)

            return AVERROR(EIO);

        film->audio_samplerate = AV_RB16(&scratch[24]);

        film->audio_channels = scratch[21];

        if (!film->audio_channels || film->audio_channels > 2) {

            av_log(s, AV_LOG_ERROR,

                   "Invalid number of channels: %d\n", film->audio_channels);

            return AVERROR_INVALIDDATA;

        }

        film->audio_bits = scratch[22];

        if (scratch[23] == 2)

            film->audio_type = AV_CODEC_ID_ADPCM_ADX;

        else if (film->audio_channels > 0) {

            if (film->audio_bits == 8)

                film->audio_type = AV_CODEC_ID_PCM_S8;

            else if (film->audio_bits == 16)

                film->audio_type = AV_CODEC_ID_PCM_S16BE;

            else

                film->audio_type = AV_CODEC_ID_NONE;

        } else

            film->audio_type = AV_CODEC_ID_NONE;

    }

    if (AV_RB32(&scratch[0]) != FDSC_TAG)

        return AVERROR_INVALIDDATA;

    if (AV_RB32(&scratch[8]) == CVID_TAG) {

        film->video_type = AV_CODEC_ID_CINEPAK;

    } else if (AV_RB32(&scratch[8]) == RAW_TAG) {

        film->video_type = AV_CODEC_ID_RAWVIDEO;

    } else {

        film->video_type = AV_CODEC_ID_NONE;

    }

    /* initialize the decoder streams */

    if (film->video_type) {

        st = avformat_new_stream(s, NULL);

        if (!st)

            return AVERROR(ENOMEM);

        film->video_stream_index = st->index;

        st->codec->codec_type = AVMEDIA_TYPE_VIDEO;

        st->codec->codec_id = film->video_type;

        st->codec->codec_tag = 0;  /* no fourcc */

        st->codec->width = AV_RB32(&scratch[16]);

        st->codec->height = AV_RB32(&scratch[12]);

        if (film->video_type == AV_CODEC_ID_RAWVIDEO) {

            if (scratch[20] == 24) {

                st->codec->pix_fmt = AV_PIX_FMT_RGB24;

            } else {

                av_log(s, AV_LOG_ERROR, "raw video is using unhandled %dbpp\n", scratch[20]);

                return -1;

            }

        }

    }

    if (film->audio_type) {

        st = avformat_new_stream(s, NULL);

        if (!st)

            return AVERROR(ENOMEM);

        film->audio_stream_index = st->index;

        st->codec->codec_type = AVMEDIA_TYPE_AUDIO;

        st->codec->codec_id = film->audio_type;

        st->codec->codec_tag = 1;

        st->codec->channels = film->audio_channels;

        st->codec->sample_rate = film->audio_samplerate;

        if (film->audio_type == AV_CODEC_ID_ADPCM_ADX) {

            st->codec->bits_per_coded_sample = 18 * 8 / 32;

            st->codec->block_align = st->codec->channels * 18;

            st->need_parsing = AVSTREAM_PARSE_FULL;

        } else {

            st->codec->bits_per_coded_sample = film->audio_bits;

            st->codec->block_align = st->codec->channels *

                st->codec->bits_per_coded_sample / 8;

        }

        st->codec->bit_rate = st->codec->channels * st->codec->sample_rate *

            st->codec->bits_per_coded_sample;

    }

    /* load the sample table */

    if (avio_read(pb, scratch, 16) != 16)

        return AVERROR(EIO);

    if (AV_RB32(&scratch[0]) != STAB_TAG)

        return AVERROR_INVALIDDATA;

    film->base_clock = AV_RB32(&scratch[8]);

    film->sample_count = AV_RB32(&scratch[12]);

    if(film->sample_count >= UINT_MAX / sizeof(film_sample))

        return -1;

    film->sample_table = av_malloc(film->sample_count * sizeof(film_sample));

    if (!film->sample_table)

        return AVERROR(ENOMEM);

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

        st = s->streams[i];

        if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO)

            avpriv_set_pts_info(st, 33, 1, film->base_clock);

        else

            avpriv_set_pts_info(st, 64, 1, film->audio_samplerate);

    }

    audio_frame_counter = 0;

    for (i = 0; i < film->sample_count; i++) {

        /* load the next sample record and transfer it to an internal struct */

        if (avio_read(pb, scratch, 16) != 16) {

            av_free(film->sample_table);

            return AVERROR(EIO);

        }

        film->sample_table[i].sample_offset =

            data_offset + AV_RB32(&scratch[0]);

        film->sample_table[i].sample_size = AV_RB32(&scratch[4]);

        if (film->sample_table[i].sample_size > INT_MAX / 4)

            return AVERROR_INVALIDDATA;

        if (AV_RB32(&scratch[8]) == 0xFFFFFFFF) {

            film->sample_table[i].stream = film->audio_stream_index;

            film->sample_table[i].pts = audio_frame_counter;

            if (film->audio_type == AV_CODEC_ID_ADPCM_ADX)

                audio_frame_counter += (film->sample_table[i].sample_size * 32 /

                    (18 * film->audio_channels));

            else if (film->audio_type != AV_CODEC_ID_NONE)

                audio_frame_counter += (film->sample_table[i].sample_size /

                    (film->audio_channels * film->audio_bits / 8));

        } else {

            film->sample_table[i].stream = film->video_stream_index;

            film->sample_table[i].pts = AV_RB32(&scratch[8]) & 0x7FFFFFFF;

            film->sample_table[i].keyframe = (scratch[8] & 0x80) ? 0 : 1;

        }

    }

    film->current_sample = 0;

    return 0;

}


ssize_t nbd_wr_sync(int fd, void *buffer, size_t size, bool do_read)

{

    size_t offset = 0;

    int err;

    if (qemu_in_coroutine()) {

        if (do_read) {

            return qemu_co_recv(fd, buffer, size);

        } else {

            return qemu_co_send(fd, buffer, size);

        }

    }

    while (offset < size) {

        ssize_t len;

        if (do_read) {

            len = qemu_recv(fd, buffer + offset, size - offset, 0);

        } else {

            len = send(fd, buffer + offset, size - offset, 0);

        }

        if (len < 0) {

            err = socket_error();

            /* recoverable error */

            if (err == EINTR || err == EAGAIN) {

                continue;

            }

            /* unrecoverable error */

            return -err;

        }

        /* eof */

        if (len == 0) {

            break;

        }

        offset += len;

    }

    return offset;

}


static int encode_q_branch(SnowContext *s, int level, int x, int y){

    uint8_t p_buffer[1024];

    uint8_t i_buffer[1024];

    uint8_t p_state[sizeof(s->block_state)];

    uint8_t i_state[sizeof(s->block_state)];

    RangeCoder pc, ic;

    uint8_t *pbbak= s->c.bytestream;

    uint8_t *pbbak_start= s->c.bytestream_start;

    int score, score2, iscore, i_len, p_len, block_s, sum, base_bits;

    const int w= s->b_width  << s->block_max_depth;

    const int h= s->b_height << s->block_max_depth;

    const int rem_depth= s->block_max_depth - level;

    const int index= (x + y*w) << rem_depth;

    const int block_w= 1<<(LOG2_MB_SIZE - level);

    int trx= (x+1)<<rem_depth;

    int try= (y+1)<<rem_depth;

    const BlockNode *left  = x ? &s->block[index-1] : &null_block;

    const BlockNode *top   = y ? &s->block[index-w] : &null_block;

    const BlockNode *right = trx<w ? &s->block[index+1] : &null_block;

    const BlockNode *bottom= try<h ? &s->block[index+w] : &null_block;

    const BlockNode *tl    = y && x ? &s->block[index-w-1] : left;

    const BlockNode *tr    = y && trx<w && ((x&1)==0 || level==0) ? &s->block[index-w+(1<<rem_depth)] : tl; //FIXME use lt

    int pl = left->color[0];

    int pcb= left->color[1];

    int pcr= left->color[2];

    int pmx, pmy;

    int mx=0, my=0;

    int l,cr,cb;

    const int stride= s->current_picture->linesize[0];

    const int uvstride= s->current_picture->linesize[1];

    uint8_t *current_data[3]= { s->input_picture->data[0] + (x + y*  stride)*block_w,

                                s->input_picture->data[1] + ((x*block_w)>>s->chroma_h_shift) + ((y*uvstride*block_w)>>s->chroma_v_shift),

                                s->input_picture->data[2] + ((x*block_w)>>s->chroma_h_shift) + ((y*uvstride*block_w)>>s->chroma_v_shift)};

    int P[10][2];

    int16_t last_mv[3][2];

    int qpel= !!(s->avctx->flags & AV_CODEC_FLAG_QPEL); //unused

    const int shift= 1+qpel;

    MotionEstContext *c= &s->m.me;

    int ref_context= av_log2(2*left->ref) + av_log2(2*top->ref);

    int mx_context= av_log2(2*FFABS(left->mx - top->mx));

    int my_context= av_log2(2*FFABS(left->my - top->my));

    int s_context= 2*left->level + 2*top->level + tl->level + tr->level;

    int ref, best_ref, ref_score, ref_mx, ref_my;

    av_assert0(sizeof(s->block_state) >= 256);

    if(s->keyframe){

        set_blocks(s, level, x, y, pl, pcb, pcr, 0, 0, 0, BLOCK_INTRA);

        return 0;

    }

//    clip predictors / edge ?

    P_LEFT[0]= left->mx;

    P_LEFT[1]= left->my;

    P_TOP [0]= top->mx;

    P_TOP [1]= top->my;

    P_TOPRIGHT[0]= tr->mx;

    P_TOPRIGHT[1]= tr->my;

    last_mv[0][0]= s->block[index].mx;

    last_mv[0][1]= s->block[index].my;

    last_mv[1][0]= right->mx;

    last_mv[1][1]= right->my;

    last_mv[2][0]= bottom->mx;

    last_mv[2][1]= bottom->my;

    s->m.mb_stride=2;

    s->m.mb_x=

    s->m.mb_y= 0;

    c->skip= 0;

    av_assert1(c->  stride ==   stride);

    av_assert1(c->uvstride == uvstride);

    c->penalty_factor    = get_penalty_factor(s->lambda, s->lambda2, c->avctx->me_cmp);

    c->sub_penalty_factor= get_penalty_factor(s->lambda, s->lambda2, c->avctx->me_sub_cmp);

    c->mb_penalty_factor = get_penalty_factor(s->lambda, s->lambda2, c->avctx->mb_cmp);

    c->current_mv_penalty= c->mv_penalty[s->m.f_code=1] + MAX_MV;

    c->xmin = - x*block_w - 16+3;

    c->ymin = - y*block_w - 16+3;

    c->xmax = - (x+1)*block_w + (w<<(LOG2_MB_SIZE - s->block_max_depth)) + 16-3;

    c->ymax = - (y+1)*block_w + (h<<(LOG2_MB_SIZE - s->block_max_depth)) + 16-3;

    if(P_LEFT[0]     > (c->xmax<<shift)) P_LEFT[0]    = (c->xmax<<shift);

    if(P_LEFT[1]     > (c->ymax<<shift)) P_LEFT[1]    = (c->ymax<<shift);

    if(P_TOP[0]      > (c->xmax<<shift)) P_TOP[0]     = (c->xmax<<shift);

    if(P_TOP[1]      > (c->ymax<<shift)) P_TOP[1]     = (c->ymax<<shift);

    if(P_TOPRIGHT[0] < (c->xmin<<shift)) P_TOPRIGHT[0]= (c->xmin<<shift);

    if(P_TOPRIGHT[0] > (c->xmax<<shift)) P_TOPRIGHT[0]= (c->xmax<<shift); //due to pmx no clip

    if(P_TOPRIGHT[1] > (c->ymax<<shift)) P_TOPRIGHT[1]= (c->ymax<<shift);

    P_MEDIAN[0]= mid_pred(P_LEFT[0], P_TOP[0], P_TOPRIGHT[0]);

    P_MEDIAN[1]= mid_pred(P_LEFT[1], P_TOP[1], P_TOPRIGHT[1]);

    if (!y) {

        c->pred_x= P_LEFT[0];

        c->pred_y= P_LEFT[1];

    } else {

        c->pred_x = P_MEDIAN[0];

        c->pred_y = P_MEDIAN[1];

    }

    score= INT_MAX;

    best_ref= 0;

    for(ref=0; ref<s->ref_frames; ref++){

        init_ref(c, current_data, s->last_picture[ref]->data, NULL, block_w*x, block_w*y, 0);

        ref_score= ff_epzs_motion_search(&s->m, &ref_mx, &ref_my, P, 0, /*ref_index*/ 0, last_mv,

                                         (1<<16)>>shift, level-LOG2_MB_SIZE+4, block_w);

        av_assert2(ref_mx >= c->xmin);

        av_assert2(ref_mx <= c->xmax);

        av_assert2(ref_my >= c->ymin);

        av_assert2(ref_my <= c->ymax);

        ref_score= c->sub_motion_search(&s->m, &ref_mx, &ref_my, ref_score, 0, 0, level-LOG2_MB_SIZE+4, block_w);

        ref_score= ff_get_mb_score(&s->m, ref_mx, ref_my, 0, 0, level-LOG2_MB_SIZE+4, block_w, 0);

        ref_score+= 2*av_log2(2*ref)*c->penalty_factor;

        if(s->ref_mvs[ref]){

            s->ref_mvs[ref][index][0]= ref_mx;

            s->ref_mvs[ref][index][1]= ref_my;

            s->ref_scores[ref][index]= ref_score;

        }

        if(score > ref_score){

            score= ref_score;

            best_ref= ref;

            mx= ref_mx;

            my= ref_my;

        }

    }

    //FIXME if mb_cmp != SSE then intra cannot be compared currently and mb_penalty vs. lambda2

  //  subpel search

    base_bits= get_rac_count(&s->c) - 8*(s->c.bytestream - s->c.bytestream_start);

    pc= s->c;

    pc.bytestream_start=

    pc.bytestream= p_buffer; //FIXME end/start? and at the other stoo

    memcpy(p_state, s->block_state, sizeof(s->block_state));

    if(level!=s->block_max_depth)

        put_rac(&pc, &p_state[4 + s_context], 1);

    put_rac(&pc, &p_state[1 + left->type + top->type], 0);

    if(s->ref_frames > 1)

        put_symbol(&pc, &p_state[128 + 1024 + 32*ref_context], best_ref, 0);

    pred_mv(s, &pmx, &pmy, best_ref, left, top, tr);

    put_symbol(&pc, &p_state[128 + 32*(mx_context + 16*!!best_ref)], mx - pmx, 1);

    put_symbol(&pc, &p_state[128 + 32*(my_context + 16*!!best_ref)], my - pmy, 1);

    p_len= pc.bytestream - pc.bytestream_start;

    score += (s->lambda2*(get_rac_count(&pc)-base_bits))>>FF_LAMBDA_SHIFT;

    block_s= block_w*block_w;

    sum = pix_sum(current_data[0], stride, block_w, block_w);

    l= (sum + block_s/2)/block_s;

    iscore = pix_norm1(current_data[0], stride, block_w) - 2*l*sum + l*l*block_s;

    if (s->nb_planes > 2) {

        block_s= block_w*block_w>>(s->chroma_h_shift + s->chroma_v_shift);

        sum = pix_sum(current_data[1], uvstride, block_w>>s->chroma_h_shift, block_w>>s->chroma_v_shift);

        cb= (sum + block_s/2)/block_s;

    //    iscore += pix_norm1(&current_mb[1][0], uvstride, block_w>>1) - 2*cb*sum + cb*cb*block_s;

        sum = pix_sum(current_data[2], uvstride, block_w>>s->chroma_h_shift, block_w>>s->chroma_v_shift);

        cr= (sum + block_s/2)/block_s;

    //    iscore += pix_norm1(&current_mb[2][0], uvstride, block_w>>1) - 2*cr*sum + cr*cr*block_s;

    }else

        cb = cr = 0;

    ic= s->c;

    ic.bytestream_start=

    ic.bytestream= i_buffer; //FIXME end/start? and at the other stoo

    memcpy(i_state, s->block_state, sizeof(s->block_state));

    if(level!=s->block_max_depth)

        put_rac(&ic, &i_state[4 + s_context], 1);

    put_rac(&ic, &i_state[1 + left->type + top->type], 1);

    put_symbol(&ic, &i_state[32],  l-pl , 1);

    if (s->nb_planes > 2) {

        put_symbol(&ic, &i_state[64], cb-pcb, 1);

        put_symbol(&ic, &i_state[96], cr-pcr, 1);

    }

    i_len= ic.bytestream - ic.bytestream_start;

    iscore += (s->lambda2*(get_rac_count(&ic)-base_bits))>>FF_LAMBDA_SHIFT;

    av_assert1(iscore < 255*255*256 + s->lambda2*10);

    av_assert1(iscore >= 0);

    av_assert1(l>=0 && l<=255);

    av_assert1(pl>=0 && pl<=255);

    if(level==0){

        int varc= iscore >> 8;

        int vard= score >> 8;

        if (vard <= 64 || vard < varc)

            c->scene_change_score+= ff_sqrt(vard) - ff_sqrt(varc);

        else

            c->scene_change_score+= s->m.qscale;

    }

    if(level!=s->block_max_depth){

        put_rac(&s->c, &s->block_state[4 + s_context], 0);

        score2 = encode_q_branch(s, level+1, 2*x+0, 2*y+0);

        score2+= encode_q_branch(s, level+1, 2*x+1, 2*y+0);

        score2+= encode_q_branch(s, level+1, 2*x+0, 2*y+1);

        score2+= encode_q_branch(s, level+1, 2*x+1, 2*y+1);

        score2+= s->lambda2>>FF_LAMBDA_SHIFT; //FIXME exact split overhead

        if(score2 < score && score2 < iscore)

            return score2;

    }

    if(iscore < score){

        pred_mv(s, &pmx, &pmy, 0, left, top, tr);

        memcpy(pbbak, i_buffer, i_len);

        s->c= ic;

        s->c.bytestream_start= pbbak_start;

        s->c.bytestream= pbbak + i_len;

        set_blocks(s, level, x, y, l, cb, cr, pmx, pmy, 0, BLOCK_INTRA);

        memcpy(s->block_state, i_state, sizeof(s->block_state));

        return iscore;

    }else{

        memcpy(pbbak, p_buffer, p_len);

        s->c= pc;

        s->c.bytestream_start= pbbak_start;

        s->c.bytestream= pbbak + p_len;

        set_blocks(s, level, x, y, pl, pcb, pcr, mx, my, best_ref, 0);

        memcpy(s->block_state, p_state, sizeof(s->block_state));

        return score;

    }

}


static inline int decode_cabac_mb_transform_size( H264Context *h ) {

    return get_cabac( &h->cabac, &h->cabac_state[399 + h->neighbor_transform_size] );

}


static av_always_inline void filter_mb_dir(const H264Context *h, H264SliceContext *sl,

                                           int mb_x, int mb_y,

                                           uint8_t *img_y, uint8_t *img_cb, uint8_t *img_cr,

                                           unsigned int linesize, unsigned int uvlinesize,

                                           int mb_xy, int mb_type, int mvy_limit,

                                           int first_vertical_edge_done, int a, int b,

                                           int chroma, int dir)

{

    int edge;

    int chroma_qp_avg[2];

    int chroma444 = CHROMA444(h);

    int chroma422 = CHROMA422(h);

    const int mbm_xy = dir == 0 ? mb_xy -1 : sl->top_mb_xy;

    const int mbm_type = dir == 0 ? sl->left_type[LTOP] : sl->top_type;

    // how often to recheck mv-based bS when iterating between edges

    static const uint8_t mask_edge_tab[2][8]={{0,3,3,3,1,1,1,1},

                                              {0,3,1,1,3,3,3,3}};

    const int mask_edge = mask_edge_tab[dir][(mb_type>>3)&7];

    const int edges = mask_edge== 3 && !(sl->cbp&15) ? 1 : 4;

    // how often to recheck mv-based bS when iterating along each edge

    const int mask_par0 = mb_type & (MB_TYPE_16x16 | (MB_TYPE_8x16 >> dir));

    if(mbm_type && !first_vertical_edge_done){

        if (FRAME_MBAFF(h) && (dir == 1) && ((mb_y&1) == 0)

            && IS_INTERLACED(mbm_type&~mb_type)

            ) {

            // This is a special case in the norm where the filtering must

            // be done twice (one each of the field) even if we are in a

            // frame macroblock.

            //

            unsigned int tmp_linesize   = 2 *   linesize;

            unsigned int tmp_uvlinesize = 2 * uvlinesize;

            int mbn_xy = mb_xy - 2 * h->mb_stride;

            int j;

            for(j=0; j<2; j++, mbn_xy += h->mb_stride){

                DECLARE_ALIGNED(8, int16_t, bS)[4];

                int qp;

                if (IS_INTRA(mb_type | h->cur_pic.mb_type[mbn_xy])) {

                    AV_WN64A(bS, 0x0003000300030003ULL);

                } else {

                    if (!CABAC(h) && IS_8x8DCT(h->cur_pic.mb_type[mbn_xy])) {

                        bS[0]= 1+((h->cbp_table[mbn_xy] & 0x4000) || sl->non_zero_count_cache[scan8[0]+0]);

                        bS[1]= 1+((h->cbp_table[mbn_xy] & 0x4000) || sl->non_zero_count_cache[scan8[0]+1]);

                        bS[2]= 1+((h->cbp_table[mbn_xy] & 0x8000) || sl->non_zero_count_cache[scan8[0]+2]);

                        bS[3]= 1+((h->cbp_table[mbn_xy] & 0x8000) || sl->non_zero_count_cache[scan8[0]+3]);

                    }else{

                    const uint8_t *mbn_nnz = h->non_zero_count[mbn_xy] + 3*4;

                    int i;

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

                        bS[i] = 1 + !!(sl->non_zero_count_cache[scan8[0]+i] | mbn_nnz[i]);

                    }

                    }

                }

                // Do not use s->qscale as luma quantizer because it has not the same

                // value in IPCM macroblocks.

                qp = (h->cur_pic.qscale_table[mb_xy] + h->cur_pic.qscale_table[mbn_xy] + 1) >> 1;

                ff_tlog(h->avctx, "filter mb:%d/%d dir:%d edge:%d, QPy:%d ls:%d uvls:%d", mb_x, mb_y, dir, edge, qp, tmp_linesize, tmp_uvlinesize);

                { int i; for (i = 0; i < 4; i++) ff_tlog(h->avctx, " bS[%d]:%d", i, bS[i]); ff_tlog(h->avctx, "\n"); }

                filter_mb_edgeh( &img_y[j*linesize], tmp_linesize, bS, qp, a, b, h, 0 );

                chroma_qp_avg[0] = (sl->chroma_qp[0] + get_chroma_qp(h->ps.pps, 0, h->cur_pic.qscale_table[mbn_xy]) + 1) >> 1;

                chroma_qp_avg[1] = (sl->chroma_qp[1] + get_chroma_qp(h->ps.pps, 1, h->cur_pic.qscale_table[mbn_xy]) + 1) >> 1;

                if (chroma) {

                    if (chroma444) {

                        filter_mb_edgeh (&img_cb[j*uvlinesize], tmp_uvlinesize, bS, chroma_qp_avg[0], a, b, h, 0);

                        filter_mb_edgeh (&img_cr[j*uvlinesize], tmp_uvlinesize, bS, chroma_qp_avg[1], a, b, h, 0);

                    } else {

                        filter_mb_edgech(&img_cb[j*uvlinesize], tmp_uvlinesize, bS, chroma_qp_avg[0], a, b, h, 0);

                        filter_mb_edgech(&img_cr[j*uvlinesize], tmp_uvlinesize, bS, chroma_qp_avg[1], a, b, h, 0);

                    }

                }

            }

        }else{

            DECLARE_ALIGNED(8, int16_t, bS)[4];

            int qp;

            if( IS_INTRA(mb_type|mbm_type)) {

                AV_WN64A(bS, 0x0003000300030003ULL);

                if (   (!IS_INTERLACED(mb_type|mbm_type))

                    || ((FRAME_MBAFF(h) || (h->picture_structure != PICT_FRAME)) && (dir == 0))

                )

                    AV_WN64A(bS, 0x0004000400040004ULL);

            } else {

                int i;

                int mv_done;

                if( dir && FRAME_MBAFF(h) && IS_INTERLACED(mb_type ^ mbm_type)) {

                    AV_WN64A(bS, 0x0001000100010001ULL);

                    mv_done = 1;

                }

                else if( mask_par0 && ((mbm_type & (MB_TYPE_16x16 | (MB_TYPE_8x16 >> dir)))) ) {

                    int b_idx= 8 + 4;

                    int bn_idx= b_idx - (dir ? 8:1);

                    bS[0] = bS[1] = bS[2] = bS[3] = check_mv(sl, 8 + 4, bn_idx, mvy_limit);

                    mv_done = 1;

                }

                else

                    mv_done = 0;

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

                    int x = dir == 0 ? 0 : i;

                    int y = dir == 0 ? i    : 0;

                    int b_idx= 8 + 4 + x + 8*y;

                    int bn_idx= b_idx - (dir ? 8:1);

                    if (sl->non_zero_count_cache[b_idx] |

                        sl->non_zero_count_cache[bn_idx]) {

                        bS[i] = 2;

                    }

                    else if(!mv_done)

                    {

                        bS[i] = check_mv(sl, b_idx, bn_idx, mvy_limit);

                    }

                }

            }

            /* Filter edge */

            // Do not use s->qscale as luma quantizer because it has not the same

            // value in IPCM macroblocks.

            if(bS[0]+bS[1]+bS[2]+bS[3]){

                qp = (h->cur_pic.qscale_table[mb_xy] + h->cur_pic.qscale_table[mbm_xy] + 1) >> 1;

                ff_tlog(h->avctx, "filter mb:%d/%d dir:%d edge:%d, QPy:%d ls:%d uvls:%d", mb_x, mb_y, dir, edge, qp, linesize, uvlinesize);

                chroma_qp_avg[0] = (sl->chroma_qp[0] + get_chroma_qp(h->ps.pps, 0, h->cur_pic.qscale_table[mbm_xy]) + 1) >> 1;

                chroma_qp_avg[1] = (sl->chroma_qp[1] + get_chroma_qp(h->ps.pps, 1, h->cur_pic.qscale_table[mbm_xy]) + 1) >> 1;

                if( dir == 0 ) {

                    filter_mb_edgev( &img_y[0], linesize, bS, qp, a, b, h, 1 );

                    if (chroma) {

                        if (chroma444) {

                            filter_mb_edgev ( &img_cb[0], uvlinesize, bS, chroma_qp_avg[0], a, b, h, 1);

                            filter_mb_edgev ( &img_cr[0], uvlinesize, bS, chroma_qp_avg[1], a, b, h, 1);

                        } else {

                            filter_mb_edgecv( &img_cb[0], uvlinesize, bS, chroma_qp_avg[0], a, b, h, 1);

                            filter_mb_edgecv( &img_cr[0], uvlinesize, bS, chroma_qp_avg[1], a, b, h, 1);

                        }

                    }

                } else {

                    filter_mb_edgeh( &img_y[0], linesize, bS, qp, a, b, h, 1 );

                    if (chroma) {

                        if (chroma444) {

                            filter_mb_edgeh ( &img_cb[0], uvlinesize, bS, chroma_qp_avg[0], a, b, h, 1);

                            filter_mb_edgeh ( &img_cr[0], uvlinesize, bS, chroma_qp_avg[1], a, b, h, 1);

                        } else {

                            filter_mb_edgech( &img_cb[0], uvlinesize, bS, chroma_qp_avg[0], a, b, h, 1);

                            filter_mb_edgech( &img_cr[0], uvlinesize, bS, chroma_qp_avg[1], a, b, h, 1);

                        }

                    }

                }

            }

        }

    }

    /* Calculate bS */

    for( edge = 1; edge < edges; edge++ ) {

        DECLARE_ALIGNED(8, int16_t, bS)[4];

        int qp;

        const int deblock_edge = !IS_8x8DCT(mb_type & (edge<<24)); // (edge&1) && IS_8x8DCT(mb_type)

        if (!deblock_edge && (!chroma422 || dir == 0))

            continue;

        if( IS_INTRA(mb_type)) {

            AV_WN64A(bS, 0x0003000300030003ULL);

        } else {

            int i;

            int mv_done;

            if( edge & mask_edge ) {

                AV_ZERO64(bS);

                mv_done = 1;

            }

            else if( mask_par0 ) {

                int b_idx= 8 + 4 + edge * (dir ? 8:1);

                int bn_idx= b_idx - (dir ? 8:1);

                bS[0] = bS[1] = bS[2] = bS[3] = check_mv(sl, b_idx, bn_idx, mvy_limit);

                mv_done = 1;

            }

            else

                mv_done = 0;

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

                int x = dir == 0 ? edge : i;

                int y = dir == 0 ? i    : edge;

                int b_idx= 8 + 4 + x + 8*y;

                int bn_idx= b_idx - (dir ? 8:1);

                if (sl->non_zero_count_cache[b_idx] |

                    sl->non_zero_count_cache[bn_idx]) {

                    bS[i] = 2;

                }

                else if(!mv_done)

                {

                    bS[i] = check_mv(sl, b_idx, bn_idx, mvy_limit);

                }

            }

            if(bS[0]+bS[1]+bS[2]+bS[3] == 0)

                continue;

        }

        /* Filter edge */

        // Do not use s->qscale as luma quantizer because it has not the same

        // value in IPCM macroblocks.

        qp = h->cur_pic.qscale_table[mb_xy];

        ff_tlog(h->avctx, "filter mb:%d/%d dir:%d edge:%d, QPy:%d ls:%d uvls:%d", mb_x, mb_y, dir, edge, qp, linesize, uvlinesize);

        if( dir == 0 ) {

            filter_mb_edgev( &img_y[4*edge << h->pixel_shift], linesize, bS, qp, a, b, h, 0 );

            if (chroma) {

                if (chroma444) {

                    filter_mb_edgev ( &img_cb[4*edge << h->pixel_shift], uvlinesize, bS, sl->chroma_qp[0], a, b, h, 0);

                    filter_mb_edgev ( &img_cr[4*edge << h->pixel_shift], uvlinesize, bS, sl->chroma_qp[1], a, b, h, 0);

                } else if( (edge&1) == 0 ) {

                    filter_mb_edgecv( &img_cb[2*edge << h->pixel_shift], uvlinesize, bS, sl->chroma_qp[0], a, b, h, 0);

                    filter_mb_edgecv( &img_cr[2*edge << h->pixel_shift], uvlinesize, bS, sl->chroma_qp[1], a, b, h, 0);

                }

            }

        } else {

            if (chroma422) {

                if (deblock_edge)

                    filter_mb_edgeh(&img_y[4*edge*linesize], linesize, bS, qp, a, b, h, 0);

                if (chroma) {

                    filter_mb_edgech(&img_cb[4*edge*uvlinesize], uvlinesize, bS, sl->chroma_qp[0], a, b, h, 0);

                    filter_mb_edgech(&img_cr[4*edge*uvlinesize], uvlinesize, bS, sl->chroma_qp[1], a, b, h, 0);

                }

            } else {

                filter_mb_edgeh(&img_y[4*edge*linesize], linesize, bS, qp, a, b, h, 0);

                if (chroma) {

                    if (chroma444) {

                        filter_mb_edgeh (&img_cb[4*edge*uvlinesize], uvlinesize, bS, sl->chroma_qp[0], a, b, h, 0);

                        filter_mb_edgeh (&img_cr[4*edge*uvlinesize], uvlinesize, bS, sl->chroma_qp[1], a, b, h, 0);

                    } else if ((edge&1) == 0) {

                        filter_mb_edgech(&img_cb[2*edge*uvlinesize], uvlinesize, bS, sl->chroma_qp[0], a, b, h, 0);

                        filter_mb_edgech(&img_cr[2*edge*uvlinesize], uvlinesize, bS, sl->chroma_qp[1], a, b, h, 0);

                    }

                }

            }

        }

    }

}