long disas_insn(DisasContext *s, uint8_t *pc_start)

{

    int b, prefixes, aflag, dflag;

    int shift, ot;

    int modrm, reg, rm, mod, reg_addr, op, opreg, offset_addr, val;

    unsigned int next_eip;

    s->pc = pc_start;

    prefixes = 0;

    aflag = s->code32;

    dflag = s->code32;

    //    cur_pc = s->pc; /* for insn generation */

 next_byte:

    b = ldub(s->pc);

    s->pc++;

    /* check prefixes */

    switch (b) {

    case 0xf3:

        prefixes |= PREFIX_REPZ;

        goto next_byte;

    case 0xf2:

        prefixes |= PREFIX_REPNZ;

        goto next_byte;

    case 0xf0:

        prefixes |= PREFIX_LOCK;

        goto next_byte;

    case 0x2e:

        prefixes |= PREFIX_CS;

        goto next_byte;

    case 0x36:

        prefixes |= PREFIX_SS;

        goto next_byte;

    case 0x3e:

        prefixes |= PREFIX_DS;

        goto next_byte;

    case 0x26:

        prefixes |= PREFIX_ES;

        goto next_byte;

    case 0x64:

        prefixes |= PREFIX_FS;

        goto next_byte;

    case 0x65:

        prefixes |= PREFIX_GS;

        goto next_byte;

    case 0x66:

        prefixes |= PREFIX_DATA;

        goto next_byte;

    case 0x67:

        prefixes |= PREFIX_ADR;

        goto next_byte;

    case 0x9b:

        prefixes |= PREFIX_FWAIT;

        goto next_byte;

    }

    if (prefixes & PREFIX_DATA)

        dflag ^= 1;

    if (prefixes & PREFIX_ADR)

        aflag ^= 1;

    s->prefix = prefixes;

    s->aflag = aflag;

    s->dflag = dflag;

    /* lock generation */

    if (prefixes & PREFIX_LOCK)

        gen_op_lock();

    /* now check op code */

 reswitch:

    switch(b) {

    case 0x0f:

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

        /* extended op code */

        b = ldub(s->pc++) | 0x100;

        goto reswitch;

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

        /* arith & logic */

    case 0x00 ... 0x05:

    case 0x08 ... 0x0d:

    case 0x10 ... 0x15:

    case 0x18 ... 0x1d:

    case 0x20 ... 0x25:

    case 0x28 ... 0x2d:

    case 0x30 ... 0x35:

    case 0x38 ... 0x3d:

        {

            int op, f, val;

            op = (b >> 3) & 7;

            f = (b >> 1) & 3;

            if ((b & 1) == 0)

                ot = OT_BYTE;

            else

                ot = dflag ? OT_LONG : OT_WORD;

            switch(f) {

            case 0: /* OP Ev, Gv */

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

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

                mod = (modrm >> 6) & 3;

                rm = modrm & 7;

                if (mod != 3) {

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

                    gen_op_ld_T0_A0[ot]();

                    opreg = OR_TMP0;

                } else {

                    opreg = OR_EAX + rm;

                }

                gen_op(s, op, ot, opreg, reg);

                if (mod != 3 && op != 7) {

                    gen_op_st_T0_A0[ot]();

                }

                break;

            case 1: /* OP Gv, Ev */

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

                mod = (modrm >> 6) & 3;

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

                rm = modrm & 7;

                if (mod != 3) {

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

                    gen_op_ld_T1_A0[ot]();

                    opreg = OR_TMP1;

                } else {

                    opreg = OR_EAX + rm;

                }

                gen_op(s, op, ot, reg, opreg);

                break;

            case 2: /* OP A, Iv */

                val = insn_get(s, ot);

                gen_opi(s, op, ot, OR_EAX, val);

                break;

            }

        }

        break;

    case 0x80: /* GRP1 */

    case 0x81:

    case 0x83:

        {

            int val;

            if ((b & 1) == 0)

                ot = OT_BYTE;

            else

                ot = dflag ? OT_LONG : OT_WORD;

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

            mod = (modrm >> 6) & 3;

            rm = modrm & 7;

            op = (modrm >> 3) & 7;

            if (mod != 3) {

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

                gen_op_ld_T0_A0[ot]();

                opreg = OR_TMP0;

            } else {

                opreg = rm + OR_EAX;

            }

            switch(b) {

            default:

            case 0x80:

            case 0x81:

                val = insn_get(s, ot);

                break;

            case 0x83:

                val = (int8_t)insn_get(s, OT_BYTE);

                break;

            }

            gen_opi(s, op, ot, opreg, val);

            if (op != 7 && mod != 3) {

                gen_op_st_T0_A0[ot]();

            }

        }

        break;

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

        /* inc, dec, and other misc arith */

    case 0x40 ... 0x47: /* inc Gv */

        ot = dflag ? OT_LONG : OT_WORD;

        gen_inc(s, ot, OR_EAX + (b & 7), 1);

        break;

    case 0x48 ... 0x4f: /* dec Gv */

        ot = dflag ? OT_LONG : OT_WORD;

        gen_inc(s, ot, OR_EAX + (b & 7), -1);

        break;

    case 0xf6: /* GRP3 */

    case 0xf7:

        if ((b & 1) == 0)

            ot = OT_BYTE;

        else

            ot = dflag ? OT_LONG : OT_WORD;

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

        mod = (modrm >> 6) & 3;

        rm = modrm & 7;

        op = (modrm >> 3) & 7;

        if (mod != 3) {

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

            gen_op_ld_T0_A0[ot]();

        } else {

            gen_op_mov_TN_reg[ot][0][rm]();

        }

        switch(op) {

        case 0: /* test */

            val = insn_get(s, ot);

            gen_op_movl_T1_im(val);

            gen_op_testl_T0_T1_cc();

            s->cc_op = CC_OP_LOGICB + ot;

            break;

        case 2: /* not */

            gen_op_notl_T0();

            if (mod != 3) {

                gen_op_st_T0_A0[ot]();

            } else {

                gen_op_mov_reg_T0[ot][rm]();

            }

            break;

        case 3: /* neg */

            gen_op_negl_T0_cc();

            if (mod != 3) {

                gen_op_st_T0_A0[ot]();

            } else {

                gen_op_mov_reg_T0[ot][rm]();

            }

            s->cc_op = CC_OP_SUBB + ot;

            break;

        case 4: /* mul */

            switch(ot) {

            case OT_BYTE:

                gen_op_mulb_AL_T0();

                break;

            case OT_WORD:

                gen_op_mulw_AX_T0();

                break;

            default:

            case OT_LONG:

                gen_op_mull_EAX_T0();

                break;

            }

            s->cc_op = CC_OP_MUL;

            break;

        case 5: /* imul */

            switch(ot) {

            case OT_BYTE:

                gen_op_imulb_AL_T0();

                break;

            case OT_WORD:

                gen_op_imulw_AX_T0();

                break;

            default:

            case OT_LONG:

                gen_op_imull_EAX_T0();

                break;

            }

            s->cc_op = CC_OP_MUL;

            break;

        case 6: /* div */

            switch(ot) {

            case OT_BYTE:

                gen_op_divb_AL_T0();

                break;

            case OT_WORD:

                gen_op_divw_AX_T0();

                break;

            default:

            case OT_LONG:

                gen_op_divl_EAX_T0();

                break;

            }

            break;

        case 7: /* idiv */

            switch(ot) {

            case OT_BYTE:

                gen_op_idivb_AL_T0();

                break;

            case OT_WORD:

                gen_op_idivw_AX_T0();

                break;

            default:

            case OT_LONG:

                gen_op_idivl_EAX_T0();

                break;

            }

            break;

        default:

            goto illegal_op;

        }

        break;

    case 0xfe: /* GRP4 */

    case 0xff: /* GRP5 */

        if ((b & 1) == 0)

            ot = OT_BYTE;

        else

            ot = dflag ? OT_LONG : OT_WORD;

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

        mod = (modrm >> 6) & 3;

        rm = modrm & 7;

        op = (modrm >> 3) & 7;

        if (op >= 2 && b == 0xfe) {

            goto illegal_op;

        }

        if (mod != 3) {

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

            if (op != 3 && op != 5)

                gen_op_ld_T0_A0[ot]();

        } else {

            gen_op_mov_TN_reg[ot][0][rm]();

        }

        switch(op) {

        case 0: /* inc Ev */

            gen_inc(s, ot, OR_TMP0, 1);

            if (mod != 3)

                gen_op_st_T0_A0[ot]();

            else

                gen_op_mov_reg_T0[ot][rm]();

            break;

        case 1: /* dec Ev */

            gen_inc(s, ot, OR_TMP0, -1);

            if (mod != 3)

                gen_op_st_T0_A0[ot]();

            else

                gen_op_mov_reg_T0[ot][rm]();

            break;

        case 2: /* call Ev */

            /* XXX: optimize if memory (no and is necessary) */

            if (s->dflag == 0)

                gen_op_andl_T0_ffff();

            gen_op_jmp_T0();

            next_eip = s->pc - s->cs_base;

            gen_op_movl_T0_im(next_eip);

            gen_push_T0(s);

            s->is_jmp = 1;

            break;

        case 3: /* lcall Ev */

            /* push return segment + offset */

            gen_op_movl_T0_seg(R_CS);

            gen_push_T0(s);

            next_eip = s->pc - s->cs_base;

            gen_op_movl_T0_im(next_eip);

            gen_push_T0(s);

            gen_op_ld_T1_A0[ot]();

            gen_op_addl_A0_im(1 << (ot - OT_WORD + 1));

            gen_op_lduw_T0_A0();

            gen_movl_seg_T0(s, R_CS);

            gen_op_movl_T0_T1();

            gen_op_jmp_T0();

            s->is_jmp = 1;

            break;

        case 4: /* jmp Ev */

            if (s->dflag == 0)

                gen_op_andl_T0_ffff();

            gen_op_jmp_T0();

            s->is_jmp = 1;

            break;

        case 5: /* ljmp Ev */

            gen_op_ld_T1_A0[ot]();

            gen_op_addl_A0_im(1 << (ot - OT_WORD + 1));

            gen_op_lduw_T0_A0();

            gen_movl_seg_T0(s, R_CS);

            gen_op_movl_T0_T1();

            gen_op_jmp_T0();

            s->is_jmp = 1;

            break;

        case 6: /* push Ev */

            gen_push_T0(s);

            break;

        default:

            goto illegal_op;

        }

        break;

    case 0x84: /* test Ev, Gv */

    case 0x85:

        if ((b & 1) == 0)

            ot = OT_BYTE;

        else

            ot = dflag ? OT_LONG : OT_WORD;

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

        mod = (modrm >> 6) & 3;

        rm = modrm & 7;

        reg = (modrm >> 3) & 7;

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

        gen_op_mov_TN_reg[ot][1][reg + OR_EAX]();

        gen_op_testl_T0_T1_cc();

        s->cc_op = CC_OP_LOGICB + ot;

        break;

    case 0xa8: /* test eAX, Iv */

    case 0xa9:

        if ((b & 1) == 0)

            ot = OT_BYTE;

        else

            ot = dflag ? OT_LONG : OT_WORD;

        val = insn_get(s, ot);

        gen_op_mov_TN_reg[ot][0][OR_EAX]();

        gen_op_movl_T1_im(val);

        gen_op_testl_T0_T1_cc();

        s->cc_op = CC_OP_LOGICB + ot;

        break;

    case 0x98: /* CWDE/CBW */

        if (dflag)

            gen_op_movswl_EAX_AX();

        else

            gen_op_movsbw_AX_AL();

        break;

    case 0x99: /* CDQ/CWD */

        if (dflag)

            gen_op_movslq_EDX_EAX();

        else

            gen_op_movswl_DX_AX();

        break;

    case 0x1af: /* imul Gv, Ev */

    case 0x69: /* imul Gv, Ev, I */

    case 0x6b:

        ot = dflag ? OT_LONG : OT_WORD;

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

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

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

        if (b == 0x69) {

            val = insn_get(s, ot);

            gen_op_movl_T1_im(val);

        } else if (b == 0x6b) {

            val = insn_get(s, OT_BYTE);

            gen_op_movl_T1_im(val);

        } else {

            gen_op_mov_TN_reg[ot][1][reg]();

        }

        if (ot == OT_LONG) {

            gen_op_imull_T0_T1();

        } else {

            gen_op_imulw_T0_T1();

        }

        gen_op_mov_reg_T0[ot][reg]();

        s->cc_op = CC_OP_MUL;

        break;

    case 0x1c0:

    case 0x1c1: /* xadd Ev, Gv */

        if ((b & 1) == 0)

            ot = OT_BYTE;

        else

            ot = dflag ? OT_LONG : OT_WORD;

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

        reg = (modrm >> 3) & 7;

        mod = (modrm >> 6) & 3;

        if (mod == 3) {

            rm = modrm & 7;

            gen_op_mov_TN_reg[ot][0][reg]();

            gen_op_mov_TN_reg[ot][1][rm]();

            gen_op_addl_T0_T1_cc();

            gen_op_mov_reg_T0[ot][rm]();

            gen_op_mov_reg_T1[ot][reg]();

        } else {

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

            gen_op_mov_TN_reg[ot][0][reg]();

            gen_op_ld_T1_A0[ot]();

            gen_op_addl_T0_T1_cc();

            gen_op_st_T0_A0[ot]();

            gen_op_mov_reg_T1[ot][reg]();

        }

        s->cc_op = CC_OP_ADDB + ot;

        break;

    case 0x1b0:

    case 0x1b1: /* cmpxchg Ev, Gv */

        if ((b & 1) == 0)

            ot = OT_BYTE;

        else

            ot = dflag ? OT_LONG : OT_WORD;

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

        reg = (modrm >> 3) & 7;

        mod = (modrm >> 6) & 3;

        gen_op_mov_TN_reg[ot][1][reg]();

        if (mod == 3) {

            rm = modrm & 7;

            gen_op_mov_TN_reg[ot][0][rm]();

            gen_op_cmpxchg_T0_T1_EAX_cc[ot]();

            gen_op_mov_reg_T0[ot][rm]();

        } else {

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

            gen_op_ld_T0_A0[ot]();

            gen_op_cmpxchg_T0_T1_EAX_cc[ot]();

            gen_op_st_T0_A0[ot]();

        }

        s->cc_op = CC_OP_SUBB + ot;

        break;

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

        /* push/pop */

    case 0x50 ... 0x57: /* push */

        gen_op_mov_TN_reg[OT_LONG][0][b & 7]();

        gen_push_T0(s);

        break;

    case 0x58 ... 0x5f: /* pop */

        ot = dflag ? OT_LONG : OT_WORD;

        gen_pop_T0(s);

        gen_op_mov_reg_T0[ot][b & 7]();

        gen_pop_update(s);

        break;

    case 0x60: /* pusha */

        gen_pusha(s);

        break;

    case 0x61: /* popa */

        gen_popa(s);

        break;

    case 0x68: /* push Iv */

    case 0x6a:

        ot = dflag ? OT_LONG : OT_WORD;

        if (b == 0x68)

            val = insn_get(s, ot);

        else

            val = (int8_t)insn_get(s, OT_BYTE);

        gen_op_movl_T0_im(val);

        gen_push_T0(s);

        break;

    case 0x8f: /* pop Ev */

        ot = dflag ? OT_LONG : OT_WORD;

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

        gen_pop_T0(s);

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

        gen_pop_update(s);

        break;

    case 0xc8: /* enter */

        {

            int level;

            val = lduw(s->pc);

            s->pc += 2;

            level = ldub(s->pc++);

            gen_enter(s, val, level);

        }

        break;

    case 0xc9: /* leave */

        /* XXX: exception not precise (ESP is update before potential exception) */

        if (s->ss32) {

            gen_op_mov_TN_reg[OT_LONG][0][R_EBP]();

            gen_op_mov_reg_T0[OT_LONG][R_ESP]();

        } else {

            gen_op_mov_TN_reg[OT_WORD][0][R_EBP]();

            gen_op_mov_reg_T0[OT_WORD][R_ESP]();

        }

        gen_pop_T0(s);

        ot = dflag ? OT_LONG : OT_WORD;

        gen_op_mov_reg_T0[ot][R_EBP]();

        gen_pop_update(s);

        break;

    case 0x06: /* push es */

    case 0x0e: /* push cs */

    case 0x16: /* push ss */

    case 0x1e: /* push ds */

        gen_op_movl_T0_seg(b >> 3);

        gen_push_T0(s);

        break;

    case 0x1a0: /* push fs */

    case 0x1a8: /* push gs */

        gen_op_movl_T0_seg(((b >> 3) & 7) + R_FS);

        gen_push_T0(s);

        break;

    case 0x07: /* pop es */

    case 0x17: /* pop ss */

    case 0x1f: /* pop ds */

        gen_pop_T0(s);

        gen_movl_seg_T0(s, b >> 3);

        gen_pop_update(s);

        break;

    case 0x1a1: /* pop fs */

    case 0x1a9: /* pop gs */

        gen_pop_T0(s);

        gen_movl_seg_T0(s, ((b >> 3) & 7) + R_FS);

        gen_pop_update(s);

        break;

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

        /* mov */

    case 0x88:

    case 0x89: /* mov Gv, Ev */

        if ((b & 1) == 0)

            ot = OT_BYTE;

        else

            ot = dflag ? OT_LONG : OT_WORD;

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

        reg = (modrm >> 3) & 7;

        /* generate a generic store */

        gen_ldst_modrm(s, modrm, ot, OR_EAX + reg, 1);

        break;

    case 0xc6:

    case 0xc7: /* mov Ev, Iv */

        if ((b & 1) == 0)

            ot = OT_BYTE;

        else

            ot = dflag ? OT_LONG : OT_WORD;

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

        mod = (modrm >> 6) & 3;

        if (mod != 3)

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

        val = insn_get(s, ot);

        gen_op_movl_T0_im(val);

        if (mod != 3)

            gen_op_st_T0_A0[ot]();

        else

            gen_op_mov_reg_T0[ot][modrm & 7]();

        break;

    case 0x8a:

    case 0x8b: /* mov Ev, Gv */

        if ((b & 1) == 0)

            ot = OT_BYTE;

        else

            ot = dflag ? OT_LONG : OT_WORD;

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

        reg = (modrm >> 3) & 7;

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

        gen_op_mov_reg_T0[ot][reg]();

        break;

    case 0x8e: /* mov seg, Gv */

        ot = dflag ? OT_LONG : OT_WORD;

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

        reg = (modrm >> 3) & 7;

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

        if (reg >= 6 || reg == R_CS)

            goto illegal_op;

        gen_movl_seg_T0(s, reg);

        break;

    case 0x8c: /* mov Gv, seg */

        ot = dflag ? OT_LONG : OT_WORD;

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

        reg = (modrm >> 3) & 7;

        if (reg >= 6)

            goto illegal_op;

        gen_op_movl_T0_seg(reg);

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

        break;

    case 0x1b6: /* movzbS Gv, Eb */

    case 0x1b7: /* movzwS Gv, Eb */

    case 0x1be: /* movsbS Gv, Eb */

    case 0x1bf: /* movswS Gv, Eb */

        {

            int d_ot;

            /* d_ot is the size of destination */

            d_ot = dflag + OT_WORD;

            /* ot is the size of source */

            ot = (b & 1) + OT_BYTE;

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

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

            mod = (modrm >> 6) & 3;

            rm = modrm & 7;

            if (mod == 3) {

                gen_op_mov_TN_reg[ot][0][rm]();

                switch(ot | (b & 8)) {

                case OT_BYTE:

                    gen_op_movzbl_T0_T0();

                    break;

                case OT_BYTE | 8:

                    gen_op_movsbl_T0_T0();

                    break;

                case OT_WORD:

                    gen_op_movzwl_T0_T0();

                    break;

                default:

                case OT_WORD | 8:

                    gen_op_movswl_T0_T0();

                    break;

                }

                gen_op_mov_reg_T0[d_ot][reg]();

            } else {

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

                if (b & 8) {

                    gen_op_lds_T0_A0[ot]();

                } else {

                    gen_op_ldu_T0_A0[ot]();

                }

                gen_op_mov_reg_T0[d_ot][reg]();

            }

        }

        break;

    case 0x8d: /* lea */

        ot = dflag ? OT_LONG : OT_WORD;

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

        reg = (modrm >> 3) & 7;

        /* we must ensure that no segment is added */

        s->prefix &= ~(PREFIX_CS | PREFIX_SS | PREFIX_DS |

                       PREFIX_ES | PREFIX_FS | PREFIX_GS);

        val = s->addseg;

        s->addseg = 0;

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

        s->addseg = val;

        gen_op_mov_reg_A0[ot - OT_WORD][reg]();

        break;

    case 0xa0: /* mov EAX, Ov */

    case 0xa1:

    case 0xa2: /* mov Ov, EAX */

    case 0xa3:

        if ((b & 1) == 0)

            ot = OT_BYTE;

        else

            ot = dflag ? OT_LONG : OT_WORD;

        if (s->aflag)

            offset_addr = insn_get(s, OT_LONG);

        else

            offset_addr = insn_get(s, OT_WORD);

        gen_op_movl_A0_im(offset_addr);

        /* handle override */

        /* XXX: factorize that */

        {

            int override, must_add_seg;

            override = R_DS;

            must_add_seg = s->addseg;

            if (s->prefix & (PREFIX_CS | PREFIX_SS | PREFIX_DS |

                             PREFIX_ES | PREFIX_FS | PREFIX_GS)) {

                if (s->prefix & PREFIX_ES)

                    override = R_ES;

                else if (s->prefix & PREFIX_CS)

                    override = R_CS;

                else if (s->prefix & PREFIX_SS)

                    override = R_SS;

                else if (s->prefix & PREFIX_DS)

                    override = R_DS;

                else if (s->prefix & PREFIX_FS)

                    override = R_FS;

                else

                    override = R_GS;

                must_add_seg = 1;

            }

            if (must_add_seg) {

                gen_op_addl_A0_seg(offsetof(CPUX86State,seg_cache[override].base));

            }

        }

        if ((b & 2) == 0) {

            gen_op_ld_T0_A0[ot]();

            gen_op_mov_reg_T0[ot][R_EAX]();

        } else {

            gen_op_mov_TN_reg[ot][0][R_EAX]();

            gen_op_st_T0_A0[ot]();

        }

        break;

    case 0xd7: /* xlat */

        /* handle override */

        gen_op_movl_A0_reg[R_EBX]();

        gen_op_addl_A0_AL();

        if (s->aflag == 0)

            gen_op_andl_A0_ffff();

        /* XXX: factorize that */

        {

            int override, must_add_seg;

            override = R_DS;

            must_add_seg = s->addseg;

            if (s->prefix & (PREFIX_CS | PREFIX_SS | PREFIX_DS |

                             PREFIX_ES | PREFIX_FS | PREFIX_GS)) {

                if (s->prefix & PREFIX_ES)

                    override = R_ES;

                else if (s->prefix & PREFIX_CS)

                    override = R_CS;

                else if (s->prefix & PREFIX_SS)

                    override = R_SS;

                else if (s->prefix & PREFIX_DS)

                    override = R_DS;

                else if (s->prefix & PREFIX_FS)

                    override = R_FS;

                else

                    override = R_GS;

                must_add_seg = 1;

            }

            if (must_add_seg) {

                gen_op_addl_A0_seg(offsetof(CPUX86State,seg_cache[override].base));

            }

        }

        gen_op_ldub_T0_A0();

        gen_op_mov_reg_T0[OT_BYTE][R_EAX]();

        break;

    case 0xb0 ... 0xb7: /* mov R, Ib */

        val = insn_get(s, OT_BYTE);

        gen_op_movl_T0_im(val);

        gen_op_mov_reg_T0[OT_BYTE][b & 7]();

        break;

    case 0xb8 ... 0xbf: /* mov R, Iv */

        ot = dflag ? OT_LONG : OT_WORD;

        val = insn_get(s, ot);

        reg = OR_EAX + (b & 7);

        gen_op_movl_T0_im(val);

        gen_op_mov_reg_T0[ot][reg]();

        break;

    case 0x91 ... 0x97: /* xchg R, EAX */

        ot = dflag ? OT_LONG : OT_WORD;

        reg = b & 7;

        rm = R_EAX;

        goto do_xchg_reg;

    case 0x86:

    case 0x87: /* xchg Ev, Gv */

        if ((b & 1) == 0)

            ot = OT_BYTE;

        else

            ot = dflag ? OT_LONG : OT_WORD;

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

        reg = (modrm >> 3) & 7;

        mod = (modrm >> 6) & 3;

        if (mod == 3) {

            rm = modrm & 7;

        do_xchg_reg:

            gen_op_mov_TN_reg[ot][0][reg]();

            gen_op_mov_TN_reg[ot][1][rm]();

            gen_op_mov_reg_T0[ot][rm]();

            gen_op_mov_reg_T1[ot][reg]();

        } else {

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

            gen_op_mov_TN_reg[ot][0][reg]();

            /* for xchg, lock is implicit */

            if (!(prefixes & PREFIX_LOCK))

                gen_op_lock();

            gen_op_ld_T1_A0[ot]();

            gen_op_st_T0_A0[ot]();

            if (!(prefixes & PREFIX_LOCK))

                gen_op_unlock();

            gen_op_mov_reg_T1[ot][reg]();

        }

        break;

    case 0xc4: /* les Gv */

        op = R_ES;

        goto do_lxx;

    case 0xc5: /* lds Gv */

        op = R_DS;

        goto do_lxx;

    case 0x1b2: /* lss Gv */

        op = R_SS;

        goto do_lxx;

    case 0x1b4: /* lfs Gv */

        op = R_FS;

        goto do_lxx;

    case 0x1b5: /* lgs Gv */

        op = R_GS;

    do_lxx:

        ot = dflag ? OT_LONG : OT_WORD;

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

        reg = (modrm >> 3) & 7;

        mod = (modrm >> 6) & 3;

        if (mod == 3)

            goto illegal_op;

        gen_op_ld_T1_A0[ot]();

        gen_op_addl_A0_im(1 << (ot - OT_WORD + 1));

        /* load the segment first to handle exceptions properly */

        gen_op_lduw_T0_A0();

        gen_movl_seg_T0(s, op);

        /* then put the data */

        gen_op_mov_reg_T1[ot][reg]();

        break;

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

        /* shifts */

    case 0xc0:

    case 0xc1:

        /* shift Ev,Ib */

        shift = 2;

    grp2:

        {

            if ((b & 1) == 0)

                ot = OT_BYTE;

            else

                ot = dflag ? OT_LONG : OT_WORD;

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

            mod = (modrm >> 6) & 3;

            rm = modrm & 7;

            op = (modrm >> 3) & 7;

            if (mod != 3) {

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

                gen_op_ld_T0_A0[ot]();

                opreg = OR_TMP0;

            } else {

                opreg = rm + OR_EAX;

            }

            /* simpler op */

            if (shift == 0) {

                gen_shift(s, op, ot, opreg, OR_ECX);

            } else {

                if (shift == 2) {

                    shift = ldub(s->pc++);

                }

                gen_shifti(s, op, ot, opreg, shift);

            }

            if (mod != 3) {

                gen_op_st_T0_A0[ot]();

            }

        }

        break;

    case 0xd0:

    case 0xd1:

        /* shift Ev,1 */

        shift = 1;

        goto grp2;

    case 0xd2:

    case 0xd3:

        /* shift Ev,cl */

        shift = 0;

        goto grp2;

    case 0x1a4: /* shld imm */

        op = 0;

        shift = 1;

        goto do_shiftd;

    case 0x1a5: /* shld cl */

        op = 0;

        shift = 0;

        goto do_shiftd;

    case 0x1ac: /* shrd imm */

        op = 1;

        shift = 1;

        goto do_shiftd;

    case 0x1ad: /* shrd cl */

        op = 1;

        shift = 0;

    do_shiftd:

        ot = dflag ? OT_LONG : OT_WORD;

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

        mod = (modrm >> 6) & 3;

        rm = modrm & 7;

        reg = (modrm >> 3) & 7;

        if (mod != 3) {

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

            gen_op_ld_T0_A0[ot]();

        } else {

            gen_op_mov_TN_reg[ot][0][rm]();

        }

        gen_op_mov_TN_reg[ot][1][reg]();

        if (shift) {

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

            val &= 0x1f;

            if (val) {

                gen_op_shiftd_T0_T1_im_cc[ot - OT_WORD][op](val);

                if (op == 0 && ot != OT_WORD)

                    s->cc_op = CC_OP_SHLB + ot;

                else

                    s->cc_op = CC_OP_SARB + ot;

            }

        } else {

            if (s->cc_op != CC_OP_DYNAMIC)

                gen_op_set_cc_op(s->cc_op);

            gen_op_shiftd_T0_T1_ECX_cc[ot - OT_WORD][op]();

            s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */

        }

        if (mod != 3) {

            gen_op_st_T0_A0[ot]();

        } else {

            gen_op_mov_reg_T0[ot][rm]();

        }

        break;

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

        /* floats */

    case 0xd8 ... 0xdf:

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

        mod = (modrm >> 6) & 3;

        rm = modrm & 7;

        op = ((b & 7) << 3) | ((modrm >> 3) & 7);

        if (mod != 3) {

            /* memory op */

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

            switch(op) {

            case 0x00 ... 0x07: /* fxxxs */

            case 0x10 ... 0x17: /* fixxxl */

            case 0x20 ... 0x27: /* fxxxl */

            case 0x30 ... 0x37: /* fixxx */

                {

                    int op1;

                    op1 = op & 7;

                    switch(op >> 4) {

                    case 0:

                        gen_op_flds_FT0_A0();

                        break;

                    case 1:

                        gen_op_fildl_FT0_A0();

                        break;

                    case 2:

                        gen_op_fldl_FT0_A0();

                        break;

                    case 3:

                    default:

                        gen_op_fild_FT0_A0();

                        break;

                    }

                    gen_op_fp_arith_ST0_FT0[op1]();

                    if (op1 == 3) {

                        /* fcomp needs pop */

                        gen_op_fpop();

                    }

                }

                break;

            case 0x08: /* flds */

            case 0x0a: /* fsts */

            case 0x0b: /* fstps */

            case 0x18: /* fildl */

            case 0x1a: /* fistl */

            case 0x1b: /* fistpl */

            case 0x28: /* fldl */

            case 0x2a: /* fstl */

            case 0x2b: /* fstpl */

            case 0x38: /* filds */

            case 0x3a: /* fists */

            case 0x3b: /* fistps */

                switch(op & 7) {

                case 0:

                    gen_op_fpush();

                    switch(op >> 4) {

                    case 0:

                        gen_op_flds_ST0_A0();

                        break;

                    case 1:

                        gen_op_fildl_ST0_A0();

                        break;

                    case 2:

                        gen_op_fldl_ST0_A0();

                        break;

                    case 3:

                    default:

                        gen_op_fild_ST0_A0();

                        break;

                    }

                    break;

                default:

                    switch(op >> 4) {

                    case 0:

                        gen_op_fsts_ST0_A0();

                        break;

                    case 1:

                        gen_op_fistl_ST0_A0();

                        break;

                    case 2:

                        gen_op_fstl_ST0_A0();

                        break;

                    case 3:

                    default:

                        gen_op_fist_ST0_A0();

                        break;

                    }

                    if ((op & 7) == 3)

                        gen_op_fpop();

                    break;

                }

                break;

            case 0x0d: /* fldcw mem */

                gen_op_fldcw_A0();

                break;

            case 0x0f: /* fnstcw mem */

                gen_op_fnstcw_A0();

                break;

            case 0x1d: /* fldt mem */

                gen_op_fpush();

                gen_op_fldt_ST0_A0();

                break;

            case 0x1f: /* fstpt mem */

                gen_op_fstt_ST0_A0();

                gen_op_fpop();

                break;

            case 0x2f: /* fnstsw mem */

                gen_op_fnstsw_A0();

                break;

            case 0x3c: /* fbld */

                gen_op_fpush();

                gen_op_fbld_ST0_A0();

                break;

            case 0x3e: /* fbstp */

                gen_op_fbst_ST0_A0();

                gen_op_fpop();

                break;

            case 0x3d: /* fildll */

                gen_op_fpush();

                gen_op_fildll_ST0_A0();

                break;

            case 0x3f: /* fistpll */

                gen_op_fistll_ST0_A0();

                gen_op_fpop();

                break;

            default:

                goto illegal_op;

            }

        } else {

            /* register float ops */

            opreg = rm;

            switch(op) {

            case 0x08: /* fld sti */

                gen_op_fpush();

                gen_op_fmov_ST0_STN((opreg + 1) & 7);

                break;

            case 0x09: /* fxchg sti */

                gen_op_fxchg_ST0_STN(opreg);

                break;

            case 0x0a: /* grp d9/2 */

                switch(rm) {

                case 0: /* fnop */

                    break;

                default:

                    goto illegal_op;

                }

                break;

            case 0x0c: /* grp d9/4 */

                switch(rm) {

                case 0: /* fchs */

                    gen_op_fchs_ST0();

                    break;

                case 1: /* fabs */

                    gen_op_fabs_ST0();

                    break;

                case 4: /* ftst */

                    gen_op_fldz_FT0();

                    gen_op_fcom_ST0_FT0();

                    break;

                case 5: /* fxam */

                    gen_op_fxam_ST0();

                    break;

                default:

                    goto illegal_op;

                }

                break;

            case 0x0d: /* grp d9/5 */

                {

                    switch(rm) {

                    case 0:

                        gen_op_fpush();

                        gen_op_fld1_ST0();

                        break;

                    case 1:

                        gen_op_fpush();

                        gen_op_fldl2t_ST0();

                        break;

                    case 2:

                        gen_op_fpush();

                        gen_op_fldl2e_ST0();

                        break;

                    case 3:

                        gen_op_fpush();

                        gen_op_fldpi_ST0();

                        break;

                    case 4:

                        gen_op_fpush();

                        gen_op_fldlg2_ST0();

                        break;

                    case 5:

                        gen_op_fpush();

                        gen_op_fldln2_ST0();

                        break;

                    case 6:

                        gen_op_fpush();

                        gen_op_fldz_ST0();

                        break;

                    default:

                        goto illegal_op;

                    }

                }

                break;

            case 0x0e: /* grp d9/6 */

                switch(rm) {

                case 0: /* f2xm1 */

                    gen_op_f2xm1();

                    break;

                case 1: /* fyl2x */

                    gen_op_fyl2x();

                    break;

                case 2: /* fptan */

                    gen_op_fptan();

                    break;

                case 3: /* fpatan */

                    gen_op_fpatan();

                    break;

                case 4: /* fxtract */

                    gen_op_fxtract();

                    break;

                case 5: /* fprem1 */

                    gen_op_fprem1();

                    break;

                case 6: /* fdecstp */

                    gen_op_fdecstp();

                    break;

                default:

                case 7: /* fincstp */

                    gen_op_fincstp();

                    break;

                }

                break;

            case 0x0f: /* grp d9/7 */

                switch(rm) {

                case 0: /* fprem */

                    gen_op_fprem();

                    break;

                case 1: /* fyl2xp1 */

                    gen_op_fyl2xp1();

                    break;

                case 2: /* fsqrt */

                    gen_op_fsqrt();

                    break;

                case 3: /* fsincos */

                    gen_op_fsincos();

                    break;

                case 5: /* fscale */

                    gen_op_fscale();

                    break;

                case 4: /* frndint */

                    gen_op_frndint();

                    break;

                case 6: /* fsin */

                    gen_op_fsin();

                    break;

                default:

                case 7: /* fcos */

                    gen_op_fcos();

                    break;

                }

                break;

            case 0x00: case 0x01: case 0x04 ... 0x07: /* fxxx st, sti */

            case 0x20: case 0x21: case 0x24 ... 0x27: /* fxxx sti, st */

            case 0x30: case 0x31: case 0x34 ... 0x37: /* fxxxp sti, st */

                {

                    int op1;

                    op1 = op & 7;

                    if (op >= 0x20) {

                        gen_op_fp_arith_STN_ST0[op1](opreg);

                        if (op >= 0x30)

                            gen_op_fpop();

                    } else {

                        gen_op_fmov_FT0_STN(opreg);

                        gen_op_fp_arith_ST0_FT0[op1]();

                    }

                }

                break;

            case 0x02: /* fcom */

                gen_op_fmov_FT0_STN(opreg);

                gen_op_fcom_ST0_FT0();

                break;

            case 0x03: /* fcomp */

                gen_op_fmov_FT0_STN(opreg);

                gen_op_fcom_ST0_FT0();

                gen_op_fpop();

                break;

            case 0x15: /* da/5 */

                switch(rm) {

                case 1: /* fucompp */

                    gen_op_fmov_FT0_STN(1);

                    gen_op_fucom_ST0_FT0();

                    gen_op_fpop();

                    gen_op_fpop();

                    break;

                default:

                    goto illegal_op;

                }

                break;

            case 0x1c:

                switch(rm) {

                case 2: /* fclex */

                    gen_op_fclex();

                    break;

                case 3: /* fninit */

                    gen_op_fninit();

                    break;

                default:

                    goto illegal_op;

                }

                break;

            case 0x2a: /* fst sti */

                gen_op_fmov_STN_ST0(opreg);

                break;

            case 0x2b: /* fstp sti */

                gen_op_fmov_STN_ST0(opreg);

                gen_op_fpop();

                break;

            case 0x2c: /* fucom st(i) */

                gen_op_fmov_FT0_STN(opreg);

                gen_op_fucom_ST0_FT0();

                break;

            case 0x2d: /* fucomp st(i) */

                gen_op_fmov_FT0_STN(opreg);

                gen_op_fucom_ST0_FT0();

                gen_op_fpop();

                break;

            case 0x33: /* de/3 */

                switch(rm) {

                case 1: /* fcompp */

                    gen_op_fmov_FT0_STN(1);

                    gen_op_fcom_ST0_FT0();

                    gen_op_fpop();

                    gen_op_fpop();

                    break;

                default:

                    goto illegal_op;

                }

                break;

            case 0x3c: /* df/4 */

                switch(rm) {

                case 0:

                    gen_op_fnstsw_EAX();

                    break;

                default:

                    goto illegal_op;

                }

                break;

            default:

                goto illegal_op;

            }

        }

        break;

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

        /* string ops */

    case 0xa4: /* movsS */

    case 0xa5:

        if ((b & 1) == 0)

            ot = OT_BYTE;

        else

            ot = dflag ? OT_LONG : OT_WORD;

        if (prefixes & PREFIX_REPZ) {

            gen_op_movs[3 + ot]();

        } else {

            gen_op_movs[ot]();

        }

        break;

    case 0xaa: /* stosS */

    case 0xab:

        if ((b & 1) == 0)

            ot = OT_BYTE;

        else

            ot = dflag ? OT_LONG : OT_WORD;

        if (prefixes & PREFIX_REPZ) {

            gen_op_stos[3 + ot]();

        } else {

            gen_op_stos[ot]();

        }

        break;

    case 0xac: /* lodsS */

    case 0xad:

        if ((b & 1) == 0)

            ot = OT_BYTE;

        else

            ot = dflag ? OT_LONG : OT_WORD;

        if (prefixes & PREFIX_REPZ) {

            gen_op_lods[3 + ot]();

        } else {

            gen_op_lods[ot]();

        }

        break;

    case 0xae: /* scasS */

    case 0xaf:

        if ((b & 1) == 0)

            ot = OT_BYTE;

        else

            ot = dflag ? OT_LONG : OT_WORD;

        if (prefixes & PREFIX_REPNZ) {

            if (s->cc_op != CC_OP_DYNAMIC)

                gen_op_set_cc_op(s->cc_op);

            gen_op_scas[6 + ot]();

            s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */

        } else if (prefixes & PREFIX_REPZ) {

            if (s->cc_op != CC_OP_DYNAMIC)

                gen_op_set_cc_op(s->cc_op);

            gen_op_scas[3 + ot]();

            s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */

        } else {

            gen_op_scas[ot]();

            s->cc_op = CC_OP_SUBB + ot;

        }

        break;

    case 0xa6: /* cmpsS */

    case 0xa7:

        if ((b & 1) == 0)

            ot = OT_BYTE;

        else

            ot = dflag ? OT_LONG : OT_WORD;

        if (prefixes & PREFIX_REPNZ) {

            if (s->cc_op != CC_OP_DYNAMIC)

                gen_op_set_cc_op(s->cc_op);

            gen_op_cmps[6 + ot]();

            s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */

        } else if (prefixes & PREFIX_REPZ) {

            if (s->cc_op != CC_OP_DYNAMIC)

                gen_op_set_cc_op(s->cc_op);

            gen_op_cmps[3 + ot]();

            s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */

        } else {

            gen_op_cmps[ot]();

            s->cc_op = CC_OP_SUBB + ot;

        }

        break;

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

        /* port I/O */

    case 0x6c: /* insS */

    case 0x6d:

        if ((b & 1) == 0)

            ot = OT_BYTE;

        else

            ot = dflag ? OT_LONG : OT_WORD;

        if (prefixes & PREFIX_REPZ) {

            gen_op_ins[3 + ot]();

        } else {

            gen_op_ins[ot]();

        }

        break;

    case 0x6e: /* outsS */

    case 0x6f:

        if ((b & 1) == 0)

            ot = OT_BYTE;

        else

            ot = dflag ? OT_LONG : OT_WORD;

        if (prefixes & PREFIX_REPZ) {

            gen_op_outs[3 + ot]();

        } else {

            gen_op_outs[ot]();

        }

        break;

    case 0xe4:

    case 0xe5:

        if ((b & 1) == 0)

            ot = OT_BYTE;

        else

            ot = dflag ? OT_LONG : OT_WORD;

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

        gen_op_movl_T0_im(val);

        gen_op_in[ot]();

        gen_op_mov_reg_T1[ot][R_EAX]();

        break;

    case 0xe6:

    case 0xe7:

        if ((b & 1) == 0)

            ot = OT_BYTE;

        else

            ot = dflag ? OT_LONG : OT_WORD;

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

        gen_op_movl_T0_im(val);

        gen_op_mov_TN_reg[ot][1][R_EAX]();

        gen_op_out[ot]();

        break;

    case 0xec:

    case 0xed:

        if ((b & 1) == 0)

            ot = OT_BYTE;

        else

            ot = dflag ? OT_LONG : OT_WORD;

        gen_op_mov_TN_reg[OT_WORD][0][R_EDX]();

        gen_op_in[ot]();

        gen_op_mov_reg_T1[ot][R_EAX]();

        break;

    case 0xee:

    case 0xef:

        if ((b & 1) == 0)

            ot = OT_BYTE;

        else

            ot = dflag ? OT_LONG : OT_WORD;

        gen_op_mov_TN_reg[OT_WORD][0][R_EDX]();

        gen_op_mov_TN_reg[ot][1][R_EAX]();

        gen_op_out[ot]();

        break;

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

        /* control */

    case 0xc2: /* ret im */

        val = ldsw(s->pc);

        s->pc += 2;

        gen_pop_T0(s);

        if (s->ss32)

            gen_op_addl_ESP_im(val + (2 << s->dflag));

        else

            gen_op_addw_ESP_im(val + (2 << s->dflag));

        if (s->dflag == 0)

            gen_op_andl_T0_ffff();

        gen_op_jmp_T0();

        s->is_jmp = 1;

        break;

    case 0xc3: /* ret */

        gen_pop_T0(s);

        gen_pop_update(s);

        if (s->dflag == 0)

            gen_op_andl_T0_ffff();

        gen_op_jmp_T0();

        s->is_jmp = 1;

        break;

    case 0xca: /* lret im */

        val = ldsw(s->pc);

        s->pc += 2;

        /* pop offset */

        gen_pop_T0(s);

        if (s->dflag == 0)

            gen_op_andl_T0_ffff();

        gen_op_jmp_T0();

        gen_pop_update(s);

        /* pop selector */

        gen_pop_T0(s);

        gen_movl_seg_T0(s, R_CS);

        gen_pop_update(s);

        /* add stack offset */

        if (s->ss32)

            gen_op_addl_ESP_im(val + (2 << s->dflag));

        else

            gen_op_addw_ESP_im(val + (2 << s->dflag));

        s->is_jmp = 1;

        break;

    case 0xcb: /* lret */

        /* pop offset */

        gen_pop_T0(s);

        if (s->dflag == 0)

            gen_op_andl_T0_ffff();

        gen_op_jmp_T0();

        gen_pop_update(s);

        /* pop selector */

        gen_pop_T0(s);

        gen_movl_seg_T0(s, R_CS);

        gen_pop_update(s);

        s->is_jmp = 1;

        break;

    case 0xe8: /* call im */

        {

            unsigned int next_eip;

            ot = dflag ? OT_LONG : OT_WORD;

            val = insn_get(s, ot);

            next_eip = s->pc - s->cs_base;

            val += next_eip;

            if (s->dflag == 0)

                val &= 0xffff;

            gen_op_movl_T0_im(next_eip);

            gen_push_T0(s);

            gen_op_jmp_im(val);

            s->is_jmp = 1;

        }

        break;

    case 0x9a: /* lcall im */

        {

            unsigned int selector, offset;

            ot = dflag ? OT_LONG : OT_WORD;

            offset = insn_get(s, ot);

            selector = insn_get(s, OT_WORD);

            /* push return segment + offset */

            gen_op_movl_T0_seg(R_CS);

            gen_push_T0(s);

            next_eip = s->pc - s->cs_base;

            gen_op_movl_T0_im(next_eip);

            gen_push_T0(s);

            /* change cs and pc */

            gen_op_movl_T0_im(selector);

            gen_movl_seg_T0(s, R_CS);

            gen_op_jmp_im((unsigned long)offset);

            s->is_jmp = 1;

        }

        break;

    case 0xe9: /* jmp */

        ot = dflag ? OT_LONG : OT_WORD;

        val = insn_get(s, ot);

        val += s->pc - s->cs_base;

        if (s->dflag == 0)

            val = val & 0xffff;

        gen_op_jmp_im(val);

        s->is_jmp = 1;

        break;

    case 0xea: /* ljmp im */

        {

            unsigned int selector, offset;

            ot = dflag ? OT_LONG : OT_WORD;

            offset = insn_get(s, ot);

            selector = insn_get(s, OT_WORD);

            /* change cs and pc */

            gen_op_movl_T0_im(selector);

            gen_movl_seg_T0(s, R_CS);

            gen_op_jmp_im((unsigned long)offset);

            s->is_jmp = 1;

        }

        break;

    case 0xeb: /* jmp Jb */

        val = (int8_t)insn_get(s, OT_BYTE);

        val += s->pc - s->cs_base;

        if (s->dflag == 0)

            val = val & 0xffff;

        gen_op_jmp_im(val);

        s->is_jmp = 1;

        break;

    case 0x70 ... 0x7f: /* jcc Jb */

        val = (int8_t)insn_get(s, OT_BYTE);

        goto do_jcc;

    case 0x180 ... 0x18f: /* jcc Jv */

        if (dflag) {

            val = insn_get(s, OT_LONG);

        } else {

            val = (int16_t)insn_get(s, OT_WORD);

        }

    do_jcc:

        next_eip = s->pc - s->cs_base;

        val += next_eip;

        if (s->dflag == 0)

            val &= 0xffff;

        gen_jcc(s, b, val, next_eip);

        s->is_jmp = 1;

        break;

    case 0x190 ... 0x19f: /* setcc Gv */

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

        gen_setcc(s, b);

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

        break;

    case 0x140 ... 0x14f: /* cmov Gv, Ev */

        ot = dflag ? OT_LONG : OT_WORD;

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

        reg = (modrm >> 3) & 7;

        mod = (modrm >> 6) & 3;

        gen_setcc(s, b);

        if (mod != 3) {

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

            gen_op_ld_T1_A0[ot]();

        } else {

            rm = modrm & 7;

            gen_op_mov_TN_reg[ot][1][rm]();

        }

        gen_op_cmov_reg_T1_T0[ot - OT_WORD][reg]();

        break;

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

        /* flags */

    case 0x9c: /* pushf */

        if (s->cc_op != CC_OP_DYNAMIC)

            gen_op_set_cc_op(s->cc_op);

        gen_op_movl_T0_eflags();

        gen_push_T0(s);

        break;

    case 0x9d: /* popf */

        gen_pop_T0(s);

        gen_op_movl_eflags_T0();

        gen_pop_update(s);

        s->cc_op = CC_OP_EFLAGS;

        break;

    case 0x9e: /* sahf */

        gen_op_mov_TN_reg[OT_BYTE][0][R_AH]();

        if (s->cc_op != CC_OP_DYNAMIC)

            gen_op_set_cc_op(s->cc_op);

        gen_op_movb_eflags_T0();

        s->cc_op = CC_OP_EFLAGS;

        break;

    case 0x9f: /* lahf */

        if (s->cc_op != CC_OP_DYNAMIC)

            gen_op_set_cc_op(s->cc_op);

        gen_op_movl_T0_eflags();

        gen_op_mov_reg_T0[OT_BYTE][R_AH]();

        break;

    case 0xf5: /* cmc */

        if (s->cc_op != CC_OP_DYNAMIC)

            gen_op_set_cc_op(s->cc_op);

        gen_op_cmc();

        s->cc_op = CC_OP_EFLAGS;

        break;

    case 0xf8: /* clc */

        if (s->cc_op != CC_OP_DYNAMIC)

            gen_op_set_cc_op(s->cc_op);

        gen_op_clc();

        s->cc_op = CC_OP_EFLAGS;

        break;

    case 0xf9: /* stc */

        if (s->cc_op != CC_OP_DYNAMIC)

            gen_op_set_cc_op(s->cc_op);

        gen_op_stc();

        s->cc_op = CC_OP_EFLAGS;

        break;

    case 0xfc: /* cld */

        gen_op_cld();

        break;

    case 0xfd: /* std */

        gen_op_std();

        break;

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

        /* bit operations */

    case 0x1ba: /* bt/bts/btr/btc Gv, im */

        ot = dflag ? OT_LONG : OT_WORD;

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

        op = (modrm >> 3) & 7;

        mod = (modrm >> 6) & 3;

        rm = modrm & 7;

        if (mod != 3) {

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

            gen_op_ld_T0_A0[ot]();

        } else {

            gen_op_mov_TN_reg[ot][0][rm]();

        }

        /* load shift */

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

        gen_op_movl_T1_im(val);

        if (op < 4)

            goto illegal_op;

        op -= 4;

        gen_op_btx_T0_T1_cc[ot - OT_WORD][op]();

        s->cc_op = CC_OP_SARB + ot;

        if (op != 0) {

            if (mod != 3)

                gen_op_st_T0_A0[ot]();

            else

                gen_op_mov_reg_T0[ot][rm]();

        }

        break;

    case 0x1a3: /* bt Gv, Ev */

        op = 0;

        goto do_btx;

    case 0x1ab: /* bts */

        op = 1;

        goto do_btx;

    case 0x1b3: /* btr */

        op = 2;

        goto do_btx;

    case 0x1bb: /* btc */

        op = 3;

    do_btx:

        ot = dflag ? OT_LONG : OT_WORD;

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

        reg = (modrm >> 3) & 7;

        mod = (modrm >> 6) & 3;

        rm = modrm & 7;

        gen_op_mov_TN_reg[OT_LONG][1][reg]();

        if (mod != 3) {

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

            /* specific case: we need to add a displacement */

            if (ot == OT_WORD)

                gen_op_add_bitw_A0_T1();

            else

                gen_op_add_bitl_A0_T1();

            gen_op_ld_T0_A0[ot]();

        } else {

            gen_op_mov_TN_reg[ot][0][rm]();

        }

        gen_op_btx_T0_T1_cc[ot - OT_WORD][op]();

        s->cc_op = CC_OP_SARB + ot;

        if (op != 0) {

            if (mod != 3)

                gen_op_st_T0_A0[ot]();

            else

                gen_op_mov_reg_T0[ot][rm]();

        }

        break;

    case 0x1bc: /* bsf */

    case 0x1bd: /* bsr */

        ot = dflag ? OT_LONG : OT_WORD;

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

        reg = (modrm >> 3) & 7;

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

        gen_op_bsx_T0_cc[ot - OT_WORD][b & 1]();

        /* NOTE: we always write back the result. Intel doc says it is

           undefined if T0 == 0 */

        gen_op_mov_reg_T0[ot][reg]();

        s->cc_op = CC_OP_LOGICB + ot;

        break;

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

        /* bcd */

    case 0x27: /* daa */

        if (s->cc_op != CC_OP_DYNAMIC)

            gen_op_set_cc_op(s->cc_op);

        gen_op_daa();

        s->cc_op = CC_OP_EFLAGS;

        break;

    case 0x2f: /* das */

        if (s->cc_op != CC_OP_DYNAMIC)

            gen_op_set_cc_op(s->cc_op);

        gen_op_das();

        s->cc_op = CC_OP_EFLAGS;

        break;

    case 0x37: /* aaa */

        if (s->cc_op != CC_OP_DYNAMIC)

            gen_op_set_cc_op(s->cc_op);

        gen_op_aaa();

        s->cc_op = CC_OP_EFLAGS;

        break;

    case 0x3f: /* aas */

        if (s->cc_op != CC_OP_DYNAMIC)

            gen_op_set_cc_op(s->cc_op);

        gen_op_aas();

        s->cc_op = CC_OP_EFLAGS;

        break;

    case 0xd4: /* aam */

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

        gen_op_aam(val);

        s->cc_op = CC_OP_LOGICB;

        break;

    case 0xd5: /* aad */

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

        gen_op_aad(val);

        s->cc_op = CC_OP_LOGICB;

        break;

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

        /* misc */

    case 0x90: /* nop */

        break;

    case 0xcc: /* int3 */

        gen_op_int3((long)pc_start);

        s->is_jmp = 1;

        break;

    case 0xcd: /* int N */

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

        /* XXX: currently we ignore the interrupt number */

        gen_op_int_im((long)pc_start);

        s->is_jmp = 1;

        break;

    case 0xce: /* into */

        if (s->cc_op != CC_OP_DYNAMIC)

            gen_op_set_cc_op(s->cc_op);

        gen_op_into((long)pc_start, (long)s->pc);

        s->is_jmp = 1;

        break;

    case 0x1c8 ... 0x1cf: /* bswap reg */

        reg = b & 7;

        gen_op_mov_TN_reg[OT_LONG][0][reg]();

        gen_op_bswapl_T0();

        gen_op_mov_reg_T0[OT_LONG][reg]();

        break;

    case 0xd6: /* salc */

        if (s->cc_op != CC_OP_DYNAMIC)

            gen_op_set_cc_op(s->cc_op);

        gen_op_salc();

        break;

    case 0xe0: /* loopnz */

    case 0xe1: /* loopz */

        if (s->cc_op != CC_OP_DYNAMIC)

            gen_op_set_cc_op(s->cc_op);

        /* FALL THRU */

    case 0xe2: /* loop */

    case 0xe3: /* jecxz */

        val = (int8_t)insn_get(s, OT_BYTE);

        next_eip = s->pc - s->cs_base;

        val += next_eip;

        if (s->dflag == 0)

            val &= 0xffff;

        gen_op_loop[s->aflag][b & 3](val, next_eip);

        s->is_jmp = 1;

        break;

    case 0x131: /* rdtsc */

        gen_op_rdtsc();

        break;

#if 0

    case 0x1a2: /* cpuid */

        gen_insn0(OP_ASM);

        break;

#endif

    default:

        goto illegal_op;

    }

    /* lock generation */

    if (s->prefix & PREFIX_LOCK)

        gen_op_unlock();

    return (long)s->pc;

 illegal_op:

    /* XXX: ensure that no lock was generated */

    return -1;

}


static void pci_mmio_map(PCIDevice * pci_dev, int region_num,

                         uint32_t addr, uint32_t size, int type)

{

    PCIEEPRO100State *d = DO_UPCAST(PCIEEPRO100State, dev, pci_dev);

    logout("region %d, addr=0x%08x, size=0x%08x, type=%d\n",

           region_num, addr, size, type);

    if (region_num == 0) {

        /* Map control / status registers. */

        cpu_register_physical_memory(addr, size, d->eepro100.mmio_index);

        d->eepro100.region[region_num] = addr;

    }

}


uint32_t ldl_le_phys(target_phys_addr_t addr)

{

    return ldl_phys_internal(addr, DEVICE_LITTLE_ENDIAN);

}


static void ivshmem_check_memdev_is_busy(const Object *obj, const char *name,

                                         Object *val, Error **errp)

{

    if (host_memory_backend_is_mapped(MEMORY_BACKEND(val))) {

        char *path = object_get_canonical_path_component(val);

        error_setg(errp, "can't use already busy memdev: %s", path);

        g_free(path);

    } else {

        qdev_prop_allow_set_link_before_realize(obj, name, val, errp);

    }

}


static int connect_to_ssh(BDRVSSHState *s, QDict *options,

                          int ssh_flags, int creat_mode)

{

    int r, ret;

    Error *err = NULL;

    const char *host, *user, *path, *host_key_check;

    int port;

    host = qdict_get_str(options, "host");

    if (qdict_haskey(options, "port")) {

        port = qdict_get_int(options, "port");

    } else {

        port = 22;

    }

    path = qdict_get_str(options, "path");

    if (qdict_haskey(options, "user")) {

        user = qdict_get_str(options, "user");

    } else {

        user = g_get_user_name();

        if (!user) {

            ret = -errno;

            goto err;

        }

    }

    if (qdict_haskey(options, "host_key_check")) {

        host_key_check = qdict_get_str(options, "host_key_check");

    } else {

        host_key_check = "yes";

    }

    /* Construct the host:port name for inet_connect. */

    g_free(s->hostport);

    s->hostport = g_strdup_printf("%s:%d", host, port);

    /* Open the socket and connect. */

    s->sock = inet_connect(s->hostport, &err);

    if (err != NULL) {

        ret = -errno;

        qerror_report_err(err);

        error_free(err);

        goto err;

    }

    /* Create SSH session. */

    s->session = libssh2_session_init();

    if (!s->session) {

        ret = -EINVAL;

        session_error_report(s, "failed to initialize libssh2 session");

        goto err;

    }

#if TRACE_LIBSSH2 != 0

    libssh2_trace(s->session, TRACE_LIBSSH2);

#endif

    r = libssh2_session_handshake(s->session, s->sock);

    if (r != 0) {

        ret = -EINVAL;

        session_error_report(s, "failed to establish SSH session");

        goto err;

    }

    /* Check the remote host's key against known_hosts. */

    ret = check_host_key(s, host, port, host_key_check, &err);

    if (ret < 0) {

        qerror_report_err(err);

        error_free(err);

        goto err;

    }

    /* Authenticate. */

    ret = authenticate(s, user);

    if (ret < 0) {

        goto err;

    }

    /* Start SFTP. */

    s->sftp = libssh2_sftp_init(s->session);

    if (!s->sftp) {

        session_error_report(s, "failed to initialize sftp handle");

        ret = -EINVAL;

        goto err;

    }

    /* Open the remote file. */

    DPRINTF("opening file %s flags=0x%x creat_mode=0%o",

            path, ssh_flags, creat_mode);

    s->sftp_handle = libssh2_sftp_open(s->sftp, path, ssh_flags, creat_mode);

    if (!s->sftp_handle) {

        session_error_report(s, "failed to open remote file '%s'", path);

        ret = -EINVAL;

        goto err;

    }

    r = libssh2_sftp_fstat(s->sftp_handle, &s->attrs);

    if (r < 0) {

        sftp_error_report(s, "failed to read file attributes");

        return -EINVAL;

    }

    /* Delete the options we've used; any not deleted will cause the

     * block layer to give an error about unused options.

     */

    qdict_del(options, "host");

    qdict_del(options, "port");

    qdict_del(options, "user");

    qdict_del(options, "path");

    qdict_del(options, "host_key_check");

    return 0;

 err:

    if (s->sftp_handle) {

        libssh2_sftp_close(s->sftp_handle);

    }

    s->sftp_handle = NULL;

    if (s->sftp) {

        libssh2_sftp_shutdown(s->sftp);

    }

    s->sftp = NULL;

    if (s->session) {

        libssh2_session_disconnect(s->session,

                                   "from qemu ssh client: "

                                   "error opening connection");

        libssh2_session_free(s->session);

    }

    s->session = NULL;

    return ret;

}


int kvm_irqchip_add_irq_notifier(KVMState *s, EventNotifier *n, int virq)

{

    return -ENOSYS;

}


static void gen_st_asi(DisasContext *dc, TCGv src, TCGv addr,

                       int insn, int size)

{

    TCGv_i32 r_asi, r_size;

    r_asi = gen_get_asi(dc, insn);

    r_size = tcg_const_i32(size);

#ifdef TARGET_SPARC64

    gen_helper_st_asi(cpu_env, addr, src, r_asi, r_size);

#else

    {

        TCGv_i64 t64 = tcg_temp_new_i64();

        tcg_gen_extu_tl_i64(t64, src);

        gen_helper_st_asi(cpu_env, addr, t64, r_asi, r_size);

        tcg_temp_free_i64(t64);

    }

#endif

    tcg_temp_free_i32(r_size);

    tcg_temp_free_i32(r_asi);

}


static double tget_double(const uint8_t **p, int le)

{

    av_alias64 i = { .u64 = le ? AV_RL64(*p) : AV_RB64(*p)};

    *p += 8;

    return i.f64;

}


void empty_slot_init(target_phys_addr_t addr, uint64_t slot_size)

{

    if (slot_size > 0) {

        /* Only empty slots larger than 0 byte need handling. */

        DeviceState *dev;

        SysBusDevice *s;

        EmptySlot *e;

        dev = qdev_create(NULL, "empty_slot");

        s = sysbus_from_qdev(dev);

        e = FROM_SYSBUS(EmptySlot, s);

        e->size = slot_size;

        qdev_init_nofail(dev);

        sysbus_mmio_map(s, 0, addr);

    }

}


build_fadt(GArray *table_data, BIOSLinker *linker, unsigned dsdt)

{

    AcpiFadtDescriptorRev5_1 *fadt = acpi_data_push(table_data, sizeof(*fadt));

    /* Hardware Reduced = 1 and use PSCI 0.2+ and with HVC */

    fadt->flags = cpu_to_le32(1 << ACPI_FADT_F_HW_REDUCED_ACPI);

    fadt->arm_boot_flags = cpu_to_le16((1 << ACPI_FADT_ARM_USE_PSCI_G_0_2) |

                                       (1 << ACPI_FADT_ARM_PSCI_USE_HVC));

    /* ACPI v5.1 (fadt->revision.fadt->minor_revision) */

    fadt->minor_revision = 0x1;

    fadt->dsdt = cpu_to_le32(dsdt);

    /* DSDT address to be filled by Guest linker */

    bios_linker_loader_add_pointer(linker, ACPI_BUILD_TABLE_FILE,

                                   ACPI_BUILD_TABLE_FILE,

                                   &fadt->dsdt,

                                   sizeof fadt->dsdt);

    build_header(linker, table_data,

                 (void *)fadt, "FACP", sizeof(*fadt), 5, NULL, NULL);

}


void apic_enable_vapic(DeviceState *d, target_phys_addr_t paddr)

{

    APICCommonState *s = DO_UPCAST(APICCommonState, busdev.qdev, d);

    APICCommonClass *info = APIC_COMMON_GET_CLASS(s);

    s->vapic_paddr = paddr;

    info->vapic_base_update(s);

}


void qmp_blockdev_snapshot_internal_sync(const char *device,

                                         const char *name,

                                         Error **errp)

{

    BlockdevSnapshotInternal snapshot = {

        .device = (char *) device,

        .name = (char *) name

    };

    TransactionAction action = {

        .type = TRANSACTION_ACTION_KIND_BLOCKDEV_SNAPSHOT_INTERNAL_SYNC,

        .u.blockdev_snapshot_internal_sync = &snapshot,

    };

    blockdev_do_action(&action, errp);

}


void nvdimm_acpi_hotplug(AcpiNVDIMMState *state)

{

    nvdimm_build_fit_buffer(&state->fit_buf);

}


int ppc_radix64_handle_mmu_fault(PowerPCCPU *cpu, vaddr eaddr, int rwx,

                                 int mmu_idx)

{

    CPUState *cs = CPU(cpu);

    CPUPPCState *env = &cpu->env;

    PPCVirtualHypervisorClass *vhc =

        PPC_VIRTUAL_HYPERVISOR_GET_CLASS(cpu->vhyp);

    hwaddr raddr, pte_addr;

    uint64_t lpid = 0, pid = 0, offset, size, patbe, prtbe0, pte;

    int page_size, prot, fault_cause = 0;

    assert((rwx == 0) || (rwx == 1) || (rwx == 2));

    assert(!msr_hv); /* For now there is no Radix PowerNV Support */

    assert(cpu->vhyp);

    assert(ppc64_use_proc_tbl(cpu));

    /* Real Mode Access */

    if (((rwx == 2) && (msr_ir == 0)) || ((rwx != 2) && (msr_dr == 0))) {

        /* In real mode top 4 effective addr bits (mostly) ignored */

        raddr = eaddr & 0x0FFFFFFFFFFFFFFFULL;

        tlb_set_page(cs, eaddr & TARGET_PAGE_MASK, raddr & TARGET_PAGE_MASK,

                     PAGE_READ | PAGE_WRITE | PAGE_EXEC, mmu_idx,

                     TARGET_PAGE_SIZE);

        return 0;

    }

    /* Virtual Mode Access - get the fully qualified address */

    if (!ppc_radix64_get_fully_qualified_addr(env, eaddr, &lpid, &pid)) {

        ppc_radix64_raise_segi(cpu, rwx, eaddr);

        return 1;

    }

    /* Get Process Table */

    patbe = vhc->get_patbe(cpu->vhyp);

    /* Index Process Table by PID to Find Corresponding Process Table Entry */

    offset = pid * sizeof(struct prtb_entry);

    size = 1ULL << ((patbe & PATBE1_R_PRTS) + 12);

    if (offset >= size) {

        /* offset exceeds size of the process table */

        ppc_radix64_raise_si(cpu, rwx, eaddr, DSISR_NOPTE);

        return 1;

    }

    prtbe0 = ldq_phys(cs->as, (patbe & PATBE1_R_PRTB) + offset);

    /* Walk Radix Tree from Process Table Entry to Convert EA to RA */

    page_size = PRTBE_R_GET_RTS(prtbe0);

    pte = ppc_radix64_walk_tree(cpu, rwx, eaddr & R_EADDR_MASK,

                                prtbe0 & PRTBE_R_RPDB, prtbe0 & PRTBE_R_RPDS,

                                &raddr, &page_size, &fault_cause, &prot,

                                &pte_addr);

    if (!pte) {

        ppc_radix64_raise_si(cpu, rwx, eaddr, fault_cause);

        return 1;

    }

    /* Update Reference and Change Bits */

    ppc_radix64_set_rc(cpu, rwx, pte, pte_addr, &prot);

    tlb_set_page(cs, eaddr & TARGET_PAGE_MASK, raddr & TARGET_PAGE_MASK,

                 prot, mmu_idx, 1UL << page_size);

    return 0;

}


int cpu_restore_state(TranslationBlock *tb,

                      CPUState *env, unsigned long searched_pc,

                      void *puc)

{

    TCGContext *s = &tcg_ctx;

    int j;

    unsigned long tc_ptr;

#ifdef CONFIG_PROFILER

    int64_t ti;

#endif

#ifdef CONFIG_PROFILER

    ti = profile_getclock();

#endif

    tcg_func_start(s);

    if (gen_intermediate_code_pc(env, tb) < 0)

        return -1;

    /* find opc index corresponding to search_pc */

    tc_ptr = (unsigned long)tb->tc_ptr;

    if (searched_pc < tc_ptr)

        return -1;

    s->tb_next_offset = tb->tb_next_offset;

#ifdef USE_DIRECT_JUMP

    s->tb_jmp_offset = tb->tb_jmp_offset;

    s->tb_next = NULL;

#else

    s->tb_jmp_offset = NULL;

    s->tb_next = tb->tb_next;

#endif

    j = dyngen_code_search_pc(s, (uint8_t *)tc_ptr,

                              (void *)searched_pc);

    if (j < 0)

        return -1;

    /* now find start of instruction before */

    while (gen_opc_instr_start[j] == 0)

        j--;

#if defined(TARGET_I386)

    {

        int cc_op;

#ifdef DEBUG_DISAS

        if (loglevel & CPU_LOG_TB_OP) {

            int i;

            fprintf(logfile, "RESTORE:\n");

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

                if (gen_opc_instr_start[i]) {

                    fprintf(logfile, "0x%04x: " TARGET_FMT_lx "\n", i, gen_opc_pc[i]);

                }

            }

            fprintf(logfile, "spc=0x%08lx j=0x%x eip=" TARGET_FMT_lx " cs_base=%x\n",

                    searched_pc, j, gen_opc_pc[j] - tb->cs_base,

                    (uint32_t)tb->cs_base);

        }

#endif

        env->eip = gen_opc_pc[j] - tb->cs_base;

        cc_op = gen_opc_cc_op[j];

        if (cc_op != CC_OP_DYNAMIC)

            env->cc_op = cc_op;

    }

#elif defined(TARGET_ARM)

    env->regs[15] = gen_opc_pc[j];

#elif defined(TARGET_SPARC)

    {

        target_ulong npc;

        env->pc = gen_opc_pc[j];

        npc = gen_opc_npc[j];

        if (npc == 1) {

            /* dynamic NPC: already stored */

        } else if (npc == 2) {

            target_ulong t2 = (target_ulong)(unsigned long)puc;

            /* jump PC: use T2 and the jump targets of the translation */

            if (t2)

                env->npc = gen_opc_jump_pc[0];

            else

                env->npc = gen_opc_jump_pc[1];

        } else {

            env->npc = npc;

        }

    }

#elif defined(TARGET_PPC)

    {

        int type, c;

        /* for PPC, we need to look at the micro operation to get the

           access type */

        env->nip = gen_opc_pc[j];

        c = gen_opc_buf[j];

        switch(c) {

#if defined(CONFIG_USER_ONLY)

#define CASE3(op)\

        case INDEX_op_ ## op ## _raw

#else

#define CASE3(op)\

        case INDEX_op_ ## op ## _user:\

        case INDEX_op_ ## op ## _kernel:\

        case INDEX_op_ ## op ## _hypv

#endif

        CASE3(stfd):

        CASE3(stfs):

        CASE3(lfd):

        CASE3(lfs):

            type = ACCESS_FLOAT;

            break;

        CASE3(lwarx):

            type = ACCESS_RES;

            break;

        CASE3(stwcx):

            type = ACCESS_RES;

            break;

        CASE3(eciwx):

        CASE3(ecowx):

            type = ACCESS_EXT;

            break;

        default:

            type = ACCESS_INT;

            break;

        }

        env->access_type = type;

    }

#elif defined(TARGET_M68K)

    env->pc = gen_opc_pc[j];

#elif defined(TARGET_MIPS)

    env->PC[env->current_tc] = gen_opc_pc[j];

    env->hflags &= ~MIPS_HFLAG_BMASK;

    env->hflags |= gen_opc_hflags[j];

#elif defined(TARGET_ALPHA)

    env->pc = gen_opc_pc[j];

#elif defined(TARGET_SH4)

    env->pc = gen_opc_pc[j];

    env->flags = gen_opc_hflags[j];

#endif

#ifdef CONFIG_PROFILER

    dyngen_restore_time += profile_getclock() - ti;

    dyngen_restore_count++;

#endif

    return 0;

}


void h263_encode_picture_header(MpegEncContext * s, int picture_number)

{

    int format;

    align_put_bits(&s->pb);

    put_bits(&s->pb, 22, 0x20);

    put_bits(&s->pb, 8, ((s->picture_number * 30 * FRAME_RATE_BASE) /

                         s->frame_rate) & 0xff);

    put_bits(&s->pb, 1, 1);	/* marker */

    put_bits(&s->pb, 1, 0);	/* h263 id */

    put_bits(&s->pb, 1, 0);	/* split screen off */

    put_bits(&s->pb, 1, 0);	/* camera  off */

    put_bits(&s->pb, 1, 0);	/* freeze picture release off */

    format = h263_get_picture_format(s->width, s->height);

    if (!s->h263_plus) {

        /* H.263v1 */

        put_bits(&s->pb, 3, format);

        put_bits(&s->pb, 1, (s->pict_type == P_TYPE));

        /* By now UMV IS DISABLED ON H.263v1, since the restrictions

        of H.263v1 UMV implies to check the predicted MV after

        calculation of the current MB to see if we're on the limits */

        put_bits(&s->pb, 1, 0);	/* unrestricted motion vector: off */

        put_bits(&s->pb, 1, 0);	/* SAC: off */

        put_bits(&s->pb, 1, 0);	/* advanced prediction mode: off */

        put_bits(&s->pb, 1, 0);	/* not PB frame */

        put_bits(&s->pb, 5, s->qscale);

        put_bits(&s->pb, 1, 0);	/* Continuous Presence Multipoint mode: off */

    } else {

        /* H.263v2 */

        /* H.263 Plus PTYPE */

        put_bits(&s->pb, 3, 7);

        put_bits(&s->pb,3,1); /* Update Full Extended PTYPE */

        if (format == 7)

            put_bits(&s->pb,3,6); /* Custom Source Format */

        else

            put_bits(&s->pb, 3, format);

        put_bits(&s->pb,1,0); /* Custom PCF: off */

        umvplus = (s->pict_type == P_TYPE) && s->unrestricted_mv;

        put_bits(&s->pb, 1, umvplus); /* Unrestricted Motion Vector */

        put_bits(&s->pb,1,0); /* SAC: off */

        put_bits(&s->pb,1,0); /* Advanced Prediction Mode: off */

        put_bits(&s->pb,1,0); /* Advanced Intra Coding: off */

        put_bits(&s->pb,1,0); /* Deblocking Filter: off */

        put_bits(&s->pb,1,0); /* Slice Structured: off */

        put_bits(&s->pb,1,0); /* Reference Picture Selection: off */

        put_bits(&s->pb,1,0); /* Independent Segment Decoding: off */

        put_bits(&s->pb,1,0); /* Alternative Inter VLC: off */

        put_bits(&s->pb,1,0); /* Modified Quantization: off */

        put_bits(&s->pb,1,1); /* "1" to prevent start code emulation */

        put_bits(&s->pb,3,0); /* Reserved */

        put_bits(&s->pb, 3, s->pict_type == P_TYPE);

        put_bits(&s->pb,1,0); /* Reference Picture Resampling: off */

        put_bits(&s->pb,1,0); /* Reduced-Resolution Update: off */

        put_bits(&s->pb,1,0); /* Rounding Type */

        put_bits(&s->pb,2,0); /* Reserved */

        put_bits(&s->pb,1,1); /* "1" to prevent start code emulation */

        /* This should be here if PLUSPTYPE */

        put_bits(&s->pb, 1, 0);	/* Continuous Presence Multipoint mode: off */

		if (format == 7) {

            /* Custom Picture Format (CPFMT) */

            put_bits(&s->pb,4,2); /* Aspect ratio: CIF 12:11 (4:3) picture */

            put_bits(&s->pb,9,(s->width >> 2) - 1);

            put_bits(&s->pb,1,1); /* "1" to prevent start code emulation */

            put_bits(&s->pb,9,(s->height >> 2));

        }

        /* Unlimited Unrestricted Motion Vectors Indicator (UUI) */

        if (umvplus)

            put_bits(&s->pb,1,1); /* Limited according tables of Annex D */

        put_bits(&s->pb, 5, s->qscale);

    }

    put_bits(&s->pb, 1, 0);	/* no PEI */

}


_net_rx_pkt_calc_l4_csum(struct NetRxPkt *pkt)

{

    uint32_t cntr;

    uint16_t csum;

    uint16_t csl;

    uint32_t cso;

    trace_net_rx_pkt_l4_csum_calc_entry();

    if (pkt->isip4) {

        if (pkt->isudp) {

            csl = be16_to_cpu(pkt->l4hdr_info.hdr.udp.uh_ulen);

            trace_net_rx_pkt_l4_csum_calc_ip4_udp();

        } else {

            csl = be16_to_cpu(pkt->ip4hdr_info.ip4_hdr.ip_len) -

                  IP_HDR_GET_LEN(&pkt->ip4hdr_info.ip4_hdr);

            trace_net_rx_pkt_l4_csum_calc_ip4_tcp();

        }

        cntr = eth_calc_ip4_pseudo_hdr_csum(&pkt->ip4hdr_info.ip4_hdr,

                                            csl, &cso);

        trace_net_rx_pkt_l4_csum_calc_ph_csum(cntr, csl);

    } else {

        if (pkt->isudp) {

            csl = be16_to_cpu(pkt->l4hdr_info.hdr.udp.uh_ulen);

            trace_net_rx_pkt_l4_csum_calc_ip6_udp();

        } else {

            struct ip6_header *ip6hdr = &pkt->ip6hdr_info.ip6_hdr;

            size_t full_ip6hdr_len = pkt->l4hdr_off - pkt->l3hdr_off;

            size_t ip6opts_len = full_ip6hdr_len - sizeof(struct ip6_header);

            csl = be16_to_cpu(ip6hdr->ip6_ctlun.ip6_un1.ip6_un1_plen) -

                  ip6opts_len;

            trace_net_rx_pkt_l4_csum_calc_ip6_tcp();

        }

        cntr = eth_calc_ip6_pseudo_hdr_csum(&pkt->ip6hdr_info.ip6_hdr, csl,

                                            pkt->ip6hdr_info.l4proto, &cso);

        trace_net_rx_pkt_l4_csum_calc_ph_csum(cntr, csl);

    }

    cntr += net_checksum_add_iov(pkt->vec, pkt->vec_len,

                                 pkt->l4hdr_off, csl, cso);

    csum = net_checksum_finish(cntr);

    trace_net_rx_pkt_l4_csum_calc_csum(pkt->l4hdr_off, csl, cntr, csum);

    return csum;

}


int xen_hvm_init(ram_addr_t *below_4g_mem_size, ram_addr_t *above_4g_mem_size,

                 MemoryRegion **ram_memory)

{

    int i, rc;

    unsigned long ioreq_pfn;

    unsigned long bufioreq_evtchn;

    XenIOState *state;

    state = g_malloc0(sizeof (XenIOState));

    state->xce_handle = xen_xc_evtchn_open(NULL, 0);

    if (state->xce_handle == XC_HANDLER_INITIAL_VALUE) {

        perror("xen: event channel open");

        return -1;

    }

    state->xenstore = xs_daemon_open();

    if (state->xenstore == NULL) {

        perror("xen: xenstore open");

        return -1;

    }

    state->exit.notify = xen_exit_notifier;

    qemu_add_exit_notifier(&state->exit);

    state->suspend.notify = xen_suspend_notifier;

    qemu_register_suspend_notifier(&state->suspend);

    state->wakeup.notify = xen_wakeup_notifier;

    qemu_register_wakeup_notifier(&state->wakeup);

    xc_get_hvm_param(xen_xc, xen_domid, HVM_PARAM_IOREQ_PFN, &ioreq_pfn);

    DPRINTF("shared page at pfn %lx\n", ioreq_pfn);

    state->shared_page = xc_map_foreign_range(xen_xc, xen_domid, XC_PAGE_SIZE,

                                              PROT_READ|PROT_WRITE, ioreq_pfn);

    if (state->shared_page == NULL) {

        hw_error("map shared IO page returned error %d handle=" XC_INTERFACE_FMT,

                 errno, xen_xc);

    }

    rc = xen_get_vmport_regs_pfn(xen_xc, xen_domid, &ioreq_pfn);

    if (!rc) {

        DPRINTF("shared vmport page at pfn %lx\n", ioreq_pfn);

        state->shared_vmport_page =

            xc_map_foreign_range(xen_xc, xen_domid, XC_PAGE_SIZE,

                                 PROT_READ|PROT_WRITE, ioreq_pfn);

        if (state->shared_vmport_page == NULL) {

            hw_error("map shared vmport IO page returned error %d handle="

                     XC_INTERFACE_FMT, errno, xen_xc);

        }

    } else if (rc != -ENOSYS) {

        hw_error("get vmport regs pfn returned error %d, rc=%d", errno, rc);

    }

    xc_get_hvm_param(xen_xc, xen_domid, HVM_PARAM_BUFIOREQ_PFN, &ioreq_pfn);

    DPRINTF("buffered io page at pfn %lx\n", ioreq_pfn);

    state->buffered_io_page = xc_map_foreign_range(xen_xc, xen_domid, XC_PAGE_SIZE,

                                                   PROT_READ|PROT_WRITE, ioreq_pfn);

    if (state->buffered_io_page == NULL) {

        hw_error("map buffered IO page returned error %d", errno);

    }

    /* Note: cpus is empty at this point in init */

    state->cpu_by_vcpu_id = g_malloc0(max_cpus * sizeof(CPUState *));

    state->ioreq_local_port = g_malloc0(max_cpus * sizeof (evtchn_port_t));

    /* FIXME: how about if we overflow the page here? */

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

        rc = xc_evtchn_bind_interdomain(state->xce_handle, xen_domid,

                                        xen_vcpu_eport(state->shared_page, i));

        if (rc == -1) {

            fprintf(stderr, "bind interdomain ioctl error %d\n", errno);

            return -1;

        }

        state->ioreq_local_port[i] = rc;

    }

    rc = xc_get_hvm_param(xen_xc, xen_domid, HVM_PARAM_BUFIOREQ_EVTCHN,

            &bufioreq_evtchn);

    if (rc < 0) {

        fprintf(stderr, "failed to get HVM_PARAM_BUFIOREQ_EVTCHN\n");

        return -1;

    }

    rc = xc_evtchn_bind_interdomain(state->xce_handle, xen_domid,

            (uint32_t)bufioreq_evtchn);

    if (rc == -1) {

        fprintf(stderr, "bind interdomain ioctl error %d\n", errno);

        return -1;

    }

    state->bufioreq_local_port = rc;

    /* Init RAM management */

    xen_map_cache_init(xen_phys_offset_to_gaddr, state);

    xen_ram_init(below_4g_mem_size, above_4g_mem_size, ram_size, ram_memory);

    qemu_add_vm_change_state_handler(xen_hvm_change_state_handler, state);

    state->memory_listener = xen_memory_listener;

    QLIST_INIT(&state->physmap);

    memory_listener_register(&state->memory_listener, &address_space_memory);

    state->log_for_dirtybit = NULL;

    /* Initialize backend core & drivers */

    if (xen_be_init() != 0) {

        fprintf(stderr, "%s: xen backend core setup failed\n", __FUNCTION__);

        return -1;

    }

    xen_be_register("console", &xen_console_ops);

    xen_be_register("vkbd", &xen_kbdmouse_ops);

    xen_be_register("qdisk", &xen_blkdev_ops);

    xen_read_physmap(state);

    return 0;

}


static void yop_paint_block(YopDecContext *s, int tag)

{

    s->dstptr[0]                        = s->srcptr[0];

    s->dstptr[1]                        = s->srcptr[paint_lut[tag][0]];

    s->dstptr[s->frame.linesize[0]]     = s->srcptr[paint_lut[tag][1]];

    s->dstptr[s->frame.linesize[0] + 1] = s->srcptr[paint_lut[tag][2]];

    // The number of src bytes consumed is in the last part of the lut entry.

    s->srcptr += paint_lut[tag][3];

}


av_cold int ff_rv34_decode_init(AVCodecContext *avctx)

{

    RV34DecContext *r = avctx->priv_data;

    MpegEncContext *s = &r->s;

    int ret;

    ff_MPV_decode_defaults(s);

    s->avctx      = avctx;

    s->out_format = FMT_H263;

    s->codec_id   = avctx->codec_id;

    s->width  = avctx->width;

    s->height = avctx->height;

    r->s.avctx = avctx;

    avctx->flags |= CODEC_FLAG_EMU_EDGE;

    r->s.flags |= CODEC_FLAG_EMU_EDGE;

    avctx->pix_fmt = AV_PIX_FMT_YUV420P;

    avctx->has_b_frames = 1;

    s->low_delay = 0;

    if ((ret = ff_MPV_common_init(s)) < 0)

        return ret;

    ff_h264_pred_init(&r->h, AV_CODEC_ID_RV40, 8, 1);

#if CONFIG_RV30_DECODER

    if (avctx->codec_id == AV_CODEC_ID_RV30)

        ff_rv30dsp_init(&r->rdsp);

#endif

#if CONFIG_RV40_DECODER

    if (avctx->codec_id == AV_CODEC_ID_RV40)

        ff_rv40dsp_init(&r->rdsp);

#endif

    if ((ret = rv34_decoder_alloc(r)) < 0)

        return ret;

    if(!intra_vlcs[0].cbppattern[0].bits)

        rv34_init_tables();

    avctx->internal->allocate_progress = 1;

    return 0;

}


static int flic_decode_frame_24BPP(AVCodecContext *avctx,

                                   void *data, int *got_frame,

                                   const uint8_t *buf, int buf_size)

{

    FlicDecodeContext *s = avctx->priv_data;

    GetByteContext g2;

    int pixel_ptr;

    unsigned char palette_idx1;

    unsigned int frame_size;

    int num_chunks;

    unsigned int chunk_size;

    int chunk_type;

    int i, j, ret;

    int lines;

    int compressed_lines;

    signed short line_packets;

    int y_ptr;

    int byte_run;

    int pixel_skip;

    int pixel_countdown;

    unsigned char *pixels;

    int pixel;

    unsigned int pixel_limit;

    bytestream2_init(&g2, buf, buf_size);

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

        return ret;

    pixels = s->frame->data[0];

    pixel_limit = s->avctx->height * s->frame->linesize[0];

    frame_size = bytestream2_get_le32(&g2);

    bytestream2_skip(&g2, 2);  /* skip the magic number */

    num_chunks = bytestream2_get_le16(&g2);

    bytestream2_skip(&g2, 8);  /* skip padding */

    if (frame_size > buf_size)

        frame_size = buf_size;

    if (frame_size < 16)

    frame_size -= 16;

    /* iterate through the chunks */

    while ((frame_size > 0) && (num_chunks > 0) &&

            bytestream2_get_bytes_left(&g2) >= 4) {

        int stream_ptr_after_chunk;

        chunk_size = bytestream2_get_le32(&g2);

        if (chunk_size > frame_size) {

            av_log(avctx, AV_LOG_WARNING,

                   "Invalid chunk_size = %u > frame_size = %u\n", chunk_size, frame_size);

            chunk_size = frame_size;

        }

        stream_ptr_after_chunk = bytestream2_tell(&g2) - 4 + chunk_size;

        chunk_type = bytestream2_get_le16(&g2);

        switch (chunk_type) {

        case FLI_256_COLOR:

        case FLI_COLOR:

            /* For some reason, it seems that non-palettized flics do

             * include one of these chunks in their first frame.

             * Why I do not know, it seems rather extraneous. */

            ff_dlog(avctx,

                    "Unexpected Palette chunk %d in non-palettized FLC\n",

                    chunk_type);

            bytestream2_skip(&g2, chunk_size - 6);

            break;

        case FLI_DELTA:

        case FLI_DTA_LC:

            y_ptr = 0;

            compressed_lines = bytestream2_get_le16(&g2);

            while (compressed_lines > 0) {

                if (bytestream2_tell(&g2) + 2 > stream_ptr_after_chunk)

                    break;

                line_packets = bytestream2_get_le16(&g2);

                if (line_packets < 0) {

                    line_packets = -line_packets;

                    y_ptr += line_packets * s->frame->linesize[0];

                } else {

                    compressed_lines--;

                    pixel_ptr = y_ptr;

                    CHECK_PIXEL_PTR(0);

                    pixel_countdown = s->avctx->width;

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

                        /* account for the skip bytes */

                        if (bytestream2_tell(&g2) + 2 > stream_ptr_after_chunk)

                            break;

                        pixel_skip = bytestream2_get_byte(&g2);

                        pixel_ptr += (pixel_skip*3); /* Pixel is 3 bytes wide */

                        pixel_countdown -= pixel_skip;

                        byte_run = sign_extend(bytestream2_get_byte(&g2), 8);

                        if (byte_run < 0) {

                            byte_run = -byte_run;

                            pixel    = bytestream2_get_le24(&g2);

                            CHECK_PIXEL_PTR(3 * byte_run);

                            for (j = 0; j < byte_run; j++, pixel_countdown -= 1) {

                                AV_WL24(&pixels[pixel_ptr], pixel);

                                pixel_ptr += 3;

                            }

                        } else {

                            if (bytestream2_tell(&g2) + 2*byte_run > stream_ptr_after_chunk)

                                break;

                            CHECK_PIXEL_PTR(2 * byte_run);

                            for (j = 0; j < byte_run; j++, pixel_countdown--) {

                                pixel = bytestream2_get_le24(&g2);

                                AV_WL24(&pixels[pixel_ptr], pixel);

                                pixel_ptr += 3;

                            }

                        }

                    }

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

                }

            }

            break;

        case FLI_LC:

            av_log(avctx, AV_LOG_ERROR, "Unexpected FLI_LC chunk in non-palettized FLC\n");

            bytestream2_skip(&g2, chunk_size - 6);

            break;

        case FLI_BLACK:

            /* set the whole frame to 0x00 which is black for 24 bit mode. */

            memset(pixels, 0x00,

                   s->frame->linesize[0] * s->avctx->height);

            break;

        case FLI_BRUN:

            y_ptr = 0;

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

                pixel_ptr = y_ptr;

                /* disregard the line packets; instead, iterate through all

                 * pixels on a row */

                bytestream2_skip(&g2, 1);

                pixel_countdown = (s->avctx->width * 3);

                while (pixel_countdown > 0) {

                    if (bytestream2_tell(&g2) + 1 > stream_ptr_after_chunk)

                        break;

                    byte_run = sign_extend(bytestream2_get_byte(&g2), 8);

                    if (byte_run > 0) {

                        palette_idx1 = bytestream2_get_byte(&g2);

                        CHECK_PIXEL_PTR(byte_run);

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

                            pixels[pixel_ptr++] = palette_idx1;

                            pixel_countdown--;

                            if (pixel_countdown < 0)

                                av_log(avctx, AV_LOG_ERROR, "pixel_countdown < 0 (%d) (linea%d)\n",

                                       pixel_countdown, lines);

                        }

                    } else {  /* copy bytes if byte_run < 0 */

                        byte_run = -byte_run;

                        if (bytestream2_tell(&g2) + byte_run > stream_ptr_after_chunk)

                            break;

                        CHECK_PIXEL_PTR(byte_run);

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

                            palette_idx1 = bytestream2_get_byte(&g2);

                            pixels[pixel_ptr++] = palette_idx1;

                            pixel_countdown--;

                            if (pixel_countdown < 0)

                                av_log(avctx, AV_LOG_ERROR, "pixel_countdown < 0 (%d) at line %d\n",

                                       pixel_countdown, lines);

                        }

                    }

                }

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

            }

            break;

        case FLI_DTA_BRUN:

            y_ptr = 0;

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

                pixel_ptr = y_ptr;

                /* disregard the line packets; instead, iterate through all

                 * pixels on a row */

                bytestream2_skip(&g2, 1);

                pixel_countdown = s->avctx->width; /* Width is in pixels, not bytes */

                while (pixel_countdown > 0) {

                    if (bytestream2_tell(&g2) + 1 > stream_ptr_after_chunk)

                        break;

                    byte_run = sign_extend(bytestream2_get_byte(&g2), 8);

                    if (byte_run > 0) {

                        pixel = bytestream2_get_le24(&g2);

                        CHECK_PIXEL_PTR(3 * byte_run);

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

                            AV_WL24(pixels + pixel_ptr, pixel);

                            pixel_ptr += 3;

                            pixel_countdown--;

                            if (pixel_countdown < 0)

                                av_log(avctx, AV_LOG_ERROR, "pixel_countdown < 0 (%d)\n",

                                       pixel_countdown);

                        }

                    } else {  /* copy pixels if byte_run < 0 */

                        byte_run = -byte_run;

                        if (bytestream2_tell(&g2) + 3 * byte_run > stream_ptr_after_chunk)

                            break;

                        CHECK_PIXEL_PTR(3 * byte_run);

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

                            pixel = bytestream2_get_le24(&g2);

                            AV_WL24(pixels + pixel_ptr, pixel);

                            pixel_ptr  += 3;

                            pixel_countdown--;

                            if (pixel_countdown < 0)

                                av_log(avctx, AV_LOG_ERROR, "pixel_countdown < 0 (%d)\n",

                                       pixel_countdown);

                        }

                    }

                }

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

            }

            break;

        case FLI_COPY:

        case FLI_DTA_COPY:

            /* copy the chunk (uncompressed frame) */

            if (chunk_size - 6 > (unsigned int)(FFALIGN(s->avctx->width, 2) * s->avctx->height)*3) {

                av_log(avctx, AV_LOG_ERROR, "In chunk FLI_COPY : source data (%d bytes) " \

                       "bigger than image, skipping chunk\n", chunk_size - 6);

                bytestream2_skip(&g2, chunk_size - 6);

            } else {

                for (y_ptr = 0; y_ptr < s->frame->linesize[0] * s->avctx->height;

                     y_ptr += s->frame->linesize[0]) {

                    pixel_countdown = s->avctx->width;

                    pixel_ptr = 0;

                    while (pixel_countdown > 0) {

                        pixel = bytestream2_get_le24(&g2);

                        AV_WL24(&pixels[y_ptr + pixel_ptr], pixel);

                        pixel_ptr += 3;

                        pixel_countdown--;

                    }

                    if (s->avctx->width & 1)

                        bytestream2_skip(&g2, 3);

                }

            }

            break;

        case FLI_MINI:

            /* some sort of a thumbnail? disregard this chunk... */

            bytestream2_skip(&g2, chunk_size - 6);

            break;

        default:

            av_log(avctx, AV_LOG_ERROR, "Unrecognized chunk type: %d\n", chunk_type);

            break;

        }

        if (stream_ptr_after_chunk - bytestream2_tell(&g2) >= 0) {

            bytestream2_skip(&g2, stream_ptr_after_chunk - bytestream2_tell(&g2));

        } else {

            av_log(avctx, AV_LOG_ERROR, "Chunk overread\n");

            break;

        }

        frame_size -= chunk_size;

        num_chunks--;

    }

    /* by the end of the chunk, the stream ptr should equal the frame

     * size (minus 1, possibly); if it doesn't, issue a warning */

    if ((bytestream2_get_bytes_left(&g2) != 0) && (bytestream2_get_bytes_left(&g2) != 1))

        av_log(avctx, AV_LOG_ERROR, "Processed FLI chunk where chunk size = %d " \

               "and final chunk ptr = %d\n", buf_size, bytestream2_tell(&g2));

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

        return ret;

    *got_frame = 1;

    return buf_size;

}


static int h264_mp4toannexb_filter(AVBitStreamFilterContext *bsfc,

                                   AVCodecContext *avctx, const char *args,

                                   uint8_t  **poutbuf, int *poutbuf_size,

                                   const uint8_t *buf, int      buf_size,

                                   int keyframe) {

    H264BSFContext *ctx = bsfc->priv_data;

    uint8_t unit_type;

    int32_t nal_size;

    uint32_t cumul_size = 0;

    const uint8_t *buf_end = buf + buf_size;

    /* nothing to filter */

    if (!avctx->extradata || avctx->extradata_size < 6) {

        *poutbuf = (uint8_t*) buf;

        *poutbuf_size = buf_size;

        return 0;

    }

    /* retrieve sps and pps NAL units from extradata */

    if (!ctx->extradata_parsed) {

        uint16_t unit_size;

        uint64_t total_size = 0;

        uint8_t *out = NULL, unit_nb, sps_done = 0;

        const uint8_t *extradata = avctx->extradata+4;

        static const uint8_t nalu_header[4] = {0, 0, 0, 1};

        /* retrieve length coded size */

        ctx->length_size = (*extradata++ & 0x3) + 1;

        if (ctx->length_size == 3)

            return AVERROR(EINVAL);

        /* retrieve sps and pps unit(s) */

        unit_nb = *extradata++ & 0x1f; /* number of sps unit(s) */

        if (!unit_nb) {

            unit_nb = *extradata++; /* number of pps unit(s) */

            sps_done++;

        }

        while (unit_nb--) {

            void *tmp;

            unit_size = AV_RB16(extradata);

            total_size += unit_size+4;

            if (total_size > INT_MAX - FF_INPUT_BUFFER_PADDING_SIZE ||

                extradata+2+unit_size > avctx->extradata+avctx->extradata_size) {

                av_free(out);

                return AVERROR(EINVAL);

            }

            tmp = av_realloc(out, total_size + FF_INPUT_BUFFER_PADDING_SIZE);

            if (!tmp) {

                av_free(out);

                return AVERROR(ENOMEM);

            }

            out = tmp;

            memcpy(out+total_size-unit_size-4, nalu_header, 4);

            memcpy(out+total_size-unit_size,   extradata+2, unit_size);

            extradata += 2+unit_size;

            if (!unit_nb && !sps_done++)

                unit_nb = *extradata++; /* number of pps unit(s) */

        }

        memset(out + total_size, 0, FF_INPUT_BUFFER_PADDING_SIZE);

        av_free(avctx->extradata);

        avctx->extradata      = out;

        avctx->extradata_size = total_size;

        ctx->first_idr        = 1;

        ctx->extradata_parsed = 1;

    }

    *poutbuf_size = 0;

    *poutbuf = NULL;

    do {

        if (buf + ctx->length_size > buf_end)

            goto fail;

        if (ctx->length_size == 1) {

            nal_size = buf[0];

        } else if (ctx->length_size == 2) {

            nal_size = AV_RB16(buf);

        } else

            nal_size = AV_RB32(buf);

        buf += ctx->length_size;

        unit_type = *buf & 0x1f;

        if (buf + nal_size > buf_end || nal_size < 0)

            goto fail;

        /* prepend only to the first type 5 NAL unit of an IDR picture */

        if (ctx->first_idr && unit_type == 5) {

            if (alloc_and_copy(poutbuf, poutbuf_size,

                               avctx->extradata, avctx->extradata_size,

                               buf, nal_size) < 0)

                goto fail;

            ctx->first_idr = 0;

        } else {

            if (alloc_and_copy(poutbuf, poutbuf_size,

                               NULL, 0,

                               buf, nal_size) < 0)

                goto fail;

            if (!ctx->first_idr && unit_type == 1)

                ctx->first_idr = 1;

        }

        buf += nal_size;

        cumul_size += nal_size + ctx->length_size;

    } while (cumul_size < buf_size);

    return 1;

fail:

    av_freep(poutbuf);

    *poutbuf_size = 0;

    return AVERROR(EINVAL);

}


static void dchip_write(void *opaque, target_phys_addr_t addr,

                        uint64_t val, unsigned size)

{

    /* Skip this.  It's all related to DRAM timing and setup.  */

}


qemu_irq get_cps_irq(MIPSCPSState *s, int pin_number)

{

    MIPSCPU *cpu = MIPS_CPU(first_cpu);

    CPUMIPSState *env = &cpu->env;

    assert(pin_number < s->num_irq);

    /* TODO: return GIC pins once implemented */

    return env->irq[pin_number];

}


static int tcp_chr_write(CharDriverState *chr, const uint8_t *buf, int len)

{

    TCPCharDriver *s = chr->opaque;

    if (s->connected) {

        return send_all(s->fd, buf, len);

    } else {

        /* (Re-)connect for unconnected writing */

        tcp_chr_connect(chr);

        return 0;

    }

}