static void pci_piix_init_ports(PCIIDEState *d) { int i; struct { int iobase; int iobase2; int isairq; } port_info[] = { {0x1f0, 0x3f6, 14}, {0x170, 0x376, 15}, }; for (i = 0; i < 2; i++) { ide_bus_new(&d->bus[i], &d->dev.qdev, i); ide_init_ioport(&d->bus[i], port_info[i].iobase, port_info[i].iobase2); ide_init2(&d->bus[i], isa_reserve_irq(port_info[i].isairq)); bmdma_init(&d->bus[i], &d->bmdma[i]); d->bmdma[i].bus = &d->bus[i]; qemu_add_vm_change_state_handler(d->bus[i].dma->ops->restart_cb, &d->bmdma[i].dma); } }


void load_seg(int seg_reg, int selector) { SegmentCache *sc; SegmentDescriptorTable *dt; int index; uint32_t e1, e2; uint8_t *ptr; env->segs[seg_reg] = selector; sc = &env->seg_cache[seg_reg]; if (env->eflags & VM_MASK) { sc->base = (void *)(selector << 4); sc->limit = 0xffff; sc->seg_32bit = 0; } else { if (selector & 0x4) dt = &env->ldt; else dt = &env->gdt; index = selector & ~7; if ((index + 7) > dt->limit) raise_exception_err(EXCP0D_GPF, selector); ptr = dt->base + index; e1 = ldl(ptr); e2 = ldl(ptr + 4); sc->base = (void *)((e1 >> 16) | ((e2 & 0xff) << 16) | (e2 & 0xff000000)); sc->limit = (e1 & 0xffff) | (e2 & 0x000f0000); if (e2 & (1 << 23)) sc->limit = (sc->limit << 12) | 0xfff; sc->seg_32bit = (e2 >> 22) & 1; #if 0 fprintf(logfile, "load_seg: sel=0x%04x base=0x%08lx limit=0x%08lx seg_32bit=%d\n", selector, (unsigned long)sc->base, sc->limit, sc->seg_32bit); #endif } }


static BlockBackend *blockdev_init(const char *file, QDict *bs_opts, Error **errp) { const char *buf; int bdrv_flags = 0; int on_read_error, on_write_error; bool account_invalid, account_failed; const char *stats_intervals; BlockBackend *blk; BlockDriverState *bs; ThrottleConfig cfg; int snapshot = 0; Error *error = NULL; QemuOpts *opts; const char *id; bool has_driver_specific_opts; BlockdevDetectZeroesOptions detect_zeroes = BLOCKDEV_DETECT_ZEROES_OPTIONS_OFF; const char *throttling_group = NULL; /* Check common options by copying from bs_opts to opts, all other options * stay in bs_opts for processing by bdrv_open(). */ id = qdict_get_try_str(bs_opts, "id"); opts = qemu_opts_create(&qemu_common_drive_opts, id, 1, &error); if (error) { error_propagate(errp, error); goto err_no_opts; } qemu_opts_absorb_qdict(opts, bs_opts, &error); if (error) { error_propagate(errp, error); goto early_err; } if (id) { qdict_del(bs_opts, "id"); } has_driver_specific_opts = !!qdict_size(bs_opts); /* extract parameters */ snapshot = qemu_opt_get_bool(opts, "snapshot", 0); account_invalid = qemu_opt_get_bool(opts, "stats-account-invalid", true); account_failed = qemu_opt_get_bool(opts, "stats-account-failed", true); stats_intervals = qemu_opt_get(opts, "stats-intervals"); extract_common_blockdev_options(opts, &bdrv_flags, &throttling_group, &cfg, &detect_zeroes, &error); if (error) { error_propagate(errp, error); goto early_err; } if ((buf = qemu_opt_get(opts, "format")) != NULL) { if (is_help_option(buf)) { error_printf("Supported formats:"); bdrv_iterate_format(bdrv_format_print, NULL); error_printf("\n"); goto early_err; } if (qdict_haskey(bs_opts, "driver")) { error_setg(errp, "Cannot specify both 'driver' and 'format'"); goto early_err; } qdict_put(bs_opts, "driver", qstring_from_str(buf)); } on_write_error = BLOCKDEV_ON_ERROR_ENOSPC; if ((buf = qemu_opt_get(opts, "werror")) != NULL) { on_write_error = parse_block_error_action(buf, 0, &error); if (error) { error_propagate(errp, error); goto early_err; } } on_read_error = BLOCKDEV_ON_ERROR_REPORT; if ((buf = qemu_opt_get(opts, "rerror")) != NULL) { on_read_error = parse_block_error_action(buf, 1, &error); if (error) { error_propagate(errp, error); goto early_err; } } if (snapshot) { /* always use cache=unsafe with snapshot */ bdrv_flags &= ~BDRV_O_CACHE_MASK; bdrv_flags |= (BDRV_O_SNAPSHOT|BDRV_O_CACHE_WB|BDRV_O_NO_FLUSH); } /* init */ if ((!file || !*file) && !has_driver_specific_opts) { BlockBackendRootState *blk_rs; blk = blk_new(qemu_opts_id(opts), errp); if (!blk) { goto early_err; } blk_rs = blk_get_root_state(blk); blk_rs->open_flags = bdrv_flags; blk_rs->read_only = !(bdrv_flags & BDRV_O_RDWR); blk_rs->detect_zeroes = detect_zeroes; if (throttle_enabled(&cfg)) { if (!throttling_group) { throttling_group = blk_name(blk); } blk_rs->throttle_group = g_strdup(throttling_group); blk_rs->throttle_state = throttle_group_incref(throttling_group); blk_rs->throttle_state->cfg = cfg; } QDECREF(bs_opts); } else { if (file && !*file) { file = NULL; } blk = blk_new_open(qemu_opts_id(opts), file, NULL, bs_opts, bdrv_flags, errp); if (!blk) { goto err_no_bs_opts; } bs = blk_bs(blk); bs->detect_zeroes = detect_zeroes; /* disk I/O throttling */ if (throttle_enabled(&cfg)) { if (!throttling_group) { throttling_group = blk_name(blk); } bdrv_io_limits_enable(bs, throttling_group); bdrv_set_io_limits(bs, &cfg); } if (bdrv_key_required(bs)) { autostart = 0; } block_acct_init(blk_get_stats(blk), account_invalid, account_failed); if (stats_intervals) { char **intervals = g_strsplit(stats_intervals, ":", 0); unsigned i; if (*stats_intervals == '\0') { error_setg(&error, "stats-intervals can't have an empty value"); } for (i = 0; !error && intervals[i] != NULL; i++) { unsigned long long val; if (parse_uint_full(intervals[i], &val, 10) == 0 && val > 0 && val <= UINT_MAX) { block_acct_add_interval(blk_get_stats(blk), val); } else { error_setg(&error, "Invalid interval length: '%s'", intervals[i]); } } g_strfreev(intervals); if (error) { error_propagate(errp, error); blk_unref(blk); blk = NULL; goto err_no_bs_opts; } } } blk_set_on_error(blk, on_read_error, on_write_error); err_no_bs_opts: qemu_opts_del(opts); return blk; early_err: qemu_opts_del(opts); err_no_opts: QDECREF(bs_opts); return NULL; }


av_cold void ff_dsputil_init_armv5te(DSPContext *c, AVCodecContext *avctx) { if (avctx->bits_per_raw_sample <= 8 && (avctx->idct_algo == FF_IDCT_AUTO || avctx->idct_algo == FF_IDCT_SIMPLEARMV5TE)) { c->idct_put = ff_simple_idct_put_armv5te; c->idct_add = ff_simple_idct_add_armv5te; c->idct = ff_simple_idct_armv5te; c->idct_permutation_type = FF_NO_IDCT_PERM; } c->prefetch = ff_prefetch_arm; }


static QObject *qmp_input_get_object(QmpInputVisitor *qiv, const char *name, bool consume, Error **errp) { StackObject *tos; QObject *qobj; QObject *ret; if (QSLIST_EMPTY(&qiv->stack)) { /* Starting at root, name is ignored. */ assert(qiv->root); return qiv->root; } /* We are in a container; find the next element. */ tos = QSLIST_FIRST(&qiv->stack); qobj = tos->obj; assert(qobj); if (qobject_type(qobj) == QTYPE_QDICT) { assert(name); ret = qdict_get(qobject_to_qdict(qobj), name); if (tos->h && consume && ret) { bool removed = g_hash_table_remove(tos->h, name); assert(removed); } if (!ret) { error_setg(errp, QERR_MISSING_PARAMETER, name); } } else { assert(qobject_type(qobj) == QTYPE_QLIST); assert(!name); ret = qlist_entry_obj(tos->entry); assert(ret); if (consume) { tos->entry = qlist_next(tos->entry); } } return ret; }


static void rtas_ibm_set_slot_reset(PowerPCCPU *cpu, sPAPREnvironment *spapr, uint32_t token, uint32_t nargs, target_ulong args, uint32_t nret, target_ulong rets) { sPAPRPHBState *sphb; sPAPRPHBClass *spc; uint32_t option; uint64_t buid; int ret; if ((nargs != 4) || (nret != 1)) { goto param_error_exit; } buid = ((uint64_t)rtas_ld(args, 1) << 32) | rtas_ld(args, 2); option = rtas_ld(args, 3); sphb = find_phb(spapr, buid); if (!sphb) { goto param_error_exit; } spc = SPAPR_PCI_HOST_BRIDGE_GET_CLASS(sphb); if (!spc->eeh_reset) { goto param_error_exit; } ret = spc->eeh_reset(sphb, option); rtas_st(rets, 0, ret); return; param_error_exit: rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR); }


int pp_check(int key, int pp, int nx) { int access; /* Compute access rights */ /* When pp is 3/7, the result is undefined. Set it to noaccess */ access = 0; if (key == 0) { switch (pp) { case 0x0: case 0x1: case 0x2: access |= PAGE_WRITE; /* No break here */ case 0x3: case 0x6: access |= PAGE_READ; break; } } else { switch (pp) { case 0x0: case 0x6: access = 0; break; case 0x1: case 0x3: access = PAGE_READ; break; case 0x2: access = PAGE_READ | PAGE_WRITE; break; } } if (nx == 0) { access |= PAGE_EXEC; } return access; }


static bool check_section_footer(QEMUFile *f, SaveStateEntry *se) { uint8_t read_mark; uint32_t read_section_id; if (skip_section_footers) { /* No footer to check */ return true; } read_mark = qemu_get_byte(f); if (read_mark != QEMU_VM_SECTION_FOOTER) { error_report("Missing section footer for %s", se->idstr); return false; } read_section_id = qemu_get_be32(f); if (read_section_id != se->section_id) { error_report("Mismatched section id in footer for %s -" " read 0x%x expected 0x%x", se->idstr, read_section_id, se->section_id); return false; } /* All good */ return true; }


static int disas_neon_data_insn(DisasContext *s, uint32_t insn) { int op; int q; int rd, rn, rm; int size; int shift; int pass; int count; int pairwise; int u; uint32_t imm, mask; TCGv_i32 tmp, tmp2, tmp3, tmp4, tmp5; TCGv_i64 tmp64; /* FIXME: this access check should not take precedence over UNDEF * for invalid encodings; we will generate incorrect syndrome information * for attempts to execute invalid vfp/neon encodings with FP disabled. */ if (!s->cpacr_fpen) { gen_exception_insn(s, 4, EXCP_UDEF, syn_fp_access_trap(1, 0xe, s->thumb), default_exception_el(s)); return 0; } if (!s->vfp_enabled) return 1; q = (insn & (1 << 6)) != 0; u = (insn >> 24) & 1; VFP_DREG_D(rd, insn); VFP_DREG_N(rn, insn); VFP_DREG_M(rm, insn); size = (insn >> 20) & 3; if ((insn & (1 << 23)) == 0) { /* Three register same length. */ op = ((insn >> 7) & 0x1e) | ((insn >> 4) & 1); /* Catch invalid op and bad size combinations: UNDEF */ if ((neon_3r_sizes[op] & (1 << size)) == 0) { return 1; } /* All insns of this form UNDEF for either this condition or the * superset of cases "Q==1"; we catch the latter later. */ if (q && ((rd | rn | rm) & 1)) { return 1; } /* * The SHA-1/SHA-256 3-register instructions require special treatment * here, as their size field is overloaded as an op type selector, and * they all consume their input in a single pass. */ if (op == NEON_3R_SHA) { if (!q) { return 1; } if (!u) { /* SHA-1 */ if (!arm_dc_feature(s, ARM_FEATURE_V8_SHA1)) { return 1; } tmp = tcg_const_i32(rd); tmp2 = tcg_const_i32(rn); tmp3 = tcg_const_i32(rm); tmp4 = tcg_const_i32(size); gen_helper_crypto_sha1_3reg(cpu_env, tmp, tmp2, tmp3, tmp4); tcg_temp_free_i32(tmp4); } else { /* SHA-256 */ if (!arm_dc_feature(s, ARM_FEATURE_V8_SHA256) || size == 3) { return 1; } tmp = tcg_const_i32(rd); tmp2 = tcg_const_i32(rn); tmp3 = tcg_const_i32(rm); switch (size) { case 0: gen_helper_crypto_sha256h(cpu_env, tmp, tmp2, tmp3); break; case 1: gen_helper_crypto_sha256h2(cpu_env, tmp, tmp2, tmp3); break; case 2: gen_helper_crypto_sha256su1(cpu_env, tmp, tmp2, tmp3); break; } } tcg_temp_free_i32(tmp); tcg_temp_free_i32(tmp2); tcg_temp_free_i32(tmp3); return 0; } if (size == 3 && op != NEON_3R_LOGIC) { /* 64-bit element instructions. */ for (pass = 0; pass < (q ? 2 : 1); pass++) { neon_load_reg64(cpu_V0, rn + pass); neon_load_reg64(cpu_V1, rm + pass); switch (op) { case NEON_3R_VQADD: if (u) { gen_helper_neon_qadd_u64(cpu_V0, cpu_env, cpu_V0, cpu_V1); } else { gen_helper_neon_qadd_s64(cpu_V0, cpu_env, cpu_V0, cpu_V1); } break; case NEON_3R_VQSUB: if (u) { gen_helper_neon_qsub_u64(cpu_V0, cpu_env, cpu_V0, cpu_V1); } else { gen_helper_neon_qsub_s64(cpu_V0, cpu_env, cpu_V0, cpu_V1); } break; case NEON_3R_VSHL: if (u) { gen_helper_neon_shl_u64(cpu_V0, cpu_V1, cpu_V0); } else { gen_helper_neon_shl_s64(cpu_V0, cpu_V1, cpu_V0); } break; case NEON_3R_VQSHL: if (u) { gen_helper_neon_qshl_u64(cpu_V0, cpu_env, cpu_V1, cpu_V0); } else { gen_helper_neon_qshl_s64(cpu_V0, cpu_env, cpu_V1, cpu_V0); } break; case NEON_3R_VRSHL: if (u) { gen_helper_neon_rshl_u64(cpu_V0, cpu_V1, cpu_V0); } else { gen_helper_neon_rshl_s64(cpu_V0, cpu_V1, cpu_V0); } break; case NEON_3R_VQRSHL: if (u) { gen_helper_neon_qrshl_u64(cpu_V0, cpu_env, cpu_V1, cpu_V0); } else { gen_helper_neon_qrshl_s64(cpu_V0, cpu_env, cpu_V1, cpu_V0); } break; case NEON_3R_VADD_VSUB: if (u) { tcg_gen_sub_i64(CPU_V001); } else { tcg_gen_add_i64(CPU_V001); } break; default: abort(); } neon_store_reg64(cpu_V0, rd + pass); } return 0; } pairwise = 0; switch (op) { case NEON_3R_VSHL: case NEON_3R_VQSHL: case NEON_3R_VRSHL: case NEON_3R_VQRSHL: { int rtmp; /* Shift instruction operands are reversed. */ rtmp = rn; rn = rm; rm = rtmp; } break; case NEON_3R_VPADD: if (u) { return 1; } /* Fall through */ case NEON_3R_VPMAX: case NEON_3R_VPMIN: pairwise = 1; break; case NEON_3R_FLOAT_ARITH: pairwise = (u && size < 2); /* if VPADD (float) */ break; case NEON_3R_FLOAT_MINMAX: pairwise = u; /* if VPMIN/VPMAX (float) */ break; case NEON_3R_FLOAT_CMP: if (!u && size) { /* no encoding for U=0 C=1x */ return 1; } break; case NEON_3R_FLOAT_ACMP: if (!u) { return 1; } break; case NEON_3R_FLOAT_MISC: /* VMAXNM/VMINNM in ARMv8 */ if (u && !arm_dc_feature(s, ARM_FEATURE_V8)) { return 1; } break; case NEON_3R_VMUL: if (u && (size != 0)) { /* UNDEF on invalid size for polynomial subcase */ return 1; } break; case NEON_3R_VFM: if (!arm_dc_feature(s, ARM_FEATURE_VFP4) || u) { return 1; } break; default: break; } if (pairwise && q) { /* All the pairwise insns UNDEF if Q is set */ return 1; } for (pass = 0; pass < (q ? 4 : 2); pass++) { if (pairwise) { /* Pairwise. */ if (pass < 1) { tmp = neon_load_reg(rn, 0); tmp2 = neon_load_reg(rn, 1); } else { tmp = neon_load_reg(rm, 0); tmp2 = neon_load_reg(rm, 1); } } else { /* Elementwise. */ tmp = neon_load_reg(rn, pass); tmp2 = neon_load_reg(rm, pass); } switch (op) { case NEON_3R_VHADD: GEN_NEON_INTEGER_OP(hadd); break; case NEON_3R_VQADD: GEN_NEON_INTEGER_OP_ENV(qadd); break; case NEON_3R_VRHADD: GEN_NEON_INTEGER_OP(rhadd); break; case NEON_3R_LOGIC: /* Logic ops. */ switch ((u << 2) | size) { case 0: /* VAND */ tcg_gen_and_i32(tmp, tmp, tmp2); break; case 1: /* BIC */ tcg_gen_andc_i32(tmp, tmp, tmp2); break; case 2: /* VORR */ tcg_gen_or_i32(tmp, tmp, tmp2); break; case 3: /* VORN */ tcg_gen_orc_i32(tmp, tmp, tmp2); break; case 4: /* VEOR */ tcg_gen_xor_i32(tmp, tmp, tmp2); break; case 5: /* VBSL */ tmp3 = neon_load_reg(rd, pass); gen_neon_bsl(tmp, tmp, tmp2, tmp3); tcg_temp_free_i32(tmp3); break; case 6: /* VBIT */ tmp3 = neon_load_reg(rd, pass); gen_neon_bsl(tmp, tmp, tmp3, tmp2); tcg_temp_free_i32(tmp3); break; case 7: /* VBIF */ tmp3 = neon_load_reg(rd, pass); gen_neon_bsl(tmp, tmp3, tmp, tmp2); tcg_temp_free_i32(tmp3); break; } break; case NEON_3R_VHSUB: GEN_NEON_INTEGER_OP(hsub); break; case NEON_3R_VQSUB: GEN_NEON_INTEGER_OP_ENV(qsub); break; case NEON_3R_VCGT: GEN_NEON_INTEGER_OP(cgt); break; case NEON_3R_VCGE: GEN_NEON_INTEGER_OP(cge); break; case NEON_3R_VSHL: GEN_NEON_INTEGER_OP(shl); break; case NEON_3R_VQSHL: GEN_NEON_INTEGER_OP_ENV(qshl); break; case NEON_3R_VRSHL: GEN_NEON_INTEGER_OP(rshl); break; case NEON_3R_VQRSHL: GEN_NEON_INTEGER_OP_ENV(qrshl); break; case NEON_3R_VMAX: GEN_NEON_INTEGER_OP(max); break; case NEON_3R_VMIN: GEN_NEON_INTEGER_OP(min); break; case NEON_3R_VABD: GEN_NEON_INTEGER_OP(abd); break; case NEON_3R_VABA: GEN_NEON_INTEGER_OP(abd); tcg_temp_free_i32(tmp2); tmp2 = neon_load_reg(rd, pass); gen_neon_add(size, tmp, tmp2); break; case NEON_3R_VADD_VSUB: if (!u) { /* VADD */ gen_neon_add(size, tmp, tmp2); } else { /* VSUB */ switch (size) { case 0: gen_helper_neon_sub_u8(tmp, tmp, tmp2); break; case 1: gen_helper_neon_sub_u16(tmp, tmp, tmp2); break; case 2: tcg_gen_sub_i32(tmp, tmp, tmp2); break; default: abort(); } } break; case NEON_3R_VTST_VCEQ: if (!u) { /* VTST */ switch (size) { case 0: gen_helper_neon_tst_u8(tmp, tmp, tmp2); break; case 1: gen_helper_neon_tst_u16(tmp, tmp, tmp2); break; case 2: gen_helper_neon_tst_u32(tmp, tmp, tmp2); break; default: abort(); } } else { /* VCEQ */ switch (size) { case 0: gen_helper_neon_ceq_u8(tmp, tmp, tmp2); break; case 1: gen_helper_neon_ceq_u16(tmp, tmp, tmp2); break; case 2: gen_helper_neon_ceq_u32(tmp, tmp, tmp2); break; default: abort(); } } break; case NEON_3R_VML: /* VMLA, VMLAL, VMLS,VMLSL */ switch (size) { case 0: gen_helper_neon_mul_u8(tmp, tmp, tmp2); break; case 1: gen_helper_neon_mul_u16(tmp, tmp, tmp2); break; case 2: tcg_gen_mul_i32(tmp, tmp, tmp2); break; default: abort(); } tcg_temp_free_i32(tmp2); tmp2 = neon_load_reg(rd, pass); if (u) { /* VMLS */ gen_neon_rsb(size, tmp, tmp2); } else { /* VMLA */ gen_neon_add(size, tmp, tmp2); } break; case NEON_3R_VMUL: if (u) { /* polynomial */ gen_helper_neon_mul_p8(tmp, tmp, tmp2); } else { /* Integer */ switch (size) { case 0: gen_helper_neon_mul_u8(tmp, tmp, tmp2); break; case 1: gen_helper_neon_mul_u16(tmp, tmp, tmp2); break; case 2: tcg_gen_mul_i32(tmp, tmp, tmp2); break; default: abort(); } } break; case NEON_3R_VPMAX: GEN_NEON_INTEGER_OP(pmax); break; case NEON_3R_VPMIN: GEN_NEON_INTEGER_OP(pmin); break; case NEON_3R_VQDMULH_VQRDMULH: /* Multiply high. */ if (!u) { /* VQDMULH */ switch (size) { case 1: gen_helper_neon_qdmulh_s16(tmp, cpu_env, tmp, tmp2); break; case 2: gen_helper_neon_qdmulh_s32(tmp, cpu_env, tmp, tmp2); break; default: abort(); } } else { /* VQRDMULH */ switch (size) { case 1: gen_helper_neon_qrdmulh_s16(tmp, cpu_env, tmp, tmp2); break; case 2: gen_helper_neon_qrdmulh_s32(tmp, cpu_env, tmp, tmp2); break; default: abort(); } } break; case NEON_3R_VPADD: switch (size) { case 0: gen_helper_neon_padd_u8(tmp, tmp, tmp2); break; case 1: gen_helper_neon_padd_u16(tmp, tmp, tmp2); break; case 2: tcg_gen_add_i32(tmp, tmp, tmp2); break; default: abort(); } break; case NEON_3R_FLOAT_ARITH: /* Floating point arithmetic. */ { TCGv_ptr fpstatus = get_fpstatus_ptr(1); switch ((u << 2) | size) { case 0: /* VADD */ case 4: /* VPADD */ gen_helper_vfp_adds(tmp, tmp, tmp2, fpstatus); break; case 2: /* VSUB */ gen_helper_vfp_subs(tmp, tmp, tmp2, fpstatus); break; case 6: /* VABD */ gen_helper_neon_abd_f32(tmp, tmp, tmp2, fpstatus); break; default: abort(); } tcg_temp_free_ptr(fpstatus); break; } case NEON_3R_FLOAT_MULTIPLY: { TCGv_ptr fpstatus = get_fpstatus_ptr(1); gen_helper_vfp_muls(tmp, tmp, tmp2, fpstatus); if (!u) { tcg_temp_free_i32(tmp2); tmp2 = neon_load_reg(rd, pass); if (size == 0) { gen_helper_vfp_adds(tmp, tmp, tmp2, fpstatus); } else { gen_helper_vfp_subs(tmp, tmp2, tmp, fpstatus); } } tcg_temp_free_ptr(fpstatus); break; } case NEON_3R_FLOAT_CMP: { TCGv_ptr fpstatus = get_fpstatus_ptr(1); if (!u) { gen_helper_neon_ceq_f32(tmp, tmp, tmp2, fpstatus); } else { if (size == 0) { gen_helper_neon_cge_f32(tmp, tmp, tmp2, fpstatus); } else { gen_helper_neon_cgt_f32(tmp, tmp, tmp2, fpstatus); } } tcg_temp_free_ptr(fpstatus); break; } case NEON_3R_FLOAT_ACMP: { TCGv_ptr fpstatus = get_fpstatus_ptr(1); if (size == 0) { gen_helper_neon_acge_f32(tmp, tmp, tmp2, fpstatus); } else { gen_helper_neon_acgt_f32(tmp, tmp, tmp2, fpstatus); } tcg_temp_free_ptr(fpstatus); break; } case NEON_3R_FLOAT_MINMAX: { TCGv_ptr fpstatus = get_fpstatus_ptr(1); if (size == 0) { gen_helper_vfp_maxs(tmp, tmp, tmp2, fpstatus); } else { gen_helper_vfp_mins(tmp, tmp, tmp2, fpstatus); } tcg_temp_free_ptr(fpstatus); break; } case NEON_3R_FLOAT_MISC: if (u) { /* VMAXNM/VMINNM */ TCGv_ptr fpstatus = get_fpstatus_ptr(1); if (size == 0) { gen_helper_vfp_maxnums(tmp, tmp, tmp2, fpstatus); } else { gen_helper_vfp_minnums(tmp, tmp, tmp2, fpstatus); } tcg_temp_free_ptr(fpstatus); } else { if (size == 0) { gen_helper_recps_f32(tmp, tmp, tmp2, cpu_env); } else { gen_helper_rsqrts_f32(tmp, tmp, tmp2, cpu_env); } } break; case NEON_3R_VFM: { /* VFMA, VFMS: fused multiply-add */ TCGv_ptr fpstatus = get_fpstatus_ptr(1); TCGv_i32 tmp3 = neon_load_reg(rd, pass); if (size) { /* VFMS */ gen_helper_vfp_negs(tmp, tmp); } gen_helper_vfp_muladds(tmp, tmp, tmp2, tmp3, fpstatus); tcg_temp_free_i32(tmp3); tcg_temp_free_ptr(fpstatus); break; } default: abort(); } tcg_temp_free_i32(tmp2); /* Save the result. For elementwise operations we can put it straight into the destination register. For pairwise operations we have to be careful to avoid clobbering the source operands. */ if (pairwise && rd == rm) { neon_store_scratch(pass, tmp); } else { neon_store_reg(rd, pass, tmp); } } /* for pass */ if (pairwise && rd == rm) { for (pass = 0; pass < (q ? 4 : 2); pass++) { tmp = neon_load_scratch(pass); neon_store_reg(rd, pass, tmp); } } /* End of 3 register same size operations. */ } else if (insn & (1 << 4)) { if ((insn & 0x00380080) != 0) { /* Two registers and shift. */ op = (insn >> 8) & 0xf; if (insn & (1 << 7)) { /* 64-bit shift. */ if (op > 7) { return 1; } size = 3; } else { size = 2; while ((insn & (1 << (size + 19))) == 0) size--; } shift = (insn >> 16) & ((1 << (3 + size)) - 1); /* To avoid excessive duplication of ops we implement shift by immediate using the variable shift operations. */ if (op < 8) { /* Shift by immediate: VSHR, VSRA, VRSHR, VRSRA, VSRI, VSHL, VQSHL, VQSHLU. */ if (q && ((rd | rm) & 1)) { return 1; } if (!u && (op == 4 || op == 6)) { return 1; } /* Right shifts are encoded as N - shift, where N is the element size in bits. */ if (op <= 4) shift = shift - (1 << (size + 3)); if (size == 3) { count = q + 1; } else { count = q ? 4: 2; } switch (size) { case 0: imm = (uint8_t) shift; imm |= imm << 8; imm |= imm << 16; break; case 1: imm = (uint16_t) shift; imm |= imm << 16; break; case 2: case 3: imm = shift; break; default: abort(); } for (pass = 0; pass < count; pass++) { if (size == 3) { neon_load_reg64(cpu_V0, rm + pass); tcg_gen_movi_i64(cpu_V1, imm); switch (op) { case 0: /* VSHR */ case 1: /* VSRA */ if (u) gen_helper_neon_shl_u64(cpu_V0, cpu_V0, cpu_V1); else gen_helper_neon_shl_s64(cpu_V0, cpu_V0, cpu_V1); break; case 2: /* VRSHR */ case 3: /* VRSRA */ if (u) gen_helper_neon_rshl_u64(cpu_V0, cpu_V0, cpu_V1); else gen_helper_neon_rshl_s64(cpu_V0, cpu_V0, cpu_V1); break; case 4: /* VSRI */ case 5: /* VSHL, VSLI */ gen_helper_neon_shl_u64(cpu_V0, cpu_V0, cpu_V1); break; case 6: /* VQSHLU */ gen_helper_neon_qshlu_s64(cpu_V0, cpu_env, cpu_V0, cpu_V1); break; case 7: /* VQSHL */ if (u) { gen_helper_neon_qshl_u64(cpu_V0, cpu_env, cpu_V0, cpu_V1); } else { gen_helper_neon_qshl_s64(cpu_V0, cpu_env, cpu_V0, cpu_V1); } break; } if (op == 1 || op == 3) { /* Accumulate. */ neon_load_reg64(cpu_V1, rd + pass); tcg_gen_add_i64(cpu_V0, cpu_V0, cpu_V1); } else if (op == 4 || (op == 5 && u)) { /* Insert */ neon_load_reg64(cpu_V1, rd + pass); uint64_t mask; if (shift < -63 || shift > 63) { mask = 0; } else { if (op == 4) { mask = 0xffffffffffffffffull >> -shift; } else { mask = 0xffffffffffffffffull << shift; } } tcg_gen_andi_i64(cpu_V1, cpu_V1, ~mask); tcg_gen_or_i64(cpu_V0, cpu_V0, cpu_V1); } neon_store_reg64(cpu_V0, rd + pass); } else { /* size < 3 */ /* Operands in T0 and T1. */ tmp = neon_load_reg(rm, pass); tmp2 = tcg_temp_new_i32(); tcg_gen_movi_i32(tmp2, imm); switch (op) { case 0: /* VSHR */ case 1: /* VSRA */ GEN_NEON_INTEGER_OP(shl); break; case 2: /* VRSHR */ case 3: /* VRSRA */ GEN_NEON_INTEGER_OP(rshl); break; case 4: /* VSRI */ case 5: /* VSHL, VSLI */ switch (size) { case 0: gen_helper_neon_shl_u8(tmp, tmp, tmp2); break; case 1: gen_helper_neon_shl_u16(tmp, tmp, tmp2); break; case 2: gen_helper_neon_shl_u32(tmp, tmp, tmp2); break; default: abort(); } break; case 6: /* VQSHLU */ switch (size) { case 0: gen_helper_neon_qshlu_s8(tmp, cpu_env, tmp, tmp2); break; case 1: gen_helper_neon_qshlu_s16(tmp, cpu_env, tmp, tmp2); break; case 2: gen_helper_neon_qshlu_s32(tmp, cpu_env, tmp, tmp2); break; default: abort(); } break; case 7: /* VQSHL */ GEN_NEON_INTEGER_OP_ENV(qshl); break; } tcg_temp_free_i32(tmp2); if (op == 1 || op == 3) { /* Accumulate. */ tmp2 = neon_load_reg(rd, pass); gen_neon_add(size, tmp, tmp2); tcg_temp_free_i32(tmp2); } else if (op == 4 || (op == 5 && u)) { /* Insert */ switch (size) { case 0: if (op == 4) mask = 0xff >> -shift; else mask = (uint8_t)(0xff << shift); mask |= mask << 8; mask |= mask << 16; break; case 1: if (op == 4) mask = 0xffff >> -shift; else mask = (uint16_t)(0xffff << shift); mask |= mask << 16; break; case 2: if (shift < -31 || shift > 31) { mask = 0; } else { if (op == 4) mask = 0xffffffffu >> -shift; else mask = 0xffffffffu << shift; } break; default: abort(); } tmp2 = neon_load_reg(rd, pass); tcg_gen_andi_i32(tmp, tmp, mask); tcg_gen_andi_i32(tmp2, tmp2, ~mask); tcg_gen_or_i32(tmp, tmp, tmp2); tcg_temp_free_i32(tmp2); } neon_store_reg(rd, pass, tmp); } } /* for pass */ } else if (op < 10) { /* Shift by immediate and narrow: VSHRN, VRSHRN, VQSHRN, VQRSHRN. */ int input_unsigned = (op == 8) ? !u : u; if (rm & 1) { return 1; } shift = shift - (1 << (size + 3)); size++; if (size == 3) { tmp64 = tcg_const_i64(shift); neon_load_reg64(cpu_V0, rm); neon_load_reg64(cpu_V1, rm + 1); for (pass = 0; pass < 2; pass++) { TCGv_i64 in; if (pass == 0) { in = cpu_V0; } else { in = cpu_V1; } if (q) { if (input_unsigned) { gen_helper_neon_rshl_u64(cpu_V0, in, tmp64); } else { gen_helper_neon_rshl_s64(cpu_V0, in, tmp64); } } else { if (input_unsigned) { gen_helper_neon_shl_u64(cpu_V0, in, tmp64); } else { gen_helper_neon_shl_s64(cpu_V0, in, tmp64); } } tmp = tcg_temp_new_i32(); gen_neon_narrow_op(op == 8, u, size - 1, tmp, cpu_V0); neon_store_reg(rd, pass, tmp); } /* for pass */ tcg_temp_free_i64(tmp64); } else { if (size == 1) { imm = (uint16_t)shift; imm |= imm << 16; } else { /* size == 2 */ imm = (uint32_t)shift; } tmp2 = tcg_const_i32(imm); tmp4 = neon_load_reg(rm + 1, 0); tmp5 = neon_load_reg(rm + 1, 1); for (pass = 0; pass < 2; pass++) { if (pass == 0) { tmp = neon_load_reg(rm, 0); } else { tmp = tmp4; } gen_neon_shift_narrow(size, tmp, tmp2, q, input_unsigned); if (pass == 0) { tmp3 = neon_load_reg(rm, 1); } else { tmp3 = tmp5; } gen_neon_shift_narrow(size, tmp3, tmp2, q, input_unsigned); tcg_gen_concat_i32_i64(cpu_V0, tmp, tmp3); tcg_temp_free_i32(tmp); tcg_temp_free_i32(tmp3); tmp = tcg_temp_new_i32(); gen_neon_narrow_op(op == 8, u, size - 1, tmp, cpu_V0); neon_store_reg(rd, pass, tmp); } /* for pass */ tcg_temp_free_i32(tmp2); } } else if (op == 10) { /* VSHLL, VMOVL */ if (q || (rd & 1)) { return 1; } tmp = neon_load_reg(rm, 0); tmp2 = neon_load_reg(rm, 1); for (pass = 0; pass < 2; pass++) { if (pass == 1) tmp = tmp2; gen_neon_widen(cpu_V0, tmp, size, u); if (shift != 0) { /* The shift is less than the width of the source type, so we can just shift the whole register. */ tcg_gen_shli_i64(cpu_V0, cpu_V0, shift); /* Widen the result of shift: we need to clear * the potential overflow bits resulting from * left bits of the narrow input appearing as * right bits of left the neighbour narrow * input. */ if (size < 2 || !u) { uint64_t imm64; if (size == 0) { imm = (0xffu >> (8 - shift)); imm |= imm << 16; } else if (size == 1) { imm = 0xffff >> (16 - shift); } else { /* size == 2 */ imm = 0xffffffff >> (32 - shift); } if (size < 2) { imm64 = imm | (((uint64_t)imm) << 32); } else { imm64 = imm; } tcg_gen_andi_i64(cpu_V0, cpu_V0, ~imm64); } } neon_store_reg64(cpu_V0, rd + pass); } } else if (op >= 14) { /* VCVT fixed-point. */ if (!(insn & (1 << 21)) || (q && ((rd | rm) & 1))) { return 1; } /* We have already masked out the must-be-1 top bit of imm6, * hence this 32-shift where the ARM ARM has 64-imm6. */ shift = 32 - shift; for (pass = 0; pass < (q ? 4 : 2); pass++) { tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, pass)); if (!(op & 1)) { if (u) gen_vfp_ulto(0, shift, 1); else gen_vfp_slto(0, shift, 1); } else { if (u) gen_vfp_toul(0, shift, 1); else gen_vfp_tosl(0, shift, 1); } tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, pass)); } } else { return 1; } } else { /* (insn & 0x00380080) == 0 */ int invert; if (q && (rd & 1)) { return 1; } op = (insn >> 8) & 0xf; /* One register and immediate. */ imm = (u << 7) | ((insn >> 12) & 0x70) | (insn & 0xf); invert = (insn & (1 << 5)) != 0; /* Note that op = 2,3,4,5,6,7,10,11,12,13 imm=0 is UNPREDICTABLE. * We choose to not special-case this and will behave as if a * valid constant encoding of 0 had been given. */ switch (op) { case 0: case 1: /* no-op */ break; case 2: case 3: imm <<= 8; break; case 4: case 5: imm <<= 16; break; case 6: case 7: imm <<= 24; break; case 8: case 9: imm |= imm << 16; break; case 10: case 11: imm = (imm << 8) | (imm << 24); break; case 12: imm = (imm << 8) | 0xff; break; case 13: imm = (imm << 16) | 0xffff; break; case 14: imm |= (imm << 8) | (imm << 16) | (imm << 24); if (invert) imm = ~imm; break; case 15: if (invert) { return 1; } imm = ((imm & 0x80) << 24) | ((imm & 0x3f) << 19) | ((imm & 0x40) ? (0x1f << 25) : (1 << 30)); break; } if (invert) imm = ~imm; for (pass = 0; pass < (q ? 4 : 2); pass++) { if (op & 1 && op < 12) { tmp = neon_load_reg(rd, pass); if (invert) { /* The immediate value has already been inverted, so BIC becomes AND. */ tcg_gen_andi_i32(tmp, tmp, imm); } else { tcg_gen_ori_i32(tmp, tmp, imm); } } else { /* VMOV, VMVN. */ tmp = tcg_temp_new_i32(); if (op == 14 && invert) { int n; uint32_t val; val = 0; for (n = 0; n < 4; n++) { if (imm & (1 << (n + (pass & 1) * 4))) val |= 0xff << (n * 8); } tcg_gen_movi_i32(tmp, val); } else { tcg_gen_movi_i32(tmp, imm); } } neon_store_reg(rd, pass, tmp); } } } else { /* (insn & 0x00800010 == 0x00800000) */ if (size != 3) { op = (insn >> 8) & 0xf; if ((insn & (1 << 6)) == 0) { /* Three registers of different lengths. */ int src1_wide; int src2_wide; int prewiden; /* undefreq: bit 0 : UNDEF if size == 0 * bit 1 : UNDEF if size == 1 * bit 2 : UNDEF if size == 2 * bit 3 : UNDEF if U == 1 * Note that [2:0] set implies 'always UNDEF' */ int undefreq; /* prewiden, src1_wide, src2_wide, undefreq */ static const int neon_3reg_wide[16][4] = { {1, 0, 0, 0}, /* VADDL */ {1, 1, 0, 0}, /* VADDW */ {1, 0, 0, 0}, /* VSUBL */ {1, 1, 0, 0}, /* VSUBW */ {0, 1, 1, 0}, /* VADDHN */ {0, 0, 0, 0}, /* VABAL */ {0, 1, 1, 0}, /* VSUBHN */ {0, 0, 0, 0}, /* VABDL */ {0, 0, 0, 0}, /* VMLAL */ {0, 0, 0, 9}, /* VQDMLAL */ {0, 0, 0, 0}, /* VMLSL */ {0, 0, 0, 9}, /* VQDMLSL */ {0, 0, 0, 0}, /* Integer VMULL */ {0, 0, 0, 1}, /* VQDMULL */ {0, 0, 0, 0xa}, /* Polynomial VMULL */ {0, 0, 0, 7}, /* Reserved: always UNDEF */ }; prewiden = neon_3reg_wide[op][0]; src1_wide = neon_3reg_wide[op][1]; src2_wide = neon_3reg_wide[op][2]; undefreq = neon_3reg_wide[op][3]; if ((undefreq & (1 << size)) || ((undefreq & 8) && u)) { return 1; } if ((src1_wide && (rn & 1)) || (src2_wide && (rm & 1)) || (!src2_wide && (rd & 1))) { return 1; } /* Handle VMULL.P64 (Polynomial 64x64 to 128 bit multiply) * outside the loop below as it only performs a single pass. */ if (op == 14 && size == 2) { TCGv_i64 tcg_rn, tcg_rm, tcg_rd; if (!arm_dc_feature(s, ARM_FEATURE_V8_PMULL)) { return 1; } tcg_rn = tcg_temp_new_i64(); tcg_rm = tcg_temp_new_i64(); tcg_rd = tcg_temp_new_i64(); neon_load_reg64(tcg_rn, rn); neon_load_reg64(tcg_rm, rm); gen_helper_neon_pmull_64_lo(tcg_rd, tcg_rn, tcg_rm); neon_store_reg64(tcg_rd, rd); gen_helper_neon_pmull_64_hi(tcg_rd, tcg_rn, tcg_rm); neon_store_reg64(tcg_rd, rd + 1); tcg_temp_free_i64(tcg_rn); tcg_temp_free_i64(tcg_rm); tcg_temp_free_i64(tcg_rd); return 0; } /* Avoid overlapping operands. Wide source operands are always aligned so will never overlap with wide destinations in problematic ways. */ if (rd == rm && !src2_wide) { tmp = neon_load_reg(rm, 1); neon_store_scratch(2, tmp); } else if (rd == rn && !src1_wide) { tmp = neon_load_reg(rn, 1); neon_store_scratch(2, tmp); } TCGV_UNUSED_I32(tmp3); for (pass = 0; pass < 2; pass++) { if (src1_wide) { neon_load_reg64(cpu_V0, rn + pass); TCGV_UNUSED_I32(tmp); } else { if (pass == 1 && rd == rn) { tmp = neon_load_scratch(2); } else { tmp = neon_load_reg(rn, pass); } if (prewiden) { gen_neon_widen(cpu_V0, tmp, size, u); } } if (src2_wide) { neon_load_reg64(cpu_V1, rm + pass); TCGV_UNUSED_I32(tmp2); } else { if (pass == 1 && rd == rm) { tmp2 = neon_load_scratch(2); } else { tmp2 = neon_load_reg(rm, pass); } if (prewiden) { gen_neon_widen(cpu_V1, tmp2, size, u); } } switch (op) { case 0: case 1: case 4: /* VADDL, VADDW, VADDHN, VRADDHN */ gen_neon_addl(size); break; case 2: case 3: case 6: /* VSUBL, VSUBW, VSUBHN, VRSUBHN */ gen_neon_subl(size); break; case 5: case 7: /* VABAL, VABDL */ switch ((size << 1) | u) { case 0: gen_helper_neon_abdl_s16(cpu_V0, tmp, tmp2); break; case 1: gen_helper_neon_abdl_u16(cpu_V0, tmp, tmp2); break; case 2: gen_helper_neon_abdl_s32(cpu_V0, tmp, tmp2); break; case 3: gen_helper_neon_abdl_u32(cpu_V0, tmp, tmp2); break; case 4: gen_helper_neon_abdl_s64(cpu_V0, tmp, tmp2); break; case 5: gen_helper_neon_abdl_u64(cpu_V0, tmp, tmp2); break; default: abort(); } tcg_temp_free_i32(tmp2); tcg_temp_free_i32(tmp); break; case 8: case 9: case 10: case 11: case 12: case 13: /* VMLAL, VQDMLAL, VMLSL, VQDMLSL, VMULL, VQDMULL */ gen_neon_mull(cpu_V0, tmp, tmp2, size, u); break; case 14: /* Polynomial VMULL */ gen_helper_neon_mull_p8(cpu_V0, tmp, tmp2); tcg_temp_free_i32(tmp2); tcg_temp_free_i32(tmp); break; default: /* 15 is RESERVED: caught earlier */ abort(); } if (op == 13) { /* VQDMULL */ gen_neon_addl_saturate(cpu_V0, cpu_V0, size); neon_store_reg64(cpu_V0, rd + pass); } else if (op == 5 || (op >= 8 && op <= 11)) { /* Accumulate. */ neon_load_reg64(cpu_V1, rd + pass); switch (op) { case 10: /* VMLSL */ gen_neon_negl(cpu_V0, size); /* Fall through */ case 5: case 8: /* VABAL, VMLAL */ gen_neon_addl(size); break; case 9: case 11: /* VQDMLAL, VQDMLSL */ gen_neon_addl_saturate(cpu_V0, cpu_V0, size); if (op == 11) { gen_neon_negl(cpu_V0, size); } gen_neon_addl_saturate(cpu_V0, cpu_V1, size); break; default: abort(); } neon_store_reg64(cpu_V0, rd + pass); } else if (op == 4 || op == 6) { /* Narrowing operation. */ tmp = tcg_temp_new_i32(); if (!u) { switch (size) { case 0: gen_helper_neon_narrow_high_u8(tmp, cpu_V0); break; case 1: gen_helper_neon_narrow_high_u16(tmp, cpu_V0); break; case 2: tcg_gen_shri_i64(cpu_V0, cpu_V0, 32); tcg_gen_trunc_i64_i32(tmp, cpu_V0); break; default: abort(); } } else { switch (size) { case 0: gen_helper_neon_narrow_round_high_u8(tmp, cpu_V0); break; case 1: gen_helper_neon_narrow_round_high_u16(tmp, cpu_V0); break; case 2: tcg_gen_addi_i64(cpu_V0, cpu_V0, 1u << 31); tcg_gen_shri_i64(cpu_V0, cpu_V0, 32); tcg_gen_trunc_i64_i32(tmp, cpu_V0); break; default: abort(); } } if (pass == 0) { tmp3 = tmp; } else { neon_store_reg(rd, 0, tmp3); neon_store_reg(rd, 1, tmp); } } else { /* Write back the result. */ neon_store_reg64(cpu_V0, rd + pass); } } } else { /* Two registers and a scalar. NB that for ops of this form * the ARM ARM labels bit 24 as Q, but it is in our variable * 'u', not 'q'. */ if (size == 0) { return 1; } switch (op) { case 1: /* Float VMLA scalar */ case 5: /* Floating point VMLS scalar */ case 9: /* Floating point VMUL scalar */ if (size == 1) { return 1; } /* fall through */ case 0: /* Integer VMLA scalar */ case 4: /* Integer VMLS scalar */ case 8: /* Integer VMUL scalar */ case 12: /* VQDMULH scalar */ case 13: /* VQRDMULH scalar */ if (u && ((rd | rn) & 1)) { return 1; } tmp = neon_get_scalar(size, rm); neon_store_scratch(0, tmp); for (pass = 0; pass < (u ? 4 : 2); pass++) { tmp = neon_load_scratch(0); tmp2 = neon_load_reg(rn, pass); if (op == 12) { if (size == 1) { gen_helper_neon_qdmulh_s16(tmp, cpu_env, tmp, tmp2); } else { gen_helper_neon_qdmulh_s32(tmp, cpu_env, tmp, tmp2); } } else if (op == 13) { if (size == 1) { gen_helper_neon_qrdmulh_s16(tmp, cpu_env, tmp, tmp2); } else { gen_helper_neon_qrdmulh_s32(tmp, cpu_env, tmp, tmp2); } } else if (op & 1) { TCGv_ptr fpstatus = get_fpstatus_ptr(1); gen_helper_vfp_muls(tmp, tmp, tmp2, fpstatus); tcg_temp_free_ptr(fpstatus); } else { switch (size) { case 0: gen_helper_neon_mul_u8(tmp, tmp, tmp2); break; case 1: gen_helper_neon_mul_u16(tmp, tmp, tmp2); break; case 2: tcg_gen_mul_i32(tmp, tmp, tmp2); break; default: abort(); } } tcg_temp_free_i32(tmp2); if (op < 8) { /* Accumulate. */ tmp2 = neon_load_reg(rd, pass); switch (op) { case 0: gen_neon_add(size, tmp, tmp2); break; case 1: { TCGv_ptr fpstatus = get_fpstatus_ptr(1); gen_helper_vfp_adds(tmp, tmp, tmp2, fpstatus); tcg_temp_free_ptr(fpstatus); break; } case 4: gen_neon_rsb(size, tmp, tmp2); break; case 5: { TCGv_ptr fpstatus = get_fpstatus_ptr(1); gen_helper_vfp_subs(tmp, tmp2, tmp, fpstatus); tcg_temp_free_ptr(fpstatus); break; } default: abort(); } tcg_temp_free_i32(tmp2); } neon_store_reg(rd, pass, tmp); } break; case 3: /* VQDMLAL scalar */ case 7: /* VQDMLSL scalar */ case 11: /* VQDMULL scalar */ if (u == 1) { return 1; } /* fall through */ case 2: /* VMLAL sclar */ case 6: /* VMLSL scalar */ case 10: /* VMULL scalar */ if (rd & 1) { return 1; } tmp2 = neon_get_scalar(size, rm); /* We need a copy of tmp2 because gen_neon_mull * deletes it during pass 0. */ tmp4 = tcg_temp_new_i32(); tcg_gen_mov_i32(tmp4, tmp2); tmp3 = neon_load_reg(rn, 1); for (pass = 0; pass < 2; pass++) { if (pass == 0) { tmp = neon_load_reg(rn, 0); } else { tmp = tmp3; tmp2 = tmp4; } gen_neon_mull(cpu_V0, tmp, tmp2, size, u); if (op != 11) { neon_load_reg64(cpu_V1, rd + pass); } switch (op) { case 6: gen_neon_negl(cpu_V0, size); /* Fall through */ case 2: gen_neon_addl(size); break; case 3: case 7: gen_neon_addl_saturate(cpu_V0, cpu_V0, size); if (op == 7) { gen_neon_negl(cpu_V0, size); } gen_neon_addl_saturate(cpu_V0, cpu_V1, size); break; case 10: /* no-op */ break; case 11: gen_neon_addl_saturate(cpu_V0, cpu_V0, size); break; default: abort(); } neon_store_reg64(cpu_V0, rd + pass); } break; default: /* 14 and 15 are RESERVED */ return 1; } } } else { /* size == 3 */ if (!u) { /* Extract. */ imm = (insn >> 8) & 0xf; if (imm > 7 && !q) return 1; if (q && ((rd | rn | rm) & 1)) { return 1; } if (imm == 0) { neon_load_reg64(cpu_V0, rn); if (q) { neon_load_reg64(cpu_V1, rn + 1); } } else if (imm == 8) { neon_load_reg64(cpu_V0, rn + 1); if (q) { neon_load_reg64(cpu_V1, rm); } } else if (q) { tmp64 = tcg_temp_new_i64(); if (imm < 8) { neon_load_reg64(cpu_V0, rn); neon_load_reg64(tmp64, rn + 1); } else { neon_load_reg64(cpu_V0, rn + 1); neon_load_reg64(tmp64, rm); } tcg_gen_shri_i64(cpu_V0, cpu_V0, (imm & 7) * 8); tcg_gen_shli_i64(cpu_V1, tmp64, 64 - ((imm & 7) * 8)); tcg_gen_or_i64(cpu_V0, cpu_V0, cpu_V1); if (imm < 8) { neon_load_reg64(cpu_V1, rm); } else { neon_load_reg64(cpu_V1, rm + 1); imm -= 8; } tcg_gen_shli_i64(cpu_V1, cpu_V1, 64 - (imm * 8)); tcg_gen_shri_i64(tmp64, tmp64, imm * 8); tcg_gen_or_i64(cpu_V1, cpu_V1, tmp64); tcg_temp_free_i64(tmp64); } else { /* BUGFIX */ neon_load_reg64(cpu_V0, rn); tcg_gen_shri_i64(cpu_V0, cpu_V0, imm * 8); neon_load_reg64(cpu_V1, rm); tcg_gen_shli_i64(cpu_V1, cpu_V1, 64 - (imm * 8)); tcg_gen_or_i64(cpu_V0, cpu_V0, cpu_V1); } neon_store_reg64(cpu_V0, rd); if (q) { neon_store_reg64(cpu_V1, rd + 1); } } else if ((insn & (1 << 11)) == 0) { /* Two register misc. */ op = ((insn >> 12) & 0x30) | ((insn >> 7) & 0xf); size = (insn >> 18) & 3; /* UNDEF for unknown op values and bad op-size combinations */ if ((neon_2rm_sizes[op] & (1 << size)) == 0) { return 1; } if ((op != NEON_2RM_VMOVN && op != NEON_2RM_VQMOVN) && q && ((rm | rd) & 1)) { return 1; } switch (op) { case NEON_2RM_VREV64: for (pass = 0; pass < (q ? 2 : 1); pass++) { tmp = neon_load_reg(rm, pass * 2); tmp2 = neon_load_reg(rm, pass * 2 + 1); switch (size) { case 0: tcg_gen_bswap32_i32(tmp, tmp); break; case 1: gen_swap_half(tmp); break; case 2: /* no-op */ break; default: abort(); } neon_store_reg(rd, pass * 2 + 1, tmp); if (size == 2) { neon_store_reg(rd, pass * 2, tmp2); } else { switch (size) { case 0: tcg_gen_bswap32_i32(tmp2, tmp2); break; case 1: gen_swap_half(tmp2); break; default: abort(); } neon_store_reg(rd, pass * 2, tmp2); } } break; case NEON_2RM_VPADDL: case NEON_2RM_VPADDL_U: case NEON_2RM_VPADAL: case NEON_2RM_VPADAL_U: for (pass = 0; pass < q + 1; pass++) { tmp = neon_load_reg(rm, pass * 2); gen_neon_widen(cpu_V0, tmp, size, op & 1); tmp = neon_load_reg(rm, pass * 2 + 1); gen_neon_widen(cpu_V1, tmp, size, op & 1); switch (size) { case 0: gen_helper_neon_paddl_u16(CPU_V001); break; case 1: gen_helper_neon_paddl_u32(CPU_V001); break; case 2: tcg_gen_add_i64(CPU_V001); break; default: abort(); } if (op >= NEON_2RM_VPADAL) { /* Accumulate. */ neon_load_reg64(cpu_V1, rd + pass); gen_neon_addl(size); } neon_store_reg64(cpu_V0, rd + pass); } break; case NEON_2RM_VTRN: if (size == 2) { int n; for (n = 0; n < (q ? 4 : 2); n += 2) { tmp = neon_load_reg(rm, n); tmp2 = neon_load_reg(rd, n + 1); neon_store_reg(rm, n, tmp2); neon_store_reg(rd, n + 1, tmp); } } else { goto elementwise; } break; case NEON_2RM_VUZP: if (gen_neon_unzip(rd, rm, size, q)) { return 1; } break; case NEON_2RM_VZIP: if (gen_neon_zip(rd, rm, size, q)) { return 1; } break; case NEON_2RM_VMOVN: case NEON_2RM_VQMOVN: /* also VQMOVUN; op field and mnemonics don't line up */ if (rm & 1) { return 1; } TCGV_UNUSED_I32(tmp2); for (pass = 0; pass < 2; pass++) { neon_load_reg64(cpu_V0, rm + pass); tmp = tcg_temp_new_i32(); gen_neon_narrow_op(op == NEON_2RM_VMOVN, q, size, tmp, cpu_V0); if (pass == 0) { tmp2 = tmp; } else { neon_store_reg(rd, 0, tmp2); neon_store_reg(rd, 1, tmp); } } break; case NEON_2RM_VSHLL: if (q || (rd & 1)) { return 1; } tmp = neon_load_reg(rm, 0); tmp2 = neon_load_reg(rm, 1); for (pass = 0; pass < 2; pass++) { if (pass == 1) tmp = tmp2; gen_neon_widen(cpu_V0, tmp, size, 1); tcg_gen_shli_i64(cpu_V0, cpu_V0, 8 << size); neon_store_reg64(cpu_V0, rd + pass); } break; case NEON_2RM_VCVT_F16_F32: if (!arm_dc_feature(s, ARM_FEATURE_VFP_FP16) || q || (rm & 1)) { return 1; } tmp = tcg_temp_new_i32(); tmp2 = tcg_temp_new_i32(); tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 0)); gen_helper_neon_fcvt_f32_to_f16(tmp, cpu_F0s, cpu_env); tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 1)); gen_helper_neon_fcvt_f32_to_f16(tmp2, cpu_F0s, cpu_env); tcg_gen_shli_i32(tmp2, tmp2, 16); tcg_gen_or_i32(tmp2, tmp2, tmp); tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 2)); gen_helper_neon_fcvt_f32_to_f16(tmp, cpu_F0s, cpu_env); tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 3)); neon_store_reg(rd, 0, tmp2); tmp2 = tcg_temp_new_i32(); gen_helper_neon_fcvt_f32_to_f16(tmp2, cpu_F0s, cpu_env); tcg_gen_shli_i32(tmp2, tmp2, 16); tcg_gen_or_i32(tmp2, tmp2, tmp); neon_store_reg(rd, 1, tmp2); tcg_temp_free_i32(tmp); break; case NEON_2RM_VCVT_F32_F16: if (!arm_dc_feature(s, ARM_FEATURE_VFP_FP16) || q || (rd & 1)) { return 1; } tmp3 = tcg_temp_new_i32(); tmp = neon_load_reg(rm, 0); tmp2 = neon_load_reg(rm, 1); tcg_gen_ext16u_i32(tmp3, tmp); gen_helper_neon_fcvt_f16_to_f32(cpu_F0s, tmp3, cpu_env); tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 0)); tcg_gen_shri_i32(tmp3, tmp, 16); gen_helper_neon_fcvt_f16_to_f32(cpu_F0s, tmp3, cpu_env); tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 1)); tcg_temp_free_i32(tmp); tcg_gen_ext16u_i32(tmp3, tmp2); gen_helper_neon_fcvt_f16_to_f32(cpu_F0s, tmp3, cpu_env); tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 2)); tcg_gen_shri_i32(tmp3, tmp2, 16); gen_helper_neon_fcvt_f16_to_f32(cpu_F0s, tmp3, cpu_env); tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 3)); tcg_temp_free_i32(tmp2); tcg_temp_free_i32(tmp3); break; case NEON_2RM_AESE: case NEON_2RM_AESMC: if (!arm_dc_feature(s, ARM_FEATURE_V8_AES) || ((rm | rd) & 1)) { return 1; } tmp = tcg_const_i32(rd); tmp2 = tcg_const_i32(rm); /* Bit 6 is the lowest opcode bit; it distinguishes between * encryption (AESE/AESMC) and decryption (AESD/AESIMC) */ tmp3 = tcg_const_i32(extract32(insn, 6, 1)); if (op == NEON_2RM_AESE) { gen_helper_crypto_aese(cpu_env, tmp, tmp2, tmp3); } else { gen_helper_crypto_aesmc(cpu_env, tmp, tmp2, tmp3); } tcg_temp_free_i32(tmp); tcg_temp_free_i32(tmp2); tcg_temp_free_i32(tmp3); break; case NEON_2RM_SHA1H: if (!arm_dc_feature(s, ARM_FEATURE_V8_SHA1) || ((rm | rd) & 1)) { return 1; } tmp = tcg_const_i32(rd); tmp2 = tcg_const_i32(rm); gen_helper_crypto_sha1h(cpu_env, tmp, tmp2); tcg_temp_free_i32(tmp); tcg_temp_free_i32(tmp2); break; case NEON_2RM_SHA1SU1: if ((rm | rd) & 1) { return 1; } /* bit 6 (q): set -> SHA256SU0, cleared -> SHA1SU1 */ if (q) { if (!arm_dc_feature(s, ARM_FEATURE_V8_SHA256)) { return 1; } } else if (!arm_dc_feature(s, ARM_FEATURE_V8_SHA1)) { return 1; } tmp = tcg_const_i32(rd); tmp2 = tcg_const_i32(rm); if (q) { gen_helper_crypto_sha256su0(cpu_env, tmp, tmp2); } else { gen_helper_crypto_sha1su1(cpu_env, tmp, tmp2); } tcg_temp_free_i32(tmp); tcg_temp_free_i32(tmp2); break; default: elementwise: for (pass = 0; pass < (q ? 4 : 2); pass++) { if (neon_2rm_is_float_op(op)) { tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, pass)); TCGV_UNUSED_I32(tmp); } else { tmp = neon_load_reg(rm, pass); } switch (op) { case NEON_2RM_VREV32: switch (size) { case 0: tcg_gen_bswap32_i32(tmp, tmp); break; case 1: gen_swap_half(tmp); break; default: abort(); } break; case NEON_2RM_VREV16: gen_rev16(tmp); break; case NEON_2RM_VCLS: switch (size) { case 0: gen_helper_neon_cls_s8(tmp, tmp); break; case 1: gen_helper_neon_cls_s16(tmp, tmp); break; case 2: gen_helper_neon_cls_s32(tmp, tmp); break; default: abort(); } break; case NEON_2RM_VCLZ: switch (size) { case 0: gen_helper_neon_clz_u8(tmp, tmp); break; case 1: gen_helper_neon_clz_u16(tmp, tmp); break; case 2: gen_helper_clz(tmp, tmp); break; default: abort(); } break; case NEON_2RM_VCNT: gen_helper_neon_cnt_u8(tmp, tmp); break; case NEON_2RM_VMVN: tcg_gen_not_i32(tmp, tmp); break; case NEON_2RM_VQABS: switch (size) { case 0: gen_helper_neon_qabs_s8(tmp, cpu_env, tmp); break; case 1: gen_helper_neon_qabs_s16(tmp, cpu_env, tmp); break; case 2: gen_helper_neon_qabs_s32(tmp, cpu_env, tmp); break; default: abort(); } break; case NEON_2RM_VQNEG: switch (size) { case 0: gen_helper_neon_qneg_s8(tmp, cpu_env, tmp); break; case 1: gen_helper_neon_qneg_s16(tmp, cpu_env, tmp); break; case 2: gen_helper_neon_qneg_s32(tmp, cpu_env, tmp); break; default: abort(); } break; case NEON_2RM_VCGT0: case NEON_2RM_VCLE0: tmp2 = tcg_const_i32(0); switch(size) { case 0: gen_helper_neon_cgt_s8(tmp, tmp, tmp2); break; case 1: gen_helper_neon_cgt_s16(tmp, tmp, tmp2); break; case 2: gen_helper_neon_cgt_s32(tmp, tmp, tmp2); break; default: abort(); } tcg_temp_free_i32(tmp2); if (op == NEON_2RM_VCLE0) { tcg_gen_not_i32(tmp, tmp); } break; case NEON_2RM_VCGE0: case NEON_2RM_VCLT0: tmp2 = tcg_const_i32(0); switch(size) { case 0: gen_helper_neon_cge_s8(tmp, tmp, tmp2); break; case 1: gen_helper_neon_cge_s16(tmp, tmp, tmp2); break; case 2: gen_helper_neon_cge_s32(tmp, tmp, tmp2); break; default: abort(); } tcg_temp_free_i32(tmp2); if (op == NEON_2RM_VCLT0) { tcg_gen_not_i32(tmp, tmp); } break; case NEON_2RM_VCEQ0: tmp2 = tcg_const_i32(0); switch(size) { case 0: gen_helper_neon_ceq_u8(tmp, tmp, tmp2); break; case 1: gen_helper_neon_ceq_u16(tmp, tmp, tmp2); break; case 2: gen_helper_neon_ceq_u32(tmp, tmp, tmp2); break; default: abort(); } tcg_temp_free_i32(tmp2); break; case NEON_2RM_VABS: switch(size) { case 0: gen_helper_neon_abs_s8(tmp, tmp); break; case 1: gen_helper_neon_abs_s16(tmp, tmp); break; case 2: tcg_gen_abs_i32(tmp, tmp); break; default: abort(); } break; case NEON_2RM_VNEG: tmp2 = tcg_const_i32(0); gen_neon_rsb(size, tmp, tmp2); tcg_temp_free_i32(tmp2); break; case NEON_2RM_VCGT0_F: { TCGv_ptr fpstatus = get_fpstatus_ptr(1); tmp2 = tcg_const_i32(0); gen_helper_neon_cgt_f32(tmp, tmp, tmp2, fpstatus); tcg_temp_free_i32(tmp2); tcg_temp_free_ptr(fpstatus); break; } case NEON_2RM_VCGE0_F: { TCGv_ptr fpstatus = get_fpstatus_ptr(1); tmp2 = tcg_const_i32(0); gen_helper_neon_cge_f32(tmp, tmp, tmp2, fpstatus); tcg_temp_free_i32(tmp2); tcg_temp_free_ptr(fpstatus); break; } case NEON_2RM_VCEQ0_F: { TCGv_ptr fpstatus = get_fpstatus_ptr(1); tmp2 = tcg_const_i32(0); gen_helper_neon_ceq_f32(tmp, tmp, tmp2, fpstatus); tcg_temp_free_i32(tmp2); tcg_temp_free_ptr(fpstatus); break; } case NEON_2RM_VCLE0_F: { TCGv_ptr fpstatus = get_fpstatus_ptr(1); tmp2 = tcg_const_i32(0); gen_helper_neon_cge_f32(tmp, tmp2, tmp, fpstatus); tcg_temp_free_i32(tmp2); tcg_temp_free_ptr(fpstatus); break; } case NEON_2RM_VCLT0_F: { TCGv_ptr fpstatus = get_fpstatus_ptr(1); tmp2 = tcg_const_i32(0); gen_helper_neon_cgt_f32(tmp, tmp2, tmp, fpstatus); tcg_temp_free_i32(tmp2); tcg_temp_free_ptr(fpstatus); break; } case NEON_2RM_VABS_F: gen_vfp_abs(0); break; case NEON_2RM_VNEG_F: gen_vfp_neg(0); break; case NEON_2RM_VSWP: tmp2 = neon_load_reg(rd, pass); neon_store_reg(rm, pass, tmp2); break; case NEON_2RM_VTRN: tmp2 = neon_load_reg(rd, pass); switch (size) { case 0: gen_neon_trn_u8(tmp, tmp2); break; case 1: gen_neon_trn_u16(tmp, tmp2); break; default: abort(); } neon_store_reg(rm, pass, tmp2); break; case NEON_2RM_VRINTN: case NEON_2RM_VRINTA: case NEON_2RM_VRINTM: case NEON_2RM_VRINTP: case NEON_2RM_VRINTZ: { TCGv_i32 tcg_rmode; TCGv_ptr fpstatus = get_fpstatus_ptr(1); int rmode; if (op == NEON_2RM_VRINTZ) { rmode = FPROUNDING_ZERO; } else { rmode = fp_decode_rm[((op & 0x6) >> 1) ^ 1]; } tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rmode)); gen_helper_set_neon_rmode(tcg_rmode, tcg_rmode, cpu_env); gen_helper_rints(cpu_F0s, cpu_F0s, fpstatus); gen_helper_set_neon_rmode(tcg_rmode, tcg_rmode, cpu_env); tcg_temp_free_ptr(fpstatus); tcg_temp_free_i32(tcg_rmode); break; } case NEON_2RM_VRINTX: { TCGv_ptr fpstatus = get_fpstatus_ptr(1); gen_helper_rints_exact(cpu_F0s, cpu_F0s, fpstatus); tcg_temp_free_ptr(fpstatus); break; } case NEON_2RM_VCVTAU: case NEON_2RM_VCVTAS: case NEON_2RM_VCVTNU: case NEON_2RM_VCVTNS: case NEON_2RM_VCVTPU: case NEON_2RM_VCVTPS: case NEON_2RM_VCVTMU: case NEON_2RM_VCVTMS: { bool is_signed = !extract32(insn, 7, 1); TCGv_ptr fpst = get_fpstatus_ptr(1); TCGv_i32 tcg_rmode, tcg_shift; int rmode = fp_decode_rm[extract32(insn, 8, 2)]; tcg_shift = tcg_const_i32(0); tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rmode)); gen_helper_set_neon_rmode(tcg_rmode, tcg_rmode, cpu_env); if (is_signed) { gen_helper_vfp_tosls(cpu_F0s, cpu_F0s, tcg_shift, fpst); } else { gen_helper_vfp_touls(cpu_F0s, cpu_F0s, tcg_shift, fpst); } gen_helper_set_neon_rmode(tcg_rmode, tcg_rmode, cpu_env); tcg_temp_free_i32(tcg_rmode); tcg_temp_free_i32(tcg_shift); tcg_temp_free_ptr(fpst); break; } case NEON_2RM_VRECPE: { TCGv_ptr fpstatus = get_fpstatus_ptr(1); gen_helper_recpe_u32(tmp, tmp, fpstatus); tcg_temp_free_ptr(fpstatus); break; } case NEON_2RM_VRSQRTE: { TCGv_ptr fpstatus = get_fpstatus_ptr(1); gen_helper_rsqrte_u32(tmp, tmp, fpstatus); tcg_temp_free_ptr(fpstatus); break; } case NEON_2RM_VRECPE_F: { TCGv_ptr fpstatus = get_fpstatus_ptr(1); gen_helper_recpe_f32(cpu_F0s, cpu_F0s, fpstatus); tcg_temp_free_ptr(fpstatus); break; } case NEON_2RM_VRSQRTE_F: { TCGv_ptr fpstatus = get_fpstatus_ptr(1); gen_helper_rsqrte_f32(cpu_F0s, cpu_F0s, fpstatus); tcg_temp_free_ptr(fpstatus); break; } case NEON_2RM_VCVT_FS: /* VCVT.F32.S32 */ gen_vfp_sito(0, 1); break; case NEON_2RM_VCVT_FU: /* VCVT.F32.U32 */ gen_vfp_uito(0, 1); break; case NEON_2RM_VCVT_SF: /* VCVT.S32.F32 */ gen_vfp_tosiz(0, 1); break; case NEON_2RM_VCVT_UF: /* VCVT.U32.F32 */ gen_vfp_touiz(0, 1); break; default: /* Reserved op values were caught by the * neon_2rm_sizes[] check earlier. */ abort(); } if (neon_2rm_is_float_op(op)) { tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, pass)); } else { neon_store_reg(rd, pass, tmp); } } break; } } else if ((insn & (1 << 10)) == 0) { /* VTBL, VTBX. */ int n = ((insn >> 8) & 3) + 1; if ((rn + n) > 32) { /* This is UNPREDICTABLE; we choose to UNDEF to avoid the * helper function running off the end of the register file. */ return 1; } n <<= 3; if (insn & (1 << 6)) { tmp = neon_load_reg(rd, 0); } else { tmp = tcg_temp_new_i32(); tcg_gen_movi_i32(tmp, 0); } tmp2 = neon_load_reg(rm, 0); tmp4 = tcg_const_i32(rn); tmp5 = tcg_const_i32(n); gen_helper_neon_tbl(tmp2, cpu_env, tmp2, tmp, tmp4, tmp5); tcg_temp_free_i32(tmp); if (insn & (1 << 6)) { tmp = neon_load_reg(rd, 1); } else { tmp = tcg_temp_new_i32(); tcg_gen_movi_i32(tmp, 0); } tmp3 = neon_load_reg(rm, 1); gen_helper_neon_tbl(tmp3, cpu_env, tmp3, tmp, tmp4, tmp5); tcg_temp_free_i32(tmp5); tcg_temp_free_i32(tmp4); neon_store_reg(rd, 0, tmp2); neon_store_reg(rd, 1, tmp3); tcg_temp_free_i32(tmp); } else if ((insn & 0x380) == 0) { /* VDUP */ if ((insn & (7 << 16)) == 0 || (q && (rd & 1))) { return 1; } if (insn & (1 << 19)) { tmp = neon_load_reg(rm, 1); } else { tmp = neon_load_reg(rm, 0); } if (insn & (1 << 16)) { gen_neon_dup_u8(tmp, ((insn >> 17) & 3) * 8); } else if (insn & (1 << 17)) { if ((insn >> 18) & 1) gen_neon_dup_high16(tmp); else gen_neon_dup_low16(tmp); } for (pass = 0; pass < (q ? 4 : 2); pass++) { tmp2 = tcg_temp_new_i32(); tcg_gen_mov_i32(tmp2, tmp); neon_store_reg(rd, pass, tmp2); } tcg_temp_free_i32(tmp); } else { return 1; } } } return 0; }


static void rtas_int_on(sPAPREnvironment *spapr, uint32_t token, uint32_t nargs, target_ulong args, uint32_t nret, target_ulong rets) { struct ics_state *ics = spapr->icp->ics; uint32_t nr; if ((nargs != 1) || (nret != 1)) { rtas_st(rets, 0, -3); return; } nr = rtas_ld(args, 0); if (!ics_valid_irq(ics, nr)) { rtas_st(rets, 0, -3); return; } ics_write_xive(ics, nr, ics->irqs[nr - ics->offset].server, ics->irqs[nr - ics->offset].saved_priority, ics->irqs[nr - ics->offset].saved_priority); rtas_st(rets, 0, 0); /* Success */ }


static void do_info(Monitor *mon, const QDict *qdict, QObject **ret_data) { const mon_cmd_t *cmd; const char *item = qdict_get_try_str(qdict, "item"); if (!item) goto help; for (cmd = info_cmds; cmd->name != NULL; cmd++) { if (compare_cmd(item, cmd->name)) break; } if (cmd->name == NULL) goto help; if (monitor_handler_ported(cmd)) { cmd->mhandler.info_new(mon, ret_data); if (*ret_data) cmd->user_print(mon, *ret_data); } else { cmd->mhandler.info(mon); } return; help: help_cmd(mon, "info"); }


static int ehci_state_fetchsitd(EHCIState *ehci, int async) { uint32_t entry; EHCIsitd sitd; assert(!async); entry = ehci_get_fetch_addr(ehci, async); get_dwords(NLPTR_GET(entry), (uint32_t *)&sitd, sizeof(EHCIsitd) >> 2); ehci_trace_sitd(ehci, entry, &sitd); if (!(sitd.results & SITD_RESULTS_ACTIVE)) { /* siTD is not active, nothing to do */; } else { /* TODO: split transfers are not implemented */ fprintf(stderr, "WARNING: Skipping active siTD\n"); } ehci_set_fetch_addr(ehci, async, sitd.next); ehci_set_state(ehci, async, EST_FETCHENTRY); return 1; }


static void test_cdrom_dma(void) { static const size_t len = ATAPI_BLOCK_SIZE; char *pattern = g_malloc(ATAPI_BLOCK_SIZE * 16); char *rx = g_malloc0(len); uintptr_t guest_buf; PrdtEntry prdt[1]; FILE *fh; ide_test_start("-drive if=none,file=%s,media=cdrom,format=raw,id=sr0,index=0 " "-device ide-cd,drive=sr0,bus=ide.0", tmp_path); qtest_irq_intercept_in(global_qtest, "ioapic"); guest_buf = guest_alloc(guest_malloc, len); prdt[0].addr = cpu_to_le32(guest_buf); prdt[0].size = cpu_to_le32(len | PRDT_EOT); generate_pattern(pattern, ATAPI_BLOCK_SIZE * 16, ATAPI_BLOCK_SIZE); fh = fopen(tmp_path, "w+"); fwrite(pattern, ATAPI_BLOCK_SIZE, 16, fh); fclose(fh); send_dma_request(CMD_PACKET, 0, 1, prdt, 1, send_scsi_cdb_read10); /* Read back data from guest memory into local qtest memory */ memread(guest_buf, rx, len); g_assert_cmpint(memcmp(pattern, rx, len), ==, 0); g_free(pattern); g_free(rx); test_bmdma_teardown(); }


static void test_abstract_interfaces(void) { QList *all_types; QList *obj_types; QListEntry *ae; qtest_start(common_args); /* qom-list-types implements=interface would return any type * that implements _any_ interface (not just interface types), * so use a trick to find the interface type names: * - list all object types * - list all types, and look for items that are not * on the first list */ all_types = qom_list_types(NULL, false); obj_types = qom_list_types("object", false); QLIST_FOREACH_ENTRY(all_types, ae) { QDict *at = qobject_to_qdict(qlist_entry_obj(ae)); const char *aname = qdict_get_str(at, "name"); QListEntry *oe; const char *found = NULL; QLIST_FOREACH_ENTRY(obj_types, oe) { QDict *ot = qobject_to_qdict(qlist_entry_obj(oe)); const char *oname = qdict_get_str(ot, "name"); if (!strcmp(aname, oname)) { found = oname; break; } } /* Using g_assert_cmpstr() will give more useful failure * messages than g_assert(found) */ g_assert_cmpstr(aname, ==, found); } QDECREF(all_types); QDECREF(obj_types); qtest_end(); }


static void mips_fulong2e_init(ram_addr_t ram_size, const char *boot_device, const char *kernel_filename, const char *kernel_cmdline, const char *initrd_filename, const char *cpu_model) { char *filename; unsigned long ram_offset, bios_offset; long bios_size; int64_t kernel_entry; qemu_irq *i8259; qemu_irq *cpu_exit_irq; int via_devfn; PCIBus *pci_bus; uint8_t *eeprom_buf; i2c_bus *smbus; int i; DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS]; DeviceState *eeprom; CPUState *env; /* init CPUs */ if (cpu_model == NULL) { cpu_model = "Loongson-2E"; } env = cpu_init(cpu_model); if (!env) { fprintf(stderr, "Unable to find CPU definition\n"); exit(1); } register_savevm(NULL, "cpu", 0, 3, cpu_save, cpu_load, env); qemu_register_reset(main_cpu_reset, env); /* fulong 2e has 256M ram. */ ram_size = 256 * 1024 * 1024; /* fulong 2e has a 1M flash.Winbond W39L040AP70Z */ bios_size = 1024 * 1024; /* allocate RAM */ ram_offset = qemu_ram_alloc(NULL, "fulong2e.ram", ram_size); bios_offset = qemu_ram_alloc(NULL, "fulong2e.bios", bios_size); cpu_register_physical_memory(0, ram_size, ram_offset); cpu_register_physical_memory(0x1fc00000LL, bios_size, bios_offset | IO_MEM_ROM); /* We do not support flash operation, just loading pmon.bin as raw BIOS. * Please use -L to set the BIOS path and -bios to set bios name. */ if (kernel_filename) { loaderparams.ram_size = ram_size; loaderparams.kernel_filename = kernel_filename; loaderparams.kernel_cmdline = kernel_cmdline; loaderparams.initrd_filename = initrd_filename; kernel_entry = load_kernel (env); write_bootloader(env, qemu_get_ram_ptr(bios_offset), kernel_entry); } else { if (bios_name == NULL) { bios_name = FULONG_BIOSNAME; } filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); if (filename) { bios_size = load_image_targphys(filename, 0x1fc00000LL, BIOS_SIZE); qemu_free(filename); } else { bios_size = -1; } if ((bios_size < 0 || bios_size > BIOS_SIZE) && !kernel_filename) { fprintf(stderr, "qemu: Could not load MIPS bios '%s'\n", bios_name); exit(1); } } /* Init internal devices */ cpu_mips_irq_init_cpu(env); cpu_mips_clock_init(env); /* Interrupt controller */ /* The 8259 -> IP5 */ i8259 = i8259_init(env->irq[5]); /* North bridge, Bonito --> IP2 */ pci_bus = bonito_init((qemu_irq *)&(env->irq[2])); /* South bridge */ if (drive_get_max_bus(IF_IDE) >= MAX_IDE_BUS) { fprintf(stderr, "qemu: too many IDE bus\n"); exit(1); } for(i = 0; i < MAX_IDE_BUS * MAX_IDE_DEVS; i++) { hd[i] = drive_get(IF_IDE, i / MAX_IDE_DEVS, i % MAX_IDE_DEVS); } via_devfn = vt82c686b_init(pci_bus, PCI_DEVFN(FULONG2E_VIA_SLOT, 0)); if (via_devfn < 0) { fprintf(stderr, "vt82c686b_init error \n"); exit(1); } isa_bus_irqs(i8259); vt82c686b_ide_init(pci_bus, hd, PCI_DEVFN(FULONG2E_VIA_SLOT, 1)); usb_uhci_vt82c686b_init(pci_bus, PCI_DEVFN(FULONG2E_VIA_SLOT, 2)); usb_uhci_vt82c686b_init(pci_bus, PCI_DEVFN(FULONG2E_VIA_SLOT, 3)); smbus = vt82c686b_pm_init(pci_bus, PCI_DEVFN(FULONG2E_VIA_SLOT, 4), 0xeee1, NULL); eeprom_buf = qemu_mallocz(8 * 256); /* XXX: make this persistent */ memcpy(eeprom_buf, eeprom_spd, sizeof(eeprom_spd)); /* TODO: Populate SPD eeprom data. */ eeprom = qdev_create((BusState *)smbus, "smbus-eeprom"); qdev_prop_set_uint8(eeprom, "address", 0x50); qdev_prop_set_ptr(eeprom, "data", eeprom_buf); qdev_init_nofail(eeprom); /* init other devices */ pit = pit_init(0x40, isa_reserve_irq(0)); cpu_exit_irq = qemu_allocate_irqs(cpu_request_exit, NULL, 1); DMA_init(0, cpu_exit_irq); /* Super I/O */ isa_create_simple("i8042"); rtc_init(2000, NULL); for(i = 0; i < MAX_SERIAL_PORTS; i++) { if (serial_hds[i]) { serial_isa_init(i, serial_hds[i]); } } if (parallel_hds[0]) { parallel_init(0, parallel_hds[0]); } /* Sound card */ audio_init(pci_bus); /* Network card */ network_init(); }


static ssize_t nic_receive(NetClientState *nc, const uint8_t * buf, size_t size) { /* TODO: * - Magic packets should set bit 30 in power management driver register. * - Interesting packets should set bit 29 in power management driver register. */ EEPRO100State *s = DO_UPCAST(NICState, nc, nc)->opaque; uint16_t rfd_status = 0xa000; #if defined(CONFIG_PAD_RECEIVED_FRAMES) uint8_t min_buf[60]; #endif static const uint8_t broadcast_macaddr[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; #if defined(CONFIG_PAD_RECEIVED_FRAMES) /* Pad to minimum Ethernet frame length */ if (size < sizeof(min_buf)) { memcpy(min_buf, buf, size); memset(&min_buf[size], 0, sizeof(min_buf) - size); buf = min_buf; size = sizeof(min_buf); } #endif if (s->configuration[8] & 0x80) { /* CSMA is disabled. */ logout("%p received while CSMA is disabled\n", s); return -1; #if !defined(CONFIG_PAD_RECEIVED_FRAMES) } else if (size < 64 && (s->configuration[7] & BIT(0))) { /* Short frame and configuration byte 7/0 (discard short receive) set: * Short frame is discarded */ logout("%p received short frame (%zu byte)\n", s, size); s->statistics.rx_short_frame_errors++; return -1; #endif } else if ((size > MAX_ETH_FRAME_SIZE + 4) && !(s->configuration[18] & BIT(3))) { /* Long frame and configuration byte 18/3 (long receive ok) not set: * Long frames are discarded. */ logout("%p received long frame (%zu byte), ignored\n", s, size); return -1; } else if (memcmp(buf, s->conf.macaddr.a, 6) == 0) { /* !!! */ /* Frame matches individual address. */ /* TODO: check configuration byte 15/4 (ignore U/L). */ TRACE(RXTX, logout("%p received frame for me, len=%zu\n", s, size)); } else if (memcmp(buf, broadcast_macaddr, 6) == 0) { /* Broadcast frame. */ TRACE(RXTX, logout("%p received broadcast, len=%zu\n", s, size)); rfd_status |= 0x0002; } else if (buf[0] & 0x01) { /* Multicast frame. */ TRACE(RXTX, logout("%p received multicast, len=%zu,%s\n", s, size, nic_dump(buf, size))); if (s->configuration[21] & BIT(3)) { /* Multicast all bit is set, receive all multicast frames. */ } else { unsigned mcast_idx = e100_compute_mcast_idx(buf); assert(mcast_idx < 64); if (s->mult[mcast_idx >> 3] & (1 << (mcast_idx & 7))) { /* Multicast frame is allowed in hash table. */ } else if (s->configuration[15] & BIT(0)) { /* Promiscuous: receive all. */ rfd_status |= 0x0004; } else { TRACE(RXTX, logout("%p multicast ignored\n", s)); return -1; } } /* TODO: Next not for promiscuous mode? */ rfd_status |= 0x0002; } else if (s->configuration[15] & BIT(0)) { /* Promiscuous: receive all. */ TRACE(RXTX, logout("%p received frame in promiscuous mode, len=%zu\n", s, size)); rfd_status |= 0x0004; } else if (s->configuration[20] & BIT(6)) { /* Multiple IA bit set. */ unsigned mcast_idx = compute_mcast_idx(buf); assert(mcast_idx < 64); if (s->mult[mcast_idx >> 3] & (1 << (mcast_idx & 7))) { TRACE(RXTX, logout("%p accepted, multiple IA bit set\n", s)); } else { TRACE(RXTX, logout("%p frame ignored, multiple IA bit set\n", s)); return -1; } } else { TRACE(RXTX, logout("%p received frame, ignored, len=%zu,%s\n", s, size, nic_dump(buf, size))); return size; } if (get_ru_state(s) != ru_ready) { /* No resources available. */ logout("no resources, state=%u\n", get_ru_state(s)); /* TODO: RNR interrupt only at first failed frame? */ eepro100_rnr_interrupt(s); s->statistics.rx_resource_errors++; #if 0 assert(!"no resources"); #endif return -1; } /* !!! */ eepro100_rx_t rx; pci_dma_read(&s->dev, s->ru_base + s->ru_offset, &rx, sizeof(eepro100_rx_t)); uint16_t rfd_command = le16_to_cpu(rx.command); uint16_t rfd_size = le16_to_cpu(rx.size); if (size > rfd_size) { logout("Receive buffer (%" PRId16 " bytes) too small for data " "(%zu bytes); data truncated\n", rfd_size, size); size = rfd_size; } #if !defined(CONFIG_PAD_RECEIVED_FRAMES) if (size < 64) { rfd_status |= 0x0080; } #endif TRACE(OTHER, logout("command 0x%04x, link 0x%08x, addr 0x%08x, size %u\n", rfd_command, rx.link, rx.rx_buf_addr, rfd_size)); stw_le_pci_dma(&s->dev, s->ru_base + s->ru_offset + offsetof(eepro100_rx_t, status), rfd_status); stw_le_pci_dma(&s->dev, s->ru_base + s->ru_offset + offsetof(eepro100_rx_t, count), size); /* Early receive interrupt not supported. */ #if 0 eepro100_er_interrupt(s); #endif /* Receive CRC Transfer not supported. */ if (s->configuration[18] & BIT(2)) { missing("Receive CRC Transfer"); return -1; } /* TODO: check stripping enable bit. */ #if 0 assert(!(s->configuration[17] & BIT(0))); #endif pci_dma_write(&s->dev, s->ru_base + s->ru_offset + sizeof(eepro100_rx_t), buf, size); s->statistics.rx_good_frames++; eepro100_fr_interrupt(s); s->ru_offset = le32_to_cpu(rx.link); if (rfd_command & COMMAND_EL) { /* EL bit is set, so this was the last frame. */ logout("receive: Running out of frames\n"); set_ru_state(s, ru_suspended); } if (rfd_command & COMMAND_S) { /* S bit is set. */ set_ru_state(s, ru_suspended); } return size; }


void pci_bus_get_w64_range(PCIBus *bus, Range *range) { range->begin = range->end = 0; pci_for_each_device_under_bus(bus, pci_dev_get_w64, range); }


static void m5208_timer_write(void *opaque, target_phys_addr_t offset, uint64_t value, unsigned size) { m5208_timer_state *s = (m5208_timer_state *)opaque; int prescale; int limit; switch (offset) { case 0: /* The PIF bit is set-to-clear. */ if (value & PCSR_PIF) { s->pcsr &= ~PCSR_PIF; value &= ~PCSR_PIF; } /* Avoid frobbing the timer if we're just twiddling IRQ bits. */ if (((s->pcsr ^ value) & ~PCSR_PIE) == 0) { s->pcsr = value; m5208_timer_update(s); return; } if (s->pcsr & PCSR_EN) ptimer_stop(s->timer); s->pcsr = value; prescale = 1 << ((s->pcsr & PCSR_PRE_MASK) >> PCSR_PRE_SHIFT); ptimer_set_freq(s->timer, (SYS_FREQ / 2) / prescale); if (s->pcsr & PCSR_RLD) limit = s->pmr; else limit = 0xffff; ptimer_set_limit(s->timer, limit, 0); if (s->pcsr & PCSR_EN) ptimer_run(s->timer, 0); break; case 2: s->pmr = value; s->pcsr &= ~PCSR_PIF; if ((s->pcsr & PCSR_RLD) == 0) { if (s->pcsr & PCSR_OVW) ptimer_set_count(s->timer, value); } else { ptimer_set_limit(s->timer, value, s->pcsr & PCSR_OVW); } break; case 4: break; default: hw_error("m5208_timer_write: Bad offset 0x%x\n", (int)offset); break; } m5208_timer_update(s); }


static void free_tables(H264Context *h){ int i; H264Context *hx; av_freep(&h->intra4x4_pred_mode); av_freep(&h->chroma_pred_mode_table); av_freep(&h->cbp_table); av_freep(&h->mvd_table[0]); av_freep(&h->mvd_table[1]); av_freep(&h->direct_table); av_freep(&h->non_zero_count); av_freep(&h->slice_table_base); h->slice_table= NULL; av_freep(&h->list_counts); av_freep(&h->mb2b_xy); av_freep(&h->mb2br_xy); for(i = 0; i < MAX_THREADS; i++) { hx = h->thread_context[i]; if(!hx) continue; av_freep(&hx->top_borders[1]); av_freep(&hx->top_borders[0]); av_freep(&hx->s.obmc_scratchpad); av_freep(&hx->rbsp_buffer[1]); av_freep(&hx->rbsp_buffer[0]); hx->rbsp_buffer_size[0] = 0; hx->rbsp_buffer_size[1] = 0; if (i) av_freep(&h->thread_context[i]); } }


CBus *cbus_init(qemu_irq dat) { CBusPriv *s = (CBusPriv *) g_malloc0(sizeof(*s)); s->dat_out = dat; s->cbus.clk = qemu_allocate_irqs(cbus_clk, s, 1)[0]; s->cbus.dat = qemu_allocate_irqs(cbus_dat, s, 1)[0]; s->cbus.sel = qemu_allocate_irqs(cbus_sel, s, 1)[0]; s->sel = 1; s->clk = 0; s->dat = 0; return &s->cbus; }


static int cp15_tls_load_store(CPUState *env, DisasContext *s, uint32_t insn, uint32_t rd) { TCGv tmp; int cpn = (insn >> 16) & 0xf; int cpm = insn & 0xf; int op = ((insn >> 5) & 7) | ((insn >> 18) & 0x38); if (!arm_feature(env, ARM_FEATURE_V6K)) return 0; if (!(cpn == 13 && cpm == 0)) return 0; if (insn & ARM_CP_RW_BIT) { switch (op) { case 2: tmp = load_cpu_field(cp15.c13_tls1); break; case 3: tmp = load_cpu_field(cp15.c13_tls2); break; case 4: tmp = load_cpu_field(cp15.c13_tls3); break; default: return 0; } store_reg(s, rd, tmp); } else { tmp = load_reg(s, rd); switch (op) { case 2: store_cpu_field(tmp, cp15.c13_tls1); break; case 3: store_cpu_field(tmp, cp15.c13_tls2); break; case 4: store_cpu_field(tmp, cp15.c13_tls3); break; default: dead_tmp(tmp); return 0; } } return 1; }


void hmp_pci_add(Monitor *mon, const QDict *qdict) { PCIDevice *dev = NULL; const char *pci_addr = qdict_get_str(qdict, "pci_addr"); const char *type = qdict_get_str(qdict, "type"); const char *opts = qdict_get_try_str(qdict, "opts"); /* strip legacy tag */ if (!strncmp(pci_addr, "pci_addr=", 9)) { pci_addr += 9; } if (!opts) { opts = ""; } if (!strcmp(pci_addr, "auto")) pci_addr = NULL; if (strcmp(type, "nic") == 0) { dev = qemu_pci_hot_add_nic(mon, pci_addr, opts); } else if (strcmp(type, "storage") == 0) { dev = qemu_pci_hot_add_storage(mon, pci_addr, opts); } else { monitor_printf(mon, "invalid type: %s\n", type); } if (dev) { monitor_printf(mon, "OK root bus %s, bus %d, slot %d, function %d\n", pci_root_bus_path(dev), pci_bus_num(dev->bus), PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn)); } else monitor_printf(mon, "failed to add %s\n", opts); }


static int ape_decode_frame(AVCodecContext * avctx, void *data, int *data_size, const uint8_t * buf, int buf_size) { APEContext *s = avctx->priv_data; int16_t *samples = data; int nblocks; int i, n; int blockstodecode; int bytes_used; if (buf_size == 0 && !s->samples) { *data_size = 0; return 0; /* should not happen but who knows */ if (BLOCKS_PER_LOOP * 2 * avctx->channels > *data_size) { av_log (avctx, AV_LOG_ERROR, "Packet size is too big to be handled in lavc! (max is %d where you have %d)\n", *data_size, s->samples * 2 * avctx->channels); if(!s->samples){ s->data = av_realloc(s->data, (buf_size + 3) & ~3); s->dsp.bswap_buf((uint32_t*)s->data, (const uint32_t*)buf, buf_size >> 2); s->ptr = s->last_ptr = s->data; s->data_end = s->data + buf_size; nblocks = s->samples = bytestream_get_be32(&s->ptr); n = bytestream_get_be32(&s->ptr); if(n < 0 || n > 3){ av_log(avctx, AV_LOG_ERROR, "Incorrect offset passed\n"); s->data = NULL; s->ptr += n; s->currentframeblocks = nblocks; buf += 4; if (s->samples <= 0) { *data_size = 0; return buf_size; memset(s->decoded0, 0, sizeof(s->decoded0)); memset(s->decoded1, 0, sizeof(s->decoded1)); /* Initialize the frame decoder */ init_frame_decoder(s); if (!s->data) { *data_size = 0; return buf_size; nblocks = s->samples; blockstodecode = FFMIN(BLOCKS_PER_LOOP, nblocks); if ((s->channels == 1) || (s->frameflags & APE_FRAMECODE_PSEUDO_STEREO)) ape_unpack_mono(s, blockstodecode); else ape_unpack_stereo(s, blockstodecode); for (i = 0; i < blockstodecode; i++) { *samples++ = s->decoded0[i]; if(s->channels == 2) *samples++ = s->decoded1[i]; s->samples -= blockstodecode; *data_size = blockstodecode * 2 * s->channels; bytes_used = s->samples ? s->ptr - s->last_ptr : buf_size; s->last_ptr = s->ptr; return bytes_used;


AVAES *av_aes_init(uint8_t *key, int key_bits, int decrypt) { AVAES *a; int i, j, t, rconpointer = 0; uint8_t tk[8][4]; int KC= key_bits>>5; int rounds= KC + 6; uint8_t log8[256]; uint8_t alog8[512]; if(!sbox[255]){ j=1; for(i=0; i<255; i++){ alog8[i]= alog8[i+255]= j; log8[j]= i; j^= j+j; if(j>255) j^= 0x11B; } for(i=0; i<256; i++){ j= i ? alog8[255-log8[i]] : 0; j ^= (j<<1) ^ (j<<2) ^ (j<<3) ^ (j<<4); j = (j ^ (j>>8) ^ 99) & 255; inv_sbox[j]= i; sbox [i]= j; } init_multbl2(dec_multbl[0], (int[4]){0xe, 0x9, 0xd, 0xb}, log8, alog8, inv_sbox); init_multbl2(enc_multbl[0], (int[4]){0x2, 0x1, 0x1, 0x3}, log8, alog8, sbox); } if(key_bits!=128 && key_bits!=192 && key_bits!=256) return NULL; a= av_malloc(sizeof(AVAES)); a->rounds= rounds; memcpy(tk, key, KC*4); for(t= 0; t < (rounds+1)*4;) { memcpy(a->round_key[0][t], tk, KC*4); t+= KC; for(i = 0; i < 4; i++) tk[0][i] ^= sbox[tk[KC-1][(i+1)&3]]; tk[0][0] ^= rcon[rconpointer++]; for(j = 1; j < KC; j++){ if(KC != 8 || j != KC>>1) for(i = 0; i < 4; i++) tk[j][i] ^= tk[j-1][i]; else for(i = 0; i < 4; i++) tk[j][i] ^= sbox[tk[j-1][i]]; } } if(decrypt){ for(i=1; i<rounds; i++){ for(j=0; j<16; j++) a->round_key[i][0][j]= sbox[a->round_key[i][0][j]]; mix(a->round_key[i], dec_multbl); } }else{ for(i=0; i<(rounds+1)>>1; i++){ for(j=0; j<16; j++) FFSWAP(int, a->round_key[i][0][j], a->round_key[rounds-i][0][j]); } } return a; }


av_cold void ff_mpadsp_init(MPADSPContext *s) { DCTContext dct; ff_dct_init(&dct, 5, DCT_II); ff_init_mpadsp_tabs_float(); ff_init_mpadsp_tabs_fixed(); s->apply_window_float = ff_mpadsp_apply_window_float; s->apply_window_fixed = ff_mpadsp_apply_window_fixed; s->dct32_float = dct.dct32; s->dct32_fixed = ff_dct32_fixed; s->imdct36_blocks_float = ff_imdct36_blocks_float; s->imdct36_blocks_fixed = ff_imdct36_blocks_fixed; if (ARCH_AARCH64) ff_mpadsp_init_aarch64(s); if (ARCH_ARM) ff_mpadsp_init_arm(s); if (ARCH_PPC) ff_mpadsp_init_ppc(s); if (ARCH_X86) ff_mpadsp_init_x86(s); if (HAVE_MIPSFPU) ff_mpadsp_init_mipsfpu(s); if (HAVE_MIPSDSP) ff_mpadsp_init_mipsdsp(s); }


static int get_range_off(int *off, int *y_rng, int *uv_rng, enum AVColorRange rng, int depth) { switch (rng) { case AVCOL_RANGE_MPEG: *off = 16 << (depth - 8); *y_rng = 219 << (depth - 8); *uv_rng = 224 << (depth - 8); break; case AVCOL_RANGE_JPEG: *off = 0; *y_rng = *uv_rng = (256 << (depth - 8)) - 1; break; default: return AVERROR(EINVAL); } return 0; }


static av_always_inline void fill_filter_caches_inter(const H264Context *h, H264SliceContext *sl, int mb_type, int top_xy, int left_xy[LEFT_MBS], int top_type, int left_type[LEFT_MBS], int mb_xy, int list) { int b_stride = h->b_stride; int16_t(*mv_dst)[2] = &sl->mv_cache[list][scan8[0]]; int8_t *ref_cache = &sl->ref_cache[list][scan8[0]]; if (IS_INTER(mb_type) || IS_DIRECT(mb_type)) { if (USES_LIST(top_type, list)) { const int b_xy = h->mb2b_xy[top_xy] + 3 * b_stride; const int b8_xy = 4 * top_xy + 2; int (*ref2frm)[64] = sl->ref2frm[h->slice_table[top_xy] & (MAX_SLICES - 1)][0] + (MB_MBAFF(sl) ? 20 : 2); AV_COPY128(mv_dst - 1 * 8, h->cur_pic.motion_val[list][b_xy + 0]); ref_cache[0 - 1 * 8] = ref_cache[1 - 1 * 8] = ref2frm[list][h->cur_pic.ref_index[list][b8_xy + 0]]; ref_cache[2 - 1 * 8] = ref_cache[3 - 1 * 8] = ref2frm[list][h->cur_pic.ref_index[list][b8_xy + 1]]; } else { AV_ZERO128(mv_dst - 1 * 8); AV_WN32A(&ref_cache[0 - 1 * 8], ((LIST_NOT_USED) & 0xFF) * 0x01010101u); } if (!IS_INTERLACED(mb_type ^ left_type[LTOP])) { if (USES_LIST(left_type[LTOP], list)) { const int b_xy = h->mb2b_xy[left_xy[LTOP]] + 3; const int b8_xy = 4 * left_xy[LTOP] + 1; int (*ref2frm)[64] = sl->ref2frm[h->slice_table[left_xy[LTOP]] & (MAX_SLICES - 1)][0] + (MB_MBAFF(sl) ? 20 : 2); AV_COPY32(mv_dst - 1 + 0, h->cur_pic.motion_val[list][b_xy + b_stride * 0]); AV_COPY32(mv_dst - 1 + 8, h->cur_pic.motion_val[list][b_xy + b_stride * 1]); AV_COPY32(mv_dst - 1 + 16, h->cur_pic.motion_val[list][b_xy + b_stride * 2]); AV_COPY32(mv_dst - 1 + 24, h->cur_pic.motion_val[list][b_xy + b_stride * 3]); ref_cache[-1 + 0] = ref_cache[-1 + 8] = ref2frm[list][h->cur_pic.ref_index[list][b8_xy + 2 * 0]]; ref_cache[-1 + 16] = ref_cache[-1 + 24] = ref2frm[list][h->cur_pic.ref_index[list][b8_xy + 2 * 1]]; } else { AV_ZERO32(mv_dst - 1 + 0); AV_ZERO32(mv_dst - 1 + 8); AV_ZERO32(mv_dst - 1 + 16); AV_ZERO32(mv_dst - 1 + 24); ref_cache[-1 + 0] = ref_cache[-1 + 8] = ref_cache[-1 + 16] = ref_cache[-1 + 24] = LIST_NOT_USED; } } } if (!USES_LIST(mb_type, list)) { fill_rectangle(mv_dst, 4, 4, 8, pack16to32(0, 0), 4); AV_WN32A(&ref_cache[0 * 8], ((LIST_NOT_USED) & 0xFF) * 0x01010101u); AV_WN32A(&ref_cache[1 * 8], ((LIST_NOT_USED) & 0xFF) * 0x01010101u); AV_WN32A(&ref_cache[2 * 8], ((LIST_NOT_USED) & 0xFF) * 0x01010101u); AV_WN32A(&ref_cache[3 * 8], ((LIST_NOT_USED) & 0xFF) * 0x01010101u); return; } { int8_t *ref = &h->cur_pic.ref_index[list][4 * mb_xy]; int (*ref2frm)[64] = sl->ref2frm[sl->slice_num & (MAX_SLICES - 1)][0] + (MB_MBAFF(sl) ? 20 : 2); uint32_t ref01 = (pack16to32(ref2frm[list][ref[0]], ref2frm[list][ref[1]]) & 0x00FF00FF) * 0x0101; uint32_t ref23 = (pack16to32(ref2frm[list][ref[2]], ref2frm[list][ref[3]]) & 0x00FF00FF) * 0x0101; AV_WN32A(&ref_cache[0 * 8], ref01); AV_WN32A(&ref_cache[1 * 8], ref01); AV_WN32A(&ref_cache[2 * 8], ref23); AV_WN32A(&ref_cache[3 * 8], ref23); } { int16_t(*mv_src)[2] = &h->cur_pic.motion_val[list][4 * sl->mb_x + 4 * sl->mb_y * b_stride]; AV_COPY128(mv_dst + 8 * 0, mv_src + 0 * b_stride); AV_COPY128(mv_dst + 8 * 1, mv_src + 1 * b_stride); AV_COPY128(mv_dst + 8 * 2, mv_src + 2 * b_stride); AV_COPY128(mv_dst + 8 * 3, mv_src + 3 * b_stride); } }


static int adpcm_decode_frame(AVCodecContext *avctx, void *data, int *data_size, uint8_t *buf, int buf_size) { ADPCMContext *c = avctx->priv_data; ADPCMChannelStatus *cs; int n, m, channel, i; int block_predictor[2]; short *samples; short *samples_end; uint8_t *src; int st; /* stereo */ /* DK3 ADPCM accounting variables */ unsigned char last_byte = 0; unsigned char nibble; int decode_top_nibble_next = 0; int diff_channel; /* EA ADPCM state variables */ uint32_t samples_in_chunk; int32_t previous_left_sample, previous_right_sample; int32_t current_left_sample, current_right_sample; int32_t next_left_sample, next_right_sample; int32_t coeff1l, coeff2l, coeff1r, coeff2r; uint8_t shift_left, shift_right; int count1, count2; if (!buf_size) return 0; //should protect all 4bit ADPCM variants //8 is needed for CODEC_ID_ADPCM_IMA_WAV with 2 channels // if(*data_size/4 < buf_size + 8) return -1; samples = data; samples_end= samples + *data_size/2; *data_size= 0; src = buf; st = avctx->channels == 2 ? 1 : 0; switch(avctx->codec->id) { case CODEC_ID_ADPCM_IMA_QT: n = (buf_size - 2);/* >> 2*avctx->channels;*/ channel = c->channel; cs = &(c->status[channel]); /* (pppppp) (piiiiiii) */ /* Bits 15-7 are the _top_ 9 bits of the 16-bit initial predictor value */ cs->predictor = (*src++) << 8; cs->predictor |= (*src & 0x80); cs->predictor &= 0xFF80; /* sign extension */ if(cs->predictor & 0x8000) cs->predictor -= 0x10000; cs->predictor = av_clip_int16(cs->predictor); cs->step_index = (*src++) & 0x7F; if (cs->step_index > 88){ av_log(avctx, AV_LOG_ERROR, "ERROR: step_index = %i\n", cs->step_index); cs->step_index = 88; } cs->step = step_table[cs->step_index]; if (st && channel) samples++; for(m=32; n>0 && m>0; n--, m--) { /* in QuickTime, IMA is encoded by chuncks of 34 bytes (=64 samples) */ *samples = adpcm_ima_expand_nibble(cs, src[0] & 0x0F, 3); samples += avctx->channels; *samples = adpcm_ima_expand_nibble(cs, (src[0] >> 4) & 0x0F, 3); samples += avctx->channels; src ++; } if(st) { /* handle stereo interlacing */ c->channel = (channel + 1) % 2; /* we get one packet for left, then one for right data */ if(channel == 1) { /* wait for the other packet before outputing anything */ return src - buf; } } break; case CODEC_ID_ADPCM_IMA_WAV: if (avctx->block_align != 0 && buf_size > avctx->block_align) buf_size = avctx->block_align; // samples_per_block= (block_align-4*chanels)*8 / (bits_per_sample * chanels) + 1; for(i=0; i<avctx->channels; i++){ cs = &(c->status[i]); cs->predictor = (int16_t)(src[0] + (src[1]<<8)); src+=2; // XXX: is this correct ??: *samples++ = cs->predictor; cs->step_index = *src++; if (cs->step_index > 88){ av_log(avctx, AV_LOG_ERROR, "ERROR: step_index = %i\n", cs->step_index); cs->step_index = 88; } if (*src++) av_log(avctx, AV_LOG_ERROR, "unused byte should be null but is %d!!\n", src[-1]); /* unused */ } while(src < buf + buf_size){ for(m=0; m<4; m++){ for(i=0; i<=st; i++) *samples++ = adpcm_ima_expand_nibble(&c->status[i], src[4*i] & 0x0F, 3); for(i=0; i<=st; i++) *samples++ = adpcm_ima_expand_nibble(&c->status[i], src[4*i] >> 4 , 3); src++; } src += 4*st; } break; case CODEC_ID_ADPCM_4XM: cs = &(c->status[0]); c->status[0].predictor= (int16_t)(src[0] + (src[1]<<8)); src+=2; if(st){ c->status[1].predictor= (int16_t)(src[0] + (src[1]<<8)); src+=2; } c->status[0].step_index= (int16_t)(src[0] + (src[1]<<8)); src+=2; if(st){ c->status[1].step_index= (int16_t)(src[0] + (src[1]<<8)); src+=2; } if (cs->step_index < 0) cs->step_index = 0; if (cs->step_index > 88) cs->step_index = 88; m= (buf_size - (src - buf))>>st; for(i=0; i<m; i++) { *samples++ = adpcm_ima_expand_nibble(&c->status[0], src[i] & 0x0F, 4); if (st) *samples++ = adpcm_ima_expand_nibble(&c->status[1], src[i+m] & 0x0F, 4); *samples++ = adpcm_ima_expand_nibble(&c->status[0], src[i] >> 4, 4); if (st) *samples++ = adpcm_ima_expand_nibble(&c->status[1], src[i+m] >> 4, 4); } src += m<<st; break; case CODEC_ID_ADPCM_MS: if (avctx->block_align != 0 && buf_size > avctx->block_align) buf_size = avctx->block_align; n = buf_size - 7 * avctx->channels; if (n < 0) return -1; block_predictor[0] = av_clip(*src++, 0, 7); block_predictor[1] = 0; if (st) block_predictor[1] = av_clip(*src++, 0, 7); c->status[0].idelta = (int16_t)((*src & 0xFF) | ((src[1] << 8) & 0xFF00)); src+=2; if (st){ c->status[1].idelta = (int16_t)((*src & 0xFF) | ((src[1] << 8) & 0xFF00)); src+=2; } c->status[0].coeff1 = AdaptCoeff1[block_predictor[0]]; c->status[0].coeff2 = AdaptCoeff2[block_predictor[0]]; c->status[1].coeff1 = AdaptCoeff1[block_predictor[1]]; c->status[1].coeff2 = AdaptCoeff2[block_predictor[1]]; c->status[0].sample1 = ((*src & 0xFF) | ((src[1] << 8) & 0xFF00)); src+=2; if (st) c->status[1].sample1 = ((*src & 0xFF) | ((src[1] << 8) & 0xFF00)); if (st) src+=2; c->status[0].sample2 = ((*src & 0xFF) | ((src[1] << 8) & 0xFF00)); src+=2; if (st) c->status[1].sample2 = ((*src & 0xFF) | ((src[1] << 8) & 0xFF00)); if (st) src+=2; *samples++ = c->status[0].sample1; if (st) *samples++ = c->status[1].sample1; *samples++ = c->status[0].sample2; if (st) *samples++ = c->status[1].sample2; for(;n>0;n--) { *samples++ = adpcm_ms_expand_nibble(&c->status[0], (src[0] >> 4) & 0x0F); *samples++ = adpcm_ms_expand_nibble(&c->status[st], src[0] & 0x0F); src ++; } break; case CODEC_ID_ADPCM_IMA_DK4: if (avctx->block_align != 0 && buf_size > avctx->block_align) buf_size = avctx->block_align; c->status[0].predictor = (int16_t)(src[0] | (src[1] << 8)); c->status[0].step_index = src[2]; src += 4; *samples++ = c->status[0].predictor; if (st) { c->status[1].predictor = (int16_t)(src[0] | (src[1] << 8)); c->status[1].step_index = src[2]; src += 4; *samples++ = c->status[1].predictor; } while (src < buf + buf_size) { /* take care of the top nibble (always left or mono channel) */ *samples++ = adpcm_ima_expand_nibble(&c->status[0], (src[0] >> 4) & 0x0F, 3); /* take care of the bottom nibble, which is right sample for * stereo, or another mono sample */ if (st) *samples++ = adpcm_ima_expand_nibble(&c->status[1], src[0] & 0x0F, 3); else *samples++ = adpcm_ima_expand_nibble(&c->status[0], src[0] & 0x0F, 3); src++; } break; case CODEC_ID_ADPCM_IMA_DK3: if (avctx->block_align != 0 && buf_size > avctx->block_align) buf_size = avctx->block_align; if(buf_size + 16 > (samples_end - samples)*3/8) return -1; c->status[0].predictor = (int16_t)(src[10] | (src[11] << 8)); c->status[1].predictor = (int16_t)(src[12] | (src[13] << 8)); c->status[0].step_index = src[14]; c->status[1].step_index = src[15]; /* sign extend the predictors */ src += 16; diff_channel = c->status[1].predictor; /* the DK3_GET_NEXT_NIBBLE macro issues the break statement when * the buffer is consumed */ while (1) { /* for this algorithm, c->status[0] is the sum channel and * c->status[1] is the diff channel */ /* process the first predictor of the sum channel */ DK3_GET_NEXT_NIBBLE(); adpcm_ima_expand_nibble(&c->status[0], nibble, 3); /* process the diff channel predictor */ DK3_GET_NEXT_NIBBLE(); adpcm_ima_expand_nibble(&c->status[1], nibble, 3); /* process the first pair of stereo PCM samples */ diff_channel = (diff_channel + c->status[1].predictor) / 2; *samples++ = c->status[0].predictor + c->status[1].predictor; *samples++ = c->status[0].predictor - c->status[1].predictor; /* process the second predictor of the sum channel */ DK3_GET_NEXT_NIBBLE(); adpcm_ima_expand_nibble(&c->status[0], nibble, 3); /* process the second pair of stereo PCM samples */ diff_channel = (diff_channel + c->status[1].predictor) / 2; *samples++ = c->status[0].predictor + c->status[1].predictor; *samples++ = c->status[0].predictor - c->status[1].predictor; } break; case CODEC_ID_ADPCM_IMA_WS: /* no per-block initialization; just start decoding the data */ while (src < buf + buf_size) { if (st) { *samples++ = adpcm_ima_expand_nibble(&c->status[0], (src[0] >> 4) & 0x0F, 3); *samples++ = adpcm_ima_expand_nibble(&c->status[1], src[0] & 0x0F, 3); } else { *samples++ = adpcm_ima_expand_nibble(&c->status[0], (src[0] >> 4) & 0x0F, 3); *samples++ = adpcm_ima_expand_nibble(&c->status[0], src[0] & 0x0F, 3); } src++; } break; case CODEC_ID_ADPCM_XA: c->status[0].sample1 = c->status[0].sample2 = c->status[1].sample1 = c->status[1].sample2 = 0; while (buf_size >= 128) { xa_decode(samples, src, &c->status[0], &c->status[1], avctx->channels); src += 128; samples += 28 * 8; buf_size -= 128; } break; case CODEC_ID_ADPCM_EA: samples_in_chunk = AV_RL32(src); if (samples_in_chunk >= ((buf_size - 12) * 2)) { src += buf_size; break; } src += 4; current_left_sample = (int16_t)AV_RL16(src); src += 2; previous_left_sample = (int16_t)AV_RL16(src); src += 2; current_right_sample = (int16_t)AV_RL16(src); src += 2; previous_right_sample = (int16_t)AV_RL16(src); src += 2; for (count1 = 0; count1 < samples_in_chunk/28;count1++) { coeff1l = ea_adpcm_table[(*src >> 4) & 0x0F]; coeff2l = ea_adpcm_table[((*src >> 4) & 0x0F) + 4]; coeff1r = ea_adpcm_table[*src & 0x0F]; coeff2r = ea_adpcm_table[(*src & 0x0F) + 4]; src++; shift_left = ((*src >> 4) & 0x0F) + 8; shift_right = (*src & 0x0F) + 8; src++; for (count2 = 0; count2 < 28; count2++) { next_left_sample = (((*src & 0xF0) << 24) >> shift_left); next_right_sample = (((*src & 0x0F) << 28) >> shift_right); src++; next_left_sample = (next_left_sample + (current_left_sample * coeff1l) + (previous_left_sample * coeff2l) + 0x80) >> 8; next_right_sample = (next_right_sample + (current_right_sample * coeff1r) + (previous_right_sample * coeff2r) + 0x80) >> 8; previous_left_sample = current_left_sample; current_left_sample = av_clip_int16(next_left_sample); previous_right_sample = current_right_sample; current_right_sample = av_clip_int16(next_right_sample); *samples++ = (unsigned short)current_left_sample; *samples++ = (unsigned short)current_right_sample; } } break; case CODEC_ID_ADPCM_IMA_AMV: case CODEC_ID_ADPCM_IMA_SMJPEG: c->status[0].predictor = *src; src += 2; c->status[0].step_index = *src++; src++; /* skip another byte before getting to the meat */ if (avctx->codec->id == CODEC_ID_ADPCM_IMA_AMV) src+=4; while (src < buf + buf_size) { char hi, lo; lo = *src & 0x0F; hi = (*src >> 4) & 0x0F; if (avctx->codec->id == CODEC_ID_ADPCM_IMA_AMV) FFSWAP(char, hi, lo); *samples++ = adpcm_ima_expand_nibble(&c->status[0], lo, 3); *samples++ = adpcm_ima_expand_nibble(&c->status[0], hi, 3); src++; } break; case CODEC_ID_ADPCM_CT: while (src < buf + buf_size) { if (st) { *samples++ = adpcm_ct_expand_nibble(&c->status[0], (src[0] >> 4) & 0x0F); *samples++ = adpcm_ct_expand_nibble(&c->status[1], src[0] & 0x0F); } else { *samples++ = adpcm_ct_expand_nibble(&c->status[0], (src[0] >> 4) & 0x0F); *samples++ = adpcm_ct_expand_nibble(&c->status[0], src[0] & 0x0F); } src++; } break; case CODEC_ID_ADPCM_SBPRO_4: case CODEC_ID_ADPCM_SBPRO_3: case CODEC_ID_ADPCM_SBPRO_2: if (!c->status[0].step_index) { /* the first byte is a raw sample */ *samples++ = 128 * (*src++ - 0x80); if (st) *samples++ = 128 * (*src++ - 0x80); c->status[0].step_index = 1; } if (avctx->codec->id == CODEC_ID_ADPCM_SBPRO_4) { while (src < buf + buf_size) { *samples++ = adpcm_sbpro_expand_nibble(&c->status[0], (src[0] >> 4) & 0x0F, 4, 0); *samples++ = adpcm_sbpro_expand_nibble(&c->status[st], src[0] & 0x0F, 4, 0); src++; } } else if (avctx->codec->id == CODEC_ID_ADPCM_SBPRO_3) { while (src < buf + buf_size && samples + 2 < samples_end) { *samples++ = adpcm_sbpro_expand_nibble(&c->status[0], (src[0] >> 5) & 0x07, 3, 0); *samples++ = adpcm_sbpro_expand_nibble(&c->status[0], (src[0] >> 2) & 0x07, 3, 0); *samples++ = adpcm_sbpro_expand_nibble(&c->status[0], src[0] & 0x03, 2, 0); src++; } } else { while (src < buf + buf_size && samples + 3 < samples_end) { *samples++ = adpcm_sbpro_expand_nibble(&c->status[0], (src[0] >> 6) & 0x03, 2, 2); *samples++ = adpcm_sbpro_expand_nibble(&c->status[st], (src[0] >> 4) & 0x03, 2, 2); *samples++ = adpcm_sbpro_expand_nibble(&c->status[0], (src[0] >> 2) & 0x03, 2, 2); *samples++ = adpcm_sbpro_expand_nibble(&c->status[st], src[0] & 0x03, 2, 2); src++; } } break; case CODEC_ID_ADPCM_SWF: { GetBitContext gb; const int *table; int k0, signmask, nb_bits, count; int size = buf_size*8; init_get_bits(&gb, buf, size); //read bits & initial values nb_bits = get_bits(&gb, 2)+2; //av_log(NULL,AV_LOG_INFO,"nb_bits: %d\n", nb_bits); table = swf_index_tables[nb_bits-2]; k0 = 1 << (nb_bits-2); signmask = 1 << (nb_bits-1); while (get_bits_count(&gb) <= size - 22*avctx->channels) { for (i = 0; i < avctx->channels; i++) { *samples++ = c->status[i].predictor = get_sbits(&gb, 16); c->status[i].step_index = get_bits(&gb, 6); } for (count = 0; get_bits_count(&gb) <= size - nb_bits*avctx->channels && count < 4095; count++) { int i; for (i = 0; i < avctx->channels; i++) { // similar to IMA adpcm int delta = get_bits(&gb, nb_bits); int step = step_table[c->status[i].step_index]; long vpdiff = 0; // vpdiff = (delta+0.5)*step/4 int k = k0; do { if (delta & k) vpdiff += step; step >>= 1; k >>= 1; } while(k); vpdiff += step; if (delta & signmask) c->status[i].predictor -= vpdiff; else c->status[i].predictor += vpdiff; c->status[i].step_index += table[delta & (~signmask)]; c->status[i].step_index = av_clip(c->status[i].step_index, 0, 88); c->status[i].predictor = av_clip_int16(c->status[i].predictor); *samples++ = c->status[i].predictor; if (samples >= samples_end) { av_log(avctx, AV_LOG_ERROR, "allocated output buffer is too small\n"); return -1; } } } } src += buf_size; break; } case CODEC_ID_ADPCM_YAMAHA: while (src < buf + buf_size) { if (st) { *samples++ = adpcm_yamaha_expand_nibble(&c->status[0], src[0] & 0x0F); *samples++ = adpcm_yamaha_expand_nibble(&c->status[1], (src[0] >> 4) & 0x0F); } else { *samples++ = adpcm_yamaha_expand_nibble(&c->status[0], src[0] & 0x0F); *samples++ = adpcm_yamaha_expand_nibble(&c->status[0], (src[0] >> 4) & 0x0F); } src++; } break; case CODEC_ID_ADPCM_THP: { int table[2][16]; unsigned int samplecnt; int prev[2][2]; int ch; if (buf_size < 80) { av_log(avctx, AV_LOG_ERROR, "frame too small\n"); return -1; } src+=4; samplecnt = bytestream_get_be32(&src); for (i = 0; i < 32; i++) table[0][i] = (int16_t)bytestream_get_be16(&src); /* Initialize the previous sample. */ for (i = 0; i < 4; i++) prev[0][i] = (int16_t)bytestream_get_be16(&src); if (samplecnt >= (samples_end - samples) / (st + 1)) { av_log(avctx, AV_LOG_ERROR, "allocated output buffer is too small\n"); return -1; } for (ch = 0; ch <= st; ch++) { samples = (unsigned short *) data + ch; /* Read in every sample for this channel. */ for (i = 0; i < samplecnt / 14; i++) { int index = (*src >> 4) & 7; unsigned int exp = 28 - (*src++ & 15); int factor1 = table[ch][index * 2]; int factor2 = table[ch][index * 2 + 1]; /* Decode 14 samples. */ for (n = 0; n < 14; n++) { int32_t sampledat; if(n&1) sampledat= *src++ <<28; else sampledat= (*src&0xF0)<<24; sampledat = ((prev[ch][0]*factor1 + prev[ch][1]*factor2) >> 11) + (sampledat>>exp); *samples = av_clip_int16(sampledat); prev[ch][1] = prev[ch][0]; prev[ch][0] = *samples++; /* In case of stereo, skip one sample, this sample is for the other channel. */ samples += st; } } } /* In the previous loop, in case stereo is used, samples is increased exactly one time too often. */ samples -= st; break; } default: return -1; } *data_size = (uint8_t *)samples - (uint8_t *)data; return src - buf; }


static void ff_h264_idct_add16intra_sse2(uint8_t *dst, const int *block_offset, DCTELEM *block, int stride, const uint8_t nnzc[6*8]){ int i; for(i=0; i<16; i+=2){ if(nnzc[ scan8[i+0] ]|nnzc[ scan8[i+1] ]) ff_x264_add8x4_idct_sse2 (dst + block_offset[i], block + i*16, stride); else if(block[i*16]|block[i*16+16]) ff_h264_idct_dc_add8_mmx2(dst + block_offset[i], block + i*16, stride); } }


int swr_init(SwrContext *s){ s->in_buffer_index= 0; s->in_buffer_count= 0; s->resample_in_constraint= 0; free_temp(&s->postin); free_temp(&s->midbuf); free_temp(&s->preout); free_temp(&s->in_buffer); swr_audio_convert_free(&s-> in_convert); swr_audio_convert_free(&s->out_convert); s-> in.planar= s-> in_sample_fmt >= 0x100; s->out.planar= s->out_sample_fmt >= 0x100; s-> in_sample_fmt &= 0xFF; s->out_sample_fmt &= 0xFF; //We assume AVOptions checked the various values and the defaults where allowed if( s->int_sample_fmt != AV_SAMPLE_FMT_S16 &&s->int_sample_fmt != AV_SAMPLE_FMT_FLT){ av_log(s, AV_LOG_ERROR, "Requested sample format %s is not supported internally, only float & S16 is supported\n", av_get_sample_fmt_name(s->int_sample_fmt)); return AVERROR(EINVAL); } //FIXME should we allow/support using FLT on material that doesnt need it ? if(s->in_sample_fmt <= AV_SAMPLE_FMT_S16 || s->int_sample_fmt==AV_SAMPLE_FMT_S16){ s->int_sample_fmt= AV_SAMPLE_FMT_S16; }else s->int_sample_fmt= AV_SAMPLE_FMT_FLT; if (s->out_sample_rate!=s->in_sample_rate || (s->flags & SWR_FLAG_RESAMPLE)){ s->resample = swr_resample_init(s->resample, s->out_sample_rate, s->in_sample_rate, 16, 10, 0, 0.8); }else swr_resample_free(&s->resample); if(s->int_sample_fmt != AV_SAMPLE_FMT_S16 && s->resample){ av_log(s, AV_LOG_ERROR, "Resampling only supported with internal s16 currently\n"); //FIXME return -1; } if(!s-> in_ch_layout) s-> in_ch_layout= guess_layout(s->in.ch_count); if(!s->out_ch_layout) s->out_ch_layout= guess_layout(s->out.ch_count); s->rematrix= s->out_ch_layout !=s->in_ch_layout; #define RSC 1 //FIXME finetune if(!s-> in.ch_count) s-> in.ch_count= av_get_channel_layout_nb_channels(s-> in_ch_layout); if(!s->out.ch_count) s->out.ch_count= av_get_channel_layout_nb_channels(s->out_ch_layout); av_assert0(s-> in.ch_count); av_assert0(s->out.ch_count); s->resample_first= RSC*s->out.ch_count/s->in.ch_count - RSC < s->out_sample_rate/(float)s-> in_sample_rate - 1.0; s-> in.bps= av_get_bits_per_sample_fmt(s-> in_sample_fmt)/8; s->int_bps= av_get_bits_per_sample_fmt(s->int_sample_fmt)/8; s->out.bps= av_get_bits_per_sample_fmt(s->out_sample_fmt)/8; s->in_convert = swr_audio_convert_alloc(s->int_sample_fmt, s-> in_sample_fmt, s-> in.ch_count, 0); s->out_convert= swr_audio_convert_alloc(s->out_sample_fmt, s->int_sample_fmt, s->out.ch_count, 0); s->postin= s->in; s->preout= s->out; s->midbuf= s->in; s->in_buffer= s->in; if(!s->resample_first){ s->midbuf.ch_count= s->out.ch_count; s->in_buffer.ch_count = s->out.ch_count; } s->in_buffer.bps = s->postin.bps = s->midbuf.bps = s->preout.bps = s->int_bps; s->in_buffer.planar = s->postin.planar = s->midbuf.planar = s->preout.planar = 1; if(s->rematrix && swr_rematrix_init(s)<0) return -1; return 0; }