static void disas_sparc_insn(DisasContext * dc)

{

    unsigned int insn, opc, rs1, rs2, rd;

    insn = ldl_code(dc->pc);

    opc = GET_FIELD(insn, 0, 1);

    rd = GET_FIELD(insn, 2, 6);

    switch (opc) {

    case 0:			/* branches/sethi */

	{

	    unsigned int xop = GET_FIELD(insn, 7, 9);

	    int32_t target;

	    switch (xop) {

#ifdef TARGET_SPARC64

	    case 0x1:		/* V9 BPcc */

		{

		    int cc;

		    target = GET_FIELD_SP(insn, 0, 18);

		    target = sign_extend(target, 18);

		    target <<= 2;

		    cc = GET_FIELD_SP(insn, 20, 21);

		    if (cc == 0)

			do_branch(dc, target, insn, 0);

		    else if (cc == 2)

			do_branch(dc, target, insn, 1);

		    else

		    goto jmp_insn;

		}

	    case 0x3:		/* V9 BPr */

		{

		    target = GET_FIELD_SP(insn, 0, 13) |

                        (GET_FIELD_SP(insn, 20, 21) << 14);

		    target = sign_extend(target, 16);

		    target <<= 2;

		    rs1 = GET_FIELD(insn, 13, 17);

		    gen_movl_reg_T0(rs1);

		    do_branch_reg(dc, target, insn);

		    goto jmp_insn;

		}

	    case 0x5:		/* V9 FBPcc */

		{

		    int cc = GET_FIELD_SP(insn, 20, 21);

                    if (gen_trap_ifnofpu(dc))

                        goto jmp_insn;

		    target = GET_FIELD_SP(insn, 0, 18);

		    target = sign_extend(target, 19);

		    target <<= 2;

		    do_fbranch(dc, target, insn, cc);

		    goto jmp_insn;

		}

#endif

	    case 0x2:		/* BN+x */

		{

		    target = GET_FIELD(insn, 10, 31);

		    target = sign_extend(target, 22);

		    target <<= 2;

		    do_branch(dc, target, insn, 0);

		    goto jmp_insn;

		}

	    case 0x6:		/* FBN+x */

		{

                    if (gen_trap_ifnofpu(dc))

                        goto jmp_insn;

		    target = GET_FIELD(insn, 10, 31);

		    target = sign_extend(target, 22);

		    target <<= 2;

		    do_fbranch(dc, target, insn, 0);

		    goto jmp_insn;

		}

	    case 0x4:		/* SETHI */

#define OPTIM

#if defined(OPTIM)

		if (rd) { // nop

#endif

		    uint32_t value = GET_FIELD(insn, 10, 31);

		    gen_movl_imm_T0(value << 10);

		    gen_movl_T0_reg(rd);

#if defined(OPTIM)

		}

#endif

		break;

	    case 0x0:		/* UNIMPL */

	    default:

	    }

	    break;

	}

	break;

    case 1:

	/*CALL*/ {

	    target_long target = GET_FIELDs(insn, 2, 31) << 2;

#ifdef TARGET_SPARC64

	    if (dc->pc == (uint32_t)dc->pc) {

		gen_op_movl_T0_im(dc->pc);

	    } else {

		gen_op_movq_T0_im64(dc->pc >> 32, dc->pc);

	    }

#else

	    gen_op_movl_T0_im(dc->pc);

#endif

	    gen_movl_T0_reg(15);

	    target += dc->pc;

            gen_mov_pc_npc(dc);

	    dc->npc = target;

	}

	goto jmp_insn;

    case 2:			/* FPU & Logical Operations */

	{

	    unsigned int xop = GET_FIELD(insn, 7, 12);

	    if (xop == 0x3a) {	/* generate trap */

                int cond;

                rs1 = GET_FIELD(insn, 13, 17);

                gen_movl_reg_T0(rs1);

		if (IS_IMM) {

		    rs2 = GET_FIELD(insn, 25, 31);

#if defined(OPTIM)

		    if (rs2 != 0) {

#endif

			gen_movl_simm_T1(rs2);

			gen_op_add_T1_T0();

#if defined(OPTIM)

		    }

#endif

                } else {

                    rs2 = GET_FIELD(insn, 27, 31);

#if defined(OPTIM)

		    if (rs2 != 0) {

#endif

			gen_movl_reg_T1(rs2);

			gen_op_add_T1_T0();

#if defined(OPTIM)

		    }

#endif

                }

                cond = GET_FIELD(insn, 3, 6);

                if (cond == 0x8) {

                    save_state(dc);

                    gen_op_trap_T0();

                } else if (cond != 0) {

#ifdef TARGET_SPARC64

		    /* V9 icc/xcc */

		    int cc = GET_FIELD_SP(insn, 11, 12);

		    flush_T2(dc);

                    save_state(dc);

		    if (cc == 0)

			gen_cond[0][cond]();

		    else if (cc == 2)

			gen_cond[1][cond]();

		    else

#else

		    flush_T2(dc);

                    save_state(dc);

		    gen_cond[0][cond]();

#endif

                    gen_op_trapcc_T0();

                }

                gen_op_next_insn();

                gen_op_movl_T0_0();

                gen_op_exit_tb();

                dc->is_br = 1;

                goto jmp_insn;

            } else if (xop == 0x28) {

                rs1 = GET_FIELD(insn, 13, 17);

                switch(rs1) {

                case 0: /* rdy */

#ifndef TARGET_SPARC64

                case 0x01 ... 0x0e: /* undefined in the SPARCv8

                                       manual, rdy on the microSPARC

                                       II */

                case 0x0f:          /* stbar in the SPARCv8 manual,

                                       rdy on the microSPARC II */

                case 0x10 ... 0x1f: /* implementation-dependent in the

                                       SPARCv8 manual, rdy on the

                                       microSPARC II */

#endif

                    gen_op_movtl_T0_env(offsetof(CPUSPARCState, y));

                    gen_movl_T0_reg(rd);

                    break;

#ifdef TARGET_SPARC64

		case 0x2: /* V9 rdccr */

                    gen_op_rdccr();

                    gen_movl_T0_reg(rd);

                    break;

		case 0x3: /* V9 rdasi */

		    gen_op_movl_T0_env(offsetof(CPUSPARCState, asi));

                    gen_movl_T0_reg(rd);

                    break;

		case 0x4: /* V9 rdtick */

                    gen_op_rdtick();

                    gen_movl_T0_reg(rd);

                    break;

		case 0x5: /* V9 rdpc */

		    if (dc->pc == (uint32_t)dc->pc) {

			gen_op_movl_T0_im(dc->pc);

		    } else {

			gen_op_movq_T0_im64(dc->pc >> 32, dc->pc);

		    }

		    gen_movl_T0_reg(rd);

		    break;

		case 0x6: /* V9 rdfprs */

		    gen_op_movl_T0_env(offsetof(CPUSPARCState, fprs));

                    gen_movl_T0_reg(rd);

                    break;

                case 0xf: /* V9 membar */

                    break; /* no effect */

		case 0x13: /* Graphics Status */

                    if (gen_trap_ifnofpu(dc))

                        goto jmp_insn;

		    gen_op_movtl_T0_env(offsetof(CPUSPARCState, gsr));

                    gen_movl_T0_reg(rd);

                    break;

		case 0x17: /* Tick compare */

		    gen_op_movtl_T0_env(offsetof(CPUSPARCState, tick_cmpr));

                    gen_movl_T0_reg(rd);

                    break;

		case 0x18: /* System tick */

                    gen_op_rdtick(); // XXX

                    gen_movl_T0_reg(rd);

                    break;

		case 0x19: /* System tick compare */

		    gen_op_movtl_T0_env(offsetof(CPUSPARCState, stick_cmpr));

                    gen_movl_T0_reg(rd);

                    break;

		case 0x10: /* Performance Control */

		case 0x11: /* Performance Instrumentation Counter */

		case 0x12: /* Dispatch Control */

		case 0x14: /* Softint set, WO */

		case 0x15: /* Softint clear, WO */

		case 0x16: /* Softint write */

#endif

                default:

                }

#if !defined(CONFIG_USER_ONLY)

#ifndef TARGET_SPARC64

            } else if (xop == 0x29) { /* rdpsr / V9 unimp */

		if (!supervisor(dc))

		    goto priv_insn;

                gen_op_rdpsr();

                gen_movl_T0_reg(rd);

                break;

#endif

            } else if (xop == 0x2a) { /* rdwim / V9 rdpr */

		if (!supervisor(dc))

		    goto priv_insn;

#ifdef TARGET_SPARC64

                rs1 = GET_FIELD(insn, 13, 17);

		switch (rs1) {

		case 0: // tpc

		    gen_op_rdtpc();

		    break;

		case 1: // tnpc

		    gen_op_rdtnpc();

		    break;

		case 2: // tstate

		    gen_op_rdtstate();

		    break;

		case 3: // tt

		    gen_op_rdtt();

		    break;

		case 4: // tick

		    gen_op_rdtick();

		    break;

		case 5: // tba

		    gen_op_movtl_T0_env(offsetof(CPUSPARCState, tbr));

		    break;

		case 6: // pstate

		    gen_op_rdpstate();

		    break;

		case 7: // tl

		    gen_op_movl_T0_env(offsetof(CPUSPARCState, tl));

		    break;

		case 8: // pil

		    gen_op_movl_T0_env(offsetof(CPUSPARCState, psrpil));

		    break;

		case 9: // cwp

		    gen_op_rdcwp();

		    break;

		case 10: // cansave

		    gen_op_movl_T0_env(offsetof(CPUSPARCState, cansave));

		    break;

		case 11: // canrestore

		    gen_op_movl_T0_env(offsetof(CPUSPARCState, canrestore));

		    break;

		case 12: // cleanwin

		    gen_op_movl_T0_env(offsetof(CPUSPARCState, cleanwin));

		    break;

		case 13: // otherwin

		    gen_op_movl_T0_env(offsetof(CPUSPARCState, otherwin));

		    break;

		case 14: // wstate

		    gen_op_movl_T0_env(offsetof(CPUSPARCState, wstate));

		    break;

		case 31: // ver

		    gen_op_movtl_T0_env(offsetof(CPUSPARCState, version));

		    break;

		case 15: // fq

		default:

		}

#else

		gen_op_movl_T0_env(offsetof(CPUSPARCState, wim));

#endif

                gen_movl_T0_reg(rd);

                break;

            } else if (xop == 0x2b) { /* rdtbr / V9 flushw */

#ifdef TARGET_SPARC64

		gen_op_flushw();

#else

		if (!supervisor(dc))

		    goto priv_insn;

		gen_op_movtl_T0_env(offsetof(CPUSPARCState, tbr));

                gen_movl_T0_reg(rd);

#endif

                break;

#endif

	    } else if (xop == 0x34) {	/* FPU Operations */

                if (gen_trap_ifnofpu(dc))

                    goto jmp_insn;

                rs1 = GET_FIELD(insn, 13, 17);

	        rs2 = GET_FIELD(insn, 27, 31);

	        xop = GET_FIELD(insn, 18, 26);

		switch (xop) {

		    case 0x1: /* fmovs */

                	gen_op_load_fpr_FT0(rs2);

			gen_op_store_FT0_fpr(rd);

			break;

		    case 0x5: /* fnegs */

                	gen_op_load_fpr_FT1(rs2);

			gen_op_fnegs();

			gen_op_store_FT0_fpr(rd);

			break;

		    case 0x9: /* fabss */

                	gen_op_load_fpr_FT1(rs2);

			gen_op_fabss();

			gen_op_store_FT0_fpr(rd);

			break;

		    case 0x29: /* fsqrts */

                	gen_op_load_fpr_FT1(rs2);

			gen_op_fsqrts();

			gen_op_store_FT0_fpr(rd);

			break;

		    case 0x2a: /* fsqrtd */

                	gen_op_load_fpr_DT1(DFPREG(rs2));

			gen_op_fsqrtd();

			gen_op_store_DT0_fpr(DFPREG(rd));

			break;

		    case 0x2b: /* fsqrtq */

		        goto nfpu_insn;

		    case 0x41:

                	gen_op_load_fpr_FT0(rs1);

                	gen_op_load_fpr_FT1(rs2);

			gen_op_fadds();

			gen_op_store_FT0_fpr(rd);

			break;

		    case 0x42:

                	gen_op_load_fpr_DT0(DFPREG(rs1));

                	gen_op_load_fpr_DT1(DFPREG(rs2));

			gen_op_faddd();

			gen_op_store_DT0_fpr(DFPREG(rd));

			break;

		    case 0x43: /* faddq */

		        goto nfpu_insn;

		    case 0x45:

                	gen_op_load_fpr_FT0(rs1);

                	gen_op_load_fpr_FT1(rs2);

			gen_op_fsubs();

			gen_op_store_FT0_fpr(rd);

			break;

		    case 0x46:

                	gen_op_load_fpr_DT0(DFPREG(rs1));

                	gen_op_load_fpr_DT1(DFPREG(rs2));

			gen_op_fsubd();

			gen_op_store_DT0_fpr(DFPREG(rd));

			break;

		    case 0x47: /* fsubq */

		        goto nfpu_insn;

		    case 0x49:

                	gen_op_load_fpr_FT0(rs1);

                	gen_op_load_fpr_FT1(rs2);

			gen_op_fmuls();

			gen_op_store_FT0_fpr(rd);

			break;

		    case 0x4a:

                	gen_op_load_fpr_DT0(DFPREG(rs1));

                	gen_op_load_fpr_DT1(DFPREG(rs2));

			gen_op_fmuld();

			gen_op_store_DT0_fpr(rd);

			break;

		    case 0x4b: /* fmulq */

		        goto nfpu_insn;

		    case 0x4d:

                	gen_op_load_fpr_FT0(rs1);

                	gen_op_load_fpr_FT1(rs2);

			gen_op_fdivs();

			gen_op_store_FT0_fpr(rd);

			break;

		    case 0x4e:

                	gen_op_load_fpr_DT0(DFPREG(rs1));

			gen_op_load_fpr_DT1(DFPREG(rs2));

			gen_op_fdivd();

			gen_op_store_DT0_fpr(DFPREG(rd));

			break;

		    case 0x4f: /* fdivq */

		        goto nfpu_insn;

		    case 0x69:

                	gen_op_load_fpr_FT0(rs1);

                	gen_op_load_fpr_FT1(rs2);

			gen_op_fsmuld();

			gen_op_store_DT0_fpr(DFPREG(rd));

			break;

		    case 0x6e: /* fdmulq */

		        goto nfpu_insn;

		    case 0xc4:

                	gen_op_load_fpr_FT1(rs2);

			gen_op_fitos();

			gen_op_store_FT0_fpr(rd);

			break;

		    case 0xc6:

                	gen_op_load_fpr_DT1(DFPREG(rs2));

			gen_op_fdtos();

			gen_op_store_FT0_fpr(rd);

			break;

		    case 0xc7: /* fqtos */

		        goto nfpu_insn;

		    case 0xc8:

                	gen_op_load_fpr_FT1(rs2);

			gen_op_fitod();

			gen_op_store_DT0_fpr(DFPREG(rd));

			break;

		    case 0xc9:

                	gen_op_load_fpr_FT1(rs2);

			gen_op_fstod();

			gen_op_store_DT0_fpr(DFPREG(rd));

			break;

		    case 0xcb: /* fqtod */

		        goto nfpu_insn;

		    case 0xcc: /* fitoq */

		        goto nfpu_insn;

		    case 0xcd: /* fstoq */

		        goto nfpu_insn;

		    case 0xce: /* fdtoq */

		        goto nfpu_insn;

		    case 0xd1:

                	gen_op_load_fpr_FT1(rs2);

			gen_op_fstoi();

			gen_op_store_FT0_fpr(rd);

			break;

		    case 0xd2:

                	gen_op_load_fpr_DT1(rs2);

			gen_op_fdtoi();

			gen_op_store_FT0_fpr(rd);

			break;

		    case 0xd3: /* fqtoi */

		        goto nfpu_insn;

#ifdef TARGET_SPARC64

		    case 0x2: /* V9 fmovd */

                	gen_op_load_fpr_DT0(DFPREG(rs2));

			gen_op_store_DT0_fpr(DFPREG(rd));

			break;

		    case 0x6: /* V9 fnegd */

                	gen_op_load_fpr_DT1(DFPREG(rs2));

			gen_op_fnegd();

			gen_op_store_DT0_fpr(DFPREG(rd));

			break;

		    case 0xa: /* V9 fabsd */

                	gen_op_load_fpr_DT1(DFPREG(rs2));

			gen_op_fabsd();

			gen_op_store_DT0_fpr(DFPREG(rd));

			break;

		    case 0x81: /* V9 fstox */

                	gen_op_load_fpr_FT1(rs2);

			gen_op_fstox();

			gen_op_store_DT0_fpr(DFPREG(rd));

			break;

		    case 0x82: /* V9 fdtox */

                	gen_op_load_fpr_DT1(DFPREG(rs2));

			gen_op_fdtox();

			gen_op_store_DT0_fpr(DFPREG(rd));

			break;

		    case 0x84: /* V9 fxtos */

                	gen_op_load_fpr_DT1(DFPREG(rs2));

			gen_op_fxtos();

			gen_op_store_FT0_fpr(rd);

			break;

		    case 0x88: /* V9 fxtod */

                	gen_op_load_fpr_DT1(DFPREG(rs2));

			gen_op_fxtod();

			gen_op_store_DT0_fpr(DFPREG(rd));

			break;

		    case 0x3: /* V9 fmovq */

		    case 0x7: /* V9 fnegq */

		    case 0xb: /* V9 fabsq */

		    case 0x83: /* V9 fqtox */

		    case 0x8c: /* V9 fxtoq */

		        goto nfpu_insn;

#endif

		    default:

		}

	    } else if (xop == 0x35) {	/* FPU Operations */

#ifdef TARGET_SPARC64

		int cond;

#endif

                if (gen_trap_ifnofpu(dc))

                    goto jmp_insn;

                rs1 = GET_FIELD(insn, 13, 17);

	        rs2 = GET_FIELD(insn, 27, 31);

	        xop = GET_FIELD(insn, 18, 26);

#ifdef TARGET_SPARC64

		if ((xop & 0x11f) == 0x005) { // V9 fmovsr

		    cond = GET_FIELD_SP(insn, 14, 17);

		    gen_op_load_fpr_FT0(rd);

		    gen_op_load_fpr_FT1(rs2);

		    rs1 = GET_FIELD(insn, 13, 17);

		    gen_movl_reg_T0(rs1);

		    flush_T2(dc);

		    gen_cond_reg(cond);

		    gen_op_fmovs_cc();

		    gen_op_store_FT0_fpr(rd);

		    break;

		} else if ((xop & 0x11f) == 0x006) { // V9 fmovdr

		    cond = GET_FIELD_SP(insn, 14, 17);

		    gen_op_load_fpr_DT0(rd);

		    gen_op_load_fpr_DT1(rs2);

		    flush_T2(dc);

		    rs1 = GET_FIELD(insn, 13, 17);

		    gen_movl_reg_T0(rs1);

		    gen_cond_reg(cond);

		    gen_op_fmovs_cc();

		    gen_op_store_DT0_fpr(rd);

		    break;

		} else if ((xop & 0x11f) == 0x007) { // V9 fmovqr

		    goto nfpu_insn;

		}

#endif

		switch (xop) {

#ifdef TARGET_SPARC64

		    case 0x001: /* V9 fmovscc %fcc0 */

			cond = GET_FIELD_SP(insn, 14, 17);

                	gen_op_load_fpr_FT0(rd);

                	gen_op_load_fpr_FT1(rs2);

			flush_T2(dc);

			gen_fcond[0][cond]();

			gen_op_fmovs_cc();

			gen_op_store_FT0_fpr(rd);

			break;

		    case 0x002: /* V9 fmovdcc %fcc0 */

			cond = GET_FIELD_SP(insn, 14, 17);

                	gen_op_load_fpr_DT0(rd);

                	gen_op_load_fpr_DT1(rs2);

			flush_T2(dc);

			gen_fcond[0][cond]();

			gen_op_fmovd_cc();

			gen_op_store_DT0_fpr(rd);

			break;

		    case 0x003: /* V9 fmovqcc %fcc0 */

		        goto nfpu_insn;

		    case 0x041: /* V9 fmovscc %fcc1 */

			cond = GET_FIELD_SP(insn, 14, 17);

                	gen_op_load_fpr_FT0(rd);

                	gen_op_load_fpr_FT1(rs2);

			flush_T2(dc);

			gen_fcond[1][cond]();

			gen_op_fmovs_cc();

			gen_op_store_FT0_fpr(rd);

			break;

		    case 0x042: /* V9 fmovdcc %fcc1 */

			cond = GET_FIELD_SP(insn, 14, 17);

                	gen_op_load_fpr_DT0(rd);

                	gen_op_load_fpr_DT1(rs2);

			flush_T2(dc);

			gen_fcond[1][cond]();

			gen_op_fmovd_cc();

			gen_op_store_DT0_fpr(rd);

			break;

		    case 0x043: /* V9 fmovqcc %fcc1 */

		        goto nfpu_insn;

		    case 0x081: /* V9 fmovscc %fcc2 */

			cond = GET_FIELD_SP(insn, 14, 17);

                	gen_op_load_fpr_FT0(rd);

                	gen_op_load_fpr_FT1(rs2);

			flush_T2(dc);

			gen_fcond[2][cond]();

			gen_op_fmovs_cc();

			gen_op_store_FT0_fpr(rd);

			break;

		    case 0x082: /* V9 fmovdcc %fcc2 */

			cond = GET_FIELD_SP(insn, 14, 17);

                	gen_op_load_fpr_DT0(rd);

                	gen_op_load_fpr_DT1(rs2);

			flush_T2(dc);

			gen_fcond[2][cond]();

			gen_op_fmovd_cc();

			gen_op_store_DT0_fpr(rd);

			break;

		    case 0x083: /* V9 fmovqcc %fcc2 */

		        goto nfpu_insn;

		    case 0x0c1: /* V9 fmovscc %fcc3 */

			cond = GET_FIELD_SP(insn, 14, 17);

                	gen_op_load_fpr_FT0(rd);

                	gen_op_load_fpr_FT1(rs2);

			flush_T2(dc);

			gen_fcond[3][cond]();

			gen_op_fmovs_cc();

			gen_op_store_FT0_fpr(rd);

			break;

		    case 0x0c2: /* V9 fmovdcc %fcc3 */

			cond = GET_FIELD_SP(insn, 14, 17);

                	gen_op_load_fpr_DT0(rd);

                	gen_op_load_fpr_DT1(rs2);

			flush_T2(dc);

			gen_fcond[3][cond]();

			gen_op_fmovd_cc();

			gen_op_store_DT0_fpr(rd);

			break;

		    case 0x0c3: /* V9 fmovqcc %fcc3 */

		        goto nfpu_insn;

		    case 0x101: /* V9 fmovscc %icc */

			cond = GET_FIELD_SP(insn, 14, 17);

                	gen_op_load_fpr_FT0(rd);

                	gen_op_load_fpr_FT1(rs2);

			flush_T2(dc);

			gen_cond[0][cond]();

			gen_op_fmovs_cc();

			gen_op_store_FT0_fpr(rd);

			break;

		    case 0x102: /* V9 fmovdcc %icc */

			cond = GET_FIELD_SP(insn, 14, 17);

                	gen_op_load_fpr_DT0(rd);

                	gen_op_load_fpr_DT1(rs2);

			flush_T2(dc);

			gen_cond[0][cond]();

			gen_op_fmovd_cc();

			gen_op_store_DT0_fpr(rd);

			break;

		    case 0x103: /* V9 fmovqcc %icc */

		        goto nfpu_insn;

		    case 0x181: /* V9 fmovscc %xcc */

			cond = GET_FIELD_SP(insn, 14, 17);

                	gen_op_load_fpr_FT0(rd);

                	gen_op_load_fpr_FT1(rs2);

			flush_T2(dc);

			gen_cond[1][cond]();

			gen_op_fmovs_cc();

			gen_op_store_FT0_fpr(rd);

			break;

		    case 0x182: /* V9 fmovdcc %xcc */

			cond = GET_FIELD_SP(insn, 14, 17);

                	gen_op_load_fpr_DT0(rd);

                	gen_op_load_fpr_DT1(rs2);

			flush_T2(dc);

			gen_cond[1][cond]();

			gen_op_fmovd_cc();

			gen_op_store_DT0_fpr(rd);

			break;

		    case 0x183: /* V9 fmovqcc %xcc */

		        goto nfpu_insn;

#endif

		    case 0x51: /* V9 %fcc */

                	gen_op_load_fpr_FT0(rs1);

                	gen_op_load_fpr_FT1(rs2);

#ifdef TARGET_SPARC64

			gen_fcmps[rd & 3]();

#else

			gen_op_fcmps();

#endif

			break;

		    case 0x52: /* V9 %fcc */

                	gen_op_load_fpr_DT0(DFPREG(rs1));

                	gen_op_load_fpr_DT1(DFPREG(rs2));

#ifdef TARGET_SPARC64

			gen_fcmpd[rd & 3]();

#else

			gen_op_fcmpd();

#endif

			break;

		    case 0x53: /* fcmpq */

		        goto nfpu_insn;

		    case 0x55: /* fcmpes, V9 %fcc */

                	gen_op_load_fpr_FT0(rs1);

                	gen_op_load_fpr_FT1(rs2);

#ifdef TARGET_SPARC64

			gen_fcmps[rd & 3]();

#else

			gen_op_fcmps(); /* XXX should trap if qNaN or sNaN  */

#endif

			break;

		    case 0x56: /* fcmped, V9 %fcc */

                	gen_op_load_fpr_DT0(DFPREG(rs1));

                	gen_op_load_fpr_DT1(DFPREG(rs2));

#ifdef TARGET_SPARC64

			gen_fcmpd[rd & 3]();

#else

			gen_op_fcmpd(); /* XXX should trap if qNaN or sNaN  */

#endif

			break;

		    case 0x57: /* fcmpeq */

		        goto nfpu_insn;

		    default:

		}

#if defined(OPTIM)

	    } else if (xop == 0x2) {

		// clr/mov shortcut

                rs1 = GET_FIELD(insn, 13, 17);

		if (rs1 == 0) {

		    // or %g0, x, y -> mov T1, x; mov y, T1

		    if (IS_IMM) {	/* immediate */

			rs2 = GET_FIELDs(insn, 19, 31);

			gen_movl_simm_T1(rs2);

		    } else {		/* register */

			rs2 = GET_FIELD(insn, 27, 31);

			gen_movl_reg_T1(rs2);

		    }

		    gen_movl_T1_reg(rd);

		} else {

		    gen_movl_reg_T0(rs1);

		    if (IS_IMM) {	/* immediate */

			// or x, #0, y -> mov T1, x; mov y, T1

			rs2 = GET_FIELDs(insn, 19, 31);

			if (rs2 != 0) {

			    gen_movl_simm_T1(rs2);

			    gen_op_or_T1_T0();

			}

		    } else {		/* register */

			// or x, %g0, y -> mov T1, x; mov y, T1

			rs2 = GET_FIELD(insn, 27, 31);

			if (rs2 != 0) {

			    gen_movl_reg_T1(rs2);

			    gen_op_or_T1_T0();

			}

		    }

		    gen_movl_T0_reg(rd);

		}

#endif

#ifdef TARGET_SPARC64

	    } else if (xop == 0x25) { /* sll, V9 sllx ( == sll) */

                rs1 = GET_FIELD(insn, 13, 17);

		gen_movl_reg_T0(rs1);

		if (IS_IMM) {	/* immediate */

                    rs2 = GET_FIELDs(insn, 20, 31);

                    gen_movl_simm_T1(rs2);

                } else {		/* register */

                    rs2 = GET_FIELD(insn, 27, 31);

                    gen_movl_reg_T1(rs2);

                }

		gen_op_sll();

		gen_movl_T0_reg(rd);

	    } else if (xop == 0x26) { /* srl, V9 srlx */

                rs1 = GET_FIELD(insn, 13, 17);

		gen_movl_reg_T0(rs1);

		if (IS_IMM) {	/* immediate */

                    rs2 = GET_FIELDs(insn, 20, 31);

                    gen_movl_simm_T1(rs2);

                } else {		/* register */

                    rs2 = GET_FIELD(insn, 27, 31);

                    gen_movl_reg_T1(rs2);

                }

		if (insn & (1 << 12))

		    gen_op_srlx();

		else

		    gen_op_srl();

		gen_movl_T0_reg(rd);

	    } else if (xop == 0x27) { /* sra, V9 srax */

                rs1 = GET_FIELD(insn, 13, 17);

		gen_movl_reg_T0(rs1);

		if (IS_IMM) {	/* immediate */

                    rs2 = GET_FIELDs(insn, 20, 31);

                    gen_movl_simm_T1(rs2);

                } else {		/* register */

                    rs2 = GET_FIELD(insn, 27, 31);

                    gen_movl_reg_T1(rs2);

                }

		if (insn & (1 << 12))

		    gen_op_srax();

		else

		    gen_op_sra();

		gen_movl_T0_reg(rd);

#endif

            } else if (xop < 0x36) {

                rs1 = GET_FIELD(insn, 13, 17);

		gen_movl_reg_T0(rs1);

		if (IS_IMM) {	/* immediate */

                    rs2 = GET_FIELDs(insn, 19, 31);

                    gen_movl_simm_T1(rs2);

                } else {		/* register */

                    rs2 = GET_FIELD(insn, 27, 31);

                    gen_movl_reg_T1(rs2);

                }

                if (xop < 0x20) {

                    switch (xop & ~0x10) {

                    case 0x0:

                        if (xop & 0x10)

                            gen_op_add_T1_T0_cc();

                        else

                            gen_op_add_T1_T0();

                        break;

                    case 0x1:

                        gen_op_and_T1_T0();

                        if (xop & 0x10)

                            gen_op_logic_T0_cc();

                        break;

                    case 0x2:

			gen_op_or_T1_T0();

			if (xop & 0x10)

			    gen_op_logic_T0_cc();

			break;

                    case 0x3:

                        gen_op_xor_T1_T0();

                        if (xop & 0x10)

                            gen_op_logic_T0_cc();

                        break;

                    case 0x4:

                        if (xop & 0x10)

                            gen_op_sub_T1_T0_cc();

                        else

                            gen_op_sub_T1_T0();

                        break;

                    case 0x5:

                        gen_op_andn_T1_T0();

                        if (xop & 0x10)

                            gen_op_logic_T0_cc();

                        break;

                    case 0x6:

                        gen_op_orn_T1_T0();

                        if (xop & 0x10)

                            gen_op_logic_T0_cc();

                        break;

                    case 0x7:

                        gen_op_xnor_T1_T0();

                        if (xop & 0x10)

                            gen_op_logic_T0_cc();

                        break;

                    case 0x8:

                        if (xop & 0x10)

                            gen_op_addx_T1_T0_cc();

                        else

                            gen_op_addx_T1_T0();

                        break;

#ifdef TARGET_SPARC64

		    case 0x9: /* V9 mulx */

                        gen_op_mulx_T1_T0();

                        break;

#endif

                    case 0xa:

                        gen_op_umul_T1_T0();

                        if (xop & 0x10)

                            gen_op_logic_T0_cc();

                        break;

                    case 0xb:

                        gen_op_smul_T1_T0();

                        if (xop & 0x10)

                            gen_op_logic_T0_cc();

                        break;

                    case 0xc:

                        if (xop & 0x10)

                            gen_op_subx_T1_T0_cc();

                        else

                            gen_op_subx_T1_T0();

                        break;

#ifdef TARGET_SPARC64

		    case 0xd: /* V9 udivx */

                        gen_op_udivx_T1_T0();

                        break;

#endif

                    case 0xe:

                        gen_op_udiv_T1_T0();

                        if (xop & 0x10)

                            gen_op_div_cc();

                        break;

                    case 0xf:

                        gen_op_sdiv_T1_T0();

                        if (xop & 0x10)

                            gen_op_div_cc();

                        break;

                    default:

                    }

		    gen_movl_T0_reg(rd);

                } else {

                    switch (xop) {

		    case 0x20: /* taddcc */

			gen_op_tadd_T1_T0_cc();

		        gen_movl_T0_reg(rd);

			break;

		    case 0x21: /* tsubcc */

			gen_op_tsub_T1_T0_cc();

		        gen_movl_T0_reg(rd);

			break;

		    case 0x22: /* taddcctv */

			gen_op_tadd_T1_T0_ccTV();

		        gen_movl_T0_reg(rd);

			break;

		    case 0x23: /* tsubcctv */

			gen_op_tsub_T1_T0_ccTV();

		        gen_movl_T0_reg(rd);

			break;

                    case 0x24: /* mulscc */

                        gen_op_mulscc_T1_T0();

                        gen_movl_T0_reg(rd);

                        break;

#ifndef TARGET_SPARC64

                    case 0x25:	/* sll */

			gen_op_sll();

                        gen_movl_T0_reg(rd);

                        break;

                    case 0x26:  /* srl */

			gen_op_srl();

                        gen_movl_T0_reg(rd);

                        break;

                    case 0x27:  /* sra */

			gen_op_sra();

                        gen_movl_T0_reg(rd);

                        break;

#endif

                    case 0x30:

                        {

                            switch(rd) {

                            case 0: /* wry */

				gen_op_xor_T1_T0();

				gen_op_movtl_env_T0(offsetof(CPUSPARCState, y));

                                break;

#ifndef TARGET_SPARC64

                            case 0x01 ... 0x0f: /* undefined in the

                                                   SPARCv8 manual, nop

                                                   on the microSPARC

                                                   II */

                            case 0x10 ... 0x1f: /* implementation-dependent

                                                   in the SPARCv8

                                                   manual, nop on the

                                                   microSPARC II */

                                break;

#else

			    case 0x2: /* V9 wrccr */

                                gen_op_wrccr();

				break;

			    case 0x3: /* V9 wrasi */

				gen_op_movl_env_T0(offsetof(CPUSPARCState, asi));

				break;

			    case 0x6: /* V9 wrfprs */

				gen_op_movl_env_T0(offsetof(CPUSPARCState, fprs));

				break;

			    case 0xf: /* V9 sir, nop if user */

#if !defined(CONFIG_USER_ONLY)

				if (supervisor(dc))

				    gen_op_sir();

#endif

				break;

			    case 0x13: /* Graphics Status */

                                if (gen_trap_ifnofpu(dc))

                                    goto jmp_insn;

				gen_op_movtl_env_T0(offsetof(CPUSPARCState, gsr));

				break;

			    case 0x17: /* Tick compare */

#if !defined(CONFIG_USER_ONLY)

				if (!supervisor(dc))

#endif

				gen_op_movtl_env_T0(offsetof(CPUSPARCState, tick_cmpr));

				break;

			    case 0x18: /* System tick */

#if !defined(CONFIG_USER_ONLY)

				if (!supervisor(dc))

#endif

				gen_op_movtl_env_T0(offsetof(CPUSPARCState, stick_cmpr));

				break;

			    case 0x19: /* System tick compare */

#if !defined(CONFIG_USER_ONLY)

				if (!supervisor(dc))

#endif

				gen_op_movtl_env_T0(offsetof(CPUSPARCState, stick_cmpr));

				break;

			    case 0x10: /* Performance Control */

			    case 0x11: /* Performance Instrumentation Counter */

			    case 0x12: /* Dispatch Control */

			    case 0x14: /* Softint set */

			    case 0x15: /* Softint clear */

			    case 0x16: /* Softint write */

#endif

                            default:

                            }

                        }

                        break;

#if !defined(CONFIG_USER_ONLY)

                    case 0x31: /* wrpsr, V9 saved, restored */

                        {

			    if (!supervisor(dc))

				goto priv_insn;

#ifdef TARGET_SPARC64

			    switch (rd) {

			    case 0:

				gen_op_saved();

				break;

			    case 1:

				gen_op_restored();

				break;

			    default:

                            }

#else

                            gen_op_xor_T1_T0();

                            gen_op_wrpsr();

                            save_state(dc);

                            gen_op_next_insn();

			    gen_op_movl_T0_0();

			    gen_op_exit_tb();

			    dc->is_br = 1;

#endif

                        }

                        break;

                    case 0x32: /* wrwim, V9 wrpr */

                        {

			    if (!supervisor(dc))

				goto priv_insn;

                            gen_op_xor_T1_T0();

#ifdef TARGET_SPARC64

			    switch (rd) {

			    case 0: // tpc

				gen_op_wrtpc();

				break;

			    case 1: // tnpc

				gen_op_wrtnpc();

				break;

			    case 2: // tstate

				gen_op_wrtstate();

				break;

			    case 3: // tt

				gen_op_wrtt();

				break;

			    case 4: // tick

				gen_op_wrtick();

				break;

			    case 5: // tba

				gen_op_movtl_env_T0(offsetof(CPUSPARCState, tbr));

				break;

			    case 6: // pstate

				gen_op_wrpstate();

                                save_state(dc);

                                gen_op_next_insn();

                                gen_op_movl_T0_0();

                                gen_op_exit_tb();

                                dc->is_br = 1;

				break;

			    case 7: // tl

				gen_op_movl_env_T0(offsetof(CPUSPARCState, tl));

				break;

			    case 8: // pil

				gen_op_movl_env_T0(offsetof(CPUSPARCState, psrpil));

				break;

			    case 9: // cwp

				gen_op_wrcwp();

				break;

			    case 10: // cansave

				gen_op_movl_env_T0(offsetof(CPUSPARCState, cansave));

				break;

			    case 11: // canrestore

				gen_op_movl_env_T0(offsetof(CPUSPARCState, canrestore));

				break;

			    case 12: // cleanwin

				gen_op_movl_env_T0(offsetof(CPUSPARCState, cleanwin));

				break;

			    case 13: // otherwin

				gen_op_movl_env_T0(offsetof(CPUSPARCState, otherwin));

				break;

			    case 14: // wstate

				gen_op_movl_env_T0(offsetof(CPUSPARCState, wstate));

				break;

			    default:

			    }

#else

			    gen_op_wrwim();

#endif

                        }

                        break;

#ifndef TARGET_SPARC64

                    case 0x33: /* wrtbr, V9 unimp */

                        {

			    if (!supervisor(dc))

				goto priv_insn;

                            gen_op_xor_T1_T0();

			    gen_op_movtl_env_T0(offsetof(CPUSPARCState, tbr));

                        }

                        break;

#endif

#endif

#ifdef TARGET_SPARC64

		    case 0x2c: /* V9 movcc */

			{

			    int cc = GET_FIELD_SP(insn, 11, 12);

			    int cond = GET_FIELD_SP(insn, 14, 17);

			    if (IS_IMM) {	/* immediate */

				rs2 = GET_FIELD_SPs(insn, 0, 10);

				gen_movl_simm_T1(rs2);

			    }

			    else {

				rs2 = GET_FIELD_SP(insn, 0, 4);

				gen_movl_reg_T1(rs2);

			    }

			    gen_movl_reg_T0(rd);

			    flush_T2(dc);

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

				if (cc == 0)

				    gen_cond[0][cond]();

				else if (cc == 2)

				    gen_cond[1][cond]();

				else

			    } else {

				gen_fcond[cc][cond]();

			    }

			    gen_op_mov_cc();

			    gen_movl_T0_reg(rd);

			    break;

			}

		    case 0x2d: /* V9 sdivx */

                        gen_op_sdivx_T1_T0();

			gen_movl_T0_reg(rd);

                        break;

		    case 0x2e: /* V9 popc */

			{

			    if (IS_IMM) {	/* immediate */

				rs2 = GET_FIELD_SPs(insn, 0, 12);

				gen_movl_simm_T1(rs2);

				// XXX optimize: popc(constant)

			    }

			    else {

				rs2 = GET_FIELD_SP(insn, 0, 4);

				gen_movl_reg_T1(rs2);

			    }

			    gen_op_popc();

			    gen_movl_T0_reg(rd);

			}

		    case 0x2f: /* V9 movr */

			{

			    int cond = GET_FIELD_SP(insn, 10, 12);

			    rs1 = GET_FIELD(insn, 13, 17);

			    flush_T2(dc);

			    gen_movl_reg_T0(rs1);

			    gen_cond_reg(cond);

			    if (IS_IMM) {	/* immediate */

				rs2 = GET_FIELD_SPs(insn, 0, 10);

				gen_movl_simm_T1(rs2);

			    }

			    else {

				rs2 = GET_FIELD_SP(insn, 0, 4);

				gen_movl_reg_T1(rs2);

			    }

			    gen_movl_reg_T0(rd);

			    gen_op_mov_cc();

			    gen_movl_T0_reg(rd);

			    break;

			}

		    case 0x36: /* UltraSparc shutdown, VIS */

			{

			    int opf = GET_FIELD_SP(insn, 5, 13);

                            rs1 = GET_FIELD(insn, 13, 17);

                            rs2 = GET_FIELD(insn, 27, 31);

                            switch (opf) {

                            case 0x018: /* VIS I alignaddr */

                                if (gen_trap_ifnofpu(dc))

                                    goto jmp_insn;

                                gen_movl_reg_T0(rs1);

                                gen_movl_reg_T1(rs2);

                                gen_op_alignaddr();

                                gen_movl_T0_reg(rd);

                                break;

                            case 0x01a: /* VIS I alignaddrl */

                                if (gen_trap_ifnofpu(dc))

                                    goto jmp_insn;

                                // XXX

                                break;

                            case 0x048: /* VIS I faligndata */

                                if (gen_trap_ifnofpu(dc))

                                    goto jmp_insn;

                                gen_op_load_fpr_DT0(rs1);

                                gen_op_load_fpr_DT1(rs2);

                                gen_op_faligndata();

                                gen_op_store_DT0_fpr(rd);

                                break;

                            default:

                            }

                            break;

			}

#endif

		    default:

		    }

		}

            } else if (xop == 0x36 || xop == 0x37) { /* CPop1 & CPop2,

                                                        V9 impdep1 &

                                                        impdep2 */

#ifdef TARGET_SPARC64

#else

	        goto ncp_insn;

#endif

#ifdef TARGET_SPARC64

	    } else if (xop == 0x39) { /* V9 return */

                rs1 = GET_FIELD(insn, 13, 17);

		gen_movl_reg_T0(rs1);

                if (IS_IMM) {	/* immediate */

		    rs2 = GET_FIELDs(insn, 19, 31);

#if defined(OPTIM)

		    if (rs2) {

#endif

			gen_movl_simm_T1(rs2);

			gen_op_add_T1_T0();

#if defined(OPTIM)

		    }

#endif

                } else {		/* register */

                    rs2 = GET_FIELD(insn, 27, 31);

#if defined(OPTIM)

		    if (rs2) {

#endif

			gen_movl_reg_T1(rs2);

			gen_op_add_T1_T0();

#if defined(OPTIM)

		    }

#endif

                }

		gen_op_restore();

		gen_mov_pc_npc(dc);

		gen_op_movl_npc_T0();

		dc->npc = DYNAMIC_PC;

		goto jmp_insn;

#endif

	    } else {

                rs1 = GET_FIELD(insn, 13, 17);

		gen_movl_reg_T0(rs1);

                if (IS_IMM) {	/* immediate */

		    rs2 = GET_FIELDs(insn, 19, 31);

#if defined(OPTIM)

		    if (rs2) {

#endif

			gen_movl_simm_T1(rs2);

			gen_op_add_T1_T0();

#if defined(OPTIM)

		    }

#endif

                } else {		/* register */

                    rs2 = GET_FIELD(insn, 27, 31);

#if defined(OPTIM)

		    if (rs2) {

#endif

			gen_movl_reg_T1(rs2);

			gen_op_add_T1_T0();

#if defined(OPTIM)

		    }

#endif

                }

		switch (xop) {

		case 0x38:	/* jmpl */

		    {

			if (rd != 0) {

#ifdef TARGET_SPARC64

                            if (dc->pc == (uint32_t)dc->pc) {

                                gen_op_movl_T1_im(dc->pc);

                            } else {

                                gen_op_movq_T1_im64(dc->pc >> 32, dc->pc);

                            }

#else

			    gen_op_movl_T1_im(dc->pc);

#endif

			    gen_movl_T1_reg(rd);

			}

                        gen_mov_pc_npc(dc);

			gen_op_movl_npc_T0();

			dc->npc = DYNAMIC_PC;

		    }

		    goto jmp_insn;

#if !defined(CONFIG_USER_ONLY) && !defined(TARGET_SPARC64)

		case 0x39:	/* rett, V9 return */

		    {

			if (!supervisor(dc))

			    goto priv_insn;

                        gen_mov_pc_npc(dc);

			gen_op_movl_npc_T0();

			dc->npc = DYNAMIC_PC;

			gen_op_rett();

		    }

		    goto jmp_insn;

#endif

		case 0x3b: /* flush */

		    gen_op_flush_T0();

		    break;

		case 0x3c:	/* save */

		    save_state(dc);

		    gen_op_save();

		    gen_movl_T0_reg(rd);

		    break;

		case 0x3d:	/* restore */

		    save_state(dc);

		    gen_op_restore();

		    gen_movl_T0_reg(rd);

		    break;

#if !defined(CONFIG_USER_ONLY) && defined(TARGET_SPARC64)

		case 0x3e:      /* V9 done/retry */

		    {

			switch (rd) {

			case 0:

			    if (!supervisor(dc))

				goto priv_insn;

			    dc->npc = DYNAMIC_PC;

			    dc->pc = DYNAMIC_PC;

			    gen_op_done();

			    goto jmp_insn;

			case 1:

			    if (!supervisor(dc))

				goto priv_insn;

			    dc->npc = DYNAMIC_PC;

			    dc->pc = DYNAMIC_PC;

			    gen_op_retry();

			    goto jmp_insn;

			default:

			}

		    }

		    break;

#endif

		default:

		}

            }

	    break;

	}

	break;

    case 3:			/* load/store instructions */

	{

	    unsigned int xop = GET_FIELD(insn, 7, 12);

	    rs1 = GET_FIELD(insn, 13, 17);

	    gen_movl_reg_T0(rs1);

	    if (IS_IMM) {	/* immediate */

		rs2 = GET_FIELDs(insn, 19, 31);

#if defined(OPTIM)

		if (rs2 != 0) {

#endif

		    gen_movl_simm_T1(rs2);

		    gen_op_add_T1_T0();

#if defined(OPTIM)

		}

#endif

	    } else {		/* register */

		rs2 = GET_FIELD(insn, 27, 31);

#if defined(OPTIM)

		if (rs2 != 0) {

#endif

		    gen_movl_reg_T1(rs2);

		    gen_op_add_T1_T0();

#if defined(OPTIM)

		}

#endif

	    }

	    if (xop < 4 || (xop > 7 && xop < 0x14 && xop != 0x0e) || \

		    (xop > 0x17 && xop < 0x1d ) || \

		    (xop > 0x2c && xop < 0x33) || xop == 0x1f) {

		switch (xop) {

		case 0x0:	/* load word */

		    gen_op_ldst(ld);

		    break;

		case 0x1:	/* load unsigned byte */

		    gen_op_ldst(ldub);

		    break;

		case 0x2:	/* load unsigned halfword */

		    gen_op_ldst(lduh);

		    break;

		case 0x3:	/* load double word */

		    gen_op_ldst(ldd);

		    gen_movl_T0_reg(rd + 1);

		    break;

		case 0x9:	/* load signed byte */

		    gen_op_ldst(ldsb);

		    break;

		case 0xa:	/* load signed halfword */

		    gen_op_ldst(ldsh);

		    break;

		case 0xd:	/* ldstub -- XXX: should be atomically */

		    gen_op_ldst(ldstub);

		    break;

		case 0x0f:	/* swap register with memory. Also atomically */

		    gen_movl_reg_T1(rd);

		    gen_op_ldst(swap);

		    break;

#if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64)

		case 0x10:	/* load word alternate */

#ifndef TARGET_SPARC64

		    if (IS_IMM)

		    if (!supervisor(dc))

			goto priv_insn;

#endif

		    gen_op_lda(insn, 1, 4, 0);

		    break;

		case 0x11:	/* load unsigned byte alternate */

#ifndef TARGET_SPARC64

		    if (IS_IMM)

		    if (!supervisor(dc))

			goto priv_insn;

#endif

		    gen_op_lduba(insn, 1, 1, 0);

		    break;

		case 0x12:	/* load unsigned halfword alternate */

#ifndef TARGET_SPARC64

		    if (IS_IMM)

		    if (!supervisor(dc))

			goto priv_insn;

#endif

		    gen_op_lduha(insn, 1, 2, 0);

		    break;

		case 0x13:	/* load double word alternate */

#ifndef TARGET_SPARC64

		    if (IS_IMM)

		    if (!supervisor(dc))

			goto priv_insn;

#endif

		    gen_op_ldda(insn, 1, 8, 0);

		    gen_movl_T0_reg(rd + 1);

		    break;

		case 0x19:	/* load signed byte alternate */

#ifndef TARGET_SPARC64

		    if (IS_IMM)

		    if (!supervisor(dc))

			goto priv_insn;

#endif

		    gen_op_ldsba(insn, 1, 1, 1);

		    break;

		case 0x1a:	/* load signed halfword alternate */

#ifndef TARGET_SPARC64

		    if (IS_IMM)

		    if (!supervisor(dc))

			goto priv_insn;

#endif

		    gen_op_ldsha(insn, 1, 2 ,1);

		    break;

		case 0x1d:	/* ldstuba -- XXX: should be atomically */

#ifndef TARGET_SPARC64

		    if (IS_IMM)

		    if (!supervisor(dc))

			goto priv_insn;

#endif

		    gen_op_ldstuba(insn, 1, 1, 0);

		    break;

		case 0x1f:	/* swap reg with alt. memory. Also atomically */

#ifndef TARGET_SPARC64

		    if (IS_IMM)

		    if (!supervisor(dc))

			goto priv_insn;

#endif

		    gen_movl_reg_T1(rd);

		    gen_op_swapa(insn, 1, 4, 0);

		    break;

#ifndef TARGET_SPARC64

		case 0x30: /* ldc */

		case 0x31: /* ldcsr */

		case 0x33: /* lddc */

		case 0x34: /* stc */

		case 0x35: /* stcsr */

		case 0x36: /* stdcq */

		case 0x37: /* stdc */

		    goto ncp_insn;

		    break;

                    /* avoid warnings */

                    (void) &gen_op_stfa;

                    (void) &gen_op_stdfa;

                    (void) &gen_op_ldfa;

                    (void) &gen_op_lddfa;

#else

#if !defined(CONFIG_USER_ONLY)

		    (void) &gen_op_cas;

		    (void) &gen_op_casx;

#endif

#endif

#endif

#ifdef TARGET_SPARC64

		case 0x08: /* V9 ldsw */

		    gen_op_ldst(ldsw);

		    break;

		case 0x0b: /* V9 ldx */

		    gen_op_ldst(ldx);

		    break;

		case 0x18: /* V9 ldswa */

		    gen_op_ldswa(insn, 1, 4, 1);

		    break;

		case 0x1b: /* V9 ldxa */

		    gen_op_ldxa(insn, 1, 8, 0);

		    break;

		case 0x2d: /* V9 prefetch, no effect */

		    goto skip_move;

		case 0x30: /* V9 ldfa */

		    gen_op_ldfa(insn, 1, 8, 0); // XXX

		    break;

		case 0x33: /* V9 lddfa */

		    gen_op_lddfa(insn, 1, 8, 0); // XXX

		    break;

		case 0x3d: /* V9 prefetcha, no effect */

		    goto skip_move;

		case 0x32: /* V9 ldqfa */

		    goto nfpu_insn;

#endif

		default:

		}

		gen_movl_T1_reg(rd);

#ifdef TARGET_SPARC64

	    skip_move: ;

#endif

	    } else if (xop >= 0x20 && xop < 0x24) {

                if (gen_trap_ifnofpu(dc))

                    goto jmp_insn;

		switch (xop) {

		case 0x20:	/* load fpreg */

		    gen_op_ldst(ldf);

		    gen_op_store_FT0_fpr(rd);

		    break;

		case 0x21:	/* load fsr */

		    gen_op_ldst(ldf);

		    gen_op_ldfsr();

		    break;

		case 0x22:      /* load quad fpreg */

		    goto nfpu_insn;

		case 0x23:	/* load double fpreg */

		    gen_op_ldst(lddf);

		    gen_op_store_DT0_fpr(DFPREG(rd));

		    break;

		default:

		}

	    } else if (xop < 8 || (xop >= 0x14 && xop < 0x18) || \

		       xop == 0xe || xop == 0x1e) {

		gen_movl_reg_T1(rd);

		switch (xop) {

		case 0x4:

		    gen_op_ldst(st);

		    break;

		case 0x5:

		    gen_op_ldst(stb);

		    break;

		case 0x6:

		    gen_op_ldst(sth);

		    break;

		case 0x7:

                    flush_T2(dc);

		    gen_movl_reg_T2(rd + 1);

		    gen_op_ldst(std);

		    break;

#if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64)

		case 0x14:

#ifndef TARGET_SPARC64

		    if (IS_IMM)

		    if (!supervisor(dc))

			goto priv_insn;

#endif

		    gen_op_sta(insn, 0, 4, 0);

                    break;

		case 0x15:

#ifndef TARGET_SPARC64

		    if (IS_IMM)

		    if (!supervisor(dc))

			goto priv_insn;

#endif

		    gen_op_stba(insn, 0, 1, 0);

                    break;

		case 0x16:

#ifndef TARGET_SPARC64

		    if (IS_IMM)

		    if (!supervisor(dc))

			goto priv_insn;

#endif

		    gen_op_stha(insn, 0, 2, 0);

                    break;

		case 0x17:

#ifndef TARGET_SPARC64

		    if (IS_IMM)

		    if (!supervisor(dc))

			goto priv_insn;

#endif

                    flush_T2(dc);

		    gen_movl_reg_T2(rd + 1);

		    gen_op_stda(insn, 0, 8, 0);

                    break;

#endif

#ifdef TARGET_SPARC64

		case 0x0e: /* V9 stx */

		    gen_op_ldst(stx);

		    break;

		case 0x1e: /* V9 stxa */

		    gen_op_stxa(insn, 0, 8, 0); // XXX

		    break;

#endif

		default:

		}

	    } else if (xop > 0x23 && xop < 0x28) {

                if (gen_trap_ifnofpu(dc))

                    goto jmp_insn;

		switch (xop) {

		case 0x24:

                    gen_op_load_fpr_FT0(rd);

		    gen_op_ldst(stf);

		    break;

		case 0x25: /* stfsr, V9 stxfsr */

		    gen_op_stfsr();

		    gen_op_ldst(stf);

		    break;

		case 0x26: /* stdfq */

		    goto nfpu_insn;

		case 0x27:

                    gen_op_load_fpr_DT0(DFPREG(rd));

		    gen_op_ldst(stdf);

		    break;

		default:

		}

	    } else if (xop > 0x33 && xop < 0x3f) {

#ifdef TARGET_SPARC64

		switch (xop) {

		case 0x34: /* V9 stfa */

		    gen_op_stfa(insn, 0, 0, 0); // XXX

		    break;

		case 0x37: /* V9 stdfa */

		    gen_op_stdfa(insn, 0, 0, 0); // XXX

		    break;

		case 0x3c: /* V9 casa */

		    gen_op_casa(insn, 0, 4, 0); // XXX

		    break;

		case 0x3e: /* V9 casxa */

		    gen_op_casxa(insn, 0, 8, 0); // XXX

		    break;

		case 0x36: /* V9 stqfa */

		    goto nfpu_insn;

		default:

		}

#else

#endif

            }

	    else

	}

	break;

    }

    /* default case for non jump instructions */

    if (dc->npc == DYNAMIC_PC) {

	dc->pc = DYNAMIC_PC;

	gen_op_next_insn();

    } else if (dc->npc == JUMP_PC) {

        /* we can do a static jump */

        gen_branch2(dc, (long)dc->tb, dc->jump_pc[0], dc->jump_pc[1]);

        dc->is_br = 1;

    } else {

	dc->pc = dc->npc;

	dc->npc = dc->npc + 4;

    }

 jmp_insn:

    return;

 illegal_insn:

    save_state(dc);

    gen_op_exception(TT_ILL_INSN);

    dc->is_br = 1;

    return;

#if !defined(CONFIG_USER_ONLY)

 priv_insn:

    save_state(dc);

    gen_op_exception(TT_PRIV_INSN);

    dc->is_br = 1;

    return;

#endif

 nfpu_insn:

    save_state(dc);

    gen_op_fpexception_im(FSR_FTT_UNIMPFPOP);

    dc->is_br = 1;

    return;

#ifndef TARGET_SPARC64

 ncp_insn:

    save_state(dc);

    gen_op_exception(TT_NCP_INSN);

    dc->is_br = 1;

    return;

#endif

}


int av_buffersrc_buffer(AVFilterContext *ctx, AVFilterBufferRef *buf)

{

    BufferSourceContext *s = ctx->priv;

    AVFrame *frame = NULL;

    AVBufferRef *dummy_buf = NULL;

    int ret = 0, planes, i;

    if (!buf) {

        s->eof = 1;

        return 0;

    } else if (s->eof)

        return AVERROR(EINVAL);

    frame = av_frame_alloc();

    if (!frame)

        return AVERROR(ENOMEM);

    dummy_buf = av_buffer_create(NULL, 0, compat_free_buffer, buf, 0);

    if (!dummy_buf) {

        ret = AVERROR(ENOMEM);

        goto fail;

    }

    if ((ret = avfilter_copy_buf_props(frame, buf)) < 0)

        goto fail;

#define WRAP_PLANE(ref_out, data, data_size)                            \

do {                                                                    \

    AVBufferRef *dummy_ref = av_buffer_ref(dummy_buf);                  \

    if (!dummy_ref) {                                                   \

        ret = AVERROR(ENOMEM);                                          \

        goto fail;                                                      \

    }                                                                   \

    ref_out = av_buffer_create(data, data_size, compat_unref_buffer,    \

                               dummy_ref, 0);                           \

    if (!ref_out) {                                                     \

        av_frame_unref(frame);                                          \

        ret = AVERROR(ENOMEM);                                          \

        goto fail;                                                      \

    }                                                                   \

} while (0)

    if (ctx->outputs[0]->type  == AVMEDIA_TYPE_VIDEO) {

        const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(frame->format);

        planes = av_pix_fmt_count_planes(frame->format);

        if (!desc || planes <= 0) {

            ret = AVERROR(EINVAL);

            goto fail;

        }

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

            int v_shift    = (i == 1 || i == 2) ? desc->log2_chroma_h : 0;

            int plane_size = (frame->height >> v_shift) * frame->linesize[i];

            WRAP_PLANE(frame->buf[i], frame->data[i], plane_size);

        }

    } else {

        int planar = av_sample_fmt_is_planar(frame->format);

        int channels = av_get_channel_layout_nb_channels(frame->channel_layout);

        planes = planar ? channels : 1;

        if (planes > FF_ARRAY_ELEMS(frame->buf)) {

            frame->nb_extended_buf = planes - FF_ARRAY_ELEMS(frame->buf);

            frame->extended_buf = av_mallocz(sizeof(*frame->extended_buf) *

                                             frame->nb_extended_buf);

            if (!frame->extended_buf) {

                ret = AVERROR(ENOMEM);

                goto fail;

            }

        }

        for (i = 0; i < FFMIN(planes, FF_ARRAY_ELEMS(frame->buf)); i++)

            WRAP_PLANE(frame->buf[i], frame->extended_data[i], frame->linesize[0]);

        for (i = 0; i < planes - FF_ARRAY_ELEMS(frame->buf); i++)

            WRAP_PLANE(frame->extended_buf[i],

                       frame->extended_data[i + FF_ARRAY_ELEMS(frame->buf)],

                       frame->linesize[0]);

    }

    ret = av_buffersrc_add_frame(ctx, frame);

fail:

    av_buffer_unref(&dummy_buf);

    av_frame_free(&frame);

    return ret;

}


void msi_uninit(struct PCIDevice *dev)

{

    uint16_t flags = pci_get_word(dev->config + msi_flags_off(dev));

    uint8_t cap_size = msi_cap_sizeof(flags);

    pci_del_capability(dev, PCI_CAP_ID_MSIX, cap_size);

    MSI_DEV_PRINTF(dev, "uninit\n");

}


Object *user_creatable_add(const QDict *qdict,

                           Visitor *v, Error **errp)

{

    char *type = NULL;

    char *id = NULL;

    Object *obj = NULL;

    Error *local_err = NULL, *end_err = NULL;

    QDict *pdict;

    pdict = qdict_clone_shallow(qdict);

    visit_start_struct(v, NULL, NULL, 0, &local_err);

    if (local_err) {

        goto out;

    }

    qdict_del(pdict, "qom-type");

    visit_type_str(v, "qom-type", &type, &local_err);

    if (local_err) {

        goto out_visit;

    }

    qdict_del(pdict, "id");

    visit_type_str(v, "id", &id, &local_err);

    if (local_err) {

        goto out_visit;

    }

    obj = user_creatable_add_type(type, id, pdict, v, &local_err);

    if (local_err) {

        goto out_visit;

    }

 out_visit:

    visit_end_struct(v, &end_err);

    if (end_err) {

        error_propagate(&local_err, end_err);

        if (obj) {

            user_creatable_del(id, NULL);

        }

        goto out;

    }

out:

    QDECREF(pdict);

    g_free(id);

    g_free(type);

    if (local_err) {

        error_propagate(errp, local_err);

        object_unref(obj);

        return NULL;

    }

    return obj;

}


int ff_h264_decode_seq_parameter_set(H264Context *h){

    MpegEncContext * const s = &h->s;

    int profile_idc, level_idc, constraint_set_flags = 0;

    unsigned int sps_id;

    int i, log2_max_frame_num_minus4;

    SPS *sps;

    profile_idc= get_bits(&s->gb, 8);

    constraint_set_flags |= get_bits1(&s->gb) << 0;   //constraint_set0_flag

    constraint_set_flags |= get_bits1(&s->gb) << 1;   //constraint_set1_flag

    constraint_set_flags |= get_bits1(&s->gb) << 2;   //constraint_set2_flag

    constraint_set_flags |= get_bits1(&s->gb) << 3;   //constraint_set3_flag

    get_bits(&s->gb, 4); // reserved

    level_idc= get_bits(&s->gb, 8);

    sps_id= get_ue_golomb_31(&s->gb);

    if(sps_id >= MAX_SPS_COUNT) {

        av_log(h->s.avctx, AV_LOG_ERROR, "sps_id (%d) out of range\n", sps_id);

        return -1;

    }

    sps= av_mallocz(sizeof(SPS));

    if(sps == NULL)

        return -1;

    sps->time_offset_length = 24;

    sps->profile_idc= profile_idc;

    sps->constraint_set_flags = constraint_set_flags;

    sps->level_idc= level_idc;

    memset(sps->scaling_matrix4, 16, sizeof(sps->scaling_matrix4));

    memset(sps->scaling_matrix8, 16, sizeof(sps->scaling_matrix8));

    sps->scaling_matrix_present = 0;

    if(sps->profile_idc >= 100){ //high profile

        sps->chroma_format_idc= get_ue_golomb_31(&s->gb);

        if(sps->chroma_format_idc > 3) {

            av_log(h->s.avctx, AV_LOG_ERROR, "chroma_format_idc (%u) out of range\n", sps->chroma_format_idc);

            goto fail;

        } else if(sps->chroma_format_idc == 3) {

            sps->residual_color_transform_flag = get_bits1(&s->gb);

        }

        sps->bit_depth_luma   = get_ue_golomb(&s->gb) + 8;

        sps->bit_depth_chroma = get_ue_golomb(&s->gb) + 8;

        sps->transform_bypass = get_bits1(&s->gb);

        decode_scaling_matrices(h, sps, NULL, 1, sps->scaling_matrix4, sps->scaling_matrix8);

    }else{

        sps->chroma_format_idc= 1;

        sps->bit_depth_luma   = 8;

        sps->bit_depth_chroma = 8;

    }

    log2_max_frame_num_minus4 = get_ue_golomb(&s->gb);

    if (log2_max_frame_num_minus4 < MIN_LOG2_MAX_FRAME_NUM - 4 ||

        log2_max_frame_num_minus4 > MAX_LOG2_MAX_FRAME_NUM - 4) {

        av_log(h->s.avctx, AV_LOG_ERROR,

               "log2_max_frame_num_minus4 out of range (0-12): %d\n",

               log2_max_frame_num_minus4);

        return AVERROR_INVALIDDATA;

    }

    sps->log2_max_frame_num = log2_max_frame_num_minus4 + 4;

    sps->poc_type= get_ue_golomb_31(&s->gb);

    if(sps->poc_type == 0){ //FIXME #define

        sps->log2_max_poc_lsb= get_ue_golomb(&s->gb) + 4;

    } else if(sps->poc_type == 1){//FIXME #define

        sps->delta_pic_order_always_zero_flag= get_bits1(&s->gb);

        sps->offset_for_non_ref_pic= get_se_golomb(&s->gb);

        sps->offset_for_top_to_bottom_field= get_se_golomb(&s->gb);

        sps->poc_cycle_length                = get_ue_golomb(&s->gb);

        if((unsigned)sps->poc_cycle_length >= FF_ARRAY_ELEMS(sps->offset_for_ref_frame)){

            av_log(h->s.avctx, AV_LOG_ERROR, "poc_cycle_length overflow %u\n", sps->poc_cycle_length);

            goto fail;

        }

        for(i=0; i<sps->poc_cycle_length; i++)

            sps->offset_for_ref_frame[i]= get_se_golomb(&s->gb);

    }else if(sps->poc_type != 2){

        av_log(h->s.avctx, AV_LOG_ERROR, "illegal POC type %d\n", sps->poc_type);

        goto fail;

    }

    sps->ref_frame_count= get_ue_golomb_31(&s->gb);

    if(sps->ref_frame_count > MAX_PICTURE_COUNT-2 || sps->ref_frame_count >= 32U){

        av_log(h->s.avctx, AV_LOG_ERROR, "too many reference frames\n");

        goto fail;

    }

    sps->gaps_in_frame_num_allowed_flag= get_bits1(&s->gb);

    sps->mb_width = get_ue_golomb(&s->gb) + 1;

    sps->mb_height= get_ue_golomb(&s->gb) + 1;

    if((unsigned)sps->mb_width >= INT_MAX/16 || (unsigned)sps->mb_height >= INT_MAX/16 ||

       av_image_check_size(16*sps->mb_width, 16*sps->mb_height, 0, h->s.avctx)){

        av_log(h->s.avctx, AV_LOG_ERROR, "mb_width/height overflow\n");

        goto fail;

    }

    sps->frame_mbs_only_flag= get_bits1(&s->gb);

    if(!sps->frame_mbs_only_flag)

        sps->mb_aff= get_bits1(&s->gb);

    else

        sps->mb_aff= 0;

    sps->direct_8x8_inference_flag= get_bits1(&s->gb);

    if(!sps->frame_mbs_only_flag && !sps->direct_8x8_inference_flag){

        av_log(h->s.avctx, AV_LOG_ERROR, "This stream was generated by a broken encoder, invalid 8x8 inference\n");

        goto fail;

    }

#ifndef ALLOW_INTERLACE

    if(sps->mb_aff)

        av_log(h->s.avctx, AV_LOG_ERROR, "MBAFF support not included; enable it at compile-time.\n");

#endif

    sps->crop= get_bits1(&s->gb);

    if(sps->crop){

        int crop_vertical_limit   = sps->chroma_format_idc  & 2 ? 16 : 8;

        int crop_horizontal_limit = sps->chroma_format_idc == 3 ? 16 : 8;

        sps->crop_left  = get_ue_golomb(&s->gb);

        sps->crop_right = get_ue_golomb(&s->gb);

        sps->crop_top   = get_ue_golomb(&s->gb);

        sps->crop_bottom= get_ue_golomb(&s->gb);

        if(sps->crop_left || sps->crop_top){

            av_log(h->s.avctx, AV_LOG_ERROR, "insane cropping not completely supported, this could look slightly wrong ...\n");

        }

        if(sps->crop_right >= crop_horizontal_limit || sps->crop_bottom >= crop_vertical_limit){

            av_log(h->s.avctx, AV_LOG_ERROR, "brainfart cropping not supported, this could look slightly wrong ...\n");

        }

    }else{

        sps->crop_left  =

        sps->crop_right =

        sps->crop_top   =

        sps->crop_bottom= 0;

    }

    sps->vui_parameters_present_flag= get_bits1(&s->gb);

    if( sps->vui_parameters_present_flag )

        if (decode_vui_parameters(h, sps) < 0)

            goto fail;

    if(!sps->sar.den)

        sps->sar.den= 1;

    if(s->avctx->debug&FF_DEBUG_PICT_INFO){

        static const char csp[4][5] = { "Gray", "420", "422", "444" };

        av_log(h->s.avctx, AV_LOG_DEBUG, "sps:%u profile:%d/%d poc:%d ref:%d %dx%d %s %s crop:%d/%d/%d/%d %s %s %d/%d\n",

               sps_id, sps->profile_idc, sps->level_idc,

               sps->poc_type,

               sps->ref_frame_count,

               sps->mb_width, sps->mb_height,

               sps->frame_mbs_only_flag ? "FRM" : (sps->mb_aff ? "MB-AFF" : "PIC-AFF"),

               sps->direct_8x8_inference_flag ? "8B8" : "",

               sps->crop_left, sps->crop_right,

               sps->crop_top, sps->crop_bottom,

               sps->vui_parameters_present_flag ? "VUI" : "",

               csp[sps->chroma_format_idc],

               sps->timing_info_present_flag ? sps->num_units_in_tick : 0,

               sps->timing_info_present_flag ? sps->time_scale : 0

               );

    }

    av_free(h->sps_buffers[sps_id]);

    h->sps_buffers[sps_id]= sps;

    h->sps = *sps;

    return 0;

fail:

    av_free(sps);

    return -1;

}


void do_compute_hflags (CPUPPCState *env)

{

    /* Compute current hflags */

    env->hflags = (msr_pr << MSR_PR) | (msr_le << MSR_LE) |

        (msr_fp << MSR_FP) | (msr_fe0 << MSR_FE0) | (msr_fe1 << MSR_FE1) |

        (msr_vr << MSR_VR) | (msr_ap << MSR_AP) | (msr_sa << MSR_SA) |

        (msr_se << MSR_SE) | (msr_be << MSR_BE);

#if defined (TARGET_PPC64)

    env->hflags |= (msr_sf << MSR_SF) | (msr_hv << MSR_HV);

#endif

}


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

{

    DeviceClass *dc = DEVICE_CLASS(klass);

    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);

    k->init = bonito_initfn;

    k->vendor_id = 0xdf53;

    k->device_id = 0x00d5;

    k->revision = 0x01;

    k->class_id = PCI_CLASS_BRIDGE_HOST;

    dc->desc = "Host bridge";

    dc->no_user = 1;

    dc->vmsd = &vmstate_bonito;

}


static void kvm_apic_realize(DeviceState *dev, Error **errp)

{

    APICCommonState *s = APIC_COMMON(dev);

    memory_region_init_io(&s->io_memory, NULL, &kvm_apic_io_ops, s, "kvm-apic-msi",

                          APIC_SPACE_SIZE);

    if (kvm_has_gsi_routing()) {

        msi_nonbroken = true;

    }

}


static uint64_t *l2_allocate(BlockDriverState *bs, int l1_index)

{

    BDRVQcowState *s = bs->opaque;

    int min_index;

    uint64_t old_l2_offset;

    uint64_t *l2_table, l2_offset;

    old_l2_offset = s->l1_table[l1_index];

    /* allocate a new l2 entry */

    l2_offset = qcow2_alloc_clusters(bs, s->l2_size * sizeof(uint64_t));

    if (l2_offset < 0) {

        return NULL;

    }

    /* update the L1 entry */

    s->l1_table[l1_index] = l2_offset | QCOW_OFLAG_COPIED;

    if (write_l1_entry(s, l1_index) < 0) {

        return NULL;

    }

    /* allocate a new entry in the l2 cache */

    min_index = l2_cache_new_entry(bs);

    l2_table = s->l2_cache + (min_index << s->l2_bits);

    if (old_l2_offset == 0) {

        /* if there was no old l2 table, clear the new table */

        memset(l2_table, 0, s->l2_size * sizeof(uint64_t));

    } else {

        /* if there was an old l2 table, read it from the disk */

        if (bdrv_pread(s->hd, old_l2_offset,

                       l2_table, s->l2_size * sizeof(uint64_t)) !=

            s->l2_size * sizeof(uint64_t))

            return NULL;

    }

    /* write the l2 table to the file */

    if (bdrv_pwrite(s->hd, l2_offset,

                    l2_table, s->l2_size * sizeof(uint64_t)) !=

        s->l2_size * sizeof(uint64_t))

        return NULL;

    /* update the l2 cache entry */

    s->l2_cache_offsets[min_index] = l2_offset;

    s->l2_cache_counts[min_index] = 1;

    return l2_table;

}


static inline int op(uint8_t **dst, const uint8_t *dst_end,

                     const uint8_t **buf, const uint8_t *buf_end,

                     int pixel, int count,

                     int *x, int width, int linesize)

{

    int remaining = width - *x;

    while(count > 0) {

        int striplen = FFMIN(count, remaining);

        if (buf) {

            striplen = FFMIN(striplen, buf_end - *buf);

            if (*buf >= buf_end)

                goto exhausted;

            memcpy(*dst, *buf, striplen);

            *buf += striplen;

        } else if (pixel >= 0)

            memset(*dst, pixel, striplen);

        *dst      += striplen;

        remaining -= striplen;

        count     -= striplen;

        if (remaining <= 0) {

            *dst      += linesize - width;

            remaining  = width;

        }

        if (linesize > 0) {

            if (*dst >= dst_end) goto exhausted;

        } else {

            if (*dst <= dst_end) goto exhausted;

        }

    }

    *x = width - remaining;

    return 0;

exhausted:

    *x = width - remaining;

    return 1;

}


static void ra144_encode_subblock(RA144Context *ractx,

                                  const int16_t *sblock_data,

                                  const int16_t *lpc_coefs, unsigned int rms,

                                  PutBitContext *pb)

{

    float data[BLOCKSIZE] = { 0 }, work[LPC_ORDER + BLOCKSIZE];

    float coefs[LPC_ORDER];

    float zero[BLOCKSIZE], cba[BLOCKSIZE], cb1[BLOCKSIZE], cb2[BLOCKSIZE];

    int16_t cba_vect[BLOCKSIZE];

    int cba_idx, cb1_idx, cb2_idx, gain;

    int i, n;

    unsigned m[3];

    float g[3];

    float error, best_error;

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

        work[i] = ractx->curr_sblock[BLOCKSIZE + i];

        coefs[i] = lpc_coefs[i] * (1/4096.0);

    }

    /**

     * Calculate the zero-input response of the LPC filter and subtract it from

     * input data.

     */

    ff_celp_lp_synthesis_filterf(work + LPC_ORDER, coefs, data, BLOCKSIZE,

                                 LPC_ORDER);

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

        zero[i] = work[LPC_ORDER + i];

        data[i] = sblock_data[i] - zero[i];

    }

    /**

     * Codebook search is performed without taking into account the contribution

     * of the previous subblock, since it has been just subtracted from input

     * data.

     */

    memset(work, 0, LPC_ORDER * sizeof(*work));

    cba_idx = adaptive_cb_search(ractx->adapt_cb, work + LPC_ORDER, coefs,

                                 data);

    if (cba_idx) {

        /**

         * The filtered vector from the adaptive codebook can be retrieved from

         * work, see implementation of adaptive_cb_search().

         */

        memcpy(cba, work + LPC_ORDER, sizeof(cba));

        ff_copy_and_dup(cba_vect, ractx->adapt_cb, cba_idx + BLOCKSIZE / 2 - 1);

        m[0] = (ff_irms(cba_vect) * rms) >> 12;

    }

    fixed_cb_search(work + LPC_ORDER, coefs, data, cba_idx, &cb1_idx, &cb2_idx);

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

        cb1[i] = ff_cb1_vects[cb1_idx][i];

        cb2[i] = ff_cb2_vects[cb2_idx][i];

    }

    ff_celp_lp_synthesis_filterf(work + LPC_ORDER, coefs, cb1, BLOCKSIZE,

                                 LPC_ORDER);

    memcpy(cb1, work + LPC_ORDER, sizeof(cb1));

    m[1] = (ff_cb1_base[cb1_idx] * rms) >> 8;

    ff_celp_lp_synthesis_filterf(work + LPC_ORDER, coefs, cb2, BLOCKSIZE,

                                 LPC_ORDER);

    memcpy(cb2, work + LPC_ORDER, sizeof(cb2));

    m[2] = (ff_cb2_base[cb2_idx] * rms) >> 8;

    best_error = FLT_MAX;

    gain = 0;

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

        g[1] = ((ff_gain_val_tab[n][1] * m[1]) >> ff_gain_exp_tab[n]) *

               (1/4096.0);

        g[2] = ((ff_gain_val_tab[n][2] * m[2]) >> ff_gain_exp_tab[n]) *

               (1/4096.0);

        error = 0;

        if (cba_idx) {

            g[0] = ((ff_gain_val_tab[n][0] * m[0]) >> ff_gain_exp_tab[n]) *

                   (1/4096.0);

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

                data[i] = zero[i] + g[0] * cba[i] + g[1] * cb1[i] +

                          g[2] * cb2[i];

                error += (data[i] - sblock_data[i]) *

                         (data[i] - sblock_data[i]);

            }

        } else {

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

                data[i] = zero[i] + g[1] * cb1[i] + g[2] * cb2[i];

                error += (data[i] - sblock_data[i]) *

                         (data[i] - sblock_data[i]);

            }

        }

        if (error < best_error) {

            best_error = error;

            gain = n;

        }

    }

    put_bits(pb, 7, cba_idx);

    put_bits(pb, 8, gain);

    put_bits(pb, 7, cb1_idx);

    put_bits(pb, 7, cb2_idx);

    ff_subblock_synthesis(ractx, lpc_coefs, cba_idx, cb1_idx, cb2_idx, rms,

                          gain);

}


build_qp_table(PPS *pps, int index)

{

    int i;

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

        pps->chroma_qp_table[i & 0xff] = chroma_qp[av_clip(i + index, 0, 51)];

    pps->chroma_qp_index_offset = index;

}


static target_ulong h_bulk_remove(PowerPCCPU *cpu, sPAPRMachineState *spapr,

                                  target_ulong opcode, target_ulong *args)

{

    CPUPPCState *env = &cpu->env;

    int i;

    target_ulong rc = H_SUCCESS;

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

        target_ulong *tsh = &args[i*2];

        target_ulong tsl = args[i*2 + 1];

        target_ulong v, r, ret;

        if ((*tsh & H_BULK_REMOVE_TYPE) == H_BULK_REMOVE_END) {

            break;

        } else if ((*tsh & H_BULK_REMOVE_TYPE) != H_BULK_REMOVE_REQUEST) {

            return H_PARAMETER;

        }

        *tsh &= H_BULK_REMOVE_PTEX | H_BULK_REMOVE_FLAGS;

        *tsh |= H_BULK_REMOVE_RESPONSE;

        if ((*tsh & H_BULK_REMOVE_ANDCOND) && (*tsh & H_BULK_REMOVE_AVPN)) {

            *tsh |= H_BULK_REMOVE_PARM;

            return H_PARAMETER;

        }

        ret = remove_hpte(cpu, *tsh & H_BULK_REMOVE_PTEX, tsl,

                          (*tsh & H_BULK_REMOVE_FLAGS) >> 26,

                          &v, &r);

        *tsh |= ret << 60;

        switch (ret) {

        case REMOVE_SUCCESS:

            *tsh |= (r & (HPTE64_R_C | HPTE64_R_R)) << 43;

            break;

        case REMOVE_PARM:

            rc = H_PARAMETER;

            goto exit;

        case REMOVE_HW:

            rc = H_HARDWARE;

            goto exit;

        }

    }

 exit:

    check_tlb_flush(env);

    return rc;

}


static void cpu_notify_map_clients(void)

{

    MapClient *client;

    while (!LIST_EMPTY(&map_client_list)) {

        client = LIST_FIRST(&map_client_list);

        client->callback(client->opaque);

        LIST_REMOVE(client, link);

    }

}


static int asf_read_stream_properties(AVFormatContext *s, int64_t size)

{

    ASFContext *asf = s->priv_data;

    AVIOContext *pb = s->pb;

    AVStream *st;

    ASFStream *asf_st;

    ff_asf_guid g;

    enum AVMediaType type;

    int type_specific_size, sizeX;

    unsigned int tag1;

    int64_t pos1, pos2, start_time;

    int test_for_ext_stream_audio, is_dvr_ms_audio=0;

    if (s->nb_streams == ASF_MAX_STREAMS) {

        av_log(s, AV_LOG_ERROR, "too many streams\n");

        return AVERROR(EINVAL);

    }

    pos1 = avio_tell(pb);

    st = avformat_new_stream(s, NULL);

    if (!st)

        return AVERROR(ENOMEM);

    avpriv_set_pts_info(st, 32, 1, 1000); /* 32 bit pts in ms */

    asf_st = av_mallocz(sizeof(ASFStream));

    if (!asf_st)

        return AVERROR(ENOMEM);

    st->priv_data = asf_st;

    start_time = asf->hdr.preroll;

    asf_st->stream_language_index = 128; // invalid stream index means no language info

    if(!(asf->hdr.flags & 0x01)) { // if we aren't streaming...

        int64_t fsize = avio_size(pb);

        if (fsize <= 0 || (int64_t)asf->hdr.file_size <= 0 || FFABS(fsize - (int64_t)asf->hdr.file_size) < 10000)

            st->duration = asf->hdr.play_time /

                (10000000 / 1000) - start_time;

    }

    ff_get_guid(pb, &g);

    test_for_ext_stream_audio = 0;

    if (!ff_guidcmp(&g, &ff_asf_audio_stream)) {

        type = AVMEDIA_TYPE_AUDIO;

    } else if (!ff_guidcmp(&g, &ff_asf_video_stream)) {

        type = AVMEDIA_TYPE_VIDEO;

    } else if (!ff_guidcmp(&g, &ff_asf_jfif_media)) {

        type = AVMEDIA_TYPE_VIDEO;

        st->codec->codec_id = AV_CODEC_ID_MJPEG;

    } else if (!ff_guidcmp(&g, &ff_asf_command_stream)) {

        type = AVMEDIA_TYPE_DATA;

    } else if (!ff_guidcmp(&g, &ff_asf_ext_stream_embed_stream_header)) {

        test_for_ext_stream_audio = 1;

        type = AVMEDIA_TYPE_UNKNOWN;

    } else {

        return -1;

    }

    ff_get_guid(pb, &g);

    avio_skip(pb, 8); /* total_size */

    type_specific_size = avio_rl32(pb);

    avio_rl32(pb);

    st->id = avio_rl16(pb) & 0x7f; /* stream id */

    // mapping of asf ID to AV stream ID;

    asf->asfid2avid[st->id] = s->nb_streams - 1;

    avio_rl32(pb);

    if (test_for_ext_stream_audio) {

        ff_get_guid(pb, &g);

        if (!ff_guidcmp(&g, &ff_asf_ext_stream_audio_stream)) {

            type = AVMEDIA_TYPE_AUDIO;

            is_dvr_ms_audio=1;

            ff_get_guid(pb, &g);

            avio_rl32(pb);

            avio_rl32(pb);

            avio_rl32(pb);

            ff_get_guid(pb, &g);

            avio_rl32(pb);

        }

    }

    st->codec->codec_type = type;

    if (type == AVMEDIA_TYPE_AUDIO) {

        int ret = ff_get_wav_header(pb, st->codec, type_specific_size);

        if (ret < 0)

            return ret;

        if (is_dvr_ms_audio) {

            // codec_id and codec_tag are unreliable in dvr_ms

            // files. Set them later by probing stream.

            st->request_probe= 1;

            st->codec->codec_tag = 0;

        }

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

            st->need_parsing = AVSTREAM_PARSE_NONE;

        } else {

            st->need_parsing = AVSTREAM_PARSE_FULL;

        }

        /* We have to init the frame size at some point .... */

        pos2 = avio_tell(pb);

        if (size >= (pos2 + 8 - pos1 + 24)) {

            asf_st->ds_span = avio_r8(pb);

            asf_st->ds_packet_size = avio_rl16(pb);

            asf_st->ds_chunk_size = avio_rl16(pb);

            avio_rl16(pb); //ds_data_size

            avio_r8(pb);   //ds_silence_data

        }

        if (asf_st->ds_span > 1) {

            if (!asf_st->ds_chunk_size

                    || (asf_st->ds_packet_size/asf_st->ds_chunk_size <= 1)

                    || asf_st->ds_packet_size % asf_st->ds_chunk_size)

                asf_st->ds_span = 0; // disable descrambling

        }

    } else if (type == AVMEDIA_TYPE_VIDEO &&

            size - (avio_tell(pb) - pos1 + 24) >= 51) {

        avio_rl32(pb);

        avio_rl32(pb);

        avio_r8(pb);

        avio_rl16(pb);        /* size */

        sizeX= avio_rl32(pb); /* size */

        st->codec->width = avio_rl32(pb);

        st->codec->height = avio_rl32(pb);

        /* not available for asf */

        avio_rl16(pb); /* panes */

        st->codec->bits_per_coded_sample = avio_rl16(pb); /* depth */

        tag1 = avio_rl32(pb);

        avio_skip(pb, 20);

        if (sizeX > 40) {

            st->codec->extradata_size = sizeX - 40;

            st->codec->extradata = av_mallocz(st->codec->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE);

            avio_read(pb, st->codec->extradata, st->codec->extradata_size);

        }

        /* Extract palette from extradata if bpp <= 8 */

        /* This code assumes that extradata contains only palette */

        /* This is true for all paletted codecs implemented in libavcodec */

        if (st->codec->extradata_size && (st->codec->bits_per_coded_sample <= 8)) {

#if HAVE_BIGENDIAN

            int i;

            for (i = 0; i < FFMIN(st->codec->extradata_size, AVPALETTE_SIZE)/4; i++)

                asf_st->palette[i] = av_bswap32(((uint32_t*)st->codec->extradata)[i]);

#else

            memcpy(asf_st->palette, st->codec->extradata,

                   FFMIN(st->codec->extradata_size, AVPALETTE_SIZE));

#endif

            asf_st->palette_changed = 1;

        }

        st->codec->codec_tag = tag1;

        st->codec->codec_id = ff_codec_get_id(ff_codec_bmp_tags, tag1);

        if(tag1 == MKTAG('D', 'V', 'R', ' ')){

            st->need_parsing = AVSTREAM_PARSE_FULL;

            // issue658 containse wrong w/h and MS even puts a fake seq header with wrong w/h in extradata while a correct one is in te stream. maximum lameness

            st->codec->width  =

                st->codec->height = 0;

            av_freep(&st->codec->extradata);

            st->codec->extradata_size=0;

        }

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

            st->need_parsing = AVSTREAM_PARSE_FULL_ONCE;

    }

    pos2 = avio_tell(pb);

    avio_skip(pb, size - (pos2 - pos1 + 24));

    return 0;

}


tb_page_addr_t get_page_addr_code(CPUArchState *env1, target_ulong addr)

{

    int mmu_idx, page_index, pd;

    void *p;

    MemoryRegion *mr;

    page_index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);

    mmu_idx = cpu_mmu_index(env1);

    if (unlikely(env1->tlb_table[mmu_idx][page_index].addr_code !=

                 (addr & TARGET_PAGE_MASK))) {

#ifdef CONFIG_TCG_PASS_AREG0

        cpu_ldub_code(env1, addr);

#else

        ldub_code(addr);

#endif

    }

    pd = env1->iotlb[mmu_idx][page_index] & ~TARGET_PAGE_MASK;

    mr = iotlb_to_region(pd);

    if (mr != &io_mem_ram && mr != &io_mem_rom

        && mr != &io_mem_notdirty && !mr->rom_device) {

#if defined(TARGET_ALPHA) || defined(TARGET_MIPS) || defined(TARGET_SPARC)

        cpu_unassigned_access(env1, addr, 0, 1, 0, 4);

#else

        cpu_abort(env1, "Trying to execute code outside RAM or ROM at 0x" TARGET_FMT_lx "\n", addr);

#endif

    }

    p = (void *)((uintptr_t)addr + env1->tlb_table[mmu_idx][page_index].addend);

    return qemu_ram_addr_from_host_nofail(p);

}


void cpu_ppc_store_decr (CPUPPCState *env, uint32_t value)

{

    PowerPCCPU *cpu = ppc_env_get_cpu(env);

    _cpu_ppc_store_decr(cpu, cpu_ppc_load_decr(env), value, 0);

}


static void test_submit_co(void)

{

    WorkerTestData data;

    Coroutine *co = qemu_coroutine_create(co_test_cb);

    qemu_coroutine_enter(co, &data);

    /* Back here once the worker has started.  */

    g_assert_cmpint(active, ==, 1);

    g_assert_cmpint(data.ret, ==, -EINPROGRESS);

    /* qemu_aio_flush will execute the rest of the coroutine.  */

    qemu_aio_flush();

    /* Back here after the coroutine has finished.  */

    g_assert_cmpint(active, ==, 0);

    g_assert_cmpint(data.ret, ==, 0);

}


static int decode_profile_tier_level(HEVCContext *s,  ProfileTierLevel *ptl)

{

    int i;

    HEVCLocalContext *lc = s->HEVClc;

    GetBitContext *gb = &lc->gb;

    ptl->profile_space = get_bits(gb, 2);

    ptl->tier_flag     = get_bits1(gb);

    ptl->profile_idc   = get_bits(gb, 5);

    if (ptl->profile_idc == 1)

        av_log(s->avctx, AV_LOG_DEBUG, "Main profile bitstream\n");

    else if (ptl->profile_idc == 2)

        av_log(s->avctx, AV_LOG_DEBUG, "Main10 profile bitstream\n");

    else

        av_log(s->avctx, AV_LOG_WARNING, "No profile indication! (%d)\n", ptl->profile_idc);

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

        ptl->profile_compatibility_flag[i] = get_bits1(gb);

    ptl->progressive_source_flag    = get_bits1(gb);

    ptl->interlaced_source_flag     = get_bits1(gb);

    ptl->non_packed_constraint_flag = get_bits1(gb);

    ptl->frame_only_constraint_flag = get_bits1(gb);

    if (get_bits(gb, 16) != 0) // XXX_reserved_zero_44bits[0..15]

        return -1;

    if (get_bits(gb, 16) != 0) // XXX_reserved_zero_44bits[16..31]

        return -1;

    if (get_bits(gb, 12) != 0) // XXX_reserved_zero_44bits[32..43]

        return -1;

    return 0;

}


int cpu_ppc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,

                              int is_user, int is_softmmu)

{

    mmu_ctx_t ctx;

    int exception = 0, error_code = 0;

    int access_type;

    int ret = 0;

    if (rw == 2) {

        /* code access */

        rw = 0;

        access_type = ACCESS_CODE;

    } else {

        /* data access */

        /* XXX: put correct access by using cpu_restore_state()

           correctly */

        access_type = ACCESS_INT;

        //        access_type = env->access_type;

    }

    ret = get_physical_address(env, &ctx, address, rw, access_type, 1);

    if (ret == 0) {

        ret = tlb_set_page(env, address & TARGET_PAGE_MASK,

                           ctx.raddr & TARGET_PAGE_MASK, ctx.prot,

                           is_user, is_softmmu);

    } else if (ret < 0) {

#if defined (DEBUG_MMU)

        if (loglevel != 0)

            cpu_dump_state(env, logfile, fprintf, 0);

#endif

        if (access_type == ACCESS_CODE) {

            exception = EXCP_ISI;

            switch (ret) {

            case -1:

                /* No matches in page tables or TLB */

                switch (env->mmu_model) {

                case POWERPC_MMU_SOFT_6xx:

                    exception = EXCP_I_TLBMISS;

                    env->spr[SPR_IMISS] = address;

                    env->spr[SPR_ICMP] = 0x80000000 | ctx.ptem;

                    error_code = 1 << 18;

                    goto tlb_miss;

                case POWERPC_MMU_SOFT_4xx:

                case POWERPC_MMU_SOFT_4xx_Z:

                    exception = EXCP_40x_ITLBMISS;

                    error_code = 0;

                    env->spr[SPR_40x_DEAR] = address;

                    env->spr[SPR_40x_ESR] = 0x00000000;

                    break;

                case POWERPC_MMU_32B:

                    error_code = 0x40000000;

                    break;

#if defined(TARGET_PPC64)

                case POWERPC_MMU_64B:

                    /* XXX: TODO */

                    cpu_abort(env, "MMU model not implemented\n");

                    return -1;

                case POWERPC_MMU_64BRIDGE:

                    /* XXX: TODO */

                    cpu_abort(env, "MMU model not implemented\n");

                    return -1;

#endif

                case POWERPC_MMU_601:

                    /* XXX: TODO */

                    cpu_abort(env, "MMU model not implemented\n");

                    return -1;

                case POWERPC_MMU_BOOKE:

                    /* XXX: TODO */

                    cpu_abort(env, "MMU model not implemented\n");

                    return -1;

                case POWERPC_MMU_BOOKE_FSL:

                    /* XXX: TODO */

                    cpu_abort(env, "MMU model not implemented\n");

                    return -1;

                case POWERPC_MMU_REAL_4xx:

                    cpu_abort(env, "PowerPC 401 should never raise any MMU "

                              "exceptions\n");

                    return -1;

                default:

                    cpu_abort(env, "Unknown or invalid MMU model\n");

                    return -1;

                }

                break;

            case -2:

                /* Access rights violation */

                error_code = 0x08000000;

                break;

            case -3:

                /* No execute protection violation */

                error_code = 0x10000000;

                break;

            case -4:

                /* Direct store exception */

                /* No code fetch is allowed in direct-store areas */

                error_code = 0x10000000;

                break;

            case -5:

                /* No match in segment table */

                exception = EXCP_ISEG;

                error_code = 0;

                break;

            }

        } else {

            exception = EXCP_DSI;

            switch (ret) {

            case -1:

                /* No matches in page tables or TLB */

                switch (env->mmu_model) {

                case POWERPC_MMU_SOFT_6xx:

                    if (rw == 1) {

                        exception = EXCP_DS_TLBMISS;

                        error_code = 1 << 16;

                    } else {

                        exception = EXCP_DL_TLBMISS;

                        error_code = 0;

                    }

                    env->spr[SPR_DMISS] = address;

                    env->spr[SPR_DCMP] = 0x80000000 | ctx.ptem;

                tlb_miss:

                    error_code |= ctx.key << 19;

                    env->spr[SPR_HASH1] = ctx.pg_addr[0];

                    env->spr[SPR_HASH2] = ctx.pg_addr[1];

                    /* Do not alter DAR nor DSISR */

                    goto out;

                case POWERPC_MMU_SOFT_4xx:

                case POWERPC_MMU_SOFT_4xx_Z:

                    exception = EXCP_40x_DTLBMISS;

                    error_code = 0;

                    env->spr[SPR_40x_DEAR] = address;

                    if (rw)

                        env->spr[SPR_40x_ESR] = 0x00800000;

                    else

                        env->spr[SPR_40x_ESR] = 0x00000000;

                    break;

                case POWERPC_MMU_32B:

                    error_code = 0x40000000;

                    break;

#if defined(TARGET_PPC64)

                case POWERPC_MMU_64B:

                    /* XXX: TODO */

                    cpu_abort(env, "MMU model not implemented\n");

                    return -1;

                case POWERPC_MMU_64BRIDGE:

                    /* XXX: TODO */

                    cpu_abort(env, "MMU model not implemented\n");

                    return -1;

#endif

                case POWERPC_MMU_601:

                    /* XXX: TODO */

                    cpu_abort(env, "MMU model not implemented\n");

                    return -1;

                case POWERPC_MMU_BOOKE:

                    /* XXX: TODO */

                    cpu_abort(env, "MMU model not implemented\n");

                    return -1;

                case POWERPC_MMU_BOOKE_FSL:

                    /* XXX: TODO */

                    cpu_abort(env, "MMU model not implemented\n");

                    return -1;

                case POWERPC_MMU_REAL_4xx:

                    cpu_abort(env, "PowerPC 401 should never raise any MMU "

                              "exceptions\n");

                    return -1;

                default:

                    cpu_abort(env, "Unknown or invalid MMU model\n");

                    return -1;

                }

                break;

            case -2:

                /* Access rights violation */

                error_code = 0x08000000;

                break;

            case -4:

                /* Direct store exception */

                switch (access_type) {

                case ACCESS_FLOAT:

                    /* Floating point load/store */

                    exception = EXCP_ALIGN;

                    error_code = EXCP_ALIGN_FP;

                    break;

                case ACCESS_RES:

                    /* lwarx, ldarx or srwcx. */

                    error_code = 0x04000000;

                    break;

                case ACCESS_EXT:

                    /* eciwx or ecowx */

                    error_code = 0x04100000;

                    break;

                default:

                    printf("DSI: invalid exception (%d)\n", ret);

                    exception = EXCP_PROGRAM;

                    error_code = EXCP_INVAL | EXCP_INVAL_INVAL;

                    break;

                }

                break;

            case -5:

                /* No match in segment table */

                exception = EXCP_DSEG;

                error_code = 0;

                break;

            }

            if (exception == EXCP_DSI && rw == 1)

                error_code |= 0x02000000;

            /* Store fault address */

            env->spr[SPR_DAR] = address;

            env->spr[SPR_DSISR] = error_code;

        }

    out:

#if 0

        printf("%s: set exception to %d %02x\n",

               __func__, exception, error_code);

#endif

        env->exception_index = exception;

        env->error_code = error_code;

        ret = 1;

    }

    return ret;

}


static int qemu_signal_init(void)

{

    int sigfd;

    sigset_t set;

    /*

     * SIG_IPI must be blocked in the main thread and must not be caught

     * by sigwait() in the signal thread. Otherwise, the cpu thread will

     * not catch it reliably.

     */

    sigemptyset(&set);

    sigaddset(&set, SIG_IPI);

    sigaddset(&set, SIGIO);

    sigaddset(&set, SIGALRM);

    sigaddset(&set, SIGBUS);

    sigaddset(&set, SIGINT);

    sigaddset(&set, SIGHUP);

    sigaddset(&set, SIGTERM);

    pthread_sigmask(SIG_BLOCK, &set, NULL);

    sigdelset(&set, SIG_IPI);

    sigfd = qemu_signalfd(&set);

    if (sigfd == -1) {

        fprintf(stderr, "failed to create signalfd\n");

        return -errno;

    }

    fcntl_setfl(sigfd, O_NONBLOCK);

    qemu_set_fd_handler2(sigfd, NULL, sigfd_handler, NULL,

                         (void *)(intptr_t)sigfd);

    return 0;

}


struct kvm_sw_breakpoint *kvm_find_sw_breakpoint(CPUState *env,

                                                 target_ulong pc)

{

    struct kvm_sw_breakpoint *bp;

    TAILQ_FOREACH(bp, &env->kvm_state->kvm_sw_breakpoints, entry) {

        if (bp->pc == pc)

            return bp;

    }

    return NULL;

}


static inline void gen_intermediate_code_internal(TranslationBlock * tb,

                                                  int spc, CPUSPARCState *env)

{

    target_ulong pc_start, last_pc;

    uint16_t *gen_opc_end;

    DisasContext dc1, *dc = &dc1;

    CPUBreakpoint *bp;

    int j, lj = -1;

    int num_insns;

    int max_insns;

    memset(dc, 0, sizeof(DisasContext));

    dc->tb = tb;

    pc_start = tb->pc;

    dc->pc = pc_start;

    last_pc = dc->pc;

    dc->npc = (target_ulong) tb->cs_base;

    dc->cc_op = CC_OP_DYNAMIC;

    dc->mem_idx = cpu_mmu_index(env);

    dc->def = env->def;

    if ((dc->def->features & CPU_FEATURE_FLOAT))

        dc->fpu_enabled = cpu_fpu_enabled(env);

    else

        dc->fpu_enabled = 0;

#ifdef TARGET_SPARC64

    dc->address_mask_32bit = env->pstate & PS_AM;

#endif

    gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;

    cpu_tmp0 = tcg_temp_new();

    cpu_tmp32 = tcg_temp_new_i32();

    cpu_tmp64 = tcg_temp_new_i64();

    cpu_dst = tcg_temp_local_new();

    // loads and stores

    cpu_val = tcg_temp_local_new();

    cpu_addr = tcg_temp_local_new();

    num_insns = 0;

    max_insns = tb->cflags & CF_COUNT_MASK;

    if (max_insns == 0)

        max_insns = CF_COUNT_MASK;

    gen_icount_start();

    do {

        if (unlikely(!TAILQ_EMPTY(&env->breakpoints))) {

            TAILQ_FOREACH(bp, &env->breakpoints, entry) {

                if (bp->pc == dc->pc) {

                    if (dc->pc != pc_start)

                        save_state(dc, cpu_cond);

                    gen_helper_debug();

                    tcg_gen_exit_tb(0);

                    dc->is_br = 1;

                    goto exit_gen_loop;

                }

            }

        }

        if (spc) {

            qemu_log("Search PC...\n");

            j = gen_opc_ptr - gen_opc_buf;

            if (lj < j) {

                lj++;

                while (lj < j)

                    gen_opc_instr_start[lj++] = 0;

                gen_opc_pc[lj] = dc->pc;

                gen_opc_npc[lj] = dc->npc;

                gen_opc_instr_start[lj] = 1;

                gen_opc_icount[lj] = num_insns;

            }

        }

        if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))

            gen_io_start();

        last_pc = dc->pc;

        disas_sparc_insn(dc);

        num_insns++;

        if (dc->is_br)

            break;

        /* if the next PC is different, we abort now */

        if (dc->pc != (last_pc + 4))

            break;

        /* if we reach a page boundary, we stop generation so that the

           PC of a TT_TFAULT exception is always in the right page */

        if ((dc->pc & (TARGET_PAGE_SIZE - 1)) == 0)

            break;

        /* if single step mode, we generate only one instruction and

           generate an exception */

        if (env->singlestep_enabled || singlestep) {

            tcg_gen_movi_tl(cpu_pc, dc->pc);

            tcg_gen_exit_tb(0);

            break;

        }

    } while ((gen_opc_ptr < gen_opc_end) &&

             (dc->pc - pc_start) < (TARGET_PAGE_SIZE - 32) &&

             num_insns < max_insns);

 exit_gen_loop:

    tcg_temp_free(cpu_addr);

    tcg_temp_free(cpu_val);

    tcg_temp_free(cpu_dst);

    tcg_temp_free_i64(cpu_tmp64);

    tcg_temp_free_i32(cpu_tmp32);

    tcg_temp_free(cpu_tmp0);

    if (tb->cflags & CF_LAST_IO)

        gen_io_end();

    if (!dc->is_br) {

        if (dc->pc != DYNAMIC_PC &&

            (dc->npc != DYNAMIC_PC && dc->npc != JUMP_PC)) {

            /* static PC and NPC: we can use direct chaining */

            gen_goto_tb(dc, 0, dc->pc, dc->npc);

        } else {

            if (dc->pc != DYNAMIC_PC)

                tcg_gen_movi_tl(cpu_pc, dc->pc);

            save_npc(dc, cpu_cond);

            tcg_gen_exit_tb(0);

        }

    }

    gen_icount_end(tb, num_insns);

    *gen_opc_ptr = INDEX_op_end;

    if (spc) {

        j = gen_opc_ptr - gen_opc_buf;

        lj++;

        while (lj <= j)

            gen_opc_instr_start[lj++] = 0;

#if 0

        log_page_dump();

#endif

        gen_opc_jump_pc[0] = dc->jump_pc[0];

        gen_opc_jump_pc[1] = dc->jump_pc[1];

    } else {

        tb->size = last_pc + 4 - pc_start;

        tb->icount = num_insns;

    }

#ifdef DEBUG_DISAS

    if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {

        qemu_log("--------------\n");

        qemu_log("IN: %s\n", lookup_symbol(pc_start));

        log_target_disas(pc_start, last_pc + 4 - pc_start, 0);

        qemu_log("\n");

    }

#endif

}


static void test_visitor_in_native_list_uint64(TestInputVisitorData *data,

                                               const void *unused)

{

    test_native_list_integer_helper(data, unused,

                                    USER_DEF_NATIVE_LIST_UNION_KIND_U64);

}


static int vtd_page_walk_level(dma_addr_t addr, uint64_t start,

                               uint64_t end, vtd_page_walk_hook hook_fn,

                               void *private, uint32_t level,

                               bool read, bool write, bool notify_unmap)

{

    bool read_cur, write_cur, entry_valid;

    uint32_t offset;

    uint64_t slpte;

    uint64_t subpage_size, subpage_mask;

    IOMMUTLBEntry entry;

    uint64_t iova = start;

    uint64_t iova_next;

    int ret = 0;

    trace_vtd_page_walk_level(addr, level, start, end);

    subpage_size = 1ULL << vtd_slpt_level_shift(level);

    subpage_mask = vtd_slpt_level_page_mask(level);

    while (iova < end) {

        iova_next = (iova & subpage_mask) + subpage_size;

        offset = vtd_iova_level_offset(iova, level);

        slpte = vtd_get_slpte(addr, offset);

        if (slpte == (uint64_t)-1) {

            trace_vtd_page_walk_skip_read(iova, iova_next);

            goto next;

        }

        if (vtd_slpte_nonzero_rsvd(slpte, level)) {

            trace_vtd_page_walk_skip_reserve(iova, iova_next);

            goto next;

        }

        /* Permissions are stacked with parents' */

        read_cur = read && (slpte & VTD_SL_R);

        write_cur = write && (slpte & VTD_SL_W);

        /*

         * As long as we have either read/write permission, this is a

         * valid entry. The rule works for both page entries and page

         * table entries.

         */

        entry_valid = read_cur | write_cur;

        if (vtd_is_last_slpte(slpte, level)) {

            entry.target_as = &address_space_memory;

            entry.iova = iova & subpage_mask;

            /* NOTE: this is only meaningful if entry_valid == true */

            entry.translated_addr = vtd_get_slpte_addr(slpte);

            entry.addr_mask = ~subpage_mask;

            entry.perm = IOMMU_ACCESS_FLAG(read_cur, write_cur);

            if (!entry_valid && !notify_unmap) {

                trace_vtd_page_walk_skip_perm(iova, iova_next);

                goto next;

            }

            trace_vtd_page_walk_one(level, entry.iova, entry.translated_addr,

                                    entry.addr_mask, entry.perm);

            if (hook_fn) {

                ret = hook_fn(&entry, private);

                if (ret < 0) {

                    return ret;

                }

            }

        } else {

            if (!entry_valid) {

                trace_vtd_page_walk_skip_perm(iova, iova_next);

                goto next;

            }

            ret = vtd_page_walk_level(vtd_get_slpte_addr(slpte), iova,

                                      MIN(iova_next, end), hook_fn, private,

                                      level - 1, read_cur, write_cur,

                                      notify_unmap);

            if (ret < 0) {

                return ret;

            }

        }

next:

        iova = iova_next;

    }

    return 0;

}


static int kvm_virtio_pci_irqfd_use(VirtIOPCIProxy *proxy,

                                 unsigned int queue_no,

                                 unsigned int vector)

{

    VirtIOIRQFD *irqfd = &proxy->vector_irqfd[vector];

    VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);

    VirtQueue *vq = virtio_get_queue(vdev, queue_no);

    EventNotifier *n = virtio_queue_get_guest_notifier(vq);

    int ret;

    ret = kvm_irqchip_add_irqfd_notifier_gsi(kvm_state, n, NULL, irqfd->virq);

    return ret;

}


void net_tx_pkt_build_vheader(struct NetTxPkt *pkt, bool tso_enable,

    bool csum_enable, uint32_t gso_size)

{

    struct tcp_hdr l4hdr;

    assert(pkt);

    /* csum has to be enabled if tso is. */

    assert(csum_enable || !tso_enable);

    pkt->virt_hdr.gso_type = net_tx_pkt_get_gso_type(pkt, tso_enable);

    switch (pkt->virt_hdr.gso_type & ~VIRTIO_NET_HDR_GSO_ECN) {

    case VIRTIO_NET_HDR_GSO_NONE:

        pkt->virt_hdr.hdr_len = 0;

        pkt->virt_hdr.gso_size = 0;

        break;

    case VIRTIO_NET_HDR_GSO_UDP:

        pkt->virt_hdr.gso_size = IP_FRAG_ALIGN_SIZE(gso_size);

        pkt->virt_hdr.hdr_len = pkt->hdr_len + sizeof(struct udp_header);

        break;

    case VIRTIO_NET_HDR_GSO_TCPV4:

    case VIRTIO_NET_HDR_GSO_TCPV6:

        iov_to_buf(&pkt->vec[NET_TX_PKT_PL_START_FRAG], pkt->payload_frags,

                   0, &l4hdr, sizeof(l4hdr));

        pkt->virt_hdr.hdr_len = pkt->hdr_len + l4hdr.th_off * sizeof(uint32_t);

        pkt->virt_hdr.gso_size = IP_FRAG_ALIGN_SIZE(gso_size);

        break;

    default:

        g_assert_not_reached();

    }

    if (csum_enable) {

        switch (pkt->l4proto) {

        case IP_PROTO_TCP:

            pkt->virt_hdr.flags = VIRTIO_NET_HDR_F_NEEDS_CSUM;

            pkt->virt_hdr.csum_start = pkt->hdr_len;

            pkt->virt_hdr.csum_offset = offsetof(struct tcp_hdr, th_sum);

            break;

        case IP_PROTO_UDP:

            pkt->virt_hdr.flags = VIRTIO_NET_HDR_F_NEEDS_CSUM;

            pkt->virt_hdr.csum_start = pkt->hdr_len;

            pkt->virt_hdr.csum_offset = offsetof(struct udp_hdr, uh_sum);

            break;

        default:

            break;

        }

    }

}