int ff_copy_whitelists(AVFormatContext *dst, AVFormatContext *src) { av_assert0(!dst->codec_whitelist && !dst->format_whitelist); dst-> codec_whitelist = av_strdup(src->codec_whitelist); dst->format_whitelist = av_strdup(src->format_whitelist); if ( (src-> codec_whitelist && !dst-> codec_whitelist) || (src->format_whitelist && !dst->format_whitelist)) { av_log(dst, AV_LOG_ERROR, "Failed to duplicate whitelist\n"); return AVERROR(ENOMEM); } return 0; }


static void init_dequant4_coeff_table(H264Context *h){ int i,j,q,x; const int transpose = (h->h264dsp.h264_idct_add != ff_h264_idct_add_c); //FIXME ugly for(i=0; i<6; i++ ){ h->dequant4_coeff[i] = h->dequant4_buffer[i]; for(j=0; j<i; j++){ if(!memcmp(h->pps.scaling_matrix4[j], h->pps.scaling_matrix4[i], 16*sizeof(uint8_t))){ h->dequant4_coeff[i] = h->dequant4_buffer[j]; break; } } if(j<i) continue; for(q=0; q<52; q++){ int shift = div6[q] + 2; int idx = rem6[q]; for(x=0; x<16; x++) h->dequant4_coeff[i][q][transpose ? (x>>2)|((x<<2)&0xF) : x] = ((uint32_t)dequant4_coeff_init[idx][(x&1) + ((x>>2)&1)] * h->pps.scaling_matrix4[i][x]) << shift; } } }


static int mpeg_mux_write_packet(AVFormatContext *ctx, AVPacket *pkt) { MpegMuxContext *s = ctx->priv_data; int stream_index= pkt->stream_index; int size= pkt->size; uint8_t *buf= pkt->data; AVStream *st = ctx->streams[stream_index]; StreamInfo *stream = st->priv_data; int64_t pts, dts, new_start_pts, new_start_dts; int len, avail_size; //XXX/FIXME this is and always was broken // compute_pts_dts(st, &pts, &dts, pkt->pts); pts= pkt->pts; dts= pkt->dts; if(s->is_svcd) { /* offset pts and dts slightly into the future to be able to do the compatibility fix below.*/ pts = (pts + 2) & ((1LL << 33) - 1); dts = (dts + 2) & ((1LL << 33) - 1); if (stream->packet_number == 0 && dts == pts) /* For the very first packet we want to force the DTS to be included. This increases compatibility with lots of DVD players. Since the MPEG-2 standard mandates that DTS is only written when it is different from PTS we have to move it slightly into the past.*/ dts = (dts - 2) & ((1LL << 33) - 1); } if(s->is_vcd) { /* We have to offset the PTS, so that it is consistent with the SCR. SCR starts at 36000, but the first two packs contain only padding and the first pack from the other stream, respectively, may also have been written before. So the real data starts at SCR 36000+3*1200. */ pts = (pts + 36000 + 3600) & ((1LL << 33) - 1); dts = (dts + 36000 + 3600) & ((1LL << 33) - 1); } #if 0 update_scr(ctx,stream_index,pts); printf("%d: pts=%0.3f dts=%0.3f scr=%0.3f\n", stream_index, pts / 90000.0, dts / 90000.0, s->last_scr / 90000.0); #endif /* we assume here that pts != AV_NOPTS_VALUE */ new_start_pts = stream->start_pts; new_start_dts = stream->start_dts; if (stream->start_pts == AV_NOPTS_VALUE) { new_start_pts = pts; new_start_dts = dts; } avail_size = get_packet_payload_size(ctx, stream_index, new_start_pts, new_start_dts); if (stream->buffer_ptr >= avail_size) { update_scr(ctx,stream_index,stream->start_pts); /* unlikely case: outputing the pts or dts increase the packet size so that we cannot write the start of the next packet. In this case, we must flush the current packet with padding. Note: this always happens for the first audio and video packet in a VCD file, since they do not carry any data.*/ flush_packet(ctx, stream_index, stream->start_pts, stream->start_dts, s->last_scr); stream->buffer_ptr = 0; } stream->start_pts = new_start_pts; stream->start_dts = new_start_dts; stream->nb_frames++; if (stream->frame_start_offset == 0) stream->frame_start_offset = stream->buffer_ptr; while (size > 0) { avail_size = get_packet_payload_size(ctx, stream_index, stream->start_pts, stream->start_dts); len = avail_size - stream->buffer_ptr; if (len > size) len = size; memcpy(stream->buffer + stream->buffer_ptr, buf, len); stream->buffer_ptr += len; buf += len; size -= len; if (stream->buffer_ptr >= avail_size) { update_scr(ctx,stream_index,stream->start_pts); /* if packet full, we send it now */ flush_packet(ctx, stream_index, stream->start_pts, stream->start_dts, s->last_scr); stream->buffer_ptr = 0; if (s->is_vcd) { /* Write one or more padding sectors, if necessary, to reach the constant overall bitrate.*/ int vcd_pad_bytes; while((vcd_pad_bytes = get_vcd_padding_size(ctx,stream->start_pts) ) >= s->packet_size) put_vcd_padding_sector(ctx); } /* Make sure only the FIRST pes packet for this frame has a timestamp */ stream->start_pts = AV_NOPTS_VALUE; stream->start_dts = AV_NOPTS_VALUE; } } return 0; }


SwsFilter *sws_getDefaultFilter(float lumaGBlur, float chromaGBlur, float lumaSharpen, float chromaSharpen, float chromaHShift, float chromaVShift, int verbose) { SwsFilter *filter = av_malloc(sizeof(SwsFilter)); if (!filter) return NULL; if (lumaGBlur != 0.0) { filter->lumH = sws_getGaussianVec(lumaGBlur, 3.0); filter->lumV = sws_getGaussianVec(lumaGBlur, 3.0); } else { filter->lumH = sws_getIdentityVec(); filter->lumV = sws_getIdentityVec(); } if (chromaGBlur != 0.0) { filter->chrH = sws_getGaussianVec(chromaGBlur, 3.0); filter->chrV = sws_getGaussianVec(chromaGBlur, 3.0); } else { filter->chrH = sws_getIdentityVec(); filter->chrV = sws_getIdentityVec(); } if (!filter->lumH || !filter->lumV || !filter->chrH || !filter->chrV) { sws_freeVec(filter->lumH); sws_freeVec(filter->lumV); sws_freeVec(filter->chrH); sws_freeVec(filter->chrV); av_freep(&filter); return NULL; } if (chromaSharpen != 0.0) { SwsVector *id = sws_getIdentityVec(); sws_scaleVec(filter->chrH, -chromaSharpen); sws_scaleVec(filter->chrV, -chromaSharpen); sws_addVec(filter->chrH, id); sws_addVec(filter->chrV, id); sws_freeVec(id); } if (lumaSharpen != 0.0) { SwsVector *id = sws_getIdentityVec(); sws_scaleVec(filter->lumH, -lumaSharpen); sws_scaleVec(filter->lumV, -lumaSharpen); sws_addVec(filter->lumH, id); sws_addVec(filter->lumV, id); sws_freeVec(id); } if (chromaHShift != 0.0) sws_shiftVec(filter->chrH, (int)(chromaHShift + 0.5)); if (chromaVShift != 0.0) sws_shiftVec(filter->chrV, (int)(chromaVShift + 0.5)); sws_normalizeVec(filter->chrH, 1.0); sws_normalizeVec(filter->chrV, 1.0); sws_normalizeVec(filter->lumH, 1.0); sws_normalizeVec(filter->lumV, 1.0); if (verbose) sws_printVec2(filter->chrH, NULL, AV_LOG_DEBUG); if (verbose) sws_printVec2(filter->lumH, NULL, AV_LOG_DEBUG); return filter; }


static int decode_frame(AVCodecContext * avctx, void *data, int *data_size, AVPacket *avpkt) { const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; MPADecodeContext *s = avctx->priv_data; uint32_t header; int out_size; OUT_INT *out_samples = data; if (buf_size < HEADER_SIZE) return AVERROR_INVALIDDATA; header = AV_RB32(buf); if (ff_mpa_check_header(header) < 0) { av_log(avctx, AV_LOG_ERROR, "Header missing\n"); return AVERROR_INVALIDDATA; } if (avpriv_mpegaudio_decode_header((MPADecodeHeader *)s, header) == 1) { /* free format: prepare to compute frame size */ s->frame_size = -1; return AVERROR_INVALIDDATA; } /* update codec info */ avctx->channels = s->nb_channels; avctx->channel_layout = s->nb_channels == 1 ? AV_CH_LAYOUT_MONO : AV_CH_LAYOUT_STEREO; if (!avctx->bit_rate) avctx->bit_rate = s->bit_rate; avctx->sub_id = s->layer; if (*data_size < 1152 * avctx->channels * sizeof(OUT_INT)) return AVERROR(EINVAL); *data_size = 0; if (s->frame_size <= 0 || s->frame_size > buf_size) { av_log(avctx, AV_LOG_ERROR, "incomplete frame\n"); return AVERROR_INVALIDDATA; } else if (s->frame_size < buf_size) { av_log(avctx, AV_LOG_ERROR, "incorrect frame size\n"); buf_size= s->frame_size; } out_size = mp_decode_frame(s, out_samples, buf, buf_size); if (out_size >= 0) { *data_size = out_size; avctx->sample_rate = s->sample_rate; //FIXME maybe move the other codec info stuff from above here too } else { av_log(avctx, AV_LOG_ERROR, "Error while decoding MPEG audio frame.\n"); /* Only return an error if the bad frame makes up the whole packet. If there is more data in the packet, just consume the bad frame instead of returning an error, which would discard the whole packet. */ if (buf_size == avpkt->size) return out_size; } s->frame_size = 0; return buf_size; }


int load_flt_binary(struct linux_binprm * bprm, struct target_pt_regs * regs, struct image_info * info) { struct lib_info libinfo[MAX_SHARED_LIBS]; abi_ulong p = bprm->p; abi_ulong stack_len; abi_ulong start_addr; abi_ulong sp; int res; int i, j; memset(libinfo, 0, sizeof(libinfo)); /* * We have to add the size of our arguments to our stack size * otherwise it's too easy for users to create stack overflows * by passing in a huge argument list. And yes, we have to be * pedantic and include space for the argv/envp array as it may have * a lot of entries. */ stack_len = 0; for (i = 0; i < bprm->argc; ++i) { /* the argv strings */ stack_len += strlen(bprm->argv[i]); } for (i = 0; i < bprm->envc; ++i) { /* the envp strings */ stack_len += strlen(bprm->envp[i]); } stack_len += (bprm->argc + 1) * 4; /* the argv array */ stack_len += (bprm->envc + 1) * 4; /* the envp array */ res = load_flat_file(bprm, libinfo, 0, &stack_len); if (res > (unsigned long)-4096) return res; /* Update data segment pointers for all libraries */ for (i=0; i<MAX_SHARED_LIBS; i++) { if (libinfo[i].loaded) { abi_ulong p; p = libinfo[i].start_data; for (j=0; j<MAX_SHARED_LIBS; j++) { p -= 4; /* FIXME - handle put_user() failures */ if (put_user_ual(libinfo[j].loaded ? libinfo[j].start_data : UNLOADED_LIB, p)) return -EFAULT; } } } p = ((libinfo[0].start_brk + stack_len + 3) & ~3) - 4; DBG_FLT("p=%x\n", (int)p); /* Copy argv/envp. */ p = copy_strings(p, bprm->envc, bprm->envp); p = copy_strings(p, bprm->argc, bprm->argv); /* Align stack. */ sp = p & ~(abi_ulong)(sizeof(abi_ulong) - 1); /* Enforce final stack alignment of 16 bytes. This is sufficient for all current targets, and excess alignment is harmless. */ stack_len = bprm->envc + bprm->argc + 2; stack_len += 3; /* argc, arvg, argp */ stack_len *= sizeof(abi_ulong); if ((sp + stack_len) & 15) sp -= 16 - ((sp + stack_len) & 15); sp = loader_build_argptr(bprm->envc, bprm->argc, sp, p, 1); /* Fake some return addresses to ensure the call chain will * initialise library in order for us. We are required to call * lib 1 first, then 2, ... and finally the main program (id 0). */ start_addr = libinfo[0].entry; #ifdef CONFIG_BINFMT_SHARED_FLAT #error here for (i = MAX_SHARED_LIBS-1; i>0; i--) { if (libinfo[i].loaded) { /* Push previos first to call address */ --sp; if (put_user_ual(start_addr, sp)) return -EFAULT; start_addr = libinfo[i].entry; } } #endif /* Stash our initial stack pointer into the mm structure */ info->start_code = libinfo[0].start_code; info->end_code = libinfo[0].start_code = libinfo[0].text_len; info->start_data = libinfo[0].start_data; info->end_data = libinfo[0].end_data; info->start_brk = libinfo[0].start_brk; info->start_stack = sp; info->stack_limit = libinfo[0].start_brk; info->entry = start_addr; info->code_offset = info->start_code; info->data_offset = info->start_data - libinfo[0].text_len; DBG_FLT("start_thread(entry=0x%x, start_stack=0x%x)\n", (int)info->entry, (int)info->start_stack); return 0; }


static always_inline void gen_farith2 (void *helper, int rb, int rc) { if (unlikely(rc == 31)) return; if (rb != 31) tcg_gen_helper_1_1(helper, cpu_fir[rc], cpu_fir[rb]); else { TCGv tmp = tcg_const_i64(0); tcg_gen_helper_1_1(helper, cpu_fir[rc], tmp); tcg_temp_free(tmp); } }


static void qio_channel_socket_connect_worker(QIOTask *task, gpointer opaque) { QIOChannelSocket *ioc = QIO_CHANNEL_SOCKET(qio_task_get_source(task)); SocketAddress *addr = opaque; Error *err = NULL; qio_channel_socket_connect_sync(ioc, addr, &err); qio_task_set_error(task, err); }


void pxa27x_timer_init(target_phys_addr_t base, qemu_irq *irqs, qemu_irq irq4) { pxa2xx_timer_info *s = pxa2xx_timer_init(base, irqs); int i; s->freq = PXA27X_FREQ; s->tm4 = (PXA2xxTimer4 *) qemu_mallocz(8 * sizeof(PXA2xxTimer4)); for (i = 0; i < 8; i ++) { s->tm4[i].tm.value = 0; s->tm4[i].tm.irq = irq4; s->tm4[i].tm.info = s; s->tm4[i].tm.num = i + 4; s->tm4[i].tm.level = 0; s->tm4[i].freq = 0; s->tm4[i].control = 0x0; s->tm4[i].tm.qtimer = qemu_new_timer(vm_clock, pxa2xx_timer_tick4, &s->tm4[i]); } }


static void serial_init_core(SerialState *s) { if (!s->chr) { fprintf(stderr, "Can't create serial device, empty char device\n"); exit(1); } s->modem_status_poll = qemu_new_timer(vm_clock, (QEMUTimerCB *) serial_update_msl, s); s->fifo_timeout_timer = qemu_new_timer(vm_clock, (QEMUTimerCB *) fifo_timeout_int, s); s->transmit_timer = qemu_new_timer(vm_clock, (QEMUTimerCB *) serial_xmit, s); qemu_register_reset(serial_reset, s); serial_reset(s); qemu_chr_add_handlers(s->chr, serial_can_receive1, serial_receive1, serial_event, s); }


int bdrv_create_file(const char* filename, QEMUOptionParameter *options) { BlockDriver *drv; drv = bdrv_find_protocol(filename); if (drv == NULL) { drv = bdrv_find_format("file"); } return bdrv_create(drv, filename, options); }


int qemu_acl_append(qemu_acl *acl, int deny, const char *match) { qemu_acl_entry *entry; entry = qemu_malloc(sizeof(*entry)); entry->match = qemu_strdup(match); entry->deny = deny; TAILQ_INSERT_TAIL(&acl->entries, entry, next); acl->nentries++; return acl->nentries; }


void virtio_scsi_common_realize(DeviceState *dev, Error **errp, HandleOutput ctrl, HandleOutput evt, HandleOutput cmd) { VirtIODevice *vdev = VIRTIO_DEVICE(dev); VirtIOSCSICommon *s = VIRTIO_SCSI_COMMON(dev); int i; virtio_init(vdev, "virtio-scsi", VIRTIO_ID_SCSI, sizeof(VirtIOSCSIConfig)); if (s->conf.num_queues <= 0 || s->conf.num_queues > VIRTIO_PCI_QUEUE_MAX) { error_setg(errp, "Invalid number of queues (= %" PRId32 "), " "must be a positive integer less than %d.", s->conf.num_queues, VIRTIO_PCI_QUEUE_MAX); virtio_cleanup(vdev); return; } s->cmd_vqs = g_malloc0(s->conf.num_queues * sizeof(VirtQueue *)); s->sense_size = VIRTIO_SCSI_SENSE_SIZE; s->cdb_size = VIRTIO_SCSI_CDB_SIZE; s->ctrl_vq = virtio_add_queue(vdev, VIRTIO_SCSI_VQ_SIZE, ctrl); s->event_vq = virtio_add_queue(vdev, VIRTIO_SCSI_VQ_SIZE, evt); for (i = 0; i < s->conf.num_queues; i++) { s->cmd_vqs[i] = virtio_add_queue(vdev, VIRTIO_SCSI_VQ_SIZE, cmd); } if (s->conf.iothread) { virtio_scsi_set_iothread(VIRTIO_SCSI(s), s->conf.iothread); } }


static int write_elf32_load(DumpState *s, MemoryMapping *memory_mapping, int phdr_index, hwaddr offset) { Elf32_Phdr phdr; int ret; int endian = s->dump_info.d_endian; memset(&phdr, 0, sizeof(Elf32_Phdr)); phdr.p_type = cpu_convert_to_target32(PT_LOAD, endian); phdr.p_offset = cpu_convert_to_target32(offset, endian); phdr.p_paddr = cpu_convert_to_target32(memory_mapping->phys_addr, endian); if (offset == -1) { /* When the memory is not stored into vmcore, offset will be -1 */ phdr.p_filesz = 0; } else { phdr.p_filesz = cpu_convert_to_target32(memory_mapping->length, endian); } phdr.p_memsz = cpu_convert_to_target32(memory_mapping->length, endian); phdr.p_vaddr = cpu_convert_to_target32(memory_mapping->virt_addr, endian); ret = fd_write_vmcore(&phdr, sizeof(Elf32_Phdr), s); if (ret < 0) { dump_error(s, "dump: failed to write program header table.\n"); return -1; } return 0; }


static void qemu_laio_enqueue_completed(struct qemu_laio_state *s, struct qemu_laiocb* laiocb) { if (laiocb->async_context_id == get_async_context_id()) { qemu_laio_process_completion(s, laiocb); } else { QLIST_INSERT_HEAD(&s->completed_reqs, laiocb, node); } }


static inline void gen_goto_tb(DisasContext *s, int n, uint64_t dest) { TranslationBlock *tb; tb = s->tb; if (use_goto_tb(s, n, dest)) { tcg_gen_goto_tb(n); gen_a64_set_pc_im(dest); tcg_gen_exit_tb((intptr_t)tb + n); s->is_jmp = DISAS_TB_JUMP; } else { gen_a64_set_pc_im(dest); if (s->singlestep_enabled) { gen_exception_internal(EXCP_DEBUG); } tcg_gen_exit_tb(0); s->is_jmp = DISAS_JUMP; } }


static void gen_spr_BookE206(CPUPPCState *env, uint32_t mas_mask, uint32_t *tlbncfg) { #if !defined(CONFIG_USER_ONLY) const char *mas_names[8] = { "MAS0", "MAS1", "MAS2", "MAS3", "MAS4", "MAS5", "MAS6", "MAS7", }; int mas_sprn[8] = { SPR_BOOKE_MAS0, SPR_BOOKE_MAS1, SPR_BOOKE_MAS2, SPR_BOOKE_MAS3, SPR_BOOKE_MAS4, SPR_BOOKE_MAS5, SPR_BOOKE_MAS6, SPR_BOOKE_MAS7, }; int i; /* TLB assist registers */ /* XXX : not implemented */ for (i = 0; i < 8; i++) { if (mas_mask & (1 << i)) { spr_register(env, mas_sprn[i], mas_names[i], SPR_NOACCESS, SPR_NOACCESS, &spr_read_generic, &spr_write_generic, 0x00000000); } } if (env->nb_pids > 1) { /* XXX : not implemented */ spr_register(env, SPR_BOOKE_PID1, "PID1", SPR_NOACCESS, SPR_NOACCESS, &spr_read_generic, &spr_write_booke_pid, 0x00000000); } if (env->nb_pids > 2) { /* XXX : not implemented */ spr_register(env, SPR_BOOKE_PID2, "PID2", SPR_NOACCESS, SPR_NOACCESS, &spr_read_generic, &spr_write_booke_pid, 0x00000000); } /* XXX : not implemented */ spr_register(env, SPR_MMUCFG, "MMUCFG", SPR_NOACCESS, SPR_NOACCESS, &spr_read_generic, SPR_NOACCESS, 0x00000000); /* TOFIX */ switch (env->nb_ways) { case 4: spr_register(env, SPR_BOOKE_TLB3CFG, "TLB3CFG", SPR_NOACCESS, SPR_NOACCESS, &spr_read_generic, SPR_NOACCESS, tlbncfg[3]); /* Fallthru */ case 3: spr_register(env, SPR_BOOKE_TLB2CFG, "TLB2CFG", SPR_NOACCESS, SPR_NOACCESS, &spr_read_generic, SPR_NOACCESS, tlbncfg[2]); /* Fallthru */ case 2: spr_register(env, SPR_BOOKE_TLB1CFG, "TLB1CFG", SPR_NOACCESS, SPR_NOACCESS, &spr_read_generic, SPR_NOACCESS, tlbncfg[1]); /* Fallthru */ case 1: spr_register(env, SPR_BOOKE_TLB0CFG, "TLB0CFG", SPR_NOACCESS, SPR_NOACCESS, &spr_read_generic, SPR_NOACCESS, tlbncfg[0]); /* Fallthru */ case 0: default: break; } #endif gen_spr_usprgh(env); }


static void vnc_tight_start(VncState *vs) { buffer_reset(&vs->tight); // make the output buffer be the zlib buffer, so we can compress it later vs->tight_tmp = vs->output; vs->output = vs->tight; }


static void error_mem_write(void *opaque, target_phys_addr_t addr, uint64_t value, unsigned size) { abort(); }


build_tpm_tcpa(GArray *table_data, GArray *linker, GArray *tcpalog) { Acpi20Tcpa *tcpa = acpi_data_push(table_data, sizeof *tcpa); uint64_t log_area_start_address = acpi_data_len(tcpalog); tcpa->platform_class = cpu_to_le16(TPM_TCPA_ACPI_CLASS_CLIENT); tcpa->log_area_minimum_length = cpu_to_le32(TPM_LOG_AREA_MINIMUM_SIZE); tcpa->log_area_start_address = cpu_to_le64(log_area_start_address); bios_linker_loader_alloc(linker, ACPI_BUILD_TPMLOG_FILE, 1, false /* high memory */); /* log area start address to be filled by Guest linker */ bios_linker_loader_add_pointer(linker, ACPI_BUILD_TABLE_FILE, ACPI_BUILD_TPMLOG_FILE, table_data, &tcpa->log_area_start_address, sizeof(tcpa->log_area_start_address)); build_header(linker, table_data, (void *)tcpa, "TCPA", sizeof(*tcpa), 2, NULL); acpi_data_push(tcpalog, TPM_LOG_AREA_MINIMUM_SIZE); }


static void build_pci_bus_state_cleanup(AcpiBuildPciBusHotplugState *state) { build_free_array(state->device_table); build_free_array(state->notify_table); }


uint32_t HELPER(mvcle)(CPUS390XState *env, uint32_t r1, uint64_t a2, uint32_t r3) { uintptr_t ra = GETPC(); uint64_t destlen = get_length(env, r1 + 1); uint64_t dest = get_address(env, r1); uint64_t srclen = get_length(env, r3 + 1); uint64_t src = get_address(env, r3); uint8_t pad = a2 & 0xff; uint8_t v; uint32_t cc; if (destlen == srclen) { cc = 0; } else if (destlen < srclen) { cc = 1; } else { cc = 2; } if (srclen > destlen) { srclen = destlen; } for (; destlen && srclen; src++, dest++, destlen--, srclen--) { v = cpu_ldub_data_ra(env, src, ra); cpu_stb_data_ra(env, dest, v, ra); } for (; destlen; dest++, destlen--) { cpu_stb_data_ra(env, dest, pad, ra); } set_length(env, r1 + 1 , destlen); /* can't use srclen here, we trunc'ed it */ set_length(env, r3 + 1, env->regs[r3 + 1] - src - env->regs[r3]); set_address(env, r1, dest); set_address(env, r3, src); return cc; }


static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop) { target_long *stack = (void *)infop->start_stack; memset(regs, 0, sizeof(*regs)); regs->ARM_cpsr = 0x10; regs->ARM_pc = infop->entry; regs->ARM_sp = infop->start_stack; regs->ARM_r2 = tswapl(stack[2]); /* envp */ regs->ARM_r1 = tswapl(stack[1]); /* argv */ /* XXX: it seems that r0 is zeroed after ! */ // regs->ARM_r0 = tswapl(stack[0]); /* argc */ }


bool qemu_aio_wait(void) { AioHandler *node; fd_set rdfds, wrfds; int max_fd = -1; int ret; bool busy; /* * If there are callbacks left that have been queued, we need to call then. * Do not call select in this case, because it is possible that the caller * does not need a complete flush (as is the case for qemu_aio_wait loops). */ if (qemu_bh_poll()) { return true; } walking_handlers++; FD_ZERO(&rdfds); FD_ZERO(&wrfds); /* fill fd sets */ busy = false; QLIST_FOREACH(node, &aio_handlers, node) { /* If there aren't pending AIO operations, don't invoke callbacks. * Otherwise, if there are no AIO requests, qemu_aio_wait() would * wait indefinitely. */ if (node->io_flush) { if (node->io_flush(node->opaque) == 0) { continue; } busy = true; } if (!node->deleted && node->io_read) { FD_SET(node->fd, &rdfds); max_fd = MAX(max_fd, node->fd + 1); } if (!node->deleted && node->io_write) { FD_SET(node->fd, &wrfds); max_fd = MAX(max_fd, node->fd + 1); } } walking_handlers--; /* No AIO operations? Get us out of here */ if (!busy) { return false; } /* wait until next event */ ret = select(max_fd, &rdfds, &wrfds, NULL, NULL); /* if we have any readable fds, dispatch event */ if (ret > 0) { walking_handlers++; /* we have to walk very carefully in case * qemu_aio_set_fd_handler is called while we're walking */ node = QLIST_FIRST(&aio_handlers); while (node) { AioHandler *tmp; if (!node->deleted && FD_ISSET(node->fd, &rdfds) && node->io_read) { node->io_read(node->opaque); } if (!node->deleted && FD_ISSET(node->fd, &wrfds) && node->io_write) { node->io_write(node->opaque); } tmp = node; node = QLIST_NEXT(node, node); if (tmp->deleted) { QLIST_REMOVE(tmp, node); g_free(tmp); } } walking_handlers--; } return true; }


static uint64_t lsi_io_read(void *opaque, target_phys_addr_t addr, unsigned size) { LSIState *s = opaque; return lsi_reg_readb(s, addr & 0xff); }


static av_cold int pcx_encode_close(AVCodecContext *avctx) { av_frame_free(&avctx->coded_frame); return 0; }


static void fill_double_array(AVLFG *lfg, double *a, int len) { int i; double bmg[2], stddev = 10.0, mean = 0.0; for (i = 0; i < len; i += 2) { av_bmg_get(lfg, bmg); a[i] = bmg[0] * stddev + mean; a[i + 1] = bmg[1] * stddev + mean; } }


static void init_input_filter(FilterGraph *fg, AVFilterInOut *in) { InputStream *ist = NULL; enum AVMediaType type = avfilter_pad_get_type(in->filter_ctx->input_pads, in->pad_idx); int i; // TODO: support other filter types if (type != AVMEDIA_TYPE_VIDEO && type != AVMEDIA_TYPE_AUDIO) { av_log(NULL, AV_LOG_FATAL, "Only video and audio filters supported " "currently.\n"); exit(1); } if (in->name) { AVFormatContext *s; AVStream *st = NULL; char *p; int file_idx = strtol(in->name, &p, 0); if (file_idx < 0 || file_idx >= nb_input_files) { av_log(NULL, AV_LOG_FATAL, "Invalid file index %d in filtegraph description %s.\n", file_idx, fg->graph_desc); exit(1); } s = input_files[file_idx]->ctx; for (i = 0; i < s->nb_streams; i++) { if (s->streams[i]->codecpar->codec_type != type) continue; if (check_stream_specifier(s, s->streams[i], *p == ':' ? p + 1 : p) == 1) { st = s->streams[i]; break; } } if (!st) { av_log(NULL, AV_LOG_FATAL, "Stream specifier '%s' in filtergraph description %s " "matches no streams.\n", p, fg->graph_desc); exit(1); } ist = input_streams[input_files[file_idx]->ist_index + st->index]; } else { /* find the first unused stream of corresponding type */ for (i = 0; i < nb_input_streams; i++) { ist = input_streams[i]; if (ist->dec_ctx->codec_type == type && ist->discard) break; } if (i == nb_input_streams) { av_log(NULL, AV_LOG_FATAL, "Cannot find a matching stream for " "unlabeled input pad %d on filter %s\n", in->pad_idx, in->filter_ctx->name); exit(1); } } av_assert0(ist); ist->discard = 0; ist->decoding_needed = 1; ist->st->discard = AVDISCARD_NONE; GROW_ARRAY(fg->inputs, fg->nb_inputs); if (!(fg->inputs[fg->nb_inputs - 1] = av_mallocz(sizeof(*fg->inputs[0])))) exit(1); fg->inputs[fg->nb_inputs - 1]->ist = ist; fg->inputs[fg->nb_inputs - 1]->graph = fg; fg->inputs[fg->nb_inputs - 1]->format = -1; fg->inputs[fg->nb_inputs - 1]->frame_queue = av_fifo_alloc(8 * sizeof(AVFrame*)); if (!fg->inputs[fg->nb_inputs - 1]) exit_program(1); GROW_ARRAY(ist->filters, ist->nb_filters); ist->filters[ist->nb_filters - 1] = fg->inputs[fg->nb_inputs - 1]; }


static int ccid_handle_data(USBDevice *dev, USBPacket *p) { USBCCIDState *s = DO_UPCAST(USBCCIDState, dev, dev); int ret = 0; uint8_t *data = p->data; int len = p->len; switch (p->pid) { case USB_TOKEN_OUT: ret = ccid_handle_bulk_out(s, p); break; case USB_TOKEN_IN: switch (p->devep & 0xf) { case CCID_BULK_IN_EP: if (!len) { ret = USB_RET_NAK; } else { ret = ccid_bulk_in_copy_to_guest(s, data, len); } break; case CCID_INT_IN_EP: if (s->notify_slot_change) { /* page 56, RDR_to_PC_NotifySlotChange */ data[0] = CCID_MESSAGE_TYPE_RDR_to_PC_NotifySlotChange; data[1] = s->bmSlotICCState; ret = 2; s->notify_slot_change = false; s->bmSlotICCState &= ~SLOT_0_CHANGED_MASK; DPRINTF(s, D_INFO, "handle_data: int_in: notify_slot_change %X, " "requested len %d\n", s->bmSlotICCState, len); } break; default: DPRINTF(s, 1, "Bad endpoint\n"); break; } break; default: DPRINTF(s, 1, "Bad token\n"); ret = USB_RET_STALL; break; } return ret; }


static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc) { #define HAS_OPTION_BITS(opt) do { \ if (!option_bits_enabled(dc, opt)) { \ qemu_log("Option is not enabled %s:%d\n", \ __FILE__, __LINE__); \ goto invalid_opcode; \ } \ } while (0) #define HAS_OPTION(opt) HAS_OPTION_BITS(XTENSA_OPTION_BIT(opt)) #define TBD() qemu_log("TBD(pc = %08x): %s:%d\n", dc->pc, __FILE__, __LINE__) #define RESERVED() do { \ qemu_log("RESERVED(pc = %08x, %02x%02x%02x): %s:%d\n", \ dc->pc, b0, b1, b2, __FILE__, __LINE__); \ goto invalid_opcode; \ } while (0) #ifdef TARGET_WORDS_BIGENDIAN #define OP0 (((b0) & 0xf0) >> 4) #define OP1 (((b2) & 0xf0) >> 4) #define OP2 ((b2) & 0xf) #define RRR_R ((b1) & 0xf) #define RRR_S (((b1) & 0xf0) >> 4) #define RRR_T ((b0) & 0xf) #else #define OP0 (((b0) & 0xf)) #define OP1 (((b2) & 0xf)) #define OP2 (((b2) & 0xf0) >> 4) #define RRR_R (((b1) & 0xf0) >> 4) #define RRR_S (((b1) & 0xf)) #define RRR_T (((b0) & 0xf0) >> 4) #endif #define RRR_X ((RRR_R & 0x4) >> 2) #define RRR_Y ((RRR_T & 0x4) >> 2) #define RRR_W (RRR_R & 0x3) #define RRRN_R RRR_R #define RRRN_S RRR_S #define RRRN_T RRR_T #define RRI8_R RRR_R #define RRI8_S RRR_S #define RRI8_T RRR_T #define RRI8_IMM8 (b2) #define RRI8_IMM8_SE ((((b2) & 0x80) ? 0xffffff00 : 0) | RRI8_IMM8) #ifdef TARGET_WORDS_BIGENDIAN #define RI16_IMM16 (((b1) << 8) | (b2)) #else #define RI16_IMM16 (((b2) << 8) | (b1)) #endif #ifdef TARGET_WORDS_BIGENDIAN #define CALL_N (((b0) & 0xc) >> 2) #define CALL_OFFSET ((((b0) & 0x3) << 16) | ((b1) << 8) | (b2)) #else #define CALL_N (((b0) & 0x30) >> 4) #define CALL_OFFSET ((((b0) & 0xc0) >> 6) | ((b1) << 2) | ((b2) << 10)) #endif #define CALL_OFFSET_SE \ (((CALL_OFFSET & 0x20000) ? 0xfffc0000 : 0) | CALL_OFFSET) #define CALLX_N CALL_N #ifdef TARGET_WORDS_BIGENDIAN #define CALLX_M ((b0) & 0x3) #else #define CALLX_M (((b0) & 0xc0) >> 6) #endif #define CALLX_S RRR_S #define BRI12_M CALLX_M #define BRI12_S RRR_S #ifdef TARGET_WORDS_BIGENDIAN #define BRI12_IMM12 ((((b1) & 0xf) << 8) | (b2)) #else #define BRI12_IMM12 ((((b1) & 0xf0) >> 4) | ((b2) << 4)) #endif #define BRI12_IMM12_SE (((BRI12_IMM12 & 0x800) ? 0xfffff000 : 0) | BRI12_IMM12) #define BRI8_M BRI12_M #define BRI8_R RRI8_R #define BRI8_S RRI8_S #define BRI8_IMM8 RRI8_IMM8 #define BRI8_IMM8_SE RRI8_IMM8_SE #define RSR_SR (b1) uint8_t b0 = cpu_ldub_code(env, dc->pc); uint8_t b1 = cpu_ldub_code(env, dc->pc + 1); uint8_t b2 = 0; static const uint32_t B4CONST[] = { 0xffffffff, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 16, 32, 64, 128, 256 }; static const uint32_t B4CONSTU[] = { 32768, 65536, 2, 3, 4, 5, 6, 7, 8, 10, 12, 16, 32, 64, 128, 256 }; if (OP0 >= 8) { dc->next_pc = dc->pc + 2; HAS_OPTION(XTENSA_OPTION_CODE_DENSITY); } else { dc->next_pc = dc->pc + 3; b2 = cpu_ldub_code(env, dc->pc + 2); } switch (OP0) { case 0: /*QRST*/ switch (OP1) { case 0: /*RST0*/ switch (OP2) { case 0: /*ST0*/ if ((RRR_R & 0xc) == 0x8) { HAS_OPTION(XTENSA_OPTION_BOOLEAN); } switch (RRR_R) { case 0: /*SNM0*/ switch (CALLX_M) { case 0: /*ILL*/ gen_exception_cause(dc, ILLEGAL_INSTRUCTION_CAUSE); break; case 1: /*reserved*/ RESERVED(); break; case 2: /*JR*/ switch (CALLX_N) { case 0: /*RET*/ case 2: /*JX*/ gen_window_check1(dc, CALLX_S); gen_jump(dc, cpu_R[CALLX_S]); break; case 1: /*RETWw*/ HAS_OPTION(XTENSA_OPTION_WINDOWED_REGISTER); { TCGv_i32 tmp = tcg_const_i32(dc->pc); gen_advance_ccount(dc); gen_helper_retw(tmp, cpu_env, tmp); gen_jump(dc, tmp); tcg_temp_free(tmp); } break; case 3: /*reserved*/ RESERVED(); break; } break; case 3: /*CALLX*/ gen_window_check2(dc, CALLX_S, CALLX_N << 2); switch (CALLX_N) { case 0: /*CALLX0*/ { TCGv_i32 tmp = tcg_temp_new_i32(); tcg_gen_mov_i32(tmp, cpu_R[CALLX_S]); tcg_gen_movi_i32(cpu_R[0], dc->next_pc); gen_jump(dc, tmp); tcg_temp_free(tmp); } break; case 1: /*CALLX4w*/ case 2: /*CALLX8w*/ case 3: /*CALLX12w*/ HAS_OPTION(XTENSA_OPTION_WINDOWED_REGISTER); { TCGv_i32 tmp = tcg_temp_new_i32(); tcg_gen_mov_i32(tmp, cpu_R[CALLX_S]); gen_callw(dc, CALLX_N, tmp); tcg_temp_free(tmp); } break; } break; } break; case 1: /*MOVSPw*/ HAS_OPTION(XTENSA_OPTION_WINDOWED_REGISTER); gen_window_check2(dc, RRR_T, RRR_S); { TCGv_i32 pc = tcg_const_i32(dc->pc); gen_advance_ccount(dc); gen_helper_movsp(cpu_env, pc); tcg_gen_mov_i32(cpu_R[RRR_T], cpu_R[RRR_S]); tcg_temp_free(pc); } break; case 2: /*SYNC*/ switch (RRR_T) { case 0: /*ISYNC*/ break; case 1: /*RSYNC*/ break; case 2: /*ESYNC*/ break; case 3: /*DSYNC*/ break; case 8: /*EXCW*/ HAS_OPTION(XTENSA_OPTION_EXCEPTION); break; case 12: /*MEMW*/ break; case 13: /*EXTW*/ break; case 15: /*NOP*/ break; default: /*reserved*/ RESERVED(); break; } break; case 3: /*RFEIx*/ switch (RRR_T) { case 0: /*RFETx*/ HAS_OPTION(XTENSA_OPTION_EXCEPTION); switch (RRR_S) { case 0: /*RFEx*/ gen_check_privilege(dc); tcg_gen_andi_i32(cpu_SR[PS], cpu_SR[PS], ~PS_EXCM); gen_helper_check_interrupts(cpu_env); gen_jump(dc, cpu_SR[EPC1]); break; case 1: /*RFUEx*/ RESERVED(); break; case 2: /*RFDEx*/ gen_check_privilege(dc); gen_jump(dc, cpu_SR[ dc->config->ndepc ? DEPC : EPC1]); break; case 4: /*RFWOw*/ case 5: /*RFWUw*/ HAS_OPTION(XTENSA_OPTION_WINDOWED_REGISTER); gen_check_privilege(dc); { TCGv_i32 tmp = tcg_const_i32(1); tcg_gen_andi_i32( cpu_SR[PS], cpu_SR[PS], ~PS_EXCM); tcg_gen_shl_i32(tmp, tmp, cpu_SR[WINDOW_BASE]); if (RRR_S == 4) { tcg_gen_andc_i32(cpu_SR[WINDOW_START], cpu_SR[WINDOW_START], tmp); } else { tcg_gen_or_i32(cpu_SR[WINDOW_START], cpu_SR[WINDOW_START], tmp); } gen_helper_restore_owb(cpu_env); gen_helper_check_interrupts(cpu_env); gen_jump(dc, cpu_SR[EPC1]); tcg_temp_free(tmp); } break; default: /*reserved*/ RESERVED(); break; } break; case 1: /*RFIx*/ HAS_OPTION(XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT); if (RRR_S >= 2 && RRR_S <= dc->config->nlevel) { gen_check_privilege(dc); tcg_gen_mov_i32(cpu_SR[PS], cpu_SR[EPS2 + RRR_S - 2]); gen_helper_check_interrupts(cpu_env); gen_jump(dc, cpu_SR[EPC1 + RRR_S - 1]); } else { qemu_log("RFI %d is illegal\n", RRR_S); gen_exception_cause(dc, ILLEGAL_INSTRUCTION_CAUSE); } break; case 2: /*RFME*/ TBD(); break; default: /*reserved*/ RESERVED(); break; } break; case 4: /*BREAKx*/ HAS_OPTION(XTENSA_OPTION_DEBUG); if (dc->debug) { gen_debug_exception(dc, DEBUGCAUSE_BI); } break; case 5: /*SYSCALLx*/ HAS_OPTION(XTENSA_OPTION_EXCEPTION); switch (RRR_S) { case 0: /*SYSCALLx*/ gen_exception_cause(dc, SYSCALL_CAUSE); break; case 1: /*SIMCALL*/ if (semihosting_enabled) { gen_check_privilege(dc); gen_helper_simcall(cpu_env); } else { qemu_log("SIMCALL but semihosting is disabled\n"); gen_exception_cause(dc, ILLEGAL_INSTRUCTION_CAUSE); } break; default: RESERVED(); break; } break; case 6: /*RSILx*/ HAS_OPTION(XTENSA_OPTION_INTERRUPT); gen_check_privilege(dc); gen_window_check1(dc, RRR_T); tcg_gen_mov_i32(cpu_R[RRR_T], cpu_SR[PS]); tcg_gen_andi_i32(cpu_SR[PS], cpu_SR[PS], ~PS_INTLEVEL); tcg_gen_ori_i32(cpu_SR[PS], cpu_SR[PS], RRR_S); gen_helper_check_interrupts(cpu_env); gen_jumpi_check_loop_end(dc, 0); break; case 7: /*WAITIx*/ HAS_OPTION(XTENSA_OPTION_INTERRUPT); gen_check_privilege(dc); gen_waiti(dc, RRR_S); break; case 8: /*ANY4p*/ case 9: /*ALL4p*/ case 10: /*ANY8p*/ case 11: /*ALL8p*/ HAS_OPTION(XTENSA_OPTION_BOOLEAN); { const unsigned shift = (RRR_R & 2) ? 8 : 4; TCGv_i32 mask = tcg_const_i32( ((1 << shift) - 1) << RRR_S); TCGv_i32 tmp = tcg_temp_new_i32(); tcg_gen_and_i32(tmp, cpu_SR[BR], mask); if (RRR_R & 1) { /*ALL*/ tcg_gen_addi_i32(tmp, tmp, 1 << RRR_S); } else { /*ANY*/ tcg_gen_add_i32(tmp, tmp, mask); } tcg_gen_shri_i32(tmp, tmp, RRR_S + shift); tcg_gen_deposit_i32(cpu_SR[BR], cpu_SR[BR], tmp, RRR_T, 1); tcg_temp_free(mask); tcg_temp_free(tmp); } break; default: /*reserved*/ RESERVED(); break; } break; case 1: /*AND*/ gen_window_check3(dc, RRR_R, RRR_S, RRR_T); tcg_gen_and_i32(cpu_R[RRR_R], cpu_R[RRR_S], cpu_R[RRR_T]); break; case 2: /*OR*/ gen_window_check3(dc, RRR_R, RRR_S, RRR_T); tcg_gen_or_i32(cpu_R[RRR_R], cpu_R[RRR_S], cpu_R[RRR_T]); break; case 3: /*XOR*/ gen_window_check3(dc, RRR_R, RRR_S, RRR_T); tcg_gen_xor_i32(cpu_R[RRR_R], cpu_R[RRR_S], cpu_R[RRR_T]); break; case 4: /*ST1*/ switch (RRR_R) { case 0: /*SSR*/ gen_window_check1(dc, RRR_S); gen_right_shift_sar(dc, cpu_R[RRR_S]); break; case 1: /*SSL*/ gen_window_check1(dc, RRR_S); gen_left_shift_sar(dc, cpu_R[RRR_S]); break; case 2: /*SSA8L*/ gen_window_check1(dc, RRR_S); { TCGv_i32 tmp = tcg_temp_new_i32(); tcg_gen_shli_i32(tmp, cpu_R[RRR_S], 3); gen_right_shift_sar(dc, tmp); tcg_temp_free(tmp); } break; case 3: /*SSA8B*/ gen_window_check1(dc, RRR_S); { TCGv_i32 tmp = tcg_temp_new_i32(); tcg_gen_shli_i32(tmp, cpu_R[RRR_S], 3); gen_left_shift_sar(dc, tmp); tcg_temp_free(tmp); } break; case 4: /*SSAI*/ { TCGv_i32 tmp = tcg_const_i32( RRR_S | ((RRR_T & 1) << 4)); gen_right_shift_sar(dc, tmp); tcg_temp_free(tmp); } break; case 6: /*RER*/ TBD(); break; case 7: /*WER*/ TBD(); break; case 8: /*ROTWw*/ HAS_OPTION(XTENSA_OPTION_WINDOWED_REGISTER); gen_check_privilege(dc); { TCGv_i32 tmp = tcg_const_i32( RRR_T | ((RRR_T & 8) ? 0xfffffff0 : 0)); gen_helper_rotw(cpu_env, tmp); tcg_temp_free(tmp); reset_used_window(dc); } break; case 14: /*NSAu*/ HAS_OPTION(XTENSA_OPTION_MISC_OP_NSA); gen_window_check2(dc, RRR_S, RRR_T); gen_helper_nsa(cpu_R[RRR_T], cpu_R[RRR_S]); break; case 15: /*NSAUu*/ HAS_OPTION(XTENSA_OPTION_MISC_OP_NSA); gen_window_check2(dc, RRR_S, RRR_T); gen_helper_nsau(cpu_R[RRR_T], cpu_R[RRR_S]); break; default: /*reserved*/ RESERVED(); break; } break; case 5: /*TLB*/ HAS_OPTION_BITS( XTENSA_OPTION_BIT(XTENSA_OPTION_MMU) | XTENSA_OPTION_BIT(XTENSA_OPTION_REGION_PROTECTION) | XTENSA_OPTION_BIT(XTENSA_OPTION_REGION_TRANSLATION)); gen_check_privilege(dc); gen_window_check2(dc, RRR_S, RRR_T); { TCGv_i32 dtlb = tcg_const_i32((RRR_R & 8) != 0); switch (RRR_R & 7) { case 3: /*RITLB0*/ /*RDTLB0*/ gen_helper_rtlb0(cpu_R[RRR_T], cpu_env, cpu_R[RRR_S], dtlb); break; case 4: /*IITLB*/ /*IDTLB*/ gen_helper_itlb(cpu_env, cpu_R[RRR_S], dtlb); /* This could change memory mapping, so exit tb */ gen_jumpi_check_loop_end(dc, -1); break; case 5: /*PITLB*/ /*PDTLB*/ tcg_gen_movi_i32(cpu_pc, dc->pc); gen_helper_ptlb(cpu_R[RRR_T], cpu_env, cpu_R[RRR_S], dtlb); break; case 6: /*WITLB*/ /*WDTLB*/ gen_helper_wtlb( cpu_env, cpu_R[RRR_T], cpu_R[RRR_S], dtlb); /* This could change memory mapping, so exit tb */ gen_jumpi_check_loop_end(dc, -1); break; case 7: /*RITLB1*/ /*RDTLB1*/ gen_helper_rtlb1(cpu_R[RRR_T], cpu_env, cpu_R[RRR_S], dtlb); break; default: tcg_temp_free(dtlb); RESERVED(); break; } tcg_temp_free(dtlb); } break; case 6: /*RT0*/ gen_window_check2(dc, RRR_R, RRR_T); switch (RRR_S) { case 0: /*NEG*/ tcg_gen_neg_i32(cpu_R[RRR_R], cpu_R[RRR_T]); break; case 1: /*ABS*/ { int label = gen_new_label(); tcg_gen_mov_i32(cpu_R[RRR_R], cpu_R[RRR_T]); tcg_gen_brcondi_i32( TCG_COND_GE, cpu_R[RRR_R], 0, label); tcg_gen_neg_i32(cpu_R[RRR_R], cpu_R[RRR_T]); gen_set_label(label); } break; default: /*reserved*/ RESERVED(); break; } break; case 7: /*reserved*/ RESERVED(); break; case 8: /*ADD*/ gen_window_check3(dc, RRR_R, RRR_S, RRR_T); tcg_gen_add_i32(cpu_R[RRR_R], cpu_R[RRR_S], cpu_R[RRR_T]); break; case 9: /*ADD**/ case 10: case 11: gen_window_check3(dc, RRR_R, RRR_S, RRR_T); { TCGv_i32 tmp = tcg_temp_new_i32(); tcg_gen_shli_i32(tmp, cpu_R[RRR_S], OP2 - 8); tcg_gen_add_i32(cpu_R[RRR_R], tmp, cpu_R[RRR_T]); tcg_temp_free(tmp); } break; case 12: /*SUB*/ gen_window_check3(dc, RRR_R, RRR_S, RRR_T); tcg_gen_sub_i32(cpu_R[RRR_R], cpu_R[RRR_S], cpu_R[RRR_T]); break; case 13: /*SUB**/ case 14: case 15: gen_window_check3(dc, RRR_R, RRR_S, RRR_T); { TCGv_i32 tmp = tcg_temp_new_i32(); tcg_gen_shli_i32(tmp, cpu_R[RRR_S], OP2 - 12); tcg_gen_sub_i32(cpu_R[RRR_R], tmp, cpu_R[RRR_T]); tcg_temp_free(tmp); } break; } break; case 1: /*RST1*/ switch (OP2) { case 0: /*SLLI*/ case 1: gen_window_check2(dc, RRR_R, RRR_S); tcg_gen_shli_i32(cpu_R[RRR_R], cpu_R[RRR_S], 32 - (RRR_T | ((OP2 & 1) << 4))); break; case 2: /*SRAI*/ case 3: gen_window_check2(dc, RRR_R, RRR_T); tcg_gen_sari_i32(cpu_R[RRR_R], cpu_R[RRR_T], RRR_S | ((OP2 & 1) << 4)); break; case 4: /*SRLI*/ gen_window_check2(dc, RRR_R, RRR_T); tcg_gen_shri_i32(cpu_R[RRR_R], cpu_R[RRR_T], RRR_S); break; case 6: /*XSR*/ { TCGv_i32 tmp = tcg_temp_new_i32(); if (RSR_SR >= 64) { gen_check_privilege(dc); } gen_window_check1(dc, RRR_T); tcg_gen_mov_i32(tmp, cpu_R[RRR_T]); gen_rsr(dc, cpu_R[RRR_T], RSR_SR); gen_wsr(dc, RSR_SR, tmp); tcg_temp_free(tmp); if (!sregnames[RSR_SR]) { TBD(); } } break; /* * Note: 64 bit ops are used here solely because SAR values * have range 0..63 */ #define gen_shift_reg(cmd, reg) do { \ TCGv_i64 tmp = tcg_temp_new_i64(); \ tcg_gen_extu_i32_i64(tmp, reg); \ tcg_gen_##cmd##_i64(v, v, tmp); \ tcg_gen_trunc_i64_i32(cpu_R[RRR_R], v); \ tcg_temp_free_i64(v); \ tcg_temp_free_i64(tmp); \ } while (0) #define gen_shift(cmd) gen_shift_reg(cmd, cpu_SR[SAR]) case 8: /*SRC*/ gen_window_check3(dc, RRR_R, RRR_S, RRR_T); { TCGv_i64 v = tcg_temp_new_i64(); tcg_gen_concat_i32_i64(v, cpu_R[RRR_T], cpu_R[RRR_S]); gen_shift(shr); } break; case 9: /*SRL*/ gen_window_check2(dc, RRR_R, RRR_T); if (dc->sar_5bit) { tcg_gen_shr_i32(cpu_R[RRR_R], cpu_R[RRR_T], cpu_SR[SAR]); } else { TCGv_i64 v = tcg_temp_new_i64(); tcg_gen_extu_i32_i64(v, cpu_R[RRR_T]); gen_shift(shr); } break; case 10: /*SLL*/ gen_window_check2(dc, RRR_R, RRR_S); if (dc->sar_m32_5bit) { tcg_gen_shl_i32(cpu_R[RRR_R], cpu_R[RRR_S], dc->sar_m32); } else { TCGv_i64 v = tcg_temp_new_i64(); TCGv_i32 s = tcg_const_i32(32); tcg_gen_sub_i32(s, s, cpu_SR[SAR]); tcg_gen_andi_i32(s, s, 0x3f); tcg_gen_extu_i32_i64(v, cpu_R[RRR_S]); gen_shift_reg(shl, s); tcg_temp_free(s); } break; case 11: /*SRA*/ gen_window_check2(dc, RRR_R, RRR_T); if (dc->sar_5bit) { tcg_gen_sar_i32(cpu_R[RRR_R], cpu_R[RRR_T], cpu_SR[SAR]); } else { TCGv_i64 v = tcg_temp_new_i64(); tcg_gen_ext_i32_i64(v, cpu_R[RRR_T]); gen_shift(sar); } break; #undef gen_shift #undef gen_shift_reg case 12: /*MUL16U*/ HAS_OPTION(XTENSA_OPTION_16_BIT_IMUL); gen_window_check3(dc, RRR_R, RRR_S, RRR_T); { TCGv_i32 v1 = tcg_temp_new_i32(); TCGv_i32 v2 = tcg_temp_new_i32(); tcg_gen_ext16u_i32(v1, cpu_R[RRR_S]); tcg_gen_ext16u_i32(v2, cpu_R[RRR_T]); tcg_gen_mul_i32(cpu_R[RRR_R], v1, v2); tcg_temp_free(v2); tcg_temp_free(v1); } break; case 13: /*MUL16S*/ HAS_OPTION(XTENSA_OPTION_16_BIT_IMUL); gen_window_check3(dc, RRR_R, RRR_S, RRR_T); { TCGv_i32 v1 = tcg_temp_new_i32(); TCGv_i32 v2 = tcg_temp_new_i32(); tcg_gen_ext16s_i32(v1, cpu_R[RRR_S]); tcg_gen_ext16s_i32(v2, cpu_R[RRR_T]); tcg_gen_mul_i32(cpu_R[RRR_R], v1, v2); tcg_temp_free(v2); tcg_temp_free(v1); } break; default: /*reserved*/ RESERVED(); break; } break; case 2: /*RST2*/ if (OP2 >= 8) { gen_window_check3(dc, RRR_R, RRR_S, RRR_T); } if (OP2 >= 12) { HAS_OPTION(XTENSA_OPTION_32_BIT_IDIV); int label = gen_new_label(); tcg_gen_brcondi_i32(TCG_COND_NE, cpu_R[RRR_T], 0, label); gen_exception_cause(dc, INTEGER_DIVIDE_BY_ZERO_CAUSE); gen_set_label(label); } switch (OP2) { #define BOOLEAN_LOGIC(fn, r, s, t) \ do { \ HAS_OPTION(XTENSA_OPTION_BOOLEAN); \ TCGv_i32 tmp1 = tcg_temp_new_i32(); \ TCGv_i32 tmp2 = tcg_temp_new_i32(); \ \ tcg_gen_shri_i32(tmp1, cpu_SR[BR], s); \ tcg_gen_shri_i32(tmp2, cpu_SR[BR], t); \ tcg_gen_##fn##_i32(tmp1, tmp1, tmp2); \ tcg_gen_deposit_i32(cpu_SR[BR], cpu_SR[BR], tmp1, r, 1); \ tcg_temp_free(tmp1); \ tcg_temp_free(tmp2); \ } while (0) case 0: /*ANDBp*/ BOOLEAN_LOGIC(and, RRR_R, RRR_S, RRR_T); break; case 1: /*ANDBCp*/ BOOLEAN_LOGIC(andc, RRR_R, RRR_S, RRR_T); break; case 2: /*ORBp*/ BOOLEAN_LOGIC(or, RRR_R, RRR_S, RRR_T); break; case 3: /*ORBCp*/ BOOLEAN_LOGIC(orc, RRR_R, RRR_S, RRR_T); break; case 4: /*XORBp*/ BOOLEAN_LOGIC(xor, RRR_R, RRR_S, RRR_T); break; #undef BOOLEAN_LOGIC case 8: /*MULLi*/ HAS_OPTION(XTENSA_OPTION_32_BIT_IMUL); tcg_gen_mul_i32(cpu_R[RRR_R], cpu_R[RRR_S], cpu_R[RRR_T]); break; case 10: /*MULUHi*/ case 11: /*MULSHi*/ HAS_OPTION(XTENSA_OPTION_32_BIT_IMUL_HIGH); { TCGv_i64 r = tcg_temp_new_i64(); TCGv_i64 s = tcg_temp_new_i64(); TCGv_i64 t = tcg_temp_new_i64(); if (OP2 == 10) { tcg_gen_extu_i32_i64(s, cpu_R[RRR_S]); tcg_gen_extu_i32_i64(t, cpu_R[RRR_T]); } else { tcg_gen_ext_i32_i64(s, cpu_R[RRR_S]); tcg_gen_ext_i32_i64(t, cpu_R[RRR_T]); } tcg_gen_mul_i64(r, s, t); tcg_gen_shri_i64(r, r, 32); tcg_gen_trunc_i64_i32(cpu_R[RRR_R], r); tcg_temp_free_i64(r); tcg_temp_free_i64(s); tcg_temp_free_i64(t); } break; case 12: /*QUOUi*/ tcg_gen_divu_i32(cpu_R[RRR_R], cpu_R[RRR_S], cpu_R[RRR_T]); break; case 13: /*QUOSi*/ case 15: /*REMSi*/ { int label1 = gen_new_label(); int label2 = gen_new_label(); tcg_gen_brcondi_i32(TCG_COND_NE, cpu_R[RRR_S], 0x80000000, label1); tcg_gen_brcondi_i32(TCG_COND_NE, cpu_R[RRR_T], 0xffffffff, label1); tcg_gen_movi_i32(cpu_R[RRR_R], OP2 == 13 ? 0x80000000 : 0); tcg_gen_br(label2); gen_set_label(label1); if (OP2 == 13) { tcg_gen_div_i32(cpu_R[RRR_R], cpu_R[RRR_S], cpu_R[RRR_T]); } else { tcg_gen_rem_i32(cpu_R[RRR_R], cpu_R[RRR_S], cpu_R[RRR_T]); } gen_set_label(label2); } break; case 14: /*REMUi*/ tcg_gen_remu_i32(cpu_R[RRR_R], cpu_R[RRR_S], cpu_R[RRR_T]); break; default: /*reserved*/ RESERVED(); break; } break; case 3: /*RST3*/ switch (OP2) { case 0: /*RSR*/ if (RSR_SR >= 64) { gen_check_privilege(dc); } gen_window_check1(dc, RRR_T); gen_rsr(dc, cpu_R[RRR_T], RSR_SR); if (!sregnames[RSR_SR]) { TBD(); } break; case 1: /*WSR*/ if (RSR_SR >= 64) { gen_check_privilege(dc); } gen_window_check1(dc, RRR_T); gen_wsr(dc, RSR_SR, cpu_R[RRR_T]); if (!sregnames[RSR_SR]) { TBD(); } break; case 2: /*SEXTu*/ HAS_OPTION(XTENSA_OPTION_MISC_OP_SEXT); gen_window_check2(dc, RRR_R, RRR_S); { int shift = 24 - RRR_T; if (shift == 24) { tcg_gen_ext8s_i32(cpu_R[RRR_R], cpu_R[RRR_S]); } else if (shift == 16) { tcg_gen_ext16s_i32(cpu_R[RRR_R], cpu_R[RRR_S]); } else { TCGv_i32 tmp = tcg_temp_new_i32(); tcg_gen_shli_i32(tmp, cpu_R[RRR_S], shift); tcg_gen_sari_i32(cpu_R[RRR_R], tmp, shift); tcg_temp_free(tmp); } } break; case 3: /*CLAMPSu*/ HAS_OPTION(XTENSA_OPTION_MISC_OP_CLAMPS); gen_window_check2(dc, RRR_R, RRR_S); { TCGv_i32 tmp1 = tcg_temp_new_i32(); TCGv_i32 tmp2 = tcg_temp_new_i32(); int label = gen_new_label(); tcg_gen_sari_i32(tmp1, cpu_R[RRR_S], 24 - RRR_T); tcg_gen_xor_i32(tmp2, tmp1, cpu_R[RRR_S]); tcg_gen_andi_i32(tmp2, tmp2, 0xffffffff << (RRR_T + 7)); tcg_gen_mov_i32(cpu_R[RRR_R], cpu_R[RRR_S]); tcg_gen_brcondi_i32(TCG_COND_EQ, tmp2, 0, label); tcg_gen_sari_i32(tmp1, cpu_R[RRR_S], 31); tcg_gen_xori_i32(cpu_R[RRR_R], tmp1, 0xffffffff >> (25 - RRR_T)); gen_set_label(label); tcg_temp_free(tmp1); tcg_temp_free(tmp2); } break; case 4: /*MINu*/ case 5: /*MAXu*/ case 6: /*MINUu*/ case 7: /*MAXUu*/ HAS_OPTION(XTENSA_OPTION_MISC_OP_MINMAX); gen_window_check3(dc, RRR_R, RRR_S, RRR_T); { static const TCGCond cond[] = { TCG_COND_LE, TCG_COND_GE, TCG_COND_LEU, TCG_COND_GEU }; int label = gen_new_label(); if (RRR_R != RRR_T) { tcg_gen_mov_i32(cpu_R[RRR_R], cpu_R[RRR_S]); tcg_gen_brcond_i32(cond[OP2 - 4], cpu_R[RRR_S], cpu_R[RRR_T], label); tcg_gen_mov_i32(cpu_R[RRR_R], cpu_R[RRR_T]); } else { tcg_gen_brcond_i32(cond[OP2 - 4], cpu_R[RRR_T], cpu_R[RRR_S], label); tcg_gen_mov_i32(cpu_R[RRR_R], cpu_R[RRR_S]); } gen_set_label(label); } break; case 8: /*MOVEQZ*/ case 9: /*MOVNEZ*/ case 10: /*MOVLTZ*/ case 11: /*MOVGEZ*/ gen_window_check3(dc, RRR_R, RRR_S, RRR_T); { static const TCGCond cond[] = { TCG_COND_NE, TCG_COND_EQ, TCG_COND_GE, TCG_COND_LT }; int label = gen_new_label(); tcg_gen_brcondi_i32(cond[OP2 - 8], cpu_R[RRR_T], 0, label); tcg_gen_mov_i32(cpu_R[RRR_R], cpu_R[RRR_S]); gen_set_label(label); } break; case 12: /*MOVFp*/ case 13: /*MOVTp*/ HAS_OPTION(XTENSA_OPTION_BOOLEAN); gen_window_check2(dc, RRR_R, RRR_S); { int label = gen_new_label(); TCGv_i32 tmp = tcg_temp_new_i32(); tcg_gen_andi_i32(tmp, cpu_SR[BR], 1 << RRR_T); tcg_gen_brcondi_i32( OP2 & 1 ? TCG_COND_EQ : TCG_COND_NE, tmp, 0, label); tcg_gen_mov_i32(cpu_R[RRR_R], cpu_R[RRR_S]); gen_set_label(label); tcg_temp_free(tmp); } break; case 14: /*RUR*/ gen_window_check1(dc, RRR_R); { int st = (RRR_S << 4) + RRR_T; if (uregnames[st]) { tcg_gen_mov_i32(cpu_R[RRR_R], cpu_UR[st]); } else { qemu_log("RUR %d not implemented, ", st); TBD(); } } break; case 15: /*WUR*/ gen_window_check1(dc, RRR_T); if (uregnames[RSR_SR]) { gen_wur(RSR_SR, cpu_R[RRR_T]); } else { qemu_log("WUR %d not implemented, ", RSR_SR); TBD(); } break; } break; case 4: /*EXTUI*/ case 5: gen_window_check2(dc, RRR_R, RRR_T); { int shiftimm = RRR_S | ((OP1 & 1) << 4); int maskimm = (1 << (OP2 + 1)) - 1; TCGv_i32 tmp = tcg_temp_new_i32(); tcg_gen_shri_i32(tmp, cpu_R[RRR_T], shiftimm); tcg_gen_andi_i32(cpu_R[RRR_R], tmp, maskimm); tcg_temp_free(tmp); } break; case 6: /*CUST0*/ RESERVED(); break; case 7: /*CUST1*/ RESERVED(); break; case 8: /*LSCXp*/ switch (OP2) { case 0: /*LSXf*/ case 1: /*LSXUf*/ case 4: /*SSXf*/ case 5: /*SSXUf*/ HAS_OPTION(XTENSA_OPTION_FP_COPROCESSOR); gen_window_check2(dc, RRR_S, RRR_T); gen_check_cpenable(dc, 0); { TCGv_i32 addr = tcg_temp_new_i32(); tcg_gen_add_i32(addr, cpu_R[RRR_S], cpu_R[RRR_T]); gen_load_store_alignment(dc, 2, addr, false); if (OP2 & 0x4) { tcg_gen_qemu_st32(cpu_FR[RRR_R], addr, dc->cring); } else { tcg_gen_qemu_ld32u(cpu_FR[RRR_R], addr, dc->cring); } if (OP2 & 0x1) { tcg_gen_mov_i32(cpu_R[RRR_S], addr); } tcg_temp_free(addr); } break; default: /*reserved*/ RESERVED(); break; } break; case 9: /*LSC4*/ gen_window_check2(dc, RRR_S, RRR_T); switch (OP2) { case 0: /*L32E*/ HAS_OPTION(XTENSA_OPTION_WINDOWED_REGISTER); gen_check_privilege(dc); { TCGv_i32 addr = tcg_temp_new_i32(); tcg_gen_addi_i32(addr, cpu_R[RRR_S], (0xffffffc0 | (RRR_R << 2))); tcg_gen_qemu_ld32u(cpu_R[RRR_T], addr, dc->ring); tcg_temp_free(addr); } break; case 4: /*S32E*/ HAS_OPTION(XTENSA_OPTION_WINDOWED_REGISTER); gen_check_privilege(dc); { TCGv_i32 addr = tcg_temp_new_i32(); tcg_gen_addi_i32(addr, cpu_R[RRR_S], (0xffffffc0 | (RRR_R << 2))); tcg_gen_qemu_st32(cpu_R[RRR_T], addr, dc->ring); tcg_temp_free(addr); } break; default: RESERVED(); break; } break; case 10: /*FP0*/ HAS_OPTION(XTENSA_OPTION_FP_COPROCESSOR); switch (OP2) { case 0: /*ADD.Sf*/ gen_check_cpenable(dc, 0); gen_helper_add_s(cpu_FR[RRR_R], cpu_env, cpu_FR[RRR_S], cpu_FR[RRR_T]); break; case 1: /*SUB.Sf*/ gen_check_cpenable(dc, 0); gen_helper_sub_s(cpu_FR[RRR_R], cpu_env, cpu_FR[RRR_S], cpu_FR[RRR_T]); break; case 2: /*MUL.Sf*/ gen_check_cpenable(dc, 0); gen_helper_mul_s(cpu_FR[RRR_R], cpu_env, cpu_FR[RRR_S], cpu_FR[RRR_T]); break; case 4: /*MADD.Sf*/ gen_check_cpenable(dc, 0); gen_helper_madd_s(cpu_FR[RRR_R], cpu_env, cpu_FR[RRR_R], cpu_FR[RRR_S], cpu_FR[RRR_T]); break; case 5: /*MSUB.Sf*/ gen_check_cpenable(dc, 0); gen_helper_msub_s(cpu_FR[RRR_R], cpu_env, cpu_FR[RRR_R], cpu_FR[RRR_S], cpu_FR[RRR_T]); break; case 8: /*ROUND.Sf*/ case 9: /*TRUNC.Sf*/ case 10: /*FLOOR.Sf*/ case 11: /*CEIL.Sf*/ case 14: /*UTRUNC.Sf*/ gen_window_check1(dc, RRR_R); gen_check_cpenable(dc, 0); { static const unsigned rounding_mode_const[] = { float_round_nearest_even, float_round_to_zero, float_round_down, float_round_up, [6] = float_round_to_zero, }; TCGv_i32 rounding_mode = tcg_const_i32( rounding_mode_const[OP2 & 7]); TCGv_i32 scale = tcg_const_i32(RRR_T); if (OP2 == 14) { gen_helper_ftoui(cpu_R[RRR_R], cpu_FR[RRR_S], rounding_mode, scale); } else { gen_helper_ftoi(cpu_R[RRR_R], cpu_FR[RRR_S], rounding_mode, scale); } tcg_temp_free(rounding_mode); tcg_temp_free(scale); } break; case 12: /*FLOAT.Sf*/ case 13: /*UFLOAT.Sf*/ gen_window_check1(dc, RRR_S); gen_check_cpenable(dc, 0); { TCGv_i32 scale = tcg_const_i32(-RRR_T); if (OP2 == 13) { gen_helper_uitof(cpu_FR[RRR_R], cpu_env, cpu_R[RRR_S], scale); } else { gen_helper_itof(cpu_FR[RRR_R], cpu_env, cpu_R[RRR_S], scale); } tcg_temp_free(scale); } break; case 15: /*FP1OP*/ switch (RRR_T) { case 0: /*MOV.Sf*/ gen_check_cpenable(dc, 0); tcg_gen_mov_i32(cpu_FR[RRR_R], cpu_FR[RRR_S]); break; case 1: /*ABS.Sf*/ gen_check_cpenable(dc, 0); gen_helper_abs_s(cpu_FR[RRR_R], cpu_FR[RRR_S]); break; case 4: /*RFRf*/ gen_window_check1(dc, RRR_R); gen_check_cpenable(dc, 0); tcg_gen_mov_i32(cpu_R[RRR_R], cpu_FR[RRR_S]); break; case 5: /*WFRf*/ gen_window_check1(dc, RRR_S); gen_check_cpenable(dc, 0); tcg_gen_mov_i32(cpu_FR[RRR_R], cpu_R[RRR_S]); break; case 6: /*NEG.Sf*/ gen_check_cpenable(dc, 0); gen_helper_neg_s(cpu_FR[RRR_R], cpu_FR[RRR_S]); break; default: /*reserved*/ RESERVED(); break; } break; default: /*reserved*/ RESERVED(); break; } break; case 11: /*FP1*/ HAS_OPTION(XTENSA_OPTION_FP_COPROCESSOR); #define gen_compare(rel, br, a, b) \ do { \ TCGv_i32 bit = tcg_const_i32(1 << br); \ \ gen_check_cpenable(dc, 0); \ gen_helper_##rel(cpu_env, bit, cpu_FR[a], cpu_FR[b]); \ tcg_temp_free(bit); \ } while (0) switch (OP2) { case 1: /*UN.Sf*/ gen_compare(un_s, RRR_R, RRR_S, RRR_T); break; case 2: /*OEQ.Sf*/ gen_compare(oeq_s, RRR_R, RRR_S, RRR_T); break; case 3: /*UEQ.Sf*/ gen_compare(ueq_s, RRR_R, RRR_S, RRR_T); break; case 4: /*OLT.Sf*/ gen_compare(olt_s, RRR_R, RRR_S, RRR_T); break; case 5: /*ULT.Sf*/ gen_compare(ult_s, RRR_R, RRR_S, RRR_T); break; case 6: /*OLE.Sf*/ gen_compare(ole_s, RRR_R, RRR_S, RRR_T); break; case 7: /*ULE.Sf*/ gen_compare(ule_s, RRR_R, RRR_S, RRR_T); break; #undef gen_compare case 8: /*MOVEQZ.Sf*/ case 9: /*MOVNEZ.Sf*/ case 10: /*MOVLTZ.Sf*/ case 11: /*MOVGEZ.Sf*/ gen_window_check1(dc, RRR_T); gen_check_cpenable(dc, 0); { static const TCGCond cond[] = { TCG_COND_NE, TCG_COND_EQ, TCG_COND_GE, TCG_COND_LT }; int label = gen_new_label(); tcg_gen_brcondi_i32(cond[OP2 - 8], cpu_R[RRR_T], 0, label); tcg_gen_mov_i32(cpu_FR[RRR_R], cpu_FR[RRR_S]); gen_set_label(label); } break; case 12: /*MOVF.Sf*/ case 13: /*MOVT.Sf*/ HAS_OPTION(XTENSA_OPTION_BOOLEAN); gen_check_cpenable(dc, 0); { int label = gen_new_label(); TCGv_i32 tmp = tcg_temp_new_i32(); tcg_gen_andi_i32(tmp, cpu_SR[BR], 1 << RRR_T); tcg_gen_brcondi_i32( OP2 & 1 ? TCG_COND_EQ : TCG_COND_NE, tmp, 0, label); tcg_gen_mov_i32(cpu_FR[RRR_R], cpu_FR[RRR_S]); gen_set_label(label); tcg_temp_free(tmp); } break; default: /*reserved*/ RESERVED(); break; } break; default: /*reserved*/ RESERVED(); break; } break; case 1: /*L32R*/ gen_window_check1(dc, RRR_T); { TCGv_i32 tmp = tcg_const_i32( ((dc->tb->flags & XTENSA_TBFLAG_LITBASE) ? 0 : ((dc->pc + 3) & ~3)) + (0xfffc0000 | (RI16_IMM16 << 2))); if (dc->tb->flags & XTENSA_TBFLAG_LITBASE) { tcg_gen_add_i32(tmp, tmp, dc->litbase); } tcg_gen_qemu_ld32u(cpu_R[RRR_T], tmp, dc->cring); tcg_temp_free(tmp); } break; case 2: /*LSAI*/ #define gen_load_store(type, shift) do { \ TCGv_i32 addr = tcg_temp_new_i32(); \ gen_window_check2(dc, RRI8_S, RRI8_T); \ tcg_gen_addi_i32(addr, cpu_R[RRI8_S], RRI8_IMM8 << shift); \ if (shift) { \ gen_load_store_alignment(dc, shift, addr, false); \ } \ tcg_gen_qemu_##type(cpu_R[RRI8_T], addr, dc->cring); \ tcg_temp_free(addr); \ } while (0) switch (RRI8_R) { case 0: /*L8UI*/ gen_load_store(ld8u, 0); break; case 1: /*L16UI*/ gen_load_store(ld16u, 1); break; case 2: /*L32I*/ gen_load_store(ld32u, 2); break; case 4: /*S8I*/ gen_load_store(st8, 0); break; case 5: /*S16I*/ gen_load_store(st16, 1); break; case 6: /*S32I*/ gen_load_store(st32, 2); break; case 7: /*CACHEc*/ if (RRI8_T < 8) { HAS_OPTION(XTENSA_OPTION_DCACHE); } switch (RRI8_T) { case 0: /*DPFRc*/ break; case 1: /*DPFWc*/ break; case 2: /*DPFROc*/ break; case 3: /*DPFWOc*/ break; case 4: /*DHWBc*/ break; case 5: /*DHWBIc*/ break; case 6: /*DHIc*/ break; case 7: /*DIIc*/ break; case 8: /*DCEc*/ switch (OP1) { case 0: /*DPFLl*/ HAS_OPTION(XTENSA_OPTION_DCACHE_INDEX_LOCK); break; case 2: /*DHUl*/ HAS_OPTION(XTENSA_OPTION_DCACHE_INDEX_LOCK); break; case 3: /*DIUl*/ HAS_OPTION(XTENSA_OPTION_DCACHE_INDEX_LOCK); break; case 4: /*DIWBc*/ HAS_OPTION(XTENSA_OPTION_DCACHE); break; case 5: /*DIWBIc*/ HAS_OPTION(XTENSA_OPTION_DCACHE); break; default: /*reserved*/ RESERVED(); break; } break; case 12: /*IPFc*/ HAS_OPTION(XTENSA_OPTION_ICACHE); break; case 13: /*ICEc*/ switch (OP1) { case 0: /*IPFLl*/ HAS_OPTION(XTENSA_OPTION_ICACHE_INDEX_LOCK); break; case 2: /*IHUl*/ HAS_OPTION(XTENSA_OPTION_ICACHE_INDEX_LOCK); break; case 3: /*IIUl*/ HAS_OPTION(XTENSA_OPTION_ICACHE_INDEX_LOCK); break; default: /*reserved*/ RESERVED(); break; } break; case 14: /*IHIc*/ HAS_OPTION(XTENSA_OPTION_ICACHE); break; case 15: /*IIIc*/ HAS_OPTION(XTENSA_OPTION_ICACHE); break; default: /*reserved*/ RESERVED(); break; } break; case 9: /*L16SI*/ gen_load_store(ld16s, 1); break; #undef gen_load_store case 10: /*MOVI*/ gen_window_check1(dc, RRI8_T); tcg_gen_movi_i32(cpu_R[RRI8_T], RRI8_IMM8 | (RRI8_S << 8) | ((RRI8_S & 0x8) ? 0xfffff000 : 0)); break; #define gen_load_store_no_hw_align(type) do { \ TCGv_i32 addr = tcg_temp_local_new_i32(); \ gen_window_check2(dc, RRI8_S, RRI8_T); \ tcg_gen_addi_i32(addr, cpu_R[RRI8_S], RRI8_IMM8 << 2); \ gen_load_store_alignment(dc, 2, addr, true); \ tcg_gen_qemu_##type(cpu_R[RRI8_T], addr, dc->cring); \ tcg_temp_free(addr); \ } while (0) case 11: /*L32AIy*/ HAS_OPTION(XTENSA_OPTION_MP_SYNCHRO); gen_load_store_no_hw_align(ld32u); /*TODO acquire?*/ break; case 12: /*ADDI*/ gen_window_check2(dc, RRI8_S, RRI8_T); tcg_gen_addi_i32(cpu_R[RRI8_T], cpu_R[RRI8_S], RRI8_IMM8_SE); break; case 13: /*ADDMI*/ gen_window_check2(dc, RRI8_S, RRI8_T); tcg_gen_addi_i32(cpu_R[RRI8_T], cpu_R[RRI8_S], RRI8_IMM8_SE << 8); break; case 14: /*S32C1Iy*/ HAS_OPTION(XTENSA_OPTION_CONDITIONAL_STORE); gen_window_check2(dc, RRI8_S, RRI8_T); { int label = gen_new_label(); TCGv_i32 tmp = tcg_temp_local_new_i32(); TCGv_i32 addr = tcg_temp_local_new_i32(); TCGv_i32 tpc; tcg_gen_mov_i32(tmp, cpu_R[RRI8_T]); tcg_gen_addi_i32(addr, cpu_R[RRI8_S], RRI8_IMM8 << 2); gen_load_store_alignment(dc, 2, addr, true); gen_advance_ccount(dc); tpc = tcg_const_i32(dc->pc); gen_helper_check_atomctl(cpu_env, tpc, addr); tcg_gen_qemu_ld32u(cpu_R[RRI8_T], addr, dc->cring); tcg_gen_brcond_i32(TCG_COND_NE, cpu_R[RRI8_T], cpu_SR[SCOMPARE1], label); tcg_gen_qemu_st32(tmp, addr, dc->cring); gen_set_label(label); tcg_temp_free(tpc); tcg_temp_free(addr); tcg_temp_free(tmp); } break; case 15: /*S32RIy*/ HAS_OPTION(XTENSA_OPTION_MP_SYNCHRO); gen_load_store_no_hw_align(st32); /*TODO release?*/ break; #undef gen_load_store_no_hw_align default: /*reserved*/ RESERVED(); break; } break; case 3: /*LSCIp*/ switch (RRI8_R) { case 0: /*LSIf*/ case 4: /*SSIf*/ case 8: /*LSIUf*/ case 12: /*SSIUf*/ HAS_OPTION(XTENSA_OPTION_FP_COPROCESSOR); gen_window_check1(dc, RRI8_S); gen_check_cpenable(dc, 0); { TCGv_i32 addr = tcg_temp_new_i32(); tcg_gen_addi_i32(addr, cpu_R[RRI8_S], RRI8_IMM8 << 2); gen_load_store_alignment(dc, 2, addr, false); if (RRI8_R & 0x4) { tcg_gen_qemu_st32(cpu_FR[RRI8_T], addr, dc->cring); } else { tcg_gen_qemu_ld32u(cpu_FR[RRI8_T], addr, dc->cring); } if (RRI8_R & 0x8) { tcg_gen_mov_i32(cpu_R[RRI8_S], addr); } tcg_temp_free(addr); } break; default: /*reserved*/ RESERVED(); break; } break; case 4: /*MAC16d*/ HAS_OPTION(XTENSA_OPTION_MAC16); { enum { MAC16_UMUL = 0x0, MAC16_MUL = 0x4, MAC16_MULA = 0x8, MAC16_MULS = 0xc, MAC16_NONE = 0xf, } op = OP1 & 0xc; bool is_m1_sr = (OP2 & 0x3) == 2; bool is_m2_sr = (OP2 & 0xc) == 0; uint32_t ld_offset = 0; if (OP2 > 9) { RESERVED(); } switch (OP2 & 2) { case 0: /*MACI?/MACC?*/ is_m1_sr = true; ld_offset = (OP2 & 1) ? -4 : 4; if (OP2 >= 8) { /*MACI/MACC*/ if (OP1 == 0) { /*LDINC/LDDEC*/ op = MAC16_NONE; } else { RESERVED(); } } else if (op != MAC16_MULA) { /*MULA.*.*.LDINC/LDDEC*/ RESERVED(); } break; case 2: /*MACD?/MACA?*/ if (op == MAC16_UMUL && OP2 != 7) { /*UMUL only in MACAA*/ RESERVED(); } break; } if (op != MAC16_NONE) { if (!is_m1_sr) { gen_window_check1(dc, RRR_S); } if (!is_m2_sr) { gen_window_check1(dc, RRR_T); } } { TCGv_i32 vaddr = tcg_temp_new_i32(); TCGv_i32 mem32 = tcg_temp_new_i32(); if (ld_offset) { gen_window_check1(dc, RRR_S); tcg_gen_addi_i32(vaddr, cpu_R[RRR_S], ld_offset); gen_load_store_alignment(dc, 2, vaddr, false); tcg_gen_qemu_ld32u(mem32, vaddr, dc->cring); } if (op != MAC16_NONE) { TCGv_i32 m1 = gen_mac16_m( is_m1_sr ? cpu_SR[MR + RRR_X] : cpu_R[RRR_S], OP1 & 1, op == MAC16_UMUL); TCGv_i32 m2 = gen_mac16_m( is_m2_sr ? cpu_SR[MR + 2 + RRR_Y] : cpu_R[RRR_T], OP1 & 2, op == MAC16_UMUL); if (op == MAC16_MUL || op == MAC16_UMUL) { tcg_gen_mul_i32(cpu_SR[ACCLO], m1, m2); if (op == MAC16_UMUL) { tcg_gen_movi_i32(cpu_SR[ACCHI], 0); } else { tcg_gen_sari_i32(cpu_SR[ACCHI], cpu_SR[ACCLO], 31); } } else { TCGv_i32 res = tcg_temp_new_i32(); TCGv_i64 res64 = tcg_temp_new_i64(); TCGv_i64 tmp = tcg_temp_new_i64(); tcg_gen_mul_i32(res, m1, m2); tcg_gen_ext_i32_i64(res64, res); tcg_gen_concat_i32_i64(tmp, cpu_SR[ACCLO], cpu_SR[ACCHI]); if (op == MAC16_MULA) { tcg_gen_add_i64(tmp, tmp, res64); } else { tcg_gen_sub_i64(tmp, tmp, res64); } tcg_gen_trunc_i64_i32(cpu_SR[ACCLO], tmp); tcg_gen_shri_i64(tmp, tmp, 32); tcg_gen_trunc_i64_i32(cpu_SR[ACCHI], tmp); tcg_gen_ext8s_i32(cpu_SR[ACCHI], cpu_SR[ACCHI]); tcg_temp_free(res); tcg_temp_free_i64(res64); tcg_temp_free_i64(tmp); } tcg_temp_free(m1); tcg_temp_free(m2); } if (ld_offset) { tcg_gen_mov_i32(cpu_R[RRR_S], vaddr); tcg_gen_mov_i32(cpu_SR[MR + RRR_W], mem32); } tcg_temp_free(vaddr); tcg_temp_free(mem32); } } break; case 5: /*CALLN*/ switch (CALL_N) { case 0: /*CALL0*/ tcg_gen_movi_i32(cpu_R[0], dc->next_pc); gen_jumpi(dc, (dc->pc & ~3) + (CALL_OFFSET_SE << 2) + 4, 0); break; case 1: /*CALL4w*/ case 2: /*CALL8w*/ case 3: /*CALL12w*/ HAS_OPTION(XTENSA_OPTION_WINDOWED_REGISTER); gen_window_check1(dc, CALL_N << 2); gen_callwi(dc, CALL_N, (dc->pc & ~3) + (CALL_OFFSET_SE << 2) + 4, 0); break; } break; case 6: /*SI*/ switch (CALL_N) { case 0: /*J*/ gen_jumpi(dc, dc->pc + 4 + CALL_OFFSET_SE, 0); break; case 1: /*BZ*/ gen_window_check1(dc, BRI12_S); { static const TCGCond cond[] = { TCG_COND_EQ, /*BEQZ*/ TCG_COND_NE, /*BNEZ*/ TCG_COND_LT, /*BLTZ*/ TCG_COND_GE, /*BGEZ*/ }; gen_brcondi(dc, cond[BRI12_M & 3], cpu_R[BRI12_S], 0, 4 + BRI12_IMM12_SE); } break; case 2: /*BI0*/ gen_window_check1(dc, BRI8_S); { static const TCGCond cond[] = { TCG_COND_EQ, /*BEQI*/ TCG_COND_NE, /*BNEI*/ TCG_COND_LT, /*BLTI*/ TCG_COND_GE, /*BGEI*/ }; gen_brcondi(dc, cond[BRI8_M & 3], cpu_R[BRI8_S], B4CONST[BRI8_R], 4 + BRI8_IMM8_SE); } break; case 3: /*BI1*/ switch (BRI8_M) { case 0: /*ENTRYw*/ HAS_OPTION(XTENSA_OPTION_WINDOWED_REGISTER); { TCGv_i32 pc = tcg_const_i32(dc->pc); TCGv_i32 s = tcg_const_i32(BRI12_S); TCGv_i32 imm = tcg_const_i32(BRI12_IMM12); gen_advance_ccount(dc); gen_helper_entry(cpu_env, pc, s, imm); tcg_temp_free(imm); tcg_temp_free(s); tcg_temp_free(pc); reset_used_window(dc); } break; case 1: /*B1*/ switch (BRI8_R) { case 0: /*BFp*/ case 1: /*BTp*/ HAS_OPTION(XTENSA_OPTION_BOOLEAN); { TCGv_i32 tmp = tcg_temp_new_i32(); tcg_gen_andi_i32(tmp, cpu_SR[BR], 1 << RRI8_S); gen_brcondi(dc, BRI8_R == 1 ? TCG_COND_NE : TCG_COND_EQ, tmp, 0, 4 + RRI8_IMM8_SE); tcg_temp_free(tmp); } break; case 8: /*LOOP*/ case 9: /*LOOPNEZ*/ case 10: /*LOOPGTZ*/ HAS_OPTION(XTENSA_OPTION_LOOP); gen_window_check1(dc, RRI8_S); { uint32_t lend = dc->pc + RRI8_IMM8 + 4; TCGv_i32 tmp = tcg_const_i32(lend); tcg_gen_subi_i32(cpu_SR[LCOUNT], cpu_R[RRI8_S], 1); tcg_gen_movi_i32(cpu_SR[LBEG], dc->next_pc); gen_helper_wsr_lend(cpu_env, tmp); tcg_temp_free(tmp); if (BRI8_R > 8) { int label = gen_new_label(); tcg_gen_brcondi_i32( BRI8_R == 9 ? TCG_COND_NE : TCG_COND_GT, cpu_R[RRI8_S], 0, label); gen_jumpi(dc, lend, 1); gen_set_label(label); } gen_jumpi(dc, dc->next_pc, 0); } break; default: /*reserved*/ RESERVED(); break; } break; case 2: /*BLTUI*/ case 3: /*BGEUI*/ gen_window_check1(dc, BRI8_S); gen_brcondi(dc, BRI8_M == 2 ? TCG_COND_LTU : TCG_COND_GEU, cpu_R[BRI8_S], B4CONSTU[BRI8_R], 4 + BRI8_IMM8_SE); break; } break; } break; case 7: /*B*/ { TCGCond eq_ne = (RRI8_R & 8) ? TCG_COND_NE : TCG_COND_EQ; switch (RRI8_R & 7) { case 0: /*BNONE*/ /*BANY*/ gen_window_check2(dc, RRI8_S, RRI8_T); { TCGv_i32 tmp = tcg_temp_new_i32(); tcg_gen_and_i32(tmp, cpu_R[RRI8_S], cpu_R[RRI8_T]); gen_brcondi(dc, eq_ne, tmp, 0, 4 + RRI8_IMM8_SE); tcg_temp_free(tmp); } break; case 1: /*BEQ*/ /*BNE*/ case 2: /*BLT*/ /*BGE*/ case 3: /*BLTU*/ /*BGEU*/ gen_window_check2(dc, RRI8_S, RRI8_T); { static const TCGCond cond[] = { [1] = TCG_COND_EQ, [2] = TCG_COND_LT, [3] = TCG_COND_LTU, [9] = TCG_COND_NE, [10] = TCG_COND_GE, [11] = TCG_COND_GEU, }; gen_brcond(dc, cond[RRI8_R], cpu_R[RRI8_S], cpu_R[RRI8_T], 4 + RRI8_IMM8_SE); } break; case 4: /*BALL*/ /*BNALL*/ gen_window_check2(dc, RRI8_S, RRI8_T); { TCGv_i32 tmp = tcg_temp_new_i32(); tcg_gen_and_i32(tmp, cpu_R[RRI8_S], cpu_R[RRI8_T]); gen_brcond(dc, eq_ne, tmp, cpu_R[RRI8_T], 4 + RRI8_IMM8_SE); tcg_temp_free(tmp); } break; case 5: /*BBC*/ /*BBS*/ gen_window_check2(dc, RRI8_S, RRI8_T); { #ifdef TARGET_WORDS_BIGENDIAN TCGv_i32 bit = tcg_const_i32(0x80000000); #else TCGv_i32 bit = tcg_const_i32(0x00000001); #endif TCGv_i32 tmp = tcg_temp_new_i32(); tcg_gen_andi_i32(tmp, cpu_R[RRI8_T], 0x1f); #ifdef TARGET_WORDS_BIGENDIAN tcg_gen_shr_i32(bit, bit, tmp); #else tcg_gen_shl_i32(bit, bit, tmp); #endif tcg_gen_and_i32(tmp, cpu_R[RRI8_S], bit); gen_brcondi(dc, eq_ne, tmp, 0, 4 + RRI8_IMM8_SE); tcg_temp_free(tmp); tcg_temp_free(bit); } break; case 6: /*BBCI*/ /*BBSI*/ case 7: gen_window_check1(dc, RRI8_S); { TCGv_i32 tmp = tcg_temp_new_i32(); tcg_gen_andi_i32(tmp, cpu_R[RRI8_S], #ifdef TARGET_WORDS_BIGENDIAN 0x80000000 >> (((RRI8_R & 1) << 4) | RRI8_T)); #else 0x00000001 << (((RRI8_R & 1) << 4) | RRI8_T)); #endif gen_brcondi(dc, eq_ne, tmp, 0, 4 + RRI8_IMM8_SE); tcg_temp_free(tmp); } break; } } break; #define gen_narrow_load_store(type) do { \ TCGv_i32 addr = tcg_temp_new_i32(); \ gen_window_check2(dc, RRRN_S, RRRN_T); \ tcg_gen_addi_i32(addr, cpu_R[RRRN_S], RRRN_R << 2); \ gen_load_store_alignment(dc, 2, addr, false); \ tcg_gen_qemu_##type(cpu_R[RRRN_T], addr, dc->cring); \ tcg_temp_free(addr); \ } while (0) case 8: /*L32I.Nn*/ gen_narrow_load_store(ld32u); break; case 9: /*S32I.Nn*/ gen_narrow_load_store(st32); break; #undef gen_narrow_load_store case 10: /*ADD.Nn*/ gen_window_check3(dc, RRRN_R, RRRN_S, RRRN_T); tcg_gen_add_i32(cpu_R[RRRN_R], cpu_R[RRRN_S], cpu_R[RRRN_T]); break; case 11: /*ADDI.Nn*/ gen_window_check2(dc, RRRN_R, RRRN_S); tcg_gen_addi_i32(cpu_R[RRRN_R], cpu_R[RRRN_S], RRRN_T ? RRRN_T : -1); break; case 12: /*ST2n*/ gen_window_check1(dc, RRRN_S); if (RRRN_T < 8) { /*MOVI.Nn*/ tcg_gen_movi_i32(cpu_R[RRRN_S], RRRN_R | (RRRN_T << 4) | ((RRRN_T & 6) == 6 ? 0xffffff80 : 0)); } else { /*BEQZ.Nn*/ /*BNEZ.Nn*/ TCGCond eq_ne = (RRRN_T & 4) ? TCG_COND_NE : TCG_COND_EQ; gen_brcondi(dc, eq_ne, cpu_R[RRRN_S], 0, 4 + (RRRN_R | ((RRRN_T & 3) << 4))); } break; case 13: /*ST3n*/ switch (RRRN_R) { case 0: /*MOV.Nn*/ gen_window_check2(dc, RRRN_S, RRRN_T); tcg_gen_mov_i32(cpu_R[RRRN_T], cpu_R[RRRN_S]); break; case 15: /*S3*/ switch (RRRN_T) { case 0: /*RET.Nn*/ gen_jump(dc, cpu_R[0]); break; case 1: /*RETW.Nn*/ HAS_OPTION(XTENSA_OPTION_WINDOWED_REGISTER); { TCGv_i32 tmp = tcg_const_i32(dc->pc); gen_advance_ccount(dc); gen_helper_retw(tmp, cpu_env, tmp); gen_jump(dc, tmp); tcg_temp_free(tmp); } break; case 2: /*BREAK.Nn*/ HAS_OPTION(XTENSA_OPTION_DEBUG); if (dc->debug) { gen_debug_exception(dc, DEBUGCAUSE_BN); } break; case 3: /*NOP.Nn*/ break; case 6: /*ILL.Nn*/ gen_exception_cause(dc, ILLEGAL_INSTRUCTION_CAUSE); break; default: /*reserved*/ RESERVED(); break; } break; default: /*reserved*/ RESERVED(); break; } break; default: /*reserved*/ RESERVED(); break; } if (dc->is_jmp == DISAS_NEXT) { gen_check_loop_end(dc, 0); } dc->pc = dc->next_pc; return; invalid_opcode: qemu_log("INVALID(pc = %08x)\n", dc->pc); gen_exception_cause(dc, ILLEGAL_INSTRUCTION_CAUSE); #undef HAS_OPTION }


static void derive_spatial_merge_candidates(HEVCContext *s, int x0, int y0, int nPbW, int nPbH, int log2_cb_size, int singleMCLFlag, int part_idx, int merge_idx, struct MvField mergecandlist[]) { HEVCLocalContext *lc = &s->HEVClc; RefPicList *refPicList = s->ref->refPicList; MvField *tab_mvf = s->ref->tab_mvf; const int min_pu_width = s->sps->min_pu_width; const int cand_bottom_left = lc->na.cand_bottom_left; const int cand_left = lc->na.cand_left; const int cand_up_left = lc->na.cand_up_left; const int cand_up = lc->na.cand_up; const int cand_up_right = lc->na.cand_up_right_sap; const int xA1 = x0 - 1; const int yA1 = y0 + nPbH - 1; const int xA1_pu = xA1 >> s->sps->log2_min_pu_size; const int yA1_pu = yA1 >> s->sps->log2_min_pu_size; const int xB1 = x0 + nPbW - 1; const int yB1 = y0 - 1; const int xB1_pu = xB1 >> s->sps->log2_min_pu_size; const int yB1_pu = yB1 >> s->sps->log2_min_pu_size; const int xB0 = x0 + nPbW; const int yB0 = y0 - 1; const int xB0_pu = xB0 >> s->sps->log2_min_pu_size; const int yB0_pu = yB0 >> s->sps->log2_min_pu_size; const int xA0 = x0 - 1; const int yA0 = y0 + nPbH; const int xA0_pu = xA0 >> s->sps->log2_min_pu_size; const int yA0_pu = yA0 >> s->sps->log2_min_pu_size; const int xB2 = x0 - 1; const int yB2 = y0 - 1; const int xB2_pu = xB2 >> s->sps->log2_min_pu_size; const int yB2_pu = yB2 >> s->sps->log2_min_pu_size; const int nb_refs = (s->sh.slice_type == P_SLICE) ? s->sh.nb_refs[0] : FFMIN(s->sh.nb_refs[0], s->sh.nb_refs[1]); int check_MER = 1; int check_MER_1 = 1; int zero_idx = 0; int nb_merge_cand = 0; int nb_orig_merge_cand = 0; int is_available_a0; int is_available_a1; int is_available_b0; int is_available_b1; int is_available_b2; int check_B0; int check_A0; //first left spatial merge candidate is_available_a1 = AVAILABLE(cand_left, A1); if (!singleMCLFlag && part_idx == 1 && (lc->cu.part_mode == PART_Nx2N || lc->cu.part_mode == PART_nLx2N || lc->cu.part_mode == PART_nRx2N) || isDiffMER(s, xA1, yA1, x0, y0)) { is_available_a1 = 0; } if (is_available_a1) { mergecandlist[0] = TAB_MVF_PU(A1); if (merge_idx == 0) return; nb_merge_cand++; } // above spatial merge candidate is_available_b1 = AVAILABLE(cand_up, B1); if (!singleMCLFlag && part_idx == 1 && (lc->cu.part_mode == PART_2NxN || lc->cu.part_mode == PART_2NxnU || lc->cu.part_mode == PART_2NxnD) || isDiffMER(s, xB1, yB1, x0, y0)) { is_available_b1 = 0; } if (is_available_a1 && is_available_b1) check_MER = !COMPARE_MV_REFIDX(B1, A1); if (is_available_b1 && check_MER) mergecandlist[nb_merge_cand++] = TAB_MVF_PU(B1); // above right spatial merge candidate check_MER = 1; check_B0 = PRED_BLOCK_AVAILABLE(B0); is_available_b0 = check_B0 && AVAILABLE(cand_up_right, B0); if (isDiffMER(s, xB0, yB0, x0, y0)) is_available_b0 = 0; if (is_available_b1 && is_available_b0) check_MER = !COMPARE_MV_REFIDX(B0, B1); if (is_available_b0 && check_MER) { mergecandlist[nb_merge_cand] = TAB_MVF_PU(B0); if (merge_idx == nb_merge_cand) return; nb_merge_cand++; } // left bottom spatial merge candidate check_MER = 1; check_A0 = PRED_BLOCK_AVAILABLE(A0); is_available_a0 = check_A0 && AVAILABLE(cand_bottom_left, A0); if (isDiffMER(s, xA0, yA0, x0, y0)) is_available_a0 = 0; if (is_available_a1 && is_available_a0) check_MER = !COMPARE_MV_REFIDX(A0, A1); if (is_available_a0 && check_MER) { mergecandlist[nb_merge_cand] = TAB_MVF_PU(A0); if (merge_idx == nb_merge_cand) return; nb_merge_cand++; } // above left spatial merge candidate check_MER = 1; is_available_b2 = AVAILABLE(cand_up_left, B2); if (isDiffMER(s, xB2, yB2, x0, y0)) is_available_b2 = 0; if (is_available_a1 && is_available_b2) check_MER = !COMPARE_MV_REFIDX(B2, A1); if (is_available_b1 && is_available_b2) check_MER_1 = !COMPARE_MV_REFIDX(B2, B1); if (is_available_b2 && check_MER && check_MER_1 && nb_merge_cand != 4) { mergecandlist[nb_merge_cand] = TAB_MVF_PU(B2); if (merge_idx == nb_merge_cand) return; nb_merge_cand++; } // temporal motion vector candidate if (s->sh.slice_temporal_mvp_enabled_flag && nb_merge_cand < s->sh.max_num_merge_cand) { Mv mv_l0_col, mv_l1_col; int available_l0 = temporal_luma_motion_vector(s, x0, y0, nPbW, nPbH, 0, &mv_l0_col, 0); int available_l1 = (s->sh.slice_type == B_SLICE) ? temporal_luma_motion_vector(s, x0, y0, nPbW, nPbH, 0, &mv_l1_col, 1) : 0; if (available_l0 || available_l1) { mergecandlist[nb_merge_cand].is_intra = 0; mergecandlist[nb_merge_cand].pred_flag[0] = available_l0; mergecandlist[nb_merge_cand].pred_flag[1] = available_l1; AV_ZERO16(mergecandlist[nb_merge_cand].ref_idx); mergecandlist[nb_merge_cand].mv[0] = mv_l0_col; mergecandlist[nb_merge_cand].mv[1] = mv_l1_col; if (merge_idx == nb_merge_cand) return; nb_merge_cand++; } } nb_orig_merge_cand = nb_merge_cand; // combined bi-predictive merge candidates (applies for B slices) if (s->sh.slice_type == B_SLICE && nb_orig_merge_cand > 1 && nb_orig_merge_cand < s->sh.max_num_merge_cand) { int comb_idx; for (comb_idx = 0; nb_merge_cand < s->sh.max_num_merge_cand && comb_idx < nb_orig_merge_cand * (nb_orig_merge_cand - 1); comb_idx++) { int l0_cand_idx = l0_l1_cand_idx[comb_idx][0]; int l1_cand_idx = l0_l1_cand_idx[comb_idx][1]; MvField l0_cand = mergecandlist[l0_cand_idx]; MvField l1_cand = mergecandlist[l1_cand_idx]; if (l0_cand.pred_flag[0] && l1_cand.pred_flag[1] && (refPicList[0].list[l0_cand.ref_idx[0]] != refPicList[1].list[l1_cand.ref_idx[1]] || AV_RN32A(&l0_cand.mv[0]) != AV_RN32A(&l1_cand.mv[1]))) { mergecandlist[nb_merge_cand].ref_idx[0] = l0_cand.ref_idx[0]; mergecandlist[nb_merge_cand].ref_idx[1] = l1_cand.ref_idx[1]; mergecandlist[nb_merge_cand].pred_flag[0] = 1; mergecandlist[nb_merge_cand].pred_flag[1] = 1; AV_COPY32(&mergecandlist[nb_merge_cand].mv[0], &l0_cand.mv[0]); AV_COPY32(&mergecandlist[nb_merge_cand].mv[1], &l1_cand.mv[1]); mergecandlist[nb_merge_cand].is_intra = 0; if (merge_idx == nb_merge_cand) return; nb_merge_cand++; } } } // append Zero motion vector candidates while (nb_merge_cand < s->sh.max_num_merge_cand) { mergecandlist[nb_merge_cand].pred_flag[0] = 1; mergecandlist[nb_merge_cand].pred_flag[1] = s->sh.slice_type == B_SLICE; AV_ZERO32(mergecandlist[nb_merge_cand].mv + 0); AV_ZERO32(mergecandlist[nb_merge_cand].mv + 1); mergecandlist[nb_merge_cand].is_intra = 0; mergecandlist[nb_merge_cand].ref_idx[0] = zero_idx < nb_refs ? zero_idx : 0; mergecandlist[nb_merge_cand].ref_idx[1] = zero_idx < nb_refs ? zero_idx : 0; if (merge_idx == nb_merge_cand) return; nb_merge_cand++; zero_idx++; } }


void ff_avg_h264_qpel4_mc12_msa(uint8_t *dst, const uint8_t *src, ptrdiff_t stride) { avc_luma_midh_qrt_and_aver_dst_4w_msa(src - (2 * stride) - 2, stride, dst, stride, 4, 0); }


static void decode_postinit(H264Context *h, int setup_finished) { const SPS *sps = h->ps.sps; H264Picture *out = h->cur_pic_ptr; H264Picture *cur = h->cur_pic_ptr; int i, pics, out_of_order, out_idx; int invalid = 0, cnt = 0; h->cur_pic_ptr->f->pict_type = h->pict_type; if (h->next_output_pic) return; if (cur->field_poc[0] == INT_MAX || cur->field_poc[1] == INT_MAX) { /* FIXME: if we have two PAFF fields in one packet, we can't start * the next thread here. If we have one field per packet, we can. * The check in decode_nal_units() is not good enough to find this * yet, so we assume the worst for now. */ // if (setup_finished) // ff_thread_finish_setup(h->avctx); return; } cur->f->interlaced_frame = 0; cur->f->repeat_pict = 0; /* Signal interlacing information externally. */ /* Prioritize picture timing SEI information over used * decoding process if it exists. */ if (sps->pic_struct_present_flag) { H264SEIPictureTiming *pt = &h->sei.picture_timing; switch (pt->pic_struct) { case SEI_PIC_STRUCT_FRAME: break; case SEI_PIC_STRUCT_TOP_FIELD: case SEI_PIC_STRUCT_BOTTOM_FIELD: cur->f->interlaced_frame = 1; break; case SEI_PIC_STRUCT_TOP_BOTTOM: case SEI_PIC_STRUCT_BOTTOM_TOP: if (FIELD_OR_MBAFF_PICTURE(h)) cur->f->interlaced_frame = 1; else // try to flag soft telecine progressive cur->f->interlaced_frame = h->prev_interlaced_frame; break; case SEI_PIC_STRUCT_TOP_BOTTOM_TOP: case SEI_PIC_STRUCT_BOTTOM_TOP_BOTTOM: /* Signal the possibility of telecined film externally * (pic_struct 5,6). From these hints, let the applications * decide if they apply deinterlacing. */ cur->f->repeat_pict = 1; break; case SEI_PIC_STRUCT_FRAME_DOUBLING: cur->f->repeat_pict = 2; break; case SEI_PIC_STRUCT_FRAME_TRIPLING: cur->f->repeat_pict = 4; break; } if ((pt->ct_type & 3) && pt->pic_struct <= SEI_PIC_STRUCT_BOTTOM_TOP) cur->f->interlaced_frame = (pt->ct_type & (1 << 1)) != 0; } else { /* Derive interlacing flag from used decoding process. */ cur->f->interlaced_frame = FIELD_OR_MBAFF_PICTURE(h); } h->prev_interlaced_frame = cur->f->interlaced_frame; if (cur->field_poc[0] != cur->field_poc[1]) { /* Derive top_field_first from field pocs. */ cur->f->top_field_first = cur->field_poc[0] < cur->field_poc[1]; } else { if (cur->f->interlaced_frame || sps->pic_struct_present_flag) { /* Use picture timing SEI information. Even if it is a * information of a past frame, better than nothing. */ if (h->sei.picture_timing.pic_struct == SEI_PIC_STRUCT_TOP_BOTTOM || h->sei.picture_timing.pic_struct == SEI_PIC_STRUCT_TOP_BOTTOM_TOP) cur->f->top_field_first = 1; else cur->f->top_field_first = 0; } else { /* Most likely progressive */ cur->f->top_field_first = 0; } } if (h->sei.frame_packing.present && h->sei.frame_packing.arrangement_type >= 0 && h->sei.frame_packing.arrangement_type <= 6 && h->sei.frame_packing.content_interpretation_type > 0 && h->sei.frame_packing.content_interpretation_type < 3) { H264SEIFramePacking *fp = &h->sei.frame_packing; AVStereo3D *stereo = av_stereo3d_create_side_data(cur->f); if (!stereo) return; switch (fp->arrangement_type) { case 0: stereo->type = AV_STEREO3D_CHECKERBOARD; break; case 1: stereo->type = AV_STEREO3D_COLUMNS; break; case 2: stereo->type = AV_STEREO3D_LINES; break; case 3: if (fp->quincunx_subsampling) stereo->type = AV_STEREO3D_SIDEBYSIDE_QUINCUNX; else stereo->type = AV_STEREO3D_SIDEBYSIDE; break; case 4: stereo->type = AV_STEREO3D_TOPBOTTOM; break; case 5: stereo->type = AV_STEREO3D_FRAMESEQUENCE; break; case 6: stereo->type = AV_STEREO3D_2D; break; } if (fp->content_interpretation_type == 2) stereo->flags = AV_STEREO3D_FLAG_INVERT; } if (h->sei.display_orientation.present && (h->sei.display_orientation.anticlockwise_rotation || h->sei.display_orientation.hflip || h->sei.display_orientation.vflip)) { H264SEIDisplayOrientation *o = &h->sei.display_orientation; double angle = o->anticlockwise_rotation * 360 / (double) (1 << 16); AVFrameSideData *rotation = av_frame_new_side_data(cur->f, AV_FRAME_DATA_DISPLAYMATRIX, sizeof(int32_t) * 9); if (!rotation) return; av_display_rotation_set((int32_t *)rotation->data, angle); av_display_matrix_flip((int32_t *)rotation->data, o->hflip, o->vflip); } if (h->sei.afd.present) { AVFrameSideData *sd = av_frame_new_side_data(cur->f, AV_FRAME_DATA_AFD, sizeof(uint8_t)); if (!sd) return; *sd->data = h->sei.afd.active_format_description; h->sei.afd.present = 0; } if (h->sei.a53_caption.a53_caption) { H264SEIA53Caption *a53 = &h->sei.a53_caption; AVFrameSideData *sd = av_frame_new_side_data(cur->f, AV_FRAME_DATA_A53_CC, a53->a53_caption_size); if (!sd) return; memcpy(sd->data, a53->a53_caption, a53->a53_caption_size); av_freep(&a53->a53_caption); a53->a53_caption_size = 0; } // FIXME do something with unavailable reference frames /* Sort B-frames into display order */ if (sps->bitstream_restriction_flag || h->avctx->strict_std_compliance >= FF_COMPLIANCE_NORMAL) { h->avctx->has_b_frames = FFMAX(h->avctx->has_b_frames, sps->num_reorder_frames); } h->low_delay = !h->avctx->has_b_frames; pics = 0; while (h->delayed_pic[pics]) pics++; assert(pics <= MAX_DELAYED_PIC_COUNT); h->delayed_pic[pics++] = cur; if (cur->reference == 0) cur->reference = DELAYED_PIC_REF; /* Frame reordering. This code takes pictures from coding order and sorts * them by their incremental POC value into display order. It supports POC * gaps, MMCO reset codes and random resets. * A "display group" can start either with a IDR frame (f.key_frame = 1), * and/or can be closed down with a MMCO reset code. In sequences where * there is no delay, we can't detect that (since the frame was already * output to the user), so we also set h->mmco_reset to detect the MMCO * reset code. * FIXME: if we detect insufficient delays (as per h->avctx->has_b_frames), * we increase the delay between input and output. All frames affected by * the lag (e.g. those that should have been output before another frame * that we already returned to the user) will be dropped. This is a bug * that we will fix later. */ for (i = 0; i < MAX_DELAYED_PIC_COUNT; i++) { cnt += out->poc < h->last_pocs[i]; invalid += out->poc == INT_MIN; } if (!h->mmco_reset && !cur->f->key_frame && cnt + invalid == MAX_DELAYED_PIC_COUNT && cnt > 0) { h->mmco_reset = 2; if (pics > 1) h->delayed_pic[pics - 2]->mmco_reset = 2; } if (h->mmco_reset || cur->f->key_frame) { for (i = 0; i < MAX_DELAYED_PIC_COUNT; i++) h->last_pocs[i] = INT_MIN; cnt = 0; invalid = MAX_DELAYED_PIC_COUNT; } out = h->delayed_pic[0]; out_idx = 0; for (i = 1; i < MAX_DELAYED_PIC_COUNT && h->delayed_pic[i] && !h->delayed_pic[i - 1]->mmco_reset && !h->delayed_pic[i]->f->key_frame; i++) if (h->delayed_pic[i]->poc < out->poc) { out = h->delayed_pic[i]; out_idx = i; } if (h->avctx->has_b_frames == 0 && (h->delayed_pic[0]->f->key_frame || h->mmco_reset)) h->next_outputed_poc = INT_MIN; out_of_order = !out->f->key_frame && !h->mmco_reset && (out->poc < h->next_outputed_poc); if (sps->bitstream_restriction_flag && h->avctx->has_b_frames >= sps->num_reorder_frames) { } else if (out_of_order && pics - 1 == h->avctx->has_b_frames && h->avctx->has_b_frames < MAX_DELAYED_PIC_COUNT) { if (invalid + cnt < MAX_DELAYED_PIC_COUNT) { h->avctx->has_b_frames = FFMAX(h->avctx->has_b_frames, cnt); } h->low_delay = 0; } else if (h->low_delay && ((h->next_outputed_poc != INT_MIN && out->poc > h->next_outputed_poc + 2) || cur->f->pict_type == AV_PICTURE_TYPE_B)) { h->low_delay = 0; h->avctx->has_b_frames++; } if (pics > h->avctx->has_b_frames) { out->reference &= ~DELAYED_PIC_REF; for (i = out_idx; h->delayed_pic[i]; i++) h->delayed_pic[i] = h->delayed_pic[i + 1]; } memmove(h->last_pocs, &h->last_pocs[1], sizeof(*h->last_pocs) * (MAX_DELAYED_PIC_COUNT - 1)); h->last_pocs[MAX_DELAYED_PIC_COUNT - 1] = cur->poc; if (!out_of_order && pics > h->avctx->has_b_frames) { h->next_output_pic = out; if (out->mmco_reset) { if (out_idx > 0) { h->next_outputed_poc = out->poc; h->delayed_pic[out_idx - 1]->mmco_reset = out->mmco_reset; } else { h->next_outputed_poc = INT_MIN; } } else { if (out_idx == 0 && pics > 1 && h->delayed_pic[0]->f->key_frame) { h->next_outputed_poc = INT_MIN; } else { h->next_outputed_poc = out->poc; } } h->mmco_reset = 0; } else { av_log(h->avctx, AV_LOG_DEBUG, "no picture\n"); } if (h->next_output_pic) { if (h->next_output_pic->recovered) { // We have reached an recovery point and all frames after it in // display order are "recovered". h->frame_recovered |= FRAME_RECOVERED_SEI; } h->next_output_pic->recovered |= !!(h->frame_recovered & FRAME_RECOVERED_SEI); } if (setup_finished && !h->avctx->hwaccel) { ff_thread_finish_setup(h->avctx); if (h->avctx->active_thread_type & FF_THREAD_FRAME) h->setup_finished = 1; } }


static int g2m_load_cursor(AVCodecContext *avctx, G2MContext *c, GetByteContext *gb) { int i, j, k; uint8_t *dst; uint32_t bits; uint32_t cur_size, cursor_w, cursor_h, cursor_stride; uint32_t cursor_hot_x, cursor_hot_y; int cursor_fmt; uint8_t *tmp; cur_size = bytestream2_get_be32(gb); cursor_w = bytestream2_get_byte(gb); cursor_h = bytestream2_get_byte(gb); cursor_hot_x = bytestream2_get_byte(gb); cursor_hot_y = bytestream2_get_byte(gb); cursor_fmt = bytestream2_get_byte(gb); cursor_stride = FFALIGN(cursor_w, c->cursor_fmt==1 ? 32 : 1) * 4; if (cursor_w < 1 || cursor_w > 256 || cursor_h < 1 || cursor_h > 256) { av_log(avctx, AV_LOG_ERROR, "Invalid cursor dimensions %dx%d\n", cursor_w, cursor_h); return AVERROR_INVALIDDATA; } if (cursor_hot_x > cursor_w || cursor_hot_y > cursor_h) { av_log(avctx, AV_LOG_WARNING, "Invalid hotspot position %d,%d\n", cursor_hot_x, cursor_hot_y); cursor_hot_x = FFMIN(cursor_hot_x, cursor_w - 1); cursor_hot_y = FFMIN(cursor_hot_y, cursor_h - 1); } if (cur_size - 9 > bytestream2_get_bytes_left(gb) || c->cursor_w * c->cursor_h / 4 > cur_size) { av_log(avctx, AV_LOG_ERROR, "Invalid cursor data size %d/%d\n", cur_size, bytestream2_get_bytes_left(gb)); return AVERROR_INVALIDDATA; } if (cursor_fmt != 1 && cursor_fmt != 32) { avpriv_report_missing_feature(avctx, "Cursor format %d", cursor_fmt); return AVERROR_PATCHWELCOME; } tmp = av_realloc(c->cursor, cursor_stride * cursor_h); if (!tmp) { av_log(avctx, AV_LOG_ERROR, "Cannot allocate cursor buffer\n"); return AVERROR(ENOMEM); } c->cursor = tmp; c->cursor_w = cursor_w; c->cursor_h = cursor_h; c->cursor_hot_x = cursor_hot_x; c->cursor_hot_y = cursor_hot_y; c->cursor_fmt = cursor_fmt; c->cursor_stride = cursor_stride; dst = c->cursor; switch (c->cursor_fmt) { case 1: // old monochrome for (j = 0; j < c->cursor_h; j++) { for (i = 0; i < c->cursor_w; i += 32) { bits = bytestream2_get_be32(gb); for (k = 0; k < 32; k++) { dst[0] = !!(bits & 0x80000000); dst += 4; bits <<= 1; } } } dst = c->cursor; for (j = 0; j < c->cursor_h; j++) { for (i = 0; i < c->cursor_w; i += 32) { bits = bytestream2_get_be32(gb); for (k = 0; k < 32; k++) { int mask_bit = !!(bits & 0x80000000); switch (dst[0] * 2 + mask_bit) { case 0: dst[0] = 0xFF; dst[1] = 0x00; dst[2] = 0x00; dst[3] = 0x00; break; case 1: dst[0] = 0xFF; dst[1] = 0xFF; dst[2] = 0xFF; dst[3] = 0xFF; break; default: dst[0] = 0x00; dst[1] = 0x00; dst[2] = 0x00; dst[3] = 0x00; } dst += 4; bits <<= 1; } } } break; case 32: // full colour /* skip monochrome version of the cursor and decode RGBA instead */ bytestream2_skip(gb, c->cursor_h * (FFALIGN(c->cursor_w, 32) >> 3)); for (j = 0; j < c->cursor_h; j++) { for (i = 0; i < c->cursor_w; i++) { int val = bytestream2_get_be32(gb); *dst++ = val >> 0; *dst++ = val >> 8; *dst++ = val >> 16; *dst++ = val >> 24; } } break; default: return AVERROR_PATCHWELCOME; } return 0; }


static int has_duration(AVFormatContext *ic) { int i; AVStream *st; for(i = 0;i < ic->nb_streams; i++) { st = ic->streams[i]; if (st->duration != AV_NOPTS_VALUE) return 1; } if (ic->duration) return 1; return 0; }


void virt_acpi_setup(VirtGuestInfo *guest_info) { AcpiBuildTables tables; AcpiBuildState *build_state; if (!guest_info->fw_cfg) { trace_virt_acpi_setup(); return; } if (!acpi_enabled) { trace_virt_acpi_setup(); return; } build_state = g_malloc0(sizeof *build_state); build_state->guest_info = guest_info; acpi_build_tables_init(&tables); virt_acpi_build(build_state->guest_info, &tables); /* Now expose it all to Guest */ build_state->table_mr = acpi_add_rom_blob(build_state, tables.table_data, ACPI_BUILD_TABLE_FILE, ACPI_BUILD_TABLE_MAX_SIZE); assert(build_state->table_mr != NULL); build_state->linker_mr = acpi_add_rom_blob(build_state, tables.linker, "etc/table-loader", 0); fw_cfg_add_file(guest_info->fw_cfg, ACPI_BUILD_TPMLOG_FILE, tables.tcpalog->data, acpi_data_len(tables.tcpalog)); build_state->rsdp_mr = acpi_add_rom_blob(build_state, tables.rsdp, ACPI_BUILD_RSDP_FILE, 0); qemu_register_reset(virt_acpi_build_reset, build_state); virt_acpi_build_reset(build_state); vmstate_register(NULL, 0, &vmstate_virt_acpi_build, build_state); /* Cleanup tables but don't free the memory: we track it * in build_state. */ acpi_build_tables_cleanup(&tables, false); }


void test_fenv(void) { struct __attribute__((packed)) { uint16_t fpuc; uint16_t dummy1; uint16_t fpus; uint16_t dummy2; uint16_t fptag; uint16_t dummy3; uint32_t ignored[4]; long double fpregs[8]; } float_env32; struct __attribute__((packed)) { uint16_t fpuc; uint16_t fpus; uint16_t fptag; uint16_t ignored[4]; long double fpregs[8]; } float_env16; double dtab[8]; double rtab[8]; int i; for(i=0;i<8;i++) dtab[i] = i + 1; TEST_ENV(&float_env16, "data16 fnstenv", "data16 fldenv"); TEST_ENV(&float_env16, "data16 fnsave", "data16 frstor"); TEST_ENV(&float_env32, "fnstenv", "fldenv"); TEST_ENV(&float_env32, "fnsave", "frstor"); /* test for ffree */ for(i=0;i<5;i++) asm volatile ("fldl %0" : : "m" (dtab[i])); asm volatile("ffree %st(2)"); asm volatile ("fnstenv %0\n" : : "m" (float_env32)); asm volatile ("fninit"); printf("fptag=%04x\n", float_env32.fptag); }


static void migrate_params_apply(MigrateSetParameters *params) { MigrationState *s = migrate_get_current(); /* TODO use QAPI_CLONE() instead of duplicating it inline */ if (params->has_compress_level) { s->parameters.compress_level = params->compress_level; } if (params->has_compress_threads) { s->parameters.compress_threads = params->compress_threads; } if (params->has_decompress_threads) { s->parameters.decompress_threads = params->decompress_threads; } if (params->has_cpu_throttle_initial) { s->parameters.cpu_throttle_initial = params->cpu_throttle_initial; } if (params->has_cpu_throttle_increment) { s->parameters.cpu_throttle_increment = params->cpu_throttle_increment; } if (params->has_tls_creds) { g_free(s->parameters.tls_creds); s->parameters.tls_creds = g_strdup(params->tls_creds); } if (params->has_tls_hostname) { g_free(s->parameters.tls_hostname); s->parameters.tls_hostname = g_strdup(params->tls_hostname); } if (params->has_max_bandwidth) { s->parameters.max_bandwidth = params->max_bandwidth; if (s->to_dst_file) { qemu_file_set_rate_limit(s->to_dst_file, s->parameters.max_bandwidth / XFER_LIMIT_RATIO); } } if (params->has_downtime_limit) { s->parameters.downtime_limit = params->downtime_limit; } if (params->has_x_checkpoint_delay) { s->parameters.x_checkpoint_delay = params->x_checkpoint_delay; if (migration_in_colo_state()) { colo_checkpoint_notify(s); } } if (params->has_block_incremental) { s->parameters.block_incremental = params->block_incremental; } }


void helper_mtc0_wired(CPUMIPSState *env, target_ulong arg1) { env->CP0_Wired = arg1 % env->tlb->nb_tlb; }


static int multiwrite_req_compare(const void *a, const void *b) { const BlockRequest *req1 = a, *req2 = b; /* * Note that we can't simply subtract req2->sector from req1->sector * here as that could overflow the return value. */ if (req1->sector > req2->sector) { return 1; } else if (req1->sector < req2->sector) { return -1; } else { return 0; } }


static void iothread_complete(UserCreatable *obj, Error **errp) { Error *local_error = NULL; IOThread *iothread = IOTHREAD(obj); iothread->stopping = false; iothread->thread_id = -1; iothread->ctx = aio_context_new(&local_error); if (!iothread->ctx) { error_propagate(errp, local_error); return; } qemu_mutex_init(&iothread->init_done_lock); qemu_cond_init(&iothread->init_done_cond); /* This assumes we are called from a thread with useful CPU affinity for us * to inherit. */ qemu_thread_create(&iothread->thread, "iothread", iothread_run, iothread, QEMU_THREAD_JOINABLE); /* Wait for initialization to complete */ qemu_mutex_lock(&iothread->init_done_lock); while (iothread->thread_id == -1) { qemu_cond_wait(&iothread->init_done_cond, &iothread->init_done_lock); } qemu_mutex_unlock(&iothread->init_done_lock); }


restore_fpu_state(CPUSPARCState *env, qemu_siginfo_fpu_t *fpu) { int err; #if 0 #ifdef CONFIG_SMP if (current->flags & PF_USEDFPU) regs->psr &= ~PSR_EF; #else if (current == last_task_used_math) { last_task_used_math = 0; regs->psr &= ~PSR_EF; } #endif current->used_math = 1; current->flags &= ~PF_USEDFPU; #endif #if 0 if (verify_area (VERIFY_READ, fpu, sizeof(*fpu))) return -EFAULT; #endif /* XXX: incorrect */ err = copy_from_user(&env->fpr[0], fpu->si_float_regs[0], (sizeof(abi_ulong) * 32)); err |= __get_user(env->fsr, &fpu->si_fsr); #if 0 err |= __get_user(current->thread.fpqdepth, &fpu->si_fpqdepth); if (current->thread.fpqdepth != 0) err |= __copy_from_user(&current->thread.fpqueue[0], &fpu->si_fpqueue[0], ((sizeof(unsigned long) + (sizeof(unsigned long *)))*16)); #endif return err; }


static int tta_decode_frame(AVCodecContext *avctx, void *data, int *data_size, AVPacket *avpkt) { const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; TTAContext *s = avctx->priv_data; int i; init_get_bits(&s->gb, buf, buf_size*8); { int cur_chan = 0, framelen = s->frame_length; int32_t *p; if (*data_size < (framelen * s->channels * 2)) { av_log(avctx, AV_LOG_ERROR, "Output buffer size is too small.\n"); return -1; } // FIXME: seeking s->total_frames--; if (!s->total_frames && s->last_frame_length) framelen = s->last_frame_length; // init per channel states for (i = 0; i < s->channels; i++) { s->ch_ctx[i].predictor = 0; ttafilter_init(&s->ch_ctx[i].filter, ttafilter_configs[s->bps-1][0], ttafilter_configs[s->bps-1][1]); rice_init(&s->ch_ctx[i].rice, 10, 10); } for (p = s->decode_buffer; p < s->decode_buffer + (framelen * s->channels); p++) { int32_t *predictor = &s->ch_ctx[cur_chan].predictor; TTAFilter *filter = &s->ch_ctx[cur_chan].filter; TTARice *rice = &s->ch_ctx[cur_chan].rice; uint32_t unary, depth, k; int32_t value; unary = tta_get_unary(&s->gb); if (unary == 0) { depth = 0; k = rice->k0; } else { depth = 1; k = rice->k1; unary--; } if (get_bits_left(&s->gb) < k) return -1; if (k) { if (k > MIN_CACHE_BITS) return -1; value = (unary << k) + get_bits(&s->gb, k); } else value = unary; // FIXME: copy paste from original switch (depth) { case 1: rice->sum1 += value - (rice->sum1 >> 4); if (rice->k1 > 0 && rice->sum1 < shift_16[rice->k1]) rice->k1--; else if(rice->sum1 > shift_16[rice->k1 + 1]) rice->k1++; value += shift_1[rice->k0]; default: rice->sum0 += value - (rice->sum0 >> 4); if (rice->k0 > 0 && rice->sum0 < shift_16[rice->k0]) rice->k0--; else if(rice->sum0 > shift_16[rice->k0 + 1]) rice->k0++; } // extract coded value #define UNFOLD(x) (((x)&1) ? (++(x)>>1) : (-(x)>>1)) *p = UNFOLD(value); // run hybrid filter ttafilter_process(filter, p, 0); // fixed order prediction #define PRED(x, k) (int32_t)((((uint64_t)x << k) - x) >> k) switch (s->bps) { case 1: *p += PRED(*predictor, 4); break; case 2: case 3: *p += PRED(*predictor, 5); break; case 4: *p += *predictor; break; } *predictor = *p; // flip channels if (cur_chan < (s->channels-1)) cur_chan++; else { // decorrelate in case of stereo integer if (s->channels > 1) { int32_t *r = p - 1; for (*p += *r / 2; r > p - s->channels; r--) *r = *(r + 1) - *r; } cur_chan = 0; } } if (get_bits_left(&s->gb) < 32) return -1; skip_bits(&s->gb, 32); // frame crc // convert to output buffer switch(s->bps) { case 2: { uint16_t *samples = data; for (p = s->decode_buffer; p < s->decode_buffer + (framelen * s->channels); p++) { *samples++ = *p; } *data_size = (uint8_t *)samples - (uint8_t *)data; break; } default: av_log(s->avctx, AV_LOG_ERROR, "Error, only 16bit samples supported!\n"); } } return buf_size; }


int qdev_init(DeviceState *dev) { int rc; assert(dev->state == DEV_STATE_CREATED); rc = dev->info->init(dev, dev->info); if (rc < 0) { qdev_free(dev); return rc; } qemu_register_reset(qdev_reset, dev); if (dev->info->vmsd) { vmstate_register_with_alias_id(dev, -1, dev->info->vmsd, dev, dev->instance_id_alias, dev->alias_required_for_version); } dev->state = DEV_STATE_INITIALIZED; return 0; }


static int coroutine_fn copy_sectors(BlockDriverState *bs, uint64_t start_sect, uint64_t cluster_offset, int n_start, int n_end) { BDRVQcowState *s = bs->opaque; QEMUIOVector qiov; struct iovec iov; int n, ret; /* * If this is the last cluster and it is only partially used, we must only * copy until the end of the image, or bdrv_check_request will fail for the * bdrv_read/write calls below. */ if (start_sect + n_end > bs->total_sectors) { n_end = bs->total_sectors - start_sect; } n = n_end - n_start; if (n <= 0) { return 0; } iov.iov_len = n * BDRV_SECTOR_SIZE; iov.iov_base = qemu_blockalign(bs, iov.iov_len); qemu_iovec_init_external(&qiov, &iov, 1); BLKDBG_EVENT(bs->file, BLKDBG_COW_READ); if (!bs->drv) { return -ENOMEDIUM; } /* Call .bdrv_co_readv() directly instead of using the public block-layer * interface. This avoids double I/O throttling and request tracking, * which can lead to deadlock when block layer copy-on-read is enabled. */ ret = bs->drv->bdrv_co_readv(bs, start_sect + n_start, n, &qiov); if (ret < 0) { goto out; } if (s->crypt_method) { qcow2_encrypt_sectors(s, start_sect + n_start, iov.iov_base, iov.iov_base, n, 1, &s->aes_encrypt_key); } ret = qcow2_pre_write_overlap_check(bs, 0, cluster_offset + n_start * BDRV_SECTOR_SIZE, n * BDRV_SECTOR_SIZE); if (ret < 0) { goto out; } BLKDBG_EVENT(bs->file, BLKDBG_COW_WRITE); ret = bdrv_co_writev(bs->file, (cluster_offset >> 9) + n_start, n, &qiov); if (ret < 0) { goto out; } ret = 0; out: qemu_vfree(iov.iov_base); return ret; }


static int xhci_ep_nuke_xfers(XHCIState *xhci, unsigned int slotid, unsigned int epid, TRBCCode report) { XHCISlot *slot; XHCIEPContext *epctx; int i, xferi, killed = 0; USBEndpoint *ep = NULL; assert(slotid >= 1 && slotid <= xhci->numslots); assert(epid >= 1 && epid <= 31); DPRINTF("xhci_ep_nuke_xfers(%d, %d)\n", slotid, epid); slot = &xhci->slots[slotid-1]; if (!slot->eps[epid-1]) { return 0; } epctx = slot->eps[epid-1]; xferi = epctx->next_xfer; for (i = 0; i < TD_QUEUE; i++) { killed += xhci_ep_nuke_one_xfer(&epctx->transfers[xferi], report); if (killed) { report = 0; /* Only report once */ } epctx->transfers[xferi].packet.ep = NULL; xferi = (xferi + 1) % TD_QUEUE; } ep = xhci_epid_to_usbep(xhci, slotid, epid); if (ep) { usb_device_ep_stopped(ep->dev, ep); } return killed; }


static inline void gen_branch_slot(uint32_t delayed_pc, int t) { TCGv sr; int label = gen_new_label(); tcg_gen_movi_i32(cpu_delayed_pc, delayed_pc); sr = tcg_temp_new(); tcg_gen_andi_i32(sr, cpu_sr, SR_T); tcg_gen_brcondi_i32(t ? TCG_COND_EQ:TCG_COND_NE, sr, 0, label); tcg_gen_ori_i32(cpu_flags, cpu_flags, DELAY_SLOT_TRUE); gen_set_label(label); }


static void put_fid(V9fsPDU *pdu, V9fsFidState *fidp) { BUG_ON(!fidp->ref); fidp->ref--; /* * Don't free the fid if it is in reclaim list */ if (!fidp->ref && fidp->clunked) { if (fidp->fid == pdu->s->root_fid) { /* * if the clunked fid is root fid then we * have unmounted the fs on the client side. * delete the migration blocker. Ideally, this * should be hooked to transport close notification */ if (pdu->s->migration_blocker) { migrate_del_blocker(pdu->s->migration_blocker); error_free(pdu->s->migration_blocker); pdu->s->migration_blocker = NULL; } } free_fid(pdu, fidp); } }


static inline void RENAME(rgb16to15)(const uint8_t *src,uint8_t *dst,unsigned src_size) { register const uint8_t* s=src; register uint8_t* d=dst; register const uint8_t *end; const uint8_t *mm_end; end = s + src_size; #ifdef HAVE_MMX __asm __volatile(PREFETCH" %0"::"m"(*s)); __asm __volatile("movq %0, %%mm7"::"m"(mask15rg)); __asm __volatile("movq %0, %%mm6"::"m"(mask15b)); mm_end = end - 15; while(s<mm_end) { __asm __volatile( PREFETCH" 32%1\n\t" "movq %1, %%mm0\n\t" "movq 8%1, %%mm2\n\t" "movq %%mm0, %%mm1\n\t" "movq %%mm2, %%mm3\n\t" "psrlq $1, %%mm0\n\t" "psrlq $1, %%mm2\n\t" "pand %%mm7, %%mm0\n\t" "pand %%mm7, %%mm2\n\t" "pand %%mm6, %%mm1\n\t" "pand %%mm6, %%mm3\n\t" "por %%mm1, %%mm0\n\t" "por %%mm3, %%mm2\n\t" MOVNTQ" %%mm0, %0\n\t" MOVNTQ" %%mm2, 8%0" :"=m"(*d) :"m"(*s) ); d+=16; s+=16; } __asm __volatile(SFENCE:::"memory"); __asm __volatile(EMMS:::"memory"); #endif mm_end = end - 3; while(s < mm_end) { register uint32_t x= *((uint32_t *)s); *((uint32_t *)d) = ((x>>1)&0x7FE07FE0) | (x&0x001F001F); s+=4; d+=4; } if(s < end) { register uint16_t x= *((uint16_t *)s); *((uint16_t *)d) = ((x>>1)&0x7FE0) | (x&0x001F); s+=2; d+=2; } }


static void moxiesim_init(MachineState *machine) { MoxieCPU *cpu = NULL; ram_addr_t ram_size = machine->ram_size; const char *cpu_model = machine->cpu_model; const char *kernel_filename = machine->kernel_filename; const char *kernel_cmdline = machine->kernel_cmdline; const char *initrd_filename = machine->initrd_filename; CPUMoxieState *env; MemoryRegion *address_space_mem = get_system_memory(); MemoryRegion *ram = g_new(MemoryRegion, 1); MemoryRegion *rom = g_new(MemoryRegion, 1); hwaddr ram_base = 0x200000; LoaderParams loader_params; /* Init CPUs. */ if (cpu_model == NULL) { cpu_model = "MoxieLite-moxie-cpu"; } cpu = MOXIE_CPU(cpu_generic_init(TYPE_MOXIE_CPU, cpu_model)); if (!cpu) { fprintf(stderr, "Unable to find CPU definition\n"); exit(1); } env = &cpu->env; qemu_register_reset(main_cpu_reset, cpu); /* Allocate RAM. */ memory_region_init_ram(ram, NULL, "moxiesim.ram", ram_size, &error_fatal); memory_region_add_subregion(address_space_mem, ram_base, ram); memory_region_init_ram(rom, NULL, "moxie.rom", 128 * 0x1000, &error_fatal); memory_region_add_subregion(get_system_memory(), 0x1000, rom); if (kernel_filename) { loader_params.ram_size = ram_size; loader_params.kernel_filename = kernel_filename; loader_params.kernel_cmdline = kernel_cmdline; loader_params.initrd_filename = initrd_filename; load_kernel(cpu, &loader_params); } /* A single 16450 sits at offset 0x3f8. */ if (serial_hds[0]) { serial_mm_init(address_space_mem, 0x3f8, 0, env->irq[4], 8000000/16, serial_hds[0], DEVICE_LITTLE_ENDIAN); } }


static void build_guest_fsinfo_for_virtual_device(char const *syspath, GuestFilesystemInfo *fs, Error **errp) { DIR *dir; char *dirpath; struct dirent entry, *result; dirpath = g_strdup_printf("%s/slaves", syspath); dir = opendir(dirpath); if (!dir) { error_setg_errno(errp, errno, "opendir(\"%s\")", dirpath); g_free(dirpath); return; } g_free(dirpath); for (;;) { if (readdir_r(dir, &entry, &result) != 0) { error_setg_errno(errp, errno, "readdir_r(\"%s\")", dirpath); break; } if (!result) { break; } if (entry.d_type == DT_LNK) { g_debug(" slave device '%s'", entry.d_name); dirpath = g_strdup_printf("%s/slaves/%s", syspath, entry.d_name); build_guest_fsinfo_for_device(dirpath, fs, errp); g_free(dirpath); if (*errp) { break; } } } closedir(dir); }


void write_video_frame(AVFormatContext *oc, AVStream *st) { int x, y, i, out_size; AVCodecContext *c; c = &st->codec; /* prepare a dummy image */ /* Y */ i = frame_count++; for(y=0;y<c->height;y++) { for(x=0;x<c->width;x++) { picture->data[0][y * picture->linesize[0] + x] = x + y + i * 3; } } /* Cb and Cr */ for(y=0;y<c->height/2;y++) { for(x=0;x<c->width/2;x++) { picture->data[1][y * picture->linesize[1] + x] = 128 + y + i * 2; picture->data[2][y * picture->linesize[2] + x] = 64 + x + i * 5; } } /* encode the image */ out_size = avcodec_encode_video(c, video_outbuf, video_outbuf_size, picture); /* write the compressed frame in the media file */ if (av_write_frame(oc, st->index, video_outbuf, out_size) != 0) { fprintf(stderr, "Error while writing video frame\n"); exit(1); } }