static void wiener_denoise(WMAVoiceContext *s, int fcb_type, float *synth_pf, int size, const float *lpcs) { int remainder, lim, n; if (fcb_type != FCB_TYPE_SILENCE) { float *tilted_lpcs = s->tilted_lpcs_pf, *coeffs = s->denoise_coeffs_pf, tilt_mem = 0; tilted_lpcs[0] = 1.0; memcpy(&tilted_lpcs[1], lpcs, sizeof(lpcs[0]) * s->lsps); memset(&tilted_lpcs[s->lsps + 1], 0, sizeof(tilted_lpcs[0]) * (128 - s->lsps - 1)); ff_tilt_compensation(&tilt_mem, 0.7 * tilt_factor(lpcs, s->lsps), tilted_lpcs, s->lsps + 2); /* The IRDFT output (127 samples for 7-bit filter) beyond the frame * size is applied to the next frame. All input beyond this is zero, * and thus all output beyond this will go towards zero, hence we can * limit to min(size-1, 127-size) as a performance consideration. */ remainder = FFMIN(127 - size, size - 1); calc_input_response(s, tilted_lpcs, fcb_type, coeffs, remainder); /* apply coefficients (in frequency spectrum domain), i.e. complex * number multiplication */ memset(&synth_pf[size], 0, sizeof(synth_pf[0]) * (128 - size)); ff_rdft_calc(&s->rdft, synth_pf); ff_rdft_calc(&s->rdft, coeffs); synth_pf[0] *= coeffs[0]; synth_pf[1] *= coeffs[1]; for (n = 1; n < 128; n++) { float v1 = synth_pf[n * 2], v2 = synth_pf[n * 2 + 1]; synth_pf[n * 2] = v1 * coeffs[n * 2] - v2 * coeffs[n * 2 + 1]; synth_pf[n * 2 + 1] = v2 * coeffs[n * 2] + v1 * coeffs[n * 2 + 1]; } ff_rdft_calc(&s->irdft, synth_pf); } /* merge filter output with the history of previous runs */ if (s->denoise_filter_cache_size) { lim = FFMIN(s->denoise_filter_cache_size, size); for (n = 0; n < lim; n++) synth_pf[n] += s->denoise_filter_cache[n]; s->denoise_filter_cache_size -= lim; memmove(s->denoise_filter_cache, &s->denoise_filter_cache[size], sizeof(s->denoise_filter_cache[0]) * s->denoise_filter_cache_size); } /* move remainder of filter output into a cache for future runs */ if (fcb_type != FCB_TYPE_SILENCE) { lim = FFMIN(remainder, s->denoise_filter_cache_size); for (n = 0; n < lim; n++) s->denoise_filter_cache[n] += synth_pf[size + n]; if (lim < remainder) { memcpy(&s->denoise_filter_cache[lim], &synth_pf[size + lim], sizeof(s->denoise_filter_cache[0]) * (remainder - lim)); s->denoise_filter_cache_size = remainder; } } }


static av_always_inline int check_4block_inter(SnowContext *s, int mb_x, int mb_y, int p0, int p1, int ref, int *best_rd){ const int b_stride= s->b_width << s->block_max_depth; BlockNode *block= &s->block[mb_x + mb_y * b_stride]; BlockNode backup[4]= {block[0], block[1], block[b_stride], block[b_stride+1]}; int rd, index, value; assert(mb_x>=0 && mb_y>=0); assert(mb_x<b_stride); assert(((mb_x|mb_y)&1) == 0); index= (p0 + 31*p1) & (ME_CACHE_SIZE-1); value= s->me_cache_generation + (p0>>10) + (p1<<6) + (block->ref<<12); if(s->me_cache[index] == value) return 0; s->me_cache[index]= value; block->mx= p0; block->my= p1; block->ref= ref; block->type &= ~BLOCK_INTRA; block[1]= block[b_stride]= block[b_stride+1]= *block; rd= get_4block_rd(s, mb_x, mb_y, 0); //FIXME chroma if(rd < *best_rd){ *best_rd= rd; return 1; }else{ block[0]= backup[0]; block[1]= backup[1]; block[b_stride]= backup[2]; block[b_stride+1]= backup[3]; return 0; } }


int qemu_signalfd(const sigset_t *mask) { #if defined(CONFIG_signalfd) int ret; ret = syscall(SYS_signalfd, -1, mask, _NSIG / 8); if (ret != -1) return ret; #endif return qemu_signalfd_compat(mask); }


static int vtd_dev_to_context_entry(IntelIOMMUState *s, uint8_t bus_num, uint8_t devfn, VTDContextEntry *ce) { VTDRootEntry re; int ret_fr; ret_fr = vtd_get_root_entry(s, bus_num, &re); if (ret_fr) { return ret_fr; } if (!vtd_root_entry_present(&re)) { /* Not error - it's okay we don't have root entry. */ trace_vtd_re_not_present(bus_num); return -VTD_FR_ROOT_ENTRY_P; } else if (re.rsvd || (re.val & VTD_ROOT_ENTRY_RSVD)) { trace_vtd_re_invalid(re.rsvd, re.val); return -VTD_FR_ROOT_ENTRY_RSVD; } ret_fr = vtd_get_context_entry_from_root(&re, devfn, ce); if (ret_fr) { return ret_fr; } if (!vtd_ce_present(ce)) { /* Not error - it's okay we don't have context entry. */ trace_vtd_ce_not_present(bus_num, devfn); return -VTD_FR_CONTEXT_ENTRY_P; } else if ((ce->hi & VTD_CONTEXT_ENTRY_RSVD_HI) || (ce->lo & VTD_CONTEXT_ENTRY_RSVD_LO)) { trace_vtd_ce_invalid(ce->hi, ce->lo); return -VTD_FR_CONTEXT_ENTRY_RSVD; } /* Check if the programming of context-entry is valid */ if (!vtd_is_level_supported(s, vtd_ce_get_level(ce))) { trace_vtd_ce_invalid(ce->hi, ce->lo); return -VTD_FR_CONTEXT_ENTRY_INV; } else { switch (vtd_ce_get_type(ce)) { case VTD_CONTEXT_TT_MULTI_LEVEL: /* fall through */ case VTD_CONTEXT_TT_DEV_IOTLB: break; default: trace_vtd_ce_invalid(ce->hi, ce->lo); return -VTD_FR_CONTEXT_ENTRY_INV; } } return 0; }


static int get_buffer(AVCodecContext *avctx, AVFrame *pic) { pic->type = FF_BUFFER_TYPE_USER; pic->data[0] = (void *)1; return 0; }


uint32_t HELPER(v7m_mrs)(CPUARMState *env, uint32_t reg) { ARMCPU *cpu = arm_env_get_cpu(env); switch (reg) { case 0: /* APSR */ return xpsr_read(env) & 0xf8000000; case 1: /* IAPSR */ return xpsr_read(env) & 0xf80001ff; case 2: /* EAPSR */ return xpsr_read(env) & 0xff00fc00; case 3: /* xPSR */ return xpsr_read(env) & 0xff00fdff; case 5: /* IPSR */ return xpsr_read(env) & 0x000001ff; case 6: /* EPSR */ return xpsr_read(env) & 0x0700fc00; case 7: /* IEPSR */ return xpsr_read(env) & 0x0700edff; case 8: /* MSP */ return env->v7m.current_sp ? env->v7m.other_sp : env->regs[13]; case 9: /* PSP */ return env->v7m.current_sp ? env->regs[13] : env->v7m.other_sp; case 16: /* PRIMASK */ return (env->daif & PSTATE_I) != 0; case 17: /* BASEPRI */ case 18: /* BASEPRI_MAX */ return env->v7m.basepri; case 19: /* FAULTMASK */ return (env->daif & PSTATE_F) != 0; case 20: /* CONTROL */ return env->v7m.control; default: /* ??? For debugging only. */ cpu_abort(CPU(cpu), "Unimplemented system register read (%d)\n", reg); return 0; } }


static inline int RENAME(yuv420_rgb32)(SwsContext *c, uint8_t* src[], int srcStride[], int srcSliceY, int srcSliceH, uint8_t* dst[], int dstStride[]){ int y, h_size; if(c->srcFormat == PIX_FMT_YUV422P){ srcStride[1] *= 2; srcStride[2] *= 2; } h_size= (c->dstW+7)&~7; if(h_size*4 > dstStride[0]) h_size-=8; __asm__ __volatile__ ("pxor %mm4, %mm4;" /* zero mm4 */ ); for (y= 0; y<srcSliceH; y++ ) { uint8_t *_image = dst[0] + (y+srcSliceY)*dstStride[0]; uint8_t *_py = src[0] + y*srcStride[0]; uint8_t *_pu = src[1] + (y>>1)*srcStride[1]; uint8_t *_pv = src[2] + (y>>1)*srcStride[2]; long index= -h_size/2; /* this mmx assembly code deals with SINGLE scan line at a time, it convert 8 pixels in each iteration */ __asm__ __volatile__ ( /* load data for start of next scan line */ "movd (%2, %0), %%mm0;" /* Load 4 Cb 00 00 00 00 u3 u2 u1 u0 */ "movd (%3, %0), %%mm1;" /* Load 4 Cr 00 00 00 00 v3 v2 v1 v0 */ "movq (%5, %0, 2), %%mm6;" /* Load 8 Y Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 */ // ".balign 16 \n\t" "1: \n\t" YUV2RGB /* convert RGB plane to RGB packed format, mm0 -> B, mm1 -> R, mm2 -> G, mm3 -> 0, mm4 -> GB, mm5 -> AR pixel 4-7, mm6 -> GB, mm7 -> AR pixel 0-3 */ "pxor %%mm3, %%mm3;" /* zero mm3 */ "movq %%mm0, %%mm6;" /* B7 B6 B5 B4 B3 B2 B1 B0 */ "movq %%mm1, %%mm7;" /* R7 R6 R5 R4 R3 R2 R1 R0 */ "movq %%mm0, %%mm4;" /* B7 B6 B5 B4 B3 B2 B1 B0 */ "movq %%mm1, %%mm5;" /* R7 R6 R5 R4 R3 R2 R1 R0 */ "punpcklbw %%mm2, %%mm6;" /* G3 B3 G2 B2 G1 B1 G0 B0 */ "punpcklbw %%mm3, %%mm7;" /* 00 R3 00 R2 00 R1 00 R0 */ "punpcklwd %%mm7, %%mm6;" /* 00 R1 B1 G1 00 R0 B0 G0 */ MOVNTQ " %%mm6, (%1);" /* Store ARGB1 ARGB0 */ "movq %%mm0, %%mm6;" /* B7 B6 B5 B4 B3 B2 B1 B0 */ "punpcklbw %%mm2, %%mm6;" /* G3 B3 G2 B2 G1 B1 G0 B0 */ "punpckhwd %%mm7, %%mm6;" /* 00 R3 G3 B3 00 R2 B3 G2 */ MOVNTQ " %%mm6, 8 (%1);" /* Store ARGB3 ARGB2 */ "punpckhbw %%mm2, %%mm4;" /* G7 B7 G6 B6 G5 B5 G4 B4 */ "punpckhbw %%mm3, %%mm5;" /* 00 R7 00 R6 00 R5 00 R4 */ "punpcklwd %%mm5, %%mm4;" /* 00 R5 B5 G5 00 R4 B4 G4 */ MOVNTQ " %%mm4, 16 (%1);" /* Store ARGB5 ARGB4 */ "movq %%mm0, %%mm4;" /* B7 B6 B5 B4 B3 B2 B1 B0 */ "punpckhbw %%mm2, %%mm4;" /* G7 B7 G6 B6 G5 B5 G4 B4 */ "punpckhwd %%mm5, %%mm4;" /* 00 R7 G7 B7 00 R6 B6 G6 */ MOVNTQ " %%mm4, 24 (%1);" /* Store ARGB7 ARGB6 */ "movd 4 (%2, %0), %%mm0;" /* Load 4 Cb 00 00 00 00 u3 u2 u1 u0 */ "movd 4 (%3, %0), %%mm1;" /* Load 4 Cr 00 00 00 00 v3 v2 v1 v0 */ "pxor %%mm4, %%mm4;" /* zero mm4 */ "movq 8 (%5, %0, 2), %%mm6;" /* Load 8 Y Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 */ "add $32, %1 \n\t" "add $4, %0 \n\t" " js 1b \n\t" : "+r" (index), "+r" (_image) : "r" (_pu - index), "r" (_pv - index), "r"(&c->redDither), "r" (_py - 2*index) ); } __asm__ __volatile__ (EMMS); return srcSliceH; }


static void qmp_tmp105_set_temperature(const char *id, int value) { QDict *response; response = qmp("{ 'execute': 'qom-set', 'arguments': { 'path': '%s', " "'property': 'temperature', 'value': %d } }", id, value); g_assert(qdict_haskey(response, "return")); QDECREF(response); }


void AUD_del_capture (CaptureVoiceOut *cap, void *cb_opaque) { struct capture_callback *cb; for (cb = cap->cb_head.lh_first; cb; cb = cb->entries.le_next) { if (cb->opaque == cb_opaque) { cb->ops.destroy (cb_opaque); QLIST_REMOVE (cb, entries); g_free (cb); if (!cap->cb_head.lh_first) { SWVoiceOut *sw = cap->hw.sw_head.lh_first, *sw1; while (sw) { SWVoiceCap *sc = (SWVoiceCap *) sw; #ifdef DEBUG_CAPTURE dolog ("freeing %s\n", sw->name); #endif sw1 = sw->entries.le_next; if (sw->rate) { st_rate_stop (sw->rate); sw->rate = NULL; } QLIST_REMOVE (sw, entries); QLIST_REMOVE (sc, entries); g_free (sc); sw = sw1; } QLIST_REMOVE (cap, entries); g_free (cap); } return; } } }


struct omap_sdrc_s *omap_sdrc_init(MemoryRegion *sysmem, hwaddr base) { struct omap_sdrc_s *s = (struct omap_sdrc_s *) g_malloc0(sizeof(struct omap_sdrc_s)); omap_sdrc_reset(s); memory_region_init_io(&s->iomem, NULL, &omap_sdrc_ops, s, "omap.sdrc", 0x1000); memory_region_add_subregion(sysmem, base, &s->iomem); return s; }


static int oggvorbis_decode_init(AVCodecContext *avccontext) { OggVorbisDecContext *context = avccontext->priv_data ; uint8_t *p= avccontext->extradata; int i, hsizes[3]; unsigned char *headers[3], *extradata = avccontext->extradata; vorbis_info_init(&context->vi) ; vorbis_comment_init(&context->vc) ; if(! avccontext->extradata_size || ! p) { av_log(avccontext, AV_LOG_ERROR, "vorbis extradata absent\n"); return -1; } if(p[0] == 0 && p[1] == 30) { for(i = 0; i < 3; i++){ hsizes[i] = bytestream_get_be16((const uint8_t **)&p); headers[i] = p; p += hsizes[i]; } } else if(*p == 2) { unsigned int offset = 1; p++; for(i=0; i<2; i++) { hsizes[i] = 0; while((*p == 0xFF) && (offset < avccontext->extradata_size)) { hsizes[i] += 0xFF; offset++; p++; } if(offset >= avccontext->extradata_size - 1) { av_log(avccontext, AV_LOG_ERROR, "vorbis header sizes damaged\n"); return -1; } hsizes[i] += *p; offset++; p++; } hsizes[2] = avccontext->extradata_size - hsizes[0]-hsizes[1]-offset; #if 0 av_log(avccontext, AV_LOG_DEBUG, "vorbis header sizes: %d, %d, %d, / extradata_len is %d \n", hsizes[0], hsizes[1], hsizes[2], avccontext->extradata_size); #endif headers[0] = extradata + offset; headers[1] = extradata + offset + hsizes[0]; headers[2] = extradata + offset + hsizes[0] + hsizes[1]; } else { av_log(avccontext, AV_LOG_ERROR, "vorbis initial header len is wrong: %d\n", *p); return -1; } for(i=0; i<3; i++){ context->op.b_o_s= i==0; context->op.bytes = hsizes[i]; context->op.packet = headers[i]; if(vorbis_synthesis_headerin(&context->vi, &context->vc, &context->op)<0){ av_log(avccontext, AV_LOG_ERROR, "%d. vorbis header damaged\n", i+1); return -1; } } avccontext->channels = context->vi.channels; avccontext->sample_rate = context->vi.rate; avccontext->sample_fmt = AV_SAMPLE_FMT_S16; avccontext->time_base= (AVRational){1, avccontext->sample_rate}; vorbis_synthesis_init(&context->vd, &context->vi); vorbis_block_init(&context->vd, &context->vb); return 0 ; }


static CharDriverState *qemu_chr_open_pipe(QemuOpts *opts) { int fd_in, fd_out; char filename_in[256], filename_out[256]; const char *filename = qemu_opt_get(opts, "path"); if (filename == NULL) { fprintf(stderr, "chardev: pipe: no filename given\n"); return NULL; } snprintf(filename_in, 256, "%s.in", filename); snprintf(filename_out, 256, "%s.out", filename); TFR(fd_in = open(filename_in, O_RDWR | O_BINARY)); TFR(fd_out = open(filename_out, O_RDWR | O_BINARY)); if (fd_in < 0 || fd_out < 0) { if (fd_in >= 0) close(fd_in); if (fd_out >= 0) close(fd_out); TFR(fd_in = fd_out = open(filename, O_RDWR | O_BINARY)); if (fd_in < 0) return NULL; } return qemu_chr_open_fd(fd_in, fd_out); }


yuv2rgb48_2_c_template(SwsContext *c, const int32_t *buf[2], const int32_t *ubuf[2], const int32_t *vbuf[2], const int32_t *abuf[2], uint16_t *dest, int dstW, int yalpha, int uvalpha, int y, enum AVPixelFormat target) { const int32_t *buf0 = buf[0], *buf1 = buf[1], *ubuf0 = ubuf[0], *ubuf1 = ubuf[1], *vbuf0 = vbuf[0], *vbuf1 = vbuf[1]; int yalpha1 = 4096 - yalpha; int uvalpha1 = 4096 - uvalpha; int i; for (i = 0; i < ((dstW + 1) >> 1); i++) { int Y1 = (buf0[i * 2] * yalpha1 + buf1[i * 2] * yalpha) >> 14; int Y2 = (buf0[i * 2 + 1] * yalpha1 + buf1[i * 2 + 1] * yalpha) >> 14; int U = (ubuf0[i] * uvalpha1 + ubuf1[i] * uvalpha + (-128 << 23)) >> 14; int V = (vbuf0[i] * uvalpha1 + vbuf1[i] * uvalpha + (-128 << 23)) >> 14; int R, G, B; Y1 -= c->yuv2rgb_y_offset; Y2 -= c->yuv2rgb_y_offset; Y1 *= c->yuv2rgb_y_coeff; Y2 *= c->yuv2rgb_y_coeff; Y1 += 1 << 13; Y2 += 1 << 13; R = V * c->yuv2rgb_v2r_coeff; G = V * c->yuv2rgb_v2g_coeff + U * c->yuv2rgb_u2g_coeff; B = U * c->yuv2rgb_u2b_coeff; output_pixel(&dest[0], av_clip_uintp2(R_B + Y1, 30) >> 14); output_pixel(&dest[1], av_clip_uintp2( G + Y1, 30) >> 14); output_pixel(&dest[2], av_clip_uintp2(B_R + Y1, 30) >> 14); output_pixel(&dest[3], av_clip_uintp2(R_B + Y2, 30) >> 14); output_pixel(&dest[4], av_clip_uintp2( G + Y2, 30) >> 14); output_pixel(&dest[5], av_clip_uintp2(B_R + Y2, 30) >> 14); dest += 6; } }


static void filter_mb( H264Context *h, int mb_x, int mb_y, uint8_t *img_y, uint8_t *img_cb, uint8_t *img_cr, unsigned int linesize, unsigned int uvlinesize) { MpegEncContext * const s = &h->s; const int mb_xy= mb_x + mb_y*s->mb_stride; const int mb_type = s->current_picture.mb_type[mb_xy]; const int mvy_limit = IS_INTERLACED(mb_type) ? 2 : 4; int first_vertical_edge_done = 0; int dir; //for sufficiently low qp, filtering wouldn't do anything //this is a conservative estimate: could also check beta_offset and more accurate chroma_qp if(!FRAME_MBAFF){ int qp_thresh = 15 - h->slice_alpha_c0_offset - FFMAX3(0, h->pps.chroma_qp_index_offset[0], h->pps.chroma_qp_index_offset[1]); int qp = s->current_picture.qscale_table[mb_xy]; if(qp <= qp_thresh && (mb_x == 0 || ((qp + s->current_picture.qscale_table[mb_xy-1] + 1)>>1) <= qp_thresh) && (mb_y == 0 || ((qp + s->current_picture.qscale_table[h->top_mb_xy] + 1)>>1) <= qp_thresh)){ return; } } if (FRAME_MBAFF // left mb is in picture && h->slice_table[mb_xy-1] != 255 // and current and left pair do not have the same interlaced type && (IS_INTERLACED(mb_type) != IS_INTERLACED(s->current_picture.mb_type[mb_xy-1])) // and left mb is in the same slice if deblocking_filter == 2 && (h->deblocking_filter!=2 || h->slice_table[mb_xy-1] == h->slice_table[mb_xy])) { /* First vertical edge is different in MBAFF frames * There are 8 different bS to compute and 2 different Qp */ const int pair_xy = mb_x + (mb_y&~1)*s->mb_stride; const int left_mb_xy[2] = { pair_xy-1, pair_xy-1+s->mb_stride }; int16_t bS[8]; int qp[2]; int bqp[2]; int rqp[2]; int mb_qp, mbn0_qp, mbn1_qp; int i; first_vertical_edge_done = 1; if( IS_INTRA(mb_type) ) bS[0] = bS[1] = bS[2] = bS[3] = bS[4] = bS[5] = bS[6] = bS[7] = 4; else { for( i = 0; i < 8; i++ ) { int mbn_xy = MB_FIELD ? left_mb_xy[i>>2] : left_mb_xy[i&1]; if( IS_INTRA( s->current_picture.mb_type[mbn_xy] ) ) bS[i] = 4; else if( h->non_zero_count_cache[12+8*(i>>1)] != 0 || /* FIXME: with 8x8dct + cavlc, should check cbp instead of nnz */ h->non_zero_count[mbn_xy][MB_FIELD ? i&3 : (i>>2)+(mb_y&1)*2] ) bS[i] = 2; else bS[i] = 1; } } mb_qp = s->current_picture.qscale_table[mb_xy]; mbn0_qp = s->current_picture.qscale_table[left_mb_xy[0]]; mbn1_qp = s->current_picture.qscale_table[left_mb_xy[1]]; qp[0] = ( mb_qp + mbn0_qp + 1 ) >> 1; bqp[0] = ( get_chroma_qp( h, 0, mb_qp ) + get_chroma_qp( h, 0, mbn0_qp ) + 1 ) >> 1; rqp[0] = ( get_chroma_qp( h, 1, mb_qp ) + get_chroma_qp( h, 1, mbn0_qp ) + 1 ) >> 1; qp[1] = ( mb_qp + mbn1_qp + 1 ) >> 1; bqp[1] = ( get_chroma_qp( h, 0, mb_qp ) + get_chroma_qp( h, 0, mbn1_qp ) + 1 ) >> 1; rqp[1] = ( get_chroma_qp( h, 1, mb_qp ) + get_chroma_qp( h, 1, mbn1_qp ) + 1 ) >> 1; /* Filter edge */ tprintf(s->avctx, "filter mb:%d/%d MBAFF, QPy:%d/%d, QPb:%d/%d QPr:%d/%d ls:%d uvls:%d", mb_x, mb_y, qp[0], qp[1], bqp[0], bqp[1], rqp[0], rqp[1], linesize, uvlinesize); { int i; for (i = 0; i < 8; i++) tprintf(s->avctx, " bS[%d]:%d", i, bS[i]); tprintf(s->avctx, "\n"); } filter_mb_mbaff_edgev ( h, &img_y [0], linesize, bS, qp ); filter_mb_mbaff_edgecv( h, &img_cb[0], uvlinesize, bS, bqp ); filter_mb_mbaff_edgecv( h, &img_cr[0], uvlinesize, bS, rqp ); } /* dir : 0 -> vertical edge, 1 -> horizontal edge */ for( dir = 0; dir < 2; dir++ ) { int edge; const int mbm_xy = dir == 0 ? mb_xy -1 : h->top_mb_xy; const int mbm_type = s->current_picture.mb_type[mbm_xy]; int start = h->slice_table[mbm_xy] == 255 ? 1 : 0; const int edges = (mb_type & (MB_TYPE_16x16|MB_TYPE_SKIP)) == (MB_TYPE_16x16|MB_TYPE_SKIP) ? 1 : 4; // how often to recheck mv-based bS when iterating between edges const int mask_edge = (mb_type & (MB_TYPE_16x16 | (MB_TYPE_16x8 << dir))) ? 3 : (mb_type & (MB_TYPE_8x16 >> dir)) ? 1 : 0; // how often to recheck mv-based bS when iterating along each edge const int mask_par0 = mb_type & (MB_TYPE_16x16 | (MB_TYPE_8x16 >> dir)); if (first_vertical_edge_done) { start = 1; first_vertical_edge_done = 0; } if (h->deblocking_filter==2 && h->slice_table[mbm_xy] != h->slice_table[mb_xy]) start = 1; if (FRAME_MBAFF && (dir == 1) && ((mb_y&1) == 0) && start == 0 && !IS_INTERLACED(mb_type) && IS_INTERLACED(mbm_type) ) { // This is a special case in the norm where the filtering must // be done twice (one each of the field) even if we are in a // frame macroblock. // static const int nnz_idx[4] = {4,5,6,3}; unsigned int tmp_linesize = 2 * linesize; unsigned int tmp_uvlinesize = 2 * uvlinesize; int mbn_xy = mb_xy - 2 * s->mb_stride; int qp; int i, j; int16_t bS[4]; for(j=0; j<2; j++, mbn_xy += s->mb_stride){ if( IS_INTRA(mb_type) || IS_INTRA(s->current_picture.mb_type[mbn_xy]) ) { bS[0] = bS[1] = bS[2] = bS[3] = 3; } else { const uint8_t *mbn_nnz = h->non_zero_count[mbn_xy]; for( i = 0; i < 4; i++ ) { if( h->non_zero_count_cache[scan8[0]+i] != 0 || mbn_nnz[nnz_idx[i]] != 0 ) bS[i] = 2; else bS[i] = 1; } } // Do not use s->qscale as luma quantizer because it has not the same // value in IPCM macroblocks. qp = ( s->current_picture.qscale_table[mb_xy] + s->current_picture.qscale_table[mbn_xy] + 1 ) >> 1; tprintf(s->avctx, "filter mb:%d/%d dir:%d edge:%d, QPy:%d ls:%d uvls:%d", mb_x, mb_y, dir, edge, qp, tmp_linesize, tmp_uvlinesize); { int i; for (i = 0; i < 4; i++) tprintf(s->avctx, " bS[%d]:%d", i, bS[i]); tprintf(s->avctx, "\n"); } filter_mb_edgeh( h, &img_y[j*linesize], tmp_linesize, bS, qp ); filter_mb_edgech( h, &img_cb[j*uvlinesize], tmp_uvlinesize, bS, ( h->chroma_qp[0] + get_chroma_qp( h, 0, s->current_picture.qscale_table[mbn_xy] ) + 1 ) >> 1); filter_mb_edgech( h, &img_cr[j*uvlinesize], tmp_uvlinesize, bS, ( h->chroma_qp[1] + get_chroma_qp( h, 1, s->current_picture.qscale_table[mbn_xy] ) + 1 ) >> 1); } start = 1; } /* Calculate bS */ for( edge = start; edge < edges; edge++ ) { /* mbn_xy: neighbor macroblock */ const int mbn_xy = edge > 0 ? mb_xy : mbm_xy; const int mbn_type = s->current_picture.mb_type[mbn_xy]; int16_t bS[4]; int qp; if( (edge&1) && IS_8x8DCT(mb_type) ) continue; if( IS_INTRA(mb_type) || IS_INTRA(mbn_type) ) { int value; if (edge == 0) { if ( (!IS_INTERLACED(mb_type) && !IS_INTERLACED(mbm_type)) || ((FRAME_MBAFF || (s->picture_structure != PICT_FRAME)) && (dir == 0)) ) { value = 4; } else { value = 3; } } else { value = 3; } bS[0] = bS[1] = bS[2] = bS[3] = value; } else { int i, l; int mv_done; if( edge & mask_edge ) { bS[0] = bS[1] = bS[2] = bS[3] = 0; mv_done = 1; } else if( FRAME_MBAFF && IS_INTERLACED(mb_type ^ mbn_type)) { bS[0] = bS[1] = bS[2] = bS[3] = 1; mv_done = 1; } else if( mask_par0 && (edge || (mbn_type & (MB_TYPE_16x16 | (MB_TYPE_8x16 >> dir)))) ) { int b_idx= 8 + 4 + edge * (dir ? 8:1); int bn_idx= b_idx - (dir ? 8:1); int v = 0; int xn= h->slice_type_nos == FF_B_TYPE && h->ref2frm[0][h->ref_cache[0][b_idx]+2] != h->ref2frm[0][h->ref_cache[0][bn_idx]+2]; for( l = 0; !v && l < 1 + (h->slice_type_nos == FF_B_TYPE); l++ ) { int ln= l^xn; v |= h->ref2frm[l][h->ref_cache[l][b_idx]+2] != h->ref2frm[ln][h->ref_cache[ln][bn_idx]+2] || FFABS( h->mv_cache[l][b_idx][0] - h->mv_cache[ln][bn_idx][0] ) >= 4 || FFABS( h->mv_cache[l][b_idx][1] - h->mv_cache[ln][bn_idx][1] ) >= mvy_limit; } bS[0] = bS[1] = bS[2] = bS[3] = v; mv_done = 1; } else mv_done = 0; for( i = 0; i < 4; i++ ) { int x = dir == 0 ? edge : i; int y = dir == 0 ? i : edge; int b_idx= 8 + 4 + x + 8*y; int bn_idx= b_idx - (dir ? 8:1); if( h->non_zero_count_cache[b_idx] != 0 || h->non_zero_count_cache[bn_idx] != 0 ) { bS[i] = 2; } else if(!mv_done) { int xn= h->slice_type_nos == FF_B_TYPE && h->ref2frm[0][h->ref_cache[0][b_idx]+2] != h->ref2frm[0][h->ref_cache[0][bn_idx]+2]; bS[i] = 0; for( l = 0; l < 1 + (h->slice_type_nos == FF_B_TYPE); l++ ) { int ln= l^xn; if( h->ref2frm[l][h->ref_cache[l][b_idx]+2] != h->ref2frm[ln][h->ref_cache[ln][bn_idx]+2] || FFABS( h->mv_cache[l][b_idx][0] - h->mv_cache[ln][bn_idx][0] ) >= 4 || FFABS( h->mv_cache[l][b_idx][1] - h->mv_cache[ln][bn_idx][1] ) >= mvy_limit ) { bS[i] = 1; break; } } } } if(bS[0]+bS[1]+bS[2]+bS[3] == 0) continue; } /* Filter edge */ // Do not use s->qscale as luma quantizer because it has not the same // value in IPCM macroblocks. qp = ( s->current_picture.qscale_table[mb_xy] + s->current_picture.qscale_table[mbn_xy] + 1 ) >> 1; //tprintf(s->avctx, "filter mb:%d/%d dir:%d edge:%d, QPy:%d, QPc:%d, QPcn:%d\n", mb_x, mb_y, dir, edge, qp, h->chroma_qp, s->current_picture.qscale_table[mbn_xy]); tprintf(s->avctx, "filter mb:%d/%d dir:%d edge:%d, QPy:%d ls:%d uvls:%d", mb_x, mb_y, dir, edge, qp, linesize, uvlinesize); { int i; for (i = 0; i < 4; i++) tprintf(s->avctx, " bS[%d]:%d", i, bS[i]); tprintf(s->avctx, "\n"); } if( dir == 0 ) { filter_mb_edgev( h, &img_y[4*edge], linesize, bS, qp ); if( (edge&1) == 0 ) { filter_mb_edgecv( h, &img_cb[2*edge], uvlinesize, bS, ( h->chroma_qp[0] + get_chroma_qp( h, 0, s->current_picture.qscale_table[mbn_xy] ) + 1 ) >> 1); filter_mb_edgecv( h, &img_cr[2*edge], uvlinesize, bS, ( h->chroma_qp[1] + get_chroma_qp( h, 1, s->current_picture.qscale_table[mbn_xy] ) + 1 ) >> 1); } } else { filter_mb_edgeh( h, &img_y[4*edge*linesize], linesize, bS, qp ); if( (edge&1) == 0 ) { filter_mb_edgech( h, &img_cb[2*edge*uvlinesize], uvlinesize, bS, ( h->chroma_qp[0] + get_chroma_qp( h, 0, s->current_picture.qscale_table[mbn_xy] ) + 1 ) >> 1); filter_mb_edgech( h, &img_cr[2*edge*uvlinesize], uvlinesize, bS, ( h->chroma_qp[1] + get_chroma_qp( h, 1, s->current_picture.qscale_table[mbn_xy] ) + 1 ) >> 1); } } } } }


static int twolame_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, const AVFrame *frame, int *got_packet_ptr) { TWOLAMEContext *s = avctx->priv_data; int ret; if ((ret = ff_alloc_packet(avpkt, MPA_MAX_CODED_FRAME_SIZE)) < 0) return ret; if (frame) { switch (avctx->sample_fmt) { case AV_SAMPLE_FMT_FLT: ret = twolame_encode_buffer_float32_interleaved(s->glopts, (const float *)frame->data[0], frame->nb_samples, avpkt->data, avpkt->size); break; case AV_SAMPLE_FMT_FLTP: ret = twolame_encode_buffer_float32(s->glopts, (const float *)frame->data[0], (const float *)frame->data[1], frame->nb_samples, avpkt->data, avpkt->size); break; case AV_SAMPLE_FMT_S16: ret = twolame_encode_buffer_interleaved(s->glopts, (const short int *)frame->data[0], frame->nb_samples, avpkt->data, avpkt->size); break; case AV_SAMPLE_FMT_S16P: ret = twolame_encode_buffer(s->glopts, (const short int *)frame->data[0], (const short int *)frame->data[1], frame->nb_samples, avpkt->data, avpkt->size); break; default: av_log(avctx, AV_LOG_ERROR, "Unsupported sample format %d.\n", avctx->sample_fmt); return AVERROR_BUG; } } else { ret = twolame_encode_flush(s->glopts, avpkt->data, avpkt->size); } if (!ret) // no bytes written return 0; if (ret < 0) // twolame error return AVERROR_UNKNOWN; avpkt->duration = ff_samples_to_time_base(avctx, frame->nb_samples); if (frame) { if (frame->pts != AV_NOPTS_VALUE) avpkt->pts = frame->pts - ff_samples_to_time_base(avctx, avctx->delay); } else { avpkt->pts = s->next_pts; } // this is for setting pts for flushed packet(s). if (avpkt->pts != AV_NOPTS_VALUE) s->next_pts = avpkt->pts + avpkt->duration; av_shrink_packet(avpkt, ret); *got_packet_ptr = 1; return 0; }


av_cold void ff_vc1dsp_init_x86(VC1DSPContext *dsp) { int cpu_flags = av_get_cpu_flags(); if (INLINE_MMX(cpu_flags)) ff_vc1dsp_init_mmx(dsp); if (INLINE_MMXEXT(cpu_flags)) ff_vc1dsp_init_mmxext(dsp); #define ASSIGN_LF(EXT) \ dsp->vc1_v_loop_filter4 = ff_vc1_v_loop_filter4_ ## EXT; \ dsp->vc1_h_loop_filter4 = ff_vc1_h_loop_filter4_ ## EXT; \ dsp->vc1_v_loop_filter8 = ff_vc1_v_loop_filter8_ ## EXT; \ dsp->vc1_h_loop_filter8 = ff_vc1_h_loop_filter8_ ## EXT; \ dsp->vc1_v_loop_filter16 = vc1_v_loop_filter16_ ## EXT; \ dsp->vc1_h_loop_filter16 = vc1_h_loop_filter16_ ## EXT #if HAVE_YASM if (cpu_flags & AV_CPU_FLAG_MMX) { dsp->put_no_rnd_vc1_chroma_pixels_tab[0] = ff_put_vc1_chroma_mc8_nornd_mmx; } if (cpu_flags & AV_CPU_FLAG_MMXEXT) { ASSIGN_LF(mmxext); dsp->avg_no_rnd_vc1_chroma_pixels_tab[0] = ff_avg_vc1_chroma_mc8_nornd_mmxext; dsp->avg_vc1_mspel_pixels_tab[0] = avg_vc1_mspel_mc00_mmxext; } else if (cpu_flags & AV_CPU_FLAG_3DNOW) { dsp->avg_no_rnd_vc1_chroma_pixels_tab[0] = ff_avg_vc1_chroma_mc8_nornd_3dnow; } if (cpu_flags & AV_CPU_FLAG_SSE2) { dsp->vc1_v_loop_filter8 = ff_vc1_v_loop_filter8_sse2; dsp->vc1_h_loop_filter8 = ff_vc1_h_loop_filter8_sse2; dsp->vc1_v_loop_filter16 = vc1_v_loop_filter16_sse2; dsp->vc1_h_loop_filter16 = vc1_h_loop_filter16_sse2; } if (cpu_flags & AV_CPU_FLAG_SSSE3) { ASSIGN_LF(ssse3); dsp->put_no_rnd_vc1_chroma_pixels_tab[0] = ff_put_vc1_chroma_mc8_nornd_ssse3; dsp->avg_no_rnd_vc1_chroma_pixels_tab[0] = ff_avg_vc1_chroma_mc8_nornd_ssse3; } if (cpu_flags & AV_CPU_FLAG_SSE4) { dsp->vc1_h_loop_filter8 = ff_vc1_h_loop_filter8_sse4; dsp->vc1_h_loop_filter16 = vc1_h_loop_filter16_sse4; } #endif /* HAVE_YASM */ }


static inline void neon_store_reg64(TCGv var, int reg) { tcg_gen_st_i64(var, cpu_env, vfp_reg_offset(1, reg)); }


static DisplaySurface *qemu_create_message_surface(int w, int h, const char *msg) { DisplaySurface *surface = qemu_create_displaysurface(w, h); pixman_color_t bg = color_table_rgb[0][COLOR_BLACK]; pixman_color_t fg = color_table_rgb[0][COLOR_WHITE]; pixman_image_t *glyph; int len, x, y, i; len = strlen(msg); x = (w / FONT_WIDTH - len) / 2; y = (h / FONT_HEIGHT - 1) / 2; for (i = 0; i < len; i++) { glyph = qemu_pixman_glyph_from_vgafont(FONT_HEIGHT, vgafont16, msg[i]); qemu_pixman_glyph_render(glyph, surface->image, &fg, &bg, x+i, y, FONT_WIDTH, FONT_HEIGHT); qemu_pixman_image_unref(glyph); } return surface; }


static bool vregs_needed(void *opaque) { #ifdef CONFIG_KVM if (kvm_enabled()) { return kvm_check_extension(kvm_state, KVM_CAP_S390_VECTOR_REGISTERS); } #endif return 0; }


static unsigned int dec_abs_r(DisasContext *dc) { TCGv t0; DIS(fprintf (logfile, "abs $r%u, $r%u\n", dc->op1, dc->op2)); cris_cc_mask(dc, CC_MASK_NZ); t0 = tcg_temp_new(TCG_TYPE_TL); tcg_gen_sari_tl(t0, cpu_R[dc->op1], 31); tcg_gen_xor_tl(cpu_R[dc->op2], cpu_R[dc->op1], t0); tcg_gen_sub_tl(cpu_R[dc->op2], cpu_R[dc->op2], t0); tcg_temp_free(t0); cris_alu(dc, CC_OP_MOVE, cpu_R[dc->op2], cpu_R[dc->op2], cpu_R[dc->op2], 4); return 2; }


static int calculate_new_instance_id(const char *idstr) { SaveStateEntry *se; int instance_id = 0; TAILQ_FOREACH(se, &savevm_handlers, entry) { if (strcmp(idstr, se->idstr) == 0 && instance_id <= se->instance_id) { instance_id = se->instance_id + 1; } } return instance_id; }


static int resample(ResampleContext *c, void *dst, const void *src, int *consumed, int src_size, int dst_size, int update_ctx, int nearest_neighbour) { int dst_index; int index = c->index; int frac = c->frac; int dst_incr_frac = c->dst_incr % c->src_incr; int dst_incr = c->dst_incr / c->src_incr; int compensation_distance = c->compensation_distance; if (!dst != !src) return AVERROR(EINVAL); if (nearest_neighbour) { int64_t index2 = ((int64_t)index) << 32; int64_t incr = (1LL << 32) * c->dst_incr / c->src_incr; dst_size = FFMIN(dst_size, (src_size-1-index) * (int64_t)c->src_incr / c->dst_incr); if (dst) { for(dst_index = 0; dst_index < dst_size; dst_index++) { c->resample_nearest(dst, dst_index, src, index2 >> 32); index2 += incr; } } else { dst_index = dst_size; } index += dst_index * dst_incr; index += (frac + dst_index * (int64_t)dst_incr_frac) / c->src_incr; frac = (frac + dst_index * (int64_t)dst_incr_frac) % c->src_incr; } else { for (dst_index = 0; dst_index < dst_size; dst_index++) { int sample_index = index >> c->phase_shift; if (sample_index + c->filter_length > src_size || -sample_index >= src_size) break; if (dst) c->resample_one(c, dst, dst_index, src, src_size, index, frac); frac += dst_incr_frac; index += dst_incr; if (frac >= c->src_incr) { frac -= c->src_incr; index++; } if (dst_index + 1 == compensation_distance) { compensation_distance = 0; dst_incr_frac = c->ideal_dst_incr % c->src_incr; dst_incr = c->ideal_dst_incr / c->src_incr; } } } if (consumed) *consumed = FFMAX(index, 0) >> c->phase_shift; if (update_ctx) { if (index >= 0) index &= c->phase_mask; if (compensation_distance) { compensation_distance -= dst_index; if (compensation_distance <= 0) return AVERROR_BUG; } c->frac = frac; c->index = index; c->dst_incr = dst_incr_frac + c->src_incr*dst_incr; c->compensation_distance = compensation_distance; } return dst_index; }


static void l2cap_frame_in(struct l2cap_instance_s *l2cap, const l2cap_hdr *frame) { uint16_t cid = le16_to_cpu(frame->cid); uint16_t len = le16_to_cpu(frame->len); if (unlikely(cid >= L2CAP_CID_MAX || !l2cap->cid[cid])) { fprintf(stderr, "%s: frame addressed to a non-existent L2CAP " "channel %04x received.\n", __FUNCTION__, cid); return; } l2cap->cid[cid]->frame_in(l2cap->cid[cid], cid, frame, len); }


static uint32_t superio_ioport_readb(void *opaque, uint32_t addr) { SuperIOConfig *superio_conf = opaque; DPRINTF("superio_ioport_readb address 0x%x \n", addr); return (superio_conf->config[superio_conf->index]); }


void aio_notify_accept(AioContext *ctx) { if (atomic_xchg(&ctx->notified, false)) { event_notifier_test_and_clear(&ctx->notifier); } }


static inline void code_gen_alloc(size_t tb_size) { code_gen_buffer_size = size_code_gen_buffer(tb_size); code_gen_buffer = alloc_code_gen_buffer(); if (code_gen_buffer == NULL) { fprintf(stderr, "Could not allocate dynamic translator buffer\n"); exit(1); } map_exec(code_gen_prologue, sizeof(code_gen_prologue)); code_gen_buffer_max_size = code_gen_buffer_size - (TCG_MAX_OP_SIZE * OPC_BUF_SIZE); code_gen_max_blocks = code_gen_buffer_size / CODE_GEN_AVG_BLOCK_SIZE; tbs = g_malloc(code_gen_max_blocks * sizeof(TranslationBlock)); }


static void qemu_chr_parse_parallel(QemuOpts *opts, ChardevBackend *backend, Error **errp) { const char *device = qemu_opt_get(opts, "path"); if (device == NULL) { error_setg(errp, "chardev: parallel: no device path given"); return; } backend->parallel = g_new0(ChardevHostdev, 1); backend->parallel->device = g_strdup(device); }


static void guess_chs_for_size(BlockDriverState *bs, uint32_t *pcyls, uint32_t *pheads, uint32_t *psecs) { uint64_t nb_sectors; int cylinders; bdrv_get_geometry(bs, &nb_sectors); cylinders = nb_sectors / (16 * 63); if (cylinders > 16383) { cylinders = 16383; } else if (cylinders < 2) { cylinders = 2; } *pcyls = cylinders; *pheads = 16; *psecs = 63; }


static void disas_xtensa_insn(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 = ldub_code(dc->pc); uint8_t b1 = ldub_code(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 = ldub_code(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, 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(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(); 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(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_R[RRR_S], dtlb); break; case 4: /*IITLB*/ /*IDTLB*/ gen_helper_itlb(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_R[RRR_S], dtlb); break; case 6: /*WITLB*/ /*WDTLB*/ gen_helper_wtlb(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_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]) { tcg_gen_mov_i32(cpu_UR[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 << 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*/ HAS_OPTION(XTENSA_OPTION_COPROCESSOR); TBD(); 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); TBD(); break; case 11: /*FP1*/ HAS_OPTION(XTENSA_OPTION_FP_COPROCESSOR); TBD(); 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(); 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); 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(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*/ HAS_OPTION(XTENSA_OPTION_COPROCESSOR); TBD(); 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(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_wsr_lend(dc, LEND, 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); { TCGv_i32 bit = tcg_const_i32(1); TCGv_i32 tmp = tcg_temp_new_i32(); tcg_gen_andi_i32(tmp, cpu_R[RRI8_T], 0x1f); tcg_gen_shl_i32(bit, bit, tmp); 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], 1 << (((RRI8_R & 1) << 4) | RRI8_T)); 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, 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; } 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 TCGReg tcg_out_tlb_read(TCGContext *s, TCGMemOp opc, TCGReg addrlo, TCGReg addrhi, int mem_index, bool is_read) { int cmp_off = (is_read ? offsetof(CPUArchState, tlb_table[mem_index][0].addr_read) : offsetof(CPUArchState, tlb_table[mem_index][0].addr_write)); int add_off = offsetof(CPUArchState, tlb_table[mem_index][0].addend); TCGReg base = TCG_AREG0; TCGMemOp s_bits = opc & MO_SIZE; /* Extract the page index, shifted into place for tlb index. */ if (TCG_TARGET_REG_BITS == 64) { if (TARGET_LONG_BITS == 32) { /* Zero-extend the address into a place helpful for further use. */ tcg_out_ext32u(s, TCG_REG_R4, addrlo); addrlo = TCG_REG_R4; } else { tcg_out_rld(s, RLDICL, TCG_REG_R3, addrlo, 64 - TARGET_PAGE_BITS, 64 - CPU_TLB_BITS); } } /* Compensate for very large offsets. */ if (add_off >= 0x8000) { /* Most target env are smaller than 32k; none are larger than 64k. Simplify the logic here merely to offset by 0x7ff0, giving us a range just shy of 64k. Check this assumption. */ QEMU_BUILD_BUG_ON(offsetof(CPUArchState, tlb_table[NB_MMU_MODES - 1][1]) > 0x7ff0 + 0x7fff); tcg_out32(s, ADDI | TAI(TCG_REG_TMP1, base, 0x7ff0)); base = TCG_REG_TMP1; cmp_off -= 0x7ff0; add_off -= 0x7ff0; } /* Extraction and shifting, part 2. */ if (TCG_TARGET_REG_BITS == 32 || TARGET_LONG_BITS == 32) { tcg_out_rlw(s, RLWINM, TCG_REG_R3, addrlo, 32 - (TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS), 32 - (CPU_TLB_BITS + CPU_TLB_ENTRY_BITS), 31 - CPU_TLB_ENTRY_BITS); } else { tcg_out_shli64(s, TCG_REG_R3, TCG_REG_R3, CPU_TLB_ENTRY_BITS); } tcg_out32(s, ADD | TAB(TCG_REG_R3, TCG_REG_R3, base)); /* Load the tlb comparator. */ if (TCG_TARGET_REG_BITS < TARGET_LONG_BITS) { tcg_out_ld(s, TCG_TYPE_I32, TCG_REG_R4, TCG_REG_R3, cmp_off); tcg_out_ld(s, TCG_TYPE_I32, TCG_REG_TMP1, TCG_REG_R3, cmp_off + 4); } else { tcg_out_ld(s, TCG_TYPE_TL, TCG_REG_TMP1, TCG_REG_R3, cmp_off); } /* Load the TLB addend for use on the fast path. Do this asap to minimize any load use delay. */ tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_R3, TCG_REG_R3, add_off); /* Clear the non-page, non-alignment bits from the address */ if (TCG_TARGET_REG_BITS == 32 || TARGET_LONG_BITS == 32) { /* We don't support unaligned accesses on 32-bits, preserve * the bottom bits and thus trigger a comparison failure on * unaligned accesses */ tcg_out_rlw(s, RLWINM, TCG_REG_R0, addrlo, 0, (32 - s_bits) & 31, 31 - TARGET_PAGE_BITS); } else if (s_bits) { /* > byte access, we need to handle alignment */ if ((opc & MO_AMASK) == MO_ALIGN) { /* Alignment required by the front-end, same as 32-bits */ tcg_out_rld(s, RLDICL, TCG_REG_R0, addrlo, 64 - TARGET_PAGE_BITS, TARGET_PAGE_BITS - s_bits); tcg_out_rld(s, RLDICL, TCG_REG_R0, TCG_REG_R0, TARGET_PAGE_BITS, 0); } else { /* We support unaligned accesses, we need to make sure we fail * if we cross a page boundary. The trick is to add the * access_size-1 to the address before masking the low bits. * That will make the address overflow to the next page if we * cross a page boundary which will then force a mismatch of * the TLB compare since the next page cannot possibly be in * the same TLB index. */ tcg_out32(s, ADDI | TAI(TCG_REG_R0, addrlo, (1 << s_bits) - 1)); tcg_out_rld(s, RLDICR, TCG_REG_R0, TCG_REG_R0, 0, 63 - TARGET_PAGE_BITS); } } else { /* Byte access, just chop off the bits below the page index */ tcg_out_rld(s, RLDICR, TCG_REG_R0, addrlo, 0, 63 - TARGET_PAGE_BITS); } if (TCG_TARGET_REG_BITS < TARGET_LONG_BITS) { tcg_out_cmp(s, TCG_COND_EQ, TCG_REG_R0, TCG_REG_TMP1, 0, 7, TCG_TYPE_I32); tcg_out_cmp(s, TCG_COND_EQ, addrhi, TCG_REG_R4, 0, 6, TCG_TYPE_I32); tcg_out32(s, CRAND | BT(7, CR_EQ) | BA(6, CR_EQ) | BB(7, CR_EQ)); } else { tcg_out_cmp(s, TCG_COND_EQ, TCG_REG_R0, TCG_REG_TMP1, 0, 7, TCG_TYPE_TL); } return addrlo; }


static av_always_inline int dnxhd_decode_dct_block(const DNXHDContext *ctx, RowContext *row, int n, int index_bits, int level_bias, int level_shift, int dc_shift) { int i, j, index1, index2, len, flags; int level, component, sign; const int *scale; const uint8_t *weight_matrix; const uint8_t *ac_info = ctx->cid_table->ac_info; int16_t *block = row->blocks[n]; const int eob_index = ctx->cid_table->eob_index; int ret = 0; OPEN_READER(bs, &row->gb); ctx->bdsp.clear_block(block); if (!ctx->is_444) { if (n & 2) { component = 1 + (n & 1); scale = row->chroma_scale; weight_matrix = ctx->cid_table->chroma_weight; } else { component = 0; scale = row->luma_scale; weight_matrix = ctx->cid_table->luma_weight; } } else { component = (n >> 1) % 3; if (component) { scale = row->chroma_scale; weight_matrix = ctx->cid_table->chroma_weight; } else { scale = row->luma_scale; weight_matrix = ctx->cid_table->luma_weight; } } UPDATE_CACHE(bs, &row->gb); GET_VLC(len, bs, &row->gb, ctx->dc_vlc.table, DNXHD_DC_VLC_BITS, 1); if (len) { level = GET_CACHE(bs, &row->gb); LAST_SKIP_BITS(bs, &row->gb, len); sign = ~level >> 31; level = (NEG_USR32(sign ^ level, len) ^ sign) - sign; row->last_dc[component] += level << dc_shift; } block[0] = row->last_dc[component]; i = 0; UPDATE_CACHE(bs, &row->gb); GET_VLC(index1, bs, &row->gb, ctx->ac_vlc.table, DNXHD_VLC_BITS, 2); while (index1 != eob_index) { level = ac_info[2*index1+0]; flags = ac_info[2*index1+1]; sign = SHOW_SBITS(bs, &row->gb, 1); SKIP_BITS(bs, &row->gb, 1); if (flags & 1) { level += SHOW_UBITS(bs, &row->gb, index_bits) << 7; SKIP_BITS(bs, &row->gb, index_bits); } if (flags & 2) { UPDATE_CACHE(bs, &row->gb); GET_VLC(index2, bs, &row->gb, ctx->run_vlc.table, DNXHD_VLC_BITS, 2); i += ctx->cid_table->run[index2]; } if (++i > 63) { av_log(ctx->avctx, AV_LOG_ERROR, "ac tex damaged %d, %d\n", n, i); ret = -1; break; } j = ctx->scantable.permutated[i]; level *= scale[i]; level += scale[i] >> 1; if (level_bias < 32 || weight_matrix[i] != level_bias) level += level_bias; // 1<<(level_shift-1) level >>= level_shift; block[j] = (level ^ sign) - sign; UPDATE_CACHE(bs, &row->gb); GET_VLC(index1, bs, &row->gb, ctx->ac_vlc.table, DNXHD_VLC_BITS, 2); } CLOSE_READER(bs, &row->gb); return ret; }


static uint64_t build_channel_report_mcic(void) { uint64_t mcic; /* subclass: indicate channel report pending */ mcic = MCIC_SC_CP | /* subclass modifiers: none */ /* storage errors: none */ /* validity bits: no damage */ MCIC_VB_WP | MCIC_VB_MS | MCIC_VB_PM | MCIC_VB_IA | MCIC_VB_FP | MCIC_VB_GR | MCIC_VB_CR | MCIC_VB_ST | MCIC_VB_AR | MCIC_VB_PR | MCIC_VB_FC | MCIC_VB_CT | MCIC_VB_CC; if (s390_has_feat(S390_FEAT_VECTOR)) { mcic |= MCIC_VB_VR; } if (s390_has_feat(S390_FEAT_GUARDED_STORAGE)) { mcic |= MCIC_VB_GS; } return mcic; }


static int do_virtio_net_can_receive(VirtIONet *n, int bufsize) { if (!virtio_queue_ready(n->rx_vq) || !(n->vdev.status & VIRTIO_CONFIG_S_DRIVER_OK)) return 0; if (virtio_queue_empty(n->rx_vq) || (n->mergeable_rx_bufs && !virtqueue_avail_bytes(n->rx_vq, bufsize, 0))) { virtio_queue_set_notification(n->rx_vq, 1); return 0; } virtio_queue_set_notification(n->rx_vq, 0); return 1; }


static inline void gen_bcond(DisasContext *ctx, int type) { uint32_t bo = BO(ctx->opcode); int l1; TCGv target; ctx->exception = POWERPC_EXCP_BRANCH; if (type == BCOND_LR || type == BCOND_CTR || type == BCOND_TAR) { target = tcg_temp_local_new(); if (type == BCOND_CTR) tcg_gen_mov_tl(target, cpu_ctr); else if (type == BCOND_TAR) gen_load_spr(target, SPR_TAR); else tcg_gen_mov_tl(target, cpu_lr); } else { TCGV_UNUSED(target); } if (LK(ctx->opcode)) gen_setlr(ctx, ctx->nip); l1 = gen_new_label(); if ((bo & 0x4) == 0) { /* Decrement and test CTR */ TCGv temp = tcg_temp_new(); if (unlikely(type == BCOND_CTR)) { gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL); return; } tcg_gen_subi_tl(cpu_ctr, cpu_ctr, 1); if (NARROW_MODE(ctx)) { tcg_gen_ext32u_tl(temp, cpu_ctr); } else { tcg_gen_mov_tl(temp, cpu_ctr); } if (bo & 0x2) { tcg_gen_brcondi_tl(TCG_COND_NE, temp, 0, l1); } else { tcg_gen_brcondi_tl(TCG_COND_EQ, temp, 0, l1); } tcg_temp_free(temp); } if ((bo & 0x10) == 0) { /* Test CR */ uint32_t bi = BI(ctx->opcode); uint32_t mask = 0x08 >> (bi & 0x03); TCGv_i32 temp = tcg_temp_new_i32(); if (bo & 0x8) { tcg_gen_andi_i32(temp, cpu_crf[bi >> 2], mask); tcg_gen_brcondi_i32(TCG_COND_EQ, temp, 0, l1); } else { tcg_gen_andi_i32(temp, cpu_crf[bi >> 2], mask); tcg_gen_brcondi_i32(TCG_COND_NE, temp, 0, l1); } tcg_temp_free_i32(temp); } gen_update_cfar(ctx, ctx->nip); if (type == BCOND_IM) { target_ulong li = (target_long)((int16_t)(BD(ctx->opcode))); if (likely(AA(ctx->opcode) == 0)) { gen_goto_tb(ctx, 0, ctx->nip + li - 4); } else { gen_goto_tb(ctx, 0, li); } gen_set_label(l1); gen_goto_tb(ctx, 1, ctx->nip); } else { if (NARROW_MODE(ctx)) { tcg_gen_andi_tl(cpu_nip, target, (uint32_t)~3); } else { tcg_gen_andi_tl(cpu_nip, target, ~3); } tcg_gen_exit_tb(0); gen_set_label(l1); gen_update_nip(ctx, ctx->nip); tcg_gen_exit_tb(0); } if (type == BCOND_LR || type == BCOND_CTR || type == BCOND_TAR) { tcg_temp_free(target); } }


static void menelaus_pre_save(void *opaque) { MenelausState *s = opaque; /* Should be <= 1000 */ s->rtc_next_vmstate = s->rtc.next - qemu_get_clock(rt_clock); }


static inline uint64_t bdrv_get_align(BlockDriverState *bs) { /* TODO Lift BDRV_SECTOR_SIZE restriction in BlockDriver interface */ return MAX(BDRV_SECTOR_SIZE, bs->request_alignment); }


static int mipsnet_can_receive(void *opaque) { MIPSnetState *s = opaque; if (s->busy) return 0; return !mipsnet_buffer_full(s); }


void hmp_host_net_remove(Monitor *mon, const QDict *qdict) { NetClientState *nc; int vlan_id = qdict_get_int(qdict, "vlan_id"); const char *device = qdict_get_str(qdict, "device"); nc = net_hub_find_client_by_name(vlan_id, device); if (!nc) { error_report("Host network device '%s' on hub '%d' not found", device, vlan_id); return; } if (!net_host_check_device(nc->model)) { error_report("invalid host network device '%s'", device); return; } qemu_del_net_client(nc->peer); qemu_del_net_client(nc); }


static int ssd0303_init(I2CSlave *i2c) { ssd0303_state *s = FROM_I2C_SLAVE(ssd0303_state, i2c); s->con = graphic_console_init(ssd0303_update_display, ssd0303_invalidate_display, NULL, NULL, s); qemu_console_resize(s->con, 96 * MAGNIFY, 16 * MAGNIFY); return 0; }


static enum AVPixelFormat webp_get_format(AVCodecContext *avctx, const enum AVPixelFormat *formats) { WebPContext *s = avctx->priv_data; if (s->has_alpha) return AV_PIX_FMT_YUVA420P; else return AV_PIX_FMT_YUV420P; }


static void coded_frame_add(void *list, struct FrameListData *cx_frame) { struct FrameListData **p = list; while (*p != NULL) p = &(*p)->next; *p = cx_frame; cx_frame->next = NULL; }


void swri_resample_dsp_x86_init(ResampleContext *c) { int av_unused mm_flags = av_get_cpu_flags(); switch(c->format){ case AV_SAMPLE_FMT_S16P: if (ARCH_X86_32 && HAVE_MMXEXT_EXTERNAL && mm_flags & AV_CPU_FLAG_MMX2) { c->dsp.resample = c->linear ? ff_resample_linear_int16_mmxext : ff_resample_common_int16_mmxext; } if (HAVE_SSE2_EXTERNAL && mm_flags & AV_CPU_FLAG_SSE2) { c->dsp.resample = c->linear ? ff_resample_linear_int16_sse2 : ff_resample_common_int16_sse2; } if (HAVE_XOP_EXTERNAL && mm_flags & AV_CPU_FLAG_XOP) { c->dsp.resample = c->linear ? ff_resample_linear_int16_xop : ff_resample_common_int16_xop; } break; case AV_SAMPLE_FMT_FLTP: if (HAVE_SSE_EXTERNAL && mm_flags & AV_CPU_FLAG_SSE) { c->dsp.resample = c->linear ? ff_resample_linear_float_sse : ff_resample_common_float_sse; } if (HAVE_AVX_EXTERNAL && mm_flags & AV_CPU_FLAG_AVX) { c->dsp.resample = c->linear ? ff_resample_linear_float_avx : ff_resample_common_float_avx; } if (HAVE_FMA3_EXTERNAL && mm_flags & AV_CPU_FLAG_FMA3) { c->dsp.resample = c->linear ? ff_resample_linear_float_fma3 : ff_resample_common_float_fma3; } if (HAVE_FMA4_EXTERNAL && mm_flags & AV_CPU_FLAG_FMA4) { c->dsp.resample = c->linear ? ff_resample_linear_float_fma4 : ff_resample_common_float_fma4; } break; case AV_SAMPLE_FMT_DBLP: if (HAVE_SSE2_EXTERNAL && mm_flags & AV_CPU_FLAG_SSE2) { c->dsp.resample = c->linear ? ff_resample_linear_double_sse2 : ff_resample_common_double_sse2; } break; } }


void qemu_spice_display_switch(SimpleSpiceDisplay *ssd, DisplaySurface *surface) { SimpleSpiceUpdate *update; bool need_destroy; if (surface && ssd->surface && surface_width(surface) == pixman_image_get_width(ssd->surface) && surface_height(surface) == pixman_image_get_height(ssd->surface)) { /* no-resize fast path: just swap backing store */ dprint(1, "%s/%d: fast (%dx%d)\n", __func__, ssd->qxl.id, surface_width(surface), surface_height(surface)); qemu_mutex_lock(&ssd->lock); ssd->ds = surface; pixman_image_unref(ssd->surface); ssd->surface = pixman_image_ref(ssd->ds->image); qemu_mutex_unlock(&ssd->lock); qemu_spice_display_update(ssd, 0, 0, surface_width(surface), surface_height(surface)); return; } /* full mode switch */ dprint(1, "%s/%d: full (%dx%d -> %dx%d)\n", __func__, ssd->qxl.id, ssd->surface ? pixman_image_get_width(ssd->surface) : 0, ssd->surface ? pixman_image_get_height(ssd->surface) : 0, surface ? surface_width(surface) : 0, surface ? surface_height(surface) : 0); memset(&ssd->dirty, 0, sizeof(ssd->dirty)); if (ssd->surface) { pixman_image_unref(ssd->surface); ssd->surface = NULL; pixman_image_unref(ssd->mirror); ssd->mirror = NULL; } qemu_mutex_lock(&ssd->lock); need_destroy = (ssd->ds != NULL); ssd->ds = surface; while ((update = QTAILQ_FIRST(&ssd->updates)) != NULL) { QTAILQ_REMOVE(&ssd->updates, update, next); qemu_spice_destroy_update(ssd, update); } qemu_mutex_unlock(&ssd->lock); if (need_destroy) { qemu_spice_destroy_host_primary(ssd); } if (ssd->ds) { ssd->surface = pixman_image_ref(ssd->ds->image); ssd->mirror = qemu_pixman_mirror_create(ssd->ds->format, ssd->ds->image); qemu_spice_create_host_primary(ssd); } memset(&ssd->dirty, 0, sizeof(ssd->dirty)); ssd->notify++; }


GuestNetworkInterfaceList *qmp_guest_network_get_interfaces(Error **errp) { GuestNetworkInterfaceList *head = NULL, *cur_item = NULL; struct ifaddrs *ifap, *ifa; char err_msg[512]; if (getifaddrs(&ifap) < 0) { snprintf(err_msg, sizeof(err_msg), "getifaddrs failed: %s", strerror(errno)); error_set(errp, QERR_QGA_COMMAND_FAILED, err_msg); goto error; } for (ifa = ifap; ifa; ifa = ifa->ifa_next) { GuestNetworkInterfaceList *info; GuestIpAddressList **address_list = NULL, *address_item = NULL; char addr4[INET_ADDRSTRLEN]; char addr6[INET6_ADDRSTRLEN]; int sock; struct ifreq ifr; unsigned char *mac_addr; void *p; g_debug("Processing %s interface", ifa->ifa_name); info = guest_find_interface(head, ifa->ifa_name); if (!info) { info = g_malloc0(sizeof(*info)); info->value = g_malloc0(sizeof(*info->value)); info->value->name = g_strdup(ifa->ifa_name); if (!cur_item) { head = cur_item = info; } else { cur_item->next = info; cur_item = info; } } if (!info->value->has_hardware_address && ifa->ifa_flags & SIOCGIFHWADDR) { /* we haven't obtained HW address yet */ sock = socket(PF_INET, SOCK_STREAM, 0); if (sock == -1) { snprintf(err_msg, sizeof(err_msg), "failed to create socket: %s", strerror(errno)); error_set(errp, QERR_QGA_COMMAND_FAILED, err_msg); goto error; } memset(&ifr, 0, sizeof(ifr)); strncpy(ifr.ifr_name, info->value->name, IF_NAMESIZE); if (ioctl(sock, SIOCGIFHWADDR, &ifr) == -1) { snprintf(err_msg, sizeof(err_msg), "failed to get MAC addres of %s: %s", ifa->ifa_name, strerror(errno)); error_set(errp, QERR_QGA_COMMAND_FAILED, err_msg); goto error; } mac_addr = (unsigned char *) &ifr.ifr_hwaddr.sa_data; if (asprintf(&info->value->hardware_address, "%02x:%02x:%02x:%02x:%02x:%02x", (int) mac_addr[0], (int) mac_addr[1], (int) mac_addr[2], (int) mac_addr[3], (int) mac_addr[4], (int) mac_addr[5]) == -1) { snprintf(err_msg, sizeof(err_msg), "failed to format MAC: %s", strerror(errno)); error_set(errp, QERR_QGA_COMMAND_FAILED, err_msg); goto error; } info->value->has_hardware_address = true; close(sock); } if (ifa->ifa_addr && ifa->ifa_addr->sa_family == AF_INET) { /* interface with IPv4 address */ address_item = g_malloc0(sizeof(*address_item)); address_item->value = g_malloc0(sizeof(*address_item->value)); p = &((struct sockaddr_in *)ifa->ifa_addr)->sin_addr; if (!inet_ntop(AF_INET, p, addr4, sizeof(addr4))) { snprintf(err_msg, sizeof(err_msg), "inet_ntop failed : %s", strerror(errno)); error_set(errp, QERR_QGA_COMMAND_FAILED, err_msg); goto error; } address_item->value->ip_address = g_strdup(addr4); address_item->value->ip_address_type = GUEST_IP_ADDRESS_TYPE_IPV4; if (ifa->ifa_netmask) { /* Count the number of set bits in netmask. * This is safe as '1' and '0' cannot be shuffled in netmask. */ p = &((struct sockaddr_in *)ifa->ifa_netmask)->sin_addr; address_item->value->prefix = ctpop32(((uint32_t *) p)[0]); } } else if (ifa->ifa_addr && ifa->ifa_addr->sa_family == AF_INET6) { /* interface with IPv6 address */ address_item = g_malloc0(sizeof(*address_item)); address_item->value = g_malloc0(sizeof(*address_item->value)); p = &((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr; if (!inet_ntop(AF_INET6, p, addr6, sizeof(addr6))) { snprintf(err_msg, sizeof(err_msg), "inet_ntop failed : %s", strerror(errno)); error_set(errp, QERR_QGA_COMMAND_FAILED, err_msg); goto error; } address_item->value->ip_address = g_strdup(addr6); address_item->value->ip_address_type = GUEST_IP_ADDRESS_TYPE_IPV6; if (ifa->ifa_netmask) { /* Count the number of set bits in netmask. * This is safe as '1' and '0' cannot be shuffled in netmask. */ p = &((struct sockaddr_in6 *)ifa->ifa_netmask)->sin6_addr; address_item->value->prefix = ctpop32(((uint32_t *) p)[0]) + ctpop32(((uint32_t *) p)[1]) + ctpop32(((uint32_t *) p)[2]) + ctpop32(((uint32_t *) p)[3]); } } if (!address_item) { continue; } address_list = &info->value->ip_addresses; while (*address_list && (*address_list)->next) { address_list = &(*address_list)->next; } if (!*address_list) { *address_list = address_item; } else { (*address_list)->next = address_item; } info->value->has_ip_addresses = true; } freeifaddrs(ifap); return head; error: freeifaddrs(ifap); qapi_free_GuestNetworkInterfaceList(head); return NULL; }


static inline int coef_test_compression(int coef) { int tmp = coef >> 2; int res = ff_ctz(tmp); if (res > 1) return 1; /* ...00 -> compressable */ else if (res == 1) return 0; /* ...10 -> uncompressable */ else if (ff_ctz(tmp >> 1) > 0) return 0; /* ...0 1 -> uncompressable */ else return 1; /* ...1 1 -> compressable */ }


static int ac97_load (QEMUFile *f, void *opaque, int version_id) { int ret; size_t i; uint8_t active[LAST_INDEX]; AC97LinkState *s = opaque; if (version_id != 2) return -EINVAL; ret = pci_device_load (s->pci_dev, f); if (ret) return ret; qemu_get_be32s (f, &s->glob_cnt); qemu_get_be32s (f, &s->glob_sta); qemu_get_be32s (f, &s->cas); for (i = 0; i < ARRAY_SIZE (s->bm_regs); ++i) { AC97BusMasterRegs *r = &s->bm_regs[i]; qemu_get_be32s (f, &r->bdbar); qemu_get_8s (f, &r->civ); qemu_get_8s (f, &r->lvi); qemu_get_be16s (f, &r->sr); qemu_get_be16s (f, &r->picb); qemu_get_8s (f, &r->piv); qemu_get_8s (f, &r->cr); qemu_get_be32s (f, &r->bd_valid); qemu_get_be32s (f, &r->bd.addr); qemu_get_be32s (f, &r->bd.ctl_len); } qemu_get_buffer (f, s->mixer_data, sizeof (s->mixer_data)); qemu_get_buffer (f, active, sizeof (active)); #ifdef USE_MIXER record_select (s, mixer_load (s, AC97_Record_Select)); #define V_(a, b) set_volume (s, a, b, mixer_load (s, a)) V_ (AC97_Master_Volume_Mute, AUD_MIXER_VOLUME); V_ (AC97_PCM_Out_Volume_Mute, AUD_MIXER_PCM); V_ (AC97_Line_In_Volume_Mute, AUD_MIXER_LINE_IN); #undef V_ #endif reset_voices (s, active); s->bup_flag = 0; s->last_samp = 0; return 0; }


void usb_test_hotplug(const char *hcd_id, const int port, void (*port_check)(void)) { QDict *response; char *cmd; cmd = g_strdup_printf("{'execute': 'device_add'," " 'arguments': {" " 'driver': 'usb-tablet'," " 'port': '%d'," " 'bus': '%s.0'," " 'id': 'usbdev%d'" "}}", port, hcd_id, port); response = qmp(cmd); g_free(cmd); g_assert(response); g_assert(!qdict_haskey(response, "error")); QDECREF(response); if (port_check) { port_check(); } cmd = g_strdup_printf("{'execute': 'device_del'," " 'arguments': {" " 'id': 'usbdev%d'" "}}", port); response = qmp(cmd); g_free(cmd); g_assert(response); g_assert(qdict_haskey(response, "event")); g_assert(!strcmp(qdict_get_str(response, "event"), "DEVICE_DELETED")); QDECREF(response); }


bool qemu_signalfd_available(void) { #ifdef CONFIG_SIGNALFD errno = 0; syscall(SYS_signalfd, -1, NULL, _NSIG / 8); return errno != ENOSYS; #else return false; #endif }


static int xen_pt_byte_reg_write(XenPCIPassthroughState *s, XenPTReg *cfg_entry, uint8_t *val, uint8_t dev_value, uint8_t valid_mask) { XenPTRegInfo *reg = cfg_entry->reg; uint8_t writable_mask = 0; uint8_t throughable_mask = get_throughable_mask(s, reg, valid_mask); /* modify emulate register */ writable_mask = reg->emu_mask & ~reg->ro_mask & valid_mask; cfg_entry->data = XEN_PT_MERGE_VALUE(*val, cfg_entry->data, writable_mask); /* create value for writing to I/O device register */ *val = XEN_PT_MERGE_VALUE(*val, dev_value, throughable_mask); return 0; }


static void omap_update_display(void *opaque) { struct omap_lcd_panel_s *omap_lcd = (struct omap_lcd_panel_s *) opaque; DisplaySurface *surface = qemu_console_surface(omap_lcd->con); draw_line_func draw_line; int size, height, first, last; int width, linesize, step, bpp, frame_offset; hwaddr frame_base; if (!omap_lcd || omap_lcd->plm == 1 || !omap_lcd->enable || !surface_bits_per_pixel(surface)) { return; } frame_offset = 0; if (omap_lcd->plm != 2) { cpu_physical_memory_read(omap_lcd->dma->phys_framebuffer[ omap_lcd->dma->current_frame], (void *)omap_lcd->palette, 0x200); switch (omap_lcd->palette[0] >> 12 & 7) { case 3 ... 7: frame_offset += 0x200; break; default: frame_offset += 0x20; } } /* Colour depth */ switch ((omap_lcd->palette[0] >> 12) & 7) { case 1: draw_line = draw_line_table2[surface_bits_per_pixel(surface)]; bpp = 2; break; case 2: draw_line = draw_line_table4[surface_bits_per_pixel(surface)]; bpp = 4; break; case 3: draw_line = draw_line_table8[surface_bits_per_pixel(surface)]; bpp = 8; break; case 4 ... 7: if (!omap_lcd->tft) draw_line = draw_line_table12[surface_bits_per_pixel(surface)]; else draw_line = draw_line_table16[surface_bits_per_pixel(surface)]; bpp = 16; break; default: /* Unsupported at the moment. */ return; } /* Resolution */ width = omap_lcd->width; if (width != surface_width(surface) || omap_lcd->height != surface_height(surface)) { qemu_console_resize(omap_lcd->con, omap_lcd->width, omap_lcd->height); surface = qemu_console_surface(omap_lcd->con); omap_lcd->invalidate = 1; } if (omap_lcd->dma->current_frame == 0) size = omap_lcd->dma->src_f1_bottom - omap_lcd->dma->src_f1_top; else size = omap_lcd->dma->src_f2_bottom - omap_lcd->dma->src_f2_top; if (frame_offset + ((width * omap_lcd->height * bpp) >> 3) > size + 2) { omap_lcd->sync_error = 1; omap_lcd_interrupts(omap_lcd); omap_lcd->enable = 0; return; } /* Content */ frame_base = omap_lcd->dma->phys_framebuffer[ omap_lcd->dma->current_frame] + frame_offset; omap_lcd->dma->condition |= 1 << omap_lcd->dma->current_frame; if (omap_lcd->dma->interrupts & 1) qemu_irq_raise(omap_lcd->dma->irq); if (omap_lcd->dma->dual) omap_lcd->dma->current_frame ^= 1; if (!surface_bits_per_pixel(surface)) { return; } first = 0; height = omap_lcd->height; if (omap_lcd->subpanel & (1 << 31)) { if (omap_lcd->subpanel & (1 << 29)) first = (omap_lcd->subpanel >> 16) & 0x3ff; else height = (omap_lcd->subpanel >> 16) & 0x3ff; /* TODO: fill the rest of the panel with DPD */ } step = width * bpp >> 3; linesize = surface_stride(surface); framebuffer_update_display(surface, omap_lcd->sysmem, frame_base, width, height, step, linesize, 0, omap_lcd->invalidate, draw_line, omap_lcd->palette, &first, &last); if (first >= 0) { dpy_gfx_update(omap_lcd->con, 0, first, width, last - first + 1); } omap_lcd->invalidate = 0; }


static void rcu_qtest(const char *test, int duration, int nreaders) { int i; long long n_removed_local = 0; struct list_element *el, *prev_el; rcu_qtest_init(); for (i = 0; i < nreaders; i++) { create_thread(rcu_q_reader); } create_thread(rcu_q_updater); rcu_qtest_run(duration, nreaders); QLIST_FOREACH_SAFE_RCU(prev_el, &Q_list_head, entry, el) { QLIST_REMOVE_RCU(prev_el, entry); call_rcu1(&prev_el->rcu, reclaim_list_el); n_removed_local++; } atomic_add(&n_nodes_removed, n_removed_local); synchronize_rcu(); while (n_nodes_removed > n_reclaims) { g_usleep(100); synchronize_rcu(); } if (g_test_in_charge) { g_assert_cmpint(n_nodes_removed, ==, n_reclaims); } else { printf("%s: %d readers; 1 updater; nodes read: " \ "%lld, nodes removed: %lld; nodes reclaimed: %lld\n", test, nthreadsrunning - 1, n_reads, n_nodes_removed, n_reclaims); exit(0); } }


void qemu_chr_close(CharDriverState *chr) { TAILQ_REMOVE(&chardevs, chr, next); if (chr->chr_close) chr->chr_close(chr); qemu_free(chr->filename); qemu_free(chr->label); qemu_free(chr); }


static void mirror_start_job(const char *job_id, BlockDriverState *bs, int creation_flags, BlockDriverState *target, const char *replaces, int64_t speed, uint32_t granularity, int64_t buf_size, BlockMirrorBackingMode backing_mode, BlockdevOnError on_source_error, BlockdevOnError on_target_error, bool unmap, BlockCompletionFunc *cb, void *opaque, const BlockJobDriver *driver, bool is_none_mode, BlockDriverState *base, bool auto_complete, const char *filter_node_name, bool is_mirror, Error **errp) { MirrorBlockJob *s; BlockDriverState *mirror_top_bs; bool target_graph_mod; bool target_is_backing; Error *local_err = NULL; int ret; if (granularity == 0) { granularity = bdrv_get_default_bitmap_granularity(target); } assert ((granularity & (granularity - 1)) == 0); /* Granularity must be large enough for sector-based dirty bitmap */ assert(granularity >= BDRV_SECTOR_SIZE); if (buf_size < 0) { error_setg(errp, "Invalid parameter 'buf-size'"); return; } if (buf_size == 0) { buf_size = DEFAULT_MIRROR_BUF_SIZE; } /* In the case of active commit, add dummy driver to provide consistent * reads on the top, while disabling it in the intermediate nodes, and make * the backing chain writable. */ mirror_top_bs = bdrv_new_open_driver(&bdrv_mirror_top, filter_node_name, BDRV_O_RDWR, errp); if (mirror_top_bs == NULL) { return; } if (!filter_node_name) { mirror_top_bs->implicit = true; } mirror_top_bs->total_sectors = bs->total_sectors; bdrv_set_aio_context(mirror_top_bs, bdrv_get_aio_context(bs)); /* bdrv_append takes ownership of the mirror_top_bs reference, need to keep * it alive until block_job_create() succeeds even if bs has no parent. */ bdrv_ref(mirror_top_bs); bdrv_drained_begin(bs); bdrv_append(mirror_top_bs, bs, &local_err); bdrv_drained_end(bs); if (local_err) { bdrv_unref(mirror_top_bs); error_propagate(errp, local_err); return; } /* Make sure that the source is not resized while the job is running */ s = block_job_create(job_id, driver, mirror_top_bs, BLK_PERM_CONSISTENT_READ, BLK_PERM_CONSISTENT_READ | BLK_PERM_WRITE_UNCHANGED | BLK_PERM_WRITE | BLK_PERM_GRAPH_MOD, speed, creation_flags, cb, opaque, errp); if (!s) { goto fail; } /* The block job now has a reference to this node */ bdrv_unref(mirror_top_bs); s->source = bs; s->mirror_top_bs = mirror_top_bs; /* No resize for the target either; while the mirror is still running, a * consistent read isn't necessarily possible. We could possibly allow * writes and graph modifications, though it would likely defeat the * purpose of a mirror, so leave them blocked for now. * * In the case of active commit, things look a bit different, though, * because the target is an already populated backing file in active use. * We can allow anything except resize there.*/ target_is_backing = bdrv_chain_contains(bs, target); target_graph_mod = (backing_mode != MIRROR_LEAVE_BACKING_CHAIN); s->target = blk_new(BLK_PERM_WRITE | BLK_PERM_RESIZE | (target_graph_mod ? BLK_PERM_GRAPH_MOD : 0), BLK_PERM_WRITE_UNCHANGED | (target_is_backing ? BLK_PERM_CONSISTENT_READ | BLK_PERM_WRITE | BLK_PERM_GRAPH_MOD : 0)); ret = blk_insert_bs(s->target, target, errp); if (ret < 0) { goto fail; } if (is_mirror) { /* XXX: Mirror target could be a NBD server of target QEMU in the case * of non-shared block migration. To allow migration completion, we * have to allow "inactivate" of the target BB. When that happens, we * know the job is drained, and the vcpus are stopped, so no write * operation will be performed. Block layer already has assertions to * ensure that. */ blk_set_force_allow_inactivate(s->target); } s->replaces = g_strdup(replaces); s->on_source_error = on_source_error; s->on_target_error = on_target_error; s->is_none_mode = is_none_mode; s->backing_mode = backing_mode; s->base = base; s->granularity = granularity; s->buf_size = ROUND_UP(buf_size, granularity); s->unmap = unmap; if (auto_complete) { s->should_complete = true; } s->dirty_bitmap = bdrv_create_dirty_bitmap(bs, granularity, NULL, errp); if (!s->dirty_bitmap) { goto fail; } /* Required permissions are already taken with blk_new() */ block_job_add_bdrv(&s->common, "target", target, 0, BLK_PERM_ALL, &error_abort); /* In commit_active_start() all intermediate nodes disappear, so * any jobs in them must be blocked */ if (target_is_backing) { BlockDriverState *iter; for (iter = backing_bs(bs); iter != target; iter = backing_bs(iter)) { /* XXX BLK_PERM_WRITE needs to be allowed so we don't block * ourselves at s->base (if writes are blocked for a node, they are * also blocked for its backing file). The other options would be a * second filter driver above s->base (== target). */ ret = block_job_add_bdrv(&s->common, "intermediate node", iter, 0, BLK_PERM_WRITE_UNCHANGED | BLK_PERM_WRITE, errp); if (ret < 0) { goto fail; } } } trace_mirror_start(bs, s, opaque); block_job_start(&s->common); return; fail: if (s) { /* Make sure this BDS does not go away until we have completed the graph * changes below */ bdrv_ref(mirror_top_bs); g_free(s->replaces); blk_unref(s->target); block_job_early_fail(&s->common); } bdrv_child_try_set_perm(mirror_top_bs->backing, 0, BLK_PERM_ALL, &error_abort); bdrv_replace_node(mirror_top_bs, backing_bs(mirror_top_bs), &error_abort); bdrv_unref(mirror_top_bs); }


static void test_acpi_tables(test_data *data) { int tables_nr = data->rsdt_tables_nr - 1; /* fadt is first */ int i; for (i = 0; i < tables_nr; i++) { AcpiSdtTable ssdt_table; uint32_t addr; addr = le32_to_cpu(data->rsdt_tables_addr[i + 1]); /* fadt is first */ test_dst_table(&ssdt_table, addr); g_array_append_val(data->tables, ssdt_table); } }


void cris_mmu_flush_pid(CPUState *env, uint32_t pid) { target_ulong vaddr; unsigned int idx; uint32_t lo, hi; uint32_t tlb_vpn; int tlb_pid, tlb_g, tlb_v, tlb_k; unsigned int set; unsigned int mmu; pid &= 0xff; for (mmu = 0; mmu < 2; mmu++) { for (set = 0; set < 4; set++) { for (idx = 0; idx < 16; idx++) { lo = env->tlbsets[mmu][set][idx].lo; hi = env->tlbsets[mmu][set][idx].hi; tlb_vpn = EXTRACT_FIELD(hi, 13, 31); tlb_pid = EXTRACT_FIELD(hi, 0, 7); tlb_g = EXTRACT_FIELD(lo, 4, 4); tlb_v = EXTRACT_FIELD(lo, 3, 3); tlb_k = EXTRACT_FIELD(lo, 2, 2); /* Kernel protected areas need to be flushed as well. */ if (tlb_v && !tlb_g && (tlb_pid == pid || tlb_k)) { vaddr = tlb_vpn << TARGET_PAGE_BITS; D(fprintf(logfile, "flush pid=%x vaddr=%x\n", pid, vaddr)); tlb_flush_page(env, vaddr); } } } } }


static void vfio_intp_interrupt(VFIOINTp *intp) { int ret; VFIOINTp *tmp; VFIOPlatformDevice *vdev = intp->vdev; bool delay_handling = false; qemu_mutex_lock(&vdev->intp_mutex); if (intp->state == VFIO_IRQ_INACTIVE) { QLIST_FOREACH(tmp, &vdev->intp_list, next) { if (tmp->state == VFIO_IRQ_ACTIVE || tmp->state == VFIO_IRQ_PENDING) { delay_handling = true; break; } } } if (delay_handling) { /* * the new IRQ gets a pending status and is pushed in * the pending queue */ intp->state = VFIO_IRQ_PENDING; trace_vfio_intp_interrupt_set_pending(intp->pin); QSIMPLEQ_INSERT_TAIL(&vdev->pending_intp_queue, intp, pqnext); ret = event_notifier_test_and_clear(&intp->interrupt); qemu_mutex_unlock(&vdev->intp_mutex); return; } trace_vfio_platform_intp_interrupt(intp->pin, event_notifier_get_fd(&intp->interrupt)); ret = event_notifier_test_and_clear(&intp->interrupt); if (!ret) { error_report("Error when clearing fd=%d (ret = %d)", event_notifier_get_fd(&intp->interrupt), ret); } intp->state = VFIO_IRQ_ACTIVE; /* sets slow path */ vfio_mmap_set_enabled(vdev, false); /* trigger the virtual IRQ */ qemu_set_irq(intp->qemuirq, 1); /* * Schedule the mmap timer which will restore fastpath when no IRQ * is active anymore */ if (vdev->mmap_timeout) { timer_mod(vdev->mmap_timer, qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) + vdev->mmap_timeout); } qemu_mutex_unlock(&vdev->intp_mutex); }


void tb_invalidate_phys_addr(hwaddr addr) { ram_addr_t ram_addr; MemoryRegionSection *section; section = phys_page_find(address_space_memory.dispatch, addr >> TARGET_PAGE_BITS); if (!(memory_region_is_ram(section->mr) || memory_region_is_romd(section->mr))) { return; } ram_addr = (memory_region_get_ram_addr(section->mr) & TARGET_PAGE_MASK) + memory_region_section_addr(section, addr); tb_invalidate_phys_page_range(ram_addr, ram_addr + 1, 0); }


static void lsi_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); k->init = lsi_scsi_init; k->exit = lsi_scsi_uninit; k->vendor_id = PCI_VENDOR_ID_LSI_LOGIC; k->device_id = PCI_DEVICE_ID_LSI_53C895A; k->class_id = PCI_CLASS_STORAGE_SCSI; k->subsystem_id = 0x1000; dc->alias = "lsi"; dc->reset = lsi_scsi_reset; dc->vmsd = &vmstate_lsi_scsi; }


static void sigp_stop(CPUState *cs, run_on_cpu_data arg) { S390CPU *cpu = S390_CPU(cs); SigpInfo *si = arg.host_ptr; if (s390_cpu_get_state(cpu) != CPU_STATE_OPERATING) { si->cc = SIGP_CC_ORDER_CODE_ACCEPTED; return; } /* disabled wait - sleeping in user space */ if (cs->halted) { s390_cpu_set_state(CPU_STATE_STOPPED, cpu); } else { /* execute the stop function */ cpu->env.sigp_order = SIGP_STOP; cpu_inject_stop(cpu); } si->cc = SIGP_CC_ORDER_CODE_ACCEPTED; }