static void iommu_mem_writew(void *opaque, target_phys_addr_t addr,

                             uint32_t val)

{

    IOMMUState *s = opaque;

    target_phys_addr_t saddr;

    saddr = (addr - s->addr) >> 2;

    DPRINTF("write reg[%d] = %x\n", (int)saddr, val);

    switch (saddr) {

    case IOMMU_CTRL:

        switch (val & IOMMU_CTRL_RNGE) {

        case IOMMU_RNGE_16MB:

            s->iostart = 0xffffffffff000000ULL;

            break;

        case IOMMU_RNGE_32MB:

            s->iostart = 0xfffffffffe000000ULL;

            break;

        case IOMMU_RNGE_64MB:

            s->iostart = 0xfffffffffc000000ULL;

            break;

        case IOMMU_RNGE_128MB:

            s->iostart = 0xfffffffff8000000ULL;

            break;

        case IOMMU_RNGE_256MB:

            s->iostart = 0xfffffffff0000000ULL;

            break;

        case IOMMU_RNGE_512MB:

            s->iostart = 0xffffffffe0000000ULL;

            break;

        case IOMMU_RNGE_1GB:

            s->iostart = 0xffffffffc0000000ULL;

            break;

        default:

        case IOMMU_RNGE_2GB:

            s->iostart = 0xffffffff80000000ULL;

            break;

        }

        DPRINTF("iostart = " TARGET_FMT_plx "\n", s->iostart);

        s->regs[saddr] = ((val & IOMMU_CTRL_MASK) | s->version);

        break;

    case IOMMU_BASE:

        s->regs[saddr] = val & IOMMU_BASE_MASK;

        break;

    case IOMMU_TLBFLUSH:

        DPRINTF("tlb flush %x\n", val);

        s->regs[saddr] = val & IOMMU_TLBFLUSH_MASK;

        break;

    case IOMMU_PGFLUSH:

        DPRINTF("page flush %x\n", val);

        s->regs[saddr] = val & IOMMU_PGFLUSH_MASK;

        break;

    case IOMMU_AFAR:

        s->regs[saddr] = val;

        qemu_irq_lower(s->irq);

        break;

    case IOMMU_AFSR:

        s->regs[saddr] = (val & IOMMU_AFSR_MASK) | IOMMU_AFSR_RESV;

        qemu_irq_lower(s->irq);

        break;

    case IOMMU_SBCFG0:

    case IOMMU_SBCFG1:

    case IOMMU_SBCFG2:

    case IOMMU_SBCFG3:

        s->regs[saddr] = val & IOMMU_SBCFG_MASK;

        break;

    case IOMMU_ARBEN:

        // XXX implement SBus probing: fault when reading unmapped

        // addresses, fault cause and address stored to MMU/IOMMU

        s->regs[saddr] = (val & IOMMU_ARBEN_MASK) | IOMMU_MID;

        break;

    default:

        s->regs[saddr] = val;

        break;

    }

}


static void pci_reset(EEPRO100State * s)

{

    uint32_t device = s->device;

    uint8_t *pci_conf = s->pci_dev->config;

    logout("%p\n", s);

    /* PCI Vendor ID */

    pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_INTEL);

    /* PCI Device ID */

    pci_config_set_device_id(pci_conf, PCI_DEVICE_ID_INTEL_82551IT);

    /* PCI Command */

    PCI_CONFIG_16(PCI_COMMAND, 0x0000);

    /* PCI Status */

    PCI_CONFIG_16(PCI_STATUS, 0x2800);

    /* PCI Revision ID */

    PCI_CONFIG_8(PCI_REVISION_ID, 0x08);

    /* PCI Class Code */

    PCI_CONFIG_8(0x09, 0x00);

    pci_config_set_class(pci_conf, PCI_CLASS_NETWORK_ETHERNET);

    /* PCI Cache Line Size */

    /* check cache line size!!! */

    //~ PCI_CONFIG_8(0x0c, 0x00);

    /* PCI Latency Timer */

    PCI_CONFIG_8(0x0d, 0x20);   // latency timer = 32 clocks

    /* PCI Header Type */

    /* BIST (built-in self test) */

#if defined(TARGET_I386)

// !!! workaround for buggy bios

//~ #define PCI_ADDRESS_SPACE_MEM_PREFETCH 0

#endif

#if 0

    /* PCI Base Address Registers */

    /* CSR Memory Mapped Base Address */

    PCI_CONFIG_32(PCI_BASE_ADDRESS_0,

                  PCI_ADDRESS_SPACE_MEM | PCI_ADDRESS_SPACE_MEM_PREFETCH);

    /* CSR I/O Mapped Base Address */

    PCI_CONFIG_32(PCI_BASE_ADDRESS_1, PCI_ADDRESS_SPACE_IO);

#if 0

    /* Flash Memory Mapped Base Address */

    PCI_CONFIG_32(PCI_BASE_ADDRESS_2, 0xfffe0000 | PCI_ADDRESS_SPACE_MEM);

#endif

#endif

    /* Expansion ROM Base Address (depends on boot disable!!!) */

    PCI_CONFIG_32(0x30, 0x00000000);

    /* Capability Pointer */

    PCI_CONFIG_8(0x34, 0xdc);

    /* Interrupt Pin */

    PCI_CONFIG_8(0x3d, 1);      // interrupt pin 0

    /* Minimum Grant */

    PCI_CONFIG_8(0x3e, 0x08);

    /* Maximum Latency */

    PCI_CONFIG_8(0x3f, 0x18);

    /* Power Management Capabilities / Next Item Pointer / Capability ID */

    PCI_CONFIG_32(0xdc, 0x7e210001);

    switch (device) {

    case i82551:

        //~ PCI_CONFIG_16(PCI_DEVICE_ID, 0x1209);

        PCI_CONFIG_8(PCI_REVISION_ID, 0x0f);

        break;

    case i82557B:

        PCI_CONFIG_16(PCI_DEVICE_ID, 0x1229);

        PCI_CONFIG_8(PCI_REVISION_ID, 0x02);

        break;

    case i82557C:

        PCI_CONFIG_16(PCI_DEVICE_ID, 0x1229);

        PCI_CONFIG_8(PCI_REVISION_ID, 0x03);

        break;

    case i82558B:

        PCI_CONFIG_16(PCI_DEVICE_ID, 0x1229);

        PCI_CONFIG_16(PCI_STATUS, 0x2810);

        PCI_CONFIG_8(PCI_REVISION_ID, 0x05);

        break;

    case i82559C:

        PCI_CONFIG_16(PCI_DEVICE_ID, 0x1229);

        PCI_CONFIG_16(PCI_STATUS, 0x2810);

        //~ PCI_CONFIG_8(PCI_REVISION_ID, 0x08);

        break;

    case i82559ER:

        //~ PCI_CONFIG_16(PCI_DEVICE_ID, 0x1209);

        PCI_CONFIG_16(PCI_STATUS, 0x2810);

        PCI_CONFIG_8(PCI_REVISION_ID, 0x09);

        break;

    //~ PCI_CONFIG_16(PCI_DEVICE_ID, 0x1029);

    //~ PCI_CONFIG_16(PCI_DEVICE_ID, 0x1030);       /* 82559 InBusiness 10/100 */

    default:

        logout("Device %X is undefined!\n", device);

    }

    if (device == i82557C || device == i82558B || device == i82559C) {

        logout("Get device id and revision from EEPROM!!!\n");

    }

}


int ff_mjpeg_find_marker(MJpegDecodeContext *s,

                         const uint8_t **buf_ptr, const uint8_t *buf_end,

                         const uint8_t **unescaped_buf_ptr,

                         int *unescaped_buf_size)

{

    int start_code;

    start_code = find_marker(buf_ptr, buf_end);

    av_fast_padded_malloc(&s->buffer, &s->buffer_size, buf_end - *buf_ptr);

    if (!s->buffer)

        return AVERROR(ENOMEM);

    /* unescape buffer of SOS, use special treatment for JPEG-LS */

    if (start_code == SOS && !s->ls) {

        const uint8_t *src = *buf_ptr;

        uint8_t *dst = s->buffer;

        while (src < buf_end) {

            uint8_t x = *(src++);

            *(dst++) = x;

            if (s->avctx->codec_id != AV_CODEC_ID_THP) {

                if (x == 0xff) {

                    while (src < buf_end && x == 0xff)

                        x = *(src++);

                    if (x >= 0xd0 && x <= 0xd7)

                        *(dst++) = x;

                    else if (x)

                        break;

                }

            }

        }

        *unescaped_buf_ptr  = s->buffer;

        *unescaped_buf_size = dst - s->buffer;

        memset(s->buffer + *unescaped_buf_size, 0,

               FF_INPUT_BUFFER_PADDING_SIZE);

        av_log(s->avctx, AV_LOG_DEBUG, "escaping removed %td bytes\n",

               (buf_end - *buf_ptr) - (dst - s->buffer));

    } else if (start_code == SOS && s->ls) {

        const uint8_t *src = *buf_ptr;

        uint8_t *dst  = s->buffer;

        int bit_count = 0;

        int t = 0, b = 0;

        PutBitContext pb;

        s->cur_scan++;

        /* find marker */

        while (src + t < buf_end) {

            uint8_t x = src[t++];

            if (x == 0xff) {

                while ((src + t < buf_end) && x == 0xff)

                    x = src[t++];

                if (x & 0x80) {

                    t -= 2;

                    break;

                }

            }

        }

        bit_count = t * 8;

        init_put_bits(&pb, dst, t);

        /* unescape bitstream */

        while (b < t) {

            uint8_t x = src[b++];

            put_bits(&pb, 8, x);

            if (x == 0xFF) {

                x = src[b++];

                put_bits(&pb, 7, x);

                bit_count--;

            }

        }

        flush_put_bits(&pb);

        *unescaped_buf_ptr  = dst;

        *unescaped_buf_size = (bit_count + 7) >> 3;

        memset(s->buffer + *unescaped_buf_size, 0,

               FF_INPUT_BUFFER_PADDING_SIZE);

    } else {

        *unescaped_buf_ptr  = *buf_ptr;

        *unescaped_buf_size = buf_end - *buf_ptr;

    }

    return start_code;

}


static int yuv4_write_header(AVFormatContext *s)

{

    int *first_pkt = s->priv_data;

    if (s->nb_streams != 1)

        return AVERROR(EIO);

    if (s->streams[0]->codecpar->codec_id != AV_CODEC_ID_WRAPPED_AVFRAME) {

        av_log(s, AV_LOG_ERROR, "ERROR: Codec not supported.\n");

        return AVERROR_INVALIDDATA;

    }

    switch (s->streams[0]->codecpar->format) {

    case AV_PIX_FMT_YUV411P:

        av_log(s, AV_LOG_WARNING, "Warning: generating rarely used 4:1:1 YUV "

               "stream, some mjpegtools might not work.\n");

        break;

    case AV_PIX_FMT_GRAY8:

    case AV_PIX_FMT_GRAY16:

    case AV_PIX_FMT_YUV420P:

    case AV_PIX_FMT_YUV422P:

    case AV_PIX_FMT_YUV444P:

        break;

    case AV_PIX_FMT_YUV420P9:

    case AV_PIX_FMT_YUV422P9:

    case AV_PIX_FMT_YUV444P9:

    case AV_PIX_FMT_YUV420P10:

    case AV_PIX_FMT_YUV422P10:

    case AV_PIX_FMT_YUV444P10:

    case AV_PIX_FMT_YUV420P12:

    case AV_PIX_FMT_YUV422P12:

    case AV_PIX_FMT_YUV444P12:

    case AV_PIX_FMT_YUV420P14:

    case AV_PIX_FMT_YUV422P14:

    case AV_PIX_FMT_YUV444P14:

    case AV_PIX_FMT_YUV420P16:

    case AV_PIX_FMT_YUV422P16:

    case AV_PIX_FMT_YUV444P16:

        if (s->strict_std_compliance >= FF_COMPLIANCE_NORMAL) {

            av_log(s, AV_LOG_ERROR, "'%s' is not an official yuv4mpegpipe pixel format. "

                   "Use '-strict -1' to encode to this pixel format.\n",

                   av_get_pix_fmt_name(s->streams[0]->codecpar->format));

            return AVERROR(EINVAL);

        }

        av_log(s, AV_LOG_WARNING, "Warning: generating non standard YUV stream. "

               "Mjpegtools will not work.\n");

        break;

    default:

        av_log(s, AV_LOG_ERROR, "ERROR: yuv4mpeg can only handle "

               "yuv444p, yuv422p, yuv420p, yuv411p and gray8 pixel formats. "

               "And using 'strict -1' also yuv444p9, yuv422p9, yuv420p9, "

               "yuv444p10, yuv422p10, yuv420p10, "

               "yuv444p12, yuv422p12, yuv420p12, "

               "yuv444p14, yuv422p14, yuv420p14, "

               "yuv444p16, yuv422p16, yuv420p16 "

               "and gray16 pixel formats. "

               "Use -pix_fmt to select one.\n");

        return AVERROR(EIO);

    }

    *first_pkt = 1;

    return 0;

}


static void gen_arith_imm (CPUState *env, DisasContext *ctx, uint32_t opc,

                           int rt, int rs, int16_t imm)

{

    target_ulong uimm;

    const char *opn = "imm arith";

    TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);

    if (rt == 0 && opc != OPC_ADDI && opc != OPC_DADDI) {

        /* If no destination, treat it as a NOP.

           For addi, we must generate the overflow exception when needed. */

        MIPS_DEBUG("NOP");

        goto out;

    }

    uimm = (uint16_t)imm;

    switch (opc) {

    case OPC_ADDI:

    case OPC_ADDIU:

#if defined(TARGET_MIPS64)

    case OPC_DADDI:

    case OPC_DADDIU:

#endif

    case OPC_SLTI:

    case OPC_SLTIU:

        uimm = (target_long)imm; /* Sign extend to 32/64 bits */

        /* Fall through. */

    case OPC_ANDI:

    case OPC_ORI:

    case OPC_XORI:

        gen_load_gpr(t0, rs);

        break;

    case OPC_LUI:

        tcg_gen_movi_tl(t0, imm << 16);

        break;

    case OPC_SLL:

    case OPC_SRA:

    case OPC_SRL:

#if defined(TARGET_MIPS64)

    case OPC_DSLL:

    case OPC_DSRA:

    case OPC_DSRL:

    case OPC_DSLL32:

    case OPC_DSRA32:

    case OPC_DSRL32:

#endif

        uimm &= 0x1f;

        gen_load_gpr(t0, rs);

        break;

    }

    switch (opc) {

    case OPC_ADDI:

        {

            TCGv r_tmp1 = tcg_temp_local_new(TCG_TYPE_TL);

            TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_TL);

            int l1 = gen_new_label();

            save_cpu_state(ctx, 1);

            tcg_gen_ext32s_tl(r_tmp1, t0);

            tcg_gen_addi_tl(t0, r_tmp1, uimm);

            tcg_gen_xori_tl(r_tmp1, r_tmp1, uimm);

            tcg_gen_xori_tl(r_tmp1, r_tmp1, -1);

            tcg_gen_xori_tl(r_tmp2, t0, uimm);

            tcg_gen_and_tl(r_tmp1, r_tmp1, r_tmp2);

            tcg_temp_free(r_tmp2);

            tcg_gen_shri_tl(r_tmp1, r_tmp1, 31);

            tcg_gen_brcondi_tl(TCG_COND_EQ, r_tmp1, 0, l1);

            tcg_temp_free(r_tmp1);

            /* operands of same sign, result different sign */

            generate_exception(ctx, EXCP_OVERFLOW);

            gen_set_label(l1);

            tcg_gen_ext32s_tl(t0, t0);

        }

        opn = "addi";

        break;

    case OPC_ADDIU:

        tcg_gen_ext32s_tl(t0, t0);

        tcg_gen_addi_tl(t0, t0, uimm);

        tcg_gen_ext32s_tl(t0, t0);

        opn = "addiu";

        break;

#if defined(TARGET_MIPS64)

    case OPC_DADDI:

        {

            TCGv r_tmp1 = tcg_temp_local_new(TCG_TYPE_TL);

            TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_TL);

            int l1 = gen_new_label();

            save_cpu_state(ctx, 1);

            tcg_gen_mov_tl(r_tmp1, t0);

            tcg_gen_addi_tl(t0, t0, uimm);

            tcg_gen_xori_tl(r_tmp1, r_tmp1, uimm);

            tcg_gen_xori_tl(r_tmp1, r_tmp1, -1);

            tcg_gen_xori_tl(r_tmp2, t0, uimm);

            tcg_gen_and_tl(r_tmp1, r_tmp1, r_tmp2);

            tcg_temp_free(r_tmp2);

            tcg_gen_shri_tl(r_tmp1, r_tmp1, 63);

            tcg_gen_brcondi_tl(TCG_COND_EQ, r_tmp1, 0, l1);

            tcg_temp_free(r_tmp1);

            /* operands of same sign, result different sign */

            generate_exception(ctx, EXCP_OVERFLOW);

            gen_set_label(l1);

        }

        opn = "daddi";

        break;

    case OPC_DADDIU:

        tcg_gen_addi_tl(t0, t0, uimm);

        opn = "daddiu";

        break;

#endif

    case OPC_SLTI:

        gen_op_lti(t0, uimm);

        opn = "slti";

        break;

    case OPC_SLTIU:

        gen_op_ltiu(t0, uimm);

        opn = "sltiu";

        break;

    case OPC_ANDI:

        tcg_gen_andi_tl(t0, t0, uimm);

        opn = "andi";

        break;

    case OPC_ORI:

        tcg_gen_ori_tl(t0, t0, uimm);

        opn = "ori";

        break;

    case OPC_XORI:

        tcg_gen_xori_tl(t0, t0, uimm);

        opn = "xori";

        break;

    case OPC_LUI:

        opn = "lui";

        break;

    case OPC_SLL:

        tcg_gen_ext32u_tl(t0, t0);

        tcg_gen_shli_tl(t0, t0, uimm);

        tcg_gen_ext32s_tl(t0, t0);

        opn = "sll";

        break;

    case OPC_SRA:

        tcg_gen_ext32s_tl(t0, t0);

        tcg_gen_sari_tl(t0, t0, uimm);

        tcg_gen_ext32s_tl(t0, t0);

        opn = "sra";

        break;

    case OPC_SRL:

        switch ((ctx->opcode >> 21) & 0x1f) {

        case 0:

            tcg_gen_ext32u_tl(t0, t0);

            tcg_gen_shri_tl(t0, t0, uimm);

            tcg_gen_ext32s_tl(t0, t0);

            opn = "srl";

            break;

        case 1:

            /* rotr is decoded as srl on non-R2 CPUs */

            if (env->insn_flags & ISA_MIPS32R2) {

                if (uimm != 0) {

                    TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I32);

                    tcg_gen_trunc_tl_i32(r_tmp1, t0);

                    tcg_gen_rotri_i32(r_tmp1, r_tmp1, uimm);

                    tcg_gen_ext_i32_tl(t0, r_tmp1);

                    tcg_temp_free(r_tmp1);

                }

                opn = "rotr";

            } else {

                tcg_gen_ext32u_tl(t0, t0);

                tcg_gen_shri_tl(t0, t0, uimm);

                tcg_gen_ext32s_tl(t0, t0);

                opn = "srl";

            }

            break;

        default:

            MIPS_INVAL("invalid srl flag");

            generate_exception(ctx, EXCP_RI);

            break;

        }

        break;

#if defined(TARGET_MIPS64)

    case OPC_DSLL:

        tcg_gen_shli_tl(t0, t0, uimm);

        opn = "dsll";

        break;

    case OPC_DSRA:

        tcg_gen_sari_tl(t0, t0, uimm);

        opn = "dsra";

        break;

    case OPC_DSRL:

        switch ((ctx->opcode >> 21) & 0x1f) {

        case 0:

            tcg_gen_shri_tl(t0, t0, uimm);

            opn = "dsrl";

            break;

        case 1:

            /* drotr is decoded as dsrl on non-R2 CPUs */

            if (env->insn_flags & ISA_MIPS32R2) {

                if (uimm != 0) {

                    tcg_gen_rotri_tl(t0, t0, uimm);

                }

                opn = "drotr";

            } else {

                tcg_gen_shri_tl(t0, t0, uimm);

                opn = "dsrl";

            }

            break;

        default:

            MIPS_INVAL("invalid dsrl flag");

            generate_exception(ctx, EXCP_RI);

            break;

        }

        break;

    case OPC_DSLL32:

        tcg_gen_shli_tl(t0, t0, uimm + 32);

        opn = "dsll32";

        break;

    case OPC_DSRA32:

        tcg_gen_sari_tl(t0, t0, uimm + 32);

        opn = "dsra32";

        break;

    case OPC_DSRL32:

        switch ((ctx->opcode >> 21) & 0x1f) {

        case 0:

            tcg_gen_shri_tl(t0, t0, uimm + 32);

            opn = "dsrl32";

            break;

        case 1:

            /* drotr32 is decoded as dsrl32 on non-R2 CPUs */

            if (env->insn_flags & ISA_MIPS32R2) {

                tcg_gen_rotri_tl(t0, t0, uimm + 32);

                opn = "drotr32";

            } else {

                tcg_gen_shri_tl(t0, t0, uimm + 32);

                opn = "dsrl32";

            }

            break;

        default:

            MIPS_INVAL("invalid dsrl32 flag");

            generate_exception(ctx, EXCP_RI);

            break;

        }

        break;

#endif

    default:

        MIPS_INVAL(opn);

        generate_exception(ctx, EXCP_RI);

        goto out;

    }

    gen_store_gpr(t0, rt);

    MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);

 out:

    tcg_temp_free(t0);

}


static ImageInfoSpecific *vmdk_get_specific_info(BlockDriverState *bs)

{

    int i;

    BDRVVmdkState *s = bs->opaque;

    ImageInfoSpecific *spec_info = g_new0(ImageInfoSpecific, 1);

    ImageInfoList **next;

    *spec_info = (ImageInfoSpecific){

        .type = IMAGE_INFO_SPECIFIC_KIND_VMDK,

        {

            .vmdk = g_new0(ImageInfoSpecificVmdk, 1),

        },

    };

    *spec_info->u.vmdk = (ImageInfoSpecificVmdk) {

        .create_type = g_strdup(s->create_type),

        .cid = s->cid,

        .parent_cid = s->parent_cid,

    };

    next = &spec_info->u.vmdk->extents;

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

        *next = g_new0(ImageInfoList, 1);

        (*next)->value = vmdk_get_extent_info(&s->extents[i]);

        (*next)->next = NULL;

        next = &(*next)->next;

    }

    return spec_info;

}


void do_smbios_option(const char *optarg)

{

#ifdef TARGET_I386

    if (smbios_entry_add(optarg) < 0) {

        fprintf(stderr, "Wrong smbios provided\n");

        exit(1);

    }

#endif

}


static int oss_run_in (HWVoiceIn *hw)

{

    OSSVoiceIn *oss = (OSSVoiceIn *) hw;

    int hwshift = hw->info.shift;

    int i;

    int live = audio_pcm_hw_get_live_in (hw);

    int dead = hw->samples - live;

    size_t read_samples = 0;

    struct {

        int add;

        int len;

    } bufs[2] = {

        { hw->wpos, 0 },

        { 0, 0 }

    };

    if (!dead) {

        return 0;

    }

    if (hw->wpos + dead > hw->samples) {

        bufs[0].len = (hw->samples - hw->wpos) << hwshift;

        bufs[1].len = (dead - (hw->samples - hw->wpos)) << hwshift;

    }

    else {

        bufs[0].len = dead << hwshift;

    }

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

        ssize_t nread;

        if (bufs[i].len) {

            void *p = advance (oss->pcm_buf, bufs[i].add << hwshift);

            nread = read (oss->fd, p, bufs[i].len);

            if (nread > 0) {

                if (nread & hw->info.align) {

                    dolog ("warning: Misaligned read %zd (requested %d), "

                           "alignment %d\n", nread, bufs[i].add << hwshift,

                           hw->info.align + 1);

                }

                read_samples += nread >> hwshift;

                hw->conv (hw->conv_buf + bufs[i].add, p, nread >> hwshift,

                          &nominal_volume);

            }

            if (bufs[i].len - nread) {

                if (nread == -1) {

                    switch (errno) {

                    case EINTR:

                    case EAGAIN:

                        break;

                    default:

                        oss_logerr (

                            errno,

                            "Failed to read %d bytes of audio (to %p)\n",

                            bufs[i].len, p

                            );

                        break;

                    }

                }

                break;

            }

        }

    }

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

    return read_samples;

}


int bdrv_debug_remove_breakpoint(BlockDriverState *bs, const char *tag)

{

    while (bs && bs->drv && !bs->drv->bdrv_debug_remove_breakpoint) {

        bs = bs->file;

    }

    if (bs && bs->drv && bs->drv->bdrv_debug_remove_breakpoint) {

        return bs->drv->bdrv_debug_remove_breakpoint(bs, tag);

    }

    return -ENOTSUP;

}


int rtp_set_remote_url(URLContext *h, const char *uri)

{

    RTPContext *s = h->priv_data;

    char hostname[256];

    int port;

    char buf[1024];

    char path[1024];

    url_split(NULL, 0, hostname, sizeof(hostname), &port,

              path, sizeof(path), uri);

    snprintf(buf, sizeof(buf), "udp://%s:%d%s", hostname, port, path);

    udp_set_remote_url(s->rtp_hd, buf);

    snprintf(buf, sizeof(buf), "udp://%s:%d%s", hostname, port + 1, path);

    udp_set_remote_url(s->rtcp_hd, buf);

    return 0;

}


int vp78_decode_mb_row_sliced(AVCodecContext *avctx, void *tdata, int jobnr,

                              int threadnr, int is_vp7)

{

    VP8Context *s = avctx->priv_data;

    VP8ThreadData *td = &s->thread_data[jobnr];

    VP8ThreadData *next_td = NULL, *prev_td = NULL;

    VP8Frame *curframe = s->curframe;

    int mb_y, num_jobs = s->num_jobs;

    int ret;

    td->thread_nr = threadnr;

    for (mb_y = jobnr; mb_y < s->mb_height; mb_y += num_jobs) {

        if (mb_y >= s->mb_height)

            break;

        td->thread_mb_pos = mb_y << 16;

        ret = s->decode_mb_row_no_filter(avctx, tdata, jobnr, threadnr);

        if (ret < 0)

            return ret;

        if (s->deblock_filter)

            s->filter_mb_row(avctx, tdata, jobnr, threadnr);

        update_pos(td, mb_y, INT_MAX & 0xFFFF);

        s->mv_min.y -= 64;

        s->mv_max.y -= 64;

        if (avctx->active_thread_type == FF_THREAD_FRAME)

            ff_thread_report_progress(&curframe->tf, mb_y, 0);

    }

    return 0;

}


const char *avfilter_configuration(void)

{

    return FFMPEG_CONFIGURATION;

}


static void uart_send_breaks(UartState *s)

{

    int break_enabled = 1;

    qemu_chr_fe_ioctl(s->chr, CHR_IOCTL_SERIAL_SET_BREAK,

                               &break_enabled);

}


static void cris_alu(DisasContext *dc, int op,

			       TCGv d, TCGv op_a, TCGv op_b, int size)

{

	TCGv tmp;

	int writeback;

	writeback = 1;

	if (op == CC_OP_BOUND || op == CC_OP_BTST)

		tmp = tcg_temp_local_new(TCG_TYPE_TL);

	if (op == CC_OP_CMP) {

		tmp = tcg_temp_new(TCG_TYPE_TL);

		writeback = 0;

	} else if (size == 4) {

		tmp = d;

		writeback = 0;

	} else

		tmp = tcg_temp_new(TCG_TYPE_TL);

	cris_pre_alu_update_cc(dc, op, op_a, op_b, size);

	cris_alu_op_exec(dc, op, tmp, op_a, op_b, size);

	cris_update_result(dc, tmp);

	/* Writeback.  */

	if (writeback) {

		if (size == 1)

			tcg_gen_andi_tl(d, d, ~0xff);

		else

			tcg_gen_andi_tl(d, d, ~0xffff);

		tcg_gen_or_tl(d, d, tmp);

	}

	if (GET_TCGV(tmp) != GET_TCGV(d))

		tcg_temp_free(tmp);

}


void ide_atapi_cmd_reply_end(IDEState *s)

{

    int byte_count_limit, size, ret;

#ifdef DEBUG_IDE_ATAPI

    printf("reply: tx_size=%d elem_tx_size=%d index=%d\n",

           s->packet_transfer_size,

           s->elementary_transfer_size,

           s->io_buffer_index);

#endif

    if (s->packet_transfer_size <= 0) {

        /* end of transfer */

        s->status = READY_STAT | SEEK_STAT;

        s->nsector = (s->nsector & ~7) | ATAPI_INT_REASON_IO | ATAPI_INT_REASON_CD;

        ide_transfer_stop(s);

        ide_set_irq(s->bus);

#ifdef DEBUG_IDE_ATAPI

        printf("status=0x%x\n", s->status);

#endif

    } else {

        /* see if a new sector must be read */

        if (s->lba != -1 && s->io_buffer_index >= s->cd_sector_size) {

            ret = cd_read_sector(s, s->lba, s->io_buffer, s->cd_sector_size);

            if (ret < 0) {

                ide_transfer_stop(s);

                ide_atapi_io_error(s, ret);

                return;

            }

            s->lba++;

            s->io_buffer_index = 0;

        }

        if (s->elementary_transfer_size > 0) {

            /* there are some data left to transmit in this elementary

               transfer */

            size = s->cd_sector_size - s->io_buffer_index;

            if (size > s->elementary_transfer_size)

                size = s->elementary_transfer_size;

            s->packet_transfer_size -= size;

            s->elementary_transfer_size -= size;

            s->io_buffer_index += size;

            ide_transfer_start(s, s->io_buffer + s->io_buffer_index - size,

                               size, ide_atapi_cmd_reply_end);

        } else {

            /* a new transfer is needed */

            s->nsector = (s->nsector & ~7) | ATAPI_INT_REASON_IO;

            byte_count_limit = s->lcyl | (s->hcyl << 8);

#ifdef DEBUG_IDE_ATAPI

            printf("byte_count_limit=%d\n", byte_count_limit);

#endif

            if (byte_count_limit == 0xffff)

                byte_count_limit--;

            size = s->packet_transfer_size;

            if (size > byte_count_limit) {

                /* byte count limit must be even if this case */

                if (byte_count_limit & 1)

                    byte_count_limit--;

                size = byte_count_limit;

            }

            s->lcyl = size;

            s->hcyl = size >> 8;

            s->elementary_transfer_size = size;

            /* we cannot transmit more than one sector at a time */

            if (s->lba != -1) {

                if (size > (s->cd_sector_size - s->io_buffer_index))

                    size = (s->cd_sector_size - s->io_buffer_index);

            }

            s->packet_transfer_size -= size;

            s->elementary_transfer_size -= size;

            s->io_buffer_index += size;

            ide_transfer_start(s, s->io_buffer + s->io_buffer_index - size,

                               size, ide_atapi_cmd_reply_end);

            ide_set_irq(s->bus);

#ifdef DEBUG_IDE_ATAPI

            printf("status=0x%x\n", s->status);

#endif

        }

    }

}


static int ehci_execute(EHCIQueue *q)

{

    USBDevice *dev;

    int ret;

    int endp;

    int devadr;

    if ( !(q->qh.token & QTD_TOKEN_ACTIVE)) {

        fprintf(stderr, "Attempting to execute inactive QH\n");

        return USB_RET_PROCERR;

    }

    q->tbytes = (q->qh.token & QTD_TOKEN_TBYTES_MASK) >> QTD_TOKEN_TBYTES_SH;

    if (q->tbytes > BUFF_SIZE) {

        fprintf(stderr, "Request for more bytes than allowed\n");

        return USB_RET_PROCERR;

    }

    q->pid = (q->qh.token & QTD_TOKEN_PID_MASK) >> QTD_TOKEN_PID_SH;

    switch(q->pid) {

        case 0: q->pid = USB_TOKEN_OUT; break;

        case 1: q->pid = USB_TOKEN_IN; break;

        case 2: q->pid = USB_TOKEN_SETUP; break;

        default: fprintf(stderr, "bad token\n"); break;

    }

    if (ehci_init_transfer(q) != 0) {

        return USB_RET_PROCERR;

    }

    endp = get_field(q->qh.epchar, QH_EPCHAR_EP);

    devadr = get_field(q->qh.epchar, QH_EPCHAR_DEVADDR);

    ret = USB_RET_NODEV;

    usb_packet_setup(&q->packet, q->pid, devadr, endp);

    usb_packet_map(&q->packet, &q->sgl);

    // TO-DO: associating device with ehci port

    dev = ehci_find_device(q->ehci, q->packet.devaddr);

    ret = usb_handle_packet(dev, &q->packet);

    DPRINTF("submit: qh %x next %x qtd %x pid %x len %zd "

            "(total %d) endp %x ret %d\n",

            q->qhaddr, q->qh.next, q->qtdaddr, q->pid,

            q->packet.iov.size, q->tbytes, endp, ret);

    if (ret > BUFF_SIZE) {

        fprintf(stderr, "ret from usb_handle_packet > BUFF_SIZE\n");

        return USB_RET_PROCERR;

    }

    return ret;

}


static void sdl_resize(DisplayState *ds, int w, int h)

{

    int flags;

    //    printf("resizing to %d %d\n", w, h);

    flags = SDL_HWSURFACE|SDL_ASYNCBLIT|SDL_HWACCEL;

    flags |= SDL_RESIZABLE;

    if (gui_fullscreen)

        flags |= SDL_FULLSCREEN;

    screen = SDL_SetVideoMode(w, h, 0, flags);

    if (!screen) {

        fprintf(stderr, "Could not open SDL display\n");

        exit(1);

    }

    ds->data = screen->pixels;

    ds->linesize = screen->pitch;

    ds->depth = screen->format->BitsPerPixel;

    ds->width = w;

    ds->height = h;

}


static uint64_t imx_avic_read(void *opaque,

                             target_phys_addr_t offset, unsigned size)

{

    IMXAVICState *s = (IMXAVICState *)opaque;

    DPRINTF("read(offset = 0x%x)\n", offset >> 2);

    switch (offset >> 2) {

    case 0: /* INTCNTL */

        return s->intcntl;

    case 1: /* Normal Interrupt Mask Register, NIMASK */

        return s->intmask;

    case 2: /* Interrupt Enable Number Register, INTENNUM */

    case 3: /* Interrupt Disable Number Register, INTDISNUM */

        return 0;

    case 4: /* Interrupt Enabled Number Register High */

        return s->enabled >> 32;

    case 5: /* Interrupt Enabled Number Register Low */

        return s->enabled & 0xffffffffULL;

    case 6: /* Interrupt Type Register High */

        return s->is_fiq >> 32;

    case 7: /* Interrupt Type Register Low */

        return s->is_fiq & 0xffffffffULL;

    case 8: /* Normal Interrupt Priority Register 7 */

    case 9: /* Normal Interrupt Priority Register 6 */

    case 10:/* Normal Interrupt Priority Register 5 */

    case 11:/* Normal Interrupt Priority Register 4 */

    case 12:/* Normal Interrupt Priority Register 3 */

    case 13:/* Normal Interrupt Priority Register 2 */

    case 14:/* Normal Interrupt Priority Register 1 */

    case 15:/* Normal Interrupt Priority Register 0 */

        return s->prio[15-(offset>>2)];

    case 16: /* Normal interrupt vector and status register */

    {

        /*

         * This returns the highest priority

         * outstanding interrupt.  Where there is more than

         * one pending IRQ with the same priority,

         * take the highest numbered one.

         */

        uint64_t flags = s->pending & s->enabled & ~s->is_fiq;

        int i;

        int prio = -1;

        int irq = -1;

        for (i = 63; i >= 0; --i) {

            if (flags & (1ULL<<i)) {

                int irq_prio = imx_avic_prio(s, i);

                if (irq_prio > prio) {

                    irq = i;

                    prio = irq_prio;

                }

            }

        }

        if (irq >= 0) {

            imx_avic_set_irq(s, irq, 0);

            return irq << 16 | prio;

        }

        return 0xffffffffULL;

    }

    case 17:/* Fast Interrupt vector and status register */

    {

        uint64_t flags = s->pending & s->enabled & s->is_fiq;

        int i = ctz64(flags);

        if (i < 64) {

            imx_avic_set_irq(opaque, i, 0);

            return i;

        }

        return 0xffffffffULL;

    }

    case 18:/* Interrupt source register high */

        return s->pending >> 32;

    case 19:/* Interrupt source register low */

        return s->pending & 0xffffffffULL;

    case 20:/* Interrupt Force Register high */

    case 21:/* Interrupt Force Register low */

        return 0;

    case 22:/* Normal Interrupt Pending Register High */

        return (s->pending & s->enabled & ~s->is_fiq) >> 32;

    case 23:/* Normal Interrupt Pending Register Low */

        return (s->pending & s->enabled & ~s->is_fiq) & 0xffffffffULL;

    case 24: /* Fast Interrupt Pending Register High  */

        return (s->pending & s->enabled & s->is_fiq) >> 32;

    case 25: /* Fast Interrupt Pending Register Low  */

        return (s->pending & s->enabled & s->is_fiq) & 0xffffffffULL;

    case 0x40:            /* AVIC vector 0, use for WFI WAR */

        return 0x4;

    default:

        IPRINTF("imx_avic_read: Bad offset 0x%x\n", (int)offset);

        return 0;

    }

}


static enum CodecID find_codec_or_die(const char *name, enum AVMediaType type, int encoder)

{

    const char *codec_string = encoder ? "encoder" : "decoder";

    AVCodec *codec;

    if(!name)

        return CODEC_ID_NONE;

    codec = encoder ?

        avcodec_find_encoder_by_name(name) :

        avcodec_find_decoder_by_name(name);

    if(!codec) {

        av_log(NULL, AV_LOG_FATAL, "Unknown %s '%s'\n", codec_string, name);

        exit_program(1);

    }

    if(codec->type != type) {

        av_log(NULL, AV_LOG_FATAL, "Invalid %s type '%s'\n", codec_string, name);

        exit_program(1);

    }

    return codec->id;

}


static void sd_blk_read(SDState *sd, uint64_t addr, uint32_t len)

{

    uint64_t end = addr + len;

    DPRINTF("sd_blk_read: addr = 0x%08llx, len = %d\n",

            (unsigned long long) addr, len);

    if (!sd->bdrv || bdrv_read(sd->bdrv, addr >> 9, sd->buf, 1) < 0) {

        fprintf(stderr, "sd_blk_read: read error on host side\n");

        return;

    }

    if (end > (addr & ~511) + 512) {

        memcpy(sd->data, sd->buf + (addr & 511), 512 - (addr & 511));

        if (bdrv_read(sd->bdrv, end >> 9, sd->buf, 1) < 0) {

            fprintf(stderr, "sd_blk_read: read error on host side\n");

            return;

        }

        memcpy(sd->data + 512 - (addr & 511), sd->buf, end & 511);

    } else

        memcpy(sd->data, sd->buf + (addr & 511), len);

}


static void thumb_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)

{

    DisasContext *dc = container_of(dcbase, DisasContext, base);

    CPUARMState *env = cpu->env_ptr;

    uint32_t insn;

    bool is_16bit;

    if (arm_pre_translate_insn(dc)) {

        return;

    }

    insn = arm_lduw_code(env, dc->pc, dc->sctlr_b);

    is_16bit = thumb_insn_is_16bit(dc, insn);

    dc->pc += 2;

    if (!is_16bit) {

        uint32_t insn2 = arm_lduw_code(env, dc->pc, dc->sctlr_b);

        insn = insn << 16 | insn2;

        dc->pc += 2;

    }

    dc->insn = insn;

    if (dc->condexec_mask && !thumb_insn_is_unconditional(dc, insn)) {

        uint32_t cond = dc->condexec_cond;

        if (cond != 0x0e) {     /* Skip conditional when condition is AL. */

            dc->condlabel = gen_new_label();

            arm_gen_test_cc(cond ^ 1, dc->condlabel);

            dc->condjmp = 1;

        }

    }

    if (is_16bit) {

        disas_thumb_insn(dc, insn);

    } else {

        if (disas_thumb2_insn(dc, insn)) {

            gen_exception_insn(dc, 4, EXCP_UDEF, syn_uncategorized(),

                               default_exception_el(dc));

        }

    }

    /* Advance the Thumb condexec condition.  */

    if (dc->condexec_mask) {

        dc->condexec_cond = ((dc->condexec_cond & 0xe) |

                             ((dc->condexec_mask >> 4) & 1));

        dc->condexec_mask = (dc->condexec_mask << 1) & 0x1f;

        if (dc->condexec_mask == 0) {

            dc->condexec_cond = 0;

        }

    }

    arm_post_translate_insn(dc);

    /* Thumb is a variable-length ISA.  Stop translation when the next insn

     * will touch a new page.  This ensures that prefetch aborts occur at

     * the right place.

     *

     * We want to stop the TB if the next insn starts in a new page,

     * or if it spans between this page and the next. This means that

     * if we're looking at the last halfword in the page we need to

     * see if it's a 16-bit Thumb insn (which will fit in this TB)

     * or a 32-bit Thumb insn (which won't).

     * This is to avoid generating a silly TB with a single 16-bit insn

     * in it at the end of this page (which would execute correctly

     * but isn't very efficient).

     */

    if (dc->base.is_jmp == DISAS_NEXT

        && (dc->pc >= dc->next_page_start

            || (dc->pc >= dc->next_page_start - 3

                && insn_crosses_page(env, dc)))) {

        dc->base.is_jmp = DISAS_TOO_MANY;

    }

}


void qemu_set_dfilter_ranges(const char *filter_spec, Error **errp)

{

    gchar **ranges = g_strsplit(filter_spec, ",", 0);

    int i;

    if (debug_regions) {

        g_array_unref(debug_regions);

        debug_regions = NULL;

    }

    debug_regions = g_array_sized_new(FALSE, FALSE,

                                      sizeof(Range), g_strv_length(ranges));

    for (i = 0; ranges[i]; i++) {

        const char *r = ranges[i];

        const char *range_op, *r2, *e;

        uint64_t r1val, r2val, lob, upb;

        struct Range range;

        range_op = strstr(r, "-");

        r2 = range_op ? range_op + 1 : NULL;

        if (!range_op) {

            range_op = strstr(r, "+");

            r2 = range_op ? range_op + 1 : NULL;

        }

        if (!range_op) {

            range_op = strstr(r, "..");

            r2 = range_op ? range_op + 2 : NULL;

        }

        if (!range_op) {

            error_setg(errp, "Bad range specifier");

            goto out;

        }

        if (qemu_strtoull(r, &e, 0, &r1val)

            || e != range_op) {

            error_setg(errp, "Invalid number to the left of %.*s",

                       (int)(r2 - range_op), range_op);

            goto out;

        }

        if (qemu_strtoull(r2, NULL, 0, &r2val)) {

            error_setg(errp, "Invalid number to the right of %.*s",

                       (int)(r2 - range_op), range_op);

            goto out;

        }

        switch (*range_op) {

        case '+':

            lob = r1val;

            upb = r1val + r2val - 1;

            break;

        case '-':

            upb = r1val;

            lob = r1val - (r2val - 1);

            break;

        case '.':

            lob = r1val;

            upb = r2val;

            break;

        default:

            g_assert_not_reached();

        }

        if (lob > upb || (lob == 0 && upb == UINT64_MAX)) {

            error_setg(errp, "Invalid range");

            goto out;

        }

        range.begin = lob;

        range.end = upb + 1;

        g_array_append_val(debug_regions, range);

    }

out:

    g_strfreev(ranges);

}


static void disas_arm_insn(CPUState * env, DisasContext *s)

{

    unsigned int cond, insn, val, op1, i, shift, rm, rs, rn, rd, sh;

    TCGv tmp;

    TCGv tmp2;

    TCGv tmp3;

    TCGv addr;

    TCGv_i64 tmp64;

    insn = ldl_code(s->pc);

    s->pc += 4;

    /* M variants do not implement ARM mode.  */

    if (IS_M(env))

        goto illegal_op;

    cond = insn >> 28;

    if (cond == 0xf){

        /* Unconditional instructions.  */

        if (((insn >> 25) & 7) == 1) {

            /* NEON Data processing.  */

            if (!arm_feature(env, ARM_FEATURE_NEON))

                goto illegal_op;

            if (disas_neon_data_insn(env, s, insn))

                goto illegal_op;

            return;

        }

        if ((insn & 0x0f100000) == 0x04000000) {

            /* NEON load/store.  */

            if (!arm_feature(env, ARM_FEATURE_NEON))

                goto illegal_op;

            if (disas_neon_ls_insn(env, s, insn))

                goto illegal_op;

            return;

        }

        if (((insn & 0x0f30f000) == 0x0510f000) ||

            ((insn & 0x0f30f010) == 0x0710f000)) {

            if ((insn & (1 << 22)) == 0) {

                /* PLDW; v7MP */

                if (!arm_feature(env, ARM_FEATURE_V7MP)) {

                    goto illegal_op;

                }

            }

            /* Otherwise PLD; v5TE+ */

            return;

        }

        if (((insn & 0x0f70f000) == 0x0450f000) ||

            ((insn & 0x0f70f010) == 0x0650f000)) {

            ARCH(7);

            return; /* PLI; V7 */

        }

        if (((insn & 0x0f700000) == 0x04100000) ||

            ((insn & 0x0f700010) == 0x06100000)) {

            if (!arm_feature(env, ARM_FEATURE_V7MP)) {

                goto illegal_op;

            }

            return; /* v7MP: Unallocated memory hint: must NOP */

        }

        if ((insn & 0x0ffffdff) == 0x01010000) {

            ARCH(6);

            /* setend */

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

                /* BE8 mode not implemented.  */

                goto illegal_op;

            }

            return;

        } else if ((insn & 0x0fffff00) == 0x057ff000) {

            switch ((insn >> 4) & 0xf) {

            case 1: /* clrex */

                ARCH(6K);

                gen_clrex(s);

                return;

            case 4: /* dsb */

            case 5: /* dmb */

            case 6: /* isb */

                ARCH(7);

                /* We don't emulate caches so these are a no-op.  */

                return;

            default:

                goto illegal_op;

            }

        } else if ((insn & 0x0e5fffe0) == 0x084d0500) {

            /* srs */

            int32_t offset;

            if (IS_USER(s))

                goto illegal_op;

            ARCH(6);

            op1 = (insn & 0x1f);

            addr = tcg_temp_new_i32();

            tmp = tcg_const_i32(op1);

            gen_helper_get_r13_banked(addr, cpu_env, tmp);

            tcg_temp_free_i32(tmp);

            i = (insn >> 23) & 3;

            switch (i) {

            case 0: offset = -4; break; /* DA */

            case 1: offset = 0; break; /* IA */

            case 2: offset = -8; break; /* DB */

            case 3: offset = 4; break; /* IB */

            default: abort();

            }

            if (offset)

                tcg_gen_addi_i32(addr, addr, offset);

            tmp = load_reg(s, 14);

            gen_st32(tmp, addr, 0);

            tmp = load_cpu_field(spsr);

            tcg_gen_addi_i32(addr, addr, 4);

            gen_st32(tmp, addr, 0);

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

                /* Base writeback.  */

                switch (i) {

                case 0: offset = -8; break;

                case 1: offset = 4; break;

                case 2: offset = -4; break;

                case 3: offset = 0; break;

                default: abort();

                }

                if (offset)

                    tcg_gen_addi_i32(addr, addr, offset);

                tmp = tcg_const_i32(op1);

                gen_helper_set_r13_banked(cpu_env, tmp, addr);

                tcg_temp_free_i32(tmp);

                tcg_temp_free_i32(addr);

            } else {

                tcg_temp_free_i32(addr);

            }

            return;

        } else if ((insn & 0x0e50ffe0) == 0x08100a00) {

            /* rfe */

            int32_t offset;

            if (IS_USER(s))

                goto illegal_op;

            ARCH(6);

            rn = (insn >> 16) & 0xf;

            addr = load_reg(s, rn);

            i = (insn >> 23) & 3;

            switch (i) {

            case 0: offset = -4; break; /* DA */

            case 1: offset = 0; break; /* IA */

            case 2: offset = -8; break; /* DB */

            case 3: offset = 4; break; /* IB */

            default: abort();

            }

            if (offset)

                tcg_gen_addi_i32(addr, addr, offset);

            /* Load PC into tmp and CPSR into tmp2.  */

            tmp = gen_ld32(addr, 0);

            tcg_gen_addi_i32(addr, addr, 4);

            tmp2 = gen_ld32(addr, 0);

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

                /* Base writeback.  */

                switch (i) {

                case 0: offset = -8; break;

                case 1: offset = 4; break;

                case 2: offset = -4; break;

                case 3: offset = 0; break;

                default: abort();

                }

                if (offset)

                    tcg_gen_addi_i32(addr, addr, offset);

                store_reg(s, rn, addr);

            } else {

                tcg_temp_free_i32(addr);

            }

            gen_rfe(s, tmp, tmp2);

            return;

        } else if ((insn & 0x0e000000) == 0x0a000000) {

            /* branch link and change to thumb (blx <offset>) */

            int32_t offset;

            val = (uint32_t)s->pc;

            tmp = tcg_temp_new_i32();

            tcg_gen_movi_i32(tmp, val);

            store_reg(s, 14, tmp);

            /* Sign-extend the 24-bit offset */

            offset = (((int32_t)insn) << 8) >> 8;

            /* offset * 4 + bit24 * 2 + (thumb bit) */

            val += (offset << 2) | ((insn >> 23) & 2) | 1;

            /* pipeline offset */

            val += 4;

            gen_bx_im(s, val);

            return;

        } else if ((insn & 0x0e000f00) == 0x0c000100) {

            if (arm_feature(env, ARM_FEATURE_IWMMXT)) {

                /* iWMMXt register transfer.  */

                if (env->cp15.c15_cpar & (1 << 1))

                    if (!disas_iwmmxt_insn(env, s, insn))

                        return;

            }

        } else if ((insn & 0x0fe00000) == 0x0c400000) {

            /* Coprocessor double register transfer.  */

        } else if ((insn & 0x0f000010) == 0x0e000010) {

            /* Additional coprocessor register transfer.  */

        } else if ((insn & 0x0ff10020) == 0x01000000) {

            uint32_t mask;

            uint32_t val;

            /* cps (privileged) */

            if (IS_USER(s))

                return;

            mask = val = 0;

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

                if (insn & (1 << 8))

                    mask |= CPSR_A;

                if (insn & (1 << 7))

                    mask |= CPSR_I;

                if (insn & (1 << 6))

                    mask |= CPSR_F;

                if (insn & (1 << 18))

                    val |= mask;

            }

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

                mask |= CPSR_M;

                val |= (insn & 0x1f);

            }

            if (mask) {

                gen_set_psr_im(s, mask, 0, val);

            }

            return;

        }

        goto illegal_op;

    }

    if (cond != 0xe) {

        /* if not always execute, we generate a conditional jump to

           next instruction */

        s->condlabel = gen_new_label();

        gen_test_cc(cond ^ 1, s->condlabel);

        s->condjmp = 1;

    }

    if ((insn & 0x0f900000) == 0x03000000) {

        if ((insn & (1 << 21)) == 0) {

            ARCH(6T2);

            rd = (insn >> 12) & 0xf;

            val = ((insn >> 4) & 0xf000) | (insn & 0xfff);

            if ((insn & (1 << 22)) == 0) {

                /* MOVW */

                tmp = tcg_temp_new_i32();

                tcg_gen_movi_i32(tmp, val);

            } else {

                /* MOVT */

                tmp = load_reg(s, rd);

                tcg_gen_ext16u_i32(tmp, tmp);

                tcg_gen_ori_i32(tmp, tmp, val << 16);

            }

            store_reg(s, rd, tmp);

        } else {

            if (((insn >> 12) & 0xf) != 0xf)

                goto illegal_op;

            if (((insn >> 16) & 0xf) == 0) {

                gen_nop_hint(s, insn & 0xff);

            } else {

                /* CPSR = immediate */

                val = insn & 0xff;

                shift = ((insn >> 8) & 0xf) * 2;

                if (shift)

                    val = (val >> shift) | (val << (32 - shift));

                i = ((insn & (1 << 22)) != 0);

                if (gen_set_psr_im(s, msr_mask(env, s, (insn >> 16) & 0xf, i), i, val))

                    goto illegal_op;

            }

        }

    } else if ((insn & 0x0f900000) == 0x01000000

               && (insn & 0x00000090) != 0x00000090) {

        /* miscellaneous instructions */

        op1 = (insn >> 21) & 3;

        sh = (insn >> 4) & 0xf;

        rm = insn & 0xf;

        switch (sh) {

        case 0x0: /* move program status register */

            if (op1 & 1) {

                /* PSR = reg */

                tmp = load_reg(s, rm);

                i = ((op1 & 2) != 0);

                if (gen_set_psr(s, msr_mask(env, s, (insn >> 16) & 0xf, i), i, tmp))

                    goto illegal_op;

            } else {

                /* reg = PSR */

                rd = (insn >> 12) & 0xf;

                if (op1 & 2) {

                    if (IS_USER(s))

                        goto illegal_op;

                    tmp = load_cpu_field(spsr);

                } else {

                    tmp = tcg_temp_new_i32();

                    gen_helper_cpsr_read(tmp);

                }

                store_reg(s, rd, tmp);

            }

            break;

        case 0x1:

            if (op1 == 1) {

                /* branch/exchange thumb (bx).  */

                tmp = load_reg(s, rm);

                gen_bx(s, tmp);

            } else if (op1 == 3) {

                /* clz */

                rd = (insn >> 12) & 0xf;

                tmp = load_reg(s, rm);

                gen_helper_clz(tmp, tmp);

                store_reg(s, rd, tmp);

            } else {

                goto illegal_op;

            }

            break;

        case 0x2:

            if (op1 == 1) {

                ARCH(5J); /* bxj */

                /* Trivial implementation equivalent to bx.  */

                tmp = load_reg(s, rm);

                gen_bx(s, tmp);

            } else {

                goto illegal_op;

            }

            break;

        case 0x3:

            if (op1 != 1)

              goto illegal_op;

            /* branch link/exchange thumb (blx) */

            tmp = load_reg(s, rm);

            tmp2 = tcg_temp_new_i32();

            tcg_gen_movi_i32(tmp2, s->pc);

            store_reg(s, 14, tmp2);

            gen_bx(s, tmp);

            break;

        case 0x5: /* saturating add/subtract */

            rd = (insn >> 12) & 0xf;

            rn = (insn >> 16) & 0xf;

            tmp = load_reg(s, rm);

            tmp2 = load_reg(s, rn);

            if (op1 & 2)

                gen_helper_double_saturate(tmp2, tmp2);

            if (op1 & 1)

                gen_helper_sub_saturate(tmp, tmp, tmp2);

            else

                gen_helper_add_saturate(tmp, tmp, tmp2);

            tcg_temp_free_i32(tmp2);

            store_reg(s, rd, tmp);

            break;

        case 7:

            /* SMC instruction (op1 == 3)

               and undefined instructions (op1 == 0 || op1 == 2)

               will trap */

            if (op1 != 1) {

                goto illegal_op;

            }

            /* bkpt */

            gen_exception_insn(s, 4, EXCP_BKPT);

            break;

        case 0x8: /* signed multiply */

        case 0xa:

        case 0xc:

        case 0xe:

            rs = (insn >> 8) & 0xf;

            rn = (insn >> 12) & 0xf;

            rd = (insn >> 16) & 0xf;

            if (op1 == 1) {

                /* (32 * 16) >> 16 */

                tmp = load_reg(s, rm);

                tmp2 = load_reg(s, rs);

                if (sh & 4)

                    tcg_gen_sari_i32(tmp2, tmp2, 16);

                else

                    gen_sxth(tmp2);

                tmp64 = gen_muls_i64_i32(tmp, tmp2);

                tcg_gen_shri_i64(tmp64, tmp64, 16);

                tmp = tcg_temp_new_i32();

                tcg_gen_trunc_i64_i32(tmp, tmp64);

                tcg_temp_free_i64(tmp64);

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

                    tmp2 = load_reg(s, rn);

                    gen_helper_add_setq(tmp, tmp, tmp2);

                    tcg_temp_free_i32(tmp2);

                }

                store_reg(s, rd, tmp);

            } else {

                /* 16 * 16 */

                tmp = load_reg(s, rm);

                tmp2 = load_reg(s, rs);

                gen_mulxy(tmp, tmp2, sh & 2, sh & 4);

                tcg_temp_free_i32(tmp2);

                if (op1 == 2) {

                    tmp64 = tcg_temp_new_i64();

                    tcg_gen_ext_i32_i64(tmp64, tmp);

                    tcg_temp_free_i32(tmp);

                    gen_addq(s, tmp64, rn, rd);

                    gen_storeq_reg(s, rn, rd, tmp64);

                    tcg_temp_free_i64(tmp64);

                } else {

                    if (op1 == 0) {

                        tmp2 = load_reg(s, rn);

                        gen_helper_add_setq(tmp, tmp, tmp2);

                        tcg_temp_free_i32(tmp2);

                    }

                    store_reg(s, rd, tmp);

                }

            }

            break;

        default:

            goto illegal_op;

        }

    } else if (((insn & 0x0e000000) == 0 &&

                (insn & 0x00000090) != 0x90) ||

               ((insn & 0x0e000000) == (1 << 25))) {

        int set_cc, logic_cc, shiftop;

        op1 = (insn >> 21) & 0xf;

        set_cc = (insn >> 20) & 1;

        logic_cc = table_logic_cc[op1] & set_cc;

        /* data processing instruction */

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

            /* immediate operand */

            val = insn & 0xff;

            shift = ((insn >> 8) & 0xf) * 2;

            if (shift) {

                val = (val >> shift) | (val << (32 - shift));

            }

            tmp2 = tcg_temp_new_i32();

            tcg_gen_movi_i32(tmp2, val);

            if (logic_cc && shift) {

                gen_set_CF_bit31(tmp2);

            }

        } else {

            /* register */

            rm = (insn) & 0xf;

            tmp2 = load_reg(s, rm);

            shiftop = (insn >> 5) & 3;

            if (!(insn & (1 << 4))) {

                shift = (insn >> 7) & 0x1f;

                gen_arm_shift_im(tmp2, shiftop, shift, logic_cc);

            } else {

                rs = (insn >> 8) & 0xf;

                tmp = load_reg(s, rs);

                gen_arm_shift_reg(tmp2, shiftop, tmp, logic_cc);

            }

        }

        if (op1 != 0x0f && op1 != 0x0d) {

            rn = (insn >> 16) & 0xf;

            tmp = load_reg(s, rn);

        } else {

            TCGV_UNUSED(tmp);

        }

        rd = (insn >> 12) & 0xf;

        switch(op1) {

        case 0x00:

            tcg_gen_and_i32(tmp, tmp, tmp2);

            if (logic_cc) {

                gen_logic_CC(tmp);

            }

            store_reg_bx(env, s, rd, tmp);

            break;

        case 0x01:

            tcg_gen_xor_i32(tmp, tmp, tmp2);

            if (logic_cc) {

                gen_logic_CC(tmp);

            }

            store_reg_bx(env, s, rd, tmp);

            break;

        case 0x02:

            if (set_cc && rd == 15) {

                /* SUBS r15, ... is used for exception return.  */

                if (IS_USER(s)) {

                    goto illegal_op;

                }

                gen_helper_sub_cc(tmp, tmp, tmp2);

                gen_exception_return(s, tmp);

            } else {

                if (set_cc) {

                    gen_helper_sub_cc(tmp, tmp, tmp2);

                } else {

                    tcg_gen_sub_i32(tmp, tmp, tmp2);

                }

                store_reg_bx(env, s, rd, tmp);

            }

            break;

        case 0x03:

            if (set_cc) {

                gen_helper_sub_cc(tmp, tmp2, tmp);

            } else {

                tcg_gen_sub_i32(tmp, tmp2, tmp);

            }

            store_reg_bx(env, s, rd, tmp);

            break;

        case 0x04:

            if (set_cc) {

                gen_helper_add_cc(tmp, tmp, tmp2);

            } else {

                tcg_gen_add_i32(tmp, tmp, tmp2);

            }

            store_reg_bx(env, s, rd, tmp);

            break;

        case 0x05:

            if (set_cc) {

                gen_helper_adc_cc(tmp, tmp, tmp2);

            } else {

                gen_add_carry(tmp, tmp, tmp2);

            }

            store_reg_bx(env, s, rd, tmp);

            break;

        case 0x06:

            if (set_cc) {

                gen_helper_sbc_cc(tmp, tmp, tmp2);

            } else {

                gen_sub_carry(tmp, tmp, tmp2);

            }

            store_reg_bx(env, s, rd, tmp);

            break;

        case 0x07:

            if (set_cc) {

                gen_helper_sbc_cc(tmp, tmp2, tmp);

            } else {

                gen_sub_carry(tmp, tmp2, tmp);

            }

            store_reg_bx(env, s, rd, tmp);

            break;

        case 0x08:

            if (set_cc) {

                tcg_gen_and_i32(tmp, tmp, tmp2);

                gen_logic_CC(tmp);

            }

            tcg_temp_free_i32(tmp);

            break;

        case 0x09:

            if (set_cc) {

                tcg_gen_xor_i32(tmp, tmp, tmp2);

                gen_logic_CC(tmp);

            }

            tcg_temp_free_i32(tmp);

            break;

        case 0x0a:

            if (set_cc) {

                gen_helper_sub_cc(tmp, tmp, tmp2);

            }

            tcg_temp_free_i32(tmp);

            break;

        case 0x0b:

            if (set_cc) {

                gen_helper_add_cc(tmp, tmp, tmp2);

            }

            tcg_temp_free_i32(tmp);

            break;

        case 0x0c:

            tcg_gen_or_i32(tmp, tmp, tmp2);

            if (logic_cc) {

                gen_logic_CC(tmp);

            }

            store_reg_bx(env, s, rd, tmp);

            break;

        case 0x0d:

            if (logic_cc && rd == 15) {

                /* MOVS r15, ... is used for exception return.  */

                if (IS_USER(s)) {

                    goto illegal_op;

                }

                gen_exception_return(s, tmp2);

            } else {

                if (logic_cc) {

                    gen_logic_CC(tmp2);

                }

                store_reg_bx(env, s, rd, tmp2);

            }

            break;

        case 0x0e:

            tcg_gen_andc_i32(tmp, tmp, tmp2);

            if (logic_cc) {

                gen_logic_CC(tmp);

            }

            store_reg_bx(env, s, rd, tmp);

            break;

        default:

        case 0x0f:

            tcg_gen_not_i32(tmp2, tmp2);

            if (logic_cc) {

                gen_logic_CC(tmp2);

            }

            store_reg_bx(env, s, rd, tmp2);

            break;

        }

        if (op1 != 0x0f && op1 != 0x0d) {

            tcg_temp_free_i32(tmp2);

        }

    } else {

        /* other instructions */

        op1 = (insn >> 24) & 0xf;

        switch(op1) {

        case 0x0:

        case 0x1:

            /* multiplies, extra load/stores */

            sh = (insn >> 5) & 3;

            if (sh == 0) {

                if (op1 == 0x0) {

                    rd = (insn >> 16) & 0xf;

                    rn = (insn >> 12) & 0xf;

                    rs = (insn >> 8) & 0xf;

                    rm = (insn) & 0xf;

                    op1 = (insn >> 20) & 0xf;

                    switch (op1) {

                    case 0: case 1: case 2: case 3: case 6:

                        /* 32 bit mul */

                        tmp = load_reg(s, rs);

                        tmp2 = load_reg(s, rm);

                        tcg_gen_mul_i32(tmp, tmp, tmp2);

                        tcg_temp_free_i32(tmp2);

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

                            /* Subtract (mls) */

                            ARCH(6T2);

                            tmp2 = load_reg(s, rn);

                            tcg_gen_sub_i32(tmp, tmp2, tmp);

                            tcg_temp_free_i32(tmp2);

                        } else if (insn & (1 << 21)) {

                            /* Add */

                            tmp2 = load_reg(s, rn);

                            tcg_gen_add_i32(tmp, tmp, tmp2);

                            tcg_temp_free_i32(tmp2);

                        }

                        if (insn & (1 << 20))

                            gen_logic_CC(tmp);

                        store_reg(s, rd, tmp);

                        break;

                    case 4:

                        /* 64 bit mul double accumulate (UMAAL) */

                        ARCH(6);

                        tmp = load_reg(s, rs);

                        tmp2 = load_reg(s, rm);

                        tmp64 = gen_mulu_i64_i32(tmp, tmp2);

                        gen_addq_lo(s, tmp64, rn);

                        gen_addq_lo(s, tmp64, rd);

                        gen_storeq_reg(s, rn, rd, tmp64);

                        tcg_temp_free_i64(tmp64);

                        break;

                    case 8: case 9: case 10: case 11:

                    case 12: case 13: case 14: case 15:

                        /* 64 bit mul: UMULL, UMLAL, SMULL, SMLAL. */

                        tmp = load_reg(s, rs);

                        tmp2 = load_reg(s, rm);

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

                            tmp64 = gen_muls_i64_i32(tmp, tmp2);

                        } else {

                            tmp64 = gen_mulu_i64_i32(tmp, tmp2);

                        }

                        if (insn & (1 << 21)) { /* mult accumulate */

                            gen_addq(s, tmp64, rn, rd);

                        }

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

                            gen_logicq_cc(tmp64);

                        }

                        gen_storeq_reg(s, rn, rd, tmp64);

                        tcg_temp_free_i64(tmp64);

                        break;

                    default:

                        goto illegal_op;

                    }

                } else {

                    rn = (insn >> 16) & 0xf;

                    rd = (insn >> 12) & 0xf;

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

                        /* load/store exclusive */

                        op1 = (insn >> 21) & 0x3;

                        if (op1)

                            ARCH(6K);

                        else

                            ARCH(6);

                        addr = tcg_temp_local_new_i32();

                        load_reg_var(s, addr, rn);

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

                            switch (op1) {

                            case 0: /* ldrex */

                                gen_load_exclusive(s, rd, 15, addr, 2);

                                break;

                            case 1: /* ldrexd */

                                gen_load_exclusive(s, rd, rd + 1, addr, 3);

                                break;

                            case 2: /* ldrexb */

                                gen_load_exclusive(s, rd, 15, addr, 0);

                                break;

                            case 3: /* ldrexh */

                                gen_load_exclusive(s, rd, 15, addr, 1);

                                break;

                            default:

                                abort();

                            }

                        } else {

                            rm = insn & 0xf;

                            switch (op1) {

                            case 0:  /*  strex */

                                gen_store_exclusive(s, rd, rm, 15, addr, 2);

                                break;

                            case 1: /*  strexd */

                                gen_store_exclusive(s, rd, rm, rm + 1, addr, 3);

                                break;

                            case 2: /*  strexb */

                                gen_store_exclusive(s, rd, rm, 15, addr, 0);

                                break;

                            case 3: /* strexh */

                                gen_store_exclusive(s, rd, rm, 15, addr, 1);

                                break;

                            default:

                                abort();

                            }

                        }

                        tcg_temp_free(addr);

                    } else {

                        /* SWP instruction */

                        rm = (insn) & 0xf;

                        /* ??? This is not really atomic.  However we know

                           we never have multiple CPUs running in parallel,

                           so it is good enough.  */

                        addr = load_reg(s, rn);

                        tmp = load_reg(s, rm);

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

                            tmp2 = gen_ld8u(addr, IS_USER(s));

                            gen_st8(tmp, addr, IS_USER(s));

                        } else {

                            tmp2 = gen_ld32(addr, IS_USER(s));

                            gen_st32(tmp, addr, IS_USER(s));

                        }

                        tcg_temp_free_i32(addr);

                        store_reg(s, rd, tmp2);

                    }

                }

            } else {

                int address_offset;

                int load;

                /* Misc load/store */

                rn = (insn >> 16) & 0xf;

                rd = (insn >> 12) & 0xf;

                addr = load_reg(s, rn);

                if (insn & (1 << 24))

                    gen_add_datah_offset(s, insn, 0, addr);

                address_offset = 0;

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

                    /* load */

                    switch(sh) {

                    case 1:

                        tmp = gen_ld16u(addr, IS_USER(s));

                        break;

                    case 2:

                        tmp = gen_ld8s(addr, IS_USER(s));

                        break;

                    default:

                    case 3:

                        tmp = gen_ld16s(addr, IS_USER(s));

                        break;

                    }

                    load = 1;

                } else if (sh & 2) {

                    /* doubleword */

                    if (sh & 1) {

                        /* store */

                        tmp = load_reg(s, rd);

                        gen_st32(tmp, addr, IS_USER(s));

                        tcg_gen_addi_i32(addr, addr, 4);

                        tmp = load_reg(s, rd + 1);

                        gen_st32(tmp, addr, IS_USER(s));

                        load = 0;

                    } else {

                        /* load */

                        tmp = gen_ld32(addr, IS_USER(s));

                        store_reg(s, rd, tmp);

                        tcg_gen_addi_i32(addr, addr, 4);

                        tmp = gen_ld32(addr, IS_USER(s));

                        rd++;

                        load = 1;

                    }

                    address_offset = -4;

                } else {

                    /* store */

                    tmp = load_reg(s, rd);

                    gen_st16(tmp, addr, IS_USER(s));

                    load = 0;

                }

                /* Perform base writeback before the loaded value to

                   ensure correct behavior with overlapping index registers.

                   ldrd with base writeback is is undefined if the

                   destination and index registers overlap.  */

                if (!(insn & (1 << 24))) {

                    gen_add_datah_offset(s, insn, address_offset, addr);

                    store_reg(s, rn, addr);

                } else if (insn & (1 << 21)) {

                    if (address_offset)

                        tcg_gen_addi_i32(addr, addr, address_offset);

                    store_reg(s, rn, addr);

                } else {

                    tcg_temp_free_i32(addr);

                }

                if (load) {

                    /* Complete the load.  */

                    store_reg(s, rd, tmp);

                }

            }

            break;

        case 0x4:

        case 0x5:

            goto do_ldst;

        case 0x6:

        case 0x7:

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

                ARCH(6);

                /* Armv6 Media instructions.  */

                rm = insn & 0xf;

                rn = (insn >> 16) & 0xf;

                rd = (insn >> 12) & 0xf;

                rs = (insn >> 8) & 0xf;

                switch ((insn >> 23) & 3) {

                case 0: /* Parallel add/subtract.  */

                    op1 = (insn >> 20) & 7;

                    tmp = load_reg(s, rn);

                    tmp2 = load_reg(s, rm);

                    sh = (insn >> 5) & 7;

                    if ((op1 & 3) == 0 || sh == 5 || sh == 6)

                        goto illegal_op;

                    gen_arm_parallel_addsub(op1, sh, tmp, tmp2);

                    tcg_temp_free_i32(tmp2);

                    store_reg(s, rd, tmp);

                    break;

                case 1:

                    if ((insn & 0x00700020) == 0) {

                        /* Halfword pack.  */

                        tmp = load_reg(s, rn);

                        tmp2 = load_reg(s, rm);

                        shift = (insn >> 7) & 0x1f;

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

                            /* pkhtb */

                            if (shift == 0)

                                shift = 31;

                            tcg_gen_sari_i32(tmp2, tmp2, shift);

                            tcg_gen_andi_i32(tmp, tmp, 0xffff0000);

                            tcg_gen_ext16u_i32(tmp2, tmp2);

                        } else {

                            /* pkhbt */

                            if (shift)

                                tcg_gen_shli_i32(tmp2, tmp2, shift);

                            tcg_gen_ext16u_i32(tmp, tmp);

                            tcg_gen_andi_i32(tmp2, tmp2, 0xffff0000);

                        }

                        tcg_gen_or_i32(tmp, tmp, tmp2);

                        tcg_temp_free_i32(tmp2);

                        store_reg(s, rd, tmp);

                    } else if ((insn & 0x00200020) == 0x00200000) {

                        /* [us]sat */

                        tmp = load_reg(s, rm);

                        shift = (insn >> 7) & 0x1f;

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

                            if (shift == 0)

                                shift = 31;

                            tcg_gen_sari_i32(tmp, tmp, shift);

                        } else {

                            tcg_gen_shli_i32(tmp, tmp, shift);

                        }

                        sh = (insn >> 16) & 0x1f;

                        tmp2 = tcg_const_i32(sh);

                        if (insn & (1 << 22))

                          gen_helper_usat(tmp, tmp, tmp2);

                        else

                          gen_helper_ssat(tmp, tmp, tmp2);

                        tcg_temp_free_i32(tmp2);

                        store_reg(s, rd, tmp);

                    } else if ((insn & 0x00300fe0) == 0x00200f20) {

                        /* [us]sat16 */

                        tmp = load_reg(s, rm);

                        sh = (insn >> 16) & 0x1f;

                        tmp2 = tcg_const_i32(sh);

                        if (insn & (1 << 22))

                          gen_helper_usat16(tmp, tmp, tmp2);

                        else

                          gen_helper_ssat16(tmp, tmp, tmp2);

                        tcg_temp_free_i32(tmp2);

                        store_reg(s, rd, tmp);

                    } else if ((insn & 0x00700fe0) == 0x00000fa0) {

                        /* Select bytes.  */

                        tmp = load_reg(s, rn);

                        tmp2 = load_reg(s, rm);

                        tmp3 = tcg_temp_new_i32();

                        tcg_gen_ld_i32(tmp3, cpu_env, offsetof(CPUState, GE));

                        gen_helper_sel_flags(tmp, tmp3, tmp, tmp2);

                        tcg_temp_free_i32(tmp3);

                        tcg_temp_free_i32(tmp2);

                        store_reg(s, rd, tmp);

                    } else if ((insn & 0x000003e0) == 0x00000060) {

                        tmp = load_reg(s, rm);

                        shift = (insn >> 10) & 3;

                        /* ??? In many cases it's not neccessary to do a

                           rotate, a shift is sufficient.  */

                        if (shift != 0)

                            tcg_gen_rotri_i32(tmp, tmp, shift * 8);

                        op1 = (insn >> 20) & 7;

                        switch (op1) {

                        case 0: gen_sxtb16(tmp);  break;

                        case 2: gen_sxtb(tmp);    break;

                        case 3: gen_sxth(tmp);    break;

                        case 4: gen_uxtb16(tmp);  break;

                        case 6: gen_uxtb(tmp);    break;

                        case 7: gen_uxth(tmp);    break;

                        default: goto illegal_op;

                        }

                        if (rn != 15) {

                            tmp2 = load_reg(s, rn);

                            if ((op1 & 3) == 0) {

                                gen_add16(tmp, tmp2);

                            } else {

                                tcg_gen_add_i32(tmp, tmp, tmp2);

                                tcg_temp_free_i32(tmp2);

                            }

                        }

                        store_reg(s, rd, tmp);

                    } else if ((insn & 0x003f0f60) == 0x003f0f20) {

                        /* rev */

                        tmp = load_reg(s, rm);

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

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

                                gen_revsh(tmp);

                            } else {

                                ARCH(6T2);

                                gen_helper_rbit(tmp, tmp);

                            }

                        } else {

                            if (insn & (1 << 7))

                                gen_rev16(tmp);

                            else

                                tcg_gen_bswap32_i32(tmp, tmp);

                        }

                        store_reg(s, rd, tmp);

                    } else {

                        goto illegal_op;

                    }

                    break;

                case 2: /* Multiplies (Type 3).  */

                    tmp = load_reg(s, rm);

                    tmp2 = load_reg(s, rs);

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

                        /* Signed multiply most significant [accumulate].

                           (SMMUL, SMMLA, SMMLS) */

                        tmp64 = gen_muls_i64_i32(tmp, tmp2);

                        if (rd != 15) {

                            tmp = load_reg(s, rd);

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

                                tmp64 = gen_subq_msw(tmp64, tmp);

                            } else {

                                tmp64 = gen_addq_msw(tmp64, tmp);

                            }

                        }

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

                            tcg_gen_addi_i64(tmp64, tmp64, 0x80000000u);

                        }

                        tcg_gen_shri_i64(tmp64, tmp64, 32);

                        tmp = tcg_temp_new_i32();

                        tcg_gen_trunc_i64_i32(tmp, tmp64);

                        tcg_temp_free_i64(tmp64);

                        store_reg(s, rn, tmp);

                    } else {

                        if (insn & (1 << 5))

                            gen_swap_half(tmp2);

                        gen_smul_dual(tmp, tmp2);

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

                            /* This subtraction cannot overflow. */

                            tcg_gen_sub_i32(tmp, tmp, tmp2);

                        } else {

                            /* This addition cannot overflow 32 bits;

                             * however it may overflow considered as a signed

                             * operation, in which case we must set the Q flag.

                             */

                            gen_helper_add_setq(tmp, tmp, tmp2);

                        }

                        tcg_temp_free_i32(tmp2);

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

                            /* smlald, smlsld */

                            tmp64 = tcg_temp_new_i64();

                            tcg_gen_ext_i32_i64(tmp64, tmp);

                            tcg_temp_free_i32(tmp);

                            gen_addq(s, tmp64, rd, rn);

                            gen_storeq_reg(s, rd, rn, tmp64);

                            tcg_temp_free_i64(tmp64);

                        } else {

                            /* smuad, smusd, smlad, smlsd */

                            if (rd != 15)

                              {

                                tmp2 = load_reg(s, rd);

                                gen_helper_add_setq(tmp, tmp, tmp2);

                                tcg_temp_free_i32(tmp2);

                              }

                            store_reg(s, rn, tmp);

                        }

                    }

                    break;

                case 3:

                    op1 = ((insn >> 17) & 0x38) | ((insn >> 5) & 7);

                    switch (op1) {

                    case 0: /* Unsigned sum of absolute differences.  */

                        ARCH(6);

                        tmp = load_reg(s, rm);

                        tmp2 = load_reg(s, rs);

                        gen_helper_usad8(tmp, tmp, tmp2);

                        tcg_temp_free_i32(tmp2);

                        if (rd != 15) {

                            tmp2 = load_reg(s, rd);

                            tcg_gen_add_i32(tmp, tmp, tmp2);

                            tcg_temp_free_i32(tmp2);

                        }

                        store_reg(s, rn, tmp);

                        break;

                    case 0x20: case 0x24: case 0x28: case 0x2c:

                        /* Bitfield insert/clear.  */

                        ARCH(6T2);

                        shift = (insn >> 7) & 0x1f;

                        i = (insn >> 16) & 0x1f;

                        i = i + 1 - shift;

                        if (rm == 15) {

                            tmp = tcg_temp_new_i32();

                            tcg_gen_movi_i32(tmp, 0);

                        } else {

                            tmp = load_reg(s, rm);

                        }

                        if (i != 32) {

                            tmp2 = load_reg(s, rd);

                            gen_bfi(tmp, tmp2, tmp, shift, (1u << i) - 1);

                            tcg_temp_free_i32(tmp2);

                        }

                        store_reg(s, rd, tmp);

                        break;

                    case 0x12: case 0x16: case 0x1a: case 0x1e: /* sbfx */

                    case 0x32: case 0x36: case 0x3a: case 0x3e: /* ubfx */

                        ARCH(6T2);

                        tmp = load_reg(s, rm);

                        shift = (insn >> 7) & 0x1f;

                        i = ((insn >> 16) & 0x1f) + 1;

                        if (shift + i > 32)

                            goto illegal_op;

                        if (i < 32) {

                            if (op1 & 0x20) {

                                gen_ubfx(tmp, shift, (1u << i) - 1);

                            } else {

                                gen_sbfx(tmp, shift, i);

                            }

                        }

                        store_reg(s, rd, tmp);

                        break;

                    default:

                        goto illegal_op;

                    }

                    break;

                }

                break;

            }

        do_ldst:

            /* Check for undefined extension instructions

             * per the ARM Bible IE:

             * xxxx 0111 1111 xxxx  xxxx xxxx 1111 xxxx

             */

            sh = (0xf << 20) | (0xf << 4);

            if (op1 == 0x7 && ((insn & sh) == sh))

            {

                goto illegal_op;

            }

            /* load/store byte/word */

            rn = (insn >> 16) & 0xf;

            rd = (insn >> 12) & 0xf;

            tmp2 = load_reg(s, rn);

            i = (IS_USER(s) || (insn & 0x01200000) == 0x00200000);

            if (insn & (1 << 24))

                gen_add_data_offset(s, insn, tmp2);

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

                /* load */

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

                    tmp = gen_ld8u(tmp2, i);

                } else {

                    tmp = gen_ld32(tmp2, i);

                }

            } else {

                /* store */

                tmp = load_reg(s, rd);

                if (insn & (1 << 22))

                    gen_st8(tmp, tmp2, i);

                else

                    gen_st32(tmp, tmp2, i);

            }

            if (!(insn & (1 << 24))) {

                gen_add_data_offset(s, insn, tmp2);

                store_reg(s, rn, tmp2);

            } else if (insn & (1 << 21)) {

                store_reg(s, rn, tmp2);

            } else {

                tcg_temp_free_i32(tmp2);

            }

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

                /* Complete the load.  */

                if (rd == 15)

                    gen_bx(s, tmp);

                else

                    store_reg(s, rd, tmp);

            }

            break;

        case 0x08:

        case 0x09:

            {

                int j, n, user, loaded_base;

                TCGv loaded_var;

                /* load/store multiple words */

                /* XXX: store correct base if write back */

                user = 0;

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

                    if (IS_USER(s))

                        goto illegal_op; /* only usable in supervisor mode */

                    if ((insn & (1 << 15)) == 0)

                        user = 1;

                }

                rn = (insn >> 16) & 0xf;

                addr = load_reg(s, rn);

                /* compute total size */

                loaded_base = 0;

                TCGV_UNUSED(loaded_var);

                n = 0;

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

                    if (insn & (1 << i))

                        n++;

                }

                /* XXX: test invalid n == 0 case ? */

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

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

                        /* pre increment */

                        tcg_gen_addi_i32(addr, addr, 4);

                    } else {

                        /* post increment */

                    }

                } else {

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

                        /* pre decrement */

                        tcg_gen_addi_i32(addr, addr, -(n * 4));

                    } else {

                        /* post decrement */

                        if (n != 1)

                        tcg_gen_addi_i32(addr, addr, -((n - 1) * 4));

                    }

                }

                j = 0;

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

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

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

                            /* load */

                            tmp = gen_ld32(addr, IS_USER(s));

                            if (i == 15) {

                                gen_bx(s, tmp);

                            } else if (user) {

                                tmp2 = tcg_const_i32(i);

                                gen_helper_set_user_reg(tmp2, tmp);

                                tcg_temp_free_i32(tmp2);

                                tcg_temp_free_i32(tmp);

                            } else if (i == rn) {

                                loaded_var = tmp;

                                loaded_base = 1;

                            } else {

                                store_reg(s, i, tmp);

                            }

                        } else {

                            /* store */

                            if (i == 15) {

                                /* special case: r15 = PC + 8 */

                                val = (long)s->pc + 4;

                                tmp = tcg_temp_new_i32();

                                tcg_gen_movi_i32(tmp, val);

                            } else if (user) {

                                tmp = tcg_temp_new_i32();

                                tmp2 = tcg_const_i32(i);

                                gen_helper_get_user_reg(tmp, tmp2);

                                tcg_temp_free_i32(tmp2);

                            } else {

                                tmp = load_reg(s, i);

                            }

                            gen_st32(tmp, addr, IS_USER(s));

                        }

                        j++;

                        /* no need to add after the last transfer */

                        if (j != n)

                            tcg_gen_addi_i32(addr, addr, 4);

                    }

                }

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

                    /* write back */

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

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

                            /* pre increment */

                        } else {

                            /* post increment */

                            tcg_gen_addi_i32(addr, addr, 4);

                        }

                    } else {

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

                            /* pre decrement */

                            if (n != 1)

                                tcg_gen_addi_i32(addr, addr, -((n - 1) * 4));

                        } else {

                            /* post decrement */

                            tcg_gen_addi_i32(addr, addr, -(n * 4));

                        }

                    }

                    store_reg(s, rn, addr);

                } else {

                    tcg_temp_free_i32(addr);

                }

                if (loaded_base) {

                    store_reg(s, rn, loaded_var);

                }

                if ((insn & (1 << 22)) && !user) {

                    /* Restore CPSR from SPSR.  */

                    tmp = load_cpu_field(spsr);

                    gen_set_cpsr(tmp, 0xffffffff);

                    tcg_temp_free_i32(tmp);

                    s->is_jmp = DISAS_UPDATE;

                }

            }

            break;

        case 0xa:

        case 0xb:

            {

                int32_t offset;

                /* branch (and link) */

                val = (int32_t)s->pc;

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

                    tmp = tcg_temp_new_i32();

                    tcg_gen_movi_i32(tmp, val);

                    store_reg(s, 14, tmp);

                }

                offset = (((int32_t)insn << 8) >> 8);

                val += (offset << 2) + 4;

                gen_jmp(s, val);

            }

            break;

        case 0xc:

        case 0xd:

        case 0xe:

            /* Coprocessor.  */

            if (disas_coproc_insn(env, s, insn))

                goto illegal_op;

            break;

        case 0xf:

            /* swi */

            gen_set_pc_im(s->pc);

            s->is_jmp = DISAS_SWI;

            break;

        default:

        illegal_op:

            gen_exception_insn(s, 4, EXCP_UDEF);

            break;

        }

    }

}


static int ppc_hash64_translate(CPUPPCState *env, struct mmu_ctx_hash64 *ctx,

                                target_ulong eaddr, int rwx)

{

    int ret;

    ppc_slb_t *slb;

    hwaddr pte_offset;

    ppc_hash_pte64_t pte;

    int target_page_bits;

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

    /* 1. Handle real mode accesses */

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

        /* Translation is off */

        /* In real mode the top 4 effective address bits are ignored */

        ctx->raddr = eaddr & 0x0FFFFFFFFFFFFFFFULL;

        ctx->prot = PAGE_READ | PAGE_EXEC | PAGE_WRITE;

        return 0;

    }

    /* 2. Translation is on, so look up the SLB */

    slb = slb_lookup(env, eaddr);

    if (!slb) {

        return -5;

    }

    /* 3. Check for segment level no-execute violation */

    if ((rwx == 2) && (slb->vsid & SLB_VSID_N)) {

        return -3;

    }

    /* 4. Locate the PTE in the hash table */

    pte_offset = ppc_hash64_htab_lookup(env, slb, eaddr, &pte);

    if (pte_offset == -1) {

        return -1;

    }

    LOG_MMU("found PTE at offset %08" HWADDR_PRIx "\n", pte_offset);

    /* 5. Check access permissions */

    ctx->key = !!(msr_pr ? (slb->vsid & SLB_VSID_KP)

                  : (slb->vsid & SLB_VSID_KS));

    int access, pp;

    bool nx;

    pp = (pte.pte1 & HPTE64_R_PP) | ((pte.pte1 & HPTE64_R_PP0) >> 61);

    /* No execute if either noexec or guarded bits set */

    nx = (pte.pte1 & HPTE64_R_N) || (pte.pte1 & HPTE64_R_G);

    /* Compute access rights */

    access = ppc_hash64_pp_check(ctx->key, pp, nx);

    /* Keep the matching PTE informations */

    ctx->raddr = pte.pte1;

    ctx->prot = access;

    ret = ppc_hash64_check_prot(ctx->prot, rwx);

    if (ret) {

        /* Access right violation */

        LOG_MMU("PTE access rejected\n");

        return ret;

    }

    LOG_MMU("PTE access granted !\n");

    /* 6. Update PTE referenced and changed bits if necessary */

    if (ppc_hash64_pte_update_flags(ctx, &pte.pte1, ret, rwx) == 1) {

        ppc_hash64_store_hpte1(env, pte_offset, pte.pte1);

    }

    /* We have a TLB that saves 4K pages, so let's

     * split a huge page to 4k chunks */

    target_page_bits = (slb->vsid & SLB_VSID_L)

        ? TARGET_PAGE_BITS_16M : TARGET_PAGE_BITS;

    if (target_page_bits != TARGET_PAGE_BITS) {

        ctx->raddr |= (eaddr & ((1 << target_page_bits) - 1))

                      & TARGET_PAGE_MASK;

    }

    return ret;

}


void pc_basic_device_init(ISABus *isa_bus, qemu_irq *gsi,

                          ISADevice **rtc_state,

                          ISADevice **floppy,

                          bool no_vmport)

{

    int i;

    DriveInfo *fd[MAX_FD];

    DeviceState *hpet = NULL;

    int pit_isa_irq = 0;

    qemu_irq pit_alt_irq = NULL;

    qemu_irq rtc_irq = NULL;

    qemu_irq *a20_line;

    ISADevice *i8042, *port92, *vmmouse, *pit;

    qemu_irq *cpu_exit_irq;

    register_ioport_write(0x80, 1, 1, ioport80_write, NULL);

    register_ioport_write(0xf0, 1, 1, ioportF0_write, NULL);

    /*

     * Check if an HPET shall be created.

     *

     * Without KVM_CAP_PIT_STATE2, we cannot switch off the in-kernel PIT

     * when the HPET wants to take over. Thus we have to disable the latter.

     */

    if (!no_hpet && (!kvm_irqchip_in_kernel() || kvm_has_pit_state2())) {

        hpet = sysbus_try_create_simple("hpet", HPET_BASE, NULL);

        if (hpet) {

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

                sysbus_connect_irq(sysbus_from_qdev(hpet), i, gsi[i]);

            }

            pit_isa_irq = -1;

            pit_alt_irq = qdev_get_gpio_in(hpet, HPET_LEGACY_PIT_INT);

            rtc_irq = qdev_get_gpio_in(hpet, HPET_LEGACY_RTC_INT);

        }

    }

    *rtc_state = rtc_init(isa_bus, 2000, rtc_irq);

    qemu_register_boot_set(pc_boot_set, *rtc_state);

    if (kvm_irqchip_in_kernel()) {

        pit = kvm_pit_init(isa_bus, 0x40);

    } else {

        pit = pit_init(isa_bus, 0x40, pit_isa_irq, pit_alt_irq);

    }

    if (hpet) {

        /* connect PIT to output control line of the HPET */

        qdev_connect_gpio_out(hpet, 0, qdev_get_gpio_in(&pit->qdev, 0));

    }

    pcspk_init(isa_bus, pit);

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

        if (serial_hds[i]) {

            serial_isa_init(isa_bus, i, serial_hds[i]);

        }

    }

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

        if (parallel_hds[i]) {

            parallel_init(isa_bus, i, parallel_hds[i]);

        }

    }

    a20_line = qemu_allocate_irqs(handle_a20_line_change, first_cpu, 2);

    i8042 = isa_create_simple(isa_bus, "i8042");

    i8042_setup_a20_line(i8042, &a20_line[0]);

    if (!no_vmport) {

        vmport_init(isa_bus);

        vmmouse = isa_try_create(isa_bus, "vmmouse");

    } else {

        vmmouse = NULL;

    }

    if (vmmouse) {

        qdev_prop_set_ptr(&vmmouse->qdev, "ps2_mouse", i8042);

        qdev_init_nofail(&vmmouse->qdev);

    }

    port92 = isa_create_simple(isa_bus, "port92");

    port92_init(port92, &a20_line[1]);

    cpu_exit_irq = qemu_allocate_irqs(cpu_request_exit, NULL, 1);

    DMA_init(0, cpu_exit_irq);

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

        fd[i] = drive_get(IF_FLOPPY, 0, i);

    }

    *floppy = fdctrl_init_isa(isa_bus, fd);

}


void stream_start(BlockDriverState *bs, BlockDriverState *base,

                  const char *base_id, BlockDriverCompletionFunc *cb,

                  void *opaque, Error **errp)

{

    StreamBlockJob *s;

    Coroutine *co;

    s = block_job_create(&stream_job_type, bs, cb, opaque, errp);

    if (!s) {

        return;

    }

    s->base = base;

    if (base_id) {

        pstrcpy(s->backing_file_id, sizeof(s->backing_file_id), base_id);

    }

    co = qemu_coroutine_create(stream_run);

    trace_stream_start(bs, base, s, co, opaque);

    qemu_coroutine_enter(co, s);

}