tcg_target_ulong tcg_qemu_tb_exec(CPUArchState *env, uint8_t *tb_ptr) { tcg_target_ulong next_tb = 0; tci_reg[TCG_AREG0] = (tcg_target_ulong)env; assert(tb_ptr); for (;;) { #if defined(GETPC) tci_tb_ptr = (uintptr_t)tb_ptr; #endif TCGOpcode opc = tb_ptr[0]; #if !defined(NDEBUG) uint8_t op_size = tb_ptr[1]; uint8_t *old_code_ptr = tb_ptr; #endif tcg_target_ulong t0; tcg_target_ulong t1; tcg_target_ulong t2; tcg_target_ulong label; TCGCond condition; target_ulong taddr; #ifndef CONFIG_SOFTMMU tcg_target_ulong host_addr; #endif uint8_t tmp8; uint16_t tmp16; uint32_t tmp32; uint64_t tmp64; #if TCG_TARGET_REG_BITS == 32 uint64_t v64; #endif /* Skip opcode and size entry. */ tb_ptr += 2; switch (opc) { case INDEX_op_end: case INDEX_op_nop: break; case INDEX_op_nop1: case INDEX_op_nop2: case INDEX_op_nop3: case INDEX_op_nopn: case INDEX_op_discard: TODO(); break; case INDEX_op_set_label: TODO(); break; case INDEX_op_call: t0 = tci_read_ri(&tb_ptr); #if TCG_TARGET_REG_BITS == 32 tmp64 = ((helper_function)t0)(tci_read_reg(TCG_REG_R0), tci_read_reg(TCG_REG_R1), tci_read_reg(TCG_REG_R2), tci_read_reg(TCG_REG_R3), tci_read_reg(TCG_REG_R5), tci_read_reg(TCG_REG_R6), tci_read_reg(TCG_REG_R7), tci_read_reg(TCG_REG_R8), tci_read_reg(TCG_REG_R9), tci_read_reg(TCG_REG_R10)); tci_write_reg(TCG_REG_R0, tmp64); tci_write_reg(TCG_REG_R1, tmp64 >> 32); #else tmp64 = ((helper_function)t0)(tci_read_reg(TCG_REG_R0), tci_read_reg(TCG_REG_R1), tci_read_reg(TCG_REG_R2), tci_read_reg(TCG_REG_R3), tci_read_reg(TCG_REG_R5)); tci_write_reg(TCG_REG_R0, tmp64); #endif break; case INDEX_op_br: label = tci_read_label(&tb_ptr); assert(tb_ptr == old_code_ptr + op_size); tb_ptr = (uint8_t *)label; continue; case INDEX_op_setcond_i32: t0 = *tb_ptr++; t1 = tci_read_r32(&tb_ptr); t2 = tci_read_ri32(&tb_ptr); condition = *tb_ptr++; tci_write_reg32(t0, tci_compare32(t1, t2, condition)); break; #if TCG_TARGET_REG_BITS == 32 case INDEX_op_setcond2_i32: t0 = *tb_ptr++; tmp64 = tci_read_r64(&tb_ptr); v64 = tci_read_ri64(&tb_ptr); condition = *tb_ptr++; tci_write_reg32(t0, tci_compare64(tmp64, v64, condition)); break; #elif TCG_TARGET_REG_BITS == 64 case INDEX_op_setcond_i64: t0 = *tb_ptr++; t1 = tci_read_r64(&tb_ptr); t2 = tci_read_ri64(&tb_ptr); condition = *tb_ptr++; tci_write_reg64(t0, tci_compare64(t1, t2, condition)); break; #endif case INDEX_op_mov_i32: t0 = *tb_ptr++; t1 = tci_read_r32(&tb_ptr); tci_write_reg32(t0, t1); break; case INDEX_op_movi_i32: t0 = *tb_ptr++; t1 = tci_read_i32(&tb_ptr); tci_write_reg32(t0, t1); break; /* Load/store operations (32 bit). */ case INDEX_op_ld8u_i32: t0 = *tb_ptr++; t1 = tci_read_r(&tb_ptr); t2 = tci_read_s32(&tb_ptr); tci_write_reg8(t0, *(uint8_t *)(t1 + t2)); break; case INDEX_op_ld8s_i32: case INDEX_op_ld16u_i32: TODO(); break; case INDEX_op_ld16s_i32: TODO(); break; case INDEX_op_ld_i32: t0 = *tb_ptr++; t1 = tci_read_r(&tb_ptr); t2 = tci_read_s32(&tb_ptr); tci_write_reg32(t0, *(uint32_t *)(t1 + t2)); break; case INDEX_op_st8_i32: t0 = tci_read_r8(&tb_ptr); t1 = tci_read_r(&tb_ptr); t2 = tci_read_s32(&tb_ptr); *(uint8_t *)(t1 + t2) = t0; break; case INDEX_op_st16_i32: t0 = tci_read_r16(&tb_ptr); t1 = tci_read_r(&tb_ptr); t2 = tci_read_s32(&tb_ptr); *(uint16_t *)(t1 + t2) = t0; break; case INDEX_op_st_i32: t0 = tci_read_r32(&tb_ptr); t1 = tci_read_r(&tb_ptr); t2 = tci_read_s32(&tb_ptr); *(uint32_t *)(t1 + t2) = t0; break; /* Arithmetic operations (32 bit). */ case INDEX_op_add_i32: t0 = *tb_ptr++; t1 = tci_read_ri32(&tb_ptr); t2 = tci_read_ri32(&tb_ptr); tci_write_reg32(t0, t1 + t2); break; case INDEX_op_sub_i32: t0 = *tb_ptr++; t1 = tci_read_ri32(&tb_ptr); t2 = tci_read_ri32(&tb_ptr); tci_write_reg32(t0, t1 - t2); break; case INDEX_op_mul_i32: t0 = *tb_ptr++; t1 = tci_read_ri32(&tb_ptr); t2 = tci_read_ri32(&tb_ptr); tci_write_reg32(t0, t1 * t2); break; #if TCG_TARGET_HAS_div_i32 case INDEX_op_div_i32: t0 = *tb_ptr++; t1 = tci_read_ri32(&tb_ptr); t2 = tci_read_ri32(&tb_ptr); tci_write_reg32(t0, (int32_t)t1 / (int32_t)t2); break; case INDEX_op_divu_i32: t0 = *tb_ptr++; t1 = tci_read_ri32(&tb_ptr); t2 = tci_read_ri32(&tb_ptr); tci_write_reg32(t0, t1 / t2); break; case INDEX_op_rem_i32: t0 = *tb_ptr++; t1 = tci_read_ri32(&tb_ptr); t2 = tci_read_ri32(&tb_ptr); tci_write_reg32(t0, (int32_t)t1 % (int32_t)t2); break; case INDEX_op_remu_i32: t0 = *tb_ptr++; t1 = tci_read_ri32(&tb_ptr); t2 = tci_read_ri32(&tb_ptr); tci_write_reg32(t0, t1 % t2); break; #elif TCG_TARGET_HAS_div2_i32 case INDEX_op_div2_i32: case INDEX_op_divu2_i32: TODO(); break; #endif case INDEX_op_and_i32: t0 = *tb_ptr++; t1 = tci_read_ri32(&tb_ptr); t2 = tci_read_ri32(&tb_ptr); tci_write_reg32(t0, t1 & t2); break; case INDEX_op_or_i32: t0 = *tb_ptr++; t1 = tci_read_ri32(&tb_ptr); t2 = tci_read_ri32(&tb_ptr); tci_write_reg32(t0, t1 | t2); break; case INDEX_op_xor_i32: t0 = *tb_ptr++; t1 = tci_read_ri32(&tb_ptr); t2 = tci_read_ri32(&tb_ptr); tci_write_reg32(t0, t1 ^ t2); break; /* Shift/rotate operations (32 bit). */ case INDEX_op_shl_i32: t0 = *tb_ptr++; t1 = tci_read_ri32(&tb_ptr); t2 = tci_read_ri32(&tb_ptr); tci_write_reg32(t0, t1 << t2); break; case INDEX_op_shr_i32: t0 = *tb_ptr++; t1 = tci_read_ri32(&tb_ptr); t2 = tci_read_ri32(&tb_ptr); tci_write_reg32(t0, t1 >> t2); break; case INDEX_op_sar_i32: t0 = *tb_ptr++; t1 = tci_read_ri32(&tb_ptr); t2 = tci_read_ri32(&tb_ptr); tci_write_reg32(t0, ((int32_t)t1 >> t2)); break; #if TCG_TARGET_HAS_rot_i32 case INDEX_op_rotl_i32: t0 = *tb_ptr++; t1 = tci_read_ri32(&tb_ptr); t2 = tci_read_ri32(&tb_ptr); tci_write_reg32(t0, (t1 << t2) | (t1 >> (32 - t2))); break; case INDEX_op_rotr_i32: t0 = *tb_ptr++; t1 = tci_read_ri32(&tb_ptr); t2 = tci_read_ri32(&tb_ptr); tci_write_reg32(t0, (t1 >> t2) | (t1 << (32 - t2))); break; #endif #if TCG_TARGET_HAS_deposit_i32 case INDEX_op_deposit_i32: t0 = *tb_ptr++; t1 = tci_read_r32(&tb_ptr); t2 = tci_read_r32(&tb_ptr); tmp16 = *tb_ptr++; tmp8 = *tb_ptr++; tmp32 = (((1 << tmp8) - 1) << tmp16); tci_write_reg32(t0, (t1 & ~tmp32) | ((t2 << tmp16) & tmp32)); break; #endif case INDEX_op_brcond_i32: t0 = tci_read_r32(&tb_ptr); t1 = tci_read_ri32(&tb_ptr); condition = *tb_ptr++; label = tci_read_label(&tb_ptr); if (tci_compare32(t0, t1, condition)) { assert(tb_ptr == old_code_ptr + op_size); tb_ptr = (uint8_t *)label; continue; } break; #if TCG_TARGET_REG_BITS == 32 case INDEX_op_add2_i32: t0 = *tb_ptr++; t1 = *tb_ptr++; tmp64 = tci_read_r64(&tb_ptr); tmp64 += tci_read_r64(&tb_ptr); tci_write_reg64(t1, t0, tmp64); break; case INDEX_op_sub2_i32: t0 = *tb_ptr++; t1 = *tb_ptr++; tmp64 = tci_read_r64(&tb_ptr); tmp64 -= tci_read_r64(&tb_ptr); tci_write_reg64(t1, t0, tmp64); break; case INDEX_op_brcond2_i32: tmp64 = tci_read_r64(&tb_ptr); v64 = tci_read_ri64(&tb_ptr); condition = *tb_ptr++; label = tci_read_label(&tb_ptr); if (tci_compare64(tmp64, v64, condition)) { assert(tb_ptr == old_code_ptr + op_size); tb_ptr = (uint8_t *)label; continue; } break; case INDEX_op_mulu2_i32: t0 = *tb_ptr++; t1 = *tb_ptr++; t2 = tci_read_r32(&tb_ptr); tmp64 = tci_read_r32(&tb_ptr); tci_write_reg64(t1, t0, t2 * tmp64); break; #endif /* TCG_TARGET_REG_BITS == 32 */ #if TCG_TARGET_HAS_ext8s_i32 case INDEX_op_ext8s_i32: t0 = *tb_ptr++; t1 = tci_read_r8s(&tb_ptr); tci_write_reg32(t0, t1); break; #endif #if TCG_TARGET_HAS_ext16s_i32 case INDEX_op_ext16s_i32: t0 = *tb_ptr++; t1 = tci_read_r16s(&tb_ptr); tci_write_reg32(t0, t1); break; #endif #if TCG_TARGET_HAS_ext8u_i32 case INDEX_op_ext8u_i32: t0 = *tb_ptr++; t1 = tci_read_r8(&tb_ptr); tci_write_reg32(t0, t1); break; #endif #if TCG_TARGET_HAS_ext16u_i32 case INDEX_op_ext16u_i32: t0 = *tb_ptr++; t1 = tci_read_r16(&tb_ptr); tci_write_reg32(t0, t1); break; #endif #if TCG_TARGET_HAS_bswap16_i32 case INDEX_op_bswap16_i32: t0 = *tb_ptr++; t1 = tci_read_r16(&tb_ptr); tci_write_reg32(t0, bswap16(t1)); break; #endif #if TCG_TARGET_HAS_bswap32_i32 case INDEX_op_bswap32_i32: t0 = *tb_ptr++; t1 = tci_read_r32(&tb_ptr); tci_write_reg32(t0, bswap32(t1)); break; #endif #if TCG_TARGET_HAS_not_i32 case INDEX_op_not_i32: t0 = *tb_ptr++; t1 = tci_read_r32(&tb_ptr); tci_write_reg32(t0, ~t1); break; #endif #if TCG_TARGET_HAS_neg_i32 case INDEX_op_neg_i32: t0 = *tb_ptr++; t1 = tci_read_r32(&tb_ptr); tci_write_reg32(t0, -t1); break; #endif #if TCG_TARGET_REG_BITS == 64 case INDEX_op_mov_i64: t0 = *tb_ptr++; t1 = tci_read_r64(&tb_ptr); tci_write_reg64(t0, t1); break; case INDEX_op_movi_i64: t0 = *tb_ptr++; t1 = tci_read_i64(&tb_ptr); tci_write_reg64(t0, t1); break; /* Load/store operations (64 bit). */ case INDEX_op_ld8u_i64: t0 = *tb_ptr++; t1 = tci_read_r(&tb_ptr); t2 = tci_read_s32(&tb_ptr); tci_write_reg8(t0, *(uint8_t *)(t1 + t2)); break; case INDEX_op_ld8s_i64: case INDEX_op_ld16u_i64: case INDEX_op_ld16s_i64: TODO(); break; case INDEX_op_ld32u_i64: t0 = *tb_ptr++; t1 = tci_read_r(&tb_ptr); t2 = tci_read_s32(&tb_ptr); tci_write_reg32(t0, *(uint32_t *)(t1 + t2)); break; case INDEX_op_ld32s_i64: t0 = *tb_ptr++; t1 = tci_read_r(&tb_ptr); t2 = tci_read_s32(&tb_ptr); tci_write_reg32s(t0, *(int32_t *)(t1 + t2)); break; case INDEX_op_ld_i64: t0 = *tb_ptr++; t1 = tci_read_r(&tb_ptr); t2 = tci_read_s32(&tb_ptr); tci_write_reg64(t0, *(uint64_t *)(t1 + t2)); break; case INDEX_op_st8_i64: t0 = tci_read_r8(&tb_ptr); t1 = tci_read_r(&tb_ptr); t2 = tci_read_s32(&tb_ptr); *(uint8_t *)(t1 + t2) = t0; break; case INDEX_op_st16_i64: t0 = tci_read_r16(&tb_ptr); t1 = tci_read_r(&tb_ptr); t2 = tci_read_s32(&tb_ptr); *(uint16_t *)(t1 + t2) = t0; break; case INDEX_op_st32_i64: t0 = tci_read_r32(&tb_ptr); t1 = tci_read_r(&tb_ptr); t2 = tci_read_s32(&tb_ptr); *(uint32_t *)(t1 + t2) = t0; break; case INDEX_op_st_i64: t0 = tci_read_r64(&tb_ptr); t1 = tci_read_r(&tb_ptr); t2 = tci_read_s32(&tb_ptr); *(uint64_t *)(t1 + t2) = t0; break; /* Arithmetic operations (64 bit). */ case INDEX_op_add_i64: t0 = *tb_ptr++; t1 = tci_read_ri64(&tb_ptr); t2 = tci_read_ri64(&tb_ptr); tci_write_reg64(t0, t1 + t2); break; case INDEX_op_sub_i64: t0 = *tb_ptr++; t1 = tci_read_ri64(&tb_ptr); t2 = tci_read_ri64(&tb_ptr); tci_write_reg64(t0, t1 - t2); break; case INDEX_op_mul_i64: t0 = *tb_ptr++; t1 = tci_read_ri64(&tb_ptr); t2 = tci_read_ri64(&tb_ptr); tci_write_reg64(t0, t1 * t2); break; #if TCG_TARGET_HAS_div_i64 case INDEX_op_div_i64: case INDEX_op_divu_i64: case INDEX_op_rem_i64: case INDEX_op_remu_i64: TODO(); break; #elif TCG_TARGET_HAS_div2_i64 case INDEX_op_div2_i64: case INDEX_op_divu2_i64: TODO(); break; #endif case INDEX_op_and_i64: t0 = *tb_ptr++; t1 = tci_read_ri64(&tb_ptr); t2 = tci_read_ri64(&tb_ptr); tci_write_reg64(t0, t1 & t2); break; case INDEX_op_or_i64: t0 = *tb_ptr++; t1 = tci_read_ri64(&tb_ptr); t2 = tci_read_ri64(&tb_ptr); tci_write_reg64(t0, t1 | t2); break; case INDEX_op_xor_i64: t0 = *tb_ptr++; t1 = tci_read_ri64(&tb_ptr); t2 = tci_read_ri64(&tb_ptr); tci_write_reg64(t0, t1 ^ t2); break; /* Shift/rotate operations (64 bit). */ case INDEX_op_shl_i64: t0 = *tb_ptr++; t1 = tci_read_ri64(&tb_ptr); t2 = tci_read_ri64(&tb_ptr); tci_write_reg64(t0, t1 << t2); break; case INDEX_op_shr_i64: t0 = *tb_ptr++; t1 = tci_read_ri64(&tb_ptr); t2 = tci_read_ri64(&tb_ptr); tci_write_reg64(t0, t1 >> t2); break; case INDEX_op_sar_i64: t0 = *tb_ptr++; t1 = tci_read_ri64(&tb_ptr); t2 = tci_read_ri64(&tb_ptr); tci_write_reg64(t0, ((int64_t)t1 >> t2)); break; #if TCG_TARGET_HAS_rot_i64 case INDEX_op_rotl_i64: case INDEX_op_rotr_i64: TODO(); break; #endif #if TCG_TARGET_HAS_deposit_i64 case INDEX_op_deposit_i64: t0 = *tb_ptr++; t1 = tci_read_r64(&tb_ptr); t2 = tci_read_r64(&tb_ptr); tmp16 = *tb_ptr++; tmp8 = *tb_ptr++; tmp64 = (((1ULL << tmp8) - 1) << tmp16); tci_write_reg64(t0, (t1 & ~tmp64) | ((t2 << tmp16) & tmp64)); break; #endif case INDEX_op_brcond_i64: t0 = tci_read_r64(&tb_ptr); t1 = tci_read_ri64(&tb_ptr); condition = *tb_ptr++; label = tci_read_label(&tb_ptr); if (tci_compare64(t0, t1, condition)) { assert(tb_ptr == old_code_ptr + op_size); tb_ptr = (uint8_t *)label; continue; } break; #if TCG_TARGET_HAS_ext8u_i64 case INDEX_op_ext8u_i64: t0 = *tb_ptr++; t1 = tci_read_r8(&tb_ptr); tci_write_reg64(t0, t1); break; #endif #if TCG_TARGET_HAS_ext8s_i64 case INDEX_op_ext8s_i64: t0 = *tb_ptr++; t1 = tci_read_r8s(&tb_ptr); tci_write_reg64(t0, t1); break; #endif #if TCG_TARGET_HAS_ext16s_i64 case INDEX_op_ext16s_i64: t0 = *tb_ptr++; t1 = tci_read_r16s(&tb_ptr); tci_write_reg64(t0, t1); break; #endif #if TCG_TARGET_HAS_ext16u_i64 case INDEX_op_ext16u_i64: t0 = *tb_ptr++; t1 = tci_read_r16(&tb_ptr); tci_write_reg64(t0, t1); break; #endif #if TCG_TARGET_HAS_ext32s_i64 case INDEX_op_ext32s_i64: t0 = *tb_ptr++; t1 = tci_read_r32s(&tb_ptr); tci_write_reg64(t0, t1); break; #endif #if TCG_TARGET_HAS_ext32u_i64 case INDEX_op_ext32u_i64: t0 = *tb_ptr++; t1 = tci_read_r32(&tb_ptr); tci_write_reg64(t0, t1); break; #endif #if TCG_TARGET_HAS_bswap16_i64 case INDEX_op_bswap16_i64: TODO(); t0 = *tb_ptr++; t1 = tci_read_r16(&tb_ptr); tci_write_reg64(t0, bswap16(t1)); break; #endif #if TCG_TARGET_HAS_bswap32_i64 case INDEX_op_bswap32_i64: t0 = *tb_ptr++; t1 = tci_read_r32(&tb_ptr); tci_write_reg64(t0, bswap32(t1)); break; #endif #if TCG_TARGET_HAS_bswap64_i64 case INDEX_op_bswap64_i64: t0 = *tb_ptr++; t1 = tci_read_r64(&tb_ptr); tci_write_reg64(t0, bswap64(t1)); break; #endif #if TCG_TARGET_HAS_not_i64 case INDEX_op_not_i64: t0 = *tb_ptr++; t1 = tci_read_r64(&tb_ptr); tci_write_reg64(t0, ~t1); break; #endif #if TCG_TARGET_HAS_neg_i64 case INDEX_op_neg_i64: t0 = *tb_ptr++; t1 = tci_read_r64(&tb_ptr); tci_write_reg64(t0, -t1); break; #endif #endif /* TCG_TARGET_REG_BITS == 64 */ /* QEMU specific operations. */ #if TARGET_LONG_BITS > TCG_TARGET_REG_BITS case INDEX_op_debug_insn_start: TODO(); break; #else case INDEX_op_debug_insn_start: TODO(); break; #endif case INDEX_op_exit_tb: next_tb = *(uint64_t *)tb_ptr; goto exit; break; case INDEX_op_goto_tb: t0 = tci_read_i32(&tb_ptr); assert(tb_ptr == old_code_ptr + op_size); tb_ptr += (int32_t)t0; continue; case INDEX_op_qemu_ld8u: t0 = *tb_ptr++; taddr = tci_read_ulong(&tb_ptr); #ifdef CONFIG_SOFTMMU tmp8 = helper_ldb_mmu(env, taddr, tci_read_i(&tb_ptr)); #else host_addr = (tcg_target_ulong)taddr; assert(taddr == host_addr); tmp8 = *(uint8_t *)(host_addr + GUEST_BASE); #endif tci_write_reg8(t0, tmp8); break; case INDEX_op_qemu_ld8s: t0 = *tb_ptr++; taddr = tci_read_ulong(&tb_ptr); #ifdef CONFIG_SOFTMMU tmp8 = helper_ldb_mmu(env, taddr, tci_read_i(&tb_ptr)); #else host_addr = (tcg_target_ulong)taddr; assert(taddr == host_addr); tmp8 = *(uint8_t *)(host_addr + GUEST_BASE); #endif tci_write_reg8s(t0, tmp8); break; case INDEX_op_qemu_ld16u: t0 = *tb_ptr++; taddr = tci_read_ulong(&tb_ptr); #ifdef CONFIG_SOFTMMU tmp16 = helper_ldw_mmu(env, taddr, tci_read_i(&tb_ptr)); #else host_addr = (tcg_target_ulong)taddr; assert(taddr == host_addr); tmp16 = tswap16(*(uint16_t *)(host_addr + GUEST_BASE)); #endif tci_write_reg16(t0, tmp16); break; case INDEX_op_qemu_ld16s: t0 = *tb_ptr++; taddr = tci_read_ulong(&tb_ptr); #ifdef CONFIG_SOFTMMU tmp16 = helper_ldw_mmu(env, taddr, tci_read_i(&tb_ptr)); #else host_addr = (tcg_target_ulong)taddr; assert(taddr == host_addr); tmp16 = tswap16(*(uint16_t *)(host_addr + GUEST_BASE)); #endif tci_write_reg16s(t0, tmp16); break; #if TCG_TARGET_REG_BITS == 64 case INDEX_op_qemu_ld32u: t0 = *tb_ptr++; taddr = tci_read_ulong(&tb_ptr); #ifdef CONFIG_SOFTMMU tmp32 = helper_ldl_mmu(env, taddr, tci_read_i(&tb_ptr)); #else host_addr = (tcg_target_ulong)taddr; assert(taddr == host_addr); tmp32 = tswap32(*(uint32_t *)(host_addr + GUEST_BASE)); #endif tci_write_reg32(t0, tmp32); break; case INDEX_op_qemu_ld32s: t0 = *tb_ptr++; taddr = tci_read_ulong(&tb_ptr); #ifdef CONFIG_SOFTMMU tmp32 = helper_ldl_mmu(env, taddr, tci_read_i(&tb_ptr)); #else host_addr = (tcg_target_ulong)taddr; assert(taddr == host_addr); tmp32 = tswap32(*(uint32_t *)(host_addr + GUEST_BASE)); #endif tci_write_reg32s(t0, tmp32); break; #endif /* TCG_TARGET_REG_BITS == 64 */ case INDEX_op_qemu_ld32: t0 = *tb_ptr++; taddr = tci_read_ulong(&tb_ptr); #ifdef CONFIG_SOFTMMU tmp32 = helper_ldl_mmu(env, taddr, tci_read_i(&tb_ptr)); #else host_addr = (tcg_target_ulong)taddr; assert(taddr == host_addr); tmp32 = tswap32(*(uint32_t *)(host_addr + GUEST_BASE)); #endif tci_write_reg32(t0, tmp32); break; case INDEX_op_qemu_ld64: t0 = *tb_ptr++; #if TCG_TARGET_REG_BITS == 32 t1 = *tb_ptr++; #endif taddr = tci_read_ulong(&tb_ptr); #ifdef CONFIG_SOFTMMU tmp64 = helper_ldq_mmu(env, taddr, tci_read_i(&tb_ptr)); #else host_addr = (tcg_target_ulong)taddr; assert(taddr == host_addr); tmp64 = tswap64(*(uint64_t *)(host_addr + GUEST_BASE)); #endif tci_write_reg(t0, tmp64); #if TCG_TARGET_REG_BITS == 32 tci_write_reg(t1, tmp64 >> 32); #endif break; case INDEX_op_qemu_st8: t0 = tci_read_r8(&tb_ptr); taddr = tci_read_ulong(&tb_ptr); #ifdef CONFIG_SOFTMMU t2 = tci_read_i(&tb_ptr); helper_stb_mmu(env, taddr, t0, t2); #else host_addr = (tcg_target_ulong)taddr; assert(taddr == host_addr); *(uint8_t *)(host_addr + GUEST_BASE) = t0; #endif break; case INDEX_op_qemu_st16: t0 = tci_read_r16(&tb_ptr); taddr = tci_read_ulong(&tb_ptr); #ifdef CONFIG_SOFTMMU t2 = tci_read_i(&tb_ptr); helper_stw_mmu(env, taddr, t0, t2); #else host_addr = (tcg_target_ulong)taddr; assert(taddr == host_addr); *(uint16_t *)(host_addr + GUEST_BASE) = tswap16(t0); #endif break; case INDEX_op_qemu_st32: t0 = tci_read_r32(&tb_ptr); taddr = tci_read_ulong(&tb_ptr); #ifdef CONFIG_SOFTMMU t2 = tci_read_i(&tb_ptr); helper_stl_mmu(env, taddr, t0, t2); #else host_addr = (tcg_target_ulong)taddr; assert(taddr == host_addr); *(uint32_t *)(host_addr + GUEST_BASE) = tswap32(t0); #endif break; case INDEX_op_qemu_st64: tmp64 = tci_read_r64(&tb_ptr); taddr = tci_read_ulong(&tb_ptr); #ifdef CONFIG_SOFTMMU t2 = tci_read_i(&tb_ptr); helper_stq_mmu(env, taddr, tmp64, t2); #else host_addr = (tcg_target_ulong)taddr; assert(taddr == host_addr); *(uint64_t *)(host_addr + GUEST_BASE) = tswap64(tmp64); #endif break; default: TODO(); break; } assert(tb_ptr == old_code_ptr + op_size); } exit: return next_tb; }


static void do_commit(void) { int i; for (i = 0; i < MAX_DISKS; i++) { if (bs_table[i]) bdrv_commit(bs_table[i]); } }


static int v9fs_do_mknod(V9fsState *s, V9fsString *path, mode_t mode, dev_t dev) { return s->ops->mknod(&s->ctx, path->data, mode, dev); }


static uint64_t g364fb_ctrl_read(void *opaque, target_phys_addr_t addr, unsigned int size) { G364State *s = opaque; uint32_t val; if (addr >= REG_CURS_PAT && addr < REG_CURS_PAT + 0x1000) { /* cursor pattern */ int idx = (addr - REG_CURS_PAT) >> 3; val = s->cursor[idx]; } else if (addr >= REG_CURS_PAL && addr < REG_CURS_PAL + 0x18) { /* cursor palette */ int idx = (addr - REG_CURS_PAL) >> 3; val = ((uint32_t)s->cursor_palette[idx][0] << 16); val |= ((uint32_t)s->cursor_palette[idx][1] << 8); val |= ((uint32_t)s->cursor_palette[idx][2] << 0); } else { switch (addr) { case REG_DISPLAY: val = s->width / 4; break; case REG_VDISPLAY: val = s->height * 2; break; case REG_CTLA: val = s->ctla; break; default: { error_report("g364: invalid read at [" TARGET_FMT_plx "]", addr); val = 0; break; } } } trace_g364fb_read(addr, val); return val; }


static void vncws_send_handshake_response(VncState *vs, const char* key) { char combined_key[WS_CLIENT_KEY_LEN + WS_GUID_LEN + 1]; unsigned char hash[SHA1_DIGEST_LEN]; size_t hash_size = sizeof(hash); char *accept = NULL, *response = NULL; gnutls_datum_t in; int ret; g_strlcpy(combined_key, key, WS_CLIENT_KEY_LEN + 1); g_strlcat(combined_key, WS_GUID, WS_CLIENT_KEY_LEN + WS_GUID_LEN + 1); /* hash and encode it */ in.data = (void *)combined_key; in.size = WS_CLIENT_KEY_LEN + WS_GUID_LEN; ret = gnutls_fingerprint(GNUTLS_DIG_SHA1, &in, hash, &hash_size); if (ret == GNUTLS_E_SUCCESS && hash_size <= SHA1_DIGEST_LEN) { accept = g_base64_encode(hash, hash_size); } if (accept == NULL) { VNC_DEBUG("Hashing Websocket combined key failed\n"); vnc_client_error(vs); return; } response = g_strdup_printf(WS_HANDSHAKE, accept); vnc_client_write_buf(vs, (const uint8_t *)response, strlen(response)); g_free(accept); g_free(response); vs->encode_ws = 1; vnc_init_state(vs); }


av_cold int ff_ffv1_init_slice_state(FFV1Context *f, FFV1Context *fs) { int j; fs->plane_count = f->plane_count; fs->transparency = f->transparency; for (j = 0; j < f->plane_count; j++) { PlaneContext *const p = &fs->plane[j]; if (fs->ac) { if (!p->state) p->state = av_malloc_array(p->context_count, CONTEXT_SIZE * sizeof(uint8_t)); if (!p->state) return AVERROR(ENOMEM); } else { if (!p->vlc_state) p->vlc_state = av_malloc_array(p->context_count, sizeof(VlcState)); if (!p->vlc_state) return AVERROR(ENOMEM); } } if (fs->ac > 1) { //FIXME only redo if state_transition changed for (j = 1; j < 256; j++) { fs->c. one_state[ j] = f->state_transition[j]; fs->c.zero_state[256 - j] = 256 - fs->c.one_state[j]; } } return 0; }


static void spitz_init(int ram_size, int vga_ram_size, int boot_device, DisplayState *ds, const char **fd_filename, int snapshot, const char *kernel_filename, const char *kernel_cmdline, const char *initrd_filename, const char *cpu_model) { spitz_common_init(ram_size, vga_ram_size, ds, kernel_filename, kernel_cmdline, initrd_filename, spitz, 0x2c9); }


static int vcr1_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *avpkt) { const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; VCR1Context *const a = avctx->priv_data; AVFrame *const p = data; const uint8_t *bytestream = buf; int i, x, y, ret; if ((ret = ff_get_buffer(avctx, p, 0)) < 0) { av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n"); return ret; } p->pict_type = AV_PICTURE_TYPE_I; p->key_frame = 1; if (buf_size < 32) for (i = 0; i < 16; i++) { a->delta[i] = *bytestream++; bytestream++; buf_size--; } for (y = 0; y < avctx->height; y++) { int offset; uint8_t *luma = &p->data[0][y * p->linesize[0]]; if ((y & 3) == 0) { uint8_t *cb = &p->data[1][(y >> 2) * p->linesize[1]]; uint8_t *cr = &p->data[2][(y >> 2) * p->linesize[2]]; for (i = 0; i < 4; i++) a->offset[i] = *bytestream++; offset = a->offset[0] - a->delta[bytestream[2] & 0xF]; for (x = 0; x < avctx->width; x += 4) { luma[0] = offset += a->delta[bytestream[2] & 0xF]; luma[1] = offset += a->delta[bytestream[2] >> 4]; luma[2] = offset += a->delta[bytestream[0] & 0xF]; luma[3] = offset += a->delta[bytestream[0] >> 4]; luma += 4; *cb++ = bytestream[3]; *cr++ = bytestream[1]; bytestream += 4; buf_size -= 4; } } else { if (buf_size < avctx->width / 2) offset = a->offset[y & 3] - a->delta[bytestream[2] & 0xF]; for (x = 0; x < avctx->width; x += 8) { luma[0] = offset += a->delta[bytestream[2] & 0xF]; luma[1] = offset += a->delta[bytestream[2] >> 4]; luma[2] = offset += a->delta[bytestream[3] & 0xF]; luma[3] = offset += a->delta[bytestream[3] >> 4]; luma[4] = offset += a->delta[bytestream[0] & 0xF]; luma[5] = offset += a->delta[bytestream[0] >> 4]; luma[6] = offset += a->delta[bytestream[1] & 0xF]; luma[7] = offset += a->delta[bytestream[1] >> 4]; luma += 8; bytestream += 4; buf_size -= 4; } } } *got_frame = 1; return buf_size; packet_small: av_log(avctx, AV_LOG_ERROR, "Input packet too small.\n"); return AVERROR_INVALIDDATA; }


long disas_insn(DisasContext *s, uint8_t *pc_start) { int b, prefixes, aflag, dflag; int shift, ot; int modrm, reg, rm, mod, reg_addr, op, opreg, offset_addr, val; unsigned int next_eip; s->pc = pc_start; prefixes = 0; aflag = s->code32; dflag = s->code32; s->override = -1; next_byte: b = ldub(s->pc); s->pc++; /* check prefixes */ switch (b) { case 0xf3: prefixes |= PREFIX_REPZ; goto next_byte; case 0xf2: prefixes |= PREFIX_REPNZ; goto next_byte; case 0xf0: prefixes |= PREFIX_LOCK; goto next_byte; case 0x2e: s->override = R_CS; goto next_byte; case 0x36: s->override = R_SS; goto next_byte; case 0x3e: s->override = R_DS; goto next_byte; case 0x26: s->override = R_ES; goto next_byte; case 0x64: s->override = R_FS; goto next_byte; case 0x65: s->override = R_GS; goto next_byte; case 0x66: prefixes |= PREFIX_DATA; goto next_byte; case 0x67: prefixes |= PREFIX_ADR; goto next_byte; case 0x9b: prefixes |= PREFIX_FWAIT; goto next_byte; } if (prefixes & PREFIX_DATA) dflag ^= 1; if (prefixes & PREFIX_ADR) aflag ^= 1; s->prefix = prefixes; s->aflag = aflag; s->dflag = dflag; /* lock generation */ if (prefixes & PREFIX_LOCK) gen_op_lock(); /* now check op code */ reswitch: switch(b) { case 0x0f: /**************************/ /* extended op code */ b = ldub(s->pc++) | 0x100; goto reswitch; /**************************/ /* arith & logic */ case 0x00 ... 0x05: case 0x08 ... 0x0d: case 0x10 ... 0x15: case 0x18 ... 0x1d: case 0x20 ... 0x25: case 0x28 ... 0x2d: case 0x30 ... 0x35: case 0x38 ... 0x3d: { int op, f, val; op = (b >> 3) & 7; f = (b >> 1) & 3; if ((b & 1) == 0) ot = OT_BYTE; else ot = dflag ? OT_LONG : OT_WORD; switch(f) { case 0: /* OP Ev, Gv */ modrm = ldub(s->pc++); reg = ((modrm >> 3) & 7) + OR_EAX; mod = (modrm >> 6) & 3; rm = modrm & 7; if (mod != 3) { gen_lea_modrm(s, modrm, &reg_addr, &offset_addr); gen_op_ld_T0_A0[ot](); opreg = OR_TMP0; } else { opreg = OR_EAX + rm; } gen_op(s, op, ot, opreg, reg); if (mod != 3 && op != 7) { gen_op_st_T0_A0[ot](); } break; case 1: /* OP Gv, Ev */ modrm = ldub(s->pc++); mod = (modrm >> 6) & 3; reg = ((modrm >> 3) & 7) + OR_EAX; rm = modrm & 7; if (mod != 3) { gen_lea_modrm(s, modrm, &reg_addr, &offset_addr); gen_op_ld_T1_A0[ot](); opreg = OR_TMP1; } else { opreg = OR_EAX + rm; } gen_op(s, op, ot, reg, opreg); break; case 2: /* OP A, Iv */ val = insn_get(s, ot); gen_opi(s, op, ot, OR_EAX, val); break; } } break; case 0x80: /* GRP1 */ case 0x81: case 0x83: { int val; if ((b & 1) == 0) ot = OT_BYTE; else ot = dflag ? OT_LONG : OT_WORD; modrm = ldub(s->pc++); mod = (modrm >> 6) & 3; rm = modrm & 7; op = (modrm >> 3) & 7; if (mod != 3) { gen_lea_modrm(s, modrm, &reg_addr, &offset_addr); gen_op_ld_T0_A0[ot](); opreg = OR_TMP0; } else { opreg = rm + OR_EAX; } switch(b) { default: case 0x80: case 0x81: val = insn_get(s, ot); break; case 0x83: val = (int8_t)insn_get(s, OT_BYTE); break; } gen_opi(s, op, ot, opreg, val); if (op != 7 && mod != 3) { gen_op_st_T0_A0[ot](); } } break; /**************************/ /* inc, dec, and other misc arith */ case 0x40 ... 0x47: /* inc Gv */ ot = dflag ? OT_LONG : OT_WORD; gen_inc(s, ot, OR_EAX + (b & 7), 1); break; case 0x48 ... 0x4f: /* dec Gv */ ot = dflag ? OT_LONG : OT_WORD; gen_inc(s, ot, OR_EAX + (b & 7), -1); break; case 0xf6: /* GRP3 */ case 0xf7: if ((b & 1) == 0) ot = OT_BYTE; else ot = dflag ? OT_LONG : OT_WORD; modrm = ldub(s->pc++); mod = (modrm >> 6) & 3; rm = modrm & 7; op = (modrm >> 3) & 7; if (mod != 3) { gen_lea_modrm(s, modrm, &reg_addr, &offset_addr); gen_op_ld_T0_A0[ot](); } else { gen_op_mov_TN_reg[ot][0][rm](); } switch(op) { case 0: /* test */ val = insn_get(s, ot); gen_op_movl_T1_im(val); gen_op_testl_T0_T1_cc(); s->cc_op = CC_OP_LOGICB + ot; break; case 2: /* not */ gen_op_notl_T0(); if (mod != 3) { gen_op_st_T0_A0[ot](); } else { gen_op_mov_reg_T0[ot][rm](); } break; case 3: /* neg */ gen_op_negl_T0_cc(); if (mod != 3) { gen_op_st_T0_A0[ot](); } else { gen_op_mov_reg_T0[ot][rm](); } s->cc_op = CC_OP_SUBB + ot; break; case 4: /* mul */ switch(ot) { case OT_BYTE: gen_op_mulb_AL_T0(); break; case OT_WORD: gen_op_mulw_AX_T0(); break; default: case OT_LONG: gen_op_mull_EAX_T0(); break; } s->cc_op = CC_OP_MUL; break; case 5: /* imul */ switch(ot) { case OT_BYTE: gen_op_imulb_AL_T0(); break; case OT_WORD: gen_op_imulw_AX_T0(); break; default: case OT_LONG: gen_op_imull_EAX_T0(); break; } s->cc_op = CC_OP_MUL; break; case 6: /* div */ switch(ot) { case OT_BYTE: gen_op_divb_AL_T0(); break; case OT_WORD: gen_op_divw_AX_T0(); break; default: case OT_LONG: gen_op_divl_EAX_T0(); break; } break; case 7: /* idiv */ switch(ot) { case OT_BYTE: gen_op_idivb_AL_T0(); break; case OT_WORD: gen_op_idivw_AX_T0(); break; default: case OT_LONG: gen_op_idivl_EAX_T0(); break; } break; default: goto illegal_op; } break; case 0xfe: /* GRP4 */ case 0xff: /* GRP5 */ if ((b & 1) == 0) ot = OT_BYTE; else ot = dflag ? OT_LONG : OT_WORD; modrm = ldub(s->pc++); mod = (modrm >> 6) & 3; rm = modrm & 7; op = (modrm >> 3) & 7; if (op >= 2 && b == 0xfe) { goto illegal_op; } if (mod != 3) { gen_lea_modrm(s, modrm, &reg_addr, &offset_addr); if (op != 3 && op != 5) gen_op_ld_T0_A0[ot](); } else { gen_op_mov_TN_reg[ot][0][rm](); } switch(op) { case 0: /* inc Ev */ gen_inc(s, ot, OR_TMP0, 1); if (mod != 3) gen_op_st_T0_A0[ot](); else gen_op_mov_reg_T0[ot][rm](); break; case 1: /* dec Ev */ gen_inc(s, ot, OR_TMP0, -1); if (mod != 3) gen_op_st_T0_A0[ot](); else gen_op_mov_reg_T0[ot][rm](); break; case 2: /* call Ev */ /* XXX: optimize if memory (no and is necessary) */ if (s->dflag == 0) gen_op_andl_T0_ffff(); gen_op_jmp_T0(); next_eip = s->pc - s->cs_base; gen_op_movl_T0_im(next_eip); gen_push_T0(s); s->is_jmp = 1; break; case 3: /* lcall Ev */ /* push return segment + offset */ gen_op_movl_T0_seg(R_CS); gen_push_T0(s); next_eip = s->pc - s->cs_base; gen_op_movl_T0_im(next_eip); gen_push_T0(s); gen_op_ld_T1_A0[ot](); gen_op_addl_A0_im(1 << (ot - OT_WORD + 1)); gen_op_lduw_T0_A0(); gen_movl_seg_T0(s, R_CS); gen_op_movl_T0_T1(); gen_op_jmp_T0(); s->is_jmp = 1; break; case 4: /* jmp Ev */ if (s->dflag == 0) gen_op_andl_T0_ffff(); gen_op_jmp_T0(); s->is_jmp = 1; break; case 5: /* ljmp Ev */ gen_op_ld_T1_A0[ot](); gen_op_addl_A0_im(1 << (ot - OT_WORD + 1)); gen_op_lduw_T0_A0(); gen_movl_seg_T0(s, R_CS); gen_op_movl_T0_T1(); gen_op_jmp_T0(); s->is_jmp = 1; break; case 6: /* push Ev */ gen_push_T0(s); break; default: goto illegal_op; } break; case 0x84: /* test Ev, Gv */ case 0x85: if ((b & 1) == 0) ot = OT_BYTE; else ot = dflag ? OT_LONG : OT_WORD; modrm = ldub(s->pc++); mod = (modrm >> 6) & 3; rm = modrm & 7; reg = (modrm >> 3) & 7; gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0); gen_op_mov_TN_reg[ot][1][reg + OR_EAX](); gen_op_testl_T0_T1_cc(); s->cc_op = CC_OP_LOGICB + ot; break; case 0xa8: /* test eAX, Iv */ case 0xa9: if ((b & 1) == 0) ot = OT_BYTE; else ot = dflag ? OT_LONG : OT_WORD; val = insn_get(s, ot); gen_op_mov_TN_reg[ot][0][OR_EAX](); gen_op_movl_T1_im(val); gen_op_testl_T0_T1_cc(); s->cc_op = CC_OP_LOGICB + ot; break; case 0x98: /* CWDE/CBW */ if (dflag) gen_op_movswl_EAX_AX(); else gen_op_movsbw_AX_AL(); break; case 0x99: /* CDQ/CWD */ if (dflag) gen_op_movslq_EDX_EAX(); else gen_op_movswl_DX_AX(); break; case 0x1af: /* imul Gv, Ev */ case 0x69: /* imul Gv, Ev, I */ case 0x6b: ot = dflag ? OT_LONG : OT_WORD; modrm = ldub(s->pc++); reg = ((modrm >> 3) & 7) + OR_EAX; gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0); if (b == 0x69) { val = insn_get(s, ot); gen_op_movl_T1_im(val); } else if (b == 0x6b) { val = insn_get(s, OT_BYTE); gen_op_movl_T1_im(val); } else { gen_op_mov_TN_reg[ot][1][reg](); } if (ot == OT_LONG) { gen_op_imull_T0_T1(); } else { gen_op_imulw_T0_T1(); } gen_op_mov_reg_T0[ot][reg](); s->cc_op = CC_OP_MUL; break; case 0x1c0: case 0x1c1: /* xadd Ev, Gv */ if ((b & 1) == 0) ot = OT_BYTE; else ot = dflag ? OT_LONG : OT_WORD; modrm = ldub(s->pc++); reg = (modrm >> 3) & 7; mod = (modrm >> 6) & 3; if (mod == 3) { rm = modrm & 7; gen_op_mov_TN_reg[ot][0][reg](); gen_op_mov_TN_reg[ot][1][rm](); gen_op_addl_T0_T1_cc(); gen_op_mov_reg_T0[ot][rm](); gen_op_mov_reg_T1[ot][reg](); } else { gen_lea_modrm(s, modrm, &reg_addr, &offset_addr); gen_op_mov_TN_reg[ot][0][reg](); gen_op_ld_T1_A0[ot](); gen_op_addl_T0_T1_cc(); gen_op_st_T0_A0[ot](); gen_op_mov_reg_T1[ot][reg](); } s->cc_op = CC_OP_ADDB + ot; break; case 0x1b0: case 0x1b1: /* cmpxchg Ev, Gv */ if ((b & 1) == 0) ot = OT_BYTE; else ot = dflag ? OT_LONG : OT_WORD; modrm = ldub(s->pc++); reg = (modrm >> 3) & 7; mod = (modrm >> 6) & 3; gen_op_mov_TN_reg[ot][1][reg](); if (mod == 3) { rm = modrm & 7; gen_op_mov_TN_reg[ot][0][rm](); gen_op_cmpxchg_T0_T1_EAX_cc[ot](); gen_op_mov_reg_T0[ot][rm](); } else { gen_lea_modrm(s, modrm, &reg_addr, &offset_addr); gen_op_ld_T0_A0[ot](); gen_op_cmpxchg_T0_T1_EAX_cc[ot](); gen_op_st_T0_A0[ot](); } s->cc_op = CC_OP_SUBB + ot; break; case 0x1c7: /* cmpxchg8b */ modrm = ldub(s->pc++); mod = (modrm >> 6) & 3; if (mod == 3) goto illegal_op; if (s->cc_op != CC_OP_DYNAMIC) gen_op_set_cc_op(s->cc_op); gen_lea_modrm(s, modrm, &reg_addr, &offset_addr); gen_op_cmpxchg8b(); s->cc_op = CC_OP_EFLAGS; break; /**************************/ /* push/pop */ case 0x50 ... 0x57: /* push */ gen_op_mov_TN_reg[OT_LONG][0][b & 7](); gen_push_T0(s); break; case 0x58 ... 0x5f: /* pop */ ot = dflag ? OT_LONG : OT_WORD; gen_pop_T0(s); gen_op_mov_reg_T0[ot][b & 7](); gen_pop_update(s); break; case 0x60: /* pusha */ gen_pusha(s); break; case 0x61: /* popa */ gen_popa(s); break; case 0x68: /* push Iv */ case 0x6a: ot = dflag ? OT_LONG : OT_WORD; if (b == 0x68) val = insn_get(s, ot); else val = (int8_t)insn_get(s, OT_BYTE); gen_op_movl_T0_im(val); gen_push_T0(s); break; case 0x8f: /* pop Ev */ ot = dflag ? OT_LONG : OT_WORD; modrm = ldub(s->pc++); gen_pop_T0(s); gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1); gen_pop_update(s); break; case 0xc8: /* enter */ { int level; val = lduw(s->pc); s->pc += 2; level = ldub(s->pc++); gen_enter(s, val, level); } break; case 0xc9: /* leave */ /* XXX: exception not precise (ESP is update before potential exception) */ if (s->ss32) { gen_op_mov_TN_reg[OT_LONG][0][R_EBP](); gen_op_mov_reg_T0[OT_LONG][R_ESP](); } else { gen_op_mov_TN_reg[OT_WORD][0][R_EBP](); gen_op_mov_reg_T0[OT_WORD][R_ESP](); } gen_pop_T0(s); ot = dflag ? OT_LONG : OT_WORD; gen_op_mov_reg_T0[ot][R_EBP](); gen_pop_update(s); break; case 0x06: /* push es */ case 0x0e: /* push cs */ case 0x16: /* push ss */ case 0x1e: /* push ds */ gen_op_movl_T0_seg(b >> 3); gen_push_T0(s); break; case 0x1a0: /* push fs */ case 0x1a8: /* push gs */ gen_op_movl_T0_seg((b >> 3) & 7); gen_push_T0(s); break; case 0x07: /* pop es */ case 0x17: /* pop ss */ case 0x1f: /* pop ds */ gen_pop_T0(s); gen_movl_seg_T0(s, b >> 3); gen_pop_update(s); break; case 0x1a1: /* pop fs */ case 0x1a9: /* pop gs */ gen_pop_T0(s); gen_movl_seg_T0(s, (b >> 3) & 7); gen_pop_update(s); break; /**************************/ /* mov */ case 0x88: case 0x89: /* mov Gv, Ev */ if ((b & 1) == 0) ot = OT_BYTE; else ot = dflag ? OT_LONG : OT_WORD; modrm = ldub(s->pc++); reg = (modrm >> 3) & 7; /* generate a generic store */ gen_ldst_modrm(s, modrm, ot, OR_EAX + reg, 1); break; case 0xc6: case 0xc7: /* mov Ev, Iv */ if ((b & 1) == 0) ot = OT_BYTE; else ot = dflag ? OT_LONG : OT_WORD; modrm = ldub(s->pc++); mod = (modrm >> 6) & 3; if (mod != 3) gen_lea_modrm(s, modrm, &reg_addr, &offset_addr); val = insn_get(s, ot); gen_op_movl_T0_im(val); if (mod != 3) gen_op_st_T0_A0[ot](); else gen_op_mov_reg_T0[ot][modrm & 7](); break; case 0x8a: case 0x8b: /* mov Ev, Gv */ if ((b & 1) == 0) ot = OT_BYTE; else ot = dflag ? OT_LONG : OT_WORD; modrm = ldub(s->pc++); reg = (modrm >> 3) & 7; gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0); gen_op_mov_reg_T0[ot][reg](); break; case 0x8e: /* mov seg, Gv */ ot = dflag ? OT_LONG : OT_WORD; modrm = ldub(s->pc++); reg = (modrm >> 3) & 7; gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0); if (reg >= 6 || reg == R_CS) goto illegal_op; gen_movl_seg_T0(s, reg); break; case 0x8c: /* mov Gv, seg */ ot = dflag ? OT_LONG : OT_WORD; modrm = ldub(s->pc++); reg = (modrm >> 3) & 7; if (reg >= 6) goto illegal_op; gen_op_movl_T0_seg(reg); gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1); break; case 0x1b6: /* movzbS Gv, Eb */ case 0x1b7: /* movzwS Gv, Eb */ case 0x1be: /* movsbS Gv, Eb */ case 0x1bf: /* movswS Gv, Eb */ { int d_ot; /* d_ot is the size of destination */ d_ot = dflag + OT_WORD; /* ot is the size of source */ ot = (b & 1) + OT_BYTE; modrm = ldub(s->pc++); reg = ((modrm >> 3) & 7) + OR_EAX; mod = (modrm >> 6) & 3; rm = modrm & 7; if (mod == 3) { gen_op_mov_TN_reg[ot][0][rm](); switch(ot | (b & 8)) { case OT_BYTE: gen_op_movzbl_T0_T0(); break; case OT_BYTE | 8: gen_op_movsbl_T0_T0(); break; case OT_WORD: gen_op_movzwl_T0_T0(); break; default: case OT_WORD | 8: gen_op_movswl_T0_T0(); break; } gen_op_mov_reg_T0[d_ot][reg](); } else { gen_lea_modrm(s, modrm, &reg_addr, &offset_addr); if (b & 8) { gen_op_lds_T0_A0[ot](); } else { gen_op_ldu_T0_A0[ot](); } gen_op_mov_reg_T0[d_ot][reg](); } } break; case 0x8d: /* lea */ ot = dflag ? OT_LONG : OT_WORD; modrm = ldub(s->pc++); reg = (modrm >> 3) & 7; /* we must ensure that no segment is added */ s->override = -1; val = s->addseg; s->addseg = 0; gen_lea_modrm(s, modrm, &reg_addr, &offset_addr); s->addseg = val; gen_op_mov_reg_A0[ot - OT_WORD][reg](); break; case 0xa0: /* mov EAX, Ov */ case 0xa1: case 0xa2: /* mov Ov, EAX */ case 0xa3: if ((b & 1) == 0) ot = OT_BYTE; else ot = dflag ? OT_LONG : OT_WORD; if (s->aflag) offset_addr = insn_get(s, OT_LONG); else offset_addr = insn_get(s, OT_WORD); gen_op_movl_A0_im(offset_addr); /* handle override */ { int override, must_add_seg; must_add_seg = s->addseg; if (s->override >= 0) { override = s->override; must_add_seg = 1; } else { override = R_DS; } if (must_add_seg) { gen_op_addl_A0_seg(offsetof(CPUX86State,seg_cache[override].base)); } } if ((b & 2) == 0) { gen_op_ld_T0_A0[ot](); gen_op_mov_reg_T0[ot][R_EAX](); } else { gen_op_mov_TN_reg[ot][0][R_EAX](); gen_op_st_T0_A0[ot](); } break; case 0xd7: /* xlat */ gen_op_movl_A0_reg[R_EBX](); gen_op_addl_A0_AL(); if (s->aflag == 0) gen_op_andl_A0_ffff(); /* handle override */ { int override, must_add_seg; must_add_seg = s->addseg; override = R_DS; if (s->override >= 0) { override = s->override; must_add_seg = 1; } else { override = R_DS; } if (must_add_seg) { gen_op_addl_A0_seg(offsetof(CPUX86State,seg_cache[override].base)); } } gen_op_ldub_T0_A0(); gen_op_mov_reg_T0[OT_BYTE][R_EAX](); break; case 0xb0 ... 0xb7: /* mov R, Ib */ val = insn_get(s, OT_BYTE); gen_op_movl_T0_im(val); gen_op_mov_reg_T0[OT_BYTE][b & 7](); break; case 0xb8 ... 0xbf: /* mov R, Iv */ ot = dflag ? OT_LONG : OT_WORD; val = insn_get(s, ot); reg = OR_EAX + (b & 7); gen_op_movl_T0_im(val); gen_op_mov_reg_T0[ot][reg](); break; case 0x91 ... 0x97: /* xchg R, EAX */ ot = dflag ? OT_LONG : OT_WORD; reg = b & 7; rm = R_EAX; goto do_xchg_reg; case 0x86: case 0x87: /* xchg Ev, Gv */ if ((b & 1) == 0) ot = OT_BYTE; else ot = dflag ? OT_LONG : OT_WORD; modrm = ldub(s->pc++); reg = (modrm >> 3) & 7; mod = (modrm >> 6) & 3; if (mod == 3) { rm = modrm & 7; do_xchg_reg: gen_op_mov_TN_reg[ot][0][reg](); gen_op_mov_TN_reg[ot][1][rm](); gen_op_mov_reg_T0[ot][rm](); gen_op_mov_reg_T1[ot][reg](); } else { gen_lea_modrm(s, modrm, &reg_addr, &offset_addr); gen_op_mov_TN_reg[ot][0][reg](); /* for xchg, lock is implicit */ if (!(prefixes & PREFIX_LOCK)) gen_op_lock(); gen_op_ld_T1_A0[ot](); gen_op_st_T0_A0[ot](); if (!(prefixes & PREFIX_LOCK)) gen_op_unlock(); gen_op_mov_reg_T1[ot][reg](); } break; case 0xc4: /* les Gv */ op = R_ES; goto do_lxx; case 0xc5: /* lds Gv */ op = R_DS; goto do_lxx; case 0x1b2: /* lss Gv */ op = R_SS; goto do_lxx; case 0x1b4: /* lfs Gv */ op = R_FS; goto do_lxx; case 0x1b5: /* lgs Gv */ op = R_GS; do_lxx: ot = dflag ? OT_LONG : OT_WORD; modrm = ldub(s->pc++); reg = (modrm >> 3) & 7; mod = (modrm >> 6) & 3; if (mod == 3) goto illegal_op; gen_lea_modrm(s, modrm, &reg_addr, &offset_addr); gen_op_ld_T1_A0[ot](); gen_op_addl_A0_im(1 << (ot - OT_WORD + 1)); /* load the segment first to handle exceptions properly */ gen_op_lduw_T0_A0(); gen_movl_seg_T0(s, op); /* then put the data */ gen_op_mov_reg_T1[ot][reg](); break; /************************/ /* shifts */ case 0xc0: case 0xc1: /* shift Ev,Ib */ shift = 2; grp2: { if ((b & 1) == 0) ot = OT_BYTE; else ot = dflag ? OT_LONG : OT_WORD; modrm = ldub(s->pc++); mod = (modrm >> 6) & 3; rm = modrm & 7; op = (modrm >> 3) & 7; if (mod != 3) { gen_lea_modrm(s, modrm, &reg_addr, &offset_addr); gen_op_ld_T0_A0[ot](); opreg = OR_TMP0; } else { opreg = rm + OR_EAX; } /* simpler op */ if (shift == 0) { gen_shift(s, op, ot, opreg, OR_ECX); } else { if (shift == 2) { shift = ldub(s->pc++); } gen_shifti(s, op, ot, opreg, shift); } if (mod != 3) { gen_op_st_T0_A0[ot](); } } break; case 0xd0: case 0xd1: /* shift Ev,1 */ shift = 1; goto grp2; case 0xd2: case 0xd3: /* shift Ev,cl */ shift = 0; goto grp2; case 0x1a4: /* shld imm */ op = 0; shift = 1; goto do_shiftd; case 0x1a5: /* shld cl */ op = 0; shift = 0; goto do_shiftd; case 0x1ac: /* shrd imm */ op = 1; shift = 1; goto do_shiftd; case 0x1ad: /* shrd cl */ op = 1; shift = 0; do_shiftd: ot = dflag ? OT_LONG : OT_WORD; modrm = ldub(s->pc++); mod = (modrm >> 6) & 3; rm = modrm & 7; reg = (modrm >> 3) & 7; if (mod != 3) { gen_lea_modrm(s, modrm, &reg_addr, &offset_addr); gen_op_ld_T0_A0[ot](); } else { gen_op_mov_TN_reg[ot][0][rm](); } gen_op_mov_TN_reg[ot][1][reg](); if (shift) { val = ldub(s->pc++); val &= 0x1f; if (val) { gen_op_shiftd_T0_T1_im_cc[ot - OT_WORD][op](val); if (op == 0 && ot != OT_WORD) s->cc_op = CC_OP_SHLB + ot; else s->cc_op = CC_OP_SARB + ot; } } else { if (s->cc_op != CC_OP_DYNAMIC) gen_op_set_cc_op(s->cc_op); gen_op_shiftd_T0_T1_ECX_cc[ot - OT_WORD][op](); s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */ } if (mod != 3) { gen_op_st_T0_A0[ot](); } else { gen_op_mov_reg_T0[ot][rm](); } break; /************************/ /* floats */ case 0xd8 ... 0xdf: modrm = ldub(s->pc++); mod = (modrm >> 6) & 3; rm = modrm & 7; op = ((b & 7) << 3) | ((modrm >> 3) & 7); if (mod != 3) { /* memory op */ gen_lea_modrm(s, modrm, &reg_addr, &offset_addr); switch(op) { case 0x00 ... 0x07: /* fxxxs */ case 0x10 ... 0x17: /* fixxxl */ case 0x20 ... 0x27: /* fxxxl */ case 0x30 ... 0x37: /* fixxx */ { int op1; op1 = op & 7; switch(op >> 4) { case 0: gen_op_flds_FT0_A0(); break; case 1: gen_op_fildl_FT0_A0(); break; case 2: gen_op_fldl_FT0_A0(); break; case 3: default: gen_op_fild_FT0_A0(); break; } gen_op_fp_arith_ST0_FT0[op1](); if (op1 == 3) { /* fcomp needs pop */ gen_op_fpop(); } } break; case 0x08: /* flds */ case 0x0a: /* fsts */ case 0x0b: /* fstps */ case 0x18: /* fildl */ case 0x1a: /* fistl */ case 0x1b: /* fistpl */ case 0x28: /* fldl */ case 0x2a: /* fstl */ case 0x2b: /* fstpl */ case 0x38: /* filds */ case 0x3a: /* fists */ case 0x3b: /* fistps */ switch(op & 7) { case 0: gen_op_fpush(); switch(op >> 4) { case 0: gen_op_flds_ST0_A0(); break; case 1: gen_op_fildl_ST0_A0(); break; case 2: gen_op_fldl_ST0_A0(); break; case 3: default: gen_op_fild_ST0_A0(); break; } break; default: switch(op >> 4) { case 0: gen_op_fsts_ST0_A0(); break; case 1: gen_op_fistl_ST0_A0(); break; case 2: gen_op_fstl_ST0_A0(); break; case 3: default: gen_op_fist_ST0_A0(); break; } if ((op & 7) == 3) gen_op_fpop(); break; } break; case 0x0d: /* fldcw mem */ gen_op_fldcw_A0(); break; case 0x0f: /* fnstcw mem */ gen_op_fnstcw_A0(); break; case 0x1d: /* fldt mem */ gen_op_fpush(); gen_op_fldt_ST0_A0(); break; case 0x1f: /* fstpt mem */ gen_op_fstt_ST0_A0(); gen_op_fpop(); break; case 0x2f: /* fnstsw mem */ gen_op_fnstsw_A0(); break; case 0x3c: /* fbld */ gen_op_fpush(); gen_op_fbld_ST0_A0(); break; case 0x3e: /* fbstp */ gen_op_fbst_ST0_A0(); gen_op_fpop(); break; case 0x3d: /* fildll */ gen_op_fpush(); gen_op_fildll_ST0_A0(); break; case 0x3f: /* fistpll */ gen_op_fistll_ST0_A0(); gen_op_fpop(); break; default: goto illegal_op; } } else { /* register float ops */ opreg = rm; switch(op) { case 0x08: /* fld sti */ gen_op_fpush(); gen_op_fmov_ST0_STN((opreg + 1) & 7); break; case 0x09: /* fxchg sti */ gen_op_fxchg_ST0_STN(opreg); break; case 0x0a: /* grp d9/2 */ switch(rm) { case 0: /* fnop */ break; default: goto illegal_op; } break; case 0x0c: /* grp d9/4 */ switch(rm) { case 0: /* fchs */ gen_op_fchs_ST0(); break; case 1: /* fabs */ gen_op_fabs_ST0(); break; case 4: /* ftst */ gen_op_fldz_FT0(); gen_op_fcom_ST0_FT0(); break; case 5: /* fxam */ gen_op_fxam_ST0(); break; default: goto illegal_op; } break; case 0x0d: /* grp d9/5 */ { switch(rm) { case 0: gen_op_fpush(); gen_op_fld1_ST0(); break; case 1: gen_op_fpush(); gen_op_fldl2t_ST0(); break; case 2: gen_op_fpush(); gen_op_fldl2e_ST0(); break; case 3: gen_op_fpush(); gen_op_fldpi_ST0(); break; case 4: gen_op_fpush(); gen_op_fldlg2_ST0(); break; case 5: gen_op_fpush(); gen_op_fldln2_ST0(); break; case 6: gen_op_fpush(); gen_op_fldz_ST0(); break; default: goto illegal_op; } } break; case 0x0e: /* grp d9/6 */ switch(rm) { case 0: /* f2xm1 */ gen_op_f2xm1(); break; case 1: /* fyl2x */ gen_op_fyl2x(); break; case 2: /* fptan */ gen_op_fptan(); break; case 3: /* fpatan */ gen_op_fpatan(); break; case 4: /* fxtract */ gen_op_fxtract(); break; case 5: /* fprem1 */ gen_op_fprem1(); break; case 6: /* fdecstp */ gen_op_fdecstp(); break; default: case 7: /* fincstp */ gen_op_fincstp(); break; } break; case 0x0f: /* grp d9/7 */ switch(rm) { case 0: /* fprem */ gen_op_fprem(); break; case 1: /* fyl2xp1 */ gen_op_fyl2xp1(); break; case 2: /* fsqrt */ gen_op_fsqrt(); break; case 3: /* fsincos */ gen_op_fsincos(); break; case 5: /* fscale */ gen_op_fscale(); break; case 4: /* frndint */ gen_op_frndint(); break; case 6: /* fsin */ gen_op_fsin(); break; default: case 7: /* fcos */ gen_op_fcos(); break; } break; case 0x00: case 0x01: case 0x04 ... 0x07: /* fxxx st, sti */ case 0x20: case 0x21: case 0x24 ... 0x27: /* fxxx sti, st */ case 0x30: case 0x31: case 0x34 ... 0x37: /* fxxxp sti, st */ { int op1; op1 = op & 7; if (op >= 0x20) { gen_op_fp_arith_STN_ST0[op1](opreg); if (op >= 0x30) gen_op_fpop(); } else { gen_op_fmov_FT0_STN(opreg); gen_op_fp_arith_ST0_FT0[op1](); } } break; case 0x02: /* fcom */ gen_op_fmov_FT0_STN(opreg); gen_op_fcom_ST0_FT0(); break; case 0x03: /* fcomp */ gen_op_fmov_FT0_STN(opreg); gen_op_fcom_ST0_FT0(); gen_op_fpop(); break; case 0x15: /* da/5 */ switch(rm) { case 1: /* fucompp */ gen_op_fmov_FT0_STN(1); gen_op_fucom_ST0_FT0(); gen_op_fpop(); gen_op_fpop(); break; default: goto illegal_op; } break; case 0x1c: switch(rm) { case 2: /* fclex */ gen_op_fclex(); break; case 3: /* fninit */ gen_op_fninit(); break; default: goto illegal_op; } break; case 0x2a: /* fst sti */ gen_op_fmov_STN_ST0(opreg); break; case 0x2b: /* fstp sti */ gen_op_fmov_STN_ST0(opreg); gen_op_fpop(); break; case 0x2c: /* fucom st(i) */ gen_op_fmov_FT0_STN(opreg); gen_op_fucom_ST0_FT0(); break; case 0x2d: /* fucomp st(i) */ gen_op_fmov_FT0_STN(opreg); gen_op_fucom_ST0_FT0(); gen_op_fpop(); break; case 0x33: /* de/3 */ switch(rm) { case 1: /* fcompp */ gen_op_fmov_FT0_STN(1); gen_op_fcom_ST0_FT0(); gen_op_fpop(); gen_op_fpop(); break; default: goto illegal_op; } break; case 0x3c: /* df/4 */ switch(rm) { case 0: gen_op_fnstsw_EAX(); break; default: goto illegal_op; } break; default: goto illegal_op; } } break; /************************/ /* string ops */ case 0xa4: /* movsS */ case 0xa5: if ((b & 1) == 0) ot = OT_BYTE; else ot = dflag ? OT_LONG : OT_WORD; if (prefixes & PREFIX_REPZ) { gen_string_ds(s, ot, gen_op_movs + 9); } else { gen_string_ds(s, ot, gen_op_movs); } break; case 0xaa: /* stosS */ case 0xab: if ((b & 1) == 0) ot = OT_BYTE; else ot = dflag ? OT_LONG : OT_WORD; if (prefixes & PREFIX_REPZ) { gen_string_es(s, ot, gen_op_stos + 9); } else { gen_string_es(s, ot, gen_op_stos); } break; case 0xac: /* lodsS */ case 0xad: if ((b & 1) == 0) ot = OT_BYTE; else ot = dflag ? OT_LONG : OT_WORD; if (prefixes & PREFIX_REPZ) { gen_string_ds(s, ot, gen_op_lods + 9); } else { gen_string_ds(s, ot, gen_op_lods); } break; case 0xae: /* scasS */ case 0xaf: if ((b & 1) == 0) ot = OT_BYTE; else ot = dflag ? OT_LONG : OT_WORD; if (prefixes & PREFIX_REPNZ) { if (s->cc_op != CC_OP_DYNAMIC) gen_op_set_cc_op(s->cc_op); gen_string_es(s, ot, gen_op_scas + 9 * 2); s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */ } else if (prefixes & PREFIX_REPZ) { if (s->cc_op != CC_OP_DYNAMIC) gen_op_set_cc_op(s->cc_op); gen_string_es(s, ot, gen_op_scas + 9); s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */ } else { gen_string_es(s, ot, gen_op_scas); s->cc_op = CC_OP_SUBB + ot; } break; case 0xa6: /* cmpsS */ case 0xa7: if ((b & 1) == 0) ot = OT_BYTE; else ot = dflag ? OT_LONG : OT_WORD; if (prefixes & PREFIX_REPNZ) { if (s->cc_op != CC_OP_DYNAMIC) gen_op_set_cc_op(s->cc_op); gen_string_ds(s, ot, gen_op_cmps + 9 * 2); s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */ } else if (prefixes & PREFIX_REPZ) { if (s->cc_op != CC_OP_DYNAMIC) gen_op_set_cc_op(s->cc_op); gen_string_ds(s, ot, gen_op_cmps + 9); s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */ } else { gen_string_ds(s, ot, gen_op_cmps); s->cc_op = CC_OP_SUBB + ot; } break; case 0x6c: /* insS */ case 0x6d: if (s->cpl > s->iopl || s->vm86) { /* NOTE: even for (E)CX = 0 the exception is raised */ gen_op_gpf(pc_start - s->cs_base); } else { if ((b & 1) == 0) ot = OT_BYTE; else ot = dflag ? OT_LONG : OT_WORD; if (prefixes & PREFIX_REPZ) { gen_string_es(s, ot, gen_op_ins + 9); } else { gen_string_es(s, ot, gen_op_ins); } } break; case 0x6e: /* outsS */ case 0x6f: if (s->cpl > s->iopl || s->vm86) { /* NOTE: even for (E)CX = 0 the exception is raised */ gen_op_gpf(pc_start - s->cs_base); } else { if ((b & 1) == 0) ot = OT_BYTE; else ot = dflag ? OT_LONG : OT_WORD; if (prefixes & PREFIX_REPZ) { gen_string_ds(s, ot, gen_op_outs + 9); } else { gen_string_ds(s, ot, gen_op_outs); } } break; /************************/ /* port I/O */ case 0xe4: case 0xe5: if (s->cpl > s->iopl || s->vm86) { gen_op_gpf(pc_start - s->cs_base); } else { if ((b & 1) == 0) ot = OT_BYTE; else ot = dflag ? OT_LONG : OT_WORD; val = ldub(s->pc++); gen_op_movl_T0_im(val); gen_op_in[ot](); gen_op_mov_reg_T1[ot][R_EAX](); } break; case 0xe6: case 0xe7: if (s->cpl > s->iopl || s->vm86) { gen_op_gpf(pc_start - s->cs_base); } else { if ((b & 1) == 0) ot = OT_BYTE; else ot = dflag ? OT_LONG : OT_WORD; val = ldub(s->pc++); gen_op_movl_T0_im(val); gen_op_mov_TN_reg[ot][1][R_EAX](); gen_op_out[ot](); } break; case 0xec: case 0xed: if (s->cpl > s->iopl || s->vm86) { gen_op_gpf(pc_start - s->cs_base); } else { if ((b & 1) == 0) ot = OT_BYTE; else ot = dflag ? OT_LONG : OT_WORD; gen_op_mov_TN_reg[OT_WORD][0][R_EDX](); gen_op_in[ot](); gen_op_mov_reg_T1[ot][R_EAX](); } break; case 0xee: case 0xef: if (s->cpl > s->iopl || s->vm86) { gen_op_gpf(pc_start - s->cs_base); } else { if ((b & 1) == 0) ot = OT_BYTE; else ot = dflag ? OT_LONG : OT_WORD; gen_op_mov_TN_reg[OT_WORD][0][R_EDX](); gen_op_mov_TN_reg[ot][1][R_EAX](); gen_op_out[ot](); } break; /************************/ /* control */ case 0xc2: /* ret im */ val = ldsw(s->pc); s->pc += 2; gen_pop_T0(s); if (s->ss32) gen_op_addl_ESP_im(val + (2 << s->dflag)); else gen_op_addw_ESP_im(val + (2 << s->dflag)); if (s->dflag == 0) gen_op_andl_T0_ffff(); gen_op_jmp_T0(); s->is_jmp = 1; break; case 0xc3: /* ret */ gen_pop_T0(s); gen_pop_update(s); if (s->dflag == 0) gen_op_andl_T0_ffff(); gen_op_jmp_T0(); s->is_jmp = 1; break; case 0xca: /* lret im */ /* XXX: not restartable */ val = ldsw(s->pc); s->pc += 2; /* pop offset */ gen_pop_T0(s); if (s->dflag == 0) gen_op_andl_T0_ffff(); gen_op_jmp_T0(); gen_pop_update(s); /* pop selector */ gen_pop_T0(s); gen_movl_seg_T0(s, R_CS); gen_pop_update(s); /* add stack offset */ if (s->ss32) gen_op_addl_ESP_im(val + (2 << s->dflag)); else gen_op_addw_ESP_im(val + (2 << s->dflag)); s->is_jmp = 1; break; case 0xcb: /* lret */ /* XXX: not restartable */ /* pop offset */ gen_pop_T0(s); if (s->dflag == 0) gen_op_andl_T0_ffff(); gen_op_jmp_T0(); gen_pop_update(s); /* pop selector */ gen_pop_T0(s); gen_movl_seg_T0(s, R_CS); gen_pop_update(s); s->is_jmp = 1; break; case 0xcf: /* iret */ /* XXX: not restartable */ /* pop offset */ gen_pop_T0(s); if (s->dflag == 0) gen_op_andl_T0_ffff(); gen_op_jmp_T0(); gen_pop_update(s); /* pop selector */ gen_pop_T0(s); gen_movl_seg_T0(s, R_CS); gen_pop_update(s); /* pop eflags */ gen_pop_T0(s); if (s->dflag) { if (s->vm86) gen_op_movl_eflags_T0_vm(pc_start - s->cs_base); else gen_op_movl_eflags_T0(); } else { if (s->vm86) gen_op_movw_eflags_T0_vm(pc_start - s->cs_base); else gen_op_movw_eflags_T0(); } gen_pop_update(s); s->cc_op = CC_OP_EFLAGS; s->is_jmp = 1; break; case 0xe8: /* call im */ { unsigned int next_eip; ot = dflag ? OT_LONG : OT_WORD; val = insn_get(s, ot); next_eip = s->pc - s->cs_base; val += next_eip; if (s->dflag == 0) val &= 0xffff; gen_op_movl_T0_im(next_eip); gen_push_T0(s); gen_op_jmp_im(val); s->is_jmp = 1; } break; case 0x9a: /* lcall im */ { unsigned int selector, offset; ot = dflag ? OT_LONG : OT_WORD; offset = insn_get(s, ot); selector = insn_get(s, OT_WORD); /* push return segment + offset */ gen_op_movl_T0_seg(R_CS); gen_push_T0(s); next_eip = s->pc - s->cs_base; gen_op_movl_T0_im(next_eip); gen_push_T0(s); /* change cs and pc */ gen_op_movl_T0_im(selector); gen_movl_seg_T0(s, R_CS); gen_op_jmp_im((unsigned long)offset); s->is_jmp = 1; } break; case 0xe9: /* jmp */ ot = dflag ? OT_LONG : OT_WORD; val = insn_get(s, ot); val += s->pc - s->cs_base; if (s->dflag == 0) val = val & 0xffff; gen_op_jmp_im(val); s->is_jmp = 1; break; case 0xea: /* ljmp im */ { unsigned int selector, offset; ot = dflag ? OT_LONG : OT_WORD; offset = insn_get(s, ot); selector = insn_get(s, OT_WORD); /* change cs and pc */ gen_op_movl_T0_im(selector); gen_movl_seg_T0(s, R_CS); gen_op_jmp_im((unsigned long)offset); s->is_jmp = 1; } break; case 0xeb: /* jmp Jb */ val = (int8_t)insn_get(s, OT_BYTE); val += s->pc - s->cs_base; if (s->dflag == 0) val = val & 0xffff; gen_op_jmp_im(val); s->is_jmp = 1; break; case 0x70 ... 0x7f: /* jcc Jb */ val = (int8_t)insn_get(s, OT_BYTE); goto do_jcc; case 0x180 ... 0x18f: /* jcc Jv */ if (dflag) { val = insn_get(s, OT_LONG); } else { val = (int16_t)insn_get(s, OT_WORD); } do_jcc: next_eip = s->pc - s->cs_base; val += next_eip; if (s->dflag == 0) val &= 0xffff; gen_jcc(s, b, val, next_eip); s->is_jmp = 1; break; case 0x190 ... 0x19f: /* setcc Gv */ modrm = ldub(s->pc++); gen_setcc(s, b); gen_ldst_modrm(s, modrm, OT_BYTE, OR_TMP0, 1); break; case 0x140 ... 0x14f: /* cmov Gv, Ev */ ot = dflag ? OT_LONG : OT_WORD; modrm = ldub(s->pc++); reg = (modrm >> 3) & 7; mod = (modrm >> 6) & 3; gen_setcc(s, b); if (mod != 3) { gen_lea_modrm(s, modrm, &reg_addr, &offset_addr); gen_op_ld_T1_A0[ot](); } else { rm = modrm & 7; gen_op_mov_TN_reg[ot][1][rm](); } gen_op_cmov_reg_T1_T0[ot - OT_WORD][reg](); break; /************************/ /* flags */ case 0x9c: /* pushf */ if (s->cc_op != CC_OP_DYNAMIC) gen_op_set_cc_op(s->cc_op); if (s->vm86) gen_op_movl_T0_eflags_vm(); else gen_op_movl_T0_eflags(); gen_push_T0(s); break; case 0x9d: /* popf */ gen_pop_T0(s); if (s->dflag) { if (s->vm86) gen_op_movl_eflags_T0_vm(pc_start - s->cs_base); else gen_op_movl_eflags_T0(); } else { if (s->vm86) gen_op_movw_eflags_T0_vm(pc_start - s->cs_base); else gen_op_movw_eflags_T0(); } gen_pop_update(s); s->cc_op = CC_OP_EFLAGS; break; case 0x9e: /* sahf */ gen_op_mov_TN_reg[OT_BYTE][0][R_AH](); if (s->cc_op != CC_OP_DYNAMIC) gen_op_set_cc_op(s->cc_op); gen_op_movb_eflags_T0(); s->cc_op = CC_OP_EFLAGS; break; case 0x9f: /* lahf */ if (s->cc_op != CC_OP_DYNAMIC) gen_op_set_cc_op(s->cc_op); gen_op_movl_T0_eflags(); gen_op_mov_reg_T0[OT_BYTE][R_AH](); break; case 0xf5: /* cmc */ if (s->cc_op != CC_OP_DYNAMIC) gen_op_set_cc_op(s->cc_op); gen_op_cmc(); s->cc_op = CC_OP_EFLAGS; break; case 0xf8: /* clc */ if (s->cc_op != CC_OP_DYNAMIC) gen_op_set_cc_op(s->cc_op); gen_op_clc(); s->cc_op = CC_OP_EFLAGS; break; case 0xf9: /* stc */ if (s->cc_op != CC_OP_DYNAMIC) gen_op_set_cc_op(s->cc_op); gen_op_stc(); s->cc_op = CC_OP_EFLAGS; break; case 0xfc: /* cld */ gen_op_cld(); break; case 0xfd: /* std */ gen_op_std(); break; /************************/ /* bit operations */ case 0x1ba: /* bt/bts/btr/btc Gv, im */ ot = dflag ? OT_LONG : OT_WORD; modrm = ldub(s->pc++); op = (modrm >> 3) & 7; mod = (modrm >> 6) & 3; rm = modrm & 7; if (mod != 3) { gen_lea_modrm(s, modrm, &reg_addr, &offset_addr); gen_op_ld_T0_A0[ot](); } else { gen_op_mov_TN_reg[ot][0][rm](); } /* load shift */ val = ldub(s->pc++); gen_op_movl_T1_im(val); if (op < 4) goto illegal_op; op -= 4; gen_op_btx_T0_T1_cc[ot - OT_WORD][op](); s->cc_op = CC_OP_SARB + ot; if (op != 0) { if (mod != 3) gen_op_st_T0_A0[ot](); else gen_op_mov_reg_T0[ot][rm](); } break; case 0x1a3: /* bt Gv, Ev */ op = 0; goto do_btx; case 0x1ab: /* bts */ op = 1; goto do_btx; case 0x1b3: /* btr */ op = 2; goto do_btx; case 0x1bb: /* btc */ op = 3; do_btx: ot = dflag ? OT_LONG : OT_WORD; modrm = ldub(s->pc++); reg = (modrm >> 3) & 7; mod = (modrm >> 6) & 3; rm = modrm & 7; gen_op_mov_TN_reg[OT_LONG][1][reg](); if (mod != 3) { gen_lea_modrm(s, modrm, &reg_addr, &offset_addr); /* specific case: we need to add a displacement */ if (ot == OT_WORD) gen_op_add_bitw_A0_T1(); else gen_op_add_bitl_A0_T1(); gen_op_ld_T0_A0[ot](); } else { gen_op_mov_TN_reg[ot][0][rm](); } gen_op_btx_T0_T1_cc[ot - OT_WORD][op](); s->cc_op = CC_OP_SARB + ot; if (op != 0) { if (mod != 3) gen_op_st_T0_A0[ot](); else gen_op_mov_reg_T0[ot][rm](); } break; case 0x1bc: /* bsf */ case 0x1bd: /* bsr */ ot = dflag ? OT_LONG : OT_WORD; modrm = ldub(s->pc++); reg = (modrm >> 3) & 7; gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0); gen_op_bsx_T0_cc[ot - OT_WORD][b & 1](); /* NOTE: we always write back the result. Intel doc says it is undefined if T0 == 0 */ gen_op_mov_reg_T0[ot][reg](); s->cc_op = CC_OP_LOGICB + ot; break; /************************/ /* bcd */ case 0x27: /* daa */ if (s->cc_op != CC_OP_DYNAMIC) gen_op_set_cc_op(s->cc_op); gen_op_daa(); s->cc_op = CC_OP_EFLAGS; break; case 0x2f: /* das */ if (s->cc_op != CC_OP_DYNAMIC) gen_op_set_cc_op(s->cc_op); gen_op_das(); s->cc_op = CC_OP_EFLAGS; break; case 0x37: /* aaa */ if (s->cc_op != CC_OP_DYNAMIC) gen_op_set_cc_op(s->cc_op); gen_op_aaa(); s->cc_op = CC_OP_EFLAGS; break; case 0x3f: /* aas */ if (s->cc_op != CC_OP_DYNAMIC) gen_op_set_cc_op(s->cc_op); gen_op_aas(); s->cc_op = CC_OP_EFLAGS; break; case 0xd4: /* aam */ val = ldub(s->pc++); gen_op_aam(val); s->cc_op = CC_OP_LOGICB; break; case 0xd5: /* aad */ val = ldub(s->pc++); gen_op_aad(val); s->cc_op = CC_OP_LOGICB; break; /************************/ /* misc */ case 0x90: /* nop */ break; case 0xcc: /* int3 */ gen_op_int3((long)pc_start); s->is_jmp = 1; break; case 0xcd: /* int N */ val = ldub(s->pc++); gen_op_int_im(val, pc_start - s->cs_base); s->is_jmp = 1; break; case 0xce: /* into */ if (s->cc_op != CC_OP_DYNAMIC) gen_op_set_cc_op(s->cc_op); gen_op_into(); break; case 0xfa: /* cli */ if (!s->vm86) { if (s->cpl <= s->iopl) gen_op_cli(); else gen_op_gpf(pc_start - s->cs_base); } else { if (s->iopl == 3) gen_op_cli(); else gen_op_cli_vm(); } break; case 0xfb: /* sti */ if (!s->vm86) { if (s->cpl <= s->iopl) gen_op_sti(); else gen_op_gpf(pc_start - s->cs_base); } else { if (s->iopl == 3) gen_op_sti(); else gen_op_sti_vm(pc_start - s->cs_base); } break; case 0x62: /* bound */ ot = dflag ? OT_LONG : OT_WORD; modrm = ldub(s->pc++); reg = (modrm >> 3) & 7; mod = (modrm >> 6) & 3; if (mod == 3) goto illegal_op; gen_op_mov_reg_T0[ot][reg](); gen_lea_modrm(s, modrm, &reg_addr, &offset_addr); if (ot == OT_WORD) gen_op_boundw(); else gen_op_boundl(); break; case 0x1c8 ... 0x1cf: /* bswap reg */ reg = b & 7; gen_op_mov_TN_reg[OT_LONG][0][reg](); gen_op_bswapl_T0(); gen_op_mov_reg_T0[OT_LONG][reg](); break; case 0xd6: /* salc */ if (s->cc_op != CC_OP_DYNAMIC) gen_op_set_cc_op(s->cc_op); gen_op_salc(); break; case 0xe0: /* loopnz */ case 0xe1: /* loopz */ if (s->cc_op != CC_OP_DYNAMIC) gen_op_set_cc_op(s->cc_op); /* FALL THRU */ case 0xe2: /* loop */ case 0xe3: /* jecxz */ val = (int8_t)insn_get(s, OT_BYTE); next_eip = s->pc - s->cs_base; val += next_eip; if (s->dflag == 0) val &= 0xffff; gen_op_loop[s->aflag][b & 3](val, next_eip); s->is_jmp = 1; break; case 0x131: /* rdtsc */ gen_op_rdtsc(); break; case 0x1a2: /* cpuid */ gen_op_cpuid(); break; case 0xf4: /* hlt */ if (s->cpl == 0) { /* ignored */ } else { gen_op_gpf(pc_start - s->cs_base); } break; default: goto illegal_op; } /* lock generation */ if (s->prefix & PREFIX_LOCK) gen_op_unlock(); return (long)s->pc; illegal_op: /* XXX: ensure that no lock was generated */ return -1; }


static void xhci_process_commands(XHCIState *xhci) { XHCITRB trb; TRBType type; XHCIEvent event = {ER_COMMAND_COMPLETE, CC_SUCCESS}; dma_addr_t addr; unsigned int i, slotid = 0; DPRINTF("xhci_process_commands()\n"); if (!xhci_running(xhci)) { DPRINTF("xhci_process_commands() called while xHC stopped or paused\n"); return; } xhci->crcr_low |= CRCR_CRR; while ((type = xhci_ring_fetch(xhci, &xhci->cmd_ring, &trb, &addr))) { event.ptr = addr; switch (type) { case CR_ENABLE_SLOT: for (i = 0; i < xhci->numslots; i++) { if (!xhci->slots[i].enabled) { break; } } if (i >= xhci->numslots) { DPRINTF("xhci: no device slots available\n"); event.ccode = CC_NO_SLOTS_ERROR; } else { slotid = i+1; event.ccode = xhci_enable_slot(xhci, slotid); } break; case CR_DISABLE_SLOT: slotid = xhci_get_slot(xhci, &event, &trb); if (slotid) { event.ccode = xhci_disable_slot(xhci, slotid); } break; case CR_ADDRESS_DEVICE: slotid = xhci_get_slot(xhci, &event, &trb); if (slotid) { event.ccode = xhci_address_slot(xhci, slotid, trb.parameter, trb.control & TRB_CR_BSR); } break; case CR_CONFIGURE_ENDPOINT: slotid = xhci_get_slot(xhci, &event, &trb); if (slotid) { event.ccode = xhci_configure_slot(xhci, slotid, trb.parameter, trb.control & TRB_CR_DC); } break; case CR_EVALUATE_CONTEXT: slotid = xhci_get_slot(xhci, &event, &trb); if (slotid) { event.ccode = xhci_evaluate_slot(xhci, slotid, trb.parameter); } break; case CR_STOP_ENDPOINT: slotid = xhci_get_slot(xhci, &event, &trb); if (slotid) { unsigned int epid = (trb.control >> TRB_CR_EPID_SHIFT) & TRB_CR_EPID_MASK; event.ccode = xhci_stop_ep(xhci, slotid, epid); } break; case CR_RESET_ENDPOINT: slotid = xhci_get_slot(xhci, &event, &trb); if (slotid) { unsigned int epid = (trb.control >> TRB_CR_EPID_SHIFT) & TRB_CR_EPID_MASK; event.ccode = xhci_reset_ep(xhci, slotid, epid); } break; case CR_SET_TR_DEQUEUE: slotid = xhci_get_slot(xhci, &event, &trb); if (slotid) { unsigned int epid = (trb.control >> TRB_CR_EPID_SHIFT) & TRB_CR_EPID_MASK; unsigned int streamid = (trb.status >> 16) & 0xffff; event.ccode = xhci_set_ep_dequeue(xhci, slotid, epid, streamid, trb.parameter); } break; case CR_RESET_DEVICE: slotid = xhci_get_slot(xhci, &event, &trb); if (slotid) { event.ccode = xhci_reset_slot(xhci, slotid); } break; case CR_GET_PORT_BANDWIDTH: event.ccode = xhci_get_port_bandwidth(xhci, trb.parameter); break; case CR_VENDOR_VIA_CHALLENGE_RESPONSE: xhci_via_challenge(xhci, trb.parameter); break; case CR_VENDOR_NEC_FIRMWARE_REVISION: event.type = 48; /* NEC reply */ event.length = 0x3025; break; case CR_VENDOR_NEC_CHALLENGE_RESPONSE: { uint32_t chi = trb.parameter >> 32; uint32_t clo = trb.parameter; uint32_t val = xhci_nec_challenge(chi, clo); event.length = val & 0xFFFF; event.epid = val >> 16; slotid = val >> 24; event.type = 48; /* NEC reply */ } break; default: trace_usb_xhci_unimplemented("command", type); event.ccode = CC_TRB_ERROR; break; } event.slotid = slotid; xhci_event(xhci, &event, 0); } }


void cpu_loop(CPUTLGState *env) { CPUState *cs = CPU(tilegx_env_get_cpu(env)); int trapnr; while (1) { cpu_exec_start(cs); trapnr = cpu_tilegx_exec(cs); cpu_exec_end(cs); switch (trapnr) { case TILEGX_EXCP_SYSCALL: env->regs[TILEGX_R_RE] = do_syscall(env, env->regs[TILEGX_R_NR], env->regs[0], env->regs[1], env->regs[2], env->regs[3], env->regs[4], env->regs[5], env->regs[6], env->regs[7]); env->regs[TILEGX_R_ERR] = TILEGX_IS_ERRNO(env->regs[TILEGX_R_RE]) ? - env->regs[TILEGX_R_RE] : 0; break; case TILEGX_EXCP_OPCODE_EXCH: do_exch(env, true, false); break; case TILEGX_EXCP_OPCODE_EXCH4: do_exch(env, false, false); break; case TILEGX_EXCP_OPCODE_CMPEXCH: do_exch(env, true, true); break; case TILEGX_EXCP_OPCODE_CMPEXCH4: do_exch(env, false, true); break; case TILEGX_EXCP_OPCODE_FETCHADD: case TILEGX_EXCP_OPCODE_FETCHADDGEZ: case TILEGX_EXCP_OPCODE_FETCHAND: case TILEGX_EXCP_OPCODE_FETCHOR: do_fetch(env, trapnr, true); break; case TILEGX_EXCP_OPCODE_FETCHADD4: case TILEGX_EXCP_OPCODE_FETCHADDGEZ4: case TILEGX_EXCP_OPCODE_FETCHAND4: case TILEGX_EXCP_OPCODE_FETCHOR4: do_fetch(env, trapnr, false); break; case TILEGX_EXCP_SIGNAL: do_signal(env, env->signo, env->sigcode); break; case TILEGX_EXCP_REG_IDN_ACCESS: case TILEGX_EXCP_REG_UDN_ACCESS: gen_sigill_reg(env); break; default: fprintf(stderr, "trapnr is %d[0x%x].\n", trapnr, trapnr); g_assert_not_reached(); } process_pending_signals(env); } }


sofree(struct socket *so) { Slirp *slirp = so->slirp; struct mbuf *ifm; for (ifm = (struct mbuf *) slirp->if_fastq.qh_link; (struct quehead *) ifm != &slirp->if_fastq; ifm = ifm->ifq_next) { if (ifm->ifq_so == so) { ifm->ifq_so = NULL; for (ifm = (struct mbuf *) slirp->if_batchq.qh_link; (struct quehead *) ifm != &slirp->if_batchq; ifm = ifm->ifq_next) { if (ifm->ifq_so == so) { ifm->ifq_so = NULL; if (so->so_emu==EMU_RSH && so->extra) { sofree(so->extra); so->extra=NULL; if (so == slirp->tcp_last_so) { slirp->tcp_last_so = &slirp->tcb; } else if (so == slirp->udp_last_so) { slirp->udp_last_so = &slirp->udb; } else if (so == slirp->icmp_last_so) { slirp->icmp_last_so = &slirp->icmp; m_free(so->so_m); if(so->so_next && so->so_prev) remque(so); /* crashes if so is not in a queue */ free(so);


static void close_slave(TeeSlave *tee_slave) { AVFormatContext *avf; unsigned i; avf = tee_slave->avf; for (i = 0; i < avf->nb_streams; ++i) { AVBitStreamFilterContext *bsf_next, *bsf = tee_slave->bsfs[i]; while (bsf) { bsf_next = bsf->next; av_bitstream_filter_close(bsf); bsf = bsf_next; } } av_freep(&tee_slave->stream_map); av_freep(&tee_slave->bsfs); ff_format_io_close(avf, &avf->pb); avformat_free_context(avf); tee_slave->avf = NULL; }


static int ac3_decode_frame(AVCodecContext * avctx, void *data, int *got_frame_ptr, AVPacket *avpkt) { const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; AC3DecodeContext *s = avctx->priv_data; int blk, ch, err, ret; const uint8_t *channel_map; const float *output[AC3_MAX_CHANNELS]; /* copy input buffer to decoder context to avoid reading past the end of the buffer, which can be caused by a damaged input stream. */ if (buf_size >= 2 && AV_RB16(buf) == 0x770B) { // seems to be byte-swapped AC-3 int cnt = FFMIN(buf_size, AC3_FRAME_BUFFER_SIZE) >> 1; s->dsp.bswap16_buf((uint16_t *)s->input_buffer, (const uint16_t *)buf, cnt); } else memcpy(s->input_buffer, buf, FFMIN(buf_size, AC3_FRAME_BUFFER_SIZE)); buf = s->input_buffer; /* initialize the GetBitContext with the start of valid AC-3 Frame */ init_get_bits(&s->gbc, buf, buf_size * 8); /* parse the syncinfo */ err = parse_frame_header(s); if (err) { switch (err) { case AAC_AC3_PARSE_ERROR_SYNC: av_log(avctx, AV_LOG_ERROR, "frame sync error\n"); return -1; case AAC_AC3_PARSE_ERROR_BSID: av_log(avctx, AV_LOG_ERROR, "invalid bitstream id\n"); break; case AAC_AC3_PARSE_ERROR_SAMPLE_RATE: av_log(avctx, AV_LOG_ERROR, "invalid sample rate\n"); break; case AAC_AC3_PARSE_ERROR_FRAME_SIZE: av_log(avctx, AV_LOG_ERROR, "invalid frame size\n"); break; case AAC_AC3_PARSE_ERROR_FRAME_TYPE: /* skip frame if CRC is ok. otherwise use error concealment. */ /* TODO: add support for substreams and dependent frames */ if (s->frame_type == EAC3_FRAME_TYPE_DEPENDENT || s->substreamid) { av_log(avctx, AV_LOG_ERROR, "unsupported frame type : " "skipping frame\n"); *got_frame_ptr = 0; return s->frame_size; } else { av_log(avctx, AV_LOG_ERROR, "invalid frame type\n"); } break; default: av_log(avctx, AV_LOG_ERROR, "invalid header\n"); break; } } else { /* check that reported frame size fits in input buffer */ if (s->frame_size > buf_size) { av_log(avctx, AV_LOG_ERROR, "incomplete frame\n"); err = AAC_AC3_PARSE_ERROR_FRAME_SIZE; } else if (avctx->err_recognition & (AV_EF_CRCCHECK|AV_EF_CAREFUL)) { /* check for crc mismatch */ if (av_crc(av_crc_get_table(AV_CRC_16_ANSI), 0, &buf[2], s->frame_size - 2)) { av_log(avctx, AV_LOG_ERROR, "frame CRC mismatch\n"); err = AAC_AC3_PARSE_ERROR_CRC; } } } /* if frame is ok, set audio parameters */ if (!err) { avctx->sample_rate = s->sample_rate; avctx->bit_rate = s->bit_rate; /* channel config */ s->out_channels = s->channels; s->output_mode = s->channel_mode; if (s->lfe_on) s->output_mode |= AC3_OUTPUT_LFEON; if (avctx->request_channels > 0 && avctx->request_channels <= 2 && avctx->request_channels < s->channels) { s->out_channels = avctx->request_channels; s->output_mode = avctx->request_channels == 1 ? AC3_CHMODE_MONO : AC3_CHMODE_STEREO; s->channel_layout = avpriv_ac3_channel_layout_tab[s->output_mode]; } avctx->channels = s->out_channels; avctx->channel_layout = s->channel_layout; s->loro_center_mix_level = gain_levels[s-> center_mix_level]; s->loro_surround_mix_level = gain_levels[s->surround_mix_level]; s->ltrt_center_mix_level = LEVEL_MINUS_3DB; s->ltrt_surround_mix_level = LEVEL_MINUS_3DB; /* set downmixing coefficients if needed */ if (s->channels != s->out_channels && !((s->output_mode & AC3_OUTPUT_LFEON) && s->fbw_channels == s->out_channels)) { set_downmix_coeffs(s); } } else if (!s->out_channels) { s->out_channels = avctx->channels; if (s->out_channels < s->channels) s->output_mode = s->out_channels == 1 ? AC3_CHMODE_MONO : AC3_CHMODE_STEREO; } if (avctx->channels != s->out_channels) { av_log(avctx, AV_LOG_ERROR, "channel number mismatching on damaged frame\n"); return AVERROR_INVALIDDATA; } /* set audio service type based on bitstream mode for AC-3 */ avctx->audio_service_type = s->bitstream_mode; if (s->bitstream_mode == 0x7 && s->channels > 1) avctx->audio_service_type = AV_AUDIO_SERVICE_TYPE_KARAOKE; /* get output buffer */ avctx->channels = s->out_channels; s->frame.nb_samples = s->num_blocks * 256; if ((ret = ff_get_buffer(avctx, &s->frame)) < 0) { av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n"); return ret; } /* decode the audio blocks */ channel_map = ff_ac3_dec_channel_map[s->output_mode & ~AC3_OUTPUT_LFEON][s->lfe_on]; for (ch = 0; ch < s->channels; ch++) { if (ch < s->out_channels) s->outptr[channel_map[ch]] = (float *)s->frame.data[ch]; else s->outptr[ch] = s->output[ch]; output[ch] = s->output[ch]; } for (blk = 0; blk < s->num_blocks; blk++) { if (!err && decode_audio_block(s, blk)) { av_log(avctx, AV_LOG_ERROR, "error decoding the audio block\n"); err = 1; } if (err) for (ch = 0; ch < s->out_channels; ch++) memcpy(s->outptr[channel_map[ch]], output[ch], 1024); for (ch = 0; ch < s->out_channels; ch++) { output[ch] = s->outptr[channel_map[ch]]; s->outptr[channel_map[ch]] += AC3_BLOCK_SIZE; } } s->frame.decode_error_flags = err ? FF_DECODE_ERROR_INVALID_BITSTREAM : 0; /* keep last block for error concealment in next frame */ for (ch = 0; ch < s->out_channels; ch++) memcpy(s->output[ch], output[ch], 1024); *got_frame_ptr = 1; *(AVFrame *)data = s->frame; return FFMIN(buf_size, s->frame_size); }


static int ffserver_parse_config_global(FFServerConfig *config, const char *cmd, const char **p, int line_num) { int val; char arg[1024]; if (!av_strcasecmp(cmd, "Port") || !av_strcasecmp(cmd, "HTTPPort")) { if (!av_strcasecmp(cmd, "Port")) WARNING("Port option is deprecated, use HTTPPort instead\n"); ffserver_get_arg(arg, sizeof(arg), p); val = atoi(arg); if (val < 1 || val > 65536) ERROR("Invalid port: %s\n", arg); if (val < 1024) WARNING("Trying to use IETF assigned system port: %d\n", val); config->http_addr.sin_port = htons(val); } else if (!av_strcasecmp(cmd, "HTTPBindAddress") || !av_strcasecmp(cmd, "BindAddress")) { if (!av_strcasecmp(cmd, "BindAddress")) WARNING("BindAddress option is deprecated, use HTTPBindAddress instead\n"); ffserver_get_arg(arg, sizeof(arg), p); if (resolve_host(&config->http_addr.sin_addr, arg) != 0) ERROR("%s:%d: Invalid host/IP address: %s\n", arg); } else if (!av_strcasecmp(cmd, "NoDaemon")) { WARNING("NoDaemon option has no effect, you should remove it\n"); } else if (!av_strcasecmp(cmd, "RTSPPort")) { ffserver_get_arg(arg, sizeof(arg), p); val = atoi(arg); if (val < 1 || val > 65536) ERROR("%s:%d: Invalid port: %s\n", arg); config->rtsp_addr.sin_port = htons(atoi(arg)); } else if (!av_strcasecmp(cmd, "RTSPBindAddress")) { ffserver_get_arg(arg, sizeof(arg), p); if (resolve_host(&config->rtsp_addr.sin_addr, arg) != 0) ERROR("Invalid host/IP address: %s\n", arg); } else if (!av_strcasecmp(cmd, "MaxHTTPConnections")) { ffserver_get_arg(arg, sizeof(arg), p); val = atoi(arg); if (val < 1 || val > 65536) ERROR("Invalid MaxHTTPConnections: %s\n", arg); config->nb_max_http_connections = val; } else if (!av_strcasecmp(cmd, "MaxClients")) { ffserver_get_arg(arg, sizeof(arg), p); val = atoi(arg); if (val < 1 || val > config->nb_max_http_connections) ERROR("Invalid MaxClients: %s\n", arg); else config->nb_max_connections = val; } else if (!av_strcasecmp(cmd, "MaxBandwidth")) { int64_t llval; ffserver_get_arg(arg, sizeof(arg), p); llval = strtoll(arg, NULL, 10); if (llval < 10 || llval > 10000000) ERROR("Invalid MaxBandwidth: %s\n", arg); else config->max_bandwidth = llval; } else if (!av_strcasecmp(cmd, "CustomLog")) { if (!config->debug) ffserver_get_arg(config->logfilename, sizeof(config->logfilename), p); } else if (!av_strcasecmp(cmd, "LoadModule")) { ERROR("Loadable modules no longer supported\n"); } else ERROR("Incorrect keyword: '%s'\n", cmd); return 0; }


int ff_h264_fill_default_ref_list(H264Context *h) { int i, len; if (h->slice_type_nos == AV_PICTURE_TYPE_B) { Picture *sorted[32]; int cur_poc, list; int lens[2]; if (FIELD_PICTURE(h)) cur_poc = h->cur_pic_ptr->field_poc[h->picture_structure == PICT_BOTTOM_FIELD]; else cur_poc = h->cur_pic_ptr->poc; for (list = 0; list < 2; list++) { len = add_sorted(sorted, h->short_ref, h->short_ref_count, cur_poc, 1 ^ list); len += add_sorted(sorted + len, h->short_ref, h->short_ref_count, cur_poc, 0 ^ list); assert(len <= 32); len = build_def_list(h->default_ref_list[list], sorted, len, 0, h->picture_structure); len += build_def_list(h->default_ref_list[list] + len, h->long_ref, 16, 1, h->picture_structure); assert(len <= 32); if (len < h->ref_count[list]) memset(&h->default_ref_list[list][len], 0, sizeof(Picture) * (h->ref_count[list] - len)); lens[list] = len; } if (lens[0] == lens[1] && lens[1] > 1) { for (i = 0; h->default_ref_list[0][i].f.data[0] == h->default_ref_list[1][i].f.data[0] && i < lens[0]; i++); if (i == lens[0]) { Picture tmp; COPY_PICTURE(&tmp, &h->default_ref_list[1][0]); COPY_PICTURE(&h->default_ref_list[1][0], &h->default_ref_list[1][1]); COPY_PICTURE(&h->default_ref_list[1][1], &tmp); } } } else { len = build_def_list(h->default_ref_list[0], h->short_ref, h->short_ref_count, 0, h->picture_structure); len += build_def_list(h->default_ref_list[0] + len, h-> long_ref, 16, 1, h->picture_structure); assert(len <= 32); if (len < h->ref_count[0]) memset(&h->default_ref_list[0][len], 0, sizeof(Picture) * (h->ref_count[0] - len)); } #ifdef TRACE for (i = 0; i < h->ref_count[0]; i++) { tprintf(h->avctx, "List0: %s fn:%d 0x%p\n", (h->default_ref_list[0][i].long_ref ? "LT" : "ST"), h->default_ref_list[0][i].pic_id, h->default_ref_list[0][i].f.data[0]); } if (h->slice_type_nos == AV_PICTURE_TYPE_B) { for (i = 0; i < h->ref_count[1]; i++) { tprintf(h->avctx, "List1: %s fn:%d 0x%p\n", (h->default_ref_list[1][i].long_ref ? "LT" : "ST"), h->default_ref_list[1][i].pic_id, h->default_ref_list[1][i].f.data[0]); } } #endif return 0; }


static int check_strtox_error(const char *p, char *endptr, const char **next, int err) { /* If no conversion was performed, prefer BSD behavior over glibc * behavior. */ if (err == 0 && endptr == p) { err = EINVAL; } if (!next && *endptr) { return -EINVAL; } if (next) { *next = endptr; } return -err; }


static void ram_decompress_close(RamDecompressState *s) { inflateEnd(&s->zstream); }


static void ahci_hba_enable(AHCIQState *ahci) { /* Bits of interest in this section: * GHC.AE Global Host Control / AHCI Enable * PxCMD.ST Port Command: Start * PxCMD.SUD "Spin Up Device" * PxCMD.POD "Power On Device" * PxCMD.FRE "FIS Receive Enable" * PxCMD.FR "FIS Receive Running" * PxCMD.CR "Command List Running" */ uint32_t reg, ports_impl; uint16_t i; uint8_t num_cmd_slots; g_assert(ahci != NULL); /* Set GHC.AE to 1 */ ahci_set(ahci, AHCI_GHC, AHCI_GHC_AE); reg = ahci_rreg(ahci, AHCI_GHC); ASSERT_BIT_SET(reg, AHCI_GHC_AE); /* Cache CAP and CAP2. */ ahci->cap = ahci_rreg(ahci, AHCI_CAP); ahci->cap2 = ahci_rreg(ahci, AHCI_CAP2); /* Read CAP.NCS, how many command slots do we have? */ num_cmd_slots = ((ahci->cap & AHCI_CAP_NCS) >> ctzl(AHCI_CAP_NCS)) + 1; g_test_message("Number of Command Slots: %u", num_cmd_slots); /* Determine which ports are implemented. */ ports_impl = ahci_rreg(ahci, AHCI_PI); for (i = 0; ports_impl; ports_impl >>= 1, ++i) { if (!(ports_impl & 0x01)) { continue; } g_test_message("Initializing port %u", i); reg = ahci_px_rreg(ahci, i, AHCI_PX_CMD); if (BITCLR(reg, AHCI_PX_CMD_ST | AHCI_PX_CMD_CR | AHCI_PX_CMD_FRE | AHCI_PX_CMD_FR)) { g_test_message("port is idle"); } else { g_test_message("port needs to be idled"); ahci_px_clr(ahci, i, AHCI_PX_CMD, (AHCI_PX_CMD_ST | AHCI_PX_CMD_FRE)); /* The port has 500ms to disengage. */ usleep(500000); reg = ahci_px_rreg(ahci, i, AHCI_PX_CMD); ASSERT_BIT_CLEAR(reg, AHCI_PX_CMD_CR); ASSERT_BIT_CLEAR(reg, AHCI_PX_CMD_FR); g_test_message("port is now idle"); /* The spec does allow for possibly needing a PORT RESET * or HBA reset if we fail to idle the port. */ } /* Allocate Memory for the Command List Buffer & FIS Buffer */ /* PxCLB space ... 0x20 per command, as in 4.2.2 p 36 */ ahci->port[i].clb = ahci_alloc(ahci, num_cmd_slots * 0x20); qmemset(ahci->port[i].clb, 0x00, 0x100); g_test_message("CLB: 0x%08" PRIx64, ahci->port[i].clb); ahci_px_wreg(ahci, i, AHCI_PX_CLB, ahci->port[i].clb); g_assert_cmphex(ahci->port[i].clb, ==, ahci_px_rreg(ahci, i, AHCI_PX_CLB)); /* PxFB space ... 0x100, as in 4.2.1 p 35 */ ahci->port[i].fb = ahci_alloc(ahci, 0x100); qmemset(ahci->port[i].fb, 0x00, 0x100); g_test_message("FB: 0x%08" PRIx64, ahci->port[i].fb); ahci_px_wreg(ahci, i, AHCI_PX_FB, ahci->port[i].fb); g_assert_cmphex(ahci->port[i].fb, ==, ahci_px_rreg(ahci, i, AHCI_PX_FB)); /* Clear PxSERR, PxIS, then IS.IPS[x] by writing '1's. */ ahci_px_wreg(ahci, i, AHCI_PX_SERR, 0xFFFFFFFF); ahci_px_wreg(ahci, i, AHCI_PX_IS, 0xFFFFFFFF); ahci_wreg(ahci, AHCI_IS, (1 << i)); /* Verify Interrupts Cleared */ reg = ahci_px_rreg(ahci, i, AHCI_PX_SERR); g_assert_cmphex(reg, ==, 0); reg = ahci_px_rreg(ahci, i, AHCI_PX_IS); g_assert_cmphex(reg, ==, 0); reg = ahci_rreg(ahci, AHCI_IS); ASSERT_BIT_CLEAR(reg, (1 << i)); /* Enable All Interrupts: */ ahci_px_wreg(ahci, i, AHCI_PX_IE, 0xFFFFFFFF); reg = ahci_px_rreg(ahci, i, AHCI_PX_IE); g_assert_cmphex(reg, ==, ~((uint32_t)AHCI_PX_IE_RESERVED)); /* Enable the FIS Receive Engine. */ ahci_px_set(ahci, i, AHCI_PX_CMD, AHCI_PX_CMD_FRE); reg = ahci_px_rreg(ahci, i, AHCI_PX_CMD); ASSERT_BIT_SET(reg, AHCI_PX_CMD_FR); /* AHCI 1.3 spec: if !STS.BSY, !STS.DRQ and PxSSTS.DET indicates * physical presence, a device is present and may be started. However, * PxSERR.DIAG.X /may/ need to be cleared a priori. */ reg = ahci_px_rreg(ahci, i, AHCI_PX_SERR); if (BITSET(reg, AHCI_PX_SERR_DIAG_X)) { ahci_px_set(ahci, i, AHCI_PX_SERR, AHCI_PX_SERR_DIAG_X); } reg = ahci_px_rreg(ahci, i, AHCI_PX_TFD); if (BITCLR(reg, AHCI_PX_TFD_STS_BSY | AHCI_PX_TFD_STS_DRQ)) { reg = ahci_px_rreg(ahci, i, AHCI_PX_SSTS); if ((reg & AHCI_PX_SSTS_DET) == SSTS_DET_ESTABLISHED) { /* Device Found: set PxCMD.ST := 1 */ ahci_px_set(ahci, i, AHCI_PX_CMD, AHCI_PX_CMD_ST); ASSERT_BIT_SET(ahci_px_rreg(ahci, i, AHCI_PX_CMD), AHCI_PX_CMD_CR); g_test_message("Started Device %u", i); } else if ((reg & AHCI_PX_SSTS_DET)) { /* Device present, but in some unknown state. */ g_assert_not_reached(); } } } /* Enable GHC.IE */ ahci_set(ahci, AHCI_GHC, AHCI_GHC_IE); reg = ahci_rreg(ahci, AHCI_GHC); ASSERT_BIT_SET(reg, AHCI_GHC_IE); /* TODO: The device should now be idling and waiting for commands. * In the future, a small test-case to inspect the Register D2H FIS * and clear the initial interrupts might be good. */ }


static int decode_p_frame(FourXContext *f, const uint8_t *buf, int length) { int x, y; const int width = f->avctx->width; const int height = f->avctx->height; uint16_t *src = (uint16_t *)f->last_picture.data[0]; uint16_t *dst = (uint16_t *)f->current_picture.data[0]; const int stride = f->current_picture.linesize[0] >> 1; unsigned int bitstream_size, bytestream_size, wordstream_size, extra, bytestream_offset, wordstream_offset; if (f->version > 1) { extra = 20; if (length < extra) return -1; bitstream_size = AV_RL32(buf + 8); wordstream_size = AV_RL32(buf + 12); bytestream_size = AV_RL32(buf + 16); } else { extra = 0; bitstream_size = AV_RL16(buf - 4); wordstream_size = AV_RL16(buf - 2); bytestream_size = FFMAX(length - bitstream_size - wordstream_size, 0); } if (bitstream_size > length || bytestream_size > length - bitstream_size || wordstream_size > length - bytestream_size - bitstream_size || extra > length - bytestream_size - bitstream_size - wordstream_size) { av_log(f->avctx, AV_LOG_ERROR, "lengths %d %d %d %d\n", bitstream_size, bytestream_size, wordstream_size, bitstream_size+ bytestream_size+ wordstream_size - length); return -1; } av_fast_malloc(&f->bitstream_buffer, &f->bitstream_buffer_size, bitstream_size + FF_INPUT_BUFFER_PADDING_SIZE); if (!f->bitstream_buffer) return AVERROR(ENOMEM); f->dsp.bswap_buf(f->bitstream_buffer, (const uint32_t*)(buf + extra), bitstream_size / 4); memset((uint8_t*)f->bitstream_buffer + bitstream_size, 0, FF_INPUT_BUFFER_PADDING_SIZE); init_get_bits(&f->gb, f->bitstream_buffer, 8 * bitstream_size); wordstream_offset = extra + bitstream_size; bytestream_offset = extra + bitstream_size + wordstream_size; bytestream2_init(&f->g2, buf + wordstream_offset, length - wordstream_offset); bytestream2_init(&f->g, buf + bytestream_offset, length - bytestream_offset); init_mv(f); for (y = 0; y < height; y += 8) { for (x = 0; x < width; x += 8) decode_p_block(f, dst + x, src + x, 3, 3, stride); src += 8 * stride; dst += 8 * stride; } return 0; }


void *kqemu_vmalloc(size_t size) { static int phys_ram_fd = -1; static int phys_ram_size = 0; const char *tmpdir; char phys_ram_file[1024]; void *ptr; struct statfs stfs; if (phys_ram_fd < 0) { tmpdir = getenv("QEMU_TMPDIR"); if (!tmpdir) tmpdir = "/dev/shm"; if (statfs(tmpdir, &stfs) == 0) { int64_t free_space; int ram_mb; extern int ram_size; free_space = (int64_t)stfs.f_bavail * stfs.f_bsize; if ((ram_size + 8192 * 1024) >= free_space) { ram_mb = (ram_size / (1024 * 1024)); fprintf(stderr, "You do not have enough space in '%s' for the %d MB of QEMU virtual RAM.\n", tmpdir, ram_mb); if (strcmp(tmpdir, "/dev/shm") == 0) { fprintf(stderr, "To have more space available provided you have enough RAM and swap, do as root:\n" "umount /dev/shm\n" "mount -t tmpfs -o size=%dm none /dev/shm\n", ram_mb + 16); } else { fprintf(stderr, "Use the '-m' option of QEMU to diminish the amount of virtual RAM or use the\n" "QEMU_TMPDIR environment variable to set another directory where the QEMU\n" "temporary RAM file will be opened.\n"); } fprintf(stderr, "Or disable the accelerator module with -no-kqemu\n"); exit(1); } } snprintf(phys_ram_file, sizeof(phys_ram_file), "%s/qemuXXXXXX", tmpdir); if (mkstemp(phys_ram_file) < 0) { fprintf(stderr, "warning: could not create temporary file in '%s'.\n" "Use QEMU_TMPDIR to select a directory in a tmpfs filesystem.\n" "Using '/tmp' as fallback.\n", tmpdir); snprintf(phys_ram_file, sizeof(phys_ram_file), "%s/qemuXXXXXX", "/tmp"); if (mkstemp(phys_ram_file) < 0) { fprintf(stderr, "Could not create temporary memory file '%s'\n", phys_ram_file); exit(1); } } phys_ram_fd = open(phys_ram_file, O_CREAT | O_TRUNC | O_RDWR, 0600); if (phys_ram_fd < 0) { fprintf(stderr, "Could not open temporary memory file '%s'\n", phys_ram_file); exit(1); } unlink(phys_ram_file); } size = (size + 4095) & ~4095; ftruncate(phys_ram_fd, phys_ram_size + size); ptr = mmap(NULL, size, PROT_WRITE | PROT_READ, MAP_SHARED, phys_ram_fd, phys_ram_size); if (ptr == MAP_FAILED) { fprintf(stderr, "Could not map physical memory\n"); exit(1); } phys_ram_size += size; return ptr; }


static uint64_t qvirtio_pci_config_readq(QVirtioDevice *d, uint64_t off) { QVirtioPCIDevice *dev = (QVirtioPCIDevice *)d; uint64_t val; val = qpci_io_readq(dev->pdev, CONFIG_BASE(dev) + off); if (qvirtio_is_big_endian(d)) { val = bswap64(val); } return val; }


void video_decode_example(const char *outfilename, const char *filename) { AVCodec *codec; AVCodecContext *c= NULL; int frame, size, got_picture, len; FILE *f; AVFrame *picture; uint8_t inbuf[INBUF_SIZE + FF_INPUT_BUFFER_PADDING_SIZE], *inbuf_ptr; char buf[1024]; /* set end of buffer to 0 (this ensures that no overreading happens for damaged mpeg streams) */ memset(inbuf + INBUF_SIZE, 0, FF_INPUT_BUFFER_PADDING_SIZE); printf("Video decoding\n"); /* find the mpeg1 video decoder */ codec = avcodec_find_decoder(CODEC_ID_MPEG1VIDEO); if (!codec) { fprintf(stderr, "codec not found\n"); exit(1); } c= avcodec_alloc_context(); picture= avcodec_alloc_frame(); if(codec->capabilities&CODEC_CAP_TRUNCATED) c->flags|= CODEC_FLAG_TRUNCATED; /* we dont send complete frames */ /* for some codecs, such as msmpeg4 and mpeg4, width and height MUST be initialized there because these info are not available in the bitstream */ /* open it */ if (avcodec_open(c, codec) < 0) { fprintf(stderr, "could not open codec\n"); exit(1); } /* the codec gives us the frame size, in samples */ f = fopen(filename, "r"); if (!f) { fprintf(stderr, "could not open %s\n", filename); exit(1); } frame = 0; for(;;) { size = fread(inbuf, 1, INBUF_SIZE, f); if (size == 0) break; /* NOTE1: some codecs are stream based (mpegvideo, mpegaudio) and this is the only method to use them because you cannot know the compressed data size before analysing it. BUT some other codecs (msmpeg4, mpeg4) are inherently frame based, so you must call them with all the data for one frame exactly. You must also initialize 'width' and 'height' before initializing them. */ /* NOTE2: some codecs allow the raw parameters (frame size, sample rate) to be changed at any frame. We handle this, so you should also take care of it */ /* here, we use a stream based decoder (mpeg1video), so we feed decoder and see if it could decode a frame */ inbuf_ptr = inbuf; while (size > 0) { len = avcodec_decode_video(c, picture, &got_picture, inbuf_ptr, size); if (len < 0) { fprintf(stderr, "Error while decoding frame %d\n", frame); exit(1); } if (got_picture) { printf("saving frame %3d\n", frame); fflush(stdout); /* the picture is allocated by the decoder. no need to free it */ snprintf(buf, sizeof(buf), outfilename, frame); pgm_save(picture->data[0], picture->linesize[0], c->width, c->height, buf); frame++; } size -= len; inbuf_ptr += len; } } /* some codecs, such as MPEG, transmit the I and P frame with a latency of one frame. You must do the following to have a chance to get the last frame of the video */ len = avcodec_decode_video(c, picture, &got_picture, NULL, 0); if (got_picture) { printf("saving last frame %3d\n", frame); fflush(stdout); /* the picture is allocated by the decoder. no need to free it */ snprintf(buf, sizeof(buf), outfilename, frame); pgm_save(picture->data[0], picture->linesize[0], c->width, c->height, buf); frame++; } fclose(f); avcodec_close(c); free(c); free(picture); printf("\n"); }


static int rebuild_refcount_structure(BlockDriverState *bs, BdrvCheckResult *res, uint16_t **refcount_table, int64_t *nb_clusters) { BDRVQcowState *s = bs->opaque; int64_t first_free_cluster = 0, reftable_offset = -1, cluster = 0; int64_t refblock_offset, refblock_start, refblock_index; uint32_t reftable_size = 0; uint64_t *on_disk_reftable = NULL; uint16_t *on_disk_refblock; int i, ret = 0; struct { uint64_t reftable_offset; uint32_t reftable_clusters; } QEMU_PACKED reftable_offset_and_clusters; qcow2_cache_empty(bs, s->refcount_block_cache); write_refblocks: for (; cluster < *nb_clusters; cluster++) { if (!(*refcount_table)[cluster]) { continue; } refblock_index = cluster >> s->refcount_block_bits; refblock_start = refblock_index << s->refcount_block_bits; /* Don't allocate a cluster in a refblock already written to disk */ if (first_free_cluster < refblock_start) { first_free_cluster = refblock_start; } refblock_offset = alloc_clusters_imrt(bs, 1, refcount_table, nb_clusters, &first_free_cluster); if (refblock_offset < 0) { fprintf(stderr, "ERROR allocating refblock: %s\n", strerror(-refblock_offset)); res->check_errors++; ret = refblock_offset; goto fail; } if (reftable_size <= refblock_index) { uint32_t old_reftable_size = reftable_size; uint64_t *new_on_disk_reftable; reftable_size = ROUND_UP((refblock_index + 1) * sizeof(uint64_t), s->cluster_size) / sizeof(uint64_t); new_on_disk_reftable = g_try_realloc(on_disk_reftable, reftable_size * sizeof(uint64_t)); if (!new_on_disk_reftable) { res->check_errors++; ret = -ENOMEM; goto fail; } on_disk_reftable = new_on_disk_reftable; memset(on_disk_reftable + old_reftable_size, 0, (reftable_size - old_reftable_size) * sizeof(uint64_t)); /* The offset we have for the reftable is now no longer valid; * this will leak that range, but we can easily fix that by running * a leak-fixing check after this rebuild operation */ reftable_offset = -1; } on_disk_reftable[refblock_index] = refblock_offset; /* If this is apparently the last refblock (for now), try to squeeze the * reftable in */ if (refblock_index == (*nb_clusters - 1) >> s->refcount_block_bits && reftable_offset < 0) { uint64_t reftable_clusters = size_to_clusters(s, reftable_size * sizeof(uint64_t)); reftable_offset = alloc_clusters_imrt(bs, reftable_clusters, refcount_table, nb_clusters, &first_free_cluster); if (reftable_offset < 0) { fprintf(stderr, "ERROR allocating reftable: %s\n", strerror(-reftable_offset)); res->check_errors++; ret = reftable_offset; goto fail; } } ret = qcow2_pre_write_overlap_check(bs, 0, refblock_offset, s->cluster_size); if (ret < 0) { fprintf(stderr, "ERROR writing refblock: %s\n", strerror(-ret)); goto fail; } on_disk_refblock = qemu_blockalign0(bs->file, s->cluster_size); for (i = 0; i < s->refcount_block_size && refblock_start + i < *nb_clusters; i++) { on_disk_refblock[i] = cpu_to_be16((*refcount_table)[refblock_start + i]); } ret = bdrv_write(bs->file, refblock_offset / BDRV_SECTOR_SIZE, (void *)on_disk_refblock, s->cluster_sectors); qemu_vfree(on_disk_refblock); if (ret < 0) { fprintf(stderr, "ERROR writing refblock: %s\n", strerror(-ret)); goto fail; } /* Go to the end of this refblock */ cluster = refblock_start + s->refcount_block_size - 1; } if (reftable_offset < 0) { uint64_t post_refblock_start, reftable_clusters; post_refblock_start = ROUND_UP(*nb_clusters, s->refcount_block_size); reftable_clusters = size_to_clusters(s, reftable_size * sizeof(uint64_t)); /* Not pretty but simple */ if (first_free_cluster < post_refblock_start) { first_free_cluster = post_refblock_start; } reftable_offset = alloc_clusters_imrt(bs, reftable_clusters, refcount_table, nb_clusters, &first_free_cluster); if (reftable_offset < 0) { fprintf(stderr, "ERROR allocating reftable: %s\n", strerror(-reftable_offset)); res->check_errors++; ret = reftable_offset; goto fail; } goto write_refblocks; } assert(on_disk_reftable); for (refblock_index = 0; refblock_index < reftable_size; refblock_index++) { cpu_to_be64s(&on_disk_reftable[refblock_index]); } ret = qcow2_pre_write_overlap_check(bs, 0, reftable_offset, reftable_size * sizeof(uint64_t)); if (ret < 0) { fprintf(stderr, "ERROR writing reftable: %s\n", strerror(-ret)); goto fail; } assert(reftable_size < INT_MAX / sizeof(uint64_t)); ret = bdrv_pwrite(bs->file, reftable_offset, on_disk_reftable, reftable_size * sizeof(uint64_t)); if (ret < 0) { fprintf(stderr, "ERROR writing reftable: %s\n", strerror(-ret)); goto fail; } /* Enter new reftable into the image header */ cpu_to_be64w(&reftable_offset_and_clusters.reftable_offset, reftable_offset); cpu_to_be32w(&reftable_offset_and_clusters.reftable_clusters, size_to_clusters(s, reftable_size * sizeof(uint64_t))); ret = bdrv_pwrite_sync(bs->file, offsetof(QCowHeader, refcount_table_offset), &reftable_offset_and_clusters, sizeof(reftable_offset_and_clusters)); if (ret < 0) { fprintf(stderr, "ERROR setting reftable: %s\n", strerror(-ret)); goto fail; } for (refblock_index = 0; refblock_index < reftable_size; refblock_index++) { be64_to_cpus(&on_disk_reftable[refblock_index]); } s->refcount_table = on_disk_reftable; s->refcount_table_offset = reftable_offset; s->refcount_table_size = reftable_size; return 0; fail: g_free(on_disk_reftable); return ret; }


static void vp8_idct_dc_add4uv_c(uint8_t *dst, int16_t block[4][16], ptrdiff_t stride) { vp8_idct_dc_add_c(dst + stride * 0 + 0, block[0], stride); vp8_idct_dc_add_c(dst + stride * 0 + 4, block[1], stride); vp8_idct_dc_add_c(dst + stride * 4 + 0, block[2], stride); vp8_idct_dc_add_c(dst + stride * 4 + 4, block[3], stride); }


static void fw_cfg_mem_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); dc->realize = fw_cfg_mem_realize; dc->props = fw_cfg_mem_properties; }


int xen_pt_msix_init(XenPCIPassthroughState *s, uint32_t base) { uint8_t id = 0; uint16_t control = 0; uint32_t table_off = 0; int i, total_entries, bar_index; XenHostPCIDevice *hd = &s->real_device; PCIDevice *d = &s->dev; int fd = -1; XenPTMSIX *msix = NULL; int rc = 0; rc = xen_host_pci_get_byte(hd, base + PCI_CAP_LIST_ID, &id); if (rc) { return rc; } if (id != PCI_CAP_ID_MSIX) { XEN_PT_ERR(d, "Invalid id %#x base %#x\n", id, base); return -1; } xen_host_pci_get_word(hd, base + PCI_MSIX_FLAGS, &control); total_entries = control & PCI_MSIX_FLAGS_QSIZE; total_entries += 1; s->msix = g_malloc0(sizeof (XenPTMSIX) + total_entries * sizeof (XenPTMSIXEntry)); msix = s->msix; msix->total_entries = total_entries; for (i = 0; i < total_entries; i++) { msix->msix_entry[i].pirq = XEN_PT_UNASSIGNED_PIRQ; } memory_region_init_io(&msix->mmio, OBJECT(s), &pci_msix_ops, s, "xen-pci-pt-msix", (total_entries * PCI_MSIX_ENTRY_SIZE + XC_PAGE_SIZE - 1) & XC_PAGE_MASK); xen_host_pci_get_long(hd, base + PCI_MSIX_TABLE, &table_off); bar_index = msix->bar_index = table_off & PCI_MSIX_FLAGS_BIRMASK; table_off = table_off & ~PCI_MSIX_FLAGS_BIRMASK; msix->table_base = s->real_device.io_regions[bar_index].base_addr; XEN_PT_LOG(d, "get MSI-X table BAR base 0x%"PRIx64"\n", msix->table_base); fd = open("/dev/mem", O_RDWR); if (fd == -1) { rc = -errno; XEN_PT_ERR(d, "Can't open /dev/mem: %s\n", strerror(errno)); goto error_out; } XEN_PT_LOG(d, "table_off = %#x, total_entries = %d\n", table_off, total_entries); msix->table_offset_adjust = table_off & 0x0fff; msix->phys_iomem_base = mmap(NULL, total_entries * PCI_MSIX_ENTRY_SIZE + msix->table_offset_adjust, PROT_READ, MAP_SHARED | MAP_LOCKED, fd, msix->table_base + table_off - msix->table_offset_adjust); close(fd); if (msix->phys_iomem_base == MAP_FAILED) { rc = -errno; XEN_PT_ERR(d, "Can't map physical MSI-X table: %s\n", strerror(errno)); goto error_out; } msix->phys_iomem_base = (char *)msix->phys_iomem_base + msix->table_offset_adjust; XEN_PT_LOG(d, "mapping physical MSI-X table to %p\n", msix->phys_iomem_base); memory_region_add_subregion_overlap(&s->bar[bar_index], table_off, &msix->mmio, 2); /* Priority: pci default + 1 */ return 0; error_out: g_free(s->msix); s->msix = NULL; return rc; }


static int64_t archipelago_volume_info(BDRVArchipelagoState *s) { uint64_t size; int ret, targetlen; struct xseg_request *req; struct xseg_reply_info *xinfo; AIORequestData *reqdata = g_malloc(sizeof(AIORequestData)); const char *volname = s->volname; targetlen = strlen(volname); req = xseg_get_request(s->xseg, s->srcport, s->mportno, X_ALLOC); if (!req) { archipelagolog("Cannot get XSEG request\n"); goto err_exit2; } ret = xseg_prep_request(s->xseg, req, targetlen, sizeof(struct xseg_reply_info)); if (ret < 0) { archipelagolog("Cannot prepare XSEG request\n"); goto err_exit; } char *target = xseg_get_target(s->xseg, req); if (!target) { archipelagolog("Cannot get XSEG target\n"); goto err_exit; } memcpy(target, volname, targetlen); req->size = req->datalen; req->offset = 0; req->op = X_INFO; reqdata->op = ARCHIP_OP_VOLINFO; reqdata->volname = volname; xseg_set_req_data(s->xseg, req, reqdata); xport p = xseg_submit(s->xseg, req, s->srcport, X_ALLOC); if (p == NoPort) { archipelagolog("Cannot submit XSEG request\n"); goto err_exit; } xseg_signal(s->xseg, p); qemu_mutex_lock(&s->archip_mutex); while (!s->is_signaled) { qemu_cond_wait(&s->archip_cond, &s->archip_mutex); } s->is_signaled = false; qemu_mutex_unlock(&s->archip_mutex); xinfo = (struct xseg_reply_info *) xseg_get_data(s->xseg, req); size = xinfo->size; xseg_put_request(s->xseg, req, s->srcport); g_free(reqdata); s->size = size; return size; err_exit: xseg_put_request(s->xseg, req, s->srcport); err_exit2: g_free(reqdata); return -EIO; }


static void openpic_set_irq(void *opaque, int n_IRQ, int level) { OpenPICState *opp = opaque; IRQSource *src; src = &opp->src[n_IRQ]; DPRINTF("openpic: set irq %d = %d ipvp=%08x\n", n_IRQ, level, src->ipvp); if (src->ipvp & IPVP_SENSE_MASK) { /* level-sensitive irq */ src->pending = level; if (!level) { src->ipvp &= ~IPVP_ACTIVITY_MASK; } } else { /* edge-sensitive irq */ if (level) { src->pending = 1; } } openpic_update_irq(opp, n_IRQ); }